CI/CD Pipeline & Automation Documentation
12 GitHub Actions Workflows — TypeScript/Node.js — DevSecOps Pipeline
📋 Document Owner: DevOps Team | 📄 Version: 0.7.0 | 📅 Last Updated: 2026-05-05 (UTC)
🔄 Review Cycle: Quarterly | ⏰ Next Review: 2026-08-05
🏷️ Classification: Public (Open Source MCP Server)
🔷 Project Version: 1.2.21
🔷 TypeScript Baseline: 6.0.3
✅ ISMS Compliance: ISO 27001 (A.8.31, A.14.2, A.12.1), NIST CSF 2.0 (PR.DS-6, DE.CM-8), CIS Controls v8.1 (2.2, 4.1, 16.6)
- Architecture Documentation Map
- Pipeline Overview
- Pipeline Stages Summary
- Workflow Overview
- Workflow Relationships
- Detailed Pipeline Stages
- Caching & Resilience
- Security Controls
- Quality Gates
- ISMS Compliance
- Related Documentation
| Document | Current | Future | Description |
|---|---|---|---|
| Architecture | ARCHITECTURE.md | FUTURE_ARCHITECTURE.md | C4 model, containers, components |
| Mind Map | MINDMAP.md | FUTURE_MINDMAP.md | System concepts and relationships |
| SWOT Analysis | SWOT.md | FUTURE_SWOT.md | Strategic positioning |
| Data Model | DATA_MODEL.md | FUTURE_DATA_MODEL.md | Entity relationships and schemas |
| Flowchart | FLOWCHART.md | FUTURE_FLOWCHART.md | Business process flows |
| State Diagram | STATEDIAGRAM.md | FUTURE_STATEDIAGRAM.md | System state transitions |
| Workflows | WORKFLOWS.md (this document) | FUTURE_WORKFLOWS.md | CI/CD pipeline documentation |
| Security Architecture | SECURITY_ARCHITECTURE.md | FUTURE_SECURITY_ARCHITECTURE.md | Security controls and design |
| Threat Model | THREAT_MODEL.md | — | STRIDE-based threat analysis |
| CRA Assessment | CRA-ASSESSMENT.md | — | EU Cyber Resilience Act review |
| Architecture Diagrams | ARCHITECTURE_DIAGRAMS.md | — | Supplementary C4 diagrams |
The European Parliament MCP Server (v0.6.2) maintains 11 automated GitHub Actions workflows organized across 8 pipeline stages, providing comprehensive DevSecOps coverage for a TypeScript/Node.js MCP server. All workflows align with Hack23 ISMS policies and follow supply-chain security best practices.
graph LR
A["📝 Code Change"] --> B["🔍 Validate"]
B --> C["🧪 Build & Test"]
C --> D["🔒 Security Scan"]
D --> E["🔄 Integration"]
E --> F{"🏷️ Tagged<br>Release?"}
F -->|Yes| G["📦 Release & Publish"]
G --> H["🛡️ Supply Chain"]
H --> I["📊 Monitor"]
F -->|No| J["✅ PR Ready"]
style A fill:#4a90e2,stroke:#2e6ab0,color:#fff
style B fill:#f5a623,stroke:#d48b1a,color:#fff
style C fill:#7b68ee,stroke:#5b48ce,color:#fff
style D fill:#e74c3c,stroke:#c0392b,color:#fff
style E fill:#2ecc71,stroke:#27ae60,color:#fff
style F fill:#ffd43b,stroke:#f0c419,color:#333
style G fill:#9b59b6,stroke:#8e44ad,color:#fff
style H fill:#e67e22,stroke:#d35400,color:#fff
style I fill:#1abc9c,stroke:#16a085,color:#fff
style J fill:#51cf66,stroke:#40c057,color:#fff
- 🔒 Security First — All workflows use
step-security/harden-runner, pinned action SHAs, and least-privilege permissions - 📦 Supply Chain Integrity — SLSA Level 3 provenance, SPDX JSON SBOMs with GitHub Attestations
- 🧪 Quality Enforcement — 80%+ code coverage, zero lint errors, type-safe builds, license compliance
- 📊 Transparency — All evidence available in the Documentation Portal
| Stage | Pipeline Phase | Workflows | Trigger | Duration | Purpose |
|---|---|---|---|---|---|
| 1 | Code Validation | dependency-review.yml, labeler.yml, knip.yml |
PR | ~1 min | Dependency scanning, PR labeling, unused-code detection |
| 2 | Build & Test | test-and-report.yml |
Push, PR | ~3 min | TypeScript build, lint, unit tests, coverage |
| 3 | Security Analysis | codeql.yml |
Push, PR, Weekly | ~5 min | SAST scanning (CodeQL) |
| 4 | Integration Testing | integration-tests.yml, osint-qa.yml |
Push, PR, Daily (integration-tests.yml only; osint-qa.yml is Push (paths), PR (paths)) |
~5–20 min | E2E tests, live API validation, OSINT QA harness (contract + per-file coverage + Stryker mutation) |
| 5 | Release & Publish | release.yml |
Tag (v*) | ~8 min | npm publish, GitHub Release, docs, SBOM generation |
| 6 | Supply Chain | slsa-provenance.yml |
Release, Push | ~4 min | SLSA provenance, attestations |
| 7 | Continuous Monitoring | scorecard.yml, refresh-stats.yml |
Push, Weekly | ~5 min | OpenSSF Scorecard, EP statistics refresh |
| 8 | Repository Mgmt | setup-labels.yml, copilot-setup-steps.yml |
Manual | ~1 min | Label sync, Copilot agent setup |
| # | Workflow | File | Trigger | Node.js | Permissions | ISMS Evidence |
|---|---|---|---|---|---|---|
| 1 | Test and Report | test-and-report.yml |
Push, PR | 26.x + TS 6.0.3 | read-all, scoped per job |
Secure Dev Policy |
| 2 | CodeQL Analysis | codeql.yml |
Push, PR, Weekly | — | security-events: write |
ISO 27001 A.14.2.8 |
| 3 | Build, Attest and Release | release.yml |
Tag (v*), Manual | 26.x + TS 6.0.3 | id-token: write, attestations: write |
SLSA Level 3, includes SBOM |
| 4 | Integration & E2E Tests | integration-tests.yml |
Push, PR, Daily, Manual | 26.x + TS 6.0.3 | read-all |
Quality Assurance |
| 5 | SLSA Provenance | slsa-provenance.yml |
Tag (v*), Release, Manual | node-version: 26 | id-token: write, attestations: write |
SLSA Level 3 |
| 6 | Scorecard | scorecard.yml |
Push, Weekly | — | security-events: write, id-token: write |
Open Source Policy |
| 7 | Dependency Review | dependency-review.yml |
PR | — | contents: read |
NIST CSF DE.CM-8 |
| 8 | PR Labeler | labeler.yml |
PR | — | pull-requests: write |
Process Automation |
| 9 | Setup Labels | setup-labels.yml |
Manual | — | issues: write |
Configuration Mgmt |
| 10 | Copilot Setup | copilot-setup-steps.yml |
Push, PR, Manual | 26.x + TS 6.0.3 | Scoped per caller | Dev Tooling |
| 11 | EP Statistics Refresh | refresh-stats.yml |
Weekly (cron), Manual | 26.x + TS 6.0.3 | contents: write |
Agentic data intelligence |
| 12 | Knip — Unused Code | knip.yml |
Push, PR, Manual | node-version: 26 | contents: read |
ISO 27001 A.8.28 (Secure Coding) |
| 13 | OSINT QA Harness | osint-qa.yml |
Push (paths), PR (paths), Manual | node-version: 26 | read-all (workflow), scoped to contents: read per job |
ISO 27001 A.8.29 (Security testing in dev & acceptance), A.8.34 (Audit protection); CIS v8.1 Control 16; Hack23 ISMS Secure Development Policy §4.4 (Testing), §4.5 (QA) |
flowchart TB
subgraph "🔀 Developer Activity"
DEV["👨💻 Code Push / PR"]
end
subgraph "Stage 1: Code Validation"
DEV --> LABEL["🏷️ PR Labeler<br><code>labeler.yml</code>"]
DEV --> DEPREVIEW["🔍 Dependency Review<br><code>dependency-review.yml</code>"]
DEV --> KNIP_WF["🧹 Knip<br><code>knip.yml</code>"]
end
subgraph "Stage 2: Build & Test"
DEV --> TEST["🧪 Test & Report<br><code>test-and-report.yml</code>"]
TEST --> PREPARE["⚙️ Prepare<br>Node.js 26, npm install"]
PREPARE --> BUILD_VAL["📦 Build Validation"]
PREPARE --> UNIT["🧪 Unit Tests"]
BUILD_VAL --> TYPE["tsc --noEmit"]
BUILD_VAL --> LINT["ESLint 10.x"]
BUILD_VAL --> KNIP["Knip"]
BUILD_VAL --> SBOM_CHECK["SBOM Quality ≥7.0"]
UNIT --> COV{"Coverage ≥80%?"}
COV -->|Yes| PASS["✅ Pass"]
COV -->|No| WARN["⚠️ Warning"]
end
subgraph "Stage 3: Security Analysis"
DEV --> CODEQL["🔒 CodeQL<br><code>codeql.yml</code>"]
CODEQL --> SARIF["📄 SARIF Upload"]
end
subgraph "Stage 4: Integration Testing"
DEV --> INTEGRATION["🔄 Integration Tests<br><code>integration-tests.yml</code>"]
INTEGRATION --> E2E["E2E Tests"]
INTEGRATION --> PERF["Performance Tests"]
INTEGRATION --> SECSCAN["Security Scan<br>npm audit"]
end
subgraph "Stage 5: Release (tags only)"
TAG["🏷️ Push v* Tag"] --> RELEASE["📦 Release<br><code>release.yml</code>"]
RELEASE --> NPM["npm publish<br>--provenance"]
RELEASE --> GH_RELEASE["GitHub Release<br>+ Changelog"]
RELEASE --> DOCS["📚 TypeDoc"]
RELEASE --> SBOM_RELEASE["📋 SBOM (SPDX JSON)"]
end
subgraph "Stage 6: Supply Chain"
RELEASE --> SLSA["🛡️ SLSA Provenance<br><code>slsa-provenance.yml</code>"]
SLSA --> SLSA_VERIFY["✅ Verify Provenance"]
SLSA --> SLSA_ATTEST["🔏 SLSA Attestation"]
end
subgraph "Stage 7: Continuous Monitoring"
WEEKLY["⏰ Scheduled"] --> SCORECARD["🏆 OpenSSF Scorecard<br><code>scorecard.yml</code>"]
WEEKLY --> REFRESH_STATS["📊 EP Statistics Refresh<br><code>refresh-stats.yml</code>"]
WEEKLY --> CODEQL
WEEKLY --> INTEGRATION
end
style DEV fill:#4a90e2,stroke:#2e6ab0,color:#fff
style TEST fill:#7b68ee,stroke:#5b48ce,color:#fff
style CODEQL fill:#e74c3c,stroke:#c0392b,color:#fff
style INTEGRATION fill:#2ecc71,stroke:#27ae60,color:#fff
style RELEASE fill:#9b59b6,stroke:#8e44ad,color:#fff
style SLSA fill:#e67e22,stroke:#d35400,color:#fff
style SCORECARD fill:#1abc9c,stroke:#16a085,color:#fff
style REFRESH_STATS fill:#1abc9c,stroke:#16a085,color:#fff
style PASS fill:#51cf66,stroke:#40c057,color:#fff
| Property | Value |
|---|---|
| Workflow File | .github/workflows/dependency-review.yml |
| Trigger | Pull requests |
| Duration | ~1 min |
| Quality Gate | Block PRs with known vulnerabilities |
| Runner Hardening | step-security/harden-runner (egress audit) |
Key Steps:
- Harden runner environment
- Checkout repository
- Run GitHub Dependency Review Action
- Post PR comment with vulnerability summary
Security Checks:
- Known vulnerability detection (CVE database, GitHub Advisory Database)
- License compliance — allowed:
MIT,Apache-2.0,BSD-*,ISC - Dependency graph analysis for transitive vulnerabilities
- Security advisory alerts for new disclosures
| Property | Value |
|---|---|
| Workflow File | .github/workflows/labeler.yml |
| Trigger | pull_request_target (opened, synchronize, reopened, edited) |
| Duration | ~30 sec |
| Quality Gate | Informational (auto-classification) |
Label Categories:
| Category | Labels | File Patterns |
|---|---|---|
| MCP | mcp-tools, mcp-resources, mcp-prompts, mcp-protocol |
src/tools/**, src/resources/** |
| EP Data | ep-api, ep-data, meps, plenary, committees, documents |
src/api/**, src/ep-*/** |
| Quality | testing, documentation, security, dependencies |
tests/**, docs/**, *.md |
| Components | component-tools, component-resources, component-client |
src/tools/**, src/resources/** |
| Property | Value |
|---|---|
| Workflow File | .github/workflows/knip.yml |
| Trigger | Push to main, Pull requests to main, Manual dispatch |
| Duration | ~1 min |
| Node.js Version | node-version: 26 |
| Quality Gate | 0 unused exports, dependencies, or files (blocking) |
| Runner Hardening | step-security/harden-runner (egress audit) |
| Concurrency | cancel-in-progress per ref to save CI minutes |
Key Steps:
- Harden runner environment
- Checkout repository
- Setup Node.js 26 + cache
~/.npm npm cinpm run knip(usesknip.jsoncoveringsrc/**/*.ts,tests/**/*.ts,scripts/**/*.ts)- Post job summary with triage guidance on failure
Triage Guidance (surfaced in failure summary):
- Integrate — code is intended but not yet wired up; complete integration.
- Whitelist — code is used by tooling Knip cannot detect (agentic workflows, dynamic imports); update
knip.json. - Delete — code is genuinely dead; remove it.
Coverage Scope:
src/**/*.ts— production sourcetests/**/*.ts— unit, integration, E2E, performance testsscripts/**/*.ts— build, release, and statistics-generation scripts
Note: npm run knip also runs as a step inside test-and-report.yml's build-validation job. The dedicated knip.yml workflow runs in parallel for faster developer feedback and clearer signal in PR checks.
| Property | Value |
|---|---|
| Workflow File | .github/workflows/test-and-report.yml |
| Trigger | Push to main, Pull requests to main |
| Duration | ~3 min |
| Node.js Version | node-version: 26 |
| Quality Gates | 9 gates (see table below) |
Jobs:
prepare → build-validation → unit-tests → report
Job Details:
| Job | Steps | Artifacts |
|---|---|---|
| prepare | Setup Node.js 26, npm ci, cache dependencies |
Cached node_modules |
| build-validation | tsc --noEmit (TypeScript 6.0.3), ESLint, Knip, npm run build, license check, SBOM quality |
Build artifacts, SBOM report |
| unit-tests | npm run test:coverage, coverage threshold check, Codecov upload |
Coverage reports (lcov, JSON) |
| report | Combine artifacts, generate test summary, PR comment | Combined test report |
Quality Gates:
| Check | Command | Threshold | On Failure |
|---|---|---|---|
| TypeScript compilation | tsc --noEmit |
0 errors | ❌ Block merge |
| Linting | npx eslint . |
0 errors | ❌ Block merge |
| Unused code | npx knip |
0 unused exports | ❌ Block merge |
| Build | npm run build |
Successful compilation | ❌ Block merge |
| Package validation | npm pack --dry-run |
Valid package structure | ❌ Block merge |
| License compliance | license-checker |
MIT, Apache-2.0, BSD, ISC only | ❌ Block merge |
| SBOM quality | SBOMQS | ≥7.0/10 | ❌ Block merge |
| Unit tests | npm run test:coverage |
All tests pass | ❌ Block merge |
| Code coverage | Vitest coverage | ≥80% lines |
| Property | Value |
|---|---|
| Workflow File | .github/workflows/codeql.yml |
| Trigger | Push to main, PR to main, Weekly (Monday 00:00 UTC) |
| Duration | ~5 min |
| Quality Gate | No high/critical findings |
| Permissions | contents: read, actions: read, security-events: write |
Configuration:
| Setting | Value |
|---|---|
| Language | JavaScript/TypeScript |
| Query suites | security-extended, security-and-quality |
| Paths analyzed | src/ (excludes node_modules, dist, tests) |
| Output | SARIF uploaded to GitHub Security tab |
CWE Coverage:
| CWE ID | Vulnerability Class | Relevance to MCP Server |
|---|---|---|
| CWE-20 | Input Validation | Zod schema validation for all tool inputs |
| CWE-79 | Cross-Site Scripting | Response sanitization for HTML content |
| CWE-78 | Command Injection | No shell execution in codebase |
| CWE-94 | Code Injection | No dynamic code evaluation |
| CWE-200 | Information Exposure | GDPR-compliant audit logging |
| CWE-312 | Cleartext Storage | No sensitive data persistence |
| CWE-287 | Authentication Issues | Read-only public API access |
| Property | Value |
|---|---|
| Workflow File | .github/workflows/integration-tests.yml |
| Trigger | Push to main, PR to main, Daily (02:00 UTC), Manual |
| Duration | ~5 min |
| Node.js Version | node-version: 26 |
| Quality Gate | All integration and E2E tests pass |
Environment Variables:
| Variable | Default | Purpose |
|---|---|---|
EP_API_URL |
https://data.europarl.europa.eu/api/v2 |
European Parliament API endpoint |
EP_INTEGRATION_TESTS |
true |
Enable live API tests |
EP_REQUEST_TIMEOUT_MS |
30000 |
Request timeout (30 sec) |
NODE_ENV |
test |
Runtime environment |
Jobs:
| Job | Purpose | Key Commands |
|---|---|---|
| integration-tests | Full test pipeline | tsc --noEmit, npm run lint, npm run build, npm run test:unit, npm run test:integration, npm run test:e2e, npm run test:performance |
| security-scan | Dependency audit | npm audit --audit-level=moderate, license compliance check |
| test-summary | Aggregate results | Download artifacts, generate summary report |
Test Modes:
| Mode | Description | API Calls |
|---|---|---|
| Unit Integration | Mock-based contract tests | None (mocked) |
| Live API | Real EP API calls (EP_INTEGRATION_TESTS=true) |
Yes — rate-limited |
| E2E | Full MCP protocol round-trip tests | Yes — real transport |
| Performance | Response time benchmarks | Yes — timed requests |
Rate Limit Awareness:
- EP API limit: 100 requests per 15 minutes
- Scheduled daily runs minimize API impact
- Fixture capture mode for offline replay
| Property | Value |
|---|---|
| Workflow File | .github/workflows/release.yml |
| Trigger | Push tags (v*), Manual dispatch |
| Duration | ~8 min |
| Node.js Version | node-version: 26 |
| Secrets | NPM_TOKEN |
| Quality Gate | Full test suite passes, attestations generated |
Jobs:
prepare → build → release
Job Details:
| Job | Permissions | Key Steps |
|---|---|---|
| prepare | contents: write |
Version extraction, tsc --noEmit, full test suite, TypeDoc generation, coverage reports, commit docs to repo |
| build | contents: read, id-token: write, attestations: write |
npm run build, npm pack, zip creation, SPDX JSON SBOM generation, GitHub Attestations API |
| release | contents: write, id-token: write |
Download artifacts, draft release notes, create GitHub Release, npm publish --provenance |
Release Process:
sequenceDiagram
participant Dev as Developer
participant GH as GitHub Actions
participant NPM as npm Registry
participant API as GitHub API
Dev->>GH: Push v* tag
GH->>GH: Prepare (type-check, test, docs)
GH->>GH: Build (tsc, npm pack, zip)
GH->>API: Generate build attestation
GH->>GH: Generate SPDX JSON SBOM
GH->>API: Create GitHub Release + changelog
GH->>NPM: npm publish --provenance
NPM-->>GH: Published with SLSA provenance
GH->>API: Upload release artifacts (zip, SBOM)
Artifact Signing:
| Artifact | Method | Verification |
|---|---|---|
| npm package | --provenance flag (Sigstore) |
npm audit signatures |
| Build artifacts | GitHub Attestations API | gh attestation verify |
| SBOM | SPDX JSON with attestation | gh attestation verify |
| Release | GitHub Release with checksums | SHA256 hash comparison |
Note: SBOM generation is integrated into the
test-and-report.ymlandrelease.ymlworkflows. There is no standalonesbom-generation.ymlworkflow file, andslsa-provenance.ymldoes not produce an SBOM. Every push/PR produces a SPDX-JSON SBOM viatest-and-report.yml(with an SBOMQS quality gate), and every tagged release produces an attested SPDX-JSON SBOM attached to the GitHub Release viarelease.yml.
SBOM Creation in CI and Release Pipelines:
| Property | Value |
|---|---|
| Workflow Files | .github/workflows/test-and-report.yml (PR/push quality gate), .github/workflows/release.yml (release artifact + attestation) |
| Trigger | Push, PR (test-and-report.yml); Tag push (v*), Manual dispatch (release.yml) |
| Duration | Included in the ~3 min build-validation job and the ~8 min release workflow |
| Quality Gate | SBOMQS quality score ≥7.0/10 (enforced in test-and-report.yml) |
| Format | SPDX 2.3 JSON (via anchore/sbom-action with format: spdx-json) + GitHub Attestations on release |
| Permissions | contents: write, id-token: write, attestations: write (release only) |
SBOM Process:
test-and-report.yml generates a SPDX-JSON SBOM via anchore/sbom-action on every push and PR, then scores it with SBOMQS and fails the build if the average score falls below 7.0/10. release.yml generates the same SPDX-JSON SBOM at release time, produces a GitHub SBOM attestation (actions/attest-sbom), attaches the .spdx.json and .spdx.json.intoto.jsonl attestation bundle to the GitHub Release, and uploads them as release assets that are verifiable via gh attestation verify.
| Property | Value |
|---|---|
| Workflow File | .github/workflows/slsa-provenance.yml |
| Trigger | Push tags (v*), Release (published), Manual |
| Duration | ~4 min |
| Quality Gate | SLSA Level 3 provenance verified |
| Permissions | contents: write, id-token: write, attestations: write, actions: read |
Jobs:
build → provenance → verify → publish-npm (release only)
SLSA Level 3 Requirements:
| SLSA Requirement | Implementation | Evidence |
|---|---|---|
| Build as code | GitHub Actions workflow definition | .github/workflows/slsa-provenance.yml |
| Hermetic build | No network access during build step | Harden-runner egress audit |
| Isolated build | GitHub-hosted Ubuntu 26.04 runners | Ephemeral VMs per run |
| Parameterless | No user-controlled build parameters | Workflow inputs validated |
| Provenance | Signed SLSA v1.0 provenance document | slsa-github-generator output |
| Verification | Checksums + attestation verification | gh attestation verify |
| Property | Value |
|---|---|
| Workflow File | .github/workflows/scorecard.yml |
| Trigger | Push to main, Weekly (Tuesday 07:20 UTC), branch_protection_rule |
| Duration | ~3 min |
| Quality Gate | Target score ≥8.0/10 |
| Permissions | security-events: write, id-token: write, contents: read, actions: read |
Scorecard Checks Evaluated:
| Check | Description | Target |
|---|---|---|
| Branch-Protection | Enforce reviews, status checks | ✅ Enabled |
| CI-Tests | CI runs on PRs | ✅ Active |
| Code-Review | PRs require review | ✅ Required |
| Dangerous-Workflow | No pull_request_target misuse |
✅ Clean |
| Dependency-Update-Tool | Dependabot or Renovate | ✅ Dependabot |
| Maintained | Recent commits and activity | ✅ Active |
| Pinned-Dependencies | SHA256-pinned actions | ✅ All pinned |
| SAST | Static analysis enabled | ✅ CodeQL |
| Security-Policy | SECURITY.md present |
✅ Published |
| Signed-Releases | Provenance on releases | ✅ SLSA L3 |
| Token-Permissions | Minimal token permissions | ✅ Scoped |
| Vulnerabilities | No known CVEs | ✅ Monitored |
| Property | Value |
|---|---|
| Workflow File | .github/workflows/refresh-stats.yml |
| Trigger | Weekly (Monday 06:00 UTC cron), Manual dispatch |
| Duration | ~5 min |
| Node.js Version | node-version: 26 |
| Permissions | contents: write |
Purpose:
The refresh-stats.yml workflow is an agentic GitHub workflow that automatically refreshes precomputed European Parliament statistics in src/data/generatedStats.ts. It fetches live counts from the EP Open Data Portal API, validates both raw and computed statistics, and commits updates on successful validation. This is an example of the Continuous AI pattern — automated intelligence gathering with validation guardrails.
Jobs:
| Job | Purpose | Key Steps |
|---|---|---|
| refresh-stats | Refresh EP stats | Check out repo, setup Node.js 26.x, install deps, run refresh script, validate stats, commit if changed |
Workflow Features:
- Agentic execution: Autonomous weekly data refresh without human intervention
- Validation gates: Validates raw EP API counts + computed statistics before commit
- Idempotent: Commits only if stats have actually changed
- Rollback safe: Uses standard git commit workflow — errors can be reverted via Git
| Property | Value |
|---|---|
| Workflow File | .github/workflows/setup-labels.yml |
| Trigger | Manual dispatch (workflow_dispatch) |
| Duration | ~1 min |
| Input | recreate_all (boolean) — destructively recreate all labels |
Features:
- Creates 50+ standardized labels with consistent colors and descriptions
- Categories: features, bugs, MCP-specific, EP-specific, infrastructure, testing, security, docs, dependencies, priorities, sizes
- Validates labeler configuration compatibility
- Optional destructive recreation mode
| Property | Value |
|---|---|
| Workflow File | .github/workflows/copilot-setup-steps.yml |
| Trigger | workflow_call (reusable workflow) |
| Duration | ~2 min |
| Node.js Version | node-version: 26 |
Setup Steps:
- Checkout repository with full history
- Cache APT packages and npm modules
- Setup Node.js 26.x with npm cache
- Install global MCP servers (
@modelcontextprotocol/server-filesystem,-memory,-sequential-thinking,@playwright/mcp) - Install project dependencies (
npm ci) - Verify all MCP server installations
Workflows are tuned for fast, reproducible builds and graceful degradation when external registries (npm, GitHub Releases, OS mirrors) experience transient failures.
Rule: exactly one cache statement per logical artifact. Never stack
actions/cacheon top ofactions/setup-node's built-in cache for the same path.
| Cache | Mechanism | Path | Where | Why |
|---|---|---|---|---|
| npm package cache | actions/setup-node@v6.4.0 with cache: "npm" (built-in) |
~/.npm |
All Node-based workflows | Official, automatically keyed on package-lock.json + Node major version, automatically pruned. No extra actions/cache step required. |
| TypeScript build output | actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 |
dist/ |
test-and-report.yml (build-validation) |
Reuses prior dist/ output across workflow runs with identical inputs and skips npm run build on cache hit. |
Pinned cache action (the only explicit one in the repo):
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5| Property | Value | Rationale |
|---|---|---|
| Version prefix | build-v2-… |
Bumping the prefix atomically expires every old cache entry (cheap rotation / forced invalidation). |
| Runner OS | ${{ runner.os }} |
Linux/macOS binaries are not interchangeable. |
| Node major | node${{ env.NODE_VERSION }} |
Conservative runtime-compatibility and policy-driven invalidation signal when the workflow Node major changes. |
| Lockfile hash | ${{ hashFiles('**/package-lock.json') }} |
Dep changes invalidate dependent caches. |
| Source hash | ${{ hashFiles('src/**/*.ts', 'tsconfig*.json') }} |
Source or compiler-config change invalidates the build cache. |
| Restore-keys | Cascading prefixes | Allows partial reuse when only the source hash changed. |
- name: Cache build artifacts
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: dist
key: build-v2-${{ runner.os }}-node${{ env.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('src/**/*.ts', 'tsconfig*.json') }}
restore-keys: |
build-v2-${{ runner.os }}-node${{ env.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}-
build-v2-${{ runner.os }}-node${{ env.NODE_VERSION }}-- GitHub-managed eviction — Actions cache entries expire automatically after 7 days of no read access and the repository pool is capped at 10 GB (least-recently-used eviction).
- Forced invalidation — bump the
build-v2-prefix tobuild-v3-to expire every existing build cache entry on the next run. - Lockfile-driven invalidation — every
package-lock.jsonchange produces a new key; old entries fall off naturally.
| Failure Mode | Mitigation |
|---|---|
| npm registry slow / flaky | Workflow-level env: NPM_CONFIG_FETCH_RETRIES=5, NPM_CONFIG_FETCH_RETRY_MINTIMEOUT=20000, NPM_CONFIG_FETCH_RETRY_MAXTIMEOUT=120000, NPM_CONFIG_FETCH_TIMEOUT=300000. Native npm honours these on every fetch. |
npm install hangs |
copilot-setup-steps.yml wraps every npm install -g in timeout 300 and a 3-attempt retry with exponential backoff. The local npm ci is wrapped in timeout 600 + 3 attempts. |
| Playwright / browser binary download fails | @playwright/mcp is installed via the resilient retry wrapper; browser binaries are downloaded lazily on first use (no eager npx playwright install at setup time, eliminating a known flaky step). |
| GitHub Releases asset (sbomqs) download fails | curl --fail --retry 5 --retry-delay 5 --retry-max-time 120 --connect-timeout 30 --max-time 180. |
| OS package mirror (apt) failure | No apt installs are required by the current pipeline. Any future apt step must use sudo apt-get update -o Acquire::Retries=5 && sudo apt-get install -y --no-install-recommends … per the resilience policy below. |
| Concurrent runs piling up | knip.yml uses concurrency.cancel-in-progress per ref; recommended for any new fast-feedback workflow. |
Whenever a workflow downloads or installs anything from an external host:
- Bound the operation — wrap with
timeout <seconds>so a hung process cannot occupy the runner. - Retry on failure — at least 3 attempts with exponential backoff (e.g.
sleep $((attempt * 10))). - Use registry-native retry knobs when available (
NPM_CONFIG_FETCH_RETRIES,curl --retry,apt -o Acquire::Retries). - Pin to a SHA / version (no floating tags).
- Document the install in
WORKFLOWS.mdso reviewers can audit the supply-chain entry point.
- Removed 6 redundant
actions/cacheblocks for~/.npmfromrelease.yml(×3) andtest-and-report.yml(×3). They duplicatedactions/setup-node's built-in npm cache and could cause cache-restore races / wasted storage. - Replaced
npm installwithnpm ciintest-and-report.yml'sprepareandunit-testsjobs (lockfile-faithful, deterministic). - Hardened the
sbomqsdownload with explicitcurlretries / timeouts. - Added workflow-level npm fetch-retry env to every Node workflow.
- Added retry + timeout wrappers around all global MCP server installs in
copilot-setup-steps.yml.
graph LR
subgraph "Layer 1: Runner Hardening"
H1["🔒 step-security/harden-runner<br>Egress audit mode"]
end
subgraph "Layer 2: Action Pinning"
H2["📌 SHA256-pinned actions<br>No mutable tag references"]
end
subgraph "Layer 3: Least Privilege"
H3["🔑 Scoped permissions<br>read-all default"]
end
subgraph "Layer 4: Secret Management"
H4["🔐 GitHub OIDC<br>No long-lived tokens"]
end
subgraph "Layer 5: Audit Trail"
H5["📊 Egress monitoring<br>Step Security dashboard"]
end
H1 --> H2 --> H3 --> H4 --> H5
style H1 fill:#e74c3c,stroke:#c0392b,color:#fff
style H2 fill:#e67e22,stroke:#d35400,color:#fff
style H3 fill:#f1c40f,stroke:#d4ac0f,color:#333
style H4 fill:#2ecc71,stroke:#27ae60,color:#fff
style H5 fill:#3498db,stroke:#2980b9,color:#fff
| Control | Implementation | Workflows Applied | Evidence |
|---|---|---|---|
| Runner Hardening | step-security/harden-runner with egress audit |
All 11 workflows | Egress audit logs |
| Action Pinning | All actions pinned to full SHA256 commit hash | All 11 workflows | No @v* tag references |
| Least Privilege | permissions: read-all default, scoped per job |
All 11 workflows | Workflow YAML audit |
| OIDC Authentication | GitHub OIDC for npm publish (no stored tokens) | release.yml, slsa-provenance.yml |
id-token: write |
| Secret Scoping | Secrets scoped to specific jobs/environments | release.yml, integration-tests.yml |
Job-level secret access |
| Egress Monitoring | Outbound connection tracking and alerting | All 11 workflows | Step Security dashboard |
| SARIF Upload | Security findings uploaded to GitHub Security tab | codeql.yml, scorecard.yml |
Code scanning alerts |
| Attestation Signing | Sigstore-backed artifact attestations | release.yml, slsa-provenance.yml |
gh attestation verify |
| Secret | Used In | Purpose | Rotation |
|---|---|---|---|
NPM_TOKEN |
release.yml, slsa-provenance.yml |
npm registry publish | On rotation schedule |
CODECOV_TOKEN |
integration-tests.yml |
Coverage upload | Auto-managed |
GITHUB_TOKEN |
All workflows | Repository access (auto-generated) | Per-workflow run |
| # | Gate | Tool | Threshold | Required | Workflow |
|---|---|---|---|---|---|
| 1 | TypeScript compilation | tsc --noEmit |
0 errors | ✅ Yes | test-and-report.yml |
| 2 | Linting | ESLint 10.x | 0 errors, 0 warnings | ✅ Yes | test-and-report.yml |
| 3 | Unused code detection | Knip | 0 unused exports | ✅ Yes | knip.yml (dedicated), test-and-report.yml (build-validation) |
| 4 | Unit tests | Vitest | All tests pass | ✅ Yes | test-and-report.yml |
| 5 | Code coverage | Vitest coverage (v8) | ≥80% lines | test-and-report.yml |
|
| 6 | License compliance | license-checker |
MIT, Apache-2.0, BSD, ISC only | ✅ Yes | test-and-report.yml |
| 7 | SBOM quality | SBOMQS | ≥7.0/10 | ✅ Yes | test-and-report.yml |
| 8 | Security analysis | CodeQL | No high/critical findings | ✅ Yes | codeql.yml |
| 9 | Dependency review | GitHub Dependency Review | No known vulnerabilities | ✅ Yes | dependency-review.yml |
| 10 | Integration tests | Vitest (E2E) | All tests pass | ✅ Yes | integration-tests.yml |
| 11 | npm audit | npm audit |
No moderate+ vulnerabilities | ✅ Yes | integration-tests.yml |
| # | Check | Frequency | Tool | Target |
|---|---|---|---|---|
| 1 | OpenSSF Scorecard | Weekly | ossf/scorecard-action |
≥8.0/10 |
| 2 | SLSA Provenance | Per release | slsa-framework/slsa-github-generator |
Level 3 |
| 3 | SBOM Generation | Per release | Syft (Anchore) | Quality ≥7.0 |
| 4 | Vulnerability Scan | Per release | Grype | No critical CVEs |
| 5 | Attestation Verification | Per release | gh attestation verify |
All pass |
| Control | Requirement | Workflow Implementation | Evidence |
|---|---|---|---|
| A.8.9 | Configuration Management | setup-labels.yml — standardized repository configuration |
Label inventory, labeler config |
| A.8.25 | Secure Development Lifecycle | test-and-report.yml — automated build, lint, test pipeline |
Test reports, coverage data |
| A.8.26 | Application Security Requirements | codeql.yml — SAST scanning with CWE coverage |
SARIF reports, security alerts |
| A.8.27 | Secure System Architecture | dependency-review.yml — dependency vulnerability scanning |
PR review comments |
| A.8.28 | Secure Coding | test-and-report.yml + knip.yml — ESLint, type checking, Knip unused-code detection |
Lint reports, Knip job summaries, build logs |
| A.8.31 | Separation of Development, Test, Production | release.yml — tagged releases with provenance |
Release artifacts, npm provenance |
| A.8.33 | Test Information | integration-tests.yml — comprehensive test suite (unit, integration, E2E) |
Test reports, coverage data |
| A.14.2.8 | System Security Testing | codeql.yml + scorecard.yml — weekly security scans |
SARIF, Scorecard results |
| Function | Category | Subcategory | Workflow Implementation |
|---|---|---|---|
| GOVERN (GV) | GV.SC | Supply Chain Risk Management | scorecard.yml, dependency-review.yml — supply chain monitoring |
| IDENTIFY (ID) | ID.AM-2 | Software Inventory | test-and-report.yml, release.yml — SPDX JSON SBOM generation with SBOMQS quality gate |
| PROTECT (PR) | PR.DS-6 | Integrity Checking | slsa-provenance.yml — SLSA Level 3 build provenance |
| PROTECT (PR) | PR.DS-1 | Data-at-Rest Protection | release.yml — signed artifacts with attestations |
| DETECT (DE) | DE.CM-8 | Vulnerability Scanning | codeql.yml — weekly SAST, dependency-review.yml — PR dep scan |
| RESPOND (RS) | RS.AN-5 | Processes Established | All workflows — automated CI/CD pipeline with quality gates |
| Control | Safeguard | Workflow Implementation | Measurement |
|---|---|---|---|
| 2.1 | Establish Software Inventory | test-and-report.yml, release.yml — SPDX JSON SBOM with SBOMQS scoring and attestation |
SBOM quality score ≥7.0 |
| 2.2 | Ensure Authorized Software | dependency-review.yml — license + vulnerability check |
Blocked PRs with violations |
| 4.1 | Establish Secure Configuration | test-and-report.yml — ESLint security rules, type checking |
Zero lint errors |
| 7.1 | Establish Vulnerability Management | codeql.yml + scorecard.yml — continuous scanning |
SARIF findings, Scorecard ≥8.0 |
| 16.1 | Establish Application Security Process | All CI workflows — automated DevSecOps pipeline | Pipeline pass rate |
| 16.6 | Use Standard Security Features | slsa-provenance.yml — Sigstore signing, attestations |
SLSA Level 3 verified |
| 16.12 | Implement Code-Level Security Checks | codeql.yml — SAST with CWE coverage |
Zero high/critical findings |
| Document | Description | Link |
|---|---|---|
| Future Workflows | CI/CD pipeline evolution roadmap | FUTURE_WORKFLOWS.md |
| Architecture | C4 system architecture and design | ARCHITECTURE.md |
| Security Architecture | Security controls and defense-in-depth | SECURITY_ARCHITECTURE.md |
| Threat Model | STRIDE-based threat analysis | THREAT_MODEL.md |
| CRA Assessment | EU Cyber Resilience Act conformity | CRA-ASSESSMENT.md |
| Developer Guide | Local development setup and testing | DEVELOPER_GUIDE.md |
| Local Testing | Running tests locally | LOCAL_TESTING.md |
| Integration Testing | Integration test documentation | INTEGRATION_TESTING.md |
| Performance Guide | Performance optimization and benchmarks | PERFORMANCE_GUIDE.md |
| Secure Development Policy | ISMS development guidelines | Secure_Development_Policy.md |
| Open Source Policy | ISMS open source governance | Open_Source_Policy.md |
| Documentation Portal | Generated API docs, coverage, test reports | hack23.github.io |
Built with ❤️ by Hack23 AB
CI/CD pipeline documentation for European Parliament MCP Server v0.6.2 — aligned with ISO 27001, NIST CSF 2.0, and CIS Controls v8.1