Topic 7.3
Git in CI/CD Pipelines
In one line
A CI/CD pipeline is triggered directly by Git events — a push, a pull request, a tag — and understanding exactly which event triggers what is the key to configuring a pipeline that runs the right checks at the right time.
Think of it like this
A security checkpoint that automatically activates the moment someone walks through a specific door, rather than requiring a guard to remember to check everyone manually — CI/CD is exactly this automation, triggered directly by specific Git events rather than relying on a human remembering to run tests or deploy manually.
Key ideas
- 01
CONTINUOUS INTEGRATION (CI) automatically builds and tests every push (or every pull request) — the standard, most valuable trigger is 'on every pull request opened or updated,' since this gives fast, objective feedback (tests pass or fail, linting is clean or not) BEFORE a human reviewer even starts looking, and before the change ever reaches the shared branch at all.
- 02
CONTINUOUS DEPLOYMENT (CD) automatically ships code to a real environment, commonly triggered by a push (or merge) specifically to the
mainbranch, or by the creation of a TAG matching a release pattern (Phase 6.3's tags) — taggingv1.4.0is often what actually triggers a real production deployment pipeline, making tag creation itself a genuinely consequential, deliberate action. - 03
Most CI/CD platforms (GitHub Actions, GitLab CI, Jenkins) read a configuration file COMMITTED directly to the repository itself (
.github/workflows/*.ymlfor GitHub Actions,.gitlab-ci.ymlfor GitLab) — this means the pipeline's own configuration is version-controlled, reviewable, and changes to it go through the exact same pull-request review process as any other code change. - 04
A pipeline typically reacts differently to DIFFERENT Git events within one configuration: run fast unit tests on every push to any branch, run a fuller integration test suite specifically on pull requests targeting
main, and only actually deploy on a push tomainitself or on a new version tag — this event-based branching logic is exactly why understanding Git's actual event vocabulary (push, pull_request, tag creation) matters for configuring CI/CD correctly. - 05
A genuinely important safety pattern: requiring CI to PASS as a precondition for merging at all (a 'required status check,' configurable as branch protection on GitHub/GitLab) — this makes it structurally impossible to merge a pull request whose tests are failing, removing 'someone forgot to check' as a possible failure mode entirely, rather than merely encouraging good behavior.
Code & diagrams
Different Git events trigger genuinely different pipeline behavior.
A realistic, minimal workflow showing different triggers doing different things.
# .github/workflows/ci.yml — committed to the repo, reviewed like any other file
name: CI
on:
pull_request:
branches: [main]
push:
branches: [main]
tags: ["v*"]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm test
deploy:
needs: test
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: echo "Deploying ${{ github.ref_name }} to production"
# a real deploy step would go hereExplain it without notes
Why is 'run CI on every pull request' generally considered more valuable than only running it after a merge to main?
Why does it make sense for a real production deployment to be triggered specifically by a tag push, rather than every push to main?
Practice
If you have access to a repository with GitHub Actions or similar CI, find its workflow configuration file and identify exactly which Git events trigger which jobs.
Sketch (on paper or in a text file) a CI/CD configuration for a hypothetical project: what runs on a pull request, what runs on a push to main, and what runs on a tag push.
Trade-offs
- ↔
Running a full, comprehensive test suite on every single push (rather than only on pull requests, or with a faster subset for regular pushes) gives maximum safety but costs real CI compute time and slows down the feedback loop for quick, iterative pushes — most real pipelines deliberately tier their checks (fast smoke tests on every push, a fuller suite specifically on pull requests to main) to balance thoroughness against feedback speed.
Done when you can
I understand that CI/CD pipelines are triggered by specific Git events, not run continuously in the background.
I can explain why running CI on pull requests specifically is more valuable than only after merging.
I understand why tagging is a natural, deliberate trigger for a real production deployment.