diff --git a/docs/devops/single_azure_vm/docker/setup.sh b/docs/devops/single_azure_vm/docker/setup.sh index 1d069d08..0a7a9943 100755 --- a/docs/devops/single_azure_vm/docker/setup.sh +++ b/docs/devops/single_azure_vm/docker/setup.sh @@ -8,7 +8,8 @@ # What gets installed: # - Docker CE + Docker Compose + BuildKit # - Node.js 22 LTS + pnpm 10.6.5 -# - Gitea (Docker container — npm package registry on :3300) +# - Gitea (Docker container — npm package registry + CI on :3300) +# - act_runner (Gitea CI runner — systemd service, host mode) # - Ollama (local LLM inference for LocalMemGPT on :11434) # - All 11 ByteLyst repos (cloned from GitHub) # - All @bytelyst/* packages (built + published to Gitea) @@ -26,8 +27,8 @@ # # Phases: # 1 System dependencies (Docker, Node, pnpm, Ollama) -# 2 Gitea npm registry (container on :3300) -# 3 Clone 11 repositories from GitHub +# 2 Gitea npm registry + CI runner (container on :3300 + act_runner systemd) +# 3 Clone 11 repositories from GitHub + push to Gitea # 4 Build all @bytelyst/* packages # 5 Publish packages to Gitea npm registry # 6 Generate .env.ecosystem config @@ -332,7 +333,7 @@ phase2_gitea() { token_response=$(curl -sf -X POST "${GITEA_URL}/api/v1/users/${GITEA_ADMIN}/tokens" \ -H "$AUTH_HEADER" \ -H "Content-Type: application/json" \ - -d '{"name":"vm-deploy","scopes":["write:package","read:package","write:organization","read:organization"]}') + -d '{"name":"vm-deploy","scopes":["write:package","read:package","write:organization","read:organization","write:repository","read:repository","write:user","read:user"]}') GITEA_NPM_TOKEN=$(echo "$token_response" | jq -r '.sha1 // .token' 2>/dev/null || echo "") if [ -z "$GITEA_NPM_TOKEN" ] || [ "$GITEA_NPM_TOKEN" = "null" ]; then @@ -344,7 +345,121 @@ phase2_gitea() { echo "$GITEA_NPM_TOKEN" > "${INSTALL_DIR}/.gitea_token" chmod 600 "${INSTALL_DIR}/.gitea_token" - ok "Phase 2 complete. Gitea running at http://localhost:${GITEA_PORT}" + # ── Install act_runner (Gitea CI) ───────────────────────────────── + log "Installing act_runner for Gitea CI..." + + local RUNNER_VERSION="0.3.0" + local RUNNER_ARCH + RUNNER_ARCH=$(dpkg --print-architecture) # amd64 or arm64 + local RUNNER_BIN="/usr/local/bin/act_runner" + + if [ ! -f "$RUNNER_BIN" ]; then + local runner_url="https://gitea.com/gitea/act_runner/releases/download/v${RUNNER_VERSION}/act_runner-${RUNNER_VERSION}-linux-${RUNNER_ARCH}" + curl -sfL "$runner_url" -o "$RUNNER_BIN" || fail "Failed to download act_runner v${RUNNER_VERSION}" + chmod +x "$RUNNER_BIN" + ok "act_runner v${RUNNER_VERSION} installed." + else + ok "act_runner already installed." + fi + + # Create runner data directory + local RUNNER_DIR="${INSTALL_DIR}/.act_runner" + mkdir -p "$RUNNER_DIR" + + # Register runner (idempotent — skip if already registered) + if [ ! -f "${RUNNER_DIR}/.runner" ]; then + # Get a runner registration token from Gitea API + local reg_token_resp + reg_token_resp=$(curl -sf -X POST "${GITEA_URL}/api/v1/admin/runners/registration-token" \ + -H "$AUTH_HEADER" \ + -H "Content-Type: application/json" 2>/dev/null || echo "") + + local reg_token + reg_token=$(echo "$reg_token_resp" | jq -r '.token' 2>/dev/null || echo "") + + if [ -z "$reg_token" ] || [ "$reg_token" = "null" ]; then + warn "Could not get runner registration token (Gitea may not support this API). Trying alternate method..." + # Fallback: use the Gitea admin API (older versions) + reg_token_resp=$(curl -sf "${GITEA_URL}/api/v1/admin/runners/registration-token" \ + -H "Authorization: token ${GITEA_NPM_TOKEN}" 2>/dev/null || echo "") + reg_token=$(echo "$reg_token_resp" | jq -r '.token' 2>/dev/null || echo "") + fi + + if [ -z "$reg_token" ] || [ "$reg_token" = "null" ]; then + warn "Could not obtain runner registration token. act_runner will need manual registration." + warn "Run: act_runner register --instance http://localhost:${GITEA_PORT} --token " + else + cd "$RUNNER_DIR" + "$RUNNER_BIN" register \ + --instance "http://localhost:${GITEA_PORT}" \ + --token "$reg_token" \ + --name "bytelyst-vm" \ + --labels "ubuntu-latest:host,self-hosted:host" \ + --no-interactive 2>/dev/null || true + ok "act_runner registered with Gitea." + fi + else + ok "act_runner already registered." + fi + + # Generate runner config + cat > "${RUNNER_DIR}/config.yaml" < /etc/systemd/system/act-runner.service </dev/null || true + systemctl restart act-runner.service 2>/dev/null || true + ok "act_runner systemd service started." + + ok "Phase 2 complete. Gitea running at http://localhost:${GITEA_PORT}, CI runner active." } # ═══════════════════════════════════════════════════════════════════════ @@ -378,7 +493,42 @@ phase3_clone() { # (commit fix(docker) across all 10 product repos + dashboards). # No runtime sed stripping needed. - ok "Phase 3 complete. All repos in ${INSTALL_DIR}/" + # ── Push repos to VM Gitea (enables CI triggers on push) ────────── + log "Pushing repos to VM Gitea (CI will trigger on push)..." + require_gitea_token + + local GITEA_URL="http://localhost:${GITEA_PORT}" + local GITEA_PUSH_URL="http://${GITEA_ADMIN}:${GITEA_PASS}@localhost:${GITEA_PORT}/bytelyst" + + for repo in "${REPOS[@]}"; do + local target="${INSTALL_DIR}/${repo}" + [ -d "$target/.git" ] || continue + + # Create repo in Gitea org if it doesn't exist (idempotent) + local repo_status + repo_status=$(curl -sf -o /dev/null -w "%{http_code}" \ + -H "Authorization: token ${GITEA_NPM_TOKEN}" \ + "${GITEA_URL}/api/v1/repos/bytelyst/${repo}" 2>/dev/null || echo "000") + + if [ "$repo_status" != "200" ]; then + curl -sf -X POST "${GITEA_URL}/api/v1/orgs/bytelyst/repos" \ + -H "Authorization: token ${GITEA_NPM_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "{\"name\":\"${repo}\",\"default_branch\":\"main\",\"auto_init\":false}" > /dev/null 2>&1 || true + fi + + # Add gitea remote and push (idempotent) + cd "$target" + git remote remove gitea 2>/dev/null || true + git remote add gitea "${GITEA_PUSH_URL}/${repo}.git" + if git push gitea main 2>/dev/null; then + log " Pushed: $repo" + else + warn " Push failed (non-fatal): $repo" + fi + done + + ok "Phase 3 complete. All repos in ${INSTALL_DIR}/ and pushed to Gitea." } # ═══════════════════════════════════════════════════════════════════════ @@ -845,8 +995,8 @@ usage() { echo "" echo "Phases:" echo " 1 System dependencies (Docker, Node, pnpm, Ollama)" - echo " 2 Gitea npm registry" - echo " 3 Clone repositories" + echo " 2 Gitea npm registry + CI runner" + echo " 3 Clone repositories + push to Gitea" echo " 4 Build @bytelyst/* packages" echo " 5 Publish packages to Gitea" echo " 6 Generate .env.ecosystem"