Set up GitHub Actions for a Pigweed project#

This tutorial shows you how to set up GitHub Actions to build and test your Bazel-based Pigweed project. You’ll learn how to set up both presubmit and postsubmit Actions.

Examples#

Pigweed’s Bazel quickstart repo demonstrates GitHub Actions integration:

Enable Actions#

Make sure that Actions are enabled for your repo. See Managing GitHub Actions settings for a repository.

Create a .bazelversion file for your repo#

Make sure that .bazelversion exists in your repo. This file specifies what version of Bazel the Actions should use.

Create a presubmit Action#

A presubmit Action runs when a pull request is sent. Creating a presubmit Action that makes sure pull requests build and pass tests involves four steps:

  1. Checking out your repo’s code.

  2. Installing Bazel.

  3. Building your code.

  4. Testing your code.

The first two steps are handled by community-managed extensions. The last two steps require just a few lines of code.

  1. From the root of your repository, create .github/workflows/presubmit.yaml. The path to the file must be .github/workflows but you can name the file whatever you want.

  2. Put the following YAML into the file:

    name: presubmit
    run-name: presubmit run triggered by ${{ github.actor }}
    
    on:
      pull_request:
        types: [opened, synchronize, reopened]
    
    jobs:
      bazel-build-test:
        runs-on: ubuntu-latest
        steps:
          - name: Checkout
            # Check out this repo's code.
            # https://github.com/actions/checkout
            uses: actions/checkout@v4
            with:
              fetch-depth: 0
              submodules: recursive
          - name: Get Bazel
            # Install Bazel.
            # https://github.com/bazel-contrib/setup-bazel
            uses: bazel-contrib/setup-bazel@0.8.1
            with:
              # Avoid downloading Bazel every time.
              bazelisk-cache: true
              # Store build cache per workflow.
              disk-cache: ${{ github.workflow }}
              # Share repository cache between workflows.
              repository-cache: true
          - name: Bazel Build
            # Always use bazelisk rather than bazel to
            # guarantee that the correct version of Bazel
            # (sourced from .bazelversion) is used.
            run: bazelisk build ...
          - name: Bazel Test
            run: bazelisk test ...
    
  3. Commit the file.

The Action runs whenever a pull request is opened, updated, or reopened.

Note

In general, Pigweed recommends always launching Bazel through the bazelisk command rather than the bazel command. Bazelisk guarantees that you’re always running the correct version of Bazel for your project, as defined in your project’s .bazelversion file. It would technically be OK to use the bazel command in your GitHub Actions code because the bazel-contrib/setup-bazel extension also makes sure to launch the correct version of Bazel based on what’s defined in .bazelversion, but in practice Pigweed finds it safer to just use bazelisk everywhere.

Create a postsubmit Action#

A postsubmit Action runs after a pull request has been merged. The process for creating a postsubmit Action that builds and tests your code when a new commit is pushed is almost identical to the presubmit Action setup. The only thing that changes is the on field in the YAML:

name: postsubmit
run-name: postsubmit run

on:
  push

jobs:
  bazel-build-test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        # Check out this repo's code.
        # https://github.com/actions/checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          submodules: recursive
      - name: Get Bazel
        # Install Bazel.
        # https://github.com/bazel-contrib/setup-bazel
        uses: bazel-contrib/setup-bazel@0.8.1
        with:
          # Avoid downloading Bazel every time.
          bazelisk-cache: true
          # Store build cache per workflow.
          disk-cache: ${{ github.workflow }}
          # Share repository cache between workflows.
          repository-cache: true
      - name: Bazel Build
        # Always use bazelisk rather than bazel to
        # guarantee that the correct version of Bazel
        # (sourced from .bazelversion) is used.
        run: bazelisk build ...
      - name: Bazel Test
        run: bazelisk test ...

Create a linter Action that uses pw_presubmit and pw_env_setup#

The following code demonstrates a presubmit linter Action that uses pw_env_setup and pw_presubmit.

name: lintformat

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  bazel-build-test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          submodules: recursive
      - name: Bootstrap
        # When run locally, bootstrap.sh has checks to ensure that
        # it's sourced (source bootstrap.sh) rather than executed
        # directly. run.sh gets around this.
        run: pw_env_setup/run.sh bootstrap.sh
      - name: lintformat
        run: pw presubmit --program lintformat --keep-going

When pw_env_setup is run within a GitHub Action, it recognizes this from the environment and writes the environment variables in a way that is understood by GitHub, and GitHub makes those variables available to subsequent steps.

Create more Actions#

You can create as many Actions as you want! Just add new files to //.github/workflows and tweak the options as needed. Check out the official GitHub Actions docs to learn more.

Support#

Please start a discussion in Pigweed’s Discord.