Skip to content
Back to skills

Gitlab Ci Quality Gates

ASecurity

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 qualit...

  • 3 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 23, 2026
developmentpythongophpshellbashnextjsnoderailsgitapi

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 5 files and shows the line behind each finding

Scanned September 23, 2026

npx -y skills add educlopez/mallard --skill gitlab-ci-quality-gates --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Gitlab Ci Quality Gates?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Gitlab Ci Quality Gates
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/educlopez-gitlab-ci-quality-gates/badge)](https://www.skillsdirectory.com/skills/educlopez-gitlab-ci-quality-gates)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
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.md9.5 KB
  • references/astro.md3.3 KB
  • references/laravel.md4.4 KB
  • references/nextjs.md4.1 KB
  • references/prestashop.md4.3 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.