CI/CD Setup
UIGraph CLI is designed for non-interactive CI/CD runs.
Recommended flow
- Pull requests:
uigraph-cli sync --dry-run - Main branch:
uigraph-cli sync - Tag pushes:
uigraph-cli release
sync and release are separate jobs with different triggers. Keep them separate — a
release job that also runs sync re-syncs the whole catalog on every tag for no reason,
and a sync job that runs on tags records nothing on the timeline.
Pointing the job at your gateway
Every job needs a gateway as well as a token. The examples below store
UIGRAPH_GATEWAY_URL next to UIGRAPH_TOKEN, which is what you want for a self-hosted
gateway.
On hosted UIGraph you can drop that variable and add --enterprise to each command
instead:
run: uigraph-cli sync --enterprise
See Gateway URL for how the two options interact.
GitHub Actions
name: UIGraph Sync with Dry Run on PR
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
uigraph-sync:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: stable
- name: Install UIGraph CLI
run: GOBIN=/usr/local/bin go install github.com/uigraph-oss/uigraph-cli@latest
- name: UIGraph Sync (dry-run on PR)
if: github.event_name == 'pull_request'
env:
UIGRAPH_TOKEN: ${{ secrets.UIGRAPH_TOKEN }}
UIGRAPH_GATEWAY_URL: ${{ secrets.UIGRAPH_GATEWAY_URL }}
run: uigraph-cli sync --dry-run
- name: UIGraph Sync
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
env:
UIGRAPH_TOKEN: ${{ secrets.UIGRAPH_TOKEN }}
UIGRAPH_GATEWAY_URL: ${{ secrets.UIGRAPH_GATEWAY_URL }}
run: uigraph-cli sync
Recording releases on tags
uigraph-cli release records one release event on the service timeline at the moment
the tag is cut, when the notes and the commit range are freshest. Add tags to the
trigger and gate the two jobs on the ref type:
name: UIGraph
on:
push:
branches: [main]
tags: ['v*']
jobs:
uigraph-sync:
if: startsWith(github.ref, 'refs/heads/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: stable
- name: Install UIGraph CLI
run: GOBIN=/usr/local/bin go install github.com/uigraph-oss/uigraph-cli@latest
- name: UIGraph Sync
env:
UIGRAPH_TOKEN: ${{ secrets.UIGRAPH_TOKEN }}
UIGRAPH_GATEWAY_URL: ${{ secrets.UIGRAPH_GATEWAY_URL }}
run: uigraph-cli sync
uigraph-release:
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
# `release` reads the previous tag and the commit range between it and
# this one, so it needs the full history, not the default shallow clone.
fetch-depth: 0
- uses: actions/setup-go@v5
with:
go-version: stable
- name: Install UIGraph CLI
run: GOBIN=/usr/local/bin go install github.com/uigraph-oss/uigraph-cli@latest
- name: Record release on the UIGraph timeline
env:
UIGRAPH_TOKEN: ${{ secrets.UIGRAPH_TOKEN }}
UIGRAPH_GATEWAY_URL: ${{ secrets.UIGRAPH_GATEWAY_URL }}
run: uigraph-cli release
fetch-depth: 0 is not optional. Without it there are no tags to read and no previous
tag to diff against, so the version cannot be resolved and the notes fall back to
nothing.
If your pipeline runs release, omit timeline.releases.changelogPath from
.uigraph.yaml. Both write the same event and would overwrite each other — see
Timeline and Releases.
Repository examples:
examples/ci-cd/github-actions.ymlexamples/ci-cd/github-actions-advanced.yml
GitLab CI
Use a job image that includes Go (for example the official golang image), then install the CLI with go install—same module as in GitHub Actions.
default:
image: golang:bookworm
before_script:
- GOBIN=/usr/local/bin go install github.com/uigraph-oss/uigraph-cli@latest
uigraph-dry-run:
stage: test
script:
- uigraph-cli sync --dry-run
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
uigraph-sync:
stage: deploy
script:
- uigraph-cli sync
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH == "master"
uigraph-release:
stage: deploy
variables:
# `release` needs the full history to resolve the previous tag.
GIT_DEPTH: 0
script:
- uigraph-cli release
rules:
- if: $CI_COMMIT_TAG
Define UIGRAPH_TOKEN and UIGRAPH_GATEWAY_URL under Settings → CI/CD → Variables (mask the token, and protect it if needed). On older GitLab versions you can replace rules with only / except equivalents.
Repository example:
examples/ci-cd/gitlab-ci.yml
Token scopes
The service-account token behind UIGRAPH_TOKEN needs a scope per surface it writes. A
missing scope turns that step's request into a 403, and the CLI stops there with exit
code 2 — steps that already ran are applied, everything after them is not. Grant every
scope the config needs before the first real run.
| Scope | Needed for |
|---|---|
services:write | Service record, APIs, dependencies, diagrams, databases, queries, test packs, test cases, docs |
maps:write | Maps, frames, focal points, and component links |
billing:write | costTags |
timeline:write | timeline events and uigraph-cli release |
mlstudio:write | ml projects, models, experiments, and runs |
Grant only the scopes the repository's .uigraph.yaml actually uses.
Best practices
- Store
UIGRAPH_TOKENin CI secret managers. - Keep
.uigraph.yamland referenced files in the same repo. - Run dry-run in every PR to catch config and path errors early.
- Prefer repository-pinned examples over copied snippets when onboarding teams.