How to open a MR

The full contribution checklist — branch policy, MR template, CI gates, and merge rules.

Goal

Open a merge request (MR) against the upstream un/itu/genie-ai project on GitLab that passes CI on the first push and lands within a single review cycle.

Branch policy

RuleReason
One MR per logical changeEasier to revert, easier to bisect
Branch name: <type>/<scope>-<summary> (e.g. feat/admin-logs-tags, fix/mobile-i18n-crash, docs/clarify-rag-overrides)Consistent, greppable history
Base branch: main for features; release/X.Y for PATCHesTrunk-based for features; cherry-pick for fixes
Rebase before reviewNo Merge branch 'main' into ... noise in the diff
Squash-merge at landingOne commit per MR in main

Never push directly to main or release/*. Branch protection rejects the push.

MR template

GitLab auto-fills the template when you check the Description box. If it doesn’t, copy this:

## What & why
<!-- One paragraph: what the change does and why it's needed. -->

## How to test
<!-- Steps a reviewer can run to validate the change. -->
<!-- Include expected output for the non-obvious steps. -->

## Related
<!-- Closes #<issue>, relates to !<MR>, ... -->

## Checklist
- [ ] Lint passes locally (`npm run lint`, `npm run lint:py`, `npm run lint:dart`)
- [ ] Tests added / updated for the change
- [ ] Docs updated if user-facing behaviour changes
- [ ] `CHANGELOG.md` updated under `[Unreleased]` (use `Added` / `Changed` / `Fixed` / etc.)
- [ ] No secrets committed

CI gates (must pass before merge)

The pipeline stages run in this order. A merge is blocked if any mandatory stage fails.

#StageWhat it runsBlock on fail?
1lintESLint (JS), Ruff (Python), Prettier format checksyes
2testJest (backend, frontend, doc-repo), pytest (OPEA), flutter_test (mobile)yes
3configconfig:validate, config:changelog, verify:overlay-locks:*yes
4buildPublish candidate images to GitLab Container Registryyes
5scanTrivy container scanningyes
6contract-in-imageContract tests vs REAL vendored comps (run inside the built image)yes
7e2ePlaywright suite against deployed infrastructuremerge_train + scheduled
8promoteRetag tested digests to deployable tagsyes (main/tags)
9releaseCreate GitLab Release from changelogyes (tag pipelines only)

Merge rules

  • Squash-merge to keep main history one-commit-per-MR.
  • Title = conventional-commit subject (feat: …, fix: …, docs: …, chore: …, ci: …).
  • Delete the source branch after merge (the template does this automatically).
  • Backports to release/X.Y are cherry-picks — open a separate MR with the [BACKPORT] tag in the title.

Troubleshooting

SymptomLikely causeFix
MR pipeline stuck on pendingRunner offlineCheck glab ci status; ping a maintainer
lint fails on prettierUnformatted codenpm run format then re-push
test fails on a single test you didn’t touchFlaky test (most often backend supertest)Re-run the job; if persistent, fix the flake in a separate MR
verify:overlay-locks:retriever (or :reranker) failsgenie-ai-overlay/<module>/requirements-cpu.txt out of datecd genie-ai-overlay/<module> && make lock-<module> (requires uv); commit the regenerated requirements-cpu.txt
Reviewer requests changes after 5 daysNormal cadencePing a maintainer or self-merge after rebase