How to run workshops in GitHub Actions

The launch-workshop action installs Workshop on a GitHub-hosted runner and launches an ephemeral workshop for the duration of a job. Use it to run your project’s tests, builds, or other tasks inside the same workshop you use locally, without standing up a self-hosted runner.

If you’d rather run jobs on your own hardware, use a workshop as a self-hosted runner instead; see How to run GitHub Actions locally.

Prerequisites

Before getting started, ensure you have:

  • A GitHub repository with Actions enabled

  • A workshop definition committed to the repository, at workshop.yaml or .workshop/<NAME>.yaml

  • A personal access token with Contents: read and Metadata: read permissions on canonical/workshop

Configure the workshop token

The action installs Workshop from canonical/workshop, which is an internal repository. The token granting read access to that repository must be stored as an Actions secret in your project repository.

In your project repository on GitHub, navigate to Settings > Secrets and variables > Actions, select New repository secret, and add the token under the name WORKSHOP_TOKEN.

The action reads this secret via the token input.

Add the action to a workflow

The smallest useful workflow checks out the repository, launches the default workshop, and runs a command inside it:

.github/workflows/test.yaml
on:
  pull_request:
  push:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - uses: canonical/launch-workshop@v0
        with:
          token: ${{ secrets.WORKSHOP_TOKEN }}

      - run: workshop exec -- pytest

If the repository contains a single workshop.yaml at the project root, the action launches it automatically. For repositories with several workshops under .workshop/, set the workshop input to the one you need.

For production use, pin the action to a specific commit SHA. The @v0 shorthand shown above tracks the latest v0.* release and can be moved between versions; @main is even less stable.

Test across multiple workshops

To test a project against several workshops in parallel, parameterize the workshop input with a matrix:

.github/workflows/matrix.yaml
jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        workshop: [dev-jammy, dev-noble]
    steps:
      - uses: actions/checkout@v6

      - uses: canonical/launch-workshop@v0
        with:
          token: ${{ secrets.WORKSHOP_TOKEN }}
          workshop: ${{ matrix.workshop }}

      - run: workshop run "$WS" unit-tests
        env:
          WS: ${{ matrix.workshop }}

This pattern fits well for testing the same project against different Ubuntu releases, different SDK channels, or any other axis you encode in the workshop name.

Cache SDK data across runs

Some SDKs expose mount plugs that can be persisted between workflow runs, such as a package cache or a build cache. List the available plugs in your local workshop with workshop connections:

$ workshop connections --all

  INTERFACE  PLUG              SLOT          NOTES
  mount      python:pip-cache  system:mount  -

Pass the matching <SDK>:<PLUG> lines to the cache input, one per line:

.github/workflows/test.yaml
steps:
  - uses: canonical/launch-workshop@v0
    with:
      token: ${{ secrets.WORKSHOP_TOKEN }}
      cache: |
        cargo:git
        cargo:registry
        go:mod-cache
        python:pip-cache

Each listed plug is mounted from a GitHub-managed cache, keyed by the SDK and plug name. Not every SDK defines cacheable plugs; check the SDK’s documentation when in doubt.

Inputs

The action exposes the following inputs:

Input

Description

token

Access token for canonical/workshop. Required.

version

Workshop version or range of versions. Defaults to latest.

project

Directory containing a workshop to launch. Defaults to the repository root.

workshop

Name of the workshop to launch. Required if the project defines several workshops.

cache

Mount plugs to cache across runs, one <SDK>:<PLUG> entry per line.

Security considerations

When integrating the action into your workflows:

  • Store the token as an Actions secret; never commit it to the repository or paste it into logs.

  • Prefer a fine-grained personal access token scoped to canonical/workshop with only Contents: read and Metadata: read permissions.

  • Pin the action to a commit SHA so a compromised tag cannot push unreviewed code into your workflows.

  • Rotate WORKSHOP_TOKEN immediately if it ever appears in logs, chat history, or any other shared transcript.

See also

How-to guides: