Skip to content
Français
CI/CD & Automatisation medium

Deploying with GitHub Actions: from CI to CD

15 min de lecture

Read this page in French

A green CI grants no right to deploy to production. This module shows how GitHub Actions materialises that boundary: an environment carries its own secrets, requires a human approval, restricts the allowed branches, and logs every deployment. You will build a build once, promote afterwards chain, from the pull request to production, with a rollback that does not depend on a rebuild.

What you will learn

  • Tell apart what CI covers from what CD covers, and what GitHub calls a deployment
  • Create an environment and attach a job to it, with the deployment URL
  • Apply protection rules: approvals, wait timer, allowed branches
  • Promote a single artifact from staging to production, without rebuilding it
  • Go back without replaying the whole pipeline

CI and CD do not ask the same question

Continuous integration answers a question of quality: does this commit break anything? It runs on every branch, every pull request, and its verdict is binary. Continuous deployment answers a question of trust: is this artifact allowed to reach the users? The answer no longer depends on the tests alone, but on who approves, from which branch, with which secrets, and towards which target.

Confusing the two produces the most widespread mistake: a single workflow that tests, builds and deploys in the same job, with every production secret loaded from the first line. One compromised test, one boobytrapped dependency, and the attacker inherits production access.

QuestionAnswered byGitHub mechanism
Does the code compile and pass the tests?CIJobs, matrices, cache
Is the artifact the one we think it is?Supply chainSHA pinning, attestations
Who authorises the production release?CDEnvironments, protection rules
How do we go back?CDA kept artifact, a redeployment

What GitHub calls a deployment

A deployment is not merely a job running a script. It is an object GitHub records: it appears in the repository's Deployments tab, it carries a target environment, a state (pending, in progress, succeeded, failed), and possibly a browsable URL. That traceability is what separates an ssh server "./deploy.sh" from an auditable delivery chain.

The trigger for that machinery fits in one workflow key:

jobs:
deploy:
runs-on: ubuntu-24.04
environment: production
steps:
- run: ./deploy.sh

From that line on, the job is no longer an ordinary job. It is subject to the rules of the production environment: if an approval is required, GitHub pauses the job and waits; if the current branch is not allowed, the job fails before starting; and the environment secrets are delivered only once those conditions are met.

The promotion chain

The mental model to install is a promotion line, not a series of independent deployments. You build one single artifact, and it is that same artifact that travels through the steps:

Pull request
|
v
CI (tests, lint, scanners)
|
v
Build -> a single artifact plus its attestation
|
v
Staging (environment, staging secrets)
|
v
Human approval
|
v
Production (protected environment, production secrets)

The property that matters is this one: what is tested in staging is exactly what goes to production. Rebuilding between the two steps breaks the guarantee, because the second build may resolve different dependencies, carry an untested fix, or simply fail after the validation has already been granted.

It is also what makes going back trivial: the previous artifact is still there, you only have to redeploy it. A rollback that requires replaying the whole pipeline is not a rollback, it is a new deployment with the risks of a new deployment.

How this module is laid out

The following pages build that chain in the order you would set it up on a real repository. The progression goes from the container (the environment) to the content (the promoted artifact), then to what happens when things go wrong.

StepWhat it installs
EnvironmentsThe named target, with its own secrets and variables
Protection rulesApprovals, wait timer, allowed branches
Artifact promotionA single build travelling through staging then production
Releases and packagesPublic distribution: a GitHub release, a GHCR image
Rollback and concurrencyGoing back, and forbidding simultaneous deployments

The billing trap to know up front

Environments with protection rules and environment secrets are not available everywhere. On a Free plan, they only work on public repositories: a private repository requires at least GitHub Pro, or a Team or Enterprise plan for an organisation.

That limit has a direct teaching consequence: if you follow this module on a private repository under a free plan, the environment will indeed be created, but the approvals and the environment secrets will not apply. Work on a public repository dedicated to learning, or check your organisation's plan before building a governance on top of it.

Key points

  • A green CI validates the quality of the code; it does not authorise a deployment. CD answers a different question, that of trust.
  • A GitHub deployment is a tracked object: a target environment, a state, a URL, a history in the Deployments tab.
  • The environment: key subjects the job to the environment rules: a pause for approval, a refusal when the branch is not allowed, secrets delivered only afterwards.
  • Naming a non-existent environment creates it with no protection at all: configure it in Settings > Environments before writing the job.
  • You build once and promote: the artifact tested in staging must be exactly the one going to production.
  • Protected environments and their secrets require a public repository on a Free plan, or at least GitHub Pro on a private one.

Next steps

  • Protection rules: the four guardrails that turn an environment into a real boundary, approvals included.
  • Promoting an artifact: the build once, deploy twice chain that guarantees staging and production get the same binary.
  • Rollback and concurrency: what has to be prepared before the incident to go back in minutes.

Is this site useful to you?

Fewer than 1% of readers support this site.

I maintain more than 700 free guides, with no ads and no tracking. Any support, even a symbolic one, helps cover hosting and keeps these resources free. Thank you for the help.

The form does not show? Open Ko-fi in a new tab.

Subscribe and follow my DevSecOps work on LinkedIn