How do you catch a broken change before customers get it?
Run a check every time someone proposes a change, try the passing version on a test site and make the live release depend on that result. Start with one customer action you can describe and verify.
What should a check tell you before you ship?
Start with one important promise your app makes. For a booking page, a time that is already taken should be unavailable. An automated check repeats that example when you propose a change and reports whether it still holds.
Continuous integration, or CI, is the habit of checking changes together as they arrive. A runner is the computer that follows the check instructions. A passing run says the checks you wrote passed for that version.
How do you try the change before customers see it?
Before sending the checked version to staging, confirm that it will use only a test database and test credentials, and that outgoing services such as email and payments are test-only or disabled. A different address can still connect to live services. If you cannot confirm the connections, use the paper rehearsal below. Once staging is isolated, release the checked version there and try the important customer action. Decide who can release that same version to the live site and what should stop them.
Continuous delivery, or CD, keeps a checked version ready to publish. Delivery can still wait for a person. Before switching traffic, write down which version is live, where the replacement will go and how to restore the earlier version. Reverting the app may leave changed data in place. Check that recovery separately.
Compare tools
Scroll the table sideways to read every column.
| Tool | Where checks are definedWhich project and instructions the service uses. | How a release waitsWhich setting makes the next step wait and who can continue. | What can use up your allowanceWhat the plan counts while checks and builds run. | What to keepWhich instructions or files can move with your app. |
|---|---|---|---|---|
| GitHub Actions | Runs next to a GitHub repository. Store the workflow in .github/workflows. | Use a deployment environment and check whether your plan supports a required reviewer for that repository. | Standard hosted runners are free in public repositories. Private work has included usage and can incur runner and storage charges. | Keep the workflow file with the code. Save needed reports beyond run retention. |
| GitLab CI/CD | Define jobs and stages in .gitlab-ci.yml in the GitLab project. | Use a blocking manual job. Check protected-environment entitlements if only certain people should release. | GitLab.com Free includes 400 compute minutes per namespace per month. Runner cost factors affect use. | Keep the pipeline file and download needed artifacts before expiry. |
| CircleCI | Connect a code project and put jobs and their dependencies in .circleci/config.yml. | Require an approval job before deployment. Check who has repository push access and who can run the downstream job. | Free includes 30,000 monthly non-open-source credits. Machine class, storage and network use affect how fast you spend them. | Keep the config with the project. Save any needed build reports or files separately. |
| Bitbucket Pipelines | Keep build and test steps in the Bitbucket Cloud repository’s pipeline file. | Make a later step manual. Premium offers separate deployer restrictions. | Compare hosted build minutes, storage and step limits. Budget for your own runners if used. | Keep the pipeline file and scripts, plus a record of environment settings. |
| Azure Pipelines | Define build, test and release stages in the Azure DevOps project. | Resource owners set approvals outside the pipeline YAML. Check the stage uses that resource. | Count simultaneous jobs and hosted minutes. The free grant can require a request. | Keep the YAML, scripts and selected artifacts. Record separate approval settings. |
| Jenkins | Review the Jenkinsfile in Git. The controller schedules work for agents. | Use an input step with a named approver or group. Administrators can still respond. | Jenkins core is open source. Budget for workers, controller and plugin maintenance. | Keep the Jenkinsfile, scripts and controller recovery copy. Store recovery keys separately. |
| Buildkite | Define steps in Buildkite’s editor or a repository file. Pick the workers that run them. | Use a block step with a team permitted to continue. | Check seats, self-hosted concurrency and hosted compute by machine. | Keep pipeline and worker settings. Save needed output beyond artifact retention. |
| Changesets | Commit small notes that say which packages change and how much to bump them. | Review the version and changelog pull request. Configure publication separately. | Open-source tooling uses your runner and package registry allowances. | Keep change notes, package files, configuration and the changelog. |
| Release Please | Use consistent commit messages to produce a release pull request on GitHub. | Review and merge the release proposal. Registry publishing or deployment is separately configured. | The open-source tool has no separate runner allowance. Check your workflow provider and registry. | Keep commit history, release configuration, version tags and notes. |
| Coolify | Choose an app source and the server that runs it. Keep separate checks in your pipeline. | Use a manual-only deployment or configure an automatic source trigger. Verify the selected version. | Cloud manages Coolify itself. The app server and data services have separate costs. | Keep source and deployment settings. An older app image does not restore the database. |
What does a blocked release look like?
Rehearse a booking change on paper. Use no account, live app or connected hosting service.
- Write the success conditionA second booking cannot claim an already reserved time.
- Trace a failureWrite that the second booking was accepted. Stop before staging or publishing and record what failed.
- Trace a passing versionWrite that the second booking was refused. Draw the step that sends the checked version to the test address and name the person who would decide when to ship.