CI workflow (brianc/node-postgres)
The CI workflow from brianc/node-postgres, explained and optimized by Latchkey.
CI health: A - excellent
Point runs-on at Latchkey and get run de-duplication, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the CI workflow from the brianc/node-postgres 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
on: [push, pull_request]
permissions:
contents: read
jobs:
lint:
timeout-minutes: 5
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 18
cache: yarn
- run: yarn install --frozen-lockfile
- run: yarn lint
build:
timeout-minutes: 15
needs: lint
services:
postgres:
image: ghcr.io/railwayapp-templates/postgres-ssl:${{ matrix.postgres }}
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_HOST_AUTH_METHOD: 'md5'
POSTGRES_DB: ci_db_test
# PostgreSQL 18's official image defaults PGDATA to a versioned
# subdirectory (/var/lib/postgresql/18/docker), but the
# railwayapp-templates/postgres-ssl entrypoint requires PGDATA to
# start with /var/lib/postgresql/data so we pin it explicitly. This is
# also the default for the older images, so it is a no-op there.
PGDATA: /var/lib/postgresql/data
ports:
- 5432:5432
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
strategy:
fail-fast: false
matrix:
include:
# Historical Node.js versions tested against a single PostgreSQL version
- { node: '16', postgres: &stable_postgres '18' }
- { node: '18', postgres: *stable_postgres }
- { node: '20', postgres: *stable_postgres }
- { node: '22', postgres: *stable_postgres }
- { node: '24', postgres: *stable_postgres }
# Latest Node.js version tested against multiple PostgreSQL versions
- { node: &latest_node '26', postgres: '13' }
- { node: *latest_node, postgres: '14' }
- { node: *latest_node, postgres: '15' }
- { node: *latest_node, postgres: '16' }
- { node: *latest_node, postgres: '17' }
- { node: *latest_node, postgres: '18' }
name: Node.js ${{ matrix.node }} x PostgreSQL ${{ matrix.postgres }}
runs-on: ubuntu-latest
env:
PGUSER: postgres
PGPASSWORD: postgres
PGHOST: localhost
PGDATABASE: ci_db_test
PGTESTNOSSL: 'true'
SCRAM_TEST_PGUSER: scram_test
SCRAM_TEST_PGPASSWORD: test4scram
SCRAM_TEST_PGUSER_UNICODE: scram_unicode_test
# Raw form of a password whose NFKC normalization differs from itself.
# U+2168 (ROMAN NUMERAL IX) decomposes to ASCII "IX" under NFKC; the
# server stores the verifier from the SASLprep-normalized form, so the
# client must apply SASLprep too. This is the regression check for the
# RFC 4013 fix in packages/pg/lib/crypto/sasl.js.
SCRAM_TEST_PGPASSWORD_UNICODE: "IX-\u2168"
steps:
- name: Show OS
run: |
uname -a
- run: |
psql \
-c "SET password_encryption = 'scram-sha-256'" \
-c "CREATE ROLE scram_test LOGIN PASSWORD 'test4scram'" \
-c "CREATE ROLE scram_unicode_test LOGIN PASSWORD U&'IX-\2168'"
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: yarn
- run: yarn install --frozen-lockfile
- run: yarn test
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: CI on: [push, pull_request] permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: lint: timeout-minutes: 5 runs-on: latchkey-small steps: - uses: actions/checkout@v4 with: persist-credentials: false - name: Setup node uses: actions/setup-node@v4 with: node-version: 18 cache: yarn - run: yarn install --frozen-lockfile - run: yarn lint build: timeout-minutes: 15 needs: lint services: postgres: image: ghcr.io/railwayapp-templates/postgres-ssl:${{ matrix.postgres }} env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_HOST_AUTH_METHOD: 'md5' POSTGRES_DB: ci_db_test # PostgreSQL 18's official image defaults PGDATA to a versioned # subdirectory (/var/lib/postgresql/18/docker), but the # railwayapp-templates/postgres-ssl entrypoint requires PGDATA to # start with /var/lib/postgresql/data so we pin it explicitly. This is # also the default for the older images, so it is a no-op there. PGDATA: /var/lib/postgresql/data ports: - 5432:5432 options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 strategy: fail-fast: false matrix: include: # Historical Node.js versions tested against a single PostgreSQL version - { node: '16', postgres: &stable_postgres '18' } - { node: '18', postgres: *stable_postgres } - { node: '20', postgres: *stable_postgres } - { node: '22', postgres: *stable_postgres } - { node: '24', postgres: *stable_postgres } # Latest Node.js version tested against multiple PostgreSQL versions - { node: &latest_node '26', postgres: '13' } - { node: *latest_node, postgres: '14' } - { node: *latest_node, postgres: '15' } - { node: *latest_node, postgres: '16' } - { node: *latest_node, postgres: '17' } - { node: *latest_node, postgres: '18' } name: Node.js ${{ matrix.node }} x PostgreSQL ${{ matrix.postgres }} runs-on: latchkey-small env: PGUSER: postgres PGPASSWORD: postgres PGHOST: localhost PGDATABASE: ci_db_test PGTESTNOSSL: 'true' SCRAM_TEST_PGUSER: scram_test SCRAM_TEST_PGPASSWORD: test4scram SCRAM_TEST_PGUSER_UNICODE: scram_unicode_test # Raw form of a password whose NFKC normalization differs from itself. # U+2168 (ROMAN NUMERAL IX) decomposes to ASCII "IX" under NFKC; the # server stores the verifier from the SASLprep-normalized form, so the # client must apply SASLprep too. This is the regression check for the # RFC 4013 fix in packages/pg/lib/crypto/sasl.js. SCRAM_TEST_PGPASSWORD_UNICODE: "IX-\u2168" steps: - name: Show OS run: | uname -a - run: | psql \ -c "SET password_encryption = 'scram-sha-256'" \ -c "CREATE ROLE scram_test LOGIN PASSWORD 'test4scram'" \ -c "CREATE ROLE scram_unicode_test LOGIN PASSWORD U&'IX-\2168'" - uses: actions/checkout@v4 with: persist-credentials: false - name: Setup node uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} cache: yarn - run: yarn install --frozen-lockfile - run: yarn test
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. - Cancel superseded runs when a branch or PR gets a newer push.
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
This workflow runs 2 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.