[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"public:announcements":3,"footer:categories:zh":4,"public:navigations:zh":132,"post:detail:post-28-CICDPipe:zh":177},[],[5,23,39,55,71,88,103,117],{"id":6,"name":7,"slug":12,"description":13,"icon":18,"color":19,"cover_image":20,"created_at":21,"post_count":22},1,{"en":8,"ja":9,"zh":10,"zh_Hant":11},"Technology","テクノロジー","技术","技術","technology",{"en":14,"ja":15,"zh":16,"zh_Hant":17},"Cutting-edge technology exploration and in-depth analysis covering programming languages, frameworks, and architecture design","プログラミング言語、フレームワーク、アーキテクチャ設計を含む先端技術の探究","前沿技术探索与深度分析，涵盖编程语言、框架、架构设计等核心领域","前沿技術探索與深度分析，涵蓋編程語言、框架、架構設計等核心領域","heroicons:cog-6-tooth","#6366f1",null,"2026-09-30T18:09:53.633610Z",8,{"id":24,"name":25,"slug":29,"description":30,"icon":35,"color":36,"cover_image":20,"created_at":37,"post_count":38},2,{"en":26,"ja":27,"zh":28,"zh_Hant":28},"Tutorial","チュートリアル","教程","tutorial",{"en":31,"ja":32,"zh":33,"zh_Hant":34},"Hands-on tutorials from scratch with clear steps and complete code for developers at all levels","ゼロから始める実践的なチュートリアル。明確な手順と完全なコードで、全てのレベルの開発者に最適","从零开始的实战教程，步骤清晰，代码完整，适合各阶段开发者学习","從零開始的實戰教程，步驟清晰，代碼完整，適合各階段開發者學習","heroicons:academic-cap","#10b981","2026-09-30T18:09:53.641581Z",6,{"id":40,"name":41,"slug":45,"description":46,"icon":51,"color":52,"cover_image":20,"created_at":53,"post_count":54},3,{"en":42,"ja":43,"zh":44,"zh_Hant":44},"Frontend","フロントエンド","前端","frontend",{"en":47,"ja":48,"zh":49,"zh_Hant":50},"Full coverage of web frontend development including Vue, React, new CSS features, and performance optimization","Vue、React、CSSの新機能やパフォーマンス最適化を含むWebフロントエンド開発の全領域","Web前端开发全栈覆盖，包括Vue、React、CSS新特性及性能优化等话题","Web前端開發全棧覆蓋，包括Vue、React、CSS新特性及性能優化等話題","heroicons:computer-desktop","#ec4899","2026-09-30T18:09:53.644838Z",7,{"id":56,"name":57,"slug":62,"description":63,"icon":68,"color":69,"cover_image":20,"created_at":70,"post_count":40},4,{"en":58,"ja":59,"zh":60,"zh_Hant":61},"Backend","バックエンド","后端","後端","backend",{"en":64,"ja":65,"zh":66,"zh_Hant":67},"Server-side development best practices including API design, database optimization, and microservices architecture","API設計、データベース最適化、マイクロサービスアーキテクチャを含むサーバーサイド開発の実践","服务端开发实战经验，API设计、数据库优化、微服务架构等深度内容","服務端開發實戰經驗，API設計、數據庫優化、微服務架構等深度內容","heroicons:server-stack","#f59e0b","2026-09-30T18:09:53.647836Z",{"id":72,"name":73,"slug":78,"description":79,"icon":84,"color":85,"cover_image":20,"created_at":86,"post_count":87},5,{"en":74,"ja":75,"zh":76,"zh_Hant":77},"Fullstack","フルスタック","全栈","全棧","fullstack",{"en":80,"ja":81,"zh":82,"zh_Hant":83},"End-to-end development guides covering the full project lifecycle and technology stack selection","フロントエンドからバックエンドまでの開発プロセス全体をカバーするガイド","从前端到后端的全流程开发指南，覆盖完整项目生命周期与技术选型","從前端到後端的全流程開發指南，覆蓋完整項目生命週期與技術選型","heroicons:swatch","#8b5cf6","2026-09-30T18:09:53.650513Z",0,{"id":38,"name":89,"slug":94,"description":95,"icon":100,"color":101,"cover_image":20,"created_at":102,"post_count":56},{"en":90,"ja":91,"zh":92,"zh_Hant":93},"Essays","エッセイ","随笔","隨筆","essays",{"en":96,"ja":97,"zh":98,"zh_Hant":99},"Technical reflections and development insights recording the programmer's growth journey","プログラマーの成長の軌跡を記録する技術的考察と開発の洞察","技术思考与开发心得分享，记录程序员成长路上的点滴感悟","技術思考與開發心得分享，記錄程序員成長路上的點滴感悟","heroicons:pencil-square","#f43f5e","2026-09-30T18:09:53.653105Z",{"id":54,"name":104,"slug":108,"description":109,"icon":114,"color":115,"cover_image":20,"created_at":116,"post_count":56},{"en":105,"ja":106,"zh":107,"zh_Hant":107},"Tools","ツール","工具","tools",{"en":110,"ja":111,"zh":112,"zh_Hant":113},"Development toolchain and productivity tool recommendations to supercharge your development experience","開発効率を飛躍的に向上させるツールチェーンと生産性ツールの推奨","开发工具链与效率提升利器推荐，让你的开发体验如虎添翼","開發工具鏈與效率提升利器推薦，讓你的開發體驗如虎添翼","heroicons:wrench-screwdriver","#06b6d4","2026-09-30T18:09:53.655605Z",{"id":22,"name":118,"slug":123,"description":124,"icon":129,"color":130,"cover_image":20,"created_at":131,"post_count":87},{"en":119,"ja":120,"zh":121,"zh_Hant":122},"Translation","翻訳","翻译","翻譯","translation",{"en":125,"ja":126,"zh":127,"zh_Hant":128},"Curated translations of high-quality foreign technical articles to keep up with international trends","国際的な技術トレンドを追うための厳選された海外技術記事の翻訳","优质外文技术文章精选翻译，紧跟国际技术前沿动态","優質外文技術文章精選翻譯，緊跟國際技術前沿動態","heroicons:language","#84cc16","2026-09-30T18:09:53.658041Z",[133,144,150,157,164,171],{"id":6,"title":134,"url":139,"icon":20,"parent_id":20,"location":140,"order":6,"is_active":141,"target_blank":142,"created_at":143,"updated_at":20},{"zh":135,"en":136,"ja":137,"zh_TW":138},"首页","Home","ホーム","首頁","\u002F","header",true,false,"2026-09-30T18:09:54.251095Z",{"id":24,"title":145,"url":149,"icon":20,"parent_id":20,"location":140,"order":24,"is_active":141,"target_blank":142,"created_at":143,"updated_at":20},{"zh":146,"en":147,"ja":148,"zh_TW":146},"文章","Posts","記事","\u002Fposts",{"id":40,"title":151,"url":156,"icon":20,"parent_id":20,"location":140,"order":40,"is_active":141,"target_blank":142,"created_at":143,"updated_at":20},{"zh":152,"en":153,"ja":154,"zh_TW":155},"分类","Categories","カテゴリー","分類","\u002Fcategories",{"id":56,"title":158,"url":163,"icon":20,"parent_id":20,"location":140,"order":56,"is_active":141,"target_blank":142,"created_at":143,"updated_at":20},{"zh":159,"en":160,"ja":161,"zh_TW":162},"标签","Tags","タグ","標籤","\u002Ftags",{"id":72,"title":165,"url":170,"icon":20,"parent_id":20,"location":140,"order":72,"is_active":141,"target_blank":142,"created_at":143,"updated_at":20},{"zh":166,"en":167,"ja":168,"zh_TW":169},"关于","About","概要","關於","\u002Fpage\u002Fabout",{"id":38,"title":172,"url":176,"icon":20,"parent_id":20,"location":140,"order":38,"is_active":141,"target_blank":142,"created_at":143,"updated_at":20},{"zh":173,"en":174,"ja":175,"zh_TW":173},"留言板","Guestbook","ゲストブック","\u002Fpage\u002Fguestbook",{"id":178,"title":179,"subtitle":20,"slug":180,"source":181,"source_url":20,"audio":20,"video":20,"video_url":20,"content":182,"excerpt":183,"cover_image":20,"author":184,"category":187,"tags":188,"status":211,"visibility":212,"password":20,"views":213,"likes_count":87,"is_pinned":142,"allow_comments":141,"comments_count":72,"is_password_protected":142,"meta_title":179,"meta_description":183,"meta_keywords":214,"created_at":215,"published_at":215,"updated_at":216,"reading_time":6},28,"CI\u002FCD Pipeline 设计：GitHub Actions + Cache + Matrix Build","post-28-CICDPipe","原创","# CI\u002FCD Pipeline 设计：GitHub Actions + Cache + Matrix Build\n\nCI\u002FCD 是研发效率的脊梁。设计差的流水线 PR 等 40 分钟、随机失败、无法复用；设计好的流水线 5 分钟内给出可信反馈，并发矩阵覆盖多版本多 OS，缓存命中让重复构建秒过。\n\n## 阶段拆分与路径过滤\n\n经典 5 阶段：(1) changes 路径过滤：未改动的子项目整段跳过（PR 只改文档不跑后端测试）；(2) lint 阶段快失败优先（8 分钟内出结果）；(3) test 多版本矩阵并发；(4) build 构建产物；(5) 打 tag 才执行 publish 推送镜像\u002F发布包。concurrency 同 ref 自动取消旧运行，节省 Action 分钟。\n\n```yaml\n```yaml\n.github\u002Fworkflows\u002Fci.yml\nname: CI\u002FCD Pipeline\n\non:\n  push:\n    branches: [main, develop]\n    tags: ['v*.*.*']\n  pull_request:\n    branches: [main, develop]\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\nenv:\n  REGISTRY: ghcr.io\n  IMAGE_NAME: ${{ github.repository }}\n\njobs:\n  changes:\n    runs-on: ubuntu-latest\n    outputs:\n      backend: ${{ steps.filter.outputs.backend }}\n      frontend: ${{ steps.filter.outputs.frontend }}\n      infra: ${{ steps.filter.outputs.infra }}\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: dorny\u002Fpaths-filter@v3\n        id: filter\n        with:\n          filters: |\n            backend:\n              - 'apps\u002Fapi\u002F**'\n              - 'packages\u002Fshared\u002F**'\n              - 'pyproject.toml'\n            frontend:\n              - 'apps\u002Fweb\u002F**'\n              - 'packages\u002Fui\u002F**'\n              - 'pnpm-lock.yaml'\n            infra:\n              - 'infra\u002F**'\n              - 'Dockerfile*'\n\n  lint:\n    needs: changes\n    if: needs.changes.outputs.backend == 'true' || needs.changes.outputs.frontend == 'true'\n    runs-on: ubuntu-latest\n    timeout-minutes: 8\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: pnpm\u002Faction-setup@v4\n        with: { version: 9 }\n      - uses: actions\u002Fsetup-node@v4\n        with:\n          node-version: 20\n          cache: pnpm\n          cache-dependency-path: pnpm-lock.yaml\n      - name: Install Node deps\n        run: pnpm install --frozen-lockfile --prefer-offline\n      - uses: actions\u002Fsetup-python@v5\n        with:\n          python-version: '3.12'\n          cache: pip\n          cache-dependency-path: pyproject.toml\n      - name: Install Python deps\n        run: pip install -e \".[dev]\" --retries 3\n      - name: Run ESLint + Ruff\n        run: |\n          pnpm lint\n          ruff check apps\u002Fapi packages\n      - name: Cache turbo setup\n        uses: actions\u002Fcache@v4\n        with:\n          path: .turbo\n          key: turbo-${{ github.sha }}\n          restore-keys: turbo-\n\n  test:\n    needs: lint\n    runs-on: ubuntu-latest\n    timeout-minutes: 20\n    strategy:\n      fail-fast: false\n      matrix:\n        python-version: ['3.11', '3.12', '3.13']\n        node-version: ['18', '20', '22']\n        os: [ubuntu-latest]\n        include:\n          - os: macos-latest\n            python-version: '3.12'\n            node-version: '20'\n    services:\n      postgres:\n        image: postgres:16-alpine\n        env: { POSTGRES_USER: test, POSTGRES_PASSWORD: test, POSTGRES_DB: test }\n        ports: ['5432:5432']\n        options: >-\n          --health-cmd pg_isready\n          --health-interval 10s --health-timeout 5s --health-retries 5\n      redis:\n        image: redis:7-alpine\n        ports: ['6379:6379']\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: pnpm\u002Faction-setup@v4; with: { version: 9 }\n      - uses: actions\u002Fsetup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n          cache: pnpm\n      - uses: actions\u002Fsetup-python@v5\n        with:\n          python-version: ${{ matrix.python-version }}\n          cache: pip\n      - run: pnpm install --frozen-lockfile\n      - run: pip install -e \".[test]\"\n      - name: Run tests with coverage\n        run: |\n          pnpm test -- --coverage --reporter=github\n          pytest apps\u002Fapi --cov=apps\u002Fapi --cov-report=xml\n        env:\n          DATABASE_URL: postgresql:\u002F\u002Ftest:test@localhost:5432\u002Ftest\n          REDIS_URL: redis:\u002F\u002Flocalhost:6379\n      - uses: codecov\u002Fcodecov-action@v4\n        if: matrix.os == 'ubuntu-latest' && matrix.node-version == '20' && matrix.python-version == '3.12'\n        with: { fail_ci_if_error: false, token: ${{ secrets.CODECOV_TOKEN }} }\n\n  build-and-push-image:\n    needs: test\n    if: github.event_name == 'push' && startsWith(github.ref, 'refs\u002Ftags\u002Fv')\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\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: ${{ env.REGISTRY }}\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: Extract metadata\n        id: meta\n        uses: docker\u002Fmetadata-action@v5\n        with:\n          images: ${{ env.REGISTRY }}\u002F${{ env.IMAGE_NAME }}\n          tags: |\n            type=semver,pattern={{version}}\n            type=semver,pattern={{major}}.{{minor}}\n            type=sha,prefix=\n      - name: Build and push\n        uses: docker\u002Fbuild-push-action@v6\n        with:\n          context: .\n          push: true\n          platforms: linux\u002Famd64,linux\u002Farm64\n          tags: ${{ steps.meta.outputs.tags }}\n          labels: ${{ steps.meta.outputs.labels }}\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n```\n```\n\n## 缓存矩阵构建加速三剑客\n\n(1) 依赖缓存：setup-node + pnpm cache、pip cache 让 90% 构建免装依赖；(2) 任务产物缓存：turbo cache 跨工作流复用构建结果；(3) Docker 层缓存：buildx gha cache 复用层，推送时间从 5 分钟缩到 40 秒。Matrix 跨 OS\u002F版本覆盖 Python 3.11-3.13 × Node 18-22，矩阵 include 注入 MacOS 单测确保 Unix 类兼容性。\n\n| 优化项 | 未优化耗时 | 优化后耗时 | 节省比例 |\n|--------|----------|----------|---------|\n| npm\u002Fpip 依赖安装 | 3min | 20s (95%命中) | 89% |\n| Turborepo 构建 | 6min | 15s (全命中) | 96% |\n| Docker 镜像推送 | 5min | 40s | 87% |\n| Matrix 顺序执行 | 30min | 6min (5并发) | 80% |\n| 路径过滤跳过 | 20min\u002F每次PR | 3min | 85% |\n\n## 最佳实践\n\ntimeout-minutes 每个 Job 强制上限防挂死；services 用 Postgres\u002FRedis 健康检查等待就绪后再跑；fail-fast:false 保证所有组合跑完不提前中断；最终 semver tag 触发发布流程，main 分支仅 build+test 止。","从零设计一套工业级 GitHub Actions 流水线：npm\u002Fpip 依赖缓存、多版本 Node\u002FPython Matrix 并行构建、Docker 镜像分层缓存、Lint+Test+Build+Publish 分阶段、条件执行、环境矩阵、失败重试和发布门禁最佳实践，附完整工作流代码。",{"id":6,"username":185,"nickname":185,"avatar":20,"cover_image":20,"bio":20,"website":20,"github":20,"avatar_source":20,"resolved_avatar_url":20,"title":20,"created_at":186},"Choyeon","2026-09-30T18:09:53.330367Z",{"id":54,"name":107,"slug":108,"description":112,"icon":114,"color":115,"cover_image":20,"created_at":116,"post_count":87},[189,194,199,205],{"id":6,"name":190,"slug":191,"color":192,"icon":20,"is_active":141,"created_at":193,"post_count":87},"Python","python","#3776ab","2026-09-30T18:09:53.663835Z",{"id":22,"name":195,"slug":196,"color":197,"icon":20,"is_active":141,"created_at":198,"post_count":87},"Node.js","nodejs","#339933","2026-09-30T18:09:53.685769Z",{"id":200,"name":201,"slug":202,"color":203,"icon":20,"is_active":141,"created_at":204,"post_count":87},9,"Docker","docker","#2496ed","2026-09-30T18:09:53.688173Z",{"id":206,"name":207,"slug":208,"color":209,"icon":20,"is_active":141,"created_at":210,"post_count":87},12,"Git","git","#f05032","2026-09-30T18:09:53.697858Z","published","public",193,"Git,Docker,Node.js,Python","2026-09-25T18:09:53.733462Z","2026-10-01T10:33:25.639153Z"]