Ci cd
Skill MARUCIE/openclaw-foundry/web/public/packs/spellbook-platform-engineer/skills/ci-cd
The curated AI Agent skill marketplace — 37K+ vetted skills, S/A/B/C ratings, deploy anywhere
npx -y skills add MARUCIE/openclaw-foundry --skill ci-cdAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when setting up or debugging GitHub Actions pipelines — adding quality gates, configuring OIDC cloud auth, building matrix test runs, publishing artifacts to GHCR/PyPI/npm, or promoting builds from staging to production.
SKILL.md
23.2 KB, as published. Nobody here has run it
是什么
这是一份 CI/CD(持续集成与持续交付)流水线规范,覆盖 GitHub Actions 的触发、缓存、矩阵测试、质量门禁、跨环境晋升等关键节点,让团队从手工部署升级到一键发版,且每次发版都自带质量保障。
怎么用
- 新项目立项时,按本规范拷贝标准 workflow 模板,5 分钟内就能跑通最小可用的 CI(持续集成)流程。
- 给流水线加单元测试、覆盖率、安全扫描等质量门禁时,对照文档中的标准门禁清单逐项启用。
- 配置云上部署 OIDC(开放身份连接)认证时,遵循免长期密钥章节的步骤,避免把 access key 写进 secrets。
- 流水线变慢时,按缓存与并行小节先加 cache,再做 job 拆分,目标 P95 时长控制在 8 分钟内。
- 从测试环境晋升到生产环境时,必须走文档约定的多环境晋升流程,加 manual approval(人工审批)兜底。
架构图
flowchart LR
A[Push 或 PR] --> B[Lint 与单测]
B --> C[构建产物]
C --> D[质量门禁]
D --> E[测试环境部署]
E --> F[人工审批晋升]
CI/CD with GitHub Actions
A complete reference for building robust, secure, and efficient CI/CD pipelines using GitHub Actions, covering everything from workflow anatomy to multi-environment deployment promotion.
When to Activate
- Creating or modifying a GitHub Actions workflow
- Adding a quality gate (coverage, lint, security scan) to a pipeline
- Setting up CD with environment promotion from staging to production
- Optimizing a slow CI pipeline with caching or parallelism
- Publishing a Docker image, Python package, or npm package from CI
- Configuring secrets and OIDC-based cloud authentication
Workflow Anatomy
Every GitHub Actions workflow is defined in .github/workflows/*.yml. Understanding the core building blocks is essential before composing pipelines.
Triggers
| Trigger | Use Case |
|---|---|
push | Run on commits to specified branches or tags |
pull_request | Run on PR open, sync, or reopen |
workflow_dispatch | Manual trigger with optional input parameters |
schedule | Cron-based triggers (e.g., nightly security scans) |
workflow_call | Reusable workflow called by another workflow |
Jobs
- Jobs run in parallel by default unless
needs:is specified. - Use
needs: [job-a, job-b]to declare dependencies; a job waits for all listed jobs to succeed. - Each job runs in a fresh virtual machine (or container).
Steps
uses:— invokes a reusable action from the marketplace or a local path.run:— executes a shell command directly on the runner.- Steps within a job share the same filesystem and runner environment.
Key Contexts
| Context | What It Provides |
|---|---|
github | Repo name, SHA, ref, event name, actor, run ID |
secrets | Encrypted secret values; never printed in logs |
env | Environment variables set at workflow, job, or step level |
matrix | Current values from the strategy matrix |
job | Current job status, container info |
Expression Syntax
All dynamic values use ${{ expression }} syntax:
if: github.ref == 'refs/heads/main'
run: echo "SHA is ${{ github.sha }}"
env:
BRANCH: ${{ github.ref_name }}
Minimal Workflow Skeleton
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tests
run: make test
Standard Pipeline Structure
The canonical stage sequence moves from fast feedback (lint) to slower gates (security), then publishing.
lint → test → build → security-scan → publish
Job Dependency Graph
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Lint
run: make lint
test:
needs: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Test
run: make test
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: make build
security-scan:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Security scan
run: make scan
publish:
needs: [build, security-scan]
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Publish
run: make publish
fail-fast Behavior
| Setting | When to Use |
|---|---|
fail-fast: true (default) | Sequential stage pipelines — stop early on first failure |
fail-fast: false | Matrix builds — collect all results before deciding |
Use fail-fast: false in matrix strategies so you see failures across all OS/version combinations rather than stopping at the first one.
Dependency Caching
Caching package manager dependencies is the single highest-impact optimization for CI speed. The key strategy: hash the lockfile so the cache automatically invalidates when dependencies change.
Cache Key Strategy
cache-key = runner-os + lockfile-hash
restore-key = runner-os (fallback to most recent cache)
Python
- uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip' # built-in caching, hashes requirements*.txt
For more control with pyproject.toml:
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml', '**/requirements*.txt') }}
restore-keys: |
${{ runner.os }}-pip-
Node.js
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm' # hashes package-lock.json automatically
For pnpm or yarn, set cache: 'pnpm' or cache: 'yarn' respectively.
Go
- uses: actions/setup-go@v5
with:
go-version: '1.22'
cache: true # caches $GOPATH/pkg/mod and build cache
Cache Hit Rate Tips
- Always commit lockfiles (
package-lock.json,poetry.lock,go.sum) to the repository. - Use
hashFiles('**/package-lock.json')to scope cache keys to the exact dependency set. - Restore keys act as fallbacks: a partial hit is better than no cache.
Matrix Builds
Matrix builds let a single job definition run across multiple configurations (language versions, operating systems) in parallel.
Matrix Strategy
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
python-version: ['3.11', '3.12', '3.13']
os: [ubuntu-latest, windows-latest]
include:
- python-version: '3.12'
os: ubuntu-latest
publish: true # custom flag for conditional steps
exclude:
- python-version: '3.11'
os: windows-latest # skip known unsupported combo
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: pip
- run: pytest
- name: Publish (only from designated matrix entry)
if: matrix.publish == true
run: make publish
Matrix Reference
| Feature | Syntax | Purpose |
|---|---|---|
| Access value | ${{ matrix.python-version }} | Use current dimension value in steps |
include | Adds extra key-value pairs to specific entries | Inject flags or override runner for one combo |
exclude | Removes specific combinations | Skip known broken or unnecessary combos |
fail-fast | false on matrix | See all failures, not just first |
Quality Gates
Coverage Threshold
Fail the build if coverage drops below the required threshold.
- name: Run tests with coverage
run: pytest --cov=src --cov-report=xml --cov-fail-under=80
- name: Upload coverage report
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
fail_ci_if_error: true
For Node.js with Jest:
- name: Run tests with coverage
run: jest --coverage --coverageThreshold='{"global":{"lines":80}}'
Inline Lint Annotations with reviewdog
reviewdog posts lint results as PR review comments, making issues visible without reading raw logs.
- uses: reviewdog/action-flake8@v3
with:
reporter: github-pr-review
level: warning
- uses: reviewdog/action-eslint@v1
with:
reporter: github-pr-review
eslint_flags: '--ext .js,.ts src/'
Branch Protection Rules
Configure these in GitHub Settings → Branches, not in workflow YAML:
- Required status checks: list every CI job name that must pass before merge.
- Required approvals: minimum 1 reviewer for
main. - Dismiss stale approvals: re-approval required after new commits are pushed.
- Require branches to be up to date: prevents merging outdated branches.
Security Scanning
- name: Python dependency audit
run: pip-audit
- name: Node audit
run: npm audit --audit-level=high
- name: Go vulnerability check
run: govulncheck ./...
For container scanning, integrate Trivy:
- uses: aquasecurity/trivy-action@master
with:
image-ref: ghcr.io/${{ github.repository }}:${{ github.sha }}
severity: 'CRITICAL,HIGH'
exit-code: '1'
Secrets and Environment Variables
Contexts
env:
APP_ENV: production # plain env var (visible in logs)
DB_HOST: ${{ vars.DB_HOST }} # repository variable (not secret, visible)
API_KEY: ${{ secrets.API_KEY }} # encrypted secret (masked in logs)
Variable Scoping
| Scope | Set In | Available To |
|---|---|---|
| Workflow | Top-level env: block | All jobs and steps |
| Job | env: under a specific job | All steps in that job |
| Step | env: under a specific step | That step only |
| Repository | GitHub Settings → Secrets and Variables | All workflows in the repo |
| Environment | GitHub Settings → Environments | Jobs using that environment |
$GITHUB_TOKEN Permissions
Declare only what the job requires (principle of least privilege):
permissions:
contents: read # read repo files
packages: write # push to GHCR
id-token: write # request OIDC token for cloud auth
pull-requests: write # post PR comments
checks: write # create check runs
Set permissions: {} at the workflow level, then grant specific permissions per job to minimize blast radius.
OIDC for Cloud Auth (No Long-Lived Credentials)
OIDC eliminates the need to store cloud credentials as GitHub secrets. The cloud provider verifies the workflow's identity token and grants temporary credentials.
AWS:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789:role/github-actions
aws-region: us-east-1
Requires an IAM role with a trust policy that allows token.actions.githubusercontent.com as an OIDC provider.
Google Cloud:
- uses: google-github-actions/auth@v2
with:
workload_identity_provider: projects/123/locations/global/workloadIdentityPools/my-pool/providers/github
service_account: [email protected]
Requires a Workload Identity Pool configured in GCP with a GitHub OIDC provider binding.
Azure:
- uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
Uses federated credentials on the Azure App Registration — no client secret stored.
CD and Environment Promotion
The standard promotion pattern: build once, deploy to staging automatically, then gate production behind a manual approval.
Staging → Production Pipeline
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build artifact
run: make build
- uses: actions/upload-artifact@v4
with:
name: app-artifact
path: dist/
deploy-staging:
environment: staging
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/download-artifact@v4
with:
name: app-artifact
path: dist/
- name: Deploy to staging
run: ./scripts/deploy.sh staging
smoke-test:
runs-on: ubuntu-latest
needs: deploy-staging
steps:
- name: Run smoke tests against staging
run: ./scripts/smoke-test.sh https://staging.example.com
deploy-production:
environment: production # required reviewers configured in GitHub Settings
runs-on: ubuntu-latest
needs: smoke-test
steps:
- uses: actions/download-artifact@v4
with:
name: app-artifact
path: dist/
- name: Deploy to production
run: ./scripts/deploy.sh production
- name: Notify on failure
if: failure()
run: ./scripts/notify-failure.sh "${{ job.status }}"
Environment Protection Configuration
Set these in GitHub Settings → Environments, not in YAML:
| Setting | Recommended Value |
|---|---|
| Required reviewers | 1–2 senior engineers for production |
| Wait timer | Optional: 5–10 min buffer before deployment |
| Deployment branches | Limit to main branch only |
| Environment secrets | Prod credentials scoped here, not at repo level |
Deployment Status
Use job.status in post-deploy notifications:
- name: Notify Slack
if: always()
uses: slackapi/slack-github-action@v1
with:
payload: '{"text": "Deploy to production: ${{ job.status }}"}'
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
Artifact and Package Publishing
Docker Image to GHCR
jobs:
publish-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/metadata-action@v5
id: meta
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=sha,prefix=,suffix=,format=short
type=ref,event=branch
type=semver,pattern={{version}}
- uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.ref == 'refs/heads/main' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
Always tag images with the commit SHA. Never use latest as the only tag in production.
PyPI with Trusted Publishing (No Token Needed)
Configure a Trusted Publisher in PyPI project settings pointing to this repository and workflow, then:
jobs:
publish-pypi:
runs-on: ubuntu-latest
permissions:
id-token: write # required for trusted publishing
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: pip install build
- run: python -m build
- uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://upload.pypi.org/legacy/
# For pre-release testing:
# repository-url: https://test.pypi.org/legacy/
npm Publish
jobs:
publish-npm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm run build
- run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Complete Workflow Examples
Python Service
name: Python CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: pip
- run: pip install -e ".[dev]"
- run: ruff check .
- run: mypy src/
- run: pytest --cov=src --cov-report=xml --cov-fail-under=80
- run: pip-audit
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
TypeScript/Node Service
name: Node CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: npm
- run: npm ci
- run: npm run lint
- run: npm run typecheck
- run: npm test -- --coverage
- run: npm audit --audit-level=high
Go Service
name: Go CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.22'
cache: true
- run: go vet ./...
- run: staticcheck ./...
- run: go test -race -coverprofile=coverage.out ./...
- run: go tool cover -func=coverage.out
- run: govulncheck ./...
Decision Tables
Which Cache Approach to Use
| Language | Recommended Approach | Lockfile to Hash |
|---|---|---|
| Python | setup-python built-in cache: pip | requirements*.txt, pyproject.toml |
| Node.js | setup-node built-in cache: npm/pnpm | package-lock.json, pnpm-lock.yaml |
| Go | setup-go built-in cache: true | go.sum |
| Rust | actions/cache on ~/.cargo | Cargo.lock |
| Java/Maven | actions/cache on ~/.m2 | pom.xml |
When to Use OIDC vs Stored Secrets
| Credential Type | Use OIDC | Use Stored Secret |
|---|---|---|
| AWS IAM role | Yes | No — OIDC is the standard |
| GCP service account | Yes | No — Workload Identity preferred |
| Azure managed identity | Yes | No — Federated credentials preferred |
| NPM publish token | No | Yes — npm does not support OIDC |
| PyPI publish token | No (use Trusted Publishing) | Only if Trusted Publishing unavailable |
| Third-party API key | No | Yes |
Trigger Selection Guide
| Scenario | Recommended Trigger |
|---|---|
| Run CI on every PR | pull_request targeting main |
| Deploy on merge to main | push on main branch |
| Nightly dependency audit | schedule with cron |
| Manual production deploy | workflow_dispatch with input parameters |
| Shared CI logic across repos | workflow_call (reusable workflow) |
| Release on tag push | push with tags: ['v*'] |
Red Flags
- Storing cloud credentials as GitHub Secrets — long-lived access keys can be exfiltrated via PR log injection; use OIDC federated credentials (
aws-actions/configure-aws-credentials) instead - Hardcoding
runs-on: ubuntu-latestwithout version pinning —ubuntu-latestcan shift to a new OS major version mid-project, silently changing available toolchains; pin toubuntu-22.04for stability - Single monolithic job with 20+ steps — any step failure retries the entire job from scratch; split into separate jobs with
needs:so fast gates (lint) don't block slow ones (security scan) - Pushing to
mainwithout a required status check — branch protection "Required status checks" must be configured in GitHub Settings, not just in the YAML; YAML alone can be bypassed - Cache key without a lockfile hash — using
key: ${{ runner.os }}-pipwithouthashFiles(...)causes stale caches after dependency updates, producing false green builds - Tagging Docker images with only
latest—latestis overwritten on every build; a failed rollback cannot target a specific previous image; always add a commit SHA tag alongsidelatest - Using
pull_request_targetwithout careful filtering — this trigger runs in the context of the base branch and has access to secrets, making it exploitable by a forked PR that modifies the workflow - Skipping
--cov-fail-underor equivalent threshold — coverage upload without a fail threshold lets coverage silently drop to zero; the gate must actively fail the build
Checklist
- Workflow triggers cover both
pushto main andpull_request - Jobs run in correct dependency order using
needs: - Package manager caching configured (pip/npm/go modules)
- Lint, type-check, test, and security scan are all separate steps
- Coverage threshold enforced (
--cov-fail-under/--coverage) -
$GITHUB_TOKENpermissions scoped to least privilege - Secrets accessed via
${{ secrets.X }}— never hardcoded - OIDC used for cloud credentials — no long-lived access keys stored as secrets
- CD deploys to staging first; production requires approval via environment protection
- Docker images tagged with commit SHA, not
latest - Failed jobs produce clear error output; no silent failures
- Pipeline completes in under 10 minutes on a typical PR
Gives 0 of the 12 instructions most ci cd skills give
Counted across 392 of the 394 authors here whose files we hold, read 2026-08-06
- pin third-party actions to full commit SHAsin 33 of 392
- cache dependencies appropriatelyin 24 of 392, across 12 files
- optimize pipelines exceeding ten minutesin 20 of 392, across 6 files
- enforce all quality gates before mergein 20 of 392, across 7 files
- Configure branch protection rulesin 19 of 392, across 5 files
- use environments for deployment trackingin 19 of 392, across 7 files
- implement manual gates for productionin 19 of 392, across 7 files
- implement security scanningin 18 of 392, across 5 files
- fix failing code instead of disabling checksin 18 of 392, across 4 files
- use CI/CD variables for secretsin 18 of 392, across 6 files
- move checks upstream in the pipelinein 17 of 392, across 3 files
- use specific image tagsin 17 of 392, across 5 files
Said here and by no other author read
- keep P95 pipeline duration under eight minutes
- commit dependency lockfiles to repository
- fail builds when coverage drops below threshold
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once.