mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-06 00:02:13 +00:00
feat: open gitlab merge requests and post diff previews on them
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75
This commit is contained in:
co-authored by
Claude Opus 5
parent
bb071efd7c
commit
900d482721
@@ -0,0 +1,99 @@
|
||||
# Git sync with GitLab
|
||||
|
||||
GitLab has no equivalent of a GitHub App, so there is nothing to install and no
|
||||
consent screen. What Windmill needs instead is one credential you create in
|
||||
GitLab and paste once. With it, a GitLab repository gets the same managed
|
||||
features an app-backed GitHub repository has: instant pull over a webhook, merge
|
||||
requests opened on deploy, and a diff preview posted onto the merge request.
|
||||
|
||||
## The credential
|
||||
|
||||
Create a **group access token** on the group that owns the project (Settings →
|
||||
Access tokens), or a **group service account** and a personal access token for
|
||||
it. Either one is a bot identity that outlives the person who created it, which
|
||||
is what you want for a credential the instance uses unattended.
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| Scope | `api` |
|
||||
| Role | Developer to push deploy branches; **Maintainer** to also manage the webhook and open merge requests |
|
||||
| Expiry | Required for a group access token; a group service account PAT can be non-expiring on self-managed (see below) |
|
||||
|
||||
The `api` scope is what makes the token rotatable, so Windmill can renew it
|
||||
before it expires. A `write_repository`-only token can still push, but Windmill
|
||||
cannot inspect or renew it and reports that in the workspace's git sync settings.
|
||||
|
||||
## Connecting a repository
|
||||
|
||||
In the resource form for a `git_repository` resource, use the **GitLab** button:
|
||||
paste the instance URL and the token, pick a project from the list, and Windmill
|
||||
stores the whole remote URL, credential included, in a **secret variable** and
|
||||
points the resource at it (`"url": "$var:u/you/gitlab_group_project_url"`).
|
||||
|
||||
The variable indirection is what makes renewal possible: when Windmill rotates
|
||||
the token it rewrites that one variable, and everything referencing it keeps
|
||||
working. A URL pasted directly into the resource also syncs, but nothing can
|
||||
renew it.
|
||||
|
||||
## Expiry and renewal
|
||||
|
||||
Windmill reads `expires_at` from the token itself and shows it on the repository
|
||||
in the workspace's git sync settings. Within three weeks of expiry it rotates the
|
||||
token through GitLab's own `POST /personal_access_tokens/self/rotate`, writes the
|
||||
replacement back to the variable, and verifies it. Only the token can rotate
|
||||
itself, so a token without `api` (or `self_rotate`) is a permanent warning rather
|
||||
than something Windmill can fix.
|
||||
|
||||
Rotation is deliberately never retried. GitLab revokes the old token the instant
|
||||
it issues the replacement, and presenting an already-rotated token to `/rotate`
|
||||
again is treated as reuse: it revokes **the whole token family, including the
|
||||
live replacement**. So a rotation that succeeded at GitLab but failed to persist
|
||||
is surfaced as an error to act on, not retried.
|
||||
|
||||
Non-expiring tokens are possible only for a **group service account PAT** on
|
||||
self-managed, with `require_personal_access_token_expiry` turned off in the
|
||||
instance's application settings. A group access token is always rejected without
|
||||
an `expires_at`.
|
||||
|
||||
## What each managed feature needs
|
||||
|
||||
| Feature | Needs |
|
||||
| --- | --- |
|
||||
| Instant pull | A project hook Windmill creates, so Maintainer; and a Windmill base URL GitLab can reach |
|
||||
| Merge requests on deploy | Developer, plus the `api` scope |
|
||||
| Diff preview on a merge request | The project hook, plus permission to post commit statuses and merge request notes |
|
||||
|
||||
Instant pull falls back to checking the tracked branch about every minute when
|
||||
the hook cannot be created or delivered, so nothing silently stops syncing.
|
||||
|
||||
## Self-managed differences
|
||||
|
||||
**Webhooks to a private network are blocked by default.** GitLab refuses to
|
||||
create a hook pointing at a private or local address until an administrator
|
||||
enables *Allow requests to the local network from webhooks and integrations*
|
||||
(Admin → Settings → Network → Outbound requests,
|
||||
`allow_local_requests_from_web_hooks_and_services`). A Windmill instance on the
|
||||
same private network as GitLab needs this; without it, hook creation fails with a
|
||||
"blocked" error and the repository keeps polling.
|
||||
|
||||
Everything else is identical: Windmill talks to `<your-gitlab>/api/v4` and needs
|
||||
no inbound access of its own beyond the hook deliveries.
|
||||
|
||||
## Commit statuses create a pipeline
|
||||
|
||||
GitLab has no separate check-run concept. Windmill's `Windmill diff` and
|
||||
`Windmill` statuses are **commit statuses**, and posting one creates an `external`
|
||||
pipeline on the project. Two consequences:
|
||||
|
||||
- A project with *Pipelines must succeed* set will not let a merge request merge
|
||||
while a Windmill status is still running, and will block it if the status
|
||||
failed. Windmill therefore always drives a status it created to a terminal
|
||||
state, and reports an informational result (for example "3 changes to deploy")
|
||||
as success rather than leaving it pending.
|
||||
- `allow_failure` is ignored on the commit-status endpoint, so a Windmill status
|
||||
cannot be made advisory. If you do not want it gating merges, turn the diff
|
||||
preview off rather than expecting it to be non-blocking.
|
||||
|
||||
A commit status carries only a name, a 255-character description and a link, so
|
||||
the diff itself goes in a merge request note that Windmill keeps up to date, and
|
||||
the status links to the job.
|
||||
Reference in New Issue
Block a user