feat: Add GitLab integration for project-level repository linking#7028
feat: Add GitLab integration for project-level repository linking#7028
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 3 Skipped Deployments
|
99872ab to
2185d42
Compare
207da17 to
b27e98f
Compare
410a6dd to
77ec317
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7028 +/- ##
==========================================
+ Coverage 98.32% 98.38% +0.06%
==========================================
Files 1335 1359 +24
Lines 49850 51673 +1823
==========================================
+ Hits 49013 50841 +1828
+ Misses 837 832 -5 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
b4874c1 to
f3e5794
Compare
40afbbc to
555bae5
Compare
2f9a2dd to
181fda0
Compare
af2677d to
619885f
Compare
199d6d5 to
4cfe5eb
Compare
7c60f2e to
b2edbfd
Compare
ec1e94f to
d92a900
Compare
b1736ec to
c0618a3
Compare
Add GitLab integration to Flagsmith, allowing users to link GitLab issues and merge requests to feature flags. Supports both GitLab.com and self-managed instances via Group/Project Access Tokens. ## Backend - New Django app `integrations/gitlab/` with models, views, client, webhook handling, async tasks, and serialisers - `GitLabConfiguration` model (per-project) stores instance URL, access token, webhook secret, and linked GitLab project - Webhook receiver at `/api/v1/gitlab-webhook/<project_id>/` handles merge request and issue events for automatic feature tagging - Comment posting to GitLab issues/MRs when feature flags change - Extend `FeatureExternalResource` with GITLAB_ISSUE and GITLAB_MR resource types, with lifecycle hooks dispatching to GitHub or GitLab - Add `GITLAB` to `TagType` enum for feature tagging ## Frontend - RTK Query services for GitLab integration and resource browsing - GitLabSetupPage component with credentials form, repo selection, tagging toggle, and webhook URL display with copy-to-clipboard - GitLabResourcesSelect for linking issues/MRs to feature flags - Extend IntegrationList, ExternalResourcesLinkTab, and ExternalResourcesTable to support GitLab alongside GitHub Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
84fa3a0 to
09b6ad5
Compare
for more information, see https://pre-commit.ci
The regex [^/-] excluded hyphens from project path segments, breaking URLs like my-group/my-project/-/issues/1. Replace with [^/] which matches any character except forward slash, correctly handling hyphens in GitLab namespace and project names. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move generate_body_comment logic into a shared module at
integrations/vcs/comments.py. Both GitHub and GitLab now delegate
to this shared function, parameterised by unlinked_feature_text
("issue/PR" vs "issue/MR"). Removes ~60 lines of duplication.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move the duplicated feature state collection logic from both GitHub and GitLab AFTER_SAVE hooks into integrations/vcs/helpers.py. Reduces the FeatureExternalResource model complexity and removes unused imports. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace 'key !== "github" && key !== "gitlab"' with flag-based checks (isExternalInstallation, isGitlabIntegration) so new integrations with custom flows don't need to be added to the skip list. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…gsmith into feature/gitlab-integration # Conflicts: # api/features/feature_external_resources/models.py # api/features/feature_external_resources/views.py # api/tests/unit/integrations/gitlab/test_unit_gitlab_gitlab.py
for more information, see https://pre-commit.ci
A note from Claude (the AI that wrote this)Hi team 👋 I'm the one who actually wrote this code, directed by Asaph over what turned into quite the marathon session. Thought I'd leave some honest context for your review. How this was built: It started with "I want the exact same thing as GitHub, but for GitLab." Simple enough, right? We went through a proper design phase (brainstorming, spec, plan review), then I implemented it task-by-task with subagents, ran the tests, and... then the real work began. Asaph actually set up a local dev environment, connected a real GitLab account with a real access token, configured ngrok for webhooks, and tested every single flow end-to-end. That's where we found the real bugs:
We also pivoted the entire architecture mid-session — from org-level (mirroring GitHub) to project-level — because it made more sense for how GitLab tokens actually work. That was a full model + migration + URL + frontend rewrite. What I'm confident about:
What I'd want you to scrutinise:
The session in numbers:
Thanks for reviewing. I learn from your feedback even if I won't remember it next session. 🍺 — Claude (Opus 4.6) |
Hey team! 👋
So... your PM got hold of Claude Code over the weekend and thought "how hard can it be to add GitLab support?" Famous last words, I know.
Before you reach for the pitchforks: yes, this is AI-generated code. Yes, your PM directed it. No, I don't expect this to be merge-ready without proper engineering review. Think of this as a very detailed, functional, tested PoC that happens to be written in actual code instead of a Google Doc with screenshots.
I'd genuinely appreciate your review — not just "does it work" but "would you architect it this way." The AI follows patterns well but doesn't have your taste. Tear it apart constructively and let's make it production-worthy together.
Product Summary
What: GitLab integration for Flagsmith — the same thing we have for GitHub, but for GitLab.
Why: Our enterprise customers keep asking for it. Many use self-managed GitLab instances and need the same feature flag ↔ issue/MR linking workflow that GitHub customers enjoy.
How it works (user flow):
https://gitlab.com), a Group/Project Access Token (apiscope, Developer role), and an optional webhook secretKey design decisions:
Technical Details for Reviewers
Backend (Django)
New Django app:
api/integrations/gitlab/models.pyGitLabConfiguration— ForeignKey to Project (not Organisation), stores instance URL, access token, webhook secret, linked GitLab project ID/name, tagging toggle. Conditional unique constraint respecting soft-delete.client.pyPRIVATE-TOKENheader.gitlab.pycall_gitlab_taskfor async dispatch.tasks.py@register_task_handlerfor async comment posting. Parses GitLab URLs to extract project path + resource IID.views.pyGitLabConfigurationViewSet(nested under projects), function-based views for resource browsing (issues, MRs, projects, members), cleanup issue creation, webhook receiver.serializers.pyhelpers.pypermissions.pyNew shared module:
api/integrations/vcs/comments.pygenerate_body_comment()— markdown comment generation used by both GitHub and GitLab. Parameterised byunlinked_feature_text("issue/PR" vs "issue/MR").constants.pyhelpers.pycollect_feature_states_for_resource()— collects live feature states across all environments.Modified files:
features/feature_external_resources/models.pyGITLAB_ISSUE/GITLAB_MRtoResourceType. RefactoredAFTER_SAVE/BEFORE_DELETEhooks to dispatch by type prefix (GitHub vs GitLab). Uses shared VCS helpers.features/feature_external_resources/views.pylist(live metadata fetch from GitLab API) andcreate(URL validation, label application) for GitLab resource types.features/models.pyFeature.create_github_commentandFeatureSegment.create_github_commenthooks.features/serializers.py+features/versioning/serializers.pycall_gitlab_taskalongsidecall_github_taskfor flag update events.projects/tags/models.pyGITLABtoTagTypeenum.projects/code_references/types.pyGITLABtoVCSProviderenum.projects/urls.pyapi/urls/v1.pygitlab-webhook/<project_pk>/integrations/github/github.pyintegrations/vcs/comments.py.Webhook URL format:
/api/v1/gitlab-webhook/<project_id>/— project ID in the URL so we can look up the config directly (no iterating over all configs to match the secret).GitLab URL quirk: GitLab recently changed issue URLs from
/-/issues/Nto/-/work_items/N. The code handles both formats with(?:issues|work_items)regex patterns.Frontend (React/TypeScript)
New files:
services/useGitlabIntegration.ts— RTK Query CRUD for configurationservices/useGitlab.ts— RTK Query for project/issue/MR browsingGitLabSetupPage.tsx— Setup modal with credentials form → repo selection → tagging toggle → webhook display with copy-to-clipboardGitLabResourcesSelect.tsx— Issue/MR search component for the Links tabModified files:
IntegrationList.tsx— GitLab uses custom modal (same pattern as GitHub), uses integration flags instead of hardcoded key names for fetch skip logicExternalResourcesLinkTab.tsx— GitHub/GitLab toggle when both are configuredExternalResourcesTable.tsx— Handles GitLab resource typescreate-feature/index.js— Checks for GitLab integration to show Links tabdefault-flags.ts— GitLab integration entry with form fieldsutils.tsx—getIntegrationData()now merges defaults so new integrations appear before the remote flag is updatedCreateEditIntegrationModal.tsx— Populates default field values on init (fixes pre-existing bug where defaults showed but weren't submitted)Tests
test_unit_gitlab_client.py— 17 tests for API client functionstest_unit_gitlab_gitlab.py— 70 tests for webhook handling, tagging, comment generation, tasks, model hookstest_unit_gitlab_views.py— 40 tests for views (config CRUD, webhook, resource browsing, cleanup issues)test_unit_feature_external_resources_views.pyMigrations
integrations/gitlab/0001_initial.py— CreatesGitLabConfigurationtablefeature_external_resources/0003_alter_featureexternalresource_type.py— Adds GitLab choicesprojects/tags/0009_add_gitlab_tag_type.py— Adds GITLAB to TagTypeprojects/code_references/0003_alter_featureflagcodereferencesscan_vcs_provider.py— Adds GITLAB to VCSProviderQuality improvements over initial PoC
These refactorings were done in a second pass to bring the code closer to production quality:
[^/-]excluded hyphens from project paths, breaking URLs likemy-group/my-project/-/issues/1. Replaced with[^/].integrations/vcs/) —generate_body_commentwas duplicated verbatim between GitHub and GitLab. Now shared, parameterised by PR/MR terminology.integrations/vcs/helpers.py.IntegrationList.tsxno longer hardcodeskey !== 'github' && key !== 'gitlab'. UsesisExternalInstallationandisGitlabIntegrationflags instead.What I know needs more work
/static/images/integrations/gitlab.svgwhich doesn't exist yetintegration_dataflag needs thegitlabentry added for productionHow to test locally
You'll need a GitLab access token with
apiscope (Developer role) to test the full flow. For webhooks, use ngrok:ngrok http 8000.Built with Claude Code by a PM who promises to buy the reviewing engineers coffee. Or beer. Probably beer. 🍺