kolm / integrations / GitLab CI
kolm in GitLab CI.
Three reference .gitlab-ci.yml snippets: verify-on-MR, release-with-binder, scheduled quarterly re-verify. Each one wires kolm into your existing GitLab project, blocks merges on K-score regression, posts receipts as MR notes, and ships signed artifacts to GitLab releases. Works on GitLab.com and self-managed.
Workflow 1 . verify on MR
Block merges on K-score regression.
Drop this in .gitlab-ci.yml. When a merge request touches a recipe, the pipeline compiles, signs, verifies, and posts a receipt as an MR note. The merge button is blocked if any artifact misses its K-score floor (the compile step exits non-zero).
Add a project CI/CD variable named KOLM_API_KEY (Settings → CI/CD → Variables; masked, protected). Add GITLAB_API_TOKEN as a project access token with api scope so the MR-note step can post.
stages: [verify] verify: stage: verify image: node:20 rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' changes: ["recipes/**/*"] variables: KOLM_BACKEND: local_cpu script: - npm install -g kolm - mkdir -p artifacts - | for r in recipes/*.recipe.json; do name=$(basename "$r" .recipe.json) kolm compile --from "$r" --out "artifacts/${name}.kolm" kolm verify "artifacts/${name}.kolm" done - | # post a single MR note with the receipts BODY="" for rc in artifacts/*.receipt.json; do K=$(node -e "console.log(require('./'+process.argv[1]).k_score)" "$rc") C=$(node -e "console.log(require('./'+process.argv[1]).cid)" "$rc") BODY="${BODY}\n**$(basename $rc)** . K=${K} . CID \`${C}\`" done curl -sf -X POST \ -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \ -H "Content-Type: application/json" \ -d "{\"body\":\"${BODY}\"}" \ "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}/notes" artifacts: when: always paths: ["artifacts/*.kolm", "artifacts/*.receipt.json"] expire_in: 30 days
Workflow 2 . release with binder
Ship a one-page audit PDF with every tag.
On a tag push, attach the .kolm, the receipt, and a single-page binder PDF that lists CID + recipe + base model + K-score to a GitLab release. The PDF is what your auditor signs.
stages: [build, release] build_release: stage: build image: node:20 rules: - if: '$CI_COMMIT_TAG' script: - npm install -g kolm - mkdir -p out - | for r in recipes/*.recipe.json; do name=$(basename "$r" .recipe.json) kolm compile --from "$r" --out "out/${name}.kolm" kolm verify "out/${name}.kolm" --binder "out/${name}.binder.pdf" done artifacts: paths: ["out/*.kolm", "out/*.receipt.json", "out/*.binder.pdf"] expire_in: never publish_release: stage: release image: registry.gitlab.com/gitlab-org/release-cli:latest needs: [build_release] rules: - if: '$CI_COMMIT_TAG' script: - echo "Publishing release ${CI_COMMIT_TAG}" release: tag_name: '$CI_COMMIT_TAG' name: 'Release $CI_COMMIT_TAG' description: 'Signed kolm artifacts + binder PDFs. Verify with `kolm verify *.kolm`.' assets: links: - name: 'kolm artifacts (zip)' url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/download' link_type: package
Workflow 3 . scheduled re-verify
Re-verify last-quarter's artifacts on a schedule.
Quarterly pipeline that re-runs kolm verify against every artifact in releases/. If a verifier-side change ever rejects an artifact you previously shipped, you find out before your auditor does. Configure the schedule in GitLab UI: Build → Pipeline schedules → New schedule, cron 0 4 1 */3 *, ref main.
stages: [reverify] reverify: stage: reverify image: node:20 rules: - if: '$CI_PIPELINE_SOURCE == "schedule"' script: - npm install -g kolm - | fails=0 for art in releases/**/*.kolm; do if ! kolm verify "$art"; then echo "FAIL: $art" >&2 fails=$((fails+1)) fi done if [ "$fails" -gt 0 ]; then echo "$fails artifact(s) failed re-verify" >&2 exit 1 fi artifacts: when: on_failure paths: ["releases/**/*.receipt.json"] expire_in: 90 days