TheoWorks

CI integration

A validated, indexed, traceable build on every push, and a static requirements viewer (plus PDF) published straight from CI — reviewers need nothing installed.

What your pipeline needs to provide

TheoWorks reads your project through a needs.json your own Sphinx build produces — it does not need a TheoWorks-specific build step to see your content. Add needs_build_json = True to conf.py (see Project setup → Your schema), then build normally and publish the output directory as a job artifact:

yaml
build-docs:
  stage: build
  image: python:3.12
  script:
    - pip install sphinx sphinx-needs
    - sphinx-build -b html docs _build/html
  artifacts:
    paths:
      - _build/html

needs.json lands at _build/html/needs.json — one of the paths the hosted/self-hosted editor searches for it. Keeping the Sphinx build's own output separate from public/ (below) matters once the pages job starts writing its own site there. The remaining jobs below are optional additions on top of this one.

Set the CLI image once

Define the CLI image once, as a CI variable, and have every job reference the variable — never the raw registry path. There are two variables, not one: publish needs a headless browser to render the site and PDF, which would roughly double the size of the slim image every other job uses, so it ships as a separate image variant.

yaml
variables:
  THEOWORKS_CLI_IMAGE: "public.ecr.aws/d9m2o0n8/theoworks-cli:v0.9.27"
  THEOWORKS_CLI_PUBLISH_IMAGE: "public.ecr.aws/d9m2o0n8/theoworks-cli-publish:v0.9.27"

Validate

Fails the job when validation finds an error (a missing required field or link, an illegal status).

yaml
validate:
  stage: test
  image: $THEOWORKS_CLI_IMAGE
  script:
    - theoworks validate "$CI_PROJECT_DIR"

Trace (optional report)

Writes a traceability/coverage report as a job artifact, without gating the pipeline.

yaml
trace:
  stage: test
  image: $THEOWORKS_CLI_IMAGE
  script:
    - theoworks trace "$CI_PROJECT_DIR" --json trace-report.json
  artifacts:
    paths:
      - trace-report.json

Build the index

Builds the compact index TheoWorks reads from, over the needs.json your build job produced.

yaml
theoworks-index:
  stage: index
  image: $THEOWORKS_CLI_IMAGE
  needs:
    - build-docs
  script:
    - theoworks build-index "$CI_PROJECT_DIR" --needs _build/html/needs.json --out theoworks-index/
  artifacts:
    paths:
      - theoworks-index/

build-index fingerprints the index against the pipeline it ran in (project, ref, pipeline id) by default, reading $CI_PROJECT_ID, $CI_COMMIT_REF_NAME and $CI_PIPELINE_ID — no extra flags needed in a GitLab CI job.

Publish the site and PDF

theoworks publish reads a theoworks.publish.toml in your project (all keys optional) and writes a static requirements site and/or a PDF:

toml
# theoworks.publish.toml
[scope]
documents = ["**/*.rst"]

[fields]
promote = ["id", "status", "priority"]

[output]
site  = true
dir   = "public"
theme = "read-render"

[output.pdf]
enabled     = true
format      = "A4"
granularity = "project"
yaml
pages:
  stage: deploy
  image: $THEOWORKS_CLI_PUBLISH_IMAGE
  needs:
    - build-docs
  script:
    - theoworks publish "$CI_PROJECT_DIR" --out public
  artifacts:
    paths:
      - public
  rules:
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'

The pages job name and the rules above are what GitLab Pages looks for: it publishes the public artifact from this job on your default branch. The PDF lands under the same --out directory alongside the site.

Pin the version

THEOWORKS_CLI_IMAGE and THEOWORKS_CLI_PUBLISH_IMAGE above both pin an explicit version (v0.9.27, not :latest) so your pipeline never silently picks up a breaking change — bump them together, deliberately, in a reviewed commit, when you want the new CLI.

Enterprise private image

The Enterprise edition's image is private — add a login step before the jobs above:

yaml
before_script:
  - echo "$THEOWORKS_REGISTRY_PASSWORD" | docker login --username AWS --password-stdin "$THEOWORKS_REGISTRY_HOST"

THEOWORKS_REGISTRY_HOST and THEOWORKS_REGISTRY_PASSWORD are provisioned per-entitlement.

Troubleshooting

  • Exit code 1 from validate — validation found an error; the job's own output lists which need and which rule.
  • Docker exit code 125, 126 or 127 — a container problem (bad image reference, entrypoint not executable, or command not found), not a TheoWorks finding — check the image reference and runner configuration.
  • "needs.json not found" — the path passed to --needs (_build/html/needs.json) does not match where your build job actually wrote it; check your sphinx-build output directory and the needs: dependency on the build job.
  • publish fails with a message about a missing node executable — the job is running the slim CLI image; use $THEOWORKS_CLI_PUBLISH_IMAGE for the pages job.

One complete pipeline

Everything above, composed into one file:

yaml
stages: [build, test, index, deploy]

variables:
  THEOWORKS_CLI_IMAGE: "public.ecr.aws/d9m2o0n8/theoworks-cli:v0.9.27"
  THEOWORKS_CLI_PUBLISH_IMAGE: "public.ecr.aws/d9m2o0n8/theoworks-cli-publish:v0.9.27"

build-docs:
  stage: build
  image: python:3.12
  script:
    - pip install sphinx sphinx-needs
    - sphinx-build -b html docs _build/html
  artifacts:
    paths:
      - _build/html

validate:
  stage: test
  image: $THEOWORKS_CLI_IMAGE
  script:
    - theoworks validate "$CI_PROJECT_DIR"

trace:
  stage: test
  image: $THEOWORKS_CLI_IMAGE
  script:
    - theoworks trace "$CI_PROJECT_DIR" --json trace-report.json
  artifacts:
    paths:
      - trace-report.json

theoworks-index:
  stage: index
  image: $THEOWORKS_CLI_IMAGE
  needs:
    - build-docs
  script:
    - theoworks build-index "$CI_PROJECT_DIR" --needs _build/html/needs.json --out theoworks-index/
  artifacts:
    paths:
      - theoworks-index/

pages:
  stage: deploy
  image: $THEOWORKS_CLI_PUBLISH_IMAGE
  needs:
    - build-docs
  script:
    - theoworks publish "$CI_PROJECT_DIR" --out public
  artifacts:
    paths:
      - public
  rules:
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'