GitHub Actions - Public Preview

The Oxide GitHub Actions runner scale set controller provides elastic, self-hosted GitHub Actions runner capacity on Oxide. It runs workflow jobs on ephemeral Oxide instances using a custom image you control without needing to maintain a fleet of static long-lived runners.

The controller creates and manages a GitHub Actions runner scale set and adjusts its capacity in response to demand. It provisions instances with just-in-time runner configurations and removes each instance and boot disk after its runner exits. You can also keep a configurable pool of idle runners to reduce job start latency.

This guide describes how to use the Oxide GitHub Actions runner scale set controller to run CI/CD workflow jobs on Oxide.

Requirements

To follow this guide, you need the following.

  • API credentials for your Oxide silo. Refer to Authentication for instructions on generating API credentials.

  • A project within your Oxide silo with a configured VPC and subnet. The controller will provision Oxide instances in this project, VPC, and subnet.

  • An Oxide image in your project prepared as an ephemeral, single-job GitHub Actions runner image. The controller source code includes a reference Packer configuration to build and upload a compatible image.

  • A GitHub repository for the controller to register a scale set and run a workflow job.

Generate GitHub credentials

The controller authenticates to GitHub using a personal access token (PAT) to simplify following this guide. In production, you’d configure the controller to authenticate using a GitHub App instead.

  1. Navigate to https://github.com/settings/personal-access-tokens.

  2. Click Generate new token.

  3. Set the following:

    1. Token name: oxide-gha-runner

  4. Under Repository access, select All repositories.

  5. Under Permissions, click RepositoriesAdd permissions and set:

    1. Administration: Read and write

  6. Click Generate token.

  7. Save the PAT to a secure location.

Start the controller

  1. Download the latest release of the controller from GitHub.

  2. Create config.yaml with the following content.

    PlaceholderValue

    ${GITHUB_ORG}

    GitHub organization to register the runner scale set.

    ${GITHUB_REPO}

    GitHub repository to register the runner scale set.

    ${GITHUB_TOKEN}

    GitHub personal access token (PAT).

    ${OXIDE_HOST}

    Oxide silo host.

    ${OXIDE_TOKEN}

    Oxide API token.

    ${OXIDE_PROJECT}

    Oxide project to create the runners in.

    ${OXIDE_IMAGE}

    Image to use for the runners.

    ${OXIDE_VPC}

    VPC to create the runners in.

    ${OXIDE_SUBNET}

    Subnet to create the runners in.

    config.yaml
    ---
    log:
    level: info
    format: json

    github:
    config_url: https://github.com/${GITHUB_ORG}/${GITHUB_REPO}
    auth:
    pat:
    token: ${GITHUB_TOKEN}

    oxide:
    host: ${OXIDE_HOST}
    token: ${OXIDE_TOKEN}

    scale_set:
    name: oxide-gha-runner
    runner_group: default

    labels:
    - oxide-gha-runner

    min_runners: 1
    max_runners: 1

    instance:
    project: ${OXIDE_PROJECT}
    image: ${OXIDE_IMAGE}
    cpus: 2
    memory_gib: 8
    vpc: ${OXIDE_VPC}
    subnet: ${OXIDE_SUBNET}
  3. Start the controller. Keep the terminal open to view its logs.

    oxide-gha-runner-scale-set-controller --config config.yaml
  4. Navigate to your Oxide project. In a few moments you’ll see an instance created with a name starting with gha-runner-.

  5. Navigate to https://github.com/${GITHUB_ORG}/${GITHUB_REPO}/settings/actions/runners. In a few moments you’ll see a runner with a name matching the created Oxide instance. The runner will show Idle when it’s ready and waiting for a workflow job.

Run a workflow job

  1. In your GitHub repository, create a workflow file .github/workflows/oxide-gha-runner.yaml.

    .github/workflows/oxide-gha-runner.yaml
    ---
    name: Oxide GitHub Actions
    on: workflow_dispatch

    jobs:
    oxide:
    # Matches the scale_set.labels configuration.
    runs-on: oxide-gha-runner
    steps:
    - run: |
    echo "Hello from Oxide!"
  2. Go to your repository on GitHub, navigate to Actions, select the Oxide GitHub Actions workflow, and click Run workflow.

  3. Navigate back to the terminal running the controller. You’ll see its logs show it tearing down the instance once the workflow job completes.

Clean up

Let’s remove the resources we created in this guide.

Drain the controller

  1. Stop the controller using Ctrl+C.

  2. Open config.yaml and set:

    1. scale_set.min_runners0

    2. scale_set.max_runners0

  3. Start the controller.

    oxide-gha-runner-scale-set-controller --config config.yaml
  4. The controller will print a log showing it started draining. It will delete the runners and exit successfully when finished.

Note
You may have to wait a few minutes for the drain to complete on newly registered runners.

Remove the workflow file

In your GitHub repository, remove the workflow file .github/workflows/oxide-gha-runner.yaml.

Delete GitHub credentials

  1. Navigate to https://github.com/settings/personal-access-tokens.

  2. Delete the personal access token that was generated earlier.