Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

CI traceability gate

Run MarkSpec in CI to enforce traceability and format hygiene across the entire repository on every push and pull request.

A minimal CI gate runs three jobs in sequence:

fmt-check → check → (optional) lint

All three jobs consume no build artifacts — they operate on the committed source files only.

GitHub Actions

name: MarkSpec

on: [push, pull_request]

jobs:
  fmt-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install markspec
        run: curl -fsSL https://raw.githubusercontent.com/driftsys/markspec/main/install.sh | sh
      - name: Format check
        run: markspec fmt --check docs/**/*.md

  check:
    runs-on: ubuntu-latest
    needs: fmt-check
    steps:
      - uses: actions/checkout@v4
      - name: Install markspec
        run: curl -fsSL https://raw.githubusercontent.com/driftsys/markspec/main/install.sh | sh
      - name: Check
        run: markspec check docs/**/*.md

  lint:
    runs-on: ubuntu-latest
    needs: check
    steps:
      - uses: actions/checkout@v4
      - name: Install markspec
        run: curl -fsSL https://raw.githubusercontent.com/driftsys/markspec/main/install.sh | sh
      - name: Prose lint
        run: markspec lint docs/**/*.md

GitLab CI

stages:
  - quality

markspec-fmt:
  stage: quality
  script:
    - curl -fsSL https://raw.githubusercontent.com/driftsys/markspec/main/install.sh | sh
    - markspec fmt --check docs/**/*.md

markspec-check:
  stage: quality
  script:
    - markspec check docs/**/*.md
  needs: [markspec-fmt]

markspec-lint:
  stage: quality
  allow_failure: true   # lint is informational; remove to make it blocking
  script:
    - markspec lint docs/**/*.md
  needs: [markspec-check]

Exit codes

CodeMeaning
0Clean — no errors, no warnings
1Errors present — commit should be blocked
2Warnings only — informational; gate at your discretion

The check command exits 2 when only warnings are present. Use --strict to promote warnings to errors and make the gate fully binary:

markspec check --strict docs/**/*.md

Traceability report as CI artifact

Generate a coverage or traceability matrix and upload it as an artifact:

- name: Traceability report
  run: markspec report traceability docs/**/*.md --output traceability.md

- uses: actions/upload-artifact@v4
  with:
    name: traceability
    path: traceability.md

Caching the binary

Cache ~/.local/bin/markspec between runs to avoid downloading on every job. Bump the version in the cache key whenever you bump MARKSPEC_VERSION (or the “latest” you’re tracking), so the cache invalidates instead of serving a stale binary:

- uses: actions/cache@v4
  with:
    path: ~/.local/bin/markspec
    key: markspec-${{ runner.os }}-0.10.3

Caching upstream snapshots

markspec lock is the only step that touches the network for references: and dependencies: upstreams — check and compile read the pinned snapshots under .markspec/cache/upstreams/ entirely offline. Cache that directory between CI runs, keyed on the lockfile’s contents, so lock only re-acquires an upstream when its pin has actually moved:

- uses: actions/cache@v4
  with:
    path: .markspec/cache/upstreams
    key: markspec-upstreams-${{ hashFiles('markspec.lock') }}

With a warm cache, markspec lock is idempotent — it verifies each pinned snapshot’s hash and skips re-acquiring an upstream whose pin hasn’t moved.

See also: Multi-repo dependencies.