GitHub Actions workflow for Python (pytest)

A continuous integration workflow for a Python project: it installs the dependencies and runs the tests with pytest on several Python versions, with pip caching. This is the exact YAML the application generates.

When to use it

  • Your Python project has a requirements.txt and pytest tests.
  • You want to check that it works on several Python versions at once.
  • You want a safe starting point (minimal permissions, pinned actions) to build on.

The complete workflow

Save it as .github/workflows/python-ci.yml in your repository
name: Python CI
on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main
  workflow_dispatch:
permissions:
  contents: read
jobs:
  test:
    name: Tests (Python ${{ matrix.python-version }})
    runs-on: ubuntu-latest
    timeout-minutes: 15
    strategy:
      matrix:
        python-version:
          - "3.11"
          - "3.12"
          - "3.13"
      fail-fast: false
    steps:
      - name: Check out the code (actions/checkout v7.0.1)
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
      - name: Set up Python (actions/setup-python v7.1.0)
        uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0
        with:
          python-version: ${{ matrix.python-version }}
          cache: pip
      - name: Install dependencies
        run: python -m pip install -r requirements.txt
      - name: Run the tests
        run: python -m pytest -q

It is a starting point: you can open it in the editor, change events, jobs and steps, and the application validates it again before generating the file.

Before you use it

  • Needs a requirements.txt at the root of the repository.
  • Runs `python -m pytest`: add pytest to your dependencies.
  • Change the matrix versions to the ones your project supports.

What each part does

  • EventsThe workflow runs on pushes to main, on pull requests targeting main, and manually from the Actions tab (workflow_dispatch).
  • Version matrixA matrix with three Python versions creates one job per version; with fail-fast disabled, a failure in one does not cancel the others.
  • pip cacheThe action that installs Python stores the pip cache between runs so installs are faster.
  • Permissions and securityMinimal permissions: the token can only read the repository contents (contents: read). Third-party actions are pinned to a specific commit SHA (with the readable version in the step name), not to a movable tag.
  • Maximum timeEvery job has a maximum run time (timeout-minutes) so a hang cannot burn minutes forever.

How to use it in your repository

  1. Save the file in the .github/workflows/ folder of your repository.
  2. Push it (commit and push). GitHub detects the workflow and runs it according to its events.
  3. Check the result in the Actions tab of the repository.

Frequently asked questions

What does my repository need for it to work?

A requirements.txt at the root and pytest among your dependencies. If you use another manager (poetry, uv…), change the install-dependencies step.

How do I change the Python versions?

Edit the matrix list (python-version) to the versions your project supports, either in the YAML or in the editor.

Why do actions have a long SHA instead of v4?

A tag like v4 can be moved to different code without warning; a commit SHA cannot. Pinning it reduces the risk of a compromised action entering your pipeline.

Other templates

  • GitHub Actions workflow for Node.js (lint, tests and build)Installs with npm ci and runs lint, tests and build on several Node versions with npm caching.
  • GitHub Actions workflow to build and publish a Docker image to GHCRBuilds the repository image and publishes it to GitHub Container Registry (ghcr.io) when you push to main or create a v* tag.

Try it for free

The editor is available with a free account, with usage limits. Nothing runs in your repository or your installation: you decide which file to use.

Create a free accountLog in