
Imagine this. It is 11 PM on a Friday. You just finished a new feature for your project. You have tested it locally β it works perfectly. You push your code to GitHub, feeling proud. Then, on Monday morning, your teammate pulls the latest code, runs it, andβ¦ it crashes. Somewhere between your machine and theirs, something broke.
If you have ever experienced this, you already understand why CI/CD exists. It is the practice that ensures your code works everywhere β not just on your laptop β and that it gets deployed to production safely, automatically, and reliably.
And the best part? You do not need a DevOps team or expensive tools to get started. GitHub Actions gives you everything you need for free, right inside the platform you already use.
In this step-by-step tutorial, we will walk through CI/CD from the ground up. By the end, you will have a working pipeline that tests, builds, and deploys your code automatically every time you push to GitHub. No prior DevOps experience required.
CI/CD stands for Continuous Integration and Continuous Delivery(or Continuous Deployment). It sounds technical, but the idea is simple.
Every time a developer pushes code to GitHub, the code is automatically tested. If something is broken, the team knows within minutes β not days later.
Once the code passes all tests, it is automatically prepared for release. Deploying to production becomes a single click β or completely automatic.
The most advanced form of CD β every change that passes tests is automatically deployed to production without any manual approval. Companies like Amazon, Netflix, and Google release code this way thousands of times per day.
Before CI/CD, developers would manually test and deploy code. It was slow, error-prone, and often stressful. CI/CD changes all of that.
| Without CI/CD | With CI/CD |
|---|---|
| Manual testing, slow and inconsistent | Automated tests run in minutes |
| Bugs found weeks later | Bugs found immediately |
| Deployments require manual steps | Deployments are automatic |
| "It works on my machine" | Consistent environment everywhere |
| Fear of releasing new code | Confidence in every release |
GitHub Actions is GitHub's built-in CI/CD platform. It lets you automate tasks like testing, building, and deploying your code directly from your GitHub repository.
It is:
Before we build our first workflow, let's cover the terminology. These words will appear everywhere in GitHub Actions.
| Term | What It Means |
|---|---|
| Workflow | An automated process defined in a YAML file inside your repo |
| Event | The trigger that starts a workflow (e.g., push, pull request) |
| Job | A set of steps that run on the same machine |
| Step | A single task inside a job (e.g., run a command) |
| Action | A reusable piece of code (like a plugin) that performs a task |
| Runner | The server that runs your workflow (GitHub provides these for free) |
Before you start, you need:
If you are brand new to Git, check out our What is Git? guide first.
GitHub Actions workflows live inside a special folder in your repository: .github/workflows/.
Let's create your first workflow. In your repository, create a new file at this path:
If the folders do not exist yet, create them. GitHub will automatically detect any YAML file placed inside .github/workflows/.
Open the file you just created and paste this in:
Let's break down what this does:
main branchgreetubuntu-latest means a fresh Linux machineSave the file, then commit and push:
Now open your repository on GitHub and click the Actions tab. You will see your workflow running β and within seconds, it will show a green checkmark. Click on it to see the output: "Hello, GitHub Actions!"
Congratulations β you just ran your first CI/CD pipeline.
The "Hello World" example shows the mechanics, but real CI does actual work. Let's build a workflow that tests a Node.js project.
Create a new file: .github/workflows/ci.yml
What this workflow does:
mainIf any step fails, you get a red X next to the commit and an email notification. This is the heart of Continuous Integration.
In the workflow above, you noticed lines like this:
This is called an action β a reusable piece of code created by GitHub or the community. Instead of writing the logic to download your code from GitHub, you use the official actions/checkout action.
There are thousands of actions available. Here are some you will use often:
| Action | Purpose |
|---|---|
actions/checkout | Download your code into the runner |
actions/setup-node | Install a specific Node.js version |
actions/setup-python | Install a specific Python version |
actions/cache | Cache dependencies to speed up workflows |
actions/upload-artifact | Save build files for later use |
You can find thousands more at github.com/marketplace?type=actions.
When deploying, you will often need to use API keys, tokens, or passwords. Never hardcode these in your workflow file β anyone can see your repository.
Instead, use GitHub Secrets:
API_KEY) and paste the valueSecrets are encrypted and never shown in logs. This is safe, secure, and required for any real-world deployment.
Now let's put everything together. This workflow:
main branchKey things to notice:
build only runs after test succeedsdeploy to only run on the main branchWant to test your code on multiple Node.js versions at once? GitHub Actions makes this easy with matrix builds.
This runs your tests three times β once for each Node.js version β in parallel. If any version fails, you know immediately.
Here are quick examples for popular platforms.
Note: GITHUB_TOKEN is provided automatically by GitHub. You do not need to create it yourself.
Follow these to keep your workflows fast, reliable, and secure.
actions/cache to speed up installs@v4 instead of @main for stabilitytimeout-minutesAdd this to your README.md to show your workflow status:
actions/checkout@v4.@main: Pin to a version number to avoid breaking changes.Now that you have built your first pipeline, here is how to grow from here.
.github/workflows/ as YAML files.CI/CD might sound like a DevOps buzzword, but the moment you set up your first pipeline and watch it run automatically, it clicks. It is not just a tool β it is a habit that makes you a better developer. Start small, iterate, and before long you will wonder how you ever worked without it.