From 1f73eb675d7bb84d59ae8173a22e6b0e2e9eb92c Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Tue, 3 Feb 2026 16:58:03 -0800 Subject: [PATCH] Auto-deploy docs from build workflow (#93) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - Add `uv` and `argocd` CLI to forgejo-runner container image - Add `workflow-bot` ArgoCD account with sync permissions (declarative via kustomize patches) - Add `ARGOCD_AUTH_TOKEN` to forgejo-runner external secret for workflow auth - Update build workflow to auto-deploy docs after release: - Update configmap with new release URL - Commit changelog and configmap changes - Sync docs app via ArgoCD ## Deployment and Testing Manual steps required before this can work: 1. [ ] Build and push new forgejo-runner image (v2.4.0) 2. [ ] Sync argocd app to create workflow-bot account 3. [ ] Generate token: `argocd account generate-token --account workflow-bot` 4. [ ] Store token in 1Password under "Forgejo Secrets" with field `argocd_token` 5. [ ] Sync forgejo-runner app to pick up new external secret 6. [ ] Update forgejo-runner deployment to use new image version 7. [ ] Test by running workflow manually 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/93 --- .forgejo/workflows/build-blumeops.yaml | 103 ++++++++++++------ argocd/manifests/argocd/argocd-cm-patch.yaml | 13 +++ .../argocd/argocd-rbac-cm-patch.yaml | 14 +++ argocd/manifests/argocd/kustomization.yaml | 2 + .../forgejo-runner/external-secret.yaml | 9 +- containers/forgejo-runner/Dockerfile | 10 ++ .../feature/auto-deploy-docs.feature.md | 1 + 7 files changed, 119 insertions(+), 33 deletions(-) create mode 100644 argocd/manifests/argocd/argocd-cm-patch.yaml create mode 100644 argocd/manifests/argocd/argocd-rbac-cm-patch.yaml create mode 100644 docs/changelog.d/feature/auto-deploy-docs.feature.md diff --git a/.forgejo/workflows/build-blumeops.yaml b/.forgejo/workflows/build-blumeops.yaml index a3fa581..849b8d5 100644 --- a/.forgejo/workflows/build-blumeops.yaml +++ b/.forgejo/workflows/build-blumeops.yaml @@ -72,11 +72,6 @@ jobs: # Need full history for git operations fetch-depth: 0 - - name: Install uv - run: | - curl -LsSf https://astral.sh/uv/install.sh | sh - echo "$HOME/.local/bin" >> "$GITHUB_PATH" - - name: Build changelog run: | VERSION="${{ steps.version.outputs.version }}" @@ -86,7 +81,7 @@ jobs: if [ "$FRAGMENTS" -gt 0 ]; then echo "Found $FRAGMENTS changelog fragments, building changelog..." - ~/.local/bin/uvx towncrier build --version "$VERSION" --yes + uvx towncrier build --version "$VERSION" --yes echo "changelog_updated=true" >> "$GITHUB_OUTPUT" else echo "No changelog fragments found, skipping towncrier" @@ -94,32 +89,6 @@ jobs: fi id: changelog - - name: Commit changelog updates - if: steps.changelog.outputs.changelog_updated == 'true' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - VERSION="${{ steps.version.outputs.version }}" - - # Configure git - git config user.name "Forgejo Actions" - git config user.email "actions@forge.ops.eblu.me" - - # Stage changes (CHANGELOG.md updated, fragments removed) - git add docs/CHANGELOG.md docs/changelog.d/ - - # Commit - git commit -m "Release $VERSION: Update changelog - - Built changelog from towncrier fragments. - - [skip ci]" - - # Push to main - git push origin HEAD:main - - echo "Changelog committed and pushed" - - name: Build docs run: | VERSION="${{ steps.version.outputs.version }}" @@ -205,6 +174,76 @@ jobs: echo "" echo "Release created successfully!" + - name: Update docs configmap + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + VERSION="${{ steps.version.outputs.version }}" + TARBALL="docs-${VERSION}.tar.gz" + CONFIGMAP_FILE="argocd/manifests/docs/configmap.yaml" + RELEASE_URL="https://forge.ops.eblu.me/eblume/blumeops/releases/download/${VERSION}/${TARBALL}" + + echo "Updating $CONFIGMAP_FILE with new release URL..." + sed -i "s|DOCS_RELEASE_URL:.*|DOCS_RELEASE_URL: \"${RELEASE_URL}\"|" "$CONFIGMAP_FILE" + + echo "Updated configmap:" + cat "$CONFIGMAP_FILE" + + - name: Commit release changes + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + VERSION="${{ steps.version.outputs.version }}" + CHANGELOG_UPDATED="${{ steps.changelog.outputs.changelog_updated }}" + + # Configure git + git config user.name "Forgejo Actions" + git config user.email "actions@forge.ops.eblu.me" + + # Stage configmap changes + git add argocd/manifests/docs/configmap.yaml + + # Stage changelog changes if updated + if [ "$CHANGELOG_UPDATED" = "true" ]; then + git add docs/CHANGELOG.md docs/changelog.d/ + fi + + # Check if there are changes to commit + if git diff --cached --quiet; then + echo "No changes to commit" + else + git commit -m "Update docs release to $VERSION + + - Updated configmap with new DOCS_RELEASE_URL + $([ "$CHANGELOG_UPDATED" = "true" ] && echo "- Built changelog from towncrier fragments") + + [skip ci]" + + # Push to main + git push origin HEAD:main + echo "Changes committed and pushed" + fi + + - name: Deploy docs + env: + ARGOCD_AUTH_TOKEN: ${{ secrets.ARGOCD_AUTH_TOKEN }} + run: | + echo "Syncing docs app via ArgoCD..." + + # Sync docs app (uses ARGOCD_AUTH_TOKEN env var for auth) + argocd app sync docs \ + --server argocd.ops.eblu.me \ + --grpc-web \ + --prune + + # Wait for sync to complete + argocd app wait docs \ + --server argocd.ops.eblu.me \ + --grpc-web \ + --timeout 120 + + echo "Docs app synced successfully!" + - name: Summary run: | VERSION="${{ steps.version.outputs.version }}" diff --git a/argocd/manifests/argocd/argocd-cm-patch.yaml b/argocd/manifests/argocd/argocd-cm-patch.yaml new file mode 100644 index 0000000..5df2f41 --- /dev/null +++ b/argocd/manifests/argocd/argocd-cm-patch.yaml @@ -0,0 +1,13 @@ +# ArgoCD ConfigMap patch for workflow-bot account +# +# Creates a service account that can generate API tokens for CI/CD workflows. +# Account is used by forgejo-runner to sync apps after builds. +# +apiVersion: v1 +kind: ConfigMap +metadata: + name: argocd-cm +data: + # workflow-bot: service account for CI/CD automation + # - apiKey: allows generating API tokens via `argocd account generate-token` + accounts.workflow-bot: apiKey diff --git a/argocd/manifests/argocd/argocd-rbac-cm-patch.yaml b/argocd/manifests/argocd/argocd-rbac-cm-patch.yaml new file mode 100644 index 0000000..ba616ff --- /dev/null +++ b/argocd/manifests/argocd/argocd-rbac-cm-patch.yaml @@ -0,0 +1,14 @@ +# ArgoCD RBAC ConfigMap patch for workflow-bot permissions +# +# Grants minimal permissions for CI/CD workflows: +# - applications: sync, get (for syncing apps after builds) +# +apiVersion: v1 +kind: ConfigMap +metadata: + name: argocd-rbac-cm +data: + policy.csv: | + p, role:workflow-bot, applications, sync, *, allow + p, role:workflow-bot, applications, get, *, allow + g, workflow-bot, role:workflow-bot diff --git a/argocd/manifests/argocd/kustomization.yaml b/argocd/manifests/argocd/kustomization.yaml index 31b9cd6..093bbb3 100644 --- a/argocd/manifests/argocd/kustomization.yaml +++ b/argocd/manifests/argocd/kustomization.yaml @@ -12,3 +12,5 @@ resources: patches: - path: argocd-cmd-params-cm.yaml - path: argocd-ssh-known-hosts-cm.yaml + - path: argocd-cm-patch.yaml + - path: argocd-rbac-cm-patch.yaml diff --git a/argocd/manifests/forgejo-runner/external-secret.yaml b/argocd/manifests/forgejo-runner/external-secret.yaml index 4bb79a3..0999855 100644 --- a/argocd/manifests/forgejo-runner/external-secret.yaml +++ b/argocd/manifests/forgejo-runner/external-secret.yaml @@ -3,7 +3,9 @@ # Replaces the manual op inject workflow from secret.yaml.tpl # # 1Password item: "Forgejo Secrets" in blumeops vault -# Field: "runner_reg" +# Fields: +# - runner_reg: Runner registration token +# - argocd_token: API token for workflow-bot account (for auto-deploying docs) # # Note: Static values (FORGEJO_URL, RUNNER_NAME, RUNNER_LABELS) are included # via template since they don't need to be in 1Password. @@ -27,8 +29,13 @@ spec: RUNNER_NAME: "k8s-runner" RUNNER_LABELS: "k8s:docker://registry.ops.eblu.me/blumeops/forgejo-runner:v2.3.0" RUNNER_TOKEN: "{{ .runner_token }}" + ARGOCD_AUTH_TOKEN: "{{ .argocd_token }}" data: - secretKey: runner_token remoteRef: key: Forgejo Secrets property: runner_reg + - secretKey: argocd_token + remoteRef: + key: Forgejo Secrets + property: argocd_token diff --git a/containers/forgejo-runner/Dockerfile b/containers/forgejo-runner/Dockerfile index 082ce96..ebb3d59 100644 --- a/containers/forgejo-runner/Dockerfile +++ b/containers/forgejo-runner/Dockerfile @@ -38,5 +38,15 @@ RUN install -m 0755 -d /etc/apt/keyrings \ && apt-get install -y --no-install-recommends docker-ce-cli skopeo \ && rm -rf /var/lib/apt/lists/* +# Install uv (Python package runner for towncrier) +RUN curl -LsSf https://astral.sh/uv/install.sh | sh \ + && mv /root/.local/bin/uv /usr/local/bin/uv \ + && mv /root/.local/bin/uvx /usr/local/bin/uvx + +# Install argocd CLI (for syncing apps from workflows) +RUN curl -sSL -o /usr/local/bin/argocd \ + "https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-${TARGETARCH}" \ + && chmod +x /usr/local/bin/argocd + # Default to bash CMD ["/bin/bash"] diff --git a/docs/changelog.d/feature/auto-deploy-docs.feature.md b/docs/changelog.d/feature/auto-deploy-docs.feature.md new file mode 100644 index 0000000..3ce6bfe --- /dev/null +++ b/docs/changelog.d/feature/auto-deploy-docs.feature.md @@ -0,0 +1 @@ +Build workflow now automatically deploys docs after release by updating the configmap and syncing ArgoCD