Git, CI/CD & GitOpsXLVIII · Conditional ExecutionTriggers
Tag and environment conditions — controlling which events touch which environments
What you'll learn
- Write `tags:` filters in GitHub Actions and the equivalent in GitLab CI
- Use `environment:` to bind a job to a named deployment target
- Distinguish tag-triggered deploys from branch-triggered deploys in an audit log
- Recognise why production deploys must be tag-driven, not push-to-main-driven
Prerequisites
Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x
A tag is a permanent name attached to a specific
commit. A push event is a transient notification. The
difference matters: a deploy triggered by a tag points
at a specific, recoverable, signable artifact; a
deploy triggered by a push to main points at
whatever main happens to be at that moment.
Tag triggers
on:
push:
tags:
- 'v*.*.*'
branches-ignore:
- '**'
The pattern v*.*.* matches v1.0.0 and v2.3.7-rc1.
Combining tags: with branches-ignore: ['**'] says
only deploy on tag - the trigger fires for tag
pushes only, never for branch pushes.
flowchart LR
A[git push] --> B{Is this a tag?}
B -- "yes" --> D[Tag trigger fires]
B -- "no" --> C[Branch trigger fires]
D --> E[Build signed artifact]
E --> F[Deploy to named environment]
C --> G[Build but do not deploy]
The same pattern in GitLab CI uses $CI_COMMIT_TAG:
deploy-prod:
stage: deploy
rules:
- if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
environment: production
script:
- deploy.sh
Environment conditions
An environment is a named deployment target. The name is metadata with consequences: protection rules, secrets, approval gates, and deployment history are attached to the name.
jobs:
deploy-prod:
environment:
name: production
runs-on: ubuntu-latest
steps:
- run: deploy.sh production
The environment: block is what attaches a job to a
named environment. Protection rules on that environment
are evaluated when the job tries to start. A job that
targets production without the required approvals is
held. A job that targets a string called prod is not
targeting production; it is targeting a string - the
platform does not bind protection rules, secrets, or
audit history to a string variable.
Production discipline
- The deploy job’s trigger is the release act. A
deploy on push-to-
mainis a side effect, not a release. Move the trigger totags:orworkflow_dispatch:. - The environment name is the audit unit. Use the platform’s environment mechanism; do not reimplement it with a string variable.
- The tag is signed.
git tag -sor-ufor hardware roots of trust.
Cross-course references
- Linux for Production Sysadmins - Part XXX covers signed packages, the package-management analogue.
- Terraform for Production Sysadmins - Part XXVIII covers promoting an immutable artifact across environments.
Quiz
Knowledge check · 4 questions
Q1. A team writes a deploy job that fires on every push to `main` and targets an environment literal `prod` instead of declaring `environment: production`. What is the production-discipline concern?
Q2. A deploy triggered by `push` to `main` is functionally equivalent to a deploy triggered by a tag, provided the workflow file is the same.
Q3. Name the three identifiers that must agree before a production deploy should be permitted to run.
Q4. Reconstruct the audit trail after a force-push to `main` triggered an unintended production deploy.
A developer force-pushed to `main` to clean up a sloppy commit history. The push triggered the deploy job. The `production` environment had no required-reviewers rule. The deploy succeeded. Two hours later, the cleanup commit was discovered to have removed a security header.
Passing score: 75%. Answers are checked in this browser.