Skip to main content

CI/CD Setup

UIGraph CLI is designed for non-interactive CI/CD runs.

  • 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.yml
  • examples/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.

ScopeNeeded for
services:writeService record, APIs, dependencies, diagrams, databases, queries, test packs, test cases, docs
maps:writeMaps, frames, focal points, and component links
billing:writecostTags
timeline:writetimeline events and uigraph-cli release
mlstudio:writeml projects, models, experiments, and runs

Grant only the scopes the repository's .uigraph.yaml actually uses.

Best practices

  • Store UIGRAPH_TOKEN in CI secret managers.
  • Keep .uigraph.yaml and 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.