CI/CD stands for continuous integration and continuous delivery. CI means every change is built and tested automatically, for example on every pull request. CD means merged changes are always ready to be deployed, that is, put online. When that happens automatically, it's called continuous deployment.
GitHub Actions, workflows and jobs
These three names nest inside each other:
GitHub Actions is GitHub's CI/CD service, the whole platform.
A workflow is one automated process, written as a YAML file in the repo's .github/workflows folder. It runs when an event happens, such as a pull request being opened. A repo can have several workflows.
A job is one part of a workflow: a list of steps (commands or ready-made actions) that run in order on the same runner, a fresh machine GitHub starts for it. A workflow has one or more jobs, and by default they run at the same time.
GitHub ActionsGitHub's CI/CD service, the whole platform
A workflowone automated process, written as a YAML file
A jobone part of a workflow: a list of steps
stepscommands or ready-made actions
These three names nest inside each other
So "CI is red" (failing) usually means one job in one workflow failed. The pull request's Checks tab shows which one. If you know Python, think of a workflow file as a script GitHub runs for you when an event happens, with each run on a clean machine.
Vercel preview and production deploys
Vercel deploys a website straight from its GitHub repo. It has two kinds of deploys:
By default, a preview deployment is made when you push to any branch that isn't the production branch, or open a pull request. It gets its own web address, usually linked in a comment on the pull request, so you can try the change live without affecting the real site.
By default, a production deployment is made when you push or merge into the production branch, usually main. That's the live site people use. One exception: a new project's very first deployment is always a production one, whatever the branch.
Each environment can have its own environment variables: settings the app reads when it runs, like the database address. That's how a preview can use a test database while production keeps the real one.
How it fits the Flows
A Ticket's pull request runs the CI workflow and gets a Vercel preview. You merge only once CI passes (shows green). A protected branch can even block the merge until it does. Merging into main then triggers the production deploy.
Going deeper
5 min read · Going deeper not read
Why it exists
Matt's pages on feedback loops are about local checks: type checks, tests and pre-commit hooks. His case for them starts from distrust. In his Ralph tips (updated 8 January 2026) he writes: "Great programmers don't trust their own code." Instead, he says: "They build automations and checks to verify what they ship." He adds: "The same applies to AI agents."
Agents raise the stakes. Ralph, the loop Matt's tips are about, which runs an agent on its own, shows why: "A human might commit once or twice a day. Ralph can pile dozens of commits into a repo in hours." He warns: "If those commits are low quality, entropy compounds fast." His feedback-loops guide (updated 16 January 2026) says why agents take this well: "AI agents don't get frustrated by repetition." When code fails a check, "the agent simply tries again."
His retro Skill goes one step further and names CI. At the Course's pin commit, it treats a repo with "no pre-commit hook and no CI job running its lint/typecheck/test command" as a finding in itself: "a standing missed opportunity, not a neutral default."
How it works underneath
The idea comes from long before agents. Martin Fowler's article (18 January 2024) says continuous integration "was developed as a practice by Kent Beck as part of Extreme Programming in the 1990s." Some people credit Grady Booch with the term, but Fowler says he only used it "as an offhand description in a single sentence."
From Fowler's "Continuous Integration" (18 January 2024): developers push commits through the day into one repository. From , 30 October 2026.
Citations (60)
From snapshot/docs/docs.github.com/understand-github-actions.md, line 9: “GitHub Actions is a continuous integration and continuous delivery (CI/CD) platform that allows you to automate your build, test, and deployment pipeline. You can create workflows that build and test every pull request to your repository, or deploy merged pull requests to production.”
Fowler's definition has two halves. Everyone merges into one shared codebase at least daily. And each merge is checked by "an automated build (including test)." The tests are what make it work: "Self-testing code is so important to Continuous Integration that it is a necessary prerequisite." Without it, he warns, CI "won't work."
A red build has one rule. Fowler quotes Kent Beck: "nobody has a higher priority task than fixing the build." Usually, he says, the best fix is to revert the faulty commit, so the rest of the team can keep working while "some folks" figure out the problem elsewhere.
The "CD" half has two meanings, and Fowler keeps them apart:
Continuous delivery: the product "should always be in a state where we can release the latest build." Releasing stays "a business decision."
Continuous deployment: the product "is automatically released to production whenever it passes all the automated tests."
Continuous delivery
Continuous deployment
the product
should always be in a state where we can release the latest build.
is automatically released to production whenever it passes all the automated tests.
The "CD" half has two meanings, and Fowler keeps them apart
A real example
In July 2025, a user named searls opened issue #319 on Anthropic's Claude Code GitHub Action. Claude had committed to their pull request, but their CI workflow never ran. A collaborator on the project replied that commits made as the github-actions user can't start workflows, a rule GitHub has "to prevent infinite recursion."
In March 2026, another user posted a fix. With use_commit_signing: "true", commits appear as claude[bot], and "GitHub fires the pull_request: synchronize event normally, triggering downstream CI."
GitHub's current GITHUB_TOKEN page (copied 30 October 2026, newer than the issue) describes something different: it says a pull request created or updated with that token starts its runs "in an approval-required state." Someone with write access has to press Approve workflows to run. Most other events made with the token still start no runs, though workflow_dispatch and repository_dispatch always do. Until someone approves, CI on those commits waits.
Where it goes wrong
GitHub's troubleshooting page for required checks lists the traps:
A skipped workflow blocks forever. If path filtering, branch filtering or a commit message skips a workflow, its checks "stay in a "Pending" state and block merging." The pull request shows "Waiting for status to be reported." GitHub's advice: "Avoid requiring workflows that can be skipped."
A skipped job may let a merge through. If a job depends on a failed job, the dependent job "is skipped and may not block merging." The fix is always() with needs.
Old greens don't count. "Required checks must pass on the latest commit SHA."
Some triggers never reach the pull request. A workflow started by workflow_dispatch on the branch doesn't "satisfy a required status check in a branch ruleset," even when it passes.
Fowler warns about one more. Running a CI service on every feature branch is "not the same as Continuous Integration," because "the whole point of integration is to have all commits coexisting on a single branch."
Try it
In your practice project (set it up first with keeping-track's Try it step if you haven't):
In the repo's settings, protect main and require the job from .github/workflows/ci.yml as a status check (on GitHub Free, this needs a public repo).
On a new branch, add paths: ['api/**'] under pull_request: in that file, and under push: too if the file has one. A push run also reports the check, so leaving it unfiltered would pass it. Change one line of README.md. Push, and open a pull request. Neither file is under api/.
Watch the merge box say "Waiting for status to be reported." Then remove both paths: filters, push again, and the check runs.
From snapshot/docs/docs.github.com/understand-github-actions.md, lines 69–70: “A runner is a server that runs your workflows when they're triggered. Each runner can run a single job at a time. GitHub provides Ubuntu Linux, Microsoft Windows, and macOS runners to run your workflows. Each workflow run executes in a fresh, newly-provisioned virtual machine.”
From snapshot/docs/docs.github.com/branches.md, line 31: “A protected branch can block force pushes or deletion, require status checks, require reviews, require code owner approval, or require signed commits before changes can merge.”
From snapshot/docs/vercel.com/environments.md, lines 41–44: “Preview environments allow you to deploy and test changes in a live setting, without affecting your production site. By default, Vercel creates a preview deployment when you: - Push a commit to a branch that is not your production branch (commonly main) - Create a pull request (PR)”
From snapshot/docs/vercel.com/environments.md, line 52: “Each deployment gets an automatically generated URL, and you'll typically see links appear in your Git provider's PR comments or in the Vercel Dashboard.”
From snapshot/skills/retro/SKILL.md, line 18: “A repo with no guardrail (no pre-commit hook and no CI job running its lint/typecheck/test command) is itself a finding: an un-linted repo is a standing missed opportunity, not a neutral default.”
From snapshot/web/docs.github.com/en-actions-concepts-security-github-token.md, line 46: “when a workflow using GITHUB_TOKEN creates or updates a pull request, the resulting pull_request event creates workflow runs in an approval-required state. The pull request displays a banner in the merge box, and a user with write access to the repository can start the runs by selecting Approve workflows to run.”
From snapshot/docs/docs.github.com/branches.md, line 31: “A protected branch can block force pushes or deletion, require status checks, require reviews, require code owner approval, or require signed commits before changes can merge.”