ci(gitea): manual smoke + daily deploy-health; stamp the rsynced commit
deploy-health replaces the GitHub-Deployments-based drift check: it compares the commit stamped on the server by the deploy action with each repo's main. The deploy action now stamps the checked-out commit rather than GITHUB_SHA so rollbacks are recorded truthfully. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AqpXh3hQMMaC74pTjFq4it
This commit is contained in:
@@ -80,10 +80,13 @@ runs:
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Stamp the commit that was actually rsynced (the checked-out tree), not
|
||||||
|
# GITHUB_SHA, so a rollback of an older commit is recorded truthfully.
|
||||||
|
DEPLOYED=$(git rev-parse HEAD 2>/dev/null || echo "$GITHUB_SHA")
|
||||||
SLUG=$(printf '%s' "$TARGET_PATH" | tr '/' '_')
|
SLUG=$(printf '%s' "$TARGET_PATH" | tr '/' '_')
|
||||||
ssh -n $SSHOPT "$R" "mkdir -p ~/.peptide-deploys/$STAGE && printf '%s %s %s\n' '$GITHUB_SHA' '$GITHUB_REPOSITORY' \"\$(date -u +%FT%TZ)\" > ~/.peptide-deploys/$STAGE/$SLUG" \
|
ssh -n $SSHOPT "$R" "mkdir -p ~/.peptide-deploys/$STAGE && printf '%s %s %s\n' '$DEPLOYED' '$GITHUB_REPOSITORY' \"\$(date -u +%FT%TZ)\" > ~/.peptide-deploys/$STAGE/$SLUG" \
|
||||||
|| echo "::warning::could not record deployed commit for deploy-health"
|
|| echo "::warning::could not record deployed commit for deploy-health"
|
||||||
echo "Deployed ${GITHUB_SHA:0:7} to $STAGE:$TARGET_PATH"
|
echo "Deployed ${DEPLOYED:0:7} to $STAGE:$TARGET_PATH"
|
||||||
|
|
||||||
- name: Health check (${{ inputs.stage }})
|
- name: Health check (${{ inputs.stage }})
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
57
.gitea/workflows/deploy-health.yml
Normal file
57
.gitea/workflows/deploy-health.yml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
name: Deploy health (daily drift check)
|
||||||
|
|
||||||
|
# Gitea rewrite of .github/workflows/deploy-health.yml. GitHub's version read
|
||||||
|
# GitHub Deployment objects, which Gitea does not have. This one compares what is
|
||||||
|
# ACTUALLY on the server: the deploy composite action stamps
|
||||||
|
# ~/.peptide-deploys/production/<target> with the deployed commit, and this job
|
||||||
|
# compares that stamp with each repo's main HEAD. Drift (or a missing stamp after
|
||||||
|
# cutover) opens one issue in peptide-e2e; it never opens duplicates.
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 13 * * *' # 21:00 SGT, same slot as the GitHub job
|
||||||
|
workflow_dispatch: {}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
drift:
|
||||||
|
name: Compare deployed commit with main
|
||||||
|
runs-on: peptide-vps
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Check every deployable repo
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
|
SSH_HOST: ${{ secrets.SSH_HOST }}
|
||||||
|
SSH_PORT: ${{ secrets.SSH_PORT }}
|
||||||
|
SSH_USERNAME: ${{ secrets.SSH_USERNAME }}
|
||||||
|
PROD_ENABLED: ${{ vars.PROD_DEPLOY_ENABLED }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
WORK=$(mktemp -d); trap 'rm -rf "$WORK"' EXIT
|
||||||
|
printf '%s\n' "$SSH_PRIVATE_KEY" > "$WORK/key"; chmod 600 "$WORK/key"
|
||||||
|
ssh-keyscan -p "$SSH_PORT" "$SSH_HOST" > "$WORK/kh" 2>/dev/null || true
|
||||||
|
SSHOPT="-n -i $WORK/key -p $SSH_PORT -o UserKnownHostsFile=$WORK/kh -o StrictHostKeyChecking=accept-new -o ConnectTimeout=30 -o BatchMode=yes"
|
||||||
|
API="$GITHUB_SERVER_URL/api/v1"; H="Authorization: token $TOKEN"
|
||||||
|
problems=""
|
||||||
|
for row in $(python3 -c 'import json; d=json.load(open("tools/gitea-pipeline/repos.json")); [print(k+"="+v["target_path"]) for k,v in d.items() if not k.startswith("_") and v.get("target_path")]'); do
|
||||||
|
repo=${row%%=*}; tp=${row#*=}; slug=$(printf '%s' "$tp" | tr '/' '_')
|
||||||
|
head=$(curl -s -H "$H" "$API/repos/peptide-repo/$repo/branches/main" | python3 -c 'import json,sys;print(json.load(sys.stdin)["commit"]["id"])')
|
||||||
|
stamp=$(ssh $SSHOPT "$SSH_USERNAME@$SSH_HOST" "cat ~/.peptide-deploys/production/$slug 2>/dev/null" || true)
|
||||||
|
dep=${stamp%% *}
|
||||||
|
if [ -z "$dep" ]; then
|
||||||
|
msg="$repo: no Gitea production deploy recorded"
|
||||||
|
if [ "$PROD_ENABLED" = "true" ]; then problems="$problems\n- $msg (main is ${head:0:7})"; else echo "::notice::$msg (expected before cutover)"; fi
|
||||||
|
elif [ "$dep" != "$head" ]; then
|
||||||
|
problems="$problems\n- $repo: production has ${dep:0:7}, main is ${head:0:7}"
|
||||||
|
else
|
||||||
|
echo "OK $repo ${head:0:7}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
[ -z "$problems" ] && { echo "No drift."; exit 0; }
|
||||||
|
printf "Drift found:%b\n" "$problems"
|
||||||
|
open=$(curl -s -H "$H" "$API/repos/$GITHUB_REPOSITORY/issues?state=open&type=issues&limit=50" | python3 -c 'import json,sys;print(sum(1 for i in json.load(sys.stdin) if i["title"]=="Deploy drift detected"))')
|
||||||
|
if [ "$open" -gt 0 ]; then echo "An open drift issue already exists; not opening another."; exit 1; fi
|
||||||
|
python3 -c 'import json,sys; print(json.dumps({"title": "Deploy drift detected", "body": "Daily deploy-health found production out of step with main:\n" + sys.argv[1].replace("\\n","\n") + "\n\nRe-run the repo pipeline on main (workflow_dispatch) or investigate the failed deploy. Opened by deploy-health.yml."}))' "$problems" > issue.json
|
||||||
|
curl -s -o /dev/null -w "issue HTTP %{http_code}\n" -H "$H" -H 'Content-Type: application/json' -X POST "$API/repos/$GITHUB_REPOSITORY/issues" --data-binary @issue.json
|
||||||
|
exit 1
|
||||||
24
.gitea/workflows/smoke.yml
Normal file
24
.gitea/workflows/smoke.yml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
name: Smoke Tests (manual)
|
||||||
|
|
||||||
|
# Manual run of the staging smoke suite (the deploy pipeline runs it automatically
|
||||||
|
# via the smoke composite action). Gitea port of the workflow_dispatch half of
|
||||||
|
# .github/workflows/smoke.yml.
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
base_url:
|
||||||
|
description: 'Target URL (defaults to staging)'
|
||||||
|
required: false
|
||||||
|
default: 'https://staging.peptiderepo.com'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
smoke:
|
||||||
|
name: Playwright smoke suite
|
||||||
|
runs-on: peptide-vps
|
||||||
|
timeout-minutes: 15
|
||||||
|
steps:
|
||||||
|
- uses: https://git.protopeer.com/peptide-repo/peptide-e2e/.gitea/actions/smoke@main
|
||||||
|
with:
|
||||||
|
base_url: ${{ inputs.base_url }}
|
||||||
|
wp_admin_user: ${{ secrets.STAGING_WP_ADMIN_USER }}
|
||||||
|
wp_admin_password: ${{ secrets.STAGING_WP_ADMIN_PASSWORD }}
|
||||||
Reference in New Issue
Block a user