Skip to main content

Command Palette

Search for a command to run...

Step-by-Step Guide to Building Your First GitHub Actions Pipeline

Updated
5 min read
Step-by-Step Guide to Building Your First GitHub Actions Pipeline
V
DevOps Engineer with 20 years of experience designing scalable CI/CD pipelines, automating cloud infrastructure, and leading high-performing SRE teams. Expert in AWS, Kubernetes, Docker, and Terraform with a strong focus on reliability, security, and performance optimization.

Modern software development demands speed, consistency, and reliability. Manual deployments and ad hoc testing processes inevitably introduce risk. GitHub Actions emerged as one of the most widely adopted CI/CD platforms because it integrates directly into GitHub repositories and enables teams to automate nearly every aspect of their software delivery lifecycle.

A GitHub Actions pipeline can automatically:

  • Build applications

  • Execute tests

  • Scan for vulnerabilities

  • Create artifacts

  • Deploy to production

  • Notify teams

The result is a streamlined software delivery process that reduces human error while accelerating releases.

Understanding GitHub Actions Architecture

Before writing workflows, understanding the core building blocks is essential.

Workflows

A workflow is an automated process defined inside a YAML file.

name: First Workflow

Each workflow performs a specific task such as testing or deployment.

Events

Events trigger workflows.

Common examples include:

on:
  push:
    branches:
      - main

Other events include:

  • pull_request

  • workflow_dispatch

  • release

  • schedule

Jobs

A workflow contains one or more jobs.

jobs:
  build:
    runs-on: ubuntu-latest

Jobs execute independently unless dependencies are specified.

Steps

Jobs contain steps.

steps:
  - name: Display Message
    run: echo "Hello World"

Each step performs a specific action.

Runners

Runners execute workflow jobs.

GitHub provides managed runners:

runs-on: ubuntu-latest

Available options:

  • Ubuntu

  • Windows

  • macOS

  • Self-hosted runners

Preparing Your Repository

Create a sample repository structure.

my-app/
├── app.py
├── requirements.txt
├── tests/
│   └── test_app.py
└── .github/
    └── workflows/

GitHub automatically detects workflow files stored inside:

.github/workflows/

Creating Your First Workflow

Create a new file:

.github/workflows/ci.yml

Basic workflow example:

name: My First Pipeline

on:
  push:
    branches:
      - main

jobs:
  hello-world:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4

    - name: Print Message
      run: echo "Pipeline Executed Successfully"

When code is pushed to the main branch, GitHub automatically executes the workflow.

Adding Automated Testing

Testing is typically the first CI task.

Example Python application:

def add(a, b):
    return a + b

Test file:

from app import add

def test_add():
    assert add(2, 3) == 5

Workflow configuration:

name: Unit Tests

on:
  push:

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4

    - name: Setup Python
      uses: actions/setup-python@v5
      with:
        python-version: "3.12"

    - name: Install Dependencies
      run: |
        pip install pytest

    - name: Run Tests
      run: pytest

Every commit now validates application correctness automatically.

Building and Packaging Applications

Most pipelines generate artifacts.

Example Node.js build:

- name: Install Dependencies
  run: npm install

- name: Build Application
  run: npm run build

Store build artifacts:

- name: Upload Artifact
  uses: actions/upload-artifact@v4
  with:
    name: application-build
    path: dist/

Artifacts can later be deployed or distributed.

Managing Secrets and Environment Variables

Hardcoded credentials are a major security risk.

GitHub provides encrypted secrets.

Example:

env:
  API_URL: https://api.example.com

Using secrets:

env:
  API_TOKEN: ${{ secrets.API_TOKEN }}

Access secrets in GitHub:

Repository
→ Settings
→ Secrets and Variables
→ Actions

Never store passwords or API keys inside workflow files.

Deploying Applications Automatically

Continuous Delivery automates deployments after successful testing.

Example deployment:

deploy:
  runs-on: ubuntu-latest

  needs: test

  steps:
  - uses: actions/checkout@v4

  - name: Deploy
    run: |
      echo "Deploying application"

Deploying to Kubernetes:

- name: Configure Kubectl
  uses: azure/setup-kubectl@v4

- name: Deploy to Cluster
  run: |
    kubectl apply -f deployment.yaml

Production deployments become repeatable and predictable.

Monitoring and Debugging Pipelines

Failures inevitably occur.

GitHub Actions provides extensive logging.

Example debug output:

- name: Debug Variables
  run: |
    env

Enable workflow debugging:

ACTIONS_STEP_DEBUG=true

Common troubleshooting areas:

  • YAML syntax errors

  • Missing secrets

  • Dependency failures

  • Incorrect permissions

Workflow logs should be reviewed after every failure.

Advanced Workflow Features

Matrix Builds

Test multiple environments simultaneously.

strategy:
  matrix:
    python-version:
      - 3.10
      - 3.11
      - 3.12

Setup:

- uses: actions/setup-python@v5
  with:
    python-version: ${{ matrix.python-version }}

One workflow now validates multiple runtime versions.

Conditional Execution

Execute steps only when conditions match.

- name: Deploy Production
  if: github.ref == 'refs/heads/main'
  run: echo "Deploying"

Reusable Workflows

Shared workflows reduce duplication.

jobs:
  call-workflow:
    uses: company/shared/.github/workflows/build.yml@main

Large organizations frequently standardize pipelines this way.

Security Best Practices for GitHub Actions

Security should be embedded into every pipeline.

Restrict Permissions

permissions:
  contents: read

Avoid granting unnecessary privileges.

Pin Action Versions

Bad practice:

uses: actions/checkout@main

Good practice:

uses: actions/checkout@v4

Version pinning prevents unexpected changes.

Scan Dependencies

Example using Trivy:

- name: Trivy Scan
  uses: aquasecurity/trivy-action@master
  with:
    scan-type: fs

Supply chain attacks increasingly target CI/CD pipelines.

Complete Production-Ready Pipeline Example

name: Production Pipeline

on:
  push:
    branches:
      - main

permissions:
  contents: read

jobs:

  test:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4

    - uses: actions/setup-python@v5
      with:
        python-version: "3.12"

    - run: |
        pip install pytest
        pytest

  security:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4

    - uses: aquasecurity/trivy-action@master
      with:
        scan-type: fs

  build:
    needs:
      - test
      - security

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4

    - run: |
        docker build -t app:${{ github.sha }} .

  deploy:
    needs: build

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4

    - name: Deploy Application
      run: |
        kubectl apply -f deployment.yaml

GitHub Actions has transformed CI/CD by making automation accessible directly within the development workflow. A simple pipeline can begin with automated testing and gradually evolve into a sophisticated delivery platform that performs security scanning, artifact management, infrastructure deployment, compliance validation, and production monitoring.

The most successful DevOps teams start with a small workflow, automate repetitive tasks, continuously refine their pipelines, and treat CI/CD as a product rather than a collection of scripts. Once mastered, GitHub Actions becomes a powerful foundation for modern software delivery at any scale.