Automating DevOps Workflows with GitHub Actions in 2026
In the fast-paced world of software development, automation is crucial for efficiency and consistency. GitHub Actions, a powerful feature of GitHub, allows developers to automate their software development workflows directly in their GitHub repositories. As of 2026, it has become a staple in DevOps for continuous integration and continuous deployment (CI/CD). This tutorial will guide you through setting up GitHub Actions to automate various tasks, enhancing your DevOps workflows.
Prerequisites
Before you begin, ensure you have the following installed:
-
Git: Version control system to manage your code.
sudo apt-get update sudo apt-get install git -
Node.js and npm: Required for running JavaScript-based projects.
sudo apt-get install nodejs sudo apt-get install npm -
GitHub Account: You need a GitHub account to create repositories and utilize GitHub Actions.
-
Basic Knowledge of YAML: GitHub Actions workflows are defined using YAML.
Project Structure
We'll start with a basic project structure to demonstrate GitHub Actions:
my-github-actions-project/
├── .github/
│ └── workflows/
│ └── ci.yml
├── src/
│ └── index.js
└── package.json
Step 1: Set Up a Basic Node.js Project
Create a directory for your project and initialize a Node.js application.
mkdir my-github-actions-project
cd my-github-actions-project
npm init -y
This command will create a package.json file in your project directory. The -y flag automatically answers "yes" to all prompts, generating a default package configuration.
Step 2: Create a Simple JavaScript Application
Next, create a simple JavaScript file in the src directory.
mkdir src
touch src/index.js
Add the following code to src/index.js:
// src/index.js
console.log("Hello, GitHub Actions!");
This JavaScript file simply logs a message to the console.
Step 3: Define a GitHub Actions Workflow
Create a GitHub Actions workflow file to automate the process of running your Node.js application.
mkdir -p .github/workflows
touch .github/workflows/ci.yml
Add the following content to .github/workflows/ci.yml:
# .github/workflows/ci.yml
name: Node.js CI
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
- name: Install dependencies
run: npm install
- name: Run application
run: node src/index.js
Explanation:
- name: This is the name of the workflow, "Node.js CI".
- on: Specifies the events that trigger the workflow. This workflow runs on pushes and pull requests to the
mainbranch. - jobs: Defines a job named
buildthat runs on the latest Ubuntu environment. - steps: Lists the steps in the job:
- actions/checkout@v3: Checks out your repository under
$GITHUB_WORKSPACE. - actions/setup-node@v3: Sets up Node.js version 16.
- npm install: Installs the project dependencies.
- node src/index.js: Runs the JavaScript application.
- actions/checkout@v3: Checks out your repository under
This setup ensures that every time you push to or create a pull request against the main branch, your application is built and executed, verifying that it works as expected.
Step 4: Add Testing to Your Workflow
Testing is a critical part of any CI/CD pipeline. Let's add a test script to our Node.js application and ensure that our GitHub Actions workflow runs these tests.
First, install a testing framework. We'll use Jest for this example.
npm install --save-dev jest
Next, update your package.json to include a test script. Add the following line to the "scripts" section:
"scripts": {
"test": "jest"
}
Create a test file for your application:
mkdir __tests__
touch __tests__/index.test.js
Add the following code to __tests__/index.test.js:
// __tests__/index.test.js
test('sample test', () => {
expect(true).toBe(true);
});
This simple test checks that true is indeed true, serving as a placeholder for more complex tests.
Update your GitHub Actions workflow to include a test step. Modify .github/workflows/ci.yml as follows:
# .github/workflows/ci.yml
name: Node.js CI
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
- name: Run application
run: node src/index.js
Explanation:
- npm test: Executes the test script defined in
package.json, running all Jest tests.
Step 5: Cache Dependencies
Caching dependencies can significantly speed up your workflow execution. Add a cache step to your workflow:
Modify .github/workflows/ci.yml:
# .github/workflows/ci.yml
name: Node.js CI
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
- name: Cache Node.js modules
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
- name: Run application
run: node src/index.js
Explanation:
- actions/cache@v3: Caches the
node_modulesdirectory to speed up subsequent builds.
Complete Working Example
Here's the complete file structure and content for your project:
Project Structure
my-github-actions-project/
├── .github/
│ └── workflows/
│ └── ci.yml
├── src/
│ └── index.js
├── __tests__/
│ └── index.test.js
└── package.json
.github/workflows/ci.yml
name: Node.js CI
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
- name: Cache Node.js modules
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
- name: Run application
run: node src/index.js
src/index.js
console.log("Hello, GitHub Actions!");
tests/index.test.js
test('sample test', () => {
expect(true).toBe(true);
});
package.json
{
"name": "my-github-actions-project",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "jest"
},
"devDependencies": {
"jest": "^29.0.0"
}
}
Common Errors and Fixes
-
Error: No matching version found for node
Ensure the Node.js version specified in the workflow is available. Check available versions using the setup-node action documentation. -
Error: Cannot find module 'jest'
Ensure you have installed Jest as a development dependency. Runnpm install --save-dev jest. -
Cache Not Restoring
Verify the cache key is correctly configured and matches the structure of yourpackage-lock.json.
Conclusion
This tutorial demonstrated how to set up a GitHub Actions workflow for a Node.js project, including building, testing, and caching dependencies. By automating these processes, you can enhance the reliability and efficiency of your DevOps workflows.