Skip to content
Latchkey

ci workflow (parse-community/parse-server)

The ci workflow from parse-community/parse-server, explained and optimized by Latchkey.

C

CI health: C - fair

Point runs-on at Latchkey and get caching, 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: parse-community/parse-server.github/workflows/ci.ymlLicense Apache-2.0View source

What it does

This is the ci workflow from the parse-community/parse-server repository, a real project running GitHub Actions. It is shown here with attribution under its Apache-2.0 license.

Below, Latchkey shows a faster, safer version produced by its optimization engine.

The workflow

workflow (.yml)
name: ci
on:
  push:
    branches: [release, alpha, beta, next-major, 'release-[0-9]+.x.x']
  pull_request:
    branches:
      - '**'
    paths-ignore:
      - '**/**.md'
env:
  NODE_VERSION: 24.11.0
  PARSE_SERVER_TEST_TIMEOUT: 20000
permissions:
  actions: write
jobs:
  check-code-analysis:
    name: Code Analysis
    runs-on: ubuntu-latest
    permissions:
      actions: read
      contents: read
      security-events: write
    strategy:
      fail-fast: false
      matrix:
        language: ['javascript']
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      - name: Initialize CodeQL
        uses: github/codeql-action/init@v2
        with:
          languages: ${{ matrix.language }}
          source-root: src
      - name: Perform CodeQL Analysis
        uses: github/codeql-action/analyze@v2
  check-ci:
    name: Node Engine Check
    timeout-minutes: 15
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Use Node.js ${{ matrix.NODE_VERSION }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - name: Install prod dependencies
        run: npm ci
      - name: Remove dev dependencies
        run: ./ci/uninstallDevDeps.sh @actions/core
      - name: CI Node Engine Check
        run: npm run ci:checkNodeEngine
  check-lint:
    name: Lint
    timeout-minutes: 15
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Use Node.js ${{ matrix.NODE_VERSION }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - name: Cache Node.js modules
        uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
      - name: Install dependencies
        run: npm ci
      - run: npm run lint
  check-definitions:
    name: Check Definitions
    timeout-minutes: 5
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Use Node.js ${{ matrix.NODE_VERSION }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - name: Cache Node.js modules
        uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
      - name: Install dependencies
        run: npm ci
      - name: CI Definitions Check
        run: npm run ci:definitionsCheck
  check-circular:
    name: Circular Dependencies
    timeout-minutes: 5
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Use Node.js ${{ matrix.NODE_VERSION }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - name: Cache Node.js modules
        uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
      - name: Install dependencies
        run: npm ci
      - run: npm run madge:circular
  check-docs:
    name: Docs
    timeout-minutes: 5
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Use Node.js ${{ matrix.NODE_VERSION }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - name: Cache Node.js modules
        uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
      - name: Install dependencies
        run: npm ci
      - name: Build source
        run: npm run build
      - name: Generate docs
        run: npm run docs
  check-docker:
    name: Docker Build
    timeout-minutes: 15
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      - name: Set up QEMU
        id: qemu
        uses: docker/setup-qemu-action@v2
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
      - name: Build docker image
        uses: docker/build-push-action@v3
        with:
          context: .
          platforms: linux/amd64, linux/arm64/v8
  check-lock-file-version:
    name: NPM Lock File Version
    timeout-minutes: 5
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Check NPM lock file version
        run: |
          version=$(node -e "console.log(require('./package-lock.json').lockfileVersion)")
          if [ "$version" != "2" ]; then
            echo "::error::Expected lockfileVersion 2, got $version"
            exit 1
          fi
  check-types:
    name: Check Types
    timeout-minutes: 5
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: npm ci
      - name: Build types
        run: npm run build:types
      - name: Test Types
        run: npm run test:types
  check-mongo:
    strategy:
      matrix:
        include:
          - name: MongoDB 7, ReplicaSet
            MONGODB_VERSION: 7.0.16
            MONGODB_TOPOLOGY: replset
            NODE_VERSION: 24.11.0
          - name: MongoDB 8, ReplicaSet
            MONGODB_VERSION: 8.0.4
            MONGODB_TOPOLOGY: replset
            NODE_VERSION: 24.11.0
          - name: Redis Cache
            PARSE_SERVER_TEST_CACHE: redis
            MONGODB_VERSION: 8.0.4
            MONGODB_TOPOLOGY: standalone
            NODE_VERSION: 24.11.0
          - name: Node 20
            MONGODB_VERSION: 8.0.4
            MONGODB_TOPOLOGY: standalone
            NODE_VERSION: 20.19.0
          - name: Node 22
            MONGODB_VERSION: 8.0.4
            MONGODB_TOPOLOGY: standalone
            NODE_VERSION: 22.12.0
      fail-fast: false
    name: ${{ matrix.name }}
    timeout-minutes: 20
    runs-on: ubuntu-latest
    services:
      redis:
        image: redis
        ports:
          - 6379:6379
    env:
      MONGODB_VERSION: ${{ matrix.MONGODB_VERSION }}
      MONGODB_TOPOLOGY: ${{ matrix.MONGODB_TOPOLOGY }}
      MONGODB_STORAGE_ENGINE: ${{ matrix.MONGODB_STORAGE_ENGINE }}
      PARSE_SERVER_TEST_CACHE: ${{ matrix.PARSE_SERVER_TEST_CACHE }}
      NODE_VERSION: ${{ matrix.NODE_VERSION }}
    steps:
      - name: Fix usage of insecure GitHub protocol
        run: sudo git config --system url."https://github".insteadOf "git://github"
      - uses: actions/checkout@v4
      - name: Use Node.js ${{ matrix.NODE_VERSION }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.NODE_VERSION }}
      - name: Cache Node.js modules
        uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
      - name: Install dependencies
        run: npm ci
      - run: npm run coverage:mongodb
        env:
          CI: true
      - name: Upload code coverage
        uses: codecov/codecov-action@v4
        with:
          # Set to `true` once codecov token bug is fixed; https://github.com/parse-community/parse-server/issues/9129
          fail_ci_if_error: false
          token: ${{ secrets.CODECOV_TOKEN }}
  check-postgres:
    strategy:
      matrix:
        include:
          - name: PostgreSQL 16, PostGIS 3.5
            POSTGRES_IMAGE: postgis/postgis:16-3.5
            NODE_VERSION: 24.11.0
          - name: PostgreSQL 17, PostGIS 3.5
            POSTGRES_IMAGE: postgis/postgis:17-3.5
            NODE_VERSION: 24.11.0
          - name: PostgreSQL 18, PostGIS 3.6
            POSTGRES_IMAGE: postgis/postgis:18-3.6
            NODE_VERSION: 24.11.0
      fail-fast: false
    name: ${{ matrix.name }}
    timeout-minutes: 20
    runs-on: ubuntu-latest
    services:
      redis:
        image: redis
        ports:
          - 6379:6379
      postgres:
        image: ${{ matrix.POSTGRES_IMAGE }}
        env:
          POSTGRES_PASSWORD: postgres
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    env:
      PARSE_SERVER_TEST_DB: postgres
      PARSE_SERVER_TEST_DATABASE_URI: postgres://postgres:postgres@localhost:5432/parse_server_postgres_adapter_test_database
      NODE_VERSION: ${{ matrix.NODE_VERSION }}
    steps:
      - uses: actions/checkout@v4
      - name: Use Node.js ${{ matrix.NODE_VERSION }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.NODE_VERSION }}
      - name: Cache Node.js modules
        uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
      - name: Install dependencies
        run: npm ci
      - run: |
          bash scripts/before_script_postgres_conf.sh
          bash scripts/before_script_postgres.sh
      - run: npm run coverage
        env:
          CI: true
      - name: Upload code coverage
        uses: codecov/codecov-action@v4
        with:
          fail_ci_if_error: false
          token: ${{ secrets.CODECOV_TOKEN }}
        env:
          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

The same workflow, on Latchkey

Estimated ~20% faster on cache hits, plus fewer wasted runs and a safer supply chain. Added and changed lines are highlighted.

name: ci
on:
  push:
    branches: [release, alpha, beta, next-major, 'release-[0-9]+.x.x']
  pull_request:
    branches:
      - '**'
    paths-ignore:
      - '**/**.md'
env:
  NODE_VERSION: 24.11.0
  PARSE_SERVER_TEST_TIMEOUT: 20000
permissions:
  actions: write
jobs:
  check-code-analysis:
    timeout-minutes: 30
    name: Code Analysis
    runs-on: latchkey-small
    permissions:
      actions: read
      contents: read
      security-events: write
    strategy:
      fail-fast: false
      matrix:
        language: ['javascript']
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      - name: Initialize CodeQL
        uses: github/codeql-action/init@v2
        with:
          languages: ${{ matrix.language }}
          source-root: src
      - name: Perform CodeQL Analysis
        uses: github/codeql-action/analyze@v2
  check-ci:
    name: Node Engine Check
    timeout-minutes: 15
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v4
      - name: Use Node.js ${{ matrix.NODE_VERSION }}
        uses: actions/setup-node@v4
        with:
          cache: 'npm'
          node-version: ${{ matrix.node-version }}
      - name: Install prod dependencies
        run: npm ci
      - name: Remove dev dependencies
        run: ./ci/uninstallDevDeps.sh @actions/core
      - name: CI Node Engine Check
        run: npm run ci:checkNodeEngine
  check-lint:
    name: Lint
    timeout-minutes: 15
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v4
      - name: Use Node.js ${{ matrix.NODE_VERSION }}
        uses: actions/setup-node@v4
        with:
          cache: 'npm'
          node-version: ${{ matrix.node-version }}
      - name: Cache Node.js modules
        uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
      - name: Install dependencies
        run: npm ci
      - run: npm run lint
  check-definitions:
    name: Check Definitions
    timeout-minutes: 5
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v4
      - name: Use Node.js ${{ matrix.NODE_VERSION }}
        uses: actions/setup-node@v4
        with:
          cache: 'npm'
          node-version: ${{ matrix.node-version }}
      - name: Cache Node.js modules
        uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
      - name: Install dependencies
        run: npm ci
      - name: CI Definitions Check
        run: npm run ci:definitionsCheck
  check-circular:
    name: Circular Dependencies
    timeout-minutes: 5
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v4
      - name: Use Node.js ${{ matrix.NODE_VERSION }}
        uses: actions/setup-node@v4
        with:
          cache: 'npm'
          node-version: ${{ matrix.node-version }}
      - name: Cache Node.js modules
        uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
      - name: Install dependencies
        run: npm ci
      - run: npm run madge:circular
  check-docs:
    name: Docs
    timeout-minutes: 5
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v4
      - name: Use Node.js ${{ matrix.NODE_VERSION }}
        uses: actions/setup-node@v4
        with:
          cache: 'npm'
          node-version: ${{ matrix.node-version }}
      - name: Cache Node.js modules
        uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
      - name: Install dependencies
        run: npm ci
      - name: Build source
        run: npm run build
      - name: Generate docs
        run: npm run docs
  check-docker:
    name: Docker Build
    timeout-minutes: 15
    runs-on: latchkey-small
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      - name: Set up QEMU
        id: qemu
        uses: docker/setup-qemu-action@v2
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
      - name: Build docker image
        uses: docker/build-push-action@v3
        with:
          context: .
          platforms: linux/amd64, linux/arm64/v8
  check-lock-file-version:
    name: NPM Lock File Version
    timeout-minutes: 5
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v4
      - name: Check NPM lock file version
        run: |
          version=$(node -e "console.log(require('./package-lock.json').lockfileVersion)")
          if [ "$version" != "2" ]; then
            echo "::error::Expected lockfileVersion 2, got $version"
            exit 1
          fi
  check-types:
    name: Check Types
    timeout-minutes: 5
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v3
      - run: npm ci
      - name: Build types
        run: npm run build:types
      - name: Test Types
        run: npm run test:types
  check-mongo:
    strategy:
      matrix:
        include:
          - name: MongoDB 7, ReplicaSet
            MONGODB_VERSION: 7.0.16
            MONGODB_TOPOLOGY: replset
            NODE_VERSION: 24.11.0
          - name: MongoDB 8, ReplicaSet
            MONGODB_VERSION: 8.0.4
            MONGODB_TOPOLOGY: replset
            NODE_VERSION: 24.11.0
          - name: Redis Cache
            PARSE_SERVER_TEST_CACHE: redis
            MONGODB_VERSION: 8.0.4
            MONGODB_TOPOLOGY: standalone
            NODE_VERSION: 24.11.0
          - name: Node 20
            MONGODB_VERSION: 8.0.4
            MONGODB_TOPOLOGY: standalone
            NODE_VERSION: 20.19.0
          - name: Node 22
            MONGODB_VERSION: 8.0.4
            MONGODB_TOPOLOGY: standalone
            NODE_VERSION: 22.12.0
      fail-fast: false
    name: ${{ matrix.name }}
    timeout-minutes: 20
    runs-on: latchkey-small
    services:
      redis:
        image: redis
        ports:
          - 6379:6379
    env:
      MONGODB_VERSION: ${{ matrix.MONGODB_VERSION }}
      MONGODB_TOPOLOGY: ${{ matrix.MONGODB_TOPOLOGY }}
      MONGODB_STORAGE_ENGINE: ${{ matrix.MONGODB_STORAGE_ENGINE }}
      PARSE_SERVER_TEST_CACHE: ${{ matrix.PARSE_SERVER_TEST_CACHE }}
      NODE_VERSION: ${{ matrix.NODE_VERSION }}
    steps:
      - name: Fix usage of insecure GitHub protocol
        run: sudo git config --system url."https://github".insteadOf "git://github"
      - uses: actions/checkout@v4
      - name: Use Node.js ${{ matrix.NODE_VERSION }}
        uses: actions/setup-node@v4
        with:
          cache: 'npm'
          node-version: ${{ matrix.NODE_VERSION }}
      - name: Cache Node.js modules
        uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
      - name: Install dependencies
        run: npm ci
      - run: npm run coverage:mongodb
        env:
          CI: true
      - name: Upload code coverage
        uses: codecov/codecov-action@v4
        with:
          # Set to `true` once codecov token bug is fixed; https://github.com/parse-community/parse-server/issues/9129
          fail_ci_if_error: false
          token: ${{ secrets.CODECOV_TOKEN }}
  check-postgres:
    strategy:
      matrix:
        include:
          - name: PostgreSQL 16, PostGIS 3.5
            POSTGRES_IMAGE: postgis/postgis:16-3.5
            NODE_VERSION: 24.11.0
          - name: PostgreSQL 17, PostGIS 3.5
            POSTGRES_IMAGE: postgis/postgis:17-3.5
            NODE_VERSION: 24.11.0
          - name: PostgreSQL 18, PostGIS 3.6
            POSTGRES_IMAGE: postgis/postgis:18-3.6
            NODE_VERSION: 24.11.0
      fail-fast: false
    name: ${{ matrix.name }}
    timeout-minutes: 20
    runs-on: latchkey-small
    services:
      redis:
        image: redis
        ports:
          - 6379:6379
      postgres:
        image: ${{ matrix.POSTGRES_IMAGE }}
        env:
          POSTGRES_PASSWORD: postgres
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    env:
      PARSE_SERVER_TEST_DB: postgres
      PARSE_SERVER_TEST_DATABASE_URI: postgres://postgres:postgres@localhost:5432/parse_server_postgres_adapter_test_database
      NODE_VERSION: ${{ matrix.NODE_VERSION }}
    steps:
      - uses: actions/checkout@v4
      - name: Use Node.js ${{ matrix.NODE_VERSION }}
        uses: actions/setup-node@v4
        with:
          cache: 'npm'
          node-version: ${{ matrix.NODE_VERSION }}
      - name: Cache Node.js modules
        uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
      - name: Install dependencies
        run: npm ci
      - run: |
          bash scripts/before_script_postgres_conf.sh
          bash scripts/before_script_postgres.sh
      - run: npm run coverage
        env:
          CI: true
      - name: Upload code coverage
        uses: codecov/codecov-action@v4
        with:
          fail_ci_if_error: false
          token: ${{ secrets.CODECOV_TOKEN }}
        env:
          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
 

What changed

4 third-party actions are referenced by a movable tag. Pin them to the commit SHA (Latchkey resolves and applies this automatically) so a repointed tag cannot change what runs.

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:

This workflow runs 11 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.

Actions used in this workflow