CI Workflows
This page documents the continuous integration (CI) workflows defined in the Express repository. The project uses GitHub Actions to automate linting, testing, security analysis, and supply-chain security scoring across multiple Node.js versions and operating systems.
Workflow Overview
The repository defines four CI workflows, each serving a distinct purpose in the development and security lifecycle.
| Workflow File | Workflow Name | Primary Purpose |
|---|---|---|
.github/workflows/ci.yml | ci | Main CI: lint, test across Node.js versions and OS, collect coverage |
.github/workflows/codeql.yml | CodeQL | Security analysis via GitHub CodeQL |
.github/workflows/legacy.yml | legacy | Test on older Node.js versions (16, 17) |
.github/workflows/scorecard.yml | Scorecard supply-chain security | OpenSSF Scorecard security assessment |
Main CI Workflow (ci.yml)
The primary CI workflow is defined in .github/workflows/ci.yml and is responsible for ensuring code quality and correctness across the supported runtime matrix.
Trigger Conditions
The workflow runs on the following events .github/workflows/ci.yml:3-12:
- Push to branches:
master,develop,4.x,5.x,5.0 - Pull requests to any branch
- Manual trigger via
workflow_dispatch
Push events ignore changes to Markdown files (*.md) to avoid unnecessary CI runs for documentation-only changes.
Concurrency Control
The workflow uses a concurrency group keyed by the workflow name and the pull request or branch reference .github/workflows/ci.yml:19-22. This ensures that only the most recent run for a given branch or pull request is in progress, canceling any previously running workflows for the same context.
Jobs
Lint Job
The lint job runs on ubuntu-latest and performs the following steps .github/workflows/ci.yml:26-42:
- Checks out the repository using
actions/checkoutwithpersist-credentials: false - Sets up Node.js using the latest LTS version via
actions/setup-node - Installs dependencies with
npm install --ignore-scripts --include=dev - Runs the lint script:
npm run lint
The --ignore-scripts flag prevents execution of lifecycle scripts during dependency installation, which is a security best practice. The --include=dev flag ensures dev dependencies (which include linting tools) are installed.
Test Job
The test job uses a build matrix to test across multiple configurations .github/workflows/ci.yml:44-83:
- Operating systems:
ubuntu-latest,windows-latest - Node.js versions: 18, 19, 20, 21, 22, 23, 24, 25, 26
The matrix uses fail-fast: false so that all combinations run even if one fails, providing full visibility into which configurations are affected.
Each test job:
- Checks out the repository
- Sets up the specified Node.js version
- Configures npm log level to
errorto reduce noise - Installs all dependencies with
npm install - Outputs Node.js and npm versions for debugging
- Runs tests using
npm run test-ci - Uploads the generated code coverage report (
./coverage/lcov.info) as an artifact with a retention period of 1 day
Coverage Job
The coverage job runs after all test jobs complete (declared via needs: test) .github/workflows/ci.yml:85-107. It:
- Installs
lcov(the LCOV coverage tool) on Ubuntu - Downloads all coverage artifacts matching the pattern
coverage-node-* - Merges all
lcov.infofiles into a single report usinglcov - Uploads the merged report to Coveralls using
coverallsapp/github-action
This job requires additional permissions: contents: read and checks: write .github/workflows/ci.yml:88-90.
CodeQL Security Analysis (codeql.yml)
The CodeQL workflow performs automated security analysis using GitHub's CodeQL engine .github/workflows/codeql.yml.
Purpose
CodeQL analyzes the codebase for security vulnerabilities, coding errors, and other issues that could lead to security problems. It is a static analysis tool that treats code as data and runs queries to find patterns associated with security weaknesses.
Trigger Conditions
The workflow runs on .github/workflows/codeql.yml:17-22:
- Push to the
masterbranch - Pull requests targeting the
masterbranch - Weekly schedule: every Monday at midnight UTC (
0 0 * * 1) - Manual trigger via
workflow_dispatch
Analysis Configuration
The workflow analyzes two languages .github/workflows/codeql.yml:34-35:
javascript(the primary language of the Express codebase)actions(GitHub Actions workflow files)
The CodeQL configuration includes a paths-ignore directive that excludes the test directory from analysis .github/workflows/codeql.yml:47-49. This prevents test files from generating noise in security results, as test code often contains patterns (like simulated attacks or insecure configurations) that would trigger false positives.
Permissions
The job requires elevated permissions .github/workflows/codeql.yml:30-33:
actions: read- to read action metadatacontents: read- to check out the repositorysecurity-events: write- to upload results to GitHub's code scanning dashboard
Legacy Testing Workflow (legacy.yml)
The legacy workflow tests the project against older Node.js versions that are no longer supported by the main CI workflow .github/workflows/legacy.yml.
Trigger Conditions
The workflow runs on .github/workflows/legacy.yml:3-16:
- Push to branches:
master,develop,4.x,5.x,5.0 - Pull requests (ignoring Markdown changes)
- Manual trigger via
workflow_dispatch
Test Matrix
The legacy workflow tests against Node.js versions 16 and 17 on both Ubuntu and Windows .github/workflows/legacy.yml:23-27. These versions are past their end-of-life but may still be used by some consumers of Express.
The job structure is identical to the main CI test job: it installs dependencies, runs npm run test-ci, and uploads coverage artifacts. The coverage job merges and uploads results to Coveralls in the same manner as the main CI workflow.
Supply-Chain Security Scorecard (scorecard.yml)
The Scorecard workflow evaluates the repository against OpenSSF (Open Source Security Foundation) security best practices .github/workflows/scorecard.yml.
Purpose
The OpenSSF Scorecard assesses a repository's security posture across several dimensions, including:
- Branch protection
- Maintained status
- Dependency pinning
- Token permissions
- Code review practices
- And other security-related checks
The workflow publishes results to the OpenSSF REST API and uploads findings to GitHub's code scanning dashboard, making them visible to repository maintainers and consumers.
Trigger Conditions
The workflow runs on .github/workflows/scorecard.yml:8-14:
- Branch protection rule events (to check branch protection settings)
- Weekly schedule: every Monday at 21:16 UTC (
16 21 * * 1) - Push to the
masterbranch
Permissions
The workflow uses minimal default permissions (read-all) and escalates only where needed .github/workflows/scorecard.yml:17-26:
security-events: write- to upload SARIF results to code scanningid-token: write- to publish results and obtain a Scorecard badge
Steps
- Checkout code using
actions/checkoutwithpersist-credentials: false - Run analysis using
ossf/scorecard-action, which produces a SARIF results file - Upload artifact - saves the SARIF file as a build artifact with 5-day retention
- Upload to code-scanning - sends the SARIF results to GitHub's code scanning dashboard using
github/codeql-action/upload-sarif
The publish_results: true setting makes the Scorecard results publicly accessible via the OpenSSF REST API and enables the repository to display a Scorecard badge .github/workflows/scorecard.yml:52-52.
Workflow Execution Summary
| Workflow | When It Runs | What It Does |
|---|---|---|
ci | Push to main branches, PRs, manual | Lint, test on Node 18-26 (Ubuntu + Windows), upload coverage |
codeql | Push to master, PRs to master, weekly, manual | Static security analysis of JavaScript and Actions code |
legacy | Push to main branches, PRs, manual | Test on Node 16-17 (Ubuntu + Windows), upload coverage |
scorecard | Branch protection events, weekly, push to master | OpenSSF security scorecard assessment |
Related Pages
- CI Workflows (this page)
- Architecture
- Package Configuration