name: Build + deploy releases # Cuts a channel/release bundle (./build alpha|beta|release [version]) # and rsyncs it to /srv/zddc/releases/ via ./deploy --releases. Runs on # this host directly (label: host) — same shell environment the operator # uses for manual cuts, so behavior is identical between the two paths. # # Triggers: # - workflow_dispatch — pick channel + optional version from the UI. # - push to a tag matching zddc-server-v[0-9]+.[0-9]+.[0-9]+ — # the canonical "stable cut" tag in our six-tag lockstep set # (one per tool: archive-vX.Y.Z, transmittal-vX.Y.Z, ..., zddc-server-vX.Y.Z). # Filtering on zddc-server-v* ensures exactly one workflow run per cut # even though six tags push together. Runner re-cuts from the tagged # commit for reproducibility — _promote_stable in shared/build-lib.sh # is idempotent re: tag creation, so rerunning at the same HEAD is a # no-op for the tags. on: workflow_dispatch: inputs: channel: description: 'Channel to cut' required: true type: choice default: alpha options: - alpha - beta - release version: description: 'Stable version (e.g. 0.1.0). Leave blank for coordinated next-stable. Ignored for alpha/beta.' required: false default: '' push: tags: - 'zddc-server-v[0-9]+.[0-9]+.[0-9]+' jobs: build-and-deploy: runs-on: host steps: - name: Checkout uses: actions/checkout@v4 with: # ./build's _coordinated_next_stable reads tags across all six # tools; full history + tags are required. fetch-depth: 0 - name: Resolve channel + version id: meta run: | set -eu if [ "$GITHUB_EVENT_NAME" = "push" ]; then # Tag push: refs/tags/zddc-server-vX.Y.Z → channel=release, version=X.Y.Z VERSION="${GITHUB_REF#refs/tags/zddc-server-v}" echo "channel=release" >> "$GITHUB_OUTPUT" echo "version=$VERSION" >> "$GITHUB_OUTPUT" else echo "channel=${{ inputs.channel }}" >> "$GITHUB_OUTPUT" echo "version=${{ inputs.version }}" >> "$GITHUB_OUTPUT" fi - name: Build run: | set -eu CH="${{ steps.meta.outputs.channel }}" VER="${{ steps.meta.outputs.version }}" if [ "$CH" = "release" ] && [ -n "$VER" ]; then ./build release "$VER" else ./build "$CH" fi - name: Deploy releases run: ./deploy --releases - name: Verify channel mirror resolves run: | set -eu CH="${{ steps.meta.outputs.channel }}" MIRROR=$([ "$CH" = "release" ] && echo stable || echo "$CH") # Runner is in a container on caddy-net; reach Caddy by container # name (`caddy`). --connect-to keeps the SNI / Host as the real # public hostname so the right vhost matches; -k skips cert # verify (Caddy uses a self-signed `tls internal` cert). curl -ksI --connect-to "zddc.varasys.io:8443:caddy:8443" \ "https://zddc.varasys.io:8443/releases/archive_${MIRROR}.html" \ | head -3 # On a stable cut (tag push), auto-bump tnd-zddc-chart's appVersion to # match the new ZDDC version, then push to the chart's main branch. # The chart's pipeline-prod fires automatically on its own main push, # rebuilds the prod Docker image with a new tag (image tag derives from # Chart.AppVersion), and helm rolls the deployment. Net effect: a # single ZDDC stable cut deploys to BMCD prod with zero manual steps # on the chart repo. Dispatch-only invocations of this workflow # (workflow_dispatch with channel=release) skip — the chart bump is # only meaningful when the actual git tag exists at refs/tags/. notify-chart-prod: needs: build-and-deploy if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/zddc-server-v') runs-on: host env: CHART_GITHUB_TOKEN: ${{ secrets.CHART_GITHUB_TOKEN }} steps: - name: Auto-bump tnd-zddc-chart appVersion + push to chart main run: | set -eu VERSION="${GITHUB_REF#refs/tags/zddc-server-v}" echo "ZDDC stable cut: $VERSION" # Sanity: make sure the secret was injected. If not, fail loud # (rather than silently failing on the git push later). if [ -z "${CHART_GITHUB_TOKEN:-}" ]; then echo "::error::CHART_GITHUB_TOKEN secret not set on this repo" >&2 exit 1 fi # Clone tnd-zddc-chart into a tmp workspace. Shallow is fine — # we only ever produce one commit on top of main. TMP=$(mktemp -d) cd "$TMP" git clone --depth=20 --branch=main \ "https://oauth2:${CHART_GITHUB_TOKEN}@github.com/burnsmcd/tnd-zddc-chart.git" cd tnd-zddc-chart # Idempotent: skip if appVersion already matches the new ZDDC # version (e.g. if the operator already manually bumped it, or # this job is being re-run on the same tag). CURRENT=$(grep '^appVersion:' chart/Chart.yaml | sed -E 's/^appVersion: *"?([^"]*)"?.*/\1/') if [ "$CURRENT" = "$VERSION" ]; then echo "Chart appVersion already at $VERSION; nothing to do" exit 0 fi # Bump appVersion to track ZDDC stable. Also bump the chart's # own version (patch) so each deploy carries a unique chart # identity in JFrog — clean release history vs. silent rev # within the same chart version. sed -i "s/^appVersion: .*/appVersion: \"$VERSION\"/" chart/Chart.yaml OLD_CHART_VER=$(grep '^version:' chart/Chart.yaml | awk '{print $2}') MAJ=$(echo "$OLD_CHART_VER" | cut -d. -f1) MIN=$(echo "$OLD_CHART_VER" | cut -d. -f2) PAT=$(echo "$OLD_CHART_VER" | cut -d. -f3) NEW_PAT=$((PAT + 1)) NEW_CHART_VER="$MAJ.$MIN.$NEW_PAT" sed -i "s/^version: .*/version: $NEW_CHART_VER/" chart/Chart.yaml echo " appVersion: $CURRENT → $VERSION" echo " version: $OLD_CHART_VER → $NEW_CHART_VER" git config user.name "ZDDC Release Bot" git config user.email "noreply@zddc.varasys.io" git add chart/Chart.yaml git commit \ -m "chore(chart): auto-bump appVersion to $VERSION (ZDDC stable cut)" \ -m "Triggered by zddc-server-v$VERSION tag push on git.varasys.io/VARASYS/ZDDC. Bumps appVersion so the prod Docker image is tagged zddc:$VERSION, ensuring kubelet pulls a fresh image on the next helm upgrade. Chart version bumped to $NEW_CHART_VER (patch) so JFrog has a clean chart history per deploy." \ -m "Auto-generated by .forgejo/workflows/deploy-release.yml's notify-chart-prod job. Do not edit manually — the next ZDDC stable cut will overwrite this commit's changes." git push origin main echo "pushed chart appVersion bump - BMCD pipeline-prod will fire"