Skip to content

feat(gitlab): system hooks, project allowlist, internal URL, encrypted secrets (v0.9.47) - #135

Merged
Liewzheng merged 1 commit into
mainfrom
feat/system-hooks
Sep 1, 2026
Merged

feat(gitlab): system hooks, project allowlist, internal URL, encrypted secrets (v0.9.47)#135
Liewzheng merged 1 commit into
mainfrom
feat/system-hooks

Conversation

@Liewzheng

Copy link
Copy Markdown
Owner

Summary

One admin-level GitLab System Hook now drives reviews for every project on an instance, with per-platform project filtering, dual-network (external/internal) URLs, and secrets encrypted at rest.

What's in

Feature Detail
System Hook support X-Gitlab-Event: System Hook routed by event type — GitLab 19+ sends event_type, older versions event_name (both supported). Payload URL extraction falls back project.web_urlproject.homepagerepository.homepageobject_attributes.url (system-hook payloads carry no project.web_url).
Project allowlist allowedProjects per platform; non-listed projects get 200 ignored; hot-effective via PUT /config.
Internal URL internalBaseUrl (optional): payload URL (external) matches the platform for verification; internal URL (container-reachable) is used for review-time GitLab API fetches. Falls back internal → base_url → payload URL.
Encrypted secrets token/webhook secrets encrypted at rest (enc: prefix, ChaCha20-Poly1305, secrets.key 0600); legacy plaintext auto-migrates on next save.
env/CLI deprecation ui-state.toml authoritative; GITLAB_TOKEN/GITLAB_WEBHOOK_*/flags are fallback-only with deprecation warnings.

Verification (per user requirement: local E2E BEFORE PR)

Full chain verified against a local GitLab EE 19.2.4 Docker testbed with a real MR:

  1. Admin system hook → signed request → verification OK (signing token)
  2. event_type routing → MR dispatch (this exposed a real bug: GitLab 19.2 sends event_type, not event_name — fixed with fallback)
  3. internal URL rewrite → MR info + diff fetched via host.docker.internal:8929 (exposed another real bug: payload external_url is unreachable from the reng container — fixed)
  4. Full 11-expert review ran → CodeReview Board + inline notes posted back to the MR
  5. Allowlist hot-apply: allowedProjects=[other/project]MR hook ignored: project not in allowlist; restored → review runs again (dispatcher dedup on same SHA)
  6. Encrypted at rest confirmed: ui-state.toml now carries enc: values, secrets.key 0600

Checks

  • cargo fmt --check / cargo clippy --all-targets --all-features: clean
  • cargo test (single-threaded): 1548 passed, 0 failed (9 new system-hook tests, 6 internal-URL tests, encryption roundtrip/migration tests, allowlist tests)
  • Self-review via review-engine: consensus reached; findings triaged (fragment/SSRF/subpath edges are config-trust model or pre-existing, no code change)
  • Frontend: vue-tsc + vite build clean

…d secrets (v0.9.47)

One admin-level GitLab System Hook now drives reviews for every project on
an instance, with per-platform project filtering and dual-network URLs.

System Hook support:
- X-Gitlab-Event: System Hook payloads are routed by event type
  (GitLab 19+ sends event_type; older versions event_name; event_name
  preferred), mapping merge_request/note/push to the existing handlers.
- Instance-URL extraction falls back project.web_url -> project.homepage
  -> repository.homepage -> object_attributes.url, since system-hook
  payloads carry no project.web_url; MR/Note handlers read the full MR
  URL from object_attributes.url.
- Verified end-to-end against GitLab EE 19.2.4 (local Docker testbed):
  signed system hook -> verification -> routing -> full 11-expert review
  -> notes posted back to the MR.

Project allowlist (allowedProjects / allowed_projects):
- path_with_namespace allowlist gates webhook-triggered MR/Note reviews;
  non-listed projects get 200 {"status":"ignored",...}. Hot-effective
  via PUT /config, no restart. Empty = all projects. REST gitlab_mr
  routing unaffected.

Dual-network URLs (internalBaseUrl / internal_base_url):
- base_url (external) identifies the instance for webhook verification;
  the optional internal URL is used for review-time GitLab API fetches
  (container-reachable endpoint, e.g. host.docker.internal or an in-net
  NAS address) where the external port-mapped URL is unreachable. Falls
  back internal -> base_url -> payload URL.

Encrypted secrets at rest:
- token/webhook_secret/webhook_signing_secret encrypted in ui-state.toml
  as enc:<base64(nonce||ct||tag)> (ChaCha20-Poly1305) under a per-config
  secrets.key (32B, 0600, auto-created). Legacy plaintext loads
  transparently and is encrypted on next save; missing key on encrypted
  values is a hard error pointing at re-entry in the Web UI.

env/CLI deprecation:
- ui-state.toml is the authoritative source for GitLab credentials;
  GITLAB_TOKEN/GITLAB_WEBHOOK_*/--gitlab-* are fallback-only (used only
  when the file lacks a value) with deprecation warnings.

Docs: integrations/gitlab.md (System Hook + filtering + internal URL),
configuration.md, config-schema.md, faq.md, rest-api.md. Frontend:
allowed projects + internal URL fields, 6 locales.
@Liewzheng
Liewzheng merged commit 5786e19 into main Sep 1, 2026
7 checks passed
@Liewzheng
Liewzheng deleted the feat/system-hooks branch September 1, 2026 04:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant