Runnable

CI/CD example

Node.js and PostgreSQL CI pipeline on Runnable

A complete, copyable workflow with two test jobs, a disposable PostgreSQL service, an npm cache, and test-output artifacts. The public example project includes a lockfile and tests.

Complete workflow YAML

Put this file at .runnable/workflows/ci.yml on the repository default branch. Runnable reads workflows from that root-level directory.

.runnable/workflows/ci.ymlYAML
name: Node.js and PostgreSQL CI

on:
  push:
    branches: [main]
  pull_request:

permissions:
  contents: read

jobs:
  test:
    runs-on: ubuntu-24.04
    strategy:
      fail-fast: false
      matrix:
        suite: [unit, db]
    services:
      postgres:
        image: postgres:17
        env:
          POSTGRES_USER: example
          POSTGRES_PASSWORD: example
          POSTGRES_DB: example
        ports:
          - 5432/tcp
        options: >-
          --health-cmd "pg_isready -U example -d example"
          --health-interval 5s
          --health-timeout 5s
          --health-retries 10
    steps:
      - uses: actions/checkout@v4
      - uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node24-${{ hashFiles('package-lock.json') }}
      - name: Install dependencies
        run: npm ci
      - name: Test ${{ matrix.suite }}
        env:
          DATABASE_URL: postgresql://example:example@127.0.0.1:${{ job.services.postgres.ports['5432'] }}/example
        run: |
          set -o pipefail
          npm run test:${{ matrix.suite }} 2>&1 | tee test-output.txt
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: node24-${{ matrix.suite }}-test-output
          path: test-output.txt
          if-no-files-found: warn

View the complete example project for its package lock and test files. The project is a folder in the public Runnable repository; copy its contents to the root of your own repository before connecting it.

How the pipeline works

The two matrix values run the unit and database suites as separate jobs. Each job gets a clean Linux x64 machine and its own PostgreSQL service.

PartPurpose
PostgreSQL serviceStarts postgres:17, waits for pg_isready, and exposes its assigned port to the test step. The demo credentials belong only to this disposable database.
MatrixExpands suite: [unit, db] into two jobs. A failing suite does not cancel the other one because fail-fast is false.
npm cacheRestores ~/.npm using the lockfile hash; npm ci still installs exactly the locked dependency graph in each clean job.
Test artifactThe test command writes test-output.txt. The upload step runs even if the test fails, so the output remains available for debugging.

The runner already includes Node.js 24

This example uses the Node.js 24 runtime in Runnable's Ubuntu 24.04 image. If your project needs another version or an external action, check that action's metadata against a connected repository before treating a pasted-YAML verdict as complete.

Run the example

Use an isolated repository so the sample workflow is discovered at the correct path.

  1. 1

    Copy the project

    Copy the contents of the example folder to a repository root, including its .runnable/workflows/ci.yml and package-lock.json.
  2. 2

    Connect and scan

    Connect the repository through the GitHub App and review its workflow compatibility report.
  3. 3

    Push and inspect

    Push a commit or open a pull request. Confirm that the unit and db matrix jobs pass, then open each run's test-output artifact.

Adapt it to your own CI

Keep the useful structure, then replace the test commands and database credentials with your application’s needs.

Start with the GitHub Actions compatibility checker for an existing workflow. The workflow reference lists supported syntax and limits, including service containers, matrices, cache, and artifacts.

Do not reuse example credentials

The example password is intentionally public. Use scoped secrets and protected environments for real databases and deployments.
NextMigrate GitHub ActionsPilot one workflow in parallel before moving required checks or deployments.