019 — Pull request mode on a GitLab release remote (#73)

Status: shipped (v0.20.0)

Why

Pull request mode (stories 005, 006, 008) opens and reads the release's pull request through the Forgejo API, so a project that declares maturity: {code: 1} with a GitLab release remote is refused by tp check ("pull request mode needs a Forgejo release remote; origin is gitlab") and by tp release in Gather. A GitLab environment has a GITLAB_TOKEN (what glab and goreleaser read) and the same merge request API shape; nothing in the mode is Forgejo-specific beyond the client that talks to the forge.

What changes

  • internal/forge: a GitLab client, GitLabRepo, speaks the subset of the GitLab REST API v4 that pull request mode and the roadmap step need: branch protection, merge requests (list, get, create), issues (list, close/reopen, comment) and the release page URL. Nested groups (group/subgroup/project) are the URL-encoded project path. The token goes in the PRIVATE-TOKEN header.
  • forge.Forge.APIToken and TokenHint are forge-aware: a GitLab remote reads token_env when set, else GITLAB_TOKEN. Forgejo keeps its chain (CODEBERG_APIKEY, FORGEJO_TOKEN, GITEA_TOKEN).
  • tp release Gather: maturity.code 1 or more accepts a Forgejo or a GitLab release remote; an undeclared GitLab project with a protected base branch gets pull request mode too, as Forgejo does. The vocabulary stays "pull request" in tp's output; GitLab calls it a merge request.
  • tp check: the maturity.code finding accepts GitLab, and names GITLAB_TOKEN as the token_env to set when no token is found.
  • docs/release-workflow.md mode table and README config comments.

Acceptance

Release remote maturity.code Token tp check tp release Gather
GitLab 1 token_env set ok: pull request mode on origin (token_env X) pull request mode
GitLab 1 GITLAB_TOKEN set, no token_env ok: pull request mode on origin (token from the default chain) pull request mode
GitLab 1 neither error: set token_env on the release remote origin (e.g. GITLAB_TOKEN) error: pull request mode needs a forge token for origin (consulted: GITLAB_TOKEN)
GitLab 0, base protected any — pull request mode (base is protected)
GitLab 0, base unprotected any — direct
GitHub 1 any error: needs a Forgejo or GitLab release remote; origin is github error, as before
GitLab API tp
GET /projects/:path/repository/branches/:name → protected BranchProtected
GET /projects/:path/merge_requests?state=all&per_page=50&page=N ListPullRequests: iid → Number, source_branch → Head, target_branch → Base, web_url → URL; state opened → open, merged → closed + Merged, closed/locked → closed; all pages
POST /projects/:path/merge_requests {source_branch, target_branch, title, description} CreatePullRequest
GET /projects/:path/issues?state=all&per_page=50&page=N ListIssues: iid, opened → open, labels as names, ascending by number
PUT /projects/:path/issues/:iid {state_event: close/reopen} SetState("closed"/"open")
POST /projects/:path/issues/:iid/notes {body} AddComment: author is author.username, URL is the issue's web_url#note_<id>
non-2xx error gitlab API <method> <status>: <message>, token redacted
ReleaseURL(v) https://<host>/<path>/-/releases/<v>

Out of scope

  • tp issue, tp story issue and tp roadmap on GitLab: they resolve the tracker through ForgejoRepoFor and stay Forgejo-only. The roadmap step of the release reads whatever the release forge lists, so it works on GitLab once stories carry GitLab issue numbers.
  • Passing a token_env other than GITLAB_TOKEN to goreleaser: it reads GITLAB_TOKEN itself, and that is the default.
  • CI_JOB_TOKEN authentication (the JOB-TOKEN header) for releases run from a GitLab pipeline.
  • GitHub pull request mode.

Decisions

none

Done when

  • tests express the acceptance table and pass
  • spec updated (docs/release-workflow.md, README)
  • changelog entry
  • issue closed with a link to the release