Skip to content

Configure CI runners for GitHub Actions

This page walks you through the configuration steps required to start using EngFlow CI runners with your GitHub Actions implementation.

Process overview

At a high-level, you'll need to complete the following steps to run your Bazel builds using EngFlow CI runners:

  1. Create and register a GitHub app
  2. Contact EngFlow to enable CI runners in your cluster
  3. Add a webhook in GitHub
  4. Build a CI container
  5. Define a Bento
  6. Update the labels in your workflow file to reference your Bento

Step 1: Create and register a GitHub app

Organization owner or admin role required

To configure CI runners for GitHub Actions, you'll need to be an organization admin or organization owner.

  1. Create a GitHub app with the following permissions:

    • Organization-level permissions:
      • Administration: Read, write
      • Self-hosted runners: Read, write
    • Repository-level permissions:
      • Administration: Read, write
      • Actions: Read
      • Metadata: Read

    Make a note of the app ID.

  2. Create a private key for the GitHub app.

  3. Convert the private key from the standard PEM format into the PKCS#8 format using the following command:
    Bash
    openssl pkcs8 -topk8 -inform PEM -outform PEM -in GITHUB-PEM-FILE -out /tmp/out.pem -nocrypt
    
  4. Create a .json file containing both the app ID and the private key, using the format:

    JSON
    1
    2
    3
    4
    {
      "github_app_id": "<app_id>",
      "private_key": "<private key with newlines escaped>"
    }
    
    Generate the .json file programmatically

    If you have the moreutils package installed, you can run the following command to generate the .json file:

    Bash
    echo {} | jq --rawfile key /tmp/out.pem '.private_key = \$key | .github_app_id = "APP_ID"' | sponge ${SECRET_JSON}
    
  5. Register the app in your organization

  6. Upload the .json file to the secrets manager running in your EngFlow cluster. Note the address of the secret.

Step 2: Contact EngFlow to enable CI runners in your cluster

Next, contact EngFlow support to enable the CI runners feature in your cluster. You'll receive confirmation once we've completed your request. Make sure to provide the address of the secrets stored in your cluster's secrets manager.

To verify that your cluster is set up to use CI runners:

  1. Log in to your EngFlow cluster's Build and Test UI.
  2. Confirm that the Bento button is displayed in the left sidebar.

Bento page

You're now ready to continue setting up CI runners.

Step 3: Add a webhook in GitHub

Prerequisite: Payload URL

Before you begin, make sure your EngFlow contact has provided you with the confidential UUID that's part of the payload URL required to add the webhook.

To add the webhook:

  1. From your organization's GitHub page, go to Settings Webhooks Add webhook.
  2. In the Add webhook dialog, fill out the fields with the following information:
    • Payload URL: https://<name>.cluster.engflow.com/webhooks/github/runners/<uuid> (UUID value is provided by EngFlow).
    • Content type: application/json
    • Secret: none (we use a secret embedded in the webhook URL)
    • Select Let me select individual events and make sure that the only selected event type is Workflow Jobs.

Step 4: Build a CI container

The CI agent runs inside a container on your EngFlow cluster, just like regular Remote Execution actions. The CI agent executes the workflow (as defined in a YAML file) in this container.

Since the workflow steps typically include running commands like git clone and bazel test //..., the container running the job must have all the tools installed that are needed on the CI host, such as ca-certificates, git, bazel, local toolchains, etc. The CI agent itself does NOT have to be installed; our system injects the latest agent into the container.

Here's an example Dockerfile for such a CI container:

Dockerfile
FROM debian:latest

RUN apt-get update --yes && \
  apt-get install ca-certificates git curl python3 --yes && \
  curl -LSsf \
    -o /usr/local/bin/bazelisk \
    https://github.com/bazelbuild/bazelisk/releases/download/v1.26.0/bazelisk-linux-amd64 && \
  chmod +x /usr/local/bin/bazelisk && \
  ln -sf bazelisk /usr/local/bin/bazel && \
  addgroup -gid 114 engflow && \
  adduser --quiet --uid 108 --gid 114 \
    --system --gecos "engflow daemon" \
    --home /var/lib/engflow --shell /bin/false \
    --disabled-login --disabled-password engflow

USER engflow

Step 5: Define a Bento

Build and Test UI access permissions

If your cluster uses the --http_auth=none option, then you cannot perform the following steps in the Build and Test UI. Contact EngFlow to help you with defining Bentos.

You can create, list, update, and delete Bentos from your EngFlow cluster's Build and Test UI.

To create a new Bento:

  1. Navigate to the Bentos list view from the sidebar in your EngFlow cluster's Build and Test UI.
  2. Click New Bento.

    New Bento

  3. In the Create Bento dialog, fill out all required fields:

    • Bento name: The name by which you'll reference this Bento in your workflow .yml file, e.g. dev_x64. You'll then reference it as engflow-bento-name=dev_x64.
    • Repo name: The URL of the repository where CI jobs will come from, e.g. github.com/MyCompany/myproject.
    • CI provider: Choose GitHub as your CI provider.
    • Image URL: The Docker image the CI host will use. The GitHub Actions runner (and git, and Bazel) will run inside of this. The image URL must include the sha256 sum of the image, e.g. my.registry/x64/ci_dev@sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef.

      • All tools required for the CI host to execute the job (e.g. git, bazel, etc) must be installed into this image, except for the runner, which will be automatically staged inside this image.
      • The image should have a default user, and the user should have a home directory set so that $HOME resolves.
      • Workers in the selected pool (specified using the Pool name attribute) must be granted permission to pull this image.

      Hosting location

      You most likely already have some execution images that EngFlow workers use for normal RE builds. Hosting the CI images in the same registry will make sure the workers can pull them.

    • Pool name: The cluster pool where CI hosts will run. EngFlow will set up this pool for you as part of enabling CI runners on your cluster.

    • Allow snapshots: If selected (recommended), then we take a snapshot of the container (under some circumstances) and reuse it for later CI jobs. We recommend enabling this option, otherwise your CI jobs will not benefit from the time savings from using warm Bazel.
    • Branch name: The name of the branch where snapshots can be taken from. CI jobs from other branches in the repo can also be executed, but the system won't take snapshots from such branches. We recommend setting this field to master or main branch so that snapshots are only captured for post-submit jobs, i.e. commits merged to master or main.

Step 6: Update the labels in your workflow file

Once you define the Bentos for your project, update your GithUb workflow file(s) to reference them. These labels ensure that CI jobs are assigned to EngFlow workers running warm Bazel.

Here's an excerpt from a sample pipeline.yml file:

pipeline.yml
jobs:
  build:
    runs-on:
    - self-hosted
    - "os=linux"
    - "arch=arm64"
    - "engflow-cluster=local"
    - "engflow-bento-allow-save=true"
    - "engflow-bento-name=dev_x64"
    - "engflow-runner-id=${{ github.repository_id }}_presubmit-checks_${{ github.run_id }}_${{ github.run_number }}_${{ github.run_attempt }}"
    - "engflow-container-image=docker://<docker URL>"

    # TODO: do we need "engflow-pool", "engflow-runtime"?