Skip to content
Commitpedia
Log in Join & edit

A minimal GitHub Actions workflow that runs your tests

Add one YAML file under .github/workflows and GitHub runs your tests on every push and pull request. Here is a small, explained example for Node.js and one for Python.

Drafted with AI from official documentation. Scripts were run in a test environment and repository links verified. Awaiting a human check. Did it work for you? Last edited Outdated?

Edit history of A minimal GitHub Actions workflow that runs your tests: 1 recorded edit
Edit history · 1 edit
Type
Article
Edits
1
Editors
1
First issued
15 Oct 2026
Last edit
15 Oct 2026
Reading
2 min

GitHub Actions runs jobs on GitHub’s machines when something happens in your repository. The most useful first job is continuous integration (CI): run the test suite on every push and every pull request, so a broken change shows a red mark before anyone merges it.

Create the workflow file

Workflows live in .github/workflows/ and can have any name ending in .yml. Create .github/workflows/ci.yml:

name: CI

on:
  push:
    branches: [main]
  pull_request:

permissions:
  contents: read

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [22, 24]
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: ${{ matrix.node-version }}
          cache: npm
      - run: npm ci
      - run: npm test

Commit and push it. The run appears under the repository’s Actions tab, and on pull requests as a check next to the merge button.

What each part does

  • on: run on pushes to main and on every pull request.
  • permissions: contents: read: the job’s automatic token can read the code and nothing more. Granting only what a job needs limits the damage if a step misbehaves.
  • concurrency: if you push again while a run for the same branch is still going, the old run is cancelled.
  • runs-on: ubuntu-latest: a fresh Linux virtual machine for each run.
  • strategy.matrix: runs the job once per listed Node.js version, in parallel.
  • actions/checkout: copies your repository onto the machine. Without it the job has no code.
  • actions/setup-node: installs Node.js; cache: npm reuses downloaded packages between runs.
  • npm ci installs exactly what package-lock.json lists (the lock file must be committed), and npm test runs the test script from package.json. A non-zero exit code fails the job.

The same idea for Python

name: CI

on:
  push:
    branches: [main]
  pull_request:

permissions:
  contents: read

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-python@v7
        with:
          python-version: "3.13"
          cache: pip
      - run: pip install -r requirements.txt
      - run: python -m pytest

Quote version numbers such as "3.13". YAML reads an unquoted 3.10 as the number 3.1, which selects the wrong Python.

Version tags for actions

@v7 pins the action to a major version, which receives fixes but no breaking changes. Each action’s README lists its current major version; update the tag when a new one comes out. For extra safety, some teams pin to a full commit hash instead.

Make the check required

A red check alone does not stop anyone from merging. In the repository settings, add a branch ruleset (or a branch protection rule) for main that requires status checks to pass, and pick the test job. When you use a matrix, each version shows up as its own check.

When a run fails

  • Open the failed run and expand the red step; the log shows the same output you would see locally.
  • “Works on my machine” failures are often a missing committed file, such as a lock file, or a different runtime version. Match the matrix to what you use locally.
  • Use the Re-run jobs button for flaky network failures, but fix flaky tests rather than re-running them forever.

Start with this file, then add steps such as a linter or a build once the tests run green.

Did this work for you?

No votes yet. Be the first.

If it did not work, the report form below tells the editors what went wrong.

See also

Repos in the wild

History

Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.

  1. Dominik +3,469 chars

Report a problem

Something wrong, unsafe or copied? Tell the editors.
What is wrong?