Build Job on Push Events

Run a build job on push events — CI/CD foundations tutorial, lesson 5. Learn hands-on steps, troubleshooting, and what to study next.

Focus: run a build job on push events

Sponsored

You just pushed a commit, and nothing happened. No tests ran, no build kicked off, no feedback loop — just a silent remote and a lingering 'did I break anything?' feeling in your gut. That silence is the number one sign you haven't wired up a CI/CD trigger yet. This lesson shows you how to close that gap by configuring a workflow that runs a build job on push events — the backbone of every modern continuous integration pipeline.

The problem this lesson solves

Without an automatic trigger, your build only runs when you remember to run it — and in a team, that means it runs whenever someone happens to think of it. The result? Broken main branches, merge conflicts that surface days late, and a deployment process that depends on tribal knowledge instead of tooling.

The core problem is reliability through automation. A push event is the earliest, most natural signal that new code exists. By tying your build to that event, you turn every commit into a potential quality checkpoint. No more "works on my machine" — the pipeline becomes the source of truth.

This lesson teaches you to:

  • Explain the core idea behind running a build job on push events
  • Complete a practical exercise that wires a real GitHub Actions workflow
  • Connect this trigger to the broader CI/CD foundations track, including pipeline anatomy, artifacts, and promotions

Core concept / mental model

Think of a push event as a knock on the door. Your CI system is the butler who hears that knock and immediately starts executing a predefined checklist. The checklist is your workflow file, and each step in the checklist is a job.

In GitHub Actions, three components work together:

  1. Event — the trigger (here, push)
  2. Workflow — a YAML file that defines jobs and steps
  3. Runner — the machine that executes the steps (can be GitHub-hosted or self-hosted)

Here's the mental model in words: the push event fires after you run git push. GitHub sees it, matches it against workflow files in the repository, and for each matching workflow it spawns a virtual machine (the runner). That runner clones your code, runs the commands you specify, and reports the results back to the GitHub UI.

Pro tip: You can think of the workflow file as a recipe. The event is the occasion, the jobs are the dishes, and the steps are the instructions. You can have multiple recipes (workflows) for the same occasion, but each one runs independently.

The key insight: the push event is the when; the workflow is the what. You can attach any number of workflows to the same event, and you can filter events by branch, tags, or paths.

Here's a minimal YAML mental model to keep in your head:

on: push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      # do something

That's it — three key parts. The rest is details (and you'll add many of them soon).

How it works step by step

Step 1: Create the workflow file

GitHub Actions looks for YAML files in the .github/workflows/ directory. The filename doesn't matter, but it's conventional to name it after the purpose, e.g., build.yml.

Step 2: Define the trigger

The on: key is the event definition. The simplest form is on: push, which triggers the workflow on every push to any branch. But you can refine it:

on:
  push:
    branches:
      - main

This limits the trigger to pushes on main only — a common pattern for production builds.

Step 3: Define jobs

A workflow can contain multiple jobs. Each job runs on its own runner and can depend on other jobs (we'll cover dependencies in a later lesson). For now, keep it simple with a single build job.

Step 4: Add steps

Inside a job, you define an ordered list of steps. Each step either runs a shell command or uses an action (a reusable piece of code). The first step is almost always actions/checkout, which clones your repository onto the runner.

Step 5: Commit and push

When you push the workflow file to your repository, GitHub picks it up and executes it. Any subsequent push to the target branch re-triggers the workflow.

The cause-and-effect chain is: git push → GitHub receives it → event fires → workflow matches → runner starts → jobs execute → status reported.

Pro tip: You can also trigger workflows manually with workflow_dispatch, but that defeats the purpose of automation. Use push as your default unless you have a specific reason not to.

Hands-on walkthrough

Prerequisites

  • A GitHub repository (public or private)
  • Git installed locally
  • Basic command-line comfort

We'll use a small Python project as our example, but the pattern works for any language.

Step 1: Create a minimal workflow

Create a directory .github/workflows/ in your repo and add a file named build.yml with the following content:

name: Build

on: push

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install pytest
      - name: Run tests
        run: pytest

This workflow does four things:

  1. Checks out your code
  2. Sets up Python 3.11
  3. Installs pytest
  4. Runs the tests

If your project doesn't have tests yet, you can create a simple test file to see the workflow in action.

Step 2: Add a sample test

Create test_sample.py in the root of your repo:

def test_always_passes():
    assert True

def test_addition():
    assert 1 + 1 == 2

Now your repo should look like:

.
├── .github
│   └── workflows
│       └── build.yml
└── test_sample.py

Step 3: Push and watch it run

git add .
git commit -m "Add CI workflow"
git push origin main

Navigate to the Actions tab in your GitHub repository. You should see a workflow run with the name "Build." Click on it to watch the live logs.

Expected output: - The build job shows a green checkmark - The log for each step shows success - The Run tests step shows output like 2 passed in 0.02s

If you see a red ✗, don't panic — head to the Troubleshooting section below.

Step 4: Trigger it again

Make a small change (e.g., edit test_sample.py), commit, and push. Notice that the workflow runs automatically — no manual clicks. That's the magic of push events.

Compare options / when to choose what

Not all CI triggers are created equal. Here's how push stacks up against other common triggers:

Trigger Best for Drawbacks
push Getting fast feedback on any code change Can run on every commit, which may be wasteful
pull_request Checking code before merge Doesn't run until a PR is opened
workflow_dispatch Manual retries / ad-hoc runs Requires human action
schedule (cron) Nightly builds, dependency checks Not immediate
push + branch filter Protecting main from bad code Misses features branches

In practice, you'll often combine triggers to get the best coverage.

Pro tip: Use push for your main branch and pull_request for feature branches. That way you get fast feedback on PRs without cluttering the main branch's build history.

Another dimension to compare: where do you run the job? GitHub-hosted runners are simple and free for public repos, but they have limits. Self-hosted runners give you more control (custom hardware, caching) but require maintenance.

Variations of the push event

You can filter by branches, tags, and paths to fine-tune when your build runs. For example:

on:
  push:
    paths:
      - 'src/**'
      - '!docs/**'

This runs the workflow only when files under src/ change, and ignores documentation-only pushes.

Troubleshooting & edge cases

Error: Workflow not appearing / not running

Symptom: You push the workflow file, but the Actions tab shows nothing.

Cause: The file might be in the wrong location or have an invalid YAML syntax.

Fix:

  • Ensure the file is exactly at .github/workflows/build.yml (not .github/build.yml)
  • Check for trailing spaces or tabs in YAML
  • Use a YAML linter locally

Error: No such file or directory when running pytest

Symptom: The step fails with pytest: command not found.

Cause: The Python environment isn't set up correctly, or the runner uses a different Python version.

Fix: Make sure you added the actions/setup-python step before the pip install step, and double-check the Python version.

Workflow runs but tests fail unexpectedly

Symptom: The job fails with a test assertion error, but passes locally.

Cause: Different platform or dependency versions.

Fix: Pin your dependency versions in requirements.txt and use the same Python version locally as in CI.

Common mistakes

  • Wrong trigger syntaxon: [push] is valid, but on: { push } is not
  • Forgetting actions/checkout — without it, your CI runner has no code to build
  • Indentation errors in YAML (e.g., mixing tabs and spaces)
  • Running push on every branch when you only meant main — use branch filters
  • Not committing the workflow file — ensure the .github directory isn't in .gitignore

What you learned & what's next

You now understand the foundational trigger of CI: how to run a build job on push events. You learned:

  • The three pillars: event → workflow → runner
  • How to structure a YAML workflow file
  • How to filter pushes by branch, tag, or path
  • How to debug common workflow issues

This is the heartbeat of CI. Without it, there's no automation — and no foundation for the advanced topics ahead.

The next lesson in this track dives into pipeline anatomy, where you'll learn to break your build into multiple jobs and stages — how to run tests, package artifacts, and pass them between steps. That's where these push-triggered builds start to earn their keep.

Pro tip: Bookmark this lesson. You'll come back to the trigger syntax more times than you think — it's the entry point for every workflow you'll ever write.

Practice recap

Create a new GitHub repository, add a simple Python file with a passing test, and write a workflow that runs on push to main. Then push a small change and watch the workflow execute automatically. Commit the workflow file first, then push a code change to see the trigger in action.

Common mistakes

  • Using on: [push] but then wondering why the workflow doesn't run on tag pushes — push includes all pushes, so you might be triggering more often than expected.
  • Forgetting to add actions/checkout as the first step — your runner will have no code to build, and every subsequent step fails with 'No such file or directory'.
  • Indenting YAML with tabs instead of spaces — GitHub Actions will reject the file with a parsing error.
  • Pushing the workflow file and then immediately editing it in the GitHub UI — the push event fires before your edit, so the old version runs.
  • Assuming push fires on pull request merges — it does, but only on the merge commit to the target branch, not on every PR update.

Variations

  1. Use pull_request triggers alongside push to get earlier feedback on feature branches before they hit main.
  2. Try schedule with cron syntax for nightly builds that run even when no one pushes.
  3. Experiment with workflow_dispatch to manually trigger a build on demand — perfect for debugging or ad-hoc retries.

Real-world use cases

  • A developer pushes a commit to a feature branch, and CI automatically runs unit tests and linting, flagging errors within minutes.
  • A team merges a PR into main, triggering a production build that compiles the app and uploads it as an artifact for deployment later.
  • An open-source project uses a push-triggered workflow to build docs site on every commit, ensuring the latest content is always live.

Key takeaways

  • The on: push trigger is the simplest way to run CI automatically on every code push.
  • A workflow file defines the event, the jobs, and the steps that execute on a runner.
  • You control triggers with filters for branches, tags, and paths — use them to avoid wasteful or overly broad builds.
  • Always start your job with actions/checkout to clone your repository onto the runner.
  • Watch the Actions tab in GitHub to see live logs and debug failures step by step.
  • Mastering push triggers lays the foundation for understanding more complex CI components like artifacts and promotions.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.