ci workflow (parse-community/parse-server)
The ci workflow from parse-community/parse-server, explained and optimized by Latchkey.
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.
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
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
- 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. - Cache dependency installs on the setup step so they are served from cache.
- Add a job timeout so a hung step cannot burn hours of runner time.
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:
- Dependency installs
- Container pulls and builds
This workflow runs 11 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.