Saltar al contenido principal

Wiedii — Branch Protection Policy (GitLab)

Configurar en GitLab → Settings → Repository → Protected branches, tanto para main como para develop:

Ajustemaindevelop
Allowed to push and mergeMaintainersMaintainers
Allowed to merge (MRs)Developers + MaintainersDevelopers + Maintainers
Required approvals (min 1)
Dismiss stale MR approvals
Require status checks (pipelines) to pass
Require branch up to date
Allow force pushes
Allow deletions

Qué logra esta configuración — push directo: solo mantenedores:

  • Los mantenedores del proyecto (rol Maintainer) pueden hacer push directo a main y develop, además de mergear MRs.
  • El resto del equipo (Developers) NO puede hacer push directo: debe integrar cambios vía Merge Request. Sí pueden mergear MRs aprobados (la regla "nadie fusiona su propio MR" sigue vigente).
  • Nadie puede force-push ni borrar las ramas protegidas.

Aun teniendo permiso, se recomienda que los mantenedores usen MR para cambios no triviales (revisión + CI). El push directo queda para casos puntuales (hotfix operativo, sync, corrección menor).

GitLab → Settings → General → Merge Requests:

  • ✅ Allow merge commits (for --no-ff)
  • ❌ Allow squash merging — DISABLED
  • ❌ Allow rebase merging — DISABLED

Nota sobre CE vs Premium

Las Approval Rules avanzadas (múltiples reglas, "Require Code Owner approval" forzado por sección) y CODEOWNERS son features Premium/Ultimate. En CE se cubre con:

  • Política operativa documentada explícita: "nadie mergea su propio MR; un MR que toque /docs/05-seguridad/ requiere visto bueno escrito del equipo de Seguridad".
  • Pipeline CI/CD valida cada cambio antes de permitir merge.
  • Required approvals (min 1) en la protección de rama garantiza revisión antes de merge.

Ver ci-caching para el pipeline.

Aplicar la protección al crear el repo (bloque copy-paste, CE-safe)

Al crear un repo, un humano con permisos de Maintainer/Owner aplica la protección el mismo día, tras el primer push (la rama debe existir). Es un bloque que se pega y se revisa antes de ejecutar (confirm-by-construction) — no una automatización que corra un agente ni una receta fleet-wide, porque POST .../protected_branches da 409 sobre una protección existente y la variante idempotente DELETE-luego-POST deja una ventana en la que main queda desprotegida. Solo campos CE (sin reglas de aprobación EE/Premium, sin CODEOWNERS, sin allowed_to_* por usuario — eso se cubre con política operativa + CI gate):

# Reemplazar :id por el project id o el path URL-encoded (p.ej. wildcat%2Fmi-repo)
glab api -X POST "projects/:id/protected_branches" -f name=main \
-f push_access_level=40 -f merge_access_level=40 -f allow_force_push=false
glab api -X PUT "projects/:id" -f merge_method=merge -f squash_option=never \
-f remove_source_branch_after_merge=true \
-f only_allow_merge_if_all_discussions_are_resolved=true
# Git Flow (repos con develop): repetir el POST para name=develop
glab api -X POST "projects/:id/protected_branches" -f name=develop \
-f push_access_level=40 -f merge_access_level=40 -f allow_force_push=false

push_access_level=40 / merge_access_level=40 = rol Maintainer (40); merge_method=merge + squash_option=never fuerzan --no-ff sin squash. /audit-project verifica este estado (detector de drift, solo lectura) pero no lo aplica — la aplicación necesita permisos que un dev normal no tiene. La reconciliación fleet-wide como config-as-code (Terraform provider GitLab) es un tema de Infra, fuera del plugin.