A Beginner's Guide to UK GDPR for Web Developers: Cookies, Consent and Data Requests
October 07, 2026 - Web Development
A manual deploy is a quiet sort of technical debt. You SSH in, run the tests you half-remember, pull the latest commit, restart the process, and hope the lockfile on the server matches the one in your editor. It works for a while. Then it's Friday afternoon, someone else's branch is live, and nobody can say which commit is running.
GitHub Actions replaces that ritual with something duller and better: every push runs your tests, and every merge to your main branch ships a build. No new servers, no third-party account, and no YAML wizardry beyond what you actually need. Here's a practical path from manual deploys to a pipeline you can trust.
Resist building everything at once. A useful first pipeline has three stages, in order:
That separation matters. Tests should be fast and always run; deploys should be deliberate and gated. Folding them into one script is how teams end up with a green tick next to a broken release.
Ten minutes of preparation saves an afternoon of red crosses.
One more check: does your test suite exit cleanly? If it hangs on your machine, it will hang on a runner, and you will spend an hour blaming GitHub.
Workflows live in .github/workflows/. Create a file there — call it ci.yml — with a name, a trigger block, and one job.
The trigger is the easy part: on: push for every branch, plus pull_request so contributors get feedback before anyone reviews the diff.
The job needs runs-on: ubuntu-latest and a short list of steps. First, check out the code with actions/checkout. Then set up Node with actions/setup-node, passing your version and setting the cache option to npm — that alone trims minutes off most builds by reusing downloaded packages between runs. Install with npm ci, then run npm test.
Pin the actions to a major version (@v4 rather than a floating tag) so a breaking change upstream doesn't wake you on a Tuesday morning.
If you maintain a library, or your team is midway through an upgrade, a matrix is worth the four extra lines. List two versions — say 20 and 22 — and GitHub runs the job once per version, in parallel. When the older one fails, you know precisely which release dropped support for the API you're using, instead of guessing from a production error later.
Once tests have been green reliably for a week, add the rest. Use needs so the deploy job only runs when the test job succeeds.
Write a deploy job with needs: test and a condition limiting it to your main branch. If you deploy over SSH, add the private key to repository secrets, write it to a file with the ssh-agent action, then use rsync to push the built output to the server. After shipping, run whatever restart command your setup uses and check the app responds — a deploy that doesn't verify itself is only half a deploy.
Attach the job to a GitHub environment, for example "production". That gives you a deployment history, and you can require manual approval before the job runs. For most teams, a human clicking a button once a week is a small price for not discovering a bad migration at midnight.
Two details make deploys calmer. Add a concurrency group so two pushes in quick succession can't deploy on top of each other; GitHub will queue or cancel the older run. And make the deploy idempotent — running it twice should leave you in the same state, not halfway through a broken one.
Most first failures are dull ones. npm ci fails when the lockfile is out of sync with package.json — run npm install locally, commit the updated lockfile, push again. A test that passes locally but fails in CI usually means a missing environment variable, or a file path that only exists on your machine. A workflow that never triggers is usually an indentation error in the YAML, or a branch filter that doesn't match. Read the log from the top; the real error is rarely the last line.
The goal isn't an impressive pipeline. It's one you stop thinking about. Tests on every push, a deploy behind a button, secrets in the right place, and a running version you can trace back to a commit. Start with the test job this afternoon, watch it go green a few times, then add the deploy step once you trust it. Within a month you'll have forgotten what the manual version felt like, which is exactly the point.
Photo: jamesmarkosborne / Pixabay
Copyright © 2026 Wren Stack. All Right Reserved.