From 67b806fc5c3f3e6a8c92e4037945d7bd39e5e490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amara=20Diallo=20=E2=80=94=20PO=20nextcraft?= Date: Thu, 5 Nov 2026 10:03:46 +0000 Subject: [PATCH] Update .gitea/workflows/release.yaml --- .gitea/workflows/release.yaml | 97 +++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml index 883ac6f..ef42630 100644 --- a/.gitea/workflows/release.yaml +++ b/.gitea/workflows/release.yaml @@ -278,3 +278,100 @@ jobs: || { echo "FAIL: embedded CLI does not run"; exit 1; } echo "assert 5/5: embedded CLI alive + clean stop" docker rm -f "$CID" >/dev/null && CID="" + # -- R1 deploy leg (REQ-v1-003 machinery set c18619; hep APPROVE c18623; + # vehicle call c18634: the last mile is THIS pipeline, not an SRE infra + # detour). Pipeline-only host refresh of the product host - no manual + # host pokes. Provenance = this job's run id + the post-deploy identity + # read below. The footer is retired as a freshness marker (it is the + # code's own label - c18624 correction, confirmed by hep): freshness + # reads are machine-read (/health + / serving HTML + the /v1/placements/ + # admin route registration in /openapi.json). + # + # One-time plumbing preconditions (declared for the MR review; NOT a + # routing of the refresh to SRE - SRE keeps the R3 re-probe lane only): + # * DEPLOY_SSH_KEY - repo Actions secret: the least-scope deploy key + # authorized on the product host's deploy account (deploy@10.0.0.105 + # per deploy/README.md topology). One-time grant via the SRE/console + # precedent (deploy/ci README G-206 pattern; self-serve secret PUT + # precedent: REGISTRY_TOKEN, HTTP 201 on 2026-09-27). + # * (optional hardening) DEPLOY_HOSTKEY - repo Actions secret holding + # the product host's complete ssh public host-key line; when set it + # is PINNED (StrictHostKeyChecking=yes), else accept-new. + # A missing DEPLOY_SSH_KEY at run time fails this leg LOUDLY - a red + # Actions tab on a tag is a red deploy by design (deploy/README.md); + # it is never silently skipped (set R1: the gate stays clearable on + # evidence). The release/asset path is untouched: a deploy-leg + # precondition failure cannot damage artifact shipping. + deploy: + needs: release + runs-on: release + steps: + - name: Preflight - fail loud when the leg is unconfigured + env: + DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} + run: | + set -euo pipefail + echo "deploy preflight: run id $GITHUB_RUN_ID / run #$GITHUB_RUN_NUMBER / job $GITHUB_JOB_ID / sha $GITHUB_SHA" + [ -n "$DEPLOY_SSH_KEY" ] || { echo "FATAL: DEPLOY_SSH_KEY unset - deploy leg unconfigured; host NOT refreshed this release; release artifacts stand (release job already green)"; exit 1; } + + - name: Refresh the product host over the declared ssh channel + env: + DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} + DEPLOY_HOSTKEY: ${{ secrets.DEPLOY_HOSTKEY }} + run: | + set -euo pipefail + trap 'rm -f /tmp/dk /tmp/kh' EXIT + apt-get update -qq && apt-get install -y -qq openssh-client >/dev/null + install -m 600 /dev/null /tmp/dk + printf '%s\n' "$DEPLOY_SSH_KEY" > /tmp/dk + unset DEPLOY_SSH_KEY + if [ -n "${DEPLOY_HOSTKEY:-}" ]; then + printf '%s\n' "$DEPLOY_HOSTKEY" > /tmp/kh + SSH_PIN="-oUserKnownHostsFile=/tmp/kh -oStrictHostKeyChecking=yes" + else + SSH_PIN="-oStrictHostKeyChecking=accept-new" + fi + TAG="${{ gitea.ref_name }}" + ssh -i /tmp/dk -o BatchMode=yes $SSH_PIN deploy@10.0.0.105 bash -s "$TAG" << 'REMOTE' + set -euo pipefail + TAG="$1" + if command -v nextcraft >/dev/null 2>&1; then + echo "channel: binary/deb - the one-command upgrade (idempotent, self-verifying per deploy/README.md)" + nextcraft deploy --service --ref "$TAG" + elif [ -n "$(docker ps --format '{{.Names}}' | grep -x nextcraft || true)" ]; then + echo "channel: docker - README upgrade (pull + recreate; nextcraft-state persists)" + docker pull git.coreci.dev/coreci/nextcraft:"$TAG" + docker rm -f nextcraft + docker run -d --name nextcraft -p 8420:8420 -v nextcraft-state:/home/nextcraft/.nextcraft git.coreci.dev/coreci/nextcraft:"$TAG" + else + echo "FATAL: no nextcraft channel on $(hostname) (no nextcraft on PATH; no docker container named nextcraft) - failing loud" + exit 1 + fi + echo "--- channel verify (advisory; the identity read below is canonical)" + command -v nextcraft >/dev/null 2>&1 && nextcraft --version || true + REMOTE + RC=$? + echo "host refresh done (rc=$RC); provenance: run id $GITHUB_RUN_ID / run #$GITHUB_RUN_NUMBER / job $GITHUB_JOB_ID / tag $TAG / sha $GITHUB_SHA" + exit $RC + + - name: Post-deploy identity read - the R1 provenance surface + run: | + set -euo pipefail + TAG="${{ gitea.ref_name }}" + echo "waiting for the stack to settle..." + OK="" + for i in $(seq 1 12); do + CODE_H="$(curl -sS -o /tmp/h -m 15 -w '%{http_code}' https://nextcraft.coreci.dev/health || true)" + if [ "$CODE_H" = "200" ] && grep -q '"status"' /tmp/h; then OK=1; break; fi + sleep 5 + done + [ -n "$OK" ] || { echo "FAIL: /health never returned 200 within the window"; exit 1; } + echo "assert 1/3: /health 200 - $(head -c 200 /tmp/h)" + CODE_R="$(curl -sS -o /tmp/r -m 15 -w '%{http_code}' https://nextcraft.coreci.dev/)" + head -c 64 /tmp/r | tr -d '[:space:]' | head -c 9 | grep -qiE '^