my blog

$ cat github-actions/part-01.md

GitHub Actions Fundamentals: From Zero to Your First Pipeline

After working with GitHub Actions in my home lab, I want to share what I learned about the basics. This is the stuff I wish someone explained to me when I started.

What is GitHub Actions?

GitHub Actions is a CI/CD tool built into GitHub. You write YAML files that tell GitHub what to do when something happens in your repository like when you push code, open a PR, or click a button.

The Building Blocks

Every GitHub Actions workflow has 3 main parts:

1. Workflows

A workflow is a YAML file stored in .github/workflows/ in your repository. Here’s my first workflow:

name: 01 - Building Blocks
on: push

jobs:
  echo-hello:
    runs-on: ubuntu-latest
    steps:
      - name: say hello
        run: echo "Hello World!"

This workflow runs every time I push code to any branch.

2. Jobs

Jobs are groups of steps that run on the same runner. By default, jobs run in parallel, but you can make them run one after another.

Here’s something I learned the hard way if one step fails, the rest of the steps in that job won’t run:

jobs:
  echo-goodbye:
    runs-on: ubuntu-latest
    steps:
      - name: Failed Step
        run: |
          echo "I will fail"
          exit 1
      - name: say goodbye
        run: echo "Good bye"  # This never runs!

The “say goodbye” step never executes because the previous step exits with code 1.

3. Steps

Steps are individual tasks in a job. They can run commands or use pre-built actions from the marketplace.

steps:
  - name: Say hello
    run: echo "Hello, world!"

Workflow Events: When Should Things Run?

The on: field tells GitHub when to trigger your workflow. I use three main types:

Push Events

Runs when you push code:

on: push

Pull Request Events

Runs when someone opens or updates a PR:

on: pull_request

Manual Trigger

This is super useful for testing. You get a “Run workflow” button in GitHub UI:

on: workflow_dispatch

Runners: Where Does Code Run?

Runners are the machines that execute your jobs. GitHub provides three types:

jobs:
  ubuntu-echo:
    runs-on: ubuntu-latest
    steps:
      - name: Show OS
        run: |
          echo "This job is running on an Ubuntu runner."
          echo "Runner OS: $RUNNER_OS"
  windows-echo:
    runs-on: windows-latest
    steps:
      - name: Show OS
        shell: bash  # Important for Windows!
        run: |
          echo "This job is running on a Windows runner."
          echo "Runner OS: $RUNNER_OS"
  mac-echo:
    runs-on: macos-latest
    steps:
      - name: Show OS
        run: |
          echo "This job is running on a MacOS runner."
          echo "Runner OS: $RUNNER_OS"

Important: On Windows runners, you need to specify shell: bash if you want to use bash commands. Otherwise it uses PowerShell by default.

Using Pre-built Actions

You don’t have to write everything from scratch. GitHub Marketplace has thousands of actions. Here’s a real example from my React app workflow:

jobs:
  build:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 04-using-actions/react-app
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4
      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: '20.x'
      - name: Install Dependencies
        run: npm ci
      - name: Run Unit Tests
        run: npm run test

The uses: keyword tells GitHub to run an action from the marketplace. The with: section passes parameters to that action.

Context: Getting Information About Your Workflow

GitHub gives you a lot of information through the github context. You can access it using ${{ }} syntax:

steps:
  - name: Display information
    run: |
      echo "Event Name: ${{ github.event_name }}"
      echo "Ref: ${{ github.ref }}"
      echo "SHA: ${{ github.sha }}"
      echo "Actor: ${{ github.actor }}"
      echo "Workflow: ${{ github.workflow }}"
      echo "Run ID: ${{ github.run_id }}"
      echo "Run number: ${{ github.run_number }}"

This is useful for debugging or creating unique identifiers for your builds.

What I Learned

  1. Start small: My first workflow was just echo commands. Then I added real steps one by one.
  2. Use workflow_dispatch: Adding manual triggers makes testing so much easier. You don’t have to push code just to test your workflow.
  3. Check the logs: When something fails, GitHub shows you exactly which step failed and why. The logs are your best friend.
  4. Runners cost money: GitHub gives you free minutes, but they run out. Ubuntu runners are cheapest. Windows and macOS cost more.
  5. YAML is sensitive: Indentation matters. A lot. One extra space and your workflow won’t work.

My Setup

I’m running these workflows in my home lab where I practice DevOps concepts. All my code is on GitHub, and I use these workflows to automate testing and deployment.

$ ls -t root-access/ | head -3

Hello world! uncategorized 1 min Building a Job Board API, Part 1: The Foundation job-board-api · 1/1 16 min Part 13 – Kubernetes Autoscaling in Action: A FastAPI Microservice That Scales Itself home-lab · 13/13 6 min

Leave a comment

Your email address will not be published. Required fields are marked *