Skip to main content

Docker & CI/CD

Praman's CI/CD pipeline runs on GitHub Actions with a 3-OS matrix, Docker support for containerized test execution, and comprehensive quality gates.

GitHub Actions CI Pipeline​

The CI workflow (.github/workflows/ci.yml) runs on every push to main and every pull request. It consists of 6 parallel jobs:

Job Overview​

+--------------------+     +-------------------------+     +-----------------+
| quality | | unit-tests | | build |
| (lint, typecheck, | | (3 OS x 3 Node) | | (3 OS) |
| spell, deadcode, | | ubuntu/windows/macos | | ESM + CJS + DTS |
| markdown lint) | | Node 20/22/24 | | attw, size-limit|
+--------------------+ +-------------------------+ +-----------------+
| |
+-------------------------+-------------------------------+
|
+--------------v--------------+
| integration-tests |
| (PW 1.50.0, PW 1.58.2) |
| SAP cloud auth via secrets |
+-----------------------------+

+--------------------+ +-------------------------+
| security | | docs-check |
| (npm audit) | | (TypeDoc + Docusaurus) |
+--------------------+ +-------------------------+

3-OS Matrix (Unit Tests)​

Unit tests run across a full OS and Node.js matrix:

strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [20, 22, 24]

This produces 9 test runs (3 OS x 3 Node versions) to catch platform-specific issues early.

Quality Job​

- run: npm run lint # ESLint with 10 plugins, 0 errors/warnings
- run: npm run typecheck # tsc --noEmit (strict mode)
- run: npx cspell "src/**/*.ts" "docs/**/*.md" --no-progress # Spell check
- run: npx knip # Dead code detection
- run: npx markdownlint-cli2 "**/*.md" # Markdown lint

Build Job​

- run: npm run build # tsup: ESM + CJS + DTS
- run: node -e "const m = require('./dist/index.cjs'); ..." # CJS smoke test
- run: npx size-limit # Bundle size check
- run: npm run check:exports # attw: validate all 6 export maps

Integration Tests​

Integration tests run against SAP cloud systems with Playwright version matrix:

strategy:
matrix:
playwright-version: ['1.50.0', '1.58.2']
env:
SAP_CLOUD_BASE_URL: ${{ secrets.SAP_CLOUD_BASE_URL }}
SAP_CLOUD_USERNAME: ${{ secrets.SAP_CLOUD_USERNAME }}
SAP_CLOUD_PASSWORD: ${{ secrets.SAP_CLOUD_PASSWORD }}

Security Scan​

- run: npm audit --audit-level=high

Documentation Validation​

- run: npx typedoc --validation # TypeDoc API docs
- run: npm run build -- --no-minify # Docusaurus site build (in docs/)

Azure Playwright Workspaces (Optional)​

Triggered manually or by adding the azure-test label to a PR:

- run: npx playwright test --config=playwright.service.config.ts --workers=20
env:
PLAYWRIGHT_SERVICE_URL: ${{ secrets.PLAYWRIGHT_SERVICE_URL }}

npm run ci Breakdown​

The local npm run ci command chains all quality gates:

npm run ci
# Equivalent to:
# npm run lint && npm run typecheck && npm run test:unit && npm run build
StepCommandPurpose
Linteslint src/ tests/ --max-warnings=010 ESLint plugins, zero tolerance
Typechecktsc --noEmitTypeScript strict mode validation
Unit testsvitest runHermetic unit tests with Vitest
BuildtsupDual ESM + CJS output with type declarations

Additional quality commands available:

CommandPurpose
npm run test:unit -- --coverageUnit tests with V8 coverage
npm run check:exportsValidate all 6 sub-path exports with attw
npm run format:checkPrettier formatting check
npm run spellcheckCSpell spell checking
npm run deadcodeKnip dead code detection
npm run mdlintMarkdown lint

Docker for Running Tests​

Dockerfile for Test Execution​

Create a Dockerfile for running Praman tests in a container:

FROM mcr.microsoft.com/playwright:v1.50.0-noble

WORKDIR /app

# Copy package files and install
COPY package.json package-lock.json ./
RUN npm ci

# Copy source and test files
COPY . .

# Build the project
RUN npm run build

# Install Playwright browsers
RUN npx playwright install --with-deps chromium

# Default: run all tests
CMD ["npm", "run", "test:integration"]

Running Tests in Docker​

# Build the test image
docker build -t praman-tests .

# Run integration tests
docker run --rm \
-e SAP_CLOUD_BASE_URL="https://your-sap-system.example.com" \
-e SAP_CLOUD_USERNAME="testuser" \
-e SAP_CLOUD_PASSWORD="secret" \
praman-tests

# Run only unit tests
docker run --rm praman-tests npm run test:unit

# Run with coverage
docker run --rm -v $(pwd)/coverage:/app/coverage \
praman-tests npm run test:unit -- --coverage

Docker Compose for Local SAP Mock​

For local development with a mock SAP backend:

# docker-compose.yml
services:
sap-mock:
image: node:20-slim
working_dir: /app
volumes:
- ./tests/mocks/odata-server:/app
command: node server.js
ports:
- '4004:4004'
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:4004/health']
interval: 5s
timeout: 3s
retries: 5

tests:
build: .
depends_on:
sap-mock:
condition: service_healthy
environment:
- SAP_CLOUD_BASE_URL=http://sap-mock:4004
- SAP_CLOUD_USERNAME=mock-user
- SAP_CLOUD_PASSWORD=mock-pass
volumes:
- ./playwright-report:/app/playwright-report
- ./test-results:/app/test-results

Run the full stack:

# Start mock server and run tests
docker compose up --build --abort-on-container-exit

# View test results
open playwright-report/index.html

Security Practices in CI​

All GitHub Actions use SHA-pinned action references:

- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4

Additional security measures:

  • permissions: contents: read (minimal permissions)
  • concurrency groups prevent duplicate runs
  • cancel-in-progress: true for PRs
  • SAP credentials stored as GitHub Secrets, never in code
  • npm audit --audit-level=high in every CI run

Coverage Reporting​

Coverage artifacts are uploaded per-matrix entry for comparison:

- uses: actions/upload-artifact
with:
name: coverage-${{ matrix.os }}-node-${{ matrix.node-version }}
path: coverage/

Coverage thresholds are enforced per-file (not just project-wide):

TierScopeStatementsBranches
Tier 1Error classes100%100%
Tier 2Core infrastructure95%90%
Tier 3All other modules90%85%