TrylleDocs
CI

Workflow Examples

Compatible Trylle CI examples for filters, matrices, dependencies, reusable workflows, manual runs, caches, and artifacts.

These examples use the workflow surface currently supported by Trylle CI. Store each top-level workflow in .github/workflows or .trylle/workflows, according to the repository's Actions policy.

Push and pull request filters

name: Validate changes

on:
  push:
    branches:
      - main
      - "release/**"
    paths:
      - "src/**"
      - "package-lock.json"
      - "!src/generated/**"
  pull_request:
    types: [opened, reopened, synchronize]
    branches: [main]
    paths-ignore:
      - "docs/**"

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm test

Patterns are evaluated in order, so a later ! entry can remove a path included by an earlier entry. Pull request branch filters apply to the base branch.

Static matrix

name: Test matrix

on:
  push:
  pull_request:

jobs:
  test:
    strategy:
      fail-fast: false
      max-parallel: 3
      matrix:
        runner: [ubuntu-latest, ubuntu-latest-arm]
        node: [20, 22]
        exclude:
          - runner: ubuntu-latest-arm
            node: 20
        include:
          - runner: ubuntu-latest
            node: 24
            experimental: true
    continue-on-error: ${{ matrix.experimental == true }}
    runs-on: ${{ matrix.runner }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
      - run: npm ci
      - run: npm test
      - uses: actions/upload-artifact@v4
        with:
          name: results-${{ matrix.runner }}-node-${{ matrix.node }}
          path: test-results/
          if-no-files-found: ignore

Keep matrices static. A matrix such as ${{ fromJSON(needs.plan.outputs.matrix) }} is not currently expanded.

Dependencies and job outputs

name: Build and publish metadata

on:
  push:
    branches: [main]

jobs:
  version:
    runs-on: ubuntu-latest
    outputs:
      value: ${{ steps.version.outputs.value }}
    steps:
      - id: version
        run: echo "value=1.0.${GITHUB_RUN_NUMBER}" >> "$GITHUB_OUTPUT"

  build:
    needs: version
    runs-on: ubuntu-latest
    env:
      RELEASE_VERSION: ${{ needs.version.outputs.value }}
    steps:
      - uses: actions/checkout@v4
      - run: ./scripts/build.sh "$RELEASE_VERSION"

  report:
    if: ${{ always() }}
    needs: [version, build]
    runs-on: ubuntu-latest
    steps:
      - run: echo "Build result was ${{ needs.build.result }}"

Trylle runs independent jobs in the same dependency wave and starts a later wave after its needs requirements resolve.

Local reusable workflow

Caller, for example .github/workflows/ci.yml:

name: CI

on:
  push:
  pull_request:

jobs:
  test:
    uses: ./.github/workflows/reusable-test.yml
    with:
      node-version: "22"

Called workflow, .github/workflows/reusable-test.yml:

name: Reusable test

on:
  workflow_call:
    inputs:
      node-version:
        required: true
        type: string

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node-version }}
      - run: npm ci
      - run: npm test

Local calls may target either workflow root. Remote calls use owner/repository/.github/workflows/file.yml@ref. Reusable workflows can nest up to four levels.

Manual workflow with inputs

name: Release candidate

on:
  workflow_dispatch:
    inputs:
      channel:
        description: Release channel
        required: true
        type: choice
        options: [preview, stable]
        default: preview
      publish:
        description: Publish artifacts
        type: boolean
        default: false
      retries:
        description: Retry count
        type: number
        default: 1
      note:
        description: Release note
        type: string
        required: false

jobs:
  release:
    runs-on: ubuntu-latest
    env:
      CHANNEL: ${{ inputs.channel }}
      PUBLISH: ${{ inputs.publish }}
      RETRIES: ${{ inputs.retries }}
      NOTE: ${{ inputs.note }}
    steps:
      - uses: actions/checkout@v4
      - run: ./scripts/release-candidate.sh

Open the repository's Actions page, select Run workflow, choose a branch or tag, select this workflow, complete the inputs, and run it. Manual dispatch requires repository write access.

Cache and pass artifacts between jobs

name: Cached build

on:
  push:
  pull_request:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/cache@v4
        with:
          path: ~/.npm
          key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
          restore-keys: |
            npm-${{ runner.os }}-
      - run: npm ci
      - run: npm run build
      - uses: actions/upload-artifact@v4
        with:
          name: web-dist
          path: dist/
          if-no-files-found: error

  inspect:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: web-dist
          path: downloaded-dist
      - run: find downloaded-dist -type f -maxdepth 2 -print

Uploaded artifacts appear on the workflow run page and can be downloaded after the job completes.

Run a job inside Docker

Job-level container: is not supported. Use Docker from a Linux step instead:

name: Container test

on:
  push:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: >-
          docker run --rm
          -v "$PWD:/workspace"
          -w /workspace
          node:22
          npm test

On this page