/gitlab-ci
Use this skill when authoring or debugging GitLab CI/CD pipelines (.gitlab-ci.yml) — e.g. "add a CI pipeline for this Drupal project", "run phpcs/phpstan/phpunit in GitLab CI", "deploy with drush from a pipeline", "why is my job not running", "cache composer dependencies", or
$ npx -y skills add siva01c/claude-plugins --skill gitlab-ci --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/gitlab-ci
Context preview
The summary Claude sees to decide when to auto-load this skill.
Use this skill when authoring or debugging GitLab CI/CD pipelines (.gitlab-ci.yml) — e.g. "add a CI pipeline for this Drupal project", "run phpcs/phpstan/phpunit in GitLab CI", "deploy with drush from a pipeline", "why is my job not running", "cache composer dependencies", or
SKILL.md
gitlab-ci.SKILL.mdname: gitlab-ci
description: >
Use this skill when authoring or debugging GitLab CI/CD pipelines
(.gitlab-ci.yml) — e.g. "add a CI pipeline for this Drupal project", "run
phpcs/phpstan/phpunit in GitLab CI", "deploy with drush from a pipeline",
"why is my job not running", "cache composer dependencies", or anything
involving stages, rules, artifacts, environments, or GitLab runners.
GitLab CI/CD Skill
GitLab CI runs pipelines defined in `.gitlab-ci.yml` at the repository root. This skill covers pipeline authoring with a Drupal project as the working example: validate → test → build → deploy, with composer caching and drush-based deployment.
---
Pipeline anatomy
stages:
- validate
- test
- deploy
default:
image: php:8.3-cli
before_script:
- curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
variables:
COMPOSER_CACHE_DIR: "$CI_PROJECT_DIR/.composer-cache"
cache:
key:
files:
- composer.lock # cache invalidates when the lock file changes
paths:
- .composer-cache/
- vendor/- **`stages`** run sequentially; jobs within a stage run in parallel.
- **`default`** holds settings shared by all jobs.
- **Cache vs artifacts:** cache is best-effort storage between pipelines
(composer/npm caches); artifacts pass build results between jobs of the same pipeline and can be downloaded from the UI.
---
Controlling when jobs run — `rules:`
`rules:` replaces the deprecated `only/except`:
phpcs:
stage: validate
script:
- composer install --no-progress
- vendor/bin/phpcs --standard=Drupal,DrupalPractice web/modules/custom
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCHFirst matching rule wins. Common conditions:
| Goal | Rule | |---|---| | MR pipelines only | `if: $CI_PIPELINE_SOURCE == "merge_request_event"` | | Default branch only | `if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH` | | Tags only | `if: $CI_COMMIT_TAG` | | Skip on draft MRs | `if: $CI_MERGE_REQUEST_TITLE =~ /^Draft:/` + `when: never` | | Manual gate | `when: manual` (e.g. production deploy) |
---
Drupal test jobs
phpstan:
stage: test
script:
- composer install --no-progress
- vendor/bin/phpstan analyse web/modules/custom
phpunit:
stage: test
services:
- name: mariadb:11.4
alias: db
variables:
MARIADB_DATABASE: drupal_test
MARIADB_ROOT_PASSWORD: root
SIMPLETEST_DB: mysql://root:root@db/drupal_test
SIMPLETEST_BASE_URL: http://localhost
script:
- composer install --no-progress
- vendor/bin/phpunit -c web/core/phpunit.xml.dist web/modules/custom
artifacts:
when: always
reports:
junit: junit.xml # test results shown in MR widget`services:` starts sidecar containers (database, redis) reachable by alias.
---
Deploying with drush
deploy_prod:
stage: deploy
environment:
name: production
url: https://www.example.com
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
when: manual # require a human click for prod
script:
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- ssh deploy@prod.example.com "cd /var/www/site && git pull --ff-only
&& composer install --no-dev --optimize-autoloader
&& vendor/bin/drush deploy -y"`drush deploy` runs `updb → config:import → cache:rebuild` in the right order. Store `SSH_PRIVATE_KEY` as a **masked, protected** CI/CD variable (Settings → CI/CD → Variables) — never in the repository.
`environment:` makes deployments visible under Operations → Environments and enables rollback tracking.
---
Reuse — include and needs
include:
- local: .gitlab/ci/common.yml # split big configs
- component: gitlab.com/components/sast/sast@main # CI/CD component
phpunit:
needs: ["phpcs"] # DAG: start as soon as phpcs passes, skip stage wait
`needs:` builds a directed acyclic graph so independent jobs don't wait for their whole previous stage.
---
Troubleshooting
| Symptom | Fix | |---|---| | Job never appears in pipeline | A `rules:` entry filtered it out — check `$CI_PIPELINE_SOURCE` for the trigger type | | "This job is stuck" | No runner with matching `tags:`; check runner availability | | Composer re-downloads everything each run | Cache key/path mismatch — cache `vendor/` and `$COMPOSER_CACHE_DIR`, key on `composer.lock` | | PHPUnit cannot connect to DB | Service alias must match host in `SIMPLETEST_DB`; wait for DB startup or use healthcheck-aware images | | Masked variable prints as `[MASKED]` but auth fails | Variable contains newline/CR — for SSH keys use `tr -d '\r'` and file-type variables | | Pipeline runs twice per MR push | Branch + MR pipelines both enabled — use `workflow: rules:` to keep one |
Read more
name: gitlab-ci description: > Use this skill when authoring or debugging GitLab CI/CD pipelines (.gitlab-ci.yml) — e.g. "add a CI pipeline for this Drupal project", "run phpcs/phpstan/phpunit in GitLab CI", "deploy with drush from a pipeline", "why is my job not running", "cache composer dependencies", or anything involving stages, rules, artifacts, environments, or GitLab runners.
GitLab CI/CD Skill
GitLab CI runs pipelines defined in `.gitlab-ci.yml` at the repository root. This skill covers pipeline authoring with a Drupal project as the working example: validate → test → build → deploy, with composer caching and drush-based deployment.
---
Pipeline anatomy
stages:
- validate
- test
- deploy
default:
image: php:8.3-cli
before_script:
- curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
variables:
COMPOSER_CACHE_DIR: "$CI_PROJECT_DIR/.composer-cache"
cache:
key:
files:
- composer.lock # cache invalidates when the lock file changes
paths:
- .composer-cache/
- vendor/- **`stages`** run sequentially; jobs within a stage run in parallel.
- **`default`** holds settings shared by all jobs.
- **Cache vs artifacts:** cache is best-effort storage between pipelines
(composer/npm caches); artifacts pass build results between jobs of the same pipeline and can be downloaded from the UI.
---
Controlling when jobs run — `rules:`
`rules:` replaces the deprecated `only/except`:
phpcs:
stage: validate
script:
- composer install --no-progress
- vendor/bin/phpcs --standard=Drupal,DrupalPractice web/modules/custom
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCHFirst matching rule wins. Common conditions:
| Goal | Rule | |---|---| | MR pipelines only | `if: $CI_PIPELINE_SOURCE == "merge_request_event"` | | Default branch only | `if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH` | | Tags only | `if: $CI_COMMIT_TAG` | | Skip on draft MRs | `if: $CI_MERGE_REQUEST_TITLE =~ /^Draft:/` + `when: never` | | Manual gate | `when: manual` (e.g. production deploy) |
---
Drupal test jobs
phpstan:
stage: test
script:
- composer install --no-progress
- vendor/bin/phpstan analyse web/modules/custom
phpunit:
stage: test
services:
- name: mariadb:11.4
alias: db
variables:
MARIADB_DATABASE: drupal_test
MARIADB_ROOT_PASSWORD: root
SIMPLETEST_DB: mysql://root:root@db/drupal_test
SIMPLETEST_BASE_URL: http://localhost
script:
- composer install --no-progress
- vendor/bin/phpunit -c web/core/phpunit.xml.dist web/modules/custom
artifacts:
when: always
reports:
junit: junit.xml # test results shown in MR widget`services:` starts sidecar containers (database, redis) reachable by alias.
---
Deploying with drush
deploy_prod:
stage: deploy
environment:
name: production
url: https://www.example.com
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
when: manual # require a human click for prod
script:
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- ssh deploy@prod.example.com "cd /var/www/site && git pull --ff-only
&& composer install --no-dev --optimize-autoloader
&& vendor/bin/drush deploy -y"`drush deploy` runs `updb → config:import → cache:rebuild` in the right order. Store `SSH_PRIVATE_KEY` as a **masked, protected** CI/CD variable (Settings → CI/CD → Variables) — never in the repository.
`environment:` makes deployments visible under Operations → Environments and enables rollback tracking.
---
Reuse — include and needs
include: - local: .gitlab/ci/common.yml # split big configs - component: gitlab.com/components/sast/sast@main # CI/CD component phpunit: needs: ["phpcs"] # DAG: start as soon as phpcs passes, skip stage wait
`needs:` builds a directed acyclic graph so independent jobs don't wait for their whole previous stage.
---
Troubleshooting
| Symptom | Fix | |---|---| | Job never appears in pipeline | A `rules:` entry filtered it out — check `$CI_PIPELINE_SOURCE` for the trigger type | | "This job is stuck" | No runner with matching `tags:`; check runner availability | | Composer re-downloads everything each run | Cache key/path mismatch — cache `vendor/` and `$COMPOSER_CACHE_DIR`, key on `composer.lock` | | PHPUnit cannot connect to DB | Service alias must match host in `SIMPLETEST_DB`; wait for DB startup or use healthcheck-aware images | | Masked variable prints as `[MASKED]` but auth fails | Variable contains newline/CR — for SSH keys use `tr -d '\r'` and file-type variables | | Pipeline runs twice per MR push | Branch + MR pipelines both enabled — use `workflow: rules:` to keep one |
A curated collection of Claude Code plugins for Drupal development, security, and deployment. Each plugin covers one topic — Drupal itself, DDEV, Docker, CI/CD, git workflows, and security verification — so you install only what you need.
Other skills on claude-plugins.
- /github-actions
Use this skill when authoring or debugging GitHub Actions workflows (.github/workflows/*.yml) — e.g. "add CI for this Drupal project on GitHub", "run phpcs/phpstan/phpunit on pull requests", "cache composer dependencies", "deploy over SSH when main is pushed", "why didn't my
Open skill - /drupal-ddev-operations
Use for operational Drupal 11 workflows in DDEV environments, including safe updates, backup-first procedures, and troubleshooting commands.
Open skill - /docker-compose
Use this skill when authoring or editing Docker Compose files (compose.yaml / docker-compose.yml), running multi-container stacks, or containerizing a Drupal/PHP application — e.g. "set up a local Drupal stack with nginx and MariaDB", "add Redis to my compose file", "why won't
Open skill - /docker-model
Use this skill when running local AI models with Docker Model Runner — the `docker model` CLI — e.g. "run an LLM locally with Docker", "pull a model from the ai/ namespace", "connect my app to a local model", "use a local model as backend for the Drupal AI module", or when
Open skill - /drupal-module-development
Use when creating or extending Drupal 11 custom modules, including scaffolding, service architecture, and dependency injection best practices.
Open skill - /drupal-security-review
Use when auditing Drupal 11 custom modules/themes for security issues such as unsafe input handling, XSS risks, SQL injection, and access control gaps.
Open skill

