CI workflow (basecamp/trix)
The CI workflow from basecamp/trix, explained and optimized by Latchkey.
CI health: A - excellent
Point runs-on at Latchkey and get job timeouts, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the CI workflow from the basecamp/trix repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
name: CI
concurrency:
group: "${{github.workflow}}-${{github.ref}}"
cancel-in-progress: true
on:
workflow_dispatch:
push:
branches: [ main ]
pull_request:
types: [opened, synchronize]
branches: [ '*' ]
permissions: {}
env:
SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
SAUCE_REGION: us
SAUCE_TUNNEL_IDENTIFIER: trix-${{ github.run_id }}
jobs:
lint-actions:
name: GitHub Actions audit
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Run actionlint
uses: rhysd/actionlint@914e7df21a07ef503a81201c76d2b11c789d3fca # v1.7.12
- name: Run zizmor
uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3
with:
advanced-security: false
build:
name: Browser tests
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 18
cache: "yarn"
- name: Install Dependencies
run: yarn install --frozen-lockfile
- name: Start Sauce Connect
if: ${{ env.SAUCE_ACCESS_KEY != '' }}
uses: saucelabs/sauce-connect-action@cb88b508c6f9ff4d84490093733315dbd55de022 # v3
with:
username: ${{ env.SAUCE_USERNAME }}
accessKey: ${{ env.SAUCE_ACCESS_KEY }}
tunnelName: ${{ env.SAUCE_TUNNEL_IDENTIFIER }}
region: ${{ env.SAUCE_REGION }}
proxyLocalhost: allow
- name: Install Playwright Browsers
if: ${{ env.SAUCE_ACCESS_KEY == '' }}
run: npx playwright install --with-deps chromium
- run: bin/ci
- name: Fail when generated npm changes are not checked-in
run: |
git update-index --refresh && git diff-index --quiet HEAD --
rails-tests:
name: Downstream Rails integration tests
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 18
cache: "yarn"
- uses: ruby/setup-ruby-pkgs@2233d39c1315c667a2970436418b520a6300124e # v1.33.5
with:
ruby-version: "3.4"
apt-get: libvips-tools
- name: Install Dependencies
run: yarn install --frozen-lockfile
- name: Packaging
run: yarn build
- name: Clone Rails
run: git clone --depth=1 https://github.com/rails/rails
- name: Configure Rails
run: |
cd rails
yarn install --frozen-lockfile
bundle add action_text-trix --path ".."
bundle show --paths action_text-trix
- name: Action Text tests
env:
RACK_ENV: test # see https://github.com/rails/rails/issues/56563
run: |
cd rails/actiontext
bundle exec rake test test:system
action_text-trix:
name: Action Text tests
runs-on: ubuntu-latest
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include:
- ruby: "3.2"
rails_branch: 7-2-stable
- ruby: "3.3"
rails_branch: 7-2-stable
- ruby: "3.4"
rails_branch: 7-2-stable
- ruby: "3.2"
rails_branch: 8-0-stable
- ruby: "3.3"
rails_branch: 8-0-stable
- ruby: "3.4"
rails_branch: 8-0-stable
- ruby: "3.2"
rails_branch: 8-1-stable
- ruby: "3.3"
rails_branch: 8-1-stable
- ruby: "3.4"
rails_branch: 8-1-stable
- ruby: "4.0"
rails_branch: 8-1-stable
- ruby: "3.3"
rails_branch: main
experimental: true
- ruby: "3.4"
rails_branch: main
experimental: true
- ruby: "4.0"
rails_branch: main
experimental: true
- ruby: head
rails_branch: main
experimental: true
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 18
cache: "yarn"
- uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
env:
RAILS_BRANCH: ${{ matrix.rails_branch }}
with:
working-directory: "./action_text-trix"
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Run tests
env:
RAILS_BRANCH: ${{ matrix.rails_branch }}
continue-on-error: ${{ matrix.experimental || false }}
working-directory: "./action_text-trix"
run: bin/rails test:all
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: CI concurrency: group: "${{github.workflow}}-${{github.ref}}" cancel-in-progress: true on: workflow_dispatch: push: branches: [ main ] pull_request: types: [opened, synchronize] branches: [ '*' ] permissions: {} env: SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }} SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} SAUCE_REGION: us SAUCE_TUNNEL_IDENTIFIER: trix-${{ github.run_id }} jobs: lint-actions: timeout-minutes: 30 name: GitHub Actions audit runs-on: latchkey-small permissions: contents: read steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Run actionlint uses: rhysd/actionlint@914e7df21a07ef503a81201c76d2b11c789d3fca # v1.7.12 - name: Run zizmor uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3 with: advanced-security: false build: timeout-minutes: 30 name: Browser tests runs-on: latchkey-small permissions: contents: read steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: 18 cache: "yarn" - name: Install Dependencies run: yarn install --frozen-lockfile - name: Start Sauce Connect if: ${{ env.SAUCE_ACCESS_KEY != '' }} uses: saucelabs/sauce-connect-action@cb88b508c6f9ff4d84490093733315dbd55de022 # v3 with: username: ${{ env.SAUCE_USERNAME }} accessKey: ${{ env.SAUCE_ACCESS_KEY }} tunnelName: ${{ env.SAUCE_TUNNEL_IDENTIFIER }} region: ${{ env.SAUCE_REGION }} proxyLocalhost: allow - name: Install Playwright Browsers if: ${{ env.SAUCE_ACCESS_KEY == '' }} run: npx playwright install --with-deps chromium - run: bin/ci - name: Fail when generated npm changes are not checked-in run: | git update-index --refresh && git diff-index --quiet HEAD -- rails-tests: timeout-minutes: 30 name: Downstream Rails integration tests runs-on: latchkey-small permissions: contents: read steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: 18 cache: "yarn" - uses: ruby/setup-ruby-pkgs@2233d39c1315c667a2970436418b520a6300124e # v1.33.5 with: ruby-version: "3.4" apt-get: libvips-tools - name: Install Dependencies run: yarn install --frozen-lockfile - name: Packaging run: yarn build - name: Clone Rails run: git clone --depth=1 https://github.com/rails/rails - name: Configure Rails run: | cd rails yarn install --frozen-lockfile bundle add action_text-trix --path ".." bundle show --paths action_text-trix - name: Action Text tests env: RACK_ENV: test # see https://github.com/rails/rails/issues/56563 run: | cd rails/actiontext bundle exec rake test test:system action_text-trix: timeout-minutes: 30 name: Action Text tests runs-on: latchkey-small permissions: contents: read strategy: fail-fast: false matrix: include: - ruby: "3.2" rails_branch: 7-2-stable - ruby: "3.3" rails_branch: 7-2-stable - ruby: "3.4" rails_branch: 7-2-stable - ruby: "3.2" rails_branch: 8-0-stable - ruby: "3.3" rails_branch: 8-0-stable - ruby: "3.4" rails_branch: 8-0-stable - ruby: "3.2" rails_branch: 8-1-stable - ruby: "3.3" rails_branch: 8-1-stable - ruby: "3.4" rails_branch: 8-1-stable - ruby: "4.0" rails_branch: 8-1-stable - ruby: "3.3" rails_branch: main experimental: true - ruby: "3.4" rails_branch: main experimental: true - ruby: "4.0" rails_branch: main experimental: true - ruby: head rails_branch: main experimental: true steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: 18 cache: "yarn" - uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0 env: RAILS_BRANCH: ${{ matrix.rails_branch }} with: working-directory: "./action_text-trix" ruby-version: ${{ matrix.ruby }} bundler-cache: true - name: Run tests env: RAILS_BRANCH: ${{ matrix.rails_branch }} continue-on-error: ${{ matrix.experimental || false }} working-directory: "./action_text-trix" run: bin/rails test:all
What changed
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Add a job timeout so a hung step cannot burn hours of runner time.
What Latchkey heals here
This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:
- Dependency installs
- End-to-end and browser tests
This workflow runs 4 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.