GitLab Sync Architecture
GitLab's model differs from GitHub: repositories are organized into Groups and Subgroups. The sync architecture leverages this: the central rules repo lives in a dedicated group (e.g., gitlab.com/org/platform/ai-rules). Target repos are in their respective team groups. The CI pipeline: triggered by changes in the central repo, iterates over target repos listed in a manifest, and creates merge requests in each target repo with the updated rules.
GitLab-specific advantages: group-level CI/CD variables (store the access token once at the group level, all projects inherit it), GitLab API for merge request creation (native API, no external tools needed), and multi-project pipelines (trigger pipelines in downstream projects). These features: make the GitLab sync workflow slightly simpler than the GitHub equivalent.
The pipeline: defined in .gitlab-ci.yml in the central rules repo. Stages: generate (compose rules per target repo), compare (check if the target's rules differ from the generated version), and sync (create or update merge requests for repos with differences). The pipeline runs: on push to the default branch and on a weekly schedule for drift detection.
Step 1: Pipeline Configuration
The .gitlab-ci.yml: defines the sync job. Image: a lightweight image with git and curl (for GitLab API calls). Variables: RULES_TOKEN (a project access token or group access token with API and write_repository scope). Script: reads manifest.yml (list of target projects with their rule composition), generates the composed rules for each target, clones each target repo, compares the generated rules against the existing rules, and calls the GitLab API to create a merge request if they differ.
Manifest format (manifest.yml): a YAML file mapping each target project to its rule layers. Example: projects: - path: org/team-a/frontend, rules: [base.md, typescript.md, react.md]. - path: org/team-b/api-service, rules: [base.md, go.md]. - path: org/team-c/ml-pipeline, rules: [base.md, python.md]. The pipeline reads this manifest and generates the correct composed rules for each project.
Merge request creation: using the GitLab API (POST /api/v4/projects/:id/merge_requests). The MR: source branch (rules-update-v2.4.0), target branch (main or the project's default branch), title ('Update AI rules to v2.4.0'), description (changelog of what changed). If an MR already exists for this source branch: update it instead of creating a duplicate. AI rule: 'GitLab's API handles MR creation natively. No need for external tools like gh CLI. The pipeline script: curl calls to the GitLab API with the access token.'
GitHub Actions: you configure the sync token in each target repo's secrets (or use an organization secret). GitLab: store the token as a group-level CI/CD variable once. Every project in the group: inherits it. Add a new project to the group: it gets the token automatically. Rotate the token: update once at the group level, all projects use the new token. This is one of GitLab's genuine advantages for multi-repo management.
Step 2: Leveraging GitLab Group Features
Group-level variables: store the RULES_TOKEN as a group-level CI/CD variable. All projects in the group inherit it. No need to configure the token in each project individually. This simplifies: onboarding new repos (they inherit the token automatically) and token rotation (update once at the group level, all projects get the new token). AI rule: 'Group-level variables are the GitLab advantage for rule sync. One configuration point: serves all projects in the group.'
GitLab compliance frameworks: GitLab Premium/Ultimate supports compliance frameworks that can enforce pipeline configurations across projects. You can: require that all projects run the rule compliance check, enforce that the CLAUDE.md file exists and is not empty, and report compliance status to the group dashboard. AI rule: 'For GitLab Premium/Ultimate users: compliance frameworks add automated enforcement beyond the sync workflow. Projects that remove or empty their CLAUDE.md: flagged automatically.'
GitLab Pages for adoption dashboard: host an adoption dashboard as a GitLab Pages site in the central rules repo. The sync pipeline: generates an HTML report showing which projects have current rules, which have pending MRs, and which are outdated. The report: accessible at the GitLab Pages URL, updated on every sync run. AI rule: 'GitLab Pages for the adoption dashboard: no separate hosting needed. The dashboard lives alongside the rules in the central repo.'
A misconfigured token: causes every sync run to fail silently. The pipeline runs, attempts to push a branch, gets a 403, and logs an error that nobody reads. For weeks: rules are not syncing. Fix: before configuring the pipeline, test the token manually: curl --header 'PRIVATE-TOKEN: <token>' 'https://gitlab.com/api/v4/projects/<id>/repository/branches'. If it returns data: the token works. If 403: the token lacks permissions.
Step 3: Troubleshooting and Best Practices
Common issue 1 โ Token permissions: the access token needs API scope (for MR creation) and write_repository scope (for pushing branches). Without write_repository: the pipeline cannot push the rules-update branch to the target repo. Without API: the pipeline cannot create the MR. AI rule: 'Test the token manually (curl the GitLab API with the token) before configuring the pipeline. A token issue: causes every sync run to fail silently.'
Common issue 2 โ Protected branches: if the target repo's default branch is protected (requires approval): the MR is created but cannot be auto-merged. This is expected behavior โ the team must review and merge. For unprotected branches (development environments): auto-merge can be enabled in the MR creation API call. AI rule: 'Protected branches: the MR waits for team review. This is the desired behavior for production repos. Auto-merge: only for non-production repos where speed is prioritized over review.'
Best practice โ Schedule + trigger: run the sync on both: push to the central rules repo (immediate propagation of rule changes) and a weekly schedule (drift detection for repos where someone manually edited the rules file). The dual trigger: ensures rules are propagated quickly AND drift is caught within one week. AI rule: 'Push trigger: for immediate propagation. Schedule trigger: for drift detection. Both are needed. Push alone misses drift. Schedule alone delays propagation.'
Push trigger alone: rules propagate immediately when changed. But: someone manually edits CLAUDE.md in a target repo. The push trigger: does not detect this (no push to the central repo). Schedule trigger alone: drift is detected weekly. But: a rule change takes up to 7 days to propagate. Both triggers together: rule changes propagate immediately (push) AND drift is detected within one week (schedule). Each trigger: covers the other's blind spot.
GitLab CI Sync Summary
Complete GitLab CI rule sync setup.
- Architecture: central rules repo โ GitLab CI pipeline โ MRs to target repos
- Pipeline: .gitlab-ci.yml with generate โ compare โ sync stages
- Manifest: manifest.yml mapping projects to rule layers (base + language-specific)
- Auth: project or group access token with API + write_repository scope
- MR creation: GitLab API (curl). One active MR per target. Update existing if present
- Group features: group-level variables (one token config), compliance frameworks (enforcement)
- Dashboard: GitLab Pages site showing adoption status. Updated on every sync run
- Triggers: push to central repo (immediate) + weekly schedule (drift detection)