Generate CI/CD pipeline (GitHub Actions / GitLab CI) with linting, static analysis, tests, security. Use when user says "ci", "setup ci", "github actions", "gitlab ci", "pipeline".
68
85%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Analyze a project and generate production-grade CI/CD pipeline configuration for GitHub Actions or GitLab CI. Generates separate jobs for linting, static analysis, tests, and security scanning — adapted to the project's language, framework, and existing tooling.
Three modes based on what exists:
| What exists | Mode | Action |
|---|---|---|
| No CI config | generate | Create pipeline from scratch with interactive setup |
| CI config exists but incomplete | enhance | Audit & improve, add missing jobs |
| Full CI config | audit | Audit against best practices, fix gaps |
Read the project description if available:
Read .ai-factory/DESCRIPTION.mdStore project context for later steps. If absent, Step 2 detects everything.
Read .ai-factory/skill-context/aif-ci/SKILL.md — MANDATORY if the file exists.
This file contains project-specific rules accumulated by /aif-evolve from patches,
codebase conventions, and tech-stack analysis. These rules are tailored to the current project.
How to apply skill-context rules:
Enforcement: After generating any output artifact, verify it against all skill-context rules. If any rule is violated — fix the output before presenting it to the user.
Glob: .github/workflows/*.yml, .github/workflows/*.yaml, .gitlab-ci.yml, .circleci/config.yml, Jenkinsfile, .travis.yml, bitbucket-pipelines.ymlClassify found files:
HAS_GITHUB_ACTIONS: .github/workflows/ contains YAML filesHAS_GITLAB_CI: .gitlab-ci.yml existsHAS_OTHER_CI: CircleCI, Jenkins, Travis, or Bitbucket detectedIf $ARGUMENTS contains --enhance -> set MODE = "enhance" regardless.
Path A: No CI config exists (!HAS_GITHUB_ACTIONS && !HAS_GITLAB_CI && !HAS_OTHER_CI):
MODE = "generate"Path B: CI config exists but is incomplete (e.g., has only tests, no linting):
MODE = "enhance"EXISTING_CONTENTPath C: Full CI setup (has linting + tests + static analysis):
MODE = "audit"EXISTING_CONTENTDetermine CI platform from $ARGUMENTS or ask:
If $ARGUMENTS contains github -> set PLATFORM = "github"
If $ARGUMENTS contains gitlab -> set PLATFORM = "gitlab"
Otherwise:
AskUserQuestion: Which CI/CD platform do you use?
Options:
1. GitHub Actions (Recommended) — .github/workflows/*.yml
2. GitLab CI — .gitlab-ci.ymlAsk about optional features:
AskUserQuestion: Which additional CI features do you need?
Options (multiSelect):
1. Security scanning — Dependency audit, SAST
2. Coverage reporting — Upload test coverage
3. Matrix builds — Test across multiple language versions
4. None — Just linting, static analysis, and testsStore choices:
PLATFORM: github | gitlabWANT_SECURITY: booleanWANT_COVERAGE: booleanWANT_MATRIX: booleanRead all existing CI files and store as EXISTING_CONTENT:
.github/workflows/*.yml files.gitlab-ci.ymlinclude: directives)Determine PLATFORM from existing files.
Scan the project thoroughly — every decision in the generated pipeline depends on this profile.
| File | Language |
|---|---|
composer.json | PHP |
package.json | Node.js / TypeScript |
pyproject.toml / setup.py / setup.cfg | Python |
go.mod | Go |
Cargo.toml | Rust |
pom.xml | Java (Maven) |
build.gradle / build.gradle.kts | Java/Kotlin (Gradle) |
Detect the project's language version to use in CI:
| Language | Version Source | Example |
|---|---|---|
| PHP | composer.json -> require.php | >=8.2 -> ['8.2', '8.3', '8.4'] |
| Node.js | package.json -> engines.node, .nvmrc, .node-version | >=18 -> [18, 20, 22] |
| Python | pyproject.toml -> requires-python, .python-version | >=3.11 -> ['3.11', '3.12', '3.13'] |
| Go | go.mod -> go directive | go 1.23 -> '1.23' |
| Rust | Cargo.toml -> rust-version, rust-toolchain.toml | 1.82 -> '1.82' |
| Java | pom.xml -> maven.compiler.source, build.gradle -> sourceCompatibility | 17 -> [17, 21] |
For matrix builds: use the minimum version from the project config as the lowest, and include the latest stable version. For non-matrix builds: use the latest version that satisfies the constraint.
| File | Package Manager | Install Command |
|---|---|---|
composer.lock | Composer | composer install --no-interaction --prefer-dist |
bun.lockb | Bun | bun install --frozen-lockfile |
pnpm-lock.yaml | pnpm | pnpm install --frozen-lockfile |
yarn.lock | Yarn | yarn install --frozen-lockfile |
package-lock.json | npm | npm ci |
uv.lock | uv | uv sync --all-extras --dev |
poetry.lock | Poetry | poetry install |
Pipfile.lock | Pipenv | pipenv install --dev |
requirements.txt | pip | pip install -r requirements.txt |
go.sum | Go modules | go mod download |
Cargo.lock | Cargo | (built-in) |
Store: PACKAGE_MANAGER, LOCK_FILE, INSTALL_CMD.
Detect project tools by scanning config files and dependencies. For the complete tool-to-command mapping → read references/TOOL-COMMANDS.md
Categories: Linters & Formatters (PHP-CS-Fixer, ESLint, Prettier, Biome, Ruff, golangci-lint, clippy, Checkstyle), Static Analysis (PHPStan, Psalm, Rector, mypy, tsc), Test Frameworks (PHPUnit, Pest, Jest, Vitest, pytest, go test, cargo test) with coverage flags, Security Audit (composer audit, npm audit, pip-audit, govulncheck, cargo audit).
Check if tests require external services (database, Redis, etc.):
Grep in tests/: postgres|mysql|redis|mongo|rabbitmq|elasticsearch
Glob: docker-compose.test.yml, docker-compose.ci.ymlIf services are needed, they will be configured in the CI pipeline as service containers.
Does the project have a build step?
| Language | Has Build | Build Command |
|---|---|---|
Node.js (with build script) | Yes | npm run build / pnpm build |
| Go | Yes | go build ./... |
| Rust | Yes | cargo build --release |
| Java | Yes | mvn package -DskipTests -B / ./gradlew assemble |
| PHP | Usually no | — |
| Python | Usually no | — |
Build PROJECT_PROFILE:
language, language_version, language_versions (for matrix)package_manager, lock_file, install_cmdlinters: list of {name, command, config_file}static_analyzers: list of {name, command}test_framework, test_cmd, coverage_cmdsecurity_tools: list of {name, command}has_build_step, build_cmdhas_typescript: boolean (for typecheck job)services_needed: list of services for CIsource_dir: main source directory (src/, app/, lib/)Read skills/ci/references/BEST-PRACTICES.mdSelect templates matching the platform and language:
GitHub Actions:
| Language | Template |
|---|---|
| PHP | templates/github/php.yml |
| Node.js | templates/github/node.yml |
| Python | templates/github/python.yml |
| Go | templates/github/go.yml |
| Rust | templates/github/rust.yml |
| Java | templates/github/java.yml |
GitLab CI:
| Language | Template |
|---|---|
| PHP | templates/gitlab/php.yml |
| Node.js | templates/gitlab/node.yml |
| Python | templates/gitlab/python.yml |
| Go | templates/gitlab/go.yml |
| Rust | templates/gitlab/rust.yml |
| Java | templates/gitlab/java.yml |
Read the selected template:
Read skills/ci/templates/<platform>/<language>.ymlUsing the PROJECT_PROFILE, best practices, and template as a base, generate a customized CI pipeline.
One workflow per concern — each file has its own triggers, permissions, concurrency:
| File | Name | Jobs | When to create |
|---|---|---|---|
lint.yml | Lint | code-style, static-analysis, rector | Linters or SA detected |
tests.yml | Tests | tests (+ service containers) | Always |
build.yml | Build | build | has_build_step |
security.yml | Security | dependency-audit, dependency-review | WANT_SECURITY |
Why one file per concern:
security-events: writetests but not security)When to keep single file: Only for very small projects with just lint + tests (2 jobs). As soon as there are 3+ concerns — split.
Every workflow gets the same header pattern:
name: <Name>
on:
push:
branches: [main]
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: readPer-file job organization:
lint.yml — all code quality checks in parallel:
| Job | Purpose | When to include |
|---|---|---|
code-style | Formatting (CS-Fixer, Prettier, Ruff format, rustfmt) | Formatter detected |
lint | Linting (ESLint, Ruff check, Clippy, golangci-lint) | Linter detected |
static-analysis | Type checking / SA (PHPStan, Psalm, mypy, tsc) | SA tools detected |
rector | Rector dry-run (PHP only) | Rector detected |
All jobs run in parallel (no needs). If only one tool detected (e.g. Go with just golangci-lint) — single job in the file is fine.
tests.yml — test suite:
| Job | Purpose | When to include |
|---|---|---|
tests | Unit/integration tests | Always |
tests-<service> | Tests requiring service containers | services_needed detected |
Matrix builds (multiple language versions) only in this file.
build.yml — build verification:
| Job | Purpose | Notes |
|---|---|---|
build | Verify compilation/bundling | Can depend on external workflow via workflow_run or just run independently |
security.yml — security scanning:
| Job | Purpose | Extra triggers |
|---|---|---|
dependency-audit | Vulnerability scan | schedule: cron '0 6 * * 1' (weekly) |
dependency-review | PR dependency diff | Only on pull_request |
Per-job rules:
shivammathur/setup-php@v2 with tools: parameteractions/setup-node@v4 with cache: parameterastral-sh/setup-uv@v5 (if uv) or actions/setup-python@v5 (if pip)actions/setup-go@v5 (auto-caches)dtolnay/rust-toolchain@stable + Swatinem/rust-cache@v2actions/setup-java@v4 with cache: parameterfail-fast: false in matrix buildsWANT_COVERAGEMatrix builds (when WANT_MATRIX):
Only the tests job uses a matrix. Lint/SA jobs run on the latest version only.
tests:
name: Tests (${{ matrix.<language>-version }})
strategy:
fail-fast: false
matrix:
<language>-version: <language_versions from PROJECT_PROFILE>Combining linter jobs:
If the project has both a formatter AND a linter from the same ecosystem, combine them into one job:
php-cs-fixer check + other lint -> code-style jobeslint + prettier -> lint job. Biome replaces BOTH ESLint and Prettier — if Biome is detected, use only npx biome check . in a single lint jobruff check + ruff format --check -> lint job (Ruff handles both)cargo fmt + cargo clippy -> can be separate (fmt is fast, clippy needs compilation)Do NOT combine lint/SA with tests — they should fail independently with clear feedback.
Use the templates in templates/github/ and templates/gitlab/ as a base for generating workflow files. Follow the header pattern (name, on, concurrency, permissions) and per-file job organization described above.
Output file: .gitlab-ci.yml
For GitLab-specific pipeline structure, cache strategy, report format integration, and language-specific patterns → read references/GITLAB-PATTERNS.md
Pipeline stages: install → lint → test → build → security
If services_needed is not empty, add service containers to the test job.
For GitHub Actions and GitLab CI service container syntax → read references/SERVICE-CONTAINERS.md
Verify generated pipeline before writing:
Correctness:
Best practices:
concurrency group set (GitHub Actions)permissions: contents: read set (GitHub Actions)interruptible: true set (GitLab CI)workflow.rules defined (GitLab CI)needs)fail-fast: false on matrix buildsNo over-engineering:
When MODE = "enhance" or MODE = "audit", analyze EXISTING_CONTENT against the project profile and best practices.
Compare existing pipeline against PROJECT_PROFILE:
Missing jobs:
Configuration issues:
actions-rs instead of dtolnay/rust-toolchain)?fail-fast: false on matrix?policy: pull-push on all GitLab jobs instead of pull on non-install jobs?Missing features:
workflow_dispatch trigger (GitHub Actions)?For audit report format, fix flow options, and display templates → read references/AUDIT-REPORT.md
Present results as tables with ✅/❌/⚠️ per check. Categorize recommendations by severity (CRITICAL, HIGH, MEDIUM, LOW). Ask user to choose: fix all, fix critical only, or show details first.
If fixing: preserve existing structure, job names, and ordering conventions.
GitHub Actions:
Bash: mkdir -p .github/workflows
Write .github/workflows/lint.yml # If linters/SA detected
Write .github/workflows/tests.yml # Always
Write .github/workflows/build.yml # If has_build_step
Write .github/workflows/security.yml # If WANT_SECURITYOnly create files for detected concerns. If only lint + tests — two files. If the project is trivially small (single lint + single test job) — a single ci.yml is acceptable.
GitLab CI:
Write .gitlab-ci.ymlGitLab CI uses a single .gitlab-ci.yml — stages and DAG (needs:) handle separation.
Edit existing files using the Edit tool. Preserve the original structure and only add/modify what's needed.
Display summary using format from references/AUDIT-REPORT.md (Summary Display Template section). Show platform, files created, features, and quick start commands.
Suggest: /aif-build-automation for CI targets in Makefile/Taskfile, /aif-dockerize for containerization.
.github/workflows/* and .gitlab-ci.yml.config.yaml.e144f95
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.