/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
$ npx -y skills add siva01c/claude-plugins --skill github-actions --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
/github-actions
Context preview
The summary Claude sees to decide when to auto-load this skill.
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
SKILL.md
github-actions.SKILL.mdname: github-actions
description: >
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
workflow trigger", or anything involving jobs, matrices, runners, secrets,
or reusable workflows.
GitHub Actions Skill
GitHub Actions runs workflows from `.github/workflows/*.yml`. This skill covers workflow authoring with a Drupal project as the working example: linting, static analysis, PHPUnit with a database service, and SSH/drush deployment.
---
Workflow anatomy
name: CI
on:
pull_request:
push:
branches: [main]
permissions:
contents: read # least privilege — grant more only per job
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true # newer push cancels the outdated run
jobs:
phpcs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
tools: composer:v2
- uses: actions/cache@v4
with:
path: ~/.composer/cache
key: composer-${{ hashFiles('composer.lock') }}
restore-keys: composer-
- run: composer install --no-progress
- run: vendor/bin/phpcs --standard=Drupal,DrupalPractice web/modules/customKey defaults to always set:
- **`permissions:`** — the implicit token is powerful; start from
`contents: read` and widen per job only when needed.
- **`concurrency:`** — avoids burning runner minutes on superseded pushes.
---
PHPUnit with a database service
phpunit:
runs-on: ubuntu-latest
services:
db:
image: mariadb:11.4
env:
MARIADB_DATABASE: drupal_test
MARIADB_ROOT_PASSWORD: root
ports: ['3306:3306']
options: >-
--health-cmd="healthcheck.sh --connect --innodb_initialized"
--health-interval=10s --health-timeout=5s --health-retries=5
env:
SIMPLETEST_DB: mysql://root:root@127.0.0.1:3306/drupal_test
SIMPLETEST_BASE_URL: http://localhost
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
extensions: gd, pdo_mysql
- run: composer install --no-progress
- run: vendor/bin/phpunit -c web/core/phpunit.xml.dist web/modules/custom`services:` containers get health-checked before steps run — no manual wait loops. From the runner they are reachable on `127.0.0.1:<mapped port>`.
Matrix builds
strategy:
matrix:
php: ['8.3', '8.4']
steps:
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}---
Deployment job
deploy:
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
needs: [phpcs, phpunit]
runs-on: ubuntu-latest
environment:
name: production
url: https://www.example.com
steps:
- uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- run: |
ssh -o StrictHostKeyChecking=accept-new deploy@prod.example.com \
"cd /var/www/site && git pull --ff-only \
&& composer install --no-dev --optimize-autoloader \
&& vendor/bin/drush deploy -y"- `needs:` gates deployment on green checks.
- `environment:` enables required reviewers and deployment history
(Settings → Environments) — use it for production approval gates.
- Secrets live in repo/environment settings, referenced via
`${{ secrets.NAME }}`. For cloud providers prefer **OIDC** (`permissions: id-token: write` + the provider's auth action) over long-lived keys.
---
Reuse
- **Reusable workflow** — a whole workflow callable from others:
# .github/workflows/drupal-tests.yml
on:
workflow_call:
inputs:
php-version: { type: string, default: '8.3' } # caller
jobs:
tests:
uses: ./.github/workflows/drupal-tests.yml
with:
php-version: '8.4'- **Composite action** — a reusable step sequence in
`.github/actions/<name>/action.yml` (e.g. "setup PHP + composer install with cache") to deduplicate job boilerplate.
---
Troubleshooting
| Symptom | Fix | |---|---| | Workflow doesn't trigger | Check `on:` filters — `branches:`/`paths:` excluded the ref, or push was from a workflow using the default token (no recursive triggers) | | `Permission denied` on push/comment from job | Widen `permissions:` for that job (e.g. `pull-requests: write`) | | Composer cache never hits | Key on `hashFiles('composer.lock')` and add a `restore-keys:` prefix fallback | | PHPUnit can't reach DB | Use `127.0.0.1` with the mapped port, not the service name (service names only resolve in container jobs) | | Deploy ran before tests finished | Add the test jobs to `needs:` of the deploy job | | Two runs per PR push | `push:` + `pull_request:` both trigger — restrict `push:` to `branches: [main]` |
Read more
name: github-actions description: > 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 workflow trigger", or anything involving jobs, matrices, runners, secrets, or reusable workflows.
GitHub Actions Skill
GitHub Actions runs workflows from `.github/workflows/*.yml`. This skill covers workflow authoring with a Drupal project as the working example: linting, static analysis, PHPUnit with a database service, and SSH/drush deployment.
---
Workflow anatomy
name: CI
on:
pull_request:
push:
branches: [main]
permissions:
contents: read # least privilege — grant more only per job
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true # newer push cancels the outdated run
jobs:
phpcs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
tools: composer:v2
- uses: actions/cache@v4
with:
path: ~/.composer/cache
key: composer-${{ hashFiles('composer.lock') }}
restore-keys: composer-
- run: composer install --no-progress
- run: vendor/bin/phpcs --standard=Drupal,DrupalPractice web/modules/customKey defaults to always set:
- **`permissions:`** — the implicit token is powerful; start from
`contents: read` and widen per job only when needed.
- **`concurrency:`** — avoids burning runner minutes on superseded pushes.
---
PHPUnit with a database service
phpunit:
runs-on: ubuntu-latest
services:
db:
image: mariadb:11.4
env:
MARIADB_DATABASE: drupal_test
MARIADB_ROOT_PASSWORD: root
ports: ['3306:3306']
options: >-
--health-cmd="healthcheck.sh --connect --innodb_initialized"
--health-interval=10s --health-timeout=5s --health-retries=5
env:
SIMPLETEST_DB: mysql://root:root@127.0.0.1:3306/drupal_test
SIMPLETEST_BASE_URL: http://localhost
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
extensions: gd, pdo_mysql
- run: composer install --no-progress
- run: vendor/bin/phpunit -c web/core/phpunit.xml.dist web/modules/custom`services:` containers get health-checked before steps run — no manual wait loops. From the runner they are reachable on `127.0.0.1:<mapped port>`.
Matrix builds
strategy:
matrix:
php: ['8.3', '8.4']
steps:
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}---
Deployment job
deploy:
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
needs: [phpcs, phpunit]
runs-on: ubuntu-latest
environment:
name: production
url: https://www.example.com
steps:
- uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- run: |
ssh -o StrictHostKeyChecking=accept-new deploy@prod.example.com \
"cd /var/www/site && git pull --ff-only \
&& composer install --no-dev --optimize-autoloader \
&& vendor/bin/drush deploy -y"- `needs:` gates deployment on green checks.
- `environment:` enables required reviewers and deployment history
(Settings → Environments) — use it for production approval gates.
- Secrets live in repo/environment settings, referenced via
`${{ secrets.NAME }}`. For cloud providers prefer **OIDC** (`permissions: id-token: write` + the provider's auth action) over long-lived keys.
---
Reuse
- **Reusable workflow** — a whole workflow callable from others:
# .github/workflows/drupal-tests.yml
on:
workflow_call:
inputs:
php-version: { type: string, default: '8.3' } # caller
jobs:
tests:
uses: ./.github/workflows/drupal-tests.yml
with:
php-version: '8.4'- **Composite action** — a reusable step sequence in
`.github/actions/<name>/action.yml` (e.g. "setup PHP + composer install with cache") to deduplicate job boilerplate.
---
Troubleshooting
| Symptom | Fix | |---|---| | Workflow doesn't trigger | Check `on:` filters — `branches:`/`paths:` excluded the ref, or push was from a workflow using the default token (no recursive triggers) | | `Permission denied` on push/comment from job | Widen `permissions:` for that job (e.g. `pull-requests: write`) | | Composer cache never hits | Key on `hashFiles('composer.lock')` and add a `restore-keys:` prefix fallback | | PHPUnit can't reach DB | Use `127.0.0.1` with the mapped port, not the service name (service names only resolve in container jobs) | | Deploy ran before tests finished | Add the test jobs to `needs:` of the deploy job | | Two runs per PR push | `push:` + `pull_request:` both trigger — restrict `push:` to `branches: [main]` |
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.
- /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
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

