Skip to content
Latchkey

CI workflow (bitcart/bitcart)

The CI workflow from bitcart/bitcart, explained and optimized by Latchkey.

B

CI health: B - good

Point runs-on at Latchkey and get job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.

Grade your own workflow free or run it on Latchkey →
Source: bitcart/bitcart.github/workflows/ci.ymlLicense MITView source

What it does

This is the CI workflow from the bitcart/bitcart 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

workflow (.yml)
name: CI

on:
  push:
    branches:
      - master
  pull_request:

concurrency:
  group: ${{ github.workflow_ref }}-${{ github.event.pull_request.number || github.run_id }}
  cancel-in-progress: true

permissions:
  contents: read

jobs:
  lint:
    name: lint
    uses: bitcart/bitcart-actions/.github/workflows/lint.yml@master
    with:
      install-dependencies: |
        uv sync --frozen --compile-bytecode --no-dev --group web --group types --group lint --group test
      extra-checks: just ci-lint

  zizmor:
    name: zizmor
    uses: bitcart/bitcart-actions/.github/workflows/zizmor-audit.yml@master
    permissions:
      contents: read
      security-events: write # needed for github advanced security

  test:
    name: test-${{ matrix.python-version }}
    needs: [lint, zizmor]
    runs-on: ubuntu-latest

    strategy:
      matrix:
        python-version: ["3.12", "3.13", "3.14"]

    services:
      redis:
        image: redis:alpine@sha256:d146f83b1e0f02fc27c26a50cee39338c736674c5959db84363e6ae3cd9e02d2
        ports:
          - 6379:6379

      postgres:
        image: postgres:18-alpine@sha256:96d56f7f57c6aacd1fcb908bc83b345ec5f83231ee486dd66a1baadce274db88
        env:
          POSTGRES_DB: bitcart_test
          POSTGRES_HOST_AUTH_METHOD: trust
        ports:
          - 5432:5432

    env:
      TEST_ARGS: "-o junit_family=legacy --junitxml test-results/junit.xml --cov-report html:coverage"

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false

      - name: Set up Python ${{ matrix.python-version }}
        uses: bitcart/bitcart-actions/actions/setup-python@master
        with:
          python-version: ${{ matrix.python-version }}

      - name: Install Python dependencies
        uses: bitcart/bitcart-actions/actions/install-daemon@master
        with:
          install-dependencies: |
            uv sync --frozen --compile-bytecode --no-dev --group web --group otel --group test --group btc

      - name: Prepare daemon
        uses: bitcart/bitcart-actions/actions/run-in-background@master
        with:
          run: BTC_EXPERIMENTAL_NOSYNC=true just testnet
          key: testnet

      - name: Run tests
        run: |
          just test -n 4 --pytest-durations=-1

      - name: Upload coverage to Codecov
        uses: bitcart/bitcart-actions/actions/codecov@master
        if: ${{ !cancelled() }}
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          name: Tests - Python ${{ env.PYTHON }}
          flags: tests
          env_vars: PYTHON
          upload_coverage: ${{ job.status == 'success' }}

      - name: Upload test results
        uses: bitcart/bitcart-actions/actions/upload-test-results@master
        if: ${{ !cancelled() }}
        with:
          suffix: py${{ env.PYTHON }}

  functional-tests:
    name: functional-tests
    uses: bitcart/bitcart-actions/.github/workflows/functional-tests.yml@master
    needs: test
    with:
      install-dependencies: |
        uv sync --frozen --compile-bytecode --no-dev --group web --group otel --group test --group btc
      enable-redis: true
      enable-postgres: true
    secrets:
      CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

  combine-coverage:
    name: combine-coverage
    uses: bitcart/bitcart-actions/.github/workflows/combine-coverage.yml@master
    needs: [test, functional-tests]
    if: ${{ !cancelled() }}

The same workflow, on Latchkey

Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.

name: CI
 
on:
  push:
    branches:
      - master
  pull_request:
 
concurrency:
  group: ${{ github.workflow_ref }}-${{ github.event.pull_request.number || github.run_id }}
  cancel-in-progress: true
 
permissions:
  contents: read
 
jobs:
  lint:
    timeout-minutes: 30
    name: lint
    uses: bitcart/bitcart-actions/.github/workflows/lint.yml@master
    with:
      install-dependencies: |
        uv sync --frozen --compile-bytecode --no-dev --group web --group types --group lint --group test
      extra-checks: just ci-lint
 
  zizmor:
    timeout-minutes: 30
    name: zizmor
    uses: bitcart/bitcart-actions/.github/workflows/zizmor-audit.yml@master
    permissions:
      contents: read
      security-events: write # needed for github advanced security
 
  test:
    timeout-minutes: 30
    name: test-${{ matrix.python-version }}
    needs: [lint, zizmor]
    runs-on: latchkey-small
 
    strategy:
      matrix:
        python-version: ["3.12", "3.13", "3.14"]
 
    services:
      redis:
        image: redis:alpine@sha256:d146f83b1e0f02fc27c26a50cee39338c736674c5959db84363e6ae3cd9e02d2
        ports:
          - 6379:6379
 
      postgres:
        image: postgres:18-alpine@sha256:96d56f7f57c6aacd1fcb908bc83b345ec5f83231ee486dd66a1baadce274db88
        env:
          POSTGRES_DB: bitcart_test
          POSTGRES_HOST_AUTH_METHOD: trust
        ports:
          - 5432:5432
 
    env:
      TEST_ARGS: "-o junit_family=legacy --junitxml test-results/junit.xml --cov-report html:coverage"
 
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
 
      - name: Set up Python ${{ matrix.python-version }}
        uses: bitcart/bitcart-actions/actions/setup-python@master
        with:
          python-version: ${{ matrix.python-version }}
 
      - name: Install Python dependencies
        uses: bitcart/bitcart-actions/actions/install-daemon@master
        with:
          install-dependencies: |
            uv sync --frozen --compile-bytecode --no-dev --group web --group otel --group test --group btc
 
      - name: Prepare daemon
        uses: bitcart/bitcart-actions/actions/run-in-background@master
        with:
          run: BTC_EXPERIMENTAL_NOSYNC=true just testnet
          key: testnet
 
      - name: Run tests
        run: |
          just test -n 4 --pytest-durations=-1
 
      - name: Upload coverage to Codecov
        uses: bitcart/bitcart-actions/actions/codecov@master
        if: ${{ !cancelled() }}
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          name: Tests - Python ${{ env.PYTHON }}
          flags: tests
          env_vars: PYTHON
          upload_coverage: ${{ job.status == 'success' }}
 
      - name: Upload test results
        uses: bitcart/bitcart-actions/actions/upload-test-results@master
        if: ${{ !cancelled() }}
        with:
          suffix: py${{ env.PYTHON }}
 
  functional-tests:
    timeout-minutes: 30
    name: functional-tests
    uses: bitcart/bitcart-actions/.github/workflows/functional-tests.yml@master
    needs: test
    with:
      install-dependencies: |
        uv sync --frozen --compile-bytecode --no-dev --group web --group otel --group test --group btc
      enable-redis: true
      enable-postgres: true
    secrets:
      CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
 
  combine-coverage:
    timeout-minutes: 30
    name: combine-coverage
    uses: bitcart/bitcart-actions/.github/workflows/combine-coverage.yml@master
    needs: [test, functional-tests]
    if: ${{ !cancelled() }}
 

What changed

1 third-party action is referenced by a movable tag. Pin it to the commit SHA (Latchkey resolves and applies this automatically) so a repointed tag cannot change what runs.

This workflow runs 5 jobs (7 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.

Actions used in this workflow