mcpField
G
gating-production-deploys

gating-production-deploys

github.com/posthogCloud & DevOps40.5k133 installsUpdated today
Repository

About gating-production-deploys

A GitHub Actions deployment-gating guide for PostHog repository maintainers. It specifies when production image pushes and deploy dispatches should depend on CD_DEPLOY_ENABLED, and which workflows should remain ungated.

Key features

  1. 01Define gates for production image pushes
  2. 02Gate Charts deployment dispatches
  3. 03Provide the repository-variable condition
  4. 04Distinguish release and PR validation workflows
  5. 05List example workflows

Use cases

  1. 01Configure production deploys on master pushes
  2. 02Check workflows for unintended deploy triggers
  3. 03Keep release and PR build workflows running

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/posthog/posthog --skill gating-production-deploys

After installing, type/gating-production-deploysin Claude Code to confirm it loaded.

Details

From the project README

Gating production builds and deploys

Container-image pushes and Charts deploy dispatches run from one canonical deploy repo, selected by the CD_DEPLOY_ENABLED variable. Gate every such step or it publishes/deploys from the wrong place.

Gate these when they run on push-to-master / schedule / workflow_dispatch:

  • a prod-tag container image push, and
  • a commit_state_update dispatch to PostHog/charts (plus its deployer-token step).

Don't gate:

  • Release/distribution workflows — GitHub release, npm, crate, Homebrew (e.g. build-phrocs.yml, release-cli.yml). They publish from public; leave them.
  • pull_request validation builds (gating them breaks contributor CI).
  • change-detection / setup jobs (use the org check only, not the variable).

The test is "pushes a prod image or triggers a deploy" — not "builds on master".

The gate

if: github.repository_owner == 'PostHog' && vars.CD_DEPLOY_ENABLED == 'true'

Use this instead of hardcoding github.repository == 'PostHog/posthog'.

Patterns

# whole job is the deploy/push (no PR builds) — gate the job:
if: github.repository_owner == 'PostHog' && vars.CD_DEPLOY_ENABLED == 'true'

# deploy job/step already keyed to master — add the gate:
if: github.repository_owner == 'PostHog' && vars.CD_DEPLOY_ENABLED == 'true' && github.ref == 'refs/heads/master'

# build job that also serves PRs — gate only the master arm of its `if`:
(github.event_name == 'push' && github.ref == 'refs/heads/master' && needs.changes.outputs.files == 'true'
  && github.repository_owner == 'PostHog' && vars.CD_DEPLOY_ENABLED == 'true')

# push step, master-only:
push: ${{ github.ref == 'refs/heads/master' && vars.CD_DEPLOY_ENABLED == 'true' }}
# push step, `push: true` (also pushes on PR for validation):
push: ${{ github.event_name == 'pull_request' || vars.CD_DEPLOY_ENABLED == 'true' }}

# reusable that pushes — add a `push` boolean input (default true), pass from caller:
#   with: { push: ${{ github.event_name == 'pull_request' || vars.CD_DEPLOY_ENABLED == 'true' }} }

Set CD_DEPLOY_ENABLED on the repo that should ship before merging, or master pushes skip the build/deploy. Lint with actionlint.

Examples: container-images-cd.yml (whole-job); cd-mcp-image.yml, livestream-docker-image.yml, cd-sandbox-base-image.yml (mixed PR+master); rust-docker-build.yml + _rust-build-images.yml (reusable push input). Counter-example, not gated: build-phrocs.yml.

Comments

Markdown supported