AgentSkillsCN

ai-factory.ci

生成CI/CD流水线(GitHub Actions / GitLab CI),并集成代码风格检查、静态分析、测试与安全防护。当用户说“CI”“设置CI”“GitHub Actions”“GitLab CI”“流水线”时使用此功能。

SKILL.md
--- frontmatter
name: ai-factory.ci
description: 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".
argument-hint: [github|gitlab] [--enhance]
allowed-tools: Read Edit Glob Grep Write Bash(git *) AskUserQuestion
disable-model-invocation: true
metadata:
  author: AI Factory
  version: "1.0"
  category: ci

CI — Pipeline Configuration Generator

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 existsModeAction
No CI configgenerateCreate pipeline from scratch with interactive setup
CI config exists but incompleteenhanceAudit & improve, add missing jobs
Full CI configauditAudit against best practices, fix gaps

Step 0: Load Project Context

Read the project description if available:

code
Read .ai-factory/DESCRIPTION.md

Store project context for later steps. If absent, Step 2 detects everything.


Step 1: Detect Existing CI & Determine Mode

1.1 Scan for Existing CI Configuration

code
Glob: .github/workflows/*.yml, .github/workflows/*.yaml, .gitlab-ci.yml, .circleci/config.yml, Jenkinsfile, .travis.yml, bitbucket-pipelines.yml

Classify found files:

  • HAS_GITHUB_ACTIONS: .github/workflows/ contains YAML files
  • HAS_GITLAB_CI: .gitlab-ci.yml exists
  • HAS_OTHER_CI: CircleCI, Jenkins, Travis, or Bitbucket detected

1.2 Determine Mode

If $ARGUMENTS contains --enhance -> set MODE = "enhance" regardless.

Path A: No CI config exists (!HAS_GITHUB_ACTIONS && !HAS_GITLAB_CI && !HAS_OTHER_CI):

  • Set MODE = "generate"
  • Proceed to Step 1.3: Interactive Setup

Path B: CI config exists but is incomplete (e.g., has only tests, no linting):

  • Set MODE = "enhance"
  • Read all existing CI files -> store as EXISTING_CONTENT
  • Log: "Found existing CI configuration. Will analyze and add missing jobs."

Path C: Full CI setup (has linting + tests + static analysis):

  • Set MODE = "audit"
  • Read all existing CI files -> store as EXISTING_CONTENT
  • Log: "Found complete CI setup. Will audit against best practices and fix gaps."

1.3 Interactive Setup (Generate Mode Only)

Determine CI platform from $ARGUMENTS or ask:

If $ARGUMENTS contains github -> set PLATFORM = "github" If $ARGUMENTS contains gitlab -> set PLATFORM = "gitlab"

Otherwise:

code
AskUserQuestion: Which CI/CD platform do you use?

Options:
1. GitHub Actions (Recommended) — .github/workflows/*.yml
2. GitLab CI — .gitlab-ci.yml

Ask about optional features:

code
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 tests

Store choices:

  • PLATFORM: github | gitlab
  • WANT_SECURITY: boolean
  • WANT_COVERAGE: boolean
  • WANT_MATRIX: boolean

1.4 Read Existing Files (Enhance / Audit Modes)

Read all existing CI files and store as EXISTING_CONTENT:

  • All .github/workflows/*.yml files
  • .gitlab-ci.yml
  • Any included GitLab CI files (check include: directives)

Determine PLATFORM from existing files.


Step 2: Deep Project Analysis

Scan the project thoroughly — every decision in the generated pipeline depends on this profile.

2.1 Language & Runtime

FileLanguage
composer.jsonPHP
package.jsonNode.js / TypeScript
pyproject.toml / setup.py / setup.cfgPython
go.modGo
Cargo.tomlRust
pom.xmlJava (Maven)
build.gradle / build.gradle.ktsJava/Kotlin (Gradle)

2.2 Language Version

Detect the project's language version to use in CI:

LanguageVersion SourceExample
PHPcomposer.json -> require.php>=8.2 -> ['8.2', '8.3', '8.4']
Node.jspackage.json -> engines.node, .nvmrc, .node-version>=18 -> [18, 20, 22]
Pythonpyproject.toml -> requires-python, .python-version>=3.11 -> ['3.11', '3.12', '3.13']
Gogo.mod -> go directivego 1.23 -> '1.23'
RustCargo.toml -> rust-version, rust-toolchain.toml1.82 -> '1.82'
Javapom.xml -> maven.compiler.source, build.gradle -> sourceCompatibility17 -> [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.

2.3 Package Manager & Lock File

FilePackage ManagerInstall Command
composer.lockComposercomposer install --no-interaction --prefer-dist
bun.lockbBunbun install --frozen-lockfile
pnpm-lock.yamlpnpmpnpm install --frozen-lockfile
yarn.lockYarnyarn install --frozen-lockfile
package-lock.jsonnpmnpm ci
uv.lockuvuv sync --all-extras --dev
poetry.lockPoetrypoetry install
Pipfile.lockPipenvpipenv install --dev
requirements.txtpippip install -r requirements.txt
go.sumGo modulesgo mod download
Cargo.lockCargo(built-in)

Store: PACKAGE_MANAGER, LOCK_FILE, INSTALL_CMD.

2.4 Linters & Formatters

Detect existing tools by scanning config files and dependency files:

PHP (scan composer.json -> require-dev):

ToolConfig FileCI Command
PHP-CS-Fixer.php-cs-fixer.php, .php-cs-fixer.dist.phpvendor/bin/php-cs-fixer fix --dry-run --diff
PHP_CodeSnifferphpcs.xml, phpcs.xml.distvendor/bin/phpcs
Pintpint.jsonvendor/bin/pint --test

Node.js (scan package.json -> devDependencies):

ToolConfig FileCI Command
ESLinteslint.config.*, .eslintrc.*npx eslint .
Prettier.prettierrc*, prettier.config.*npx prettier --check .
Biomebiome.json, biome.jsoncnpx biome check .

Python (scan pyproject.toml -> [tool.*] sections, requirements-dev.txt):

ToolConfig FileCI Command
Ruffruff.toml, pyproject.toml [tool.ruff]ruff check . / ruff format --check .
Blackpyproject.toml [tool.black]black --check .
isortpyproject.toml [tool.isort]isort --check-only .
Flake8.flake8, setup.cfg [flake8]flake8 .
Pylint.pylintrc, pyproject.toml [tool.pylint]pylint src/

Go:

ToolConfig FileCI Command
golangci-lint.golangci.yml, .golangci.yamlgolangci-lint run

Rust (built-in):

ToolCI Command
clippycargo clippy --all-targets --all-features -- -D warnings
rustfmtcargo fmt --all -- --check

Java:

ToolConfig FileCI Command (Maven)CI Command (Gradle)
Checkstylecheckstyle.xmlmvn checkstyle:check -B./gradlew checkstyleMain
PMDpmd-ruleset.xmlmvn pmd:check -B./gradlew pmdMain
SpotBugsmvn compile spotbugs:check -B./gradlew spotbugsMain

2.5 Static Analysis Tools

PHP (scan composer.json -> require-dev):

ToolConfig FileCI Command
PHPStanphpstan.neon, phpstan.neon.distvendor/bin/phpstan analyse --memory-limit=512M
Psalmpsalm.xml, psalm.xml.distvendor/bin/psalm --no-cache
Rectorrector.phpvendor/bin/rector process --dry-run

Python:

ToolCI Command
mypymypy src/
pyrightpyright

Node.js (TypeScript):

ToolCI Command
tscnpx tsc --noEmit

Go:

  • golangci-lint includes static analysis (go vet, staticcheck, etc.)

Rust:

  • cargo clippy covers static analysis

2.6 Test Framework

LanguageDetect ByTest Command
PHPphpunit/phpunit in composer.jsonvendor/bin/phpunit
PHPpestphp/pest in composer.jsonvendor/bin/pest --ci
Node.jsjest in package.jsonnpx jest --ci
Node.jsvitest in package.jsonnpx vitest run
Pythonpytest in pyproject.tomlpytest -v
GoBuilt-ingo test -race -v ./...
RustBuilt-incargo test --all-features
JavaBuilt-in (JUnit)mvn verify -B / ./gradlew test

Also detect coverage tools:

LanguageCoverage Flag
PHP--coverage-clover coverage.xml
Node.js (Jest)--coverage
Node.js (Vitest)--coverage
Python--cov=src --cov-report=xml
Go-coverprofile=coverage.out -covermode=atomic
Rustcargo tarpaulin --ignore-tests --out xml
Javamvn jacoco:report / ./gradlew jacocoTestReport

2.7 Security Audit Tools

LanguageToolCI Command
PHPComposer auditcomposer audit
Node.jsnpm auditnpm audit --audit-level=high
Pythonpip-auditpip-audit or uv run pip-audit (dependency vulnerabilities)
Pythonbanditbandit -r src/ or uv run bandit -r src/ (code security)
Gogovulncheckgovulncheck ./...
Rustcargo auditcargo audit
Rustcargo denycargo deny check
JavaOWASPmvn dependency-check:check -B

2.8 Services Detection

Check if tests require external services (database, Redis, etc.):

code
Grep in tests/: postgres|mysql|redis|mongo|rabbitmq|elasticsearch
Glob: docker-compose.test.yml, docker-compose.ci.yml

If services are needed, they will be configured in the CI pipeline as service containers.

2.9 Build Output

Does the project have a build step?

LanguageHas BuildBuild Command
Node.js (with build script)Yesnpm run build / pnpm build
GoYesgo build ./...
RustYescargo build --release
JavaYesmvn package -DskipTests -B / ./gradlew assemble
PHPUsually no
PythonUsually no

Summary

Build PROJECT_PROFILE:

  • language, language_version, language_versions (for matrix)
  • package_manager, lock_file, install_cmd
  • linters: list of {name, command, config_file}
  • static_analyzers: list of {name, command}
  • test_framework, test_cmd, coverage_cmd
  • security_tools: list of {name, command}
  • has_build_step, build_cmd
  • has_typescript: boolean (for typecheck job)
  • services_needed: list of services for CI
  • source_dir: main source directory (src/, app/, lib/)

Step 3: Read Best Practices & Templates

code
Read skills/ci/references/BEST-PRACTICES.md

Select templates matching the platform and language:

GitHub Actions:

LanguageTemplate
PHPtemplates/github/php.yml
Node.jstemplates/github/node.yml
Pythontemplates/github/python.yml
Gotemplates/github/go.yml
Rusttemplates/github/rust.yml
Javatemplates/github/java.yml

GitLab CI:

LanguageTemplate
PHPtemplates/gitlab/php.yml
Node.jstemplates/gitlab/node.yml
Pythontemplates/gitlab/python.yml
Gotemplates/gitlab/go.yml
Rusttemplates/gitlab/rust.yml
Javatemplates/gitlab/java.yml

Read the selected template:

code
Read skills/ci/templates/<platform>/<language>.yml

Step 4: Generate Pipeline (Generate Mode)

Using the PROJECT_PROFILE, best practices, and template as a base, generate a customized CI pipeline.

4.1 GitHub Actions Generation

One workflow per concern — each file has its own triggers, permissions, concurrency:

FileNameJobsWhen to create
lint.ymlLintcode-style, static-analysis, rectorLinters or SA detected
tests.ymlTeststests (+ service containers)Always
build.ymlBuildbuildhas_build_step
security.ymlSecuritydependency-audit, dependency-reviewWANT_SECURITY

Why one file per concern:

  • Each check is a separate status check in PR — instantly see what failed
  • Independent triggers — security on schedule, tests on push/PR, build only after tests
  • Independent permissions — security may need security-events: write
  • Can disable/re-run one workflow without touching others
  • Branch protection rules can require specific workflows (e.g. require tests 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:

yaml
name: <Name>

on:
  push:
    branches: [main]
  pull_request:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

permissions:
  contents: read

Per-file job organization:

lint.yml — all code quality checks in parallel:

JobPurposeWhen to include
code-styleFormatting (CS-Fixer, Prettier, Ruff format, rustfmt)Formatter detected
lintLinting (ESLint, Ruff check, Clippy, golangci-lint)Linter detected
static-analysisType checking / SA (PHPStan, Psalm, mypy, tsc)SA tools detected
rectorRector 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:

JobPurposeWhen to include
testsUnit/integration testsAlways
tests-<service>Tests requiring service containersservices_needed detected

Matrix builds (multiple language versions) only in this file.

build.yml — build verification:

JobPurposeNotes
buildVerify compilation/bundlingCan depend on external workflow via workflow_run or just run independently

security.yml — security scanning:

JobPurposeExtra triggers
dependency-auditVulnerability scanschedule: cron '0 6 * * 1' (weekly)
dependency-reviewPR dependency diffOnly on pull_request

Per-job rules:

  1. Each job gets its own setup (checkout, language setup, cache, dependency install)
  2. Use language-specific setup actions with built-in cache:
    • PHP: shivammathur/setup-php@v2 with tools: parameter
    • Node.js: actions/setup-node@v4 with cache: parameter
    • Python: astral-sh/setup-uv@v5 (if uv) or actions/setup-python@v5 (if pip)
    • Go: actions/setup-go@v5 (auto-caches)
    • Rust: dtolnay/rust-toolchain@stable + Swatinem/rust-cache@v2
    • Java: actions/setup-java@v4 with cache: parameter
  3. Use fail-fast: false in matrix builds
  4. Upload coverage as artifact when WANT_COVERAGE

Matrix builds (when WANT_MATRIX):

Only the tests job uses a matrix. Lint/SA jobs run on the latest version only.

yaml
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: php-cs-fixer check + other lint -> code-style job
  • Node.js: eslint + prettier -> lint job. Biome replaces BOTH ESLint and Prettier — if Biome is detected, use only npx biome check . in a single lint job
  • Python: ruff check + ruff format --check -> lint job (Ruff handles both)
  • Rust: 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.

security.yml example (when WANT_SECURITY):

yaml
name: Security

on:
  push:
    branches: [main]
  pull_request:
  schedule:
    - cron: '0 6 * * 1'  # Weekly on Monday

permissions:
  contents: read

jobs:
  dependency-audit:
    name: Dependency Audit
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      # Language-specific: composer audit / govulncheck / npm audit / cargo deny

  dependency-review:
    name: Dependency Review
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    steps:
      - uses: actions/checkout@v4
      - uses: actions/dependency-review-action@v4
        with:
          fail-on-severity: high

tests.yml example:

yaml
name: Tests

on:
  push:
    branches: [main]
  pull_request:

concurrency:
  group: tests-${{ github.ref }}
  cancel-in-progress: true

permissions:
  contents: read

jobs:
  tests:
    name: Tests
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      # Language-specific setup + test command

4.2 GitLab CI Generation

Output file: .gitlab-ci.yml

Pipeline structure:

yaml
stages:
  - install
  - lint
  - test
  - build

workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

default:
  interruptible: true

Job organization:

StageJobsNotes
installinstallInstall dependencies, cache + artifact for downstream
lintcode-style, lint, static-analysis, rectorAll needs: [install], run in parallel
testtestsneeds: [install]
buildbuildneeds: [tests, lint, ...]
securitysecurityneeds: [install], allow_failure: true

GitLab-specific features:

  1. Cache strategy: Use policy: pull-push on install job, policy: pull on all others
  2. Cache key: Use key: files: with lock file for automatic invalidation
  3. Artifacts: Pass vendor//node_modules/ via artifacts from install job (faster than cache for same-pipeline)
  4. Reports: Use artifacts.reports.junit for test results, artifacts.reports.codequality for lint output
  5. DAG: Use needs: keyword for parallel execution within stages
  6. Hidden jobs: Use .setup anchors for shared before_script and cache config
  7. Coverage regex: Add coverage: regex for test jobs

PHP-specific GitLab patterns:

yaml
image: php:8.3-cli

variables:
  COMPOSER_HOME: $CI_PROJECT_DIR/.composer

.composer-setup:
  before_script:
    - apt-get update && apt-get install -y git unzip
    - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

Report formats for GitLab integration:

ToolFlagReport Type
PHPStan--error-format=gitlabcodequality
ESLint--format jsoncodequality
Ruff--output-format=gitlabcodequality
golangci-lint--out-format code-climatecodequality
PHPUnit--log-junit report.xmljunit
Jest--reporters=jest-junitjunit
pytest--junitxml=report.xmljunit

4.3 Service Containers

If services_needed is not empty, add service containers to the test job:

GitHub Actions:

yaml
tests:
  services:
    postgres:
      image: postgres:17
      env:
        POSTGRES_DB: test
        POSTGRES_USER: test
        POSTGRES_PASSWORD: test
      ports:
        - 5432:5432
      options: >-
        --health-cmd pg_isready
        --health-interval 10s
        --health-timeout 5s
        --health-retries 5

GitLab CI:

yaml
tests:
  services:
    - name: postgres:17
      alias: db
  variables:
    POSTGRES_DB: test
    POSTGRES_USER: test
    POSTGRES_PASSWORD: test
    DATABASE_URL: "postgresql://test:test@db:5432/test"

Quality Checks (Before Writing)

Verify generated pipeline before writing:

Correctness:

  • Every job has checkout/setup/install steps
  • Cache is configured for the correct lock file
  • All commands match tools actually present in the project
  • Matrix versions match the project's version constraints
  • Service containers have health checks

Best practices:

  • concurrency group set (GitHub Actions)
  • permissions: contents: read set (GitHub Actions)
  • interruptible: true set (GitLab CI)
  • workflow.rules defined (GitLab CI)
  • Jobs are parallel where possible (no unnecessary needs)
  • fail-fast: false on matrix builds

No over-engineering:

  • No jobs for tools not present in the project
  • No matrix builds if the project only targets one version
  • No security scanning unless requested or tools are installed
  • No build job if the project has no build step

Step 5: Enhance / Audit Existing Pipeline

When MODE = "enhance" or MODE = "audit", analyze EXISTING_CONTENT against the project profile and best practices.

5.1 Gap Analysis

Compare existing pipeline against PROJECT_PROFILE:

Missing jobs:

  • Linter installed but no lint job in CI?
  • SA tool installed but no SA job?
  • Tests exist but no test job?
  • Security tools installed but no security job?

Configuration issues:

  • No caching configured?
  • No concurrency group (GitHub Actions)?
  • Using deprecated actions (e.g., actions-rs instead of dtolnay/rust-toolchain)?
  • Hardcoded language versions instead of variable/matrix?
  • Missing fail-fast: false on matrix?
  • Using policy: pull-push on all GitLab jobs instead of pull on non-install jobs?

Missing features:

  • No coverage reporting when coverage tools are available?
  • No JUnit/codequality report integration (GitLab)?
  • No path filtering for monorepos?
  • No workflow_dispatch trigger (GitHub Actions)?

5.2 Audit Report

code
## CI Pipeline Audit

### Jobs
| Check | Status | Detail |
|-------|--------|--------|
| Code style job | ✅ | php-cs-fixer dry-run |
| Static analysis | ❌ | PHPStan installed but no CI job |
| Rector check | ❌ | rector.php exists but no CI job |
| Tests | ✅ | PHPUnit with coverage |
| Security audit | ❌ | No dependency scanning |

### Configuration
| Check | Status | Detail |
|-------|--------|--------|
| Caching | ⚠️ | Missing composer cache |
| Concurrency | ❌ | No concurrency group |
| Permissions | ❌ | No explicit permissions |
| Matrix builds | ⚠️ | Only PHP 8.3, missing 8.2 |

### Recommendations
1. CRITICAL: Add PHPStan job — phpstan.neon exists
2. CRITICAL: Add Rector dry-run job — rector.php exists
3. HIGH: Add concurrency group to cancel redundant runs
4. HIGH: Add composer cache for faster installs
5. MEDIUM: Add security audit job (composer audit)
6. LOW: Add PHP 8.2 to test matrix

5.3 Fix Issues

code
AskUserQuestion: CI audit found issues. What should we do?

Options:
1. Fix all — Apply all recommendations
2. Fix critical only — Add missing jobs, skip configuration improvements
3. Show details — Explain each issue before deciding

If fixing:

  • For missing jobs -> add new jobs to existing pipeline
  • For configuration issues -> edit existing jobs
  • Preserve existing structure, job names, and ordering conventions
  • For GitHub Actions: edit in-place or add new workflow files
  • For GitLab CI: edit .gitlab-ci.yml in-place

Step 6: Write Files

6.1 Generate Mode — Write Pipeline

GitHub Actions:

code
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_SECURITY

Only 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:

code
Write .gitlab-ci.yml

GitLab CI uses a single .gitlab-ci.yml — stages and DAG (needs:) handle separation.

6.2 Enhance / Audit Mode — Update Existing

Edit existing files using the Edit tool. Preserve the original structure and only add/modify what's needed.


Step 7: Summary & Follow-Up

7.1 Display Summary

code
## CI Pipeline Generated

### Platform
GitHub Actions

### Files Created
| File | Purpose |
|------|---------|
| .github/workflows/lint.yml | code-style, static-analysis, rector |
| .github/workflows/tests.yml | phpunit (PHP 8.2, 8.3, 8.4) |
| .github/workflows/security.yml | composer audit |

### Features
- Composer caching via shivammathur/setup-php
- Concurrency groups (cancel redundant runs)
- Matrix builds for PHP 8.2, 8.3, 8.4
- Coverage upload as artifact

### Quick Start
  # Trigger manually
  gh workflow run ci.yml

  # View runs
  gh run list --workflow=ci.yml

7.2 Suggest Follow-Up Skills

code
AskUserQuestion: CI pipeline is ready. What's next?

Options:
1. Build automation — Run /ai-factory.build-automation to add CI targets to Makefile/Taskfile
2. Docker setup — Run /ai-factory.dockerize to containerize the project
3. Both
4. Done — Skip follow-ups