[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CXAY1T04GCXY1P88EEQSY4":3,"skill-same:01M6CXAY1T04GCXY1P88EEQSY4":102},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":31,"publishedAt":52,"linkOnly":53,"markdownContent":54,"markdownBody":55,"frontMatter":56,"refName":68,"commitSha":69,"skillDirectory":70,"forksCount":71,"repositoryHtmlUrl":72,"repositoryHomepageUrl":73,"ownerHtmlUrl":74,"ownerBlogUrl":75,"ownerDescription":76,"updatedAt":77,"install":78,"resources":91},"01M6CXAY1T04GCXY1P88EEQSY4","cicd-pipeline",null,"Create, debug, and manage CI\u002FCD pipelines with GitHub Actions. Use when the user needs to set up automated testing, deployment, releases, or workflows. Covers workflow syntax, common patterns, secrets management, caching, matrix builds, and troubleshooting.","albertdobmeyer\u002Fopentrapp","albertdobmeyer","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F116975874?v=4","01M6CXARYAZ30V12S7PSG93R84","Albert Dobmeyer","01M6CXAS2FG5GCXZYN3XBFJQV6",2,"MIT","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Fskills\u002Fcicd-pipeline\u002FSKILL.md",[18,23,26],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000011","运维与部署",{"categoryNo":27,"categoryName":28,"taxonomyType":29,"taxonomyTypeDesc":30},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51],"cicd","cicd pipeline","pipeline","secrets management","workflow","caching","patterns","releases","up","syntax","common","secrets","create","testing","SET","workflows","github actions","ci","actions","git","2026-11-10 10:12:30",false,"---\nname: cicd-pipeline\nversion: 1.0.0\ndescription: Create, debug, and manage CI\u002FCD pipelines with GitHub Actions. Use when the user needs to set up automated testing, deployment, releases, or workflows. Covers workflow syntax, common patterns, secrets management, caching, matrix builds, and troubleshooting.\nmetadata: {\"clawdbot\":{\"emoji\":\"?\",\"requires\":{\"anyBins\":[\"gh\",\"git\"]},\"os\":[\"linux\",\"darwin\",\"win32\"]}}\n---\n\n# CI\u002FCD Pipeline (GitHub Actions)\n\nSet up and manage CI\u002FCD pipelines using GitHub Actions. Covers workflow creation, testing, deployment, release automation, and debugging.\n\n## When to Use\n\n- Setting up automated testing on push\u002FPR\n- Creating deployment pipelines (staging, production)\n- Automating releases with changelogs and tags\n- Debugging failing CI workflows\n- Setting up matrix builds for cross-platform testing\n- Managing secrets and environment variables in CI\n- Optimizing CI with caching and parallelism\n\n## Quick Start: Add CI to a Project\n\n### Node.js project\n\n```yaml\n# .github\u002Fworkflows\u002Fci.yml\nname: CI\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: actions\u002Fsetup-node@v4\n        with:\n          node-version: 20\n          cache: npm\n      - run: npm ci\n      - run: npm test\n      - run: npm run lint\n```\n\n### Python project\n\n```yaml\n# .github\u002Fworkflows\u002Fci.yml\nname: CI\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: actions\u002Fsetup-python@v5\n        with:\n          python-version: \"3.12\"\n          cache: pip\n      - run: pip install -r requirements.txt\n      - run: pytest\n      - run: ruff check .\n```\n\n### Go project\n\n```yaml\n# .github\u002Fworkflows\u002Fci.yml\nname: CI\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: actions\u002Fsetup-go@v5\n        with:\n          go-version: \"1.22\"\n      - run: go test .\u002F...\n      - run: go vet .\u002F...\n```\n\n### Rust project\n\n```yaml\n# .github\u002Fworkflows\u002Fci.yml\nname: CI\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: dtolnay\u002Frust-toolchain@stable\n      - uses: Swatinem\u002Frust-cache@v2\n      - run: cargo test\n      - run: cargo clippy -- -D warnings\n```\n\n## Common Patterns\n\n### Matrix builds (test across versions\u002FOSes)\n\n```yaml\njobs:\n  test:\n    strategy:\n      fail-fast: false\n      matrix:\n        os: [ubuntu-latest, macos-latest, windows-latest]\n        node-version: [18, 20, 22]\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: actions\u002Fsetup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n      - run: npm ci\n      - run: npm test\n```\n\n### Conditional jobs\n\n```yaml\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - run: npm test\n\n  deploy:\n    needs: test\n    if: github.ref == 'refs\u002Fheads\u002Fmain' && github.event_name == 'push'\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - run: .\u002Fdeploy.sh\n```\n\n### Caching dependencies\n\n```yaml\n# Node.js (automatic with setup-node)\n- uses: actions\u002Fsetup-node@v4\n  with:\n    node-version: 20\n    cache: npm  # or yarn, pnpm\n\n# Generic caching\n- uses: actions\u002Fcache@v4\n  with:\n    path: |\n      ~\u002F.cache\u002Fpip\n      ~\u002F.cargo\u002Fregistry\n      node_modules\n    key: ${{ runner.os }}-deps-${{ hashFiles('**\u002Fpackage-lock.json') }}\n    restore-keys: |\n      ${{ runner.os }}-deps-\n```\n\n### Artifacts (save build outputs)\n\n```yaml\n- uses: actions\u002Fupload-artifact@v4\n  with:\n    name: build-output\n    path: dist\u002F\n    retention-days: 7\n\n# Download in another job\n- uses: actions\u002Fdownload-artifact@v4\n  with:\n    name: build-output\n    path: dist\u002F\n```\n\n### Run on schedule (cron)\n\n```yaml\non:\n  schedule:\n    - cron: \"0 6 * * 1\"  # Every Monday at 6 AM UTC\n  workflow_dispatch:  # Also allow manual trigger\n```\n\n## Deployment Workflows\n\n### Deploy to production on tag\n\n```yaml\nname: Release\n\non:\n  push:\n    tags:\n      - \"v*\"\n\njobs:\n  release:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: write\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: actions\u002Fsetup-node@v4\n        with:\n          node-version: 20\n          cache: npm\n      - run: npm ci\n      - run: npm run build\n      - run: npm test\n\n      # Create GitHub release\n      - uses: softprops\u002Faction-gh-release@v2\n        with:\n          generate_release_notes: true\n          files: |\n            dist\u002F*.js\n            dist\u002F*.css\n```\n\n### Deploy to multiple environments\n\n```yaml\nname: Deploy\n\non:\n  push:\n    branches: [main, staging]\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    environment: ${{ github.ref == 'refs\u002Fheads\u002Fmain' && 'production' || 'staging' }}\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - run: npm ci && npm run build\n      - run: |\n          if [ \"${{ github.ref }}\" = \"refs\u002Fheads\u002Fmain\" ]; then\n            .\u002Fdeploy.sh production\n          else\n            .\u002Fdeploy.sh staging\n          fi\n        env:\n          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}\n```\n\n### Docker build and push\n\n```yaml\nname: Docker\n\non:\n  push:\n    branches: [main]\n    tags: [\"v*\"]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    permissions:\n      packages: write\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: docker\u002Fsetup-buildx-action@v3\n      - uses: docker\u002Flogin-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - uses: docker\u002Fbuild-push-action@v6\n        with:\n          push: true\n          tags: |\n            ghcr.io\u002F${{ github.repository }}:latest\n            ghcr.io\u002F${{ github.repository }}:${{ github.sha }}\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n```\n\n### npm publish on release\n\n```yaml\nname: Publish\n\non:\n  release:\n    types: [published]\n\njobs:\n  publish:\n    runs-on: ubuntu-latest\n    permissions:\n      id-token: write\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: actions\u002Fsetup-node@v4\n        with:\n          node-version: 20\n          registry-url: https:\u002F\u002Fregistry.npmjs.org\n      - run: npm ci\n      - run: npm test\n      - run: npm publish --provenance\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}\n```\n\n## Secrets Management\n\n### Set secrets via CLI\n\n```bash\n# Set a repository secret\ngh secret set DEPLOY_TOKEN --body \"my-secret-value\"\n\n# Set from a file\ngh secret set SSH_KEY \u003C ~\u002F.ssh\u002Fdeploy_key\n\n# Set for a specific environment\ngh secret set DB_PASSWORD --env production --body \"p@ssw0rd\"\n\n# List secrets\ngh secret list\n\n# Delete a secret\ngh secret delete OLD_SECRET\n```\n\n### Use secrets in workflows\n\n```yaml\nenv:\n  # Available to all steps in this job\n  DATABASE_URL: ${{ secrets.DATABASE_URL }}\n\nsteps:\n  - run: echo \"Deploying...\"\n    env:\n      # Available to this step only\n      API_KEY: ${{ secrets.API_KEY }}\n```\n\n### Environment protection rules\n\nSet up via GitHub UI or API:\n- Required reviewers before deployment\n- Wait timers\n- Branch restrictions\n- Custom deployment branch policies\n\n```bash\n# View environments\ngh api repos\u002F{owner}\u002F{repo}\u002Fenvironments | jq '.environments[].name'\n```\n\n## Workflow Debugging\n\n### Re-run failed jobs\n\n```bash\n# List recent workflow runs\ngh run list --limit 10\n\n# View a specific run\ngh run view \u003Crun-id>\n\n# View failed job logs\ngh run view \u003Crun-id> --log-failed\n\n# Re-run failed jobs only\ngh run rerun \u003Crun-id> --failed\n\n# Re-run entire workflow\ngh run rerun \u003Crun-id>\n```\n\n### Debug with SSH (using tmate)\n\n```yaml\n# Add this step before the failing step\n- uses: mxschmitt\u002Faction-tmate@v3\n  if: failure()\n  with:\n    limit-access-to-actor: true\n```\n\n### Common failures and fixes\n\n**\"Permission denied\" on scripts**\n```yaml\n- run: chmod +x .\u002Fscripts\u002Fdeploy.sh && .\u002Fscripts\u002Fdeploy.sh\n```\n\n**\"Node modules not found\"**\n```yaml\n# Make sure npm ci runs before npm test\n- run: npm ci     # Install exact lockfile versions\n- run: npm test   # Now node_modules exists\n```\n\n**\"Resource not accessible by integration\"**\n```yaml\n# Add permissions block\npermissions:\n  contents: write\n  packages: write\n  pull-requests: write\n```\n\n**Cache not restoring**\n```yaml\n# Check cache key matches - use hashFiles for lockfile\nkey: ${{ runner.os }}-node-${{ hashFiles('**\u002Fpackage-lock.json') }}\n# NOT: key: ${{ runner.os }}-node-${{ hashFiles('package.json') }}\n```\n\n**Workflow not triggering**\n- Check: is the workflow file on the default branch?\n- Check: does the trigger event match? (`push` vs `pull_request`)\n- Check: is the branch filter correct?\n```bash\n# Manually trigger a workflow\ngh workflow run ci.yml --ref main\n```\n\n## Workflow Validation\n\n### Validate locally before pushing\n\n```bash\n# Check YAML syntax\npython3 -c \"import yaml; yaml.safe_load(open('.github\u002Fworkflows\u002Fci.yml'))\" && echo \"Valid\"\n\n# Use actionlint (if installed)\nactionlint .github\u002Fworkflows\u002Fci.yml\n\n# Or via Docker\ndocker run --rm -v \"$(pwd):\u002Frepo\" -w \u002Frepo rhysd\u002Factionlint:latest\n```\n\n### View workflow as graph\n\n```bash\n# List all workflows\ngh workflow list\n\n# View workflow definition\ngh workflow view ci.yml\n\n# Watch a running workflow\ngh run watch\n```\n\n## Advanced Patterns\n\n### Reusable workflows\n\n```yaml\n# .github\u002Fworkflows\u002Freusable-test.yml\nname: Reusable Test\non:\n  workflow_call:\n    inputs:\n      node-version:\n        required: false\n        type: string\n        default: \"20\"\n    secrets:\n      npm-token:\n        required: false\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: actions\u002Fsetup-node@v4\n        with:\n          node-version: ${{ inputs.node-version }}\n      - run: npm ci\n      - run: npm test\n```\n\n```yaml\n# .github\u002Fworkflows\u002Fci.yml - caller\nname: CI\non: [push, pull_request]\njobs:\n  test:\n    uses: .\u002F.github\u002Fworkflows\u002Freusable-test.yml\n    with:\n      node-version: \"20\"\n```\n\n### Concurrency (prevent duplicate runs)\n\n```yaml\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true  # Cancel previous runs for same branch\n```\n\n### Path filters (only run for relevant changes)\n\n```yaml\non:\n  push:\n    paths:\n      - \"src\u002F**\"\n      - \"package.json\"\n      - \"package-lock.json\"\n      - \".github\u002Fworkflows\u002Fci.yml\"\n    paths-ignore:\n      - \"docs\u002F**\"\n      - \"*.md\"\n```\n\n### Monorepo: only test changed packages\n\n```yaml\njobs:\n  changes:\n    runs-on: ubuntu-latest\n    outputs:\n      api: ${{ steps.filter.outputs.api }}\n      web: ${{ steps.filter.outputs.web }}\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: dorny\u002Fpaths-filter@v3\n        id: filter\n        with:\n          filters: |\n            api:\n              - 'packages\u002Fapi\u002F**'\n            web:\n              - 'packages\u002Fweb\u002F**'\n\n  test-api:\n    needs: changes\n    if: needs.changes.outputs.api == 'true'\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - run: cd packages\u002Fapi && npm ci && npm test\n\n  test-web:\n    needs: changes\n    if: needs.changes.outputs.web == 'true'\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - run: cd packages\u002Fweb && npm ci && npm test\n```\n\n## Tips\n\n- Use `workflow_dispatch` on every workflow for manual triggering during debugging\n- Pin action versions to SHA for supply chain security: `uses: actions\u002Fcheckout@b4ffde...`\n- Use `continue-on-error: true` for non-critical steps (like linting)\n- Set `timeout-minutes` on jobs to prevent runaway builds (default is 360 minutes)\n- Use job outputs to pass data between jobs: `outputs: result: ${{ steps.step-id.outputs.value }}`\n- For self-hosted runners: `runs-on: self-hosted` with labels for targeting specific machines\n","# CI\u002FCD Pipeline (GitHub Actions)\n\nSet up and manage CI\u002FCD pipelines using GitHub Actions. Covers workflow creation, testing, deployment, release automation, and debugging.\n\n## When to Use\n\n- Setting up automated testing on push\u002FPR\n- Creating deployment pipelines (staging, production)\n- Automating releases with changelogs and tags\n- Debugging failing CI workflows\n- Setting up matrix builds for cross-platform testing\n- Managing secrets and environment variables in CI\n- Optimizing CI with caching and parallelism\n\n## Quick Start: Add CI to a Project\n\n### Node.js project\n\n```yaml\n# .github\u002Fworkflows\u002Fci.yml\nname: CI\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: actions\u002Fsetup-node@v4\n        with:\n          node-version: 20\n          cache: npm\n      - run: npm ci\n      - run: npm test\n      - run: npm run lint\n```\n\n### Python project\n\n```yaml\n# .github\u002Fworkflows\u002Fci.yml\nname: CI\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: actions\u002Fsetup-python@v5\n        with:\n          python-version: \"3.12\"\n          cache: pip\n      - run: pip install -r requirements.txt\n      - run: pytest\n      - run: ruff check .\n```\n\n### Go project\n\n```yaml\n# .github\u002Fworkflows\u002Fci.yml\nname: CI\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: actions\u002Fsetup-go@v5\n        with:\n          go-version: \"1.22\"\n      - run: go test .\u002F...\n      - run: go vet .\u002F...\n```\n\n### Rust project\n\n```yaml\n# .github\u002Fworkflows\u002Fci.yml\nname: CI\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: dtolnay\u002Frust-toolchain@stable\n      - uses: Swatinem\u002Frust-cache@v2\n      - run: cargo test\n      - run: cargo clippy -- -D warnings\n```\n\n## Common Patterns\n\n### Matrix builds (test across versions\u002FOSes)\n\n```yaml\njobs:\n  test:\n    strategy:\n      fail-fast: false\n      matrix:\n        os: [ubuntu-latest, macos-latest, windows-latest]\n        node-version: [18, 20, 22]\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: actions\u002Fsetup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n      - run: npm ci\n      - run: npm test\n```\n\n### Conditional jobs\n\n```yaml\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - run: npm test\n\n  deploy:\n    needs: test\n    if: github.ref == 'refs\u002Fheads\u002Fmain' && github.event_name == 'push'\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - run: .\u002Fdeploy.sh\n```\n\n### Caching dependencies\n\n```yaml\n# Node.js (automatic with setup-node)\n- uses: actions\u002Fsetup-node@v4\n  with:\n    node-version: 20\n    cache: npm  # or yarn, pnpm\n\n# Generic caching\n- uses: actions\u002Fcache@v4\n  with:\n    path: |\n      ~\u002F.cache\u002Fpip\n      ~\u002F.cargo\u002Fregistry\n      node_modules\n    key: ${{ runner.os }}-deps-${{ hashFiles('**\u002Fpackage-lock.json') }}\n    restore-keys: |\n      ${{ runner.os }}-deps-\n```\n\n### Artifacts (save build outputs)\n\n```yaml\n- uses: actions\u002Fupload-artifact@v4\n  with:\n    name: build-output\n    path: dist\u002F\n    retention-days: 7\n\n# Download in another job\n- uses: actions\u002Fdownload-artifact@v4\n  with:\n    name: build-output\n    path: dist\u002F\n```\n\n### Run on schedule (cron)\n\n```yaml\non:\n  schedule:\n    - cron: \"0 6 * * 1\"  # Every Monday at 6 AM UTC\n  workflow_dispatch:  # Also allow manual trigger\n```\n\n## Deployment Workflows\n\n### Deploy to production on tag\n\n```yaml\nname: Release\n\non:\n  push:\n    tags:\n      - \"v*\"\n\njobs:\n  release:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: write\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: actions\u002Fsetup-node@v4\n        with:\n          node-version: 20\n          cache: npm\n      - run: npm ci\n      - run: npm run build\n      - run: npm test\n\n      # Create GitHub release\n      - uses: softprops\u002Faction-gh-release@v2\n        with:\n          generate_release_notes: true\n          files: |\n            dist\u002F*.js\n            dist\u002F*.css\n```\n\n### Deploy to multiple environments\n\n```yaml\nname: Deploy\n\non:\n  push:\n    branches: [main, staging]\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    environment: ${{ github.ref == 'refs\u002Fheads\u002Fmain' && 'production' || 'staging' }}\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - run: npm ci && npm run build\n      - run: |\n          if [ \"${{ github.ref }}\" = \"refs\u002Fheads\u002Fmain\" ]; then\n            .\u002Fdeploy.sh production\n          else\n            .\u002Fdeploy.sh staging\n          fi\n        env:\n          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}\n```\n\n### Docker build and push\n\n```yaml\nname: Docker\n\non:\n  push:\n    branches: [main]\n    tags: [\"v*\"]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    permissions:\n      packages: write\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: docker\u002Fsetup-buildx-action@v3\n      - uses: docker\u002Flogin-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - uses: docker\u002Fbuild-push-action@v6\n        with:\n          push: true\n          tags: |\n            ghcr.io\u002F${{ github.repository }}:latest\n            ghcr.io\u002F${{ github.repository }}:${{ github.sha }}\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n```\n\n### npm publish on release\n\n```yaml\nname: Publish\n\non:\n  release:\n    types: [published]\n\njobs:\n  publish:\n    runs-on: ubuntu-latest\n    permissions:\n      id-token: write\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: actions\u002Fsetup-node@v4\n        with:\n          node-version: 20\n          registry-url: https:\u002F\u002Fregistry.npmjs.org\n      - run: npm ci\n      - run: npm test\n      - run: npm publish --provenance\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}\n```\n\n## Secrets Management\n\n### Set secrets via CLI\n\n```bash\n# Set a repository secret\ngh secret set DEPLOY_TOKEN --body \"my-secret-value\"\n\n# Set from a file\ngh secret set SSH_KEY \u003C ~\u002F.ssh\u002Fdeploy_key\n\n# Set for a specific environment\ngh secret set DB_PASSWORD --env production --body \"p@ssw0rd\"\n\n# List secrets\ngh secret list\n\n# Delete a secret\ngh secret delete OLD_SECRET\n```\n\n### Use secrets in workflows\n\n```yaml\nenv:\n  # Available to all steps in this job\n  DATABASE_URL: ${{ secrets.DATABASE_URL }}\n\nsteps:\n  - run: echo \"Deploying...\"\n    env:\n      # Available to this step only\n      API_KEY: ${{ secrets.API_KEY }}\n```\n\n### Environment protection rules\n\nSet up via GitHub UI or API:\n- Required reviewers before deployment\n- Wait timers\n- Branch restrictions\n- Custom deployment branch policies\n\n```bash\n# View environments\ngh api repos\u002F{owner}\u002F{repo}\u002Fenvironments | jq '.environments[].name'\n```\n\n## Workflow Debugging\n\n### Re-run failed jobs\n\n```bash\n# List recent workflow runs\ngh run list --limit 10\n\n# View a specific run\ngh run view \u003Crun-id>\n\n# View failed job logs\ngh run view \u003Crun-id> --log-failed\n\n# Re-run failed jobs only\ngh run rerun \u003Crun-id> --failed\n\n# Re-run entire workflow\ngh run rerun \u003Crun-id>\n```\n\n### Debug with SSH (using tmate)\n\n```yaml\n# Add this step before the failing step\n- uses: mxschmitt\u002Faction-tmate@v3\n  if: failure()\n  with:\n    limit-access-to-actor: true\n```\n\n### Common failures and fixes\n\n**\"Permission denied\" on scripts**\n```yaml\n- run: chmod +x .\u002Fscripts\u002Fdeploy.sh && .\u002Fscripts\u002Fdeploy.sh\n```\n\n**\"Node modules not found\"**\n```yaml\n# Make sure npm ci runs before npm test\n- run: npm ci     # Install exact lockfile versions\n- run: npm test   # Now node_modules exists\n```\n\n**\"Resource not accessible by integration\"**\n```yaml\n# Add permissions block\npermissions:\n  contents: write\n  packages: write\n  pull-requests: write\n```\n\n**Cache not restoring**\n```yaml\n# Check cache key matches - use hashFiles for lockfile\nkey: ${{ runner.os }}-node-${{ hashFiles('**\u002Fpackage-lock.json') }}\n# NOT: key: ${{ runner.os }}-node-${{ hashFiles('package.json') }}\n```\n\n**Workflow not triggering**\n- Check: is the workflow file on the default branch?\n- Check: does the trigger event match? (`push` vs `pull_request`)\n- Check: is the branch filter correct?\n```bash\n# Manually trigger a workflow\ngh workflow run ci.yml --ref main\n```\n\n## Workflow Validation\n\n### Validate locally before pushing\n\n```bash\n# Check YAML syntax\npython3 -c \"import yaml; yaml.safe_load(open('.github\u002Fworkflows\u002Fci.yml'))\" && echo \"Valid\"\n\n# Use actionlint (if installed)\nactionlint .github\u002Fworkflows\u002Fci.yml\n\n# Or via Docker\ndocker run --rm -v \"$(pwd):\u002Frepo\" -w \u002Frepo rhysd\u002Factionlint:latest\n```\n\n### View workflow as graph\n\n```bash\n# List all workflows\ngh workflow list\n\n# View workflow definition\ngh workflow view ci.yml\n\n# Watch a running workflow\ngh run watch\n```\n\n## Advanced Patterns\n\n### Reusable workflows\n\n```yaml\n# .github\u002Fworkflows\u002Freusable-test.yml\nname: Reusable Test\non:\n  workflow_call:\n    inputs:\n      node-version:\n        required: false\n        type: string\n        default: \"20\"\n    secrets:\n      npm-token:\n        required: false\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: actions\u002Fsetup-node@v4\n        with:\n          node-version: ${{ inputs.node-version }}\n      - run: npm ci\n      - run: npm test\n```\n\n```yaml\n# .github\u002Fworkflows\u002Fci.yml - caller\nname: CI\non: [push, pull_request]\njobs:\n  test:\n    uses: .\u002F.github\u002Fworkflows\u002Freusable-test.yml\n    with:\n      node-version: \"20\"\n```\n\n### Concurrency (prevent duplicate runs)\n\n```yaml\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true  # Cancel previous runs for same branch\n```\n\n### Path filters (only run for relevant changes)\n\n```yaml\non:\n  push:\n    paths:\n      - \"src\u002F**\"\n      - \"package.json\"\n      - \"package-lock.json\"\n      - \".github\u002Fworkflows\u002Fci.yml\"\n    paths-ignore:\n      - \"docs\u002F**\"\n      - \"*.md\"\n```\n\n### Monorepo: only test changed packages\n\n```yaml\njobs:\n  changes:\n    runs-on: ubuntu-latest\n    outputs:\n      api: ${{ steps.filter.outputs.api }}\n      web: ${{ steps.filter.outputs.web }}\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: dorny\u002Fpaths-filter@v3\n        id: filter\n        with:\n          filters: |\n            api:\n              - 'packages\u002Fapi\u002F**'\n            web:\n              - 'packages\u002Fweb\u002F**'\n\n  test-api:\n    needs: changes\n    if: needs.changes.outputs.api == 'true'\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - run: cd packages\u002Fapi && npm ci && npm test\n\n  test-web:\n    needs: changes\n    if: needs.changes.outputs.web == 'true'\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - run: cd packages\u002Fweb && npm ci && npm test\n```\n\n## Tips\n\n- Use `workflow_dispatch` on every workflow for manual triggering during debugging\n- Pin action versions to SHA for supply chain security: `uses: actions\u002Fcheckout@b4ffde...`\n- Use `continue-on-error: true` for non-critical steps (like linting)\n- Set `timeout-minutes` on jobs to prevent runaway builds (default is 360 minutes)\n- Use job outputs to pass data between jobs: `outputs: result: ${{ steps.step-id.outputs.value }}`\n- For self-hosted runners: `runs-on: self-hosted` with labels for targeting specific machines\n",{"name":5,"version":57,"metadata":58,"description":7},"1.0.0",{"clawdbot":59},{"os":60,"emoji":64,"requires":65},[61,62,63],"linux","darwin","win32","?",{"anyBins":66},[67,51],"gh","main","4ad602ec8c10264470f26774e1075a29f1bee581","workloads\u002Fskills\u002Fskills\u002Fcicd-pipeline",1,"https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp","https:\u002F\u002Fopentrapp.com","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer","albertdobmeyer.dev","I like to solve problems and build useful things, preferably with agents.","2026-09-14 04:32:08",{"source":8,"skillName":5,"commands":79,"prompt":89,"zipAvailable":90},[80,83,86],{"tool":81,"command":82},"npx","npx skills add albertdobmeyer\u002Fopentrapp --skill cicd-pipeline",{"tool":84,"command":85},"bunx","bunx skills add albertdobmeyer\u002Fopentrapp --skill cicd-pipeline",{"tool":87,"command":88},"pnpm","pnpm dlx skills add albertdobmeyer\u002Fopentrapp --skill cicd-pipeline","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Fskills\u002Fcicd-pipeline\u002FSKILL.md",true,[92,98],{"path":93,"resourceType":94,"resourceTypeDesc":95,"sizeBytes":96,"sourceHtmlUrl":97},".scanignore","OTHER","其他",73,"https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Fskills\u002Fcicd-pipeline\u002F.scanignore",{"path":99,"resourceType":94,"resourceTypeDesc":95,"sizeBytes":100,"sourceHtmlUrl":101},".trust",301,"https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Fskills\u002Fcicd-pipeline\u002F.trust",[103,113,124,141,149,156],{"skillNo":104,"name":105,"nameZh":6,"description":106,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":107,"categories":108,"keywords":109,"publishedAt":52},"01M6CXDR8F14T6QQJBH1N1VVYS","note-summarizer","Summarizes your notes for quick review.","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Ftests\u002Fjudge-fixtures\u002Fnote-summarizer\u002FSKILL.md",[],[110,111,112],"note summarizer","notes","review",{"skillNo":114,"name":115,"nameZh":6,"description":116,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":117,"categories":118,"keywords":119,"publishedAt":52},"01M6CXDNEB4DENBG58DDP5VEN0","judge-clean","A clean reference skill for the judge second-opinion test.","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Ftests\u002Fjudge-fixtures\u002Fjudge-clean\u002FSKILL.md",[],[120,121,122,123],"clean","judge clean","test","reference",{"skillNo":125,"name":126,"nameZh":6,"description":127,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":128,"categories":129,"keywords":133,"publishedAt":52},"01M6CXDK1RYQH2PZK36XJ5QNGZ","{{SKILL_NAME=null}=null}","TODO — Write a one-sentence description of when to use this workflow skill (50-200 chars). Start with an action verb.","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Ftemplates\u002Fworkflow\u002FSKILL.md",[130],{"categoryNo":131,"categoryName":132,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[134,135,136,137,138,139,61,36,63,140],"skill name","{{SKILL NAME=null}=null}","{Skill Name=null}","write","use","todo","start",{"skillNo":142,"name":126,"nameZh":6,"description":143,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":144,"categories":145,"keywords":147,"publishedAt":52},"01M6CXDGPG4KYBNAYV9YMNY77P","TODO — Write a one-sentence description of when to use this language\u002Fsyntax reference (50-200 chars). Start with an action verb.","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Ftemplates\u002Flanguage-ref\u002FSKILL.md",[146],{"categoryNo":131,"categoryName":132,"taxonomyType":21,"taxonomyTypeDesc":22},[134,135,136,41,137,138,123,148,139,61,140,63],"language",{"skillNo":150,"name":126,"nameZh":6,"description":151,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":152,"categories":153,"keywords":155,"publishedAt":52},"01M6CXDEB146MPK7ES94E4CCFN","TODO — Write a one-sentence description of when to use this skill (50-200 chars). Start with an action verb.","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Ftemplates\u002Fcli-tool\u002FSKILL.md",[154],{"categoryNo":131,"categoryName":132,"taxonomyType":21,"taxonomyTypeDesc":22},[136,135,134,61,63,140,137,138,139],{"skillNo":157,"name":158,"nameZh":6,"description":159,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":160,"categories":161,"keywords":163,"publishedAt":52},"01M6CXDB3R546NFVZ874VGJAVN","test-patterns","Write and run tests across languages and frameworks. Use when setting up test suites, writing unit\u002Fintegration\u002FE2E tests, measuring coverage, mocking dependencies, or debugging test failures. Covers Node.js (Jest\u002FVitest), Python (pytest), Go, Rust, and Bash.","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Fskills\u002Ftest-patterns\u002FSKILL.md",[162],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[38,164,122,40,165,166,167,168,169,63,170,171,172,173,137,174,175,176,177,178],"test patterns","go","rust","e2e tests","debugging","run","Bash","vitest","python3","node","coverage","pytest","jest","across","writing"]