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 logsSPECVAULT_SERVICE_ID— the service ID from SpecVaultSPECVAULT_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.