CI/CD: a deploy on every commit
Why:Uploading a site by hand over FTP means hoping nothing was forgotten. Afterwards you’ll understand continuous integration and delivery, read and write a pipeline file for GitHub Actions that checks, builds and deploys your site, keep secrets in settings, and know how to roll back a bad version.
25 minutes
Read by speech synthesis (Qwen3-TTS); the voice is not a person’s.
CI/CD is a pipeline that checks, builds and deploys a site on every commit by itself, and deploys only when every check has passed.
Friday evening, FTP
Remember how a site was deployed in 2010: open a program, connect to the server, drag files from one folder to another. What can go wrong here? Everything. One file forgotten. The wrong version uploaded. A broken link unnoticed. A change goes to the live site unchecked, and the earlier version is nowhere. And all of it is known by one person who “knows how to upload”.
The modern answer is called CI/CD, and behind the two letters hides a simple idea: let a machine do the deploying, by written rules, the same way every time.
- CI (continuous integration): every change is built and checked automatically at once. Small edits, frequent checks, and a mistake is found while it is fresh.
- CD (continuous delivery or deployment): a checked version reaches people automatically. With delivery, a version is always ready, and a person presses the last “release” button. With deployment, the site is updated by itself after green checks. For a small site the second is usually the choice.
For you this means that editing a site turns from a ritual into a commit: you saved a change in the repository (you know Git as a way to keep versions), pushed it to the main branch, and everything after that goes by itself.
The stations of a pipeline
A pipeline is a chain of stations, and each checks or does something. If a station jams (turns red), nothing goes further.
- The start: an event, such as a commit to the
mainbranch or an opened pull request. - Checks: broken links, markup errors, tests, accessibility, the presence of the pages that must exist.
- The build: turns the sources into a finished site (you read about building in the part on JavaScript).
- A preview: a draft at a temporary address so you can look at it with your own eyes. Many platforms make one for every pull request.
- The deploy: replacing the live site, but only when everything before it is green.
- A notice: a message in the chat or by email: “published”, or “failed on the link check”.
Run a change through the diagram. Then jam different stations and compare with deploying by hand: there nobody stops a bad change. Switch on “a mistake the checks can’t see” and press “Roll back”.
Press a station to jam it, then run.
-
You saved an edit and pushed it to the main branch.
-
Links, markup, the privacy notice and consent page.
-
Builds the pages: Home, Services, Contact.
-
Publishes a draft at a temporary address so you can look at it.
-
Replaces the live site with the new version, once everything above has passed.
-
Writes to the chat or by email: what was published or what failed.
The result appears after the run.
Check yourself: why does the deploy come after the checks and not beside them?
So that a bad version doesn’t reach the live site: if any check is red, the deploy never starts, and the site stays as it was.
What it looks like in a file
A pipeline is written in a file. In GitHub Actions it is a text YAML file in the .github/workflows/ folder. Here is a file for a site on GitHub Pages (the lesson on publishing shows it at work):
name: Check and deploy the site
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Links and markup
run: npm run check:links && npm run check:html
- name: Build the pages
run: npm run build
- name: The privacy notice and consent page is there
run: test -f dist/privacy/index.html
- uses: actions/upload-pages-artifact@v5
with:
path: dist
deploy:
needs: check
runs-on: ubuntu-latest
environment: github-pages
steps:
- uses: actions/deploy-pages@v5 Read it as instructions. on: push: branches: [main]: run on every commit to main. There are two jobs: check (check and build) and deploy. The line needs: check says the deploy waits for the checks to succeed, and if they are red it won’t run. Each step is either a ready-made action (uses:, for example getting the code) or a command (run:). The version numbers of the actions (@v7, @v5) keep changing: the current ones are in the documentation (in the sources), and these were the latest releases in October 2026.
Lines such as npm run check:links are your own commands: they are defined in the project. What each does depends on the tools you chose: a link checker, a markup checker, a bundler. This textbook is checked the same way: on every change it runs type checks, tests, an accessibility check, a link check and a content check, and only then is the main branch deployed to Pages. If the site has a form, add a check that the privacy notice and consent page exists (a step in the example): that way the important page won’t be lost in the next edit.
GitLab writes the same thing in a file called .gitlab-ci.yml, and platforms such as Netlify, Vercel and Cloudflare Pages manage with no file at all: connect a repository, and they build and deploy on every commit themselves. That is the simplest pipeline, and for many sites it is enough.
Secrets
A pipeline needs rights: to deploy to hosting, to write in the chat. Those rights are kept in tokens and keys. The main rule is the same as in Docker: secrets don’t live in the repository. Not in the pipeline file, not in the code, not in the README. Colleagues, contractors and sometimes the whole world read a repository, and Git’s history keeps everything for good: a deleted file stays in the old commits.
Secrets go into the service’s settings (at GitHub, the “Secrets and variables” section in the repository’s settings). The file holds only a name, such as secrets.NOTIFY_URL, and the platform fills in the value at run time, hiding it in the log. Three more habits: give a token the least rights it needs (only deploying), pin the versions of other people’s actions (other people’s code runs with your rights), and remember that pull requests from other people’s copies of the repository don’t get secrets.
Check yourself: why can’t you just delete a token from the repository after it got there?
It stays in the commit history, and anyone who read or copied the history could have seen it. A token that got into a repository counts as leaked: you revoke it and issue a new one.
Rolling back
Any pipeline will one day release a bad version: checks don’t see everything. So decide in advance how you will go back.
- Through Git. The
git revertcommand creates a new commit that undoes the bad one. You push it tomain, and the same pipeline deploys the earlier behavior. You don’t rewrite the main branch’s history with a forced push: that is how other people’s work gets lost. - Through the hosting panel. Static platforms keep earlier deploys, and you can make one of them live with a button.
- First bring it back, then investigate. Minutes of downtime are worth more than a fine understanding of the cause.
The one thing a rollback can’t fix is data: if a bad version spoiled the database, the data has to be restored, and that needs backups (the last lesson of the part).
Practice
In front of you is your project’s site, and under it a pipeline file with gaps. Finish it: a start on a push to main, a check job with the build and the checks (links, markup and, if the project has a form, the privacy page), a deploy job with needs: check, and a secret as secrets.NAME. Then write what the build checks for each section of the brief, and how you would roll back.
The file here is only read and checked: Actions can’t be run in the sandbox. In the next lesson you’ll deploy a real site, and this file will be useful to you.
What was wrong before
In 2010 people were afraid of the word “release”: once a month, at night, with a six-page checklist and one person who had “everything set up”. After a release, a week went on fixing what was found. The idea of continuous integration appeared earlier (in the late 1990s), but it became ordinary for small sites only when free pipelines came with repositories. Now a release is boring, and that is exactly what was wanted.
Practice
Preparing your page…
Test
Question 1 of 5
Cards
These cards go into your review once you finish the lesson.
What are CI and CD?
Answer
CI (continuous integration): every change is built and checked automatically. CD: continuous delivery (a version is always ready, and a button deploys it) or deployment (after the checks it goes to the site by itself).
What is a site’s pipeline made of?
Answer
A start on commit, checks (links, markup, consent), a build, a preview, a deploy only after green checks, a notice. If any station fails, nothing goes further.
Where do you keep a pipeline’s tokens and keys?
Answer
In the service’s secrets settings. The pipeline file refers to a name, and the value never reaches the repository. If someone read the repository, they read everything in it.
How do you roll back a bad version?
Answer
Bring back the previous one: git revert the bad commit and push (the pipeline deploys the earlier version), or pick an earlier deploy in the hosting panel. Don’t rewrite the history of main.
Sources
- GitHub Docs: Understanding GitHub Actions CC BY, in English
- GitHub Docs: Using custom workflows with GitHub Pages CC BY, in English
- GitLab Docs: CI/CD link only, in English
- Continuous integration (Wikipedia) CC BY-SA, in English
- The Twelve-Factor App link only, in English
Videos
DevOps CI/CD Explained in 100 Seconds (Fireship)
The video loads from youtube-nocookie.com only when you press play.
GitHub Actions Tutorial: Basic Concepts and CI/CD Pipeline with Docker (TechWorld with Nana)
The video loads from youtube-nocookie.com only when you press play.
Next
You now know: CI/CD.