SpecVault Docs

GitLab CI

Publish your OpenAPI spec to SpecVault automatically from a GitLab CI/CD pipeline.

Prerequisites

  • A SpecVault API token (see API Tokens)
  • The service ID for the API you want to publish

Store secrets in GitLab

In your GitLab project, go to Settings → CI/CD → Variables and add:

  • SPECVAULT_TOKEN — set as Masked so it never appears in job logs
  • SPECVAULT_SERVICE_ID — the service ID from SpecVault
  • SPECVAULT_URL — your SpecVault instance URL

Complete .gitlab-ci.yml example

This configuration adds a publish-spec job that runs after a successful deploy, only on the main branch:

stages:
  - test
  - deploy
  - publish

test:
  stage: test
  image: python:3.12
  script:
    - pip install -r requirements.txt
    - pytest

deploy:
  stage: deploy
  script:
    - ./scripts/deploy.sh
  only:
    - main

publish-spec:
  stage: publish
  image: alpine/curl
  script:
    - |
      curl -sf -X POST \
        "${SPECVAULT_URL}/api/services/${SPECVAULT_SERVICE_ID}/specs" \
        -H "Authorization: Bearer ${SPECVAULT_TOKEN}" \
        -H "Content-Type: application/json" \
        -d "{\"spec_url\": \"${API_BASE_URL}/openapi.json\"}"
  only:
    - main
  needs:
    - deploy

Uploading a spec file

If your CI build generates the spec as an artifact, use the file upload form:

publish-spec:
  stage: publish
  image: alpine/curl
  script:
    - |
      curl -sf -X POST \
        "${SPECVAULT_URL}/api/services/${SPECVAULT_SERVICE_ID}/specs" \
        -H "Authorization: Bearer ${SPECVAULT_TOKEN}" \
        -F "file=@build/openapi.yaml"
  artifacts:
    paths:
      - build/openapi.yaml
  only:
    - main

Tip: Use needs: [deploy] to ensure the spec is published only after a successful deploy, not just after tests pass. This way SpecVault always reflects what's actually running in production.

Publishing on tags only

For release-based publishing rather than every push to main:

publish-spec:
  stage: publish
  image: alpine/curl
  script:
    - |
      curl -sf -X POST \
        "${SPECVAULT_URL}/api/services/${SPECVAULT_SERVICE_ID}/specs" \
        -H "Authorization: Bearer ${SPECVAULT_TOKEN}" \
        -H "Content-Type: application/json" \
        -d "{\"spec_url\": \"${API_BASE_URL}/openapi.json\"}"
  only:
    - tags

Using alpine/curl keeps the publish job fast — it's a tiny image with just curl installed, no Python runtime needed.