Set up or align a GitHub Actions deploy pipeline for an app or service. Use when standardizing repos around the verify-then-deploy shape: push to main → detect affected lanes → verify and build artifacts → e2e → deploy each lane to its host (Cloudflare Pages, AWS Amplify, GHCR + VPS).
99
100%
Does it follow best practices?
Impact
97%
1.21xAverage score across 4 eval scenarios
Passed
No known issues
Push-to-main, lane-aware, artifact-driven. Detect what changed, build it once, run e2e against the built artifact, then deploy that same artifact per host. Frontends ship to a static host (Cloudflare Pages, AWS Amplify); backends ship a container image to GHCR and cut over on the VPS. The shape is identical across both.
push to main
└─► detect-changes (paths-filter or turbo --affected → per-lane outputs)
└─► verify-<lane> (lint + typecheck + test + build → upload artifact)
└─► e2e-<lane> (download artifact, run e2e against it)
└─► deploy-<lane> (download artifact + load env → ship to host)
└─► smoke / health-check (hit the deployed URL)Each lane is independent: a web-only change builds and deploys only web, leaving api untouched. Verify, e2e, and deploy run cancellable concurrency groups; the deploy job uses a non-cancellable group per (env, lane) so two pushes never race the same target.
A separate deploy.yml (workflow_dispatch) lets a human re-deploy a specific ref + lane without re-running verify — same composite actions, same concurrency group, no path detection.
.github/workflows/*, .github/actions/*, hosting scripts, infra files, and recent failing runs. If the org has a known-good sibling repo for the same host, read that workflow before choosing actions or inventing shell.main is the deploy branch, the host (Cloudflare/Amplify/VPS) is reachable, and the secret store (1Password Connect, AWS OIDC, or repo secrets) is wired..github/actions/<name> so the workflow stays declarative. Prefer a working repo-local or sibling composite action over a fresh marketplace guess..github/workflows/main.yml and (optionally) .github/workflows/deploy.yml per references/workflows.md. Keep the changes → verify → e2e → deploy topology; do not collapse stages.dorny/paths-filter@v4 for simple per-app rules, or a Turbo --affected walker for monorepos that need package-graph awareness. Output one boolean per deploy lane.(env, lane) so a web deploy does not block an api deploy, but two web deploys serialize.Load detailed workflow snippets from references/workflows.md only after the target lanes and host are known; load references/targets.md only for the selected host.
Minimal deploy anchor:
deploy-web:
needs: [verify-web, e2e-web]
if: ${{ needs.verify-web.result == 'success' && needs.e2e-web.result == 'success' }}
concurrency: { group: deploy-production-web, cancel-in-progress: false }
steps:
- uses: actions/download-artifact@v8
with: { name: web-dist, path: apps/web/dist }
- run: curl -fsS https://web.example.com/healthz(env, lane) and shared between main.yml and deploy.yml.