Foxglider — the delivery-view theme for the Metaphor org — a Konstruct Theme that
renders a read-only dashboard of GitLab build metadata: every project in every
group your token can see, with pipeline timelines, per-pipeline stage/job
gantts, and a cross-project activity feed. Every element deep-links to the
corresponding GitLab page. Borrows the Konstruct theme architecture (embedded
static frontend + tiny Go server) without using any theme-rpc operations.
Grew from a seed. Forked from
civo/konstruct/theme-foxglider, org-pinned tocivo/metaphor. On top of foxglider's read-only pipeline dashboard it now adds the Delivery view — the metaphor supply chain (microcharts → themetaphor-macroumbrella → what's delivered to dev-33) with drift detection, which is the data-plane half ofcivo/metaphor/metaphor#37. Still ahead in #37: guarded pipeline-trigger buttons (releases/promotions from the UI, with preconditions).
- Delivery (default) — the supply chain: each service's base→bundled
microchart version, the umbrella's published RC, and the delivered version per
environment with an up-to-date / N behind drift badge. Sibling umbrellas
sharing the charts monorepo are auto-discovered and get full cards (picker,
bundle, hotfix, release); group projects that publish charts outside any
umbrella render as
independentservice tiles. - Fleet — per-project pipeline timelines across the org.
- Activity — merged, filterable event stream.
| endpoint | returns |
|---|---|
GET /api/ecosystem |
the metaphor supply chain: services (base + bundled chart versions + latest pipeline), the metaphor-macro umbrella (base + published RC tag), and per-environment delivered version with drift |
GET /api/meta |
theme build version + connection scope (unguarded, so the version badge always renders) |
GET /api/overview |
groups → projects, each with its 20 newest pipelines |
GET /api/projects/{id}/pipelines |
recent pipelines for one project |
GET /api/pipelines/{pid}/{plid} |
pipeline detail: stages + jobs with timings |
GET /api/activity?hours=24 |
merged newest-first events (pipelines, pushes, MRs, issues, comments) |
The ecosystem topology (which repos are services, the umbrella, and the delivery
targets) lives in defaultTopology() in eco.go.
All GitLab access is GET-only. List-row duration_s approximates
updated_at − created_at; exact durations come from the detail endpoint.
| var | default | meaning |
|---|---|---|
GITLAB_HOST |
https://gitlab.com |
GitLab base URL |
GITLAB_TOKEN |
(required) | read_api-scoped token; never sent to the browser |
GITLAB_GROUPS |
civo/metaphor |
comma-separated group paths to scope; any non-metaphor install must set this |
TOPOLOGY |
metaphor's supply chain | JSON {services, macro, delivery} describing the org's micros, umbrella, and delivery targets — see topologyJSON in eco.go. Any non-metaphor install must set this; an invalid value falls back loudly in the logs. Optional macros: [] declares sibling umbrellas in the same charts repo (each with its own name/file/tagPrefix/delivery) — anything you don't declare, discovery finds |
DISCOVERY |
(on) | off disables auto-discovery entirely — only the declared topology renders |
DISCOVERY_EXCLUDE |
(unset) | comma-separated chart/repo short names discovery must ignore (noisy umbrella dirs, chart-publishing repos that aren't real services) |
GITLAB_ACTION_TOKEN |
(unset) | write-scoped bot token (group token, api); unset hides every action button — the dashboard is then read-only |
ACTION_ACTOR |
konstruct |
fallback attribution when the konstruct shell doesn't communicate a session identity |
GITLAB_TOKEN_DELIVERY |
(unset) | second read client used only for delivery app files that live outside the groups the primary token can read (e.g. a platform gitops repo) |
per-target token_envs |
(unset) | each TOPOLOGY delivery target may name its own credential env (e.g. GITLAB_TOKEN_DELIVERY_W, GITHUB_TOKEN_SAAS); a missing one renders that env card as "credentials pending" — nothing breaks, nothing is guessed |
PORT |
8080 |
listen port |
THEME_STATIC_DIR |
(embedded) | serve the frontend from disk instead of the embedded copy (dev) |
Without a token the API answers 503 {"error": …} and the UI shows an
explicit "Not connected to GitLab" state — there is no sample data.
Installing as a Konstruct ThemedApp: put these in the ThemedApp's
spec.env. Name every credential with TOKEN or SECRET in it — the
theme-operator routes credential-shaped names through the <app>-env
Secret via secretKeyRef; anything else is rendered as plaintext env in a
committed gitops manifest. Edit env on the ThemedApp CR only — the operator
reconciles the Secret from it and overwrites direct Secret edits.
go run ./cmd/fakegitlab # canned GitLab on :9911
GITLAB_HOST=http://localhost:9911 GITLAB_TOKEN=dev go run .go test -race ./...