CHAPTER 06
Building CI Pipelines
Updated: May 15, 2026
25 min read
# CHAPTER 6
Building CI Pipelines
1. Introduction
A workflow that just echoes "Hello World" is a great learning tool, but it provides no business value. The true purpose of Continuous Integration (CI) is to validate that the code a developer wrote actually functions properly before it is allowed to merge. To do this, the pipeline must mimic the developer's computer: it needs to install the correct programming language (like PHP or Node.js), download third-party dependencies, and compile the code. In this chapter, we will construct the first half of a professional DevOps pipeline: the Build Phase.2. Learning Objectives
By the end of this chapter, you will be able to:- Define the "Build Phase" of a CI/CD pipeline.
-
Use the
actions/setup-*marketplace actions to configure programming languages.
-
Execute package managers (like
composerornpm) within a workflow.
- Understand how to structure a pipeline to "Fail Fast" on syntax errors.
- Construct a functional CI pipeline for a web application.
3. Beginner-Friendly Explanation
Imagine building a Lego car.- Checkout: The robot opens the Lego box and dumps the pieces on the table. (Chapter 5).
- The Build Phase: The robot realizes it's missing the wheels. It calls the Lego factory and orders the exact wheels needed. (Downloading dependencies). Once the wheels arrive, the robot snaps all the pieces together according to the instruction manual. (Compiling the code). If a piece doesn't fit, the robot stops immediately and says "Build Failed!"
4. Setting Up the Environment (actions/setup-*)
While the ubuntu-latest runner comes with many tools pre-installed, relying on default versions is dangerous. If your app requires Node.js v18, but the runner defaults to Node.js v20, your code might break.
Best Practice: Always explicitly declare the exact version of the language your app requires. GitHub provides official actions for this:
-
actions/setup-node@v4
-
shivammathur/setup-php@v2(The industry standard for PHP in GitHub Actions)
-
actions/setup-python@v5
5. Installing Dependencies
Modern web apps rarely consist of just the code you wrote. They rely on thousands of files written by other people (Libraries/Packages).-
PHP uses
composer.
-
JavaScript uses
npm.
6. Mini Project: Build CI Pipeline for a PHP Application
Let's build a professional Continuous Integration pipeline that checks out code, sets up a specific PHP version, downloads vendor packages, and performs a rapid syntax check (Linting).Step-by-Step Walkthrough:
-
1.
Create
.github/workflows/ci-pipeline.yml.
- 2. Paste the following declarative code:
yaml
7. Real-World Scenarios
A team was relying on the default PHP version installed onubuntu-latest for their CI pipeline. Their application was written in PHP 7.4. One weekend, GitHub updated their runner images, bumping the default PHP version to 8.1. On Monday morning, every single Pull Request the team opened failed instantly because PHP 8.1 introduced breaking changes that their code couldn't handle. The DevOps engineer fixed the outage by explicitly adding the shivammathur/setup-php step and locking the version to 7.4. You must explicitly control your build environment!
8. Best Practices
- Fail Fast (Linting First): In the mini-project, Step 4 is a "Linter" (a syntax checker). It takes 2 seconds to run. Always run your fastest checks first. If a developer forgot a semicolon, the pipeline fails instantly, saving 10 minutes of cloud compute time that would have been wasted running heavy, slow integration tests.
9. Security Recommendations
-
Supply Chain Security: When you run
npm installorcomposer installin your pipeline, you are downloading code from the internet and executing it on your server. If a malicious actor hacks an open-source library you depend on, your pipeline could be compromised. Always use lock files (e.g.,composer.lockorpackage-lock.json) and run security audit commands (likenpm audit) inside your pipeline.
10. Troubleshooting Tips
- Composer/NPM Errors: If your dependency installation step fails with a network timeout, it's often a temporary issue with the package registry (like Packagist or npmjs.com), not your code. Try re-running the failed job in the GitHub UI before changing your workflow YAML.
11. Exercises
-
1.
Why is it dangerous to omit the
setup-*step and rely on the default software installed on theubuntu-latestrunner?
- 2. What is the purpose of the "Linting" step in a Continuous Integration pipeline?
12. FAQs
Q: Can I run a database like MySQL during the build phase? A: Yes! GitHub Actions provides a feature calledservices. You can spin up a temporary MySQL or Redis container right alongside your job to test database connections. We will explore this in the next chapter.
13. Interview Questions
-
Q: Explain the concept of "Dependency Hell" and how explicit environment setup steps (like
actions/setup-node) mitigate this risk in a CI/CD pipeline.
-
Q: A developer commits a change where they accidentally missed a closing bracket
}in a core application file. Walk through how the CI pipeline designed in this chapter detects and handles this error.
14. Summary
In Chapter 6, we evolved our workflows from simple scripts into functional Continuous Integration pipelines. We learned the critical necessity of explicitly defining our execution environment usingsetup actions, preventing unexpected breakages caused by underlying runner updates. We integrated package managers to hydrate our application with external dependencies, and we instituted a "Fail Fast" methodology by implementing rapid syntax linting as our first line of defense against buggy code.
15. Next Chapter Recommendation
Syntax checking is great, but it doesn't prove the math works. If2 + 2 equals 5 in your code, the syntax linter won't care. We need real tests. Proceed to Chapter 7: Automated Testing with GitHub Actions.