Gitlab Ci Quality Gates
ASecurityWires Cinetic's reusable GitLab CI/CD Components (gitlab.com/educlopezcinetic/ci-templates — lint, typecheck, test, semantic MR titles, agent guardrails, secret scanning, dependency audits) into a project's .gitlab-ci.yml, adds the stack's static-analysis job (PHPStan for PrestaShop, Larastan for Laravel — not yet a ci-templates component, wired repo-local), and configures branch protection + merge checks to match how the project is actually worked. Use when the user asks to "set up CI qualit...
- 3 stars
- 0 votes
- 0 copies
- 1 view
- Added September 23, 2026
Works with
Security analysis
100/100Pro scans all 5 files and shows the line behind each finding
npx -y skills add educlopez/mallard --skill gitlab-ci-quality-gates --agent claude-codeAre you the author of Gitlab Ci Quality Gates?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/educlopez-gitlab-ci-quality-gates)---
name: gitlab-ci-quality-gates
description: >
Wires Cinetic's reusable GitLab CI/CD Components
(gitlab.com/educlopezcinetic/ci-templates — lint, typecheck, test, semantic
MR titles, agent guardrails, secret scanning, dependency audits) into a
project's .gitlab-ci.yml, adds the stack's static-analysis job (PHPStan for
PrestaShop, Larastan for Laravel — not yet a ci-templates component, wired
repo-local), and configures branch protection + merge checks to match how
the project is actually worked. Use when the user asks to "set up CI
quality gates", "montar CI en este proyecto", "añadir ci-templates", wants
PHPStan/Larastan added, or wants MR-based branch protection on a GitLab
project. Covers PrestaShop, Laravel, Astro, and Next.js — add a new
reference file the same shape when another stack needs this, don't build
ahead of need. Distinct from
gitlab-security-setup (scheduled Trivy/pnpm supply-chain email report) and
ps-security-audit — this is about MR-time quality/security GATES, not
scheduled reports. Do NOT use for GitHub-hosted projects.
version: "0.4.0"
metadata:
author: Eduardo Calvo
---
# GitLab CI Quality Gates (ci-templates)
Wires the already-built, versioned components from
[`educlopezcinetic/ci-templates`](https://gitlab.com/educlopezcinetic/ci-templates)
into a project, plus the one piece that repo doesn't cover yet (PHP static
analysis), and sets branch protection to match how the project is really
worked. Validated end-to-end against `educlopezcinetic/prestashop-demo` and
`laravel-demo` (real deliberate-failure smoke tests for every gate, not just
"pipeline ran").
The stack-specific include blocks and static-analysis job live in
`references/` — this file is the shared decision tree and gotchas, identical
regardless of stack. Load the matching reference file for Step 1 and Step 2:
- `references/prestashop.md`
- `references/laravel.md`
- `references/astro.md`
- `references/nextjs.md`
- (No other stack references exist yet — add one following the same shape
when a new stack actually needs this, don't build ahead of need.)
## Step 0 — ask, don't assume: blocking or informational?
This is the one decision that changes everything else. Ask the user:
> "¿Este proyecto lo trabajás solo con hábito de PR, o el equipo mergea ramas
> directo a `test` sin MR?"
- **Solo / personal workflow, real PR habit** → gates are **blocking**.
Enable `only_allow_merge_if_pipeline_succeeds`, protect `test`/`main` with
push access "No one" (merge via MR only). This is the Eduardo-personal-project
case — see Step 3.
- **Team client project** (coworkers merge branches straight to `test`, no
MR habit yet) → gates are **informational only**. Do **NOT** enable
`only_allow_merge_if_pipeline_succeeds` and do **NOT** restrict push access
on `test`/`main` — that would silently block a coworker's normal workflow
the moment they push, with no warning, for a policy they never agreed to.
The pipeline still shows red/green on every push as a signal; it just never
blocks anything. Skip Step 3 entirely for this case.
Never flip a real client project to blocking without the user explicitly
confirming the whole team knows and is ready for it.
## Step 1 — wire the ci-templates components
Open the reference file matching the project's stack (`references/prestashop.md`
or `references/laravel.md`) for the exact `include:` block and `workflow:`
rules to use.
Always verify the current tag before wiring — do not assume the version in
the reference file is still latest:
```bash
glab api "projects/educlopezcinetic%2Fci-templates/repository/tags"
```
Check the `ci-templates` repo's own README for the current, authoritative
input list per component before wiring — it's the source of truth; this
skill and its references just point you at it and add the missing
static-analysis piece.
## Step 2 — static analysis (repo-local, not a component yet)
`ci-templates` doesn't have a PHPStan/Larastan component yet — add it as a
repo-local job per the stack's reference file. **Critical gotcha**: every
`ci-templates` component job declares `needs: []` on purpose (see the repo's
own README) so one gate failing doesn't silently skip the others via classic
stage-based blocking. Any repo-local job you add alongside them — like this
one — MUST also declare `needs: []`, or it will get marked `skipped` (not
run, not failed, just invisible) the first time an earlier-stage gate fails.
Confirmed as a real bug in `prestashop-demo` before this skill existed —
don't repeat it.
## Step 3 — branch protection + merge checks (blocking case ONLY)
Only do this after Step 0 confirmed the project is solo/personal with a real
PR habit. Skip entirely for team client projects.
```bash
enc=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1], safe=''))" "<namespace>/<project>")
# Create + protect a `test` branch (pre-prod), merge-only:
glab api -X POST "projects/$enc/repository/branches" --field "branch=test" --field "ref=main"
glab api -X POST "projects/$enc/protected_branches" --field "name=test" --field "push_access_level=0" --field "merge_access_level=40"
# Block merge on red pipeline:
glab api -X PUT "projects/$enc" --field "only_allow_merge_if_pipeline_succeeds=true"
```
`push_access_level=0` ("No one") is deliberate — it forces even the repo
owner through a Merge Request, which is the whole point if the goal is
building the habit. If that's too strict for how the user actually wants to
work, use `40` (Maintainer) instead and say so explicitly — don't silently
soften it.
If the project follows Cinetic's Intervals-task branching model (task branch
off `main`/`master`, merged to `test` first for pre-prod validation, then
**the same task branch** — never `test` itself — merged to `main` once the
client approves), the `workflow:` rules already cover both merge targets:
`merge_request_event` fires regardless of which branch the MR targets, so
gates run identically whether the MR goes into `test` or `main`. No extra
config needed for this branching model specifically.
## Gotchas (stack-agnostic)
- **`needs: []` on every repo-local job** you add next to ci-templates
components — omitting it causes silent `skipped` (not `failed`) status the
first time an earlier gate fails. See Step 2.
- **Pin the exact `ci-templates` tag** (`@vX.Y.Z`), never `@main`. If you're
the one maintaining `ci-templates` itself, also protect its tags
(Settings → Repository → Protected tags, pattern `v*`, Maintainer-only) —
GitLab tags are mutable by default, and an unprotected tag is a single
point of failure across every project that includes it.
- **No zizmor-equivalent exists for GitLab CI.** The closest tool is
`gitlab-ci-verify` (ShellCheck over `script:` blocks) — small, low-adoption.
The real defenses are GitLab-native: protected CI/CD variables are never
exposed to non-protected-branch or fork-originated pipelines by default;
the actual gotcha is a maintainer manually running a fork MR's pipeline
*in the parent project* — review the `.gitlab-ci.yml` diff first if you
ever do that.
- **GitLab Free tier is enough for all of this.** `only_allow_merge_if_pipeline_succeeds`
is a plain repository setting, not a Premium feature. What Free tier
*doesn't* have is GitHub-style named required-status-checks or MR approval
rules — the whole pipeline is the unit; if it's green, every gate in it
passed.
- **CI minutes are limited** on GitLab.com's standard tier (shared runners).
All the ci-templates gates are already designed around this: secret-scan
and dependency-audit are MR-diff/lockfile-scoped (not full-repo), and
`dependency-audit-*` also runs on scheduled pipelines rather than every
push where it makes sense. Don't add a full test/build matrix across
multiple PHP/framework versions on a client project's real CI — that's an
OSS-scale practice (see PrestaShop core/Laravel core's own CI), not
appropriate for a small team's per-minute budget. One job pinned to the
actual production PHP/framework version is enough.
- **Dependency-audit findings on a fresh/clean install are normal**, not a
setup mistake — see the stack reference file for the specific "safe to
hand-patch vs. wait for upstream" version-range logic before touching
anything a scan finds.
## Known gaps — researched, not built yet
External research across large OSS PrestaShop/Laravel/Astro/Next.js
projects (astro, starlight, next.js, cal.com, formbricks, laravel/framework,
spatie/laravel-permission, filamentphp/filament) surfaced practices this
skill doesn't cover yet. Don't build these speculatively — add them when a
real project's needs justify the CI-minute cost, same reasoning as
everything else here:
- **Dependabot/Renovate-equivalent** — near-universal in every repo studied,
currently absent here. GitLab's own Dependency Scanning / a self-hosted
Renovate bot both fit; hasn't been evaluated yet for this team's scale.
- **Severity-threshold hard-fail on dependency audits** — `cal.com` runs
`audit --severity critical` as an actual blocking gate rather than a
passive report. `dependency-audit-node`/`dependency-audit-php` here
already support an `audit-level` input (see references) — using it as a
hard gate rather than leaving it at a lenient default is a cheap upgrade
worth considering per-project.
- **Free-tier SAST (CodeQL/Semgrep-equivalent)** — used at scale by
astro/formbricks/cloudflare-docs for any project touching auth/user data.
No direct GitLab-native equivalent evaluated yet — flagged as a candidate,
not scoped.
Files in this skill
- SKILL.md
- references/astro.md
- references/laravel.md
- references/nextjs.md
- references/prestashop.md
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.