CI/CD Basics

Expected level: Working

Continuous integration (CI) means merging changes often and having a server automatically build and test every change. Continuous delivery and deployment (CD) extend that by automating the release of passing builds to environments.

What happens when you push a commit

A pipeline is a defined series of automated steps, triggered by an event such as a push or a pull request. A typical CI run:

  1. Checks out the code at that commit onto a clean machine.
  2. Restores dependencies.
  3. Builds the project.
  4. Runs automated tests (see Unit Testing and Integration Testing).
  5. Runs other checks such as linting, formatting or a dependency scan (see Dependency Risks).
  6. Reports pass or fail, usually on the pull request, and may store the build as an artifact.

If a step fails, the pipeline stops and the change should not be merged.

CI, delivery and deployment

  • Continuous integration: build and test every change, merged to the main line often.
  • Continuous delivery: every passing build is ready to release, and a person decides when to deploy it.
  • Continuous deployment: every passing build is deployed to production automatically.

“CD” is used for either of the last two, so check what a team means by it.

Pipelines as code

Most tools (GitHub Actions, Azure Pipelines, GitLab CI and others) define pipelines in a file in the repository, usually YAML. The pipeline is versioned and reviewed like any other code. The file is where you find which commands run and in what order.

Using a pipeline day to day

  • Run the same build and test commands locally before pushing.
  • Read the failing step’s log first; the cause is usually near the first error (see Log Analysis).
  • Keep the pipeline fast. Fix or remove flaky tests instead of re-running until green.
  • Pass secrets through the tool’s secret store, never in the pipeline file (see Secrets Management).
  • Pipelines usually deploy through environments, with a manual approval before production in many teams.

Try it

Open a repository you work on and find its pipeline definition file. Write down the trigger, each step, and what would make it fail. Then break something on a branch on purpose, for example a failing test, push it and watch the pipeline report it.

Common mistakes

  • Re-running a flaky test until it passes instead of fixing it.
  • Putting secrets in the pipeline file instead of the secret store.
  • Pushing without running the same build and tests locally first.
  • Reading the end of a long log instead of the first error.

Check yourself

  • What is the difference between continuous delivery and continuous deployment?
  • Where do you find which commands a pipeline runs?
  • Where in a failing log should you start reading?

Related topics

Terms

Further reading