{"product_id":"claude-code-github-actions-tự-dộng-hoa-ci-cd-với-ai","title":"Claude Code + GitHub Actions — Tự động hóa CI\/CD với AI","description":"\n\u003cp\u003eTrong quy trình phát triển phần mềm hiện đại, CI\/CD (Continuous Integration \/ Continuous Deployment) là xương sống giúp team ship code nhanh và ổn định. Nhưng phần lớn pipeline CI\/CD hiện tại chỉ chạy linting, build và test đã viết sẵn — chúng không thực sự \"hiểu\" code. Claude Code thay đổi điều này: một AI agent có khả năng đọc diff, phân tích logic, phát hiện lỗi bảo mật, sinh test case và thậm chí đưa ra quyết định deploy — tất cả chạy tự động trong GitHub Actions.\u003c\/p\u003e\n\u003cp\u003eBài viết này hướng dẫn bạn xây dựng một CI\/CD pipeline hoàn chỉnh tích hợp Claude Code, từ auto PR review đến deploy decision — kèm file workflow YAML sẵn sàng sử dụng.\u003c\/p\u003e\n\n\u003ch2\u003eTại sao cần Claude Code trong CI\/CD Pipeline?\u003c\/h2\u003e\n\u003cp\u003ePipeline CI\/CD truyền thống chỉ kiểm tra những gì bạn đã quy định trước: ESLint bắt lỗi cú pháp, unit test kiểm tra logic đã viết, build step đảm bảo code compile được. Nhưng chúng bỏ sót rất nhiều thứ quan trọng:\u003c\/p\u003e\n\u003cul\u003e\n  \u003cli\u003e\n\u003cstrong\u003eLogic bugs:\u003c\/strong\u003e Code chạy đúng cú pháp nhưng sai logic nghiệp vụ — static analysis không bắt được\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eSecurity vulnerabilities:\u003c\/strong\u003e SQL injection, XSS, hardcoded secrets — cần context để phát hiện\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eCode quality:\u003c\/strong\u003e Naming kém, function quá dài, thiếu error handling — reviewer phải đọc thủ công\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eMissing tests:\u003c\/strong\u003e Code mới thêm nhưng không có test đi kèm — dễ bị bỏ qua\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eDeploy risk:\u003c\/strong\u003e Thay đổi lớn ảnh hưởng nhiều module — cần đánh giá impact trước khi deploy\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003cp\u003eClaude Code giải quyết tất cả vấn đề này vì nó đọc và hiểu code như một senior developer. Khi tích hợp vào GitHub Actions, mỗi PR sẽ được review tự động, mỗi commit mới sẽ được phân tích, và quyết định deploy được hỗ trợ bằng AI.\u003c\/p\u003e\n\n\u003ch2\u003eKiến trúc tổng quan\u003c\/h2\u003e\n\u003cp\u003ePipeline CI\/CD với Claude Code gồm 3 tầng chính:\u003c\/p\u003e\n\u003col\u003e\n  \u003cli\u003e\n\u003cstrong\u003ePR Review Stage:\u003c\/strong\u003e Claude đọc diff, comment trực tiếp vào PR về quality, security, performance\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eTest Generation Stage:\u003c\/strong\u003e Claude sinh test case cho code mới, chạy và báo cáo kết quả\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eDeploy Decision Stage:\u003c\/strong\u003e Claude phân tích staging health, đánh giá risk level, quyết định có nên deploy production không\u003c\/li\u003e\n\u003c\/ol\u003e\n\u003cp\u003eMỗi tầng là một GitHub Actions workflow riêng biệt, có thể bật\/tắt độc lập.\u003c\/p\u003e\n\n\u003ch2\u003eThiết lập ban đầu\u003c\/h2\u003e\n\u003ch3\u003eYêu cầu\u003c\/h3\u003e\n\u003cul\u003e\n  \u003cli\u003eRepository trên GitHub (public hoặc private)\u003c\/li\u003e\n  \u003cli\u003eAnthropic API key với quyền truy cập Claude Code\u003c\/li\u003e\n  \u003cli\u003eGitHub Actions đã bật cho repository\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003ch3\u003eCấu hình Secrets\u003c\/h3\u003e\n\u003cp\u003eVào \u003cstrong\u003eSettings \u0026gt; Secrets and variables \u0026gt; Actions\u003c\/strong\u003e của repository, thêm các secret sau:\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003eANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxx\u003c\/code\u003e\u003c\/pre\u003e\n\u003cp\u003eQuan trọng: không bao giờ hardcode API key trong file workflow. Luôn sử dụng GitHub Secrets.\u003c\/p\u003e\n\n\u003ch2\u003eStage 1: Auto PR Review với Claude Code\u003c\/h2\u003e\n\u003cp\u003eĐây là stage có ROI cao nhất — mỗi PR được review tự động trong vài phút, phát hiện vấn đề trước khi human reviewer đọc code.\u003c\/p\u003e\n\n\u003ch3\u003eWorkflow file: \u003ccode\u003e.github\/workflows\/claude-pr-review.yml\u003c\/code\u003e\n\u003c\/h3\u003e\n\u003cpre\u003e\u003ccode\u003ename: Claude PR Review\n\non:\n  pull_request:\n    types: [opened, synchronize, reopened]\n\npermissions:\n  contents: read\n  pull-requests: write\n\njobs:\n  claude-review:\n    runs-on: ubuntu-latest\n    timeout-minutes: 10\n\n    steps:\n      - name: Checkout code\n        uses: actions\/checkout@v4\n        with:\n          fetch-depth: 0\n\n      - name: Install Claude Code\n        run: npm install -g @anthropic-ai\/claude-code\n\n      - name: Get PR diff\n        id: diff\n        run: |\n          git diff origin\/${{ github.base_ref }}...HEAD \u0026gt; \/tmp\/pr-diff.txt\n          echo \"diff_size=$(wc -l \u0026lt; \/tmp\/pr-diff.txt)\" \u0026gt;\u0026gt; $GITHUB_OUTPUT\n\n      - name: Claude Review\n        if: steps.diff.outputs.diff_size \u0026gt; 0\n        env:\n          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}\n        run: |\n          claude -p \"You are a senior code reviewer. Analyze this PR diff and provide feedback in Vietnamese.\n\n          Focus on:\n          1. Bug risks and logic errors\n          2. Security vulnerabilities (SQL injection, XSS, hardcoded secrets)\n          3. Performance issues\n          4. Code quality (naming, structure, error handling)\n          5. Missing edge cases\n\n          Format output as markdown with severity levels: 🔴 Critical, 🟡 Warning, 🟢 Suggestion.\n          Be concise. Only flag real issues, not style preferences.\n\n          $(cat \/tmp\/pr-diff.txt)\"           --max-turns 1           --output-format text \u0026gt; \/tmp\/review-result.txt\n\n      - name: Post review comment\n        if: steps.diff.outputs.diff_size \u0026gt; 0\n        uses: actions\/github-script@v7\n        with:\n          script: |\n            const fs = require('fs');\n            const review = fs.readFileSync('\/tmp\/review-result.txt', 'utf8');\n            await github.rest.issues.createComment({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              issue_number: context.issue.number,\n              body: '## 🤖 Claude Code Review\\n\\n' + review +\n                '\\n\\n---\\n*Auto-reviewed by Claude Code*'\n            });\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eCách hoạt động\u003c\/h3\u003e\n\u003col\u003e\n  \u003cli\u003eKhi PR được mở hoặc cập nhật, workflow tự động trigger\u003c\/li\u003e\n  \u003cli\u003eLấy diff giữa branch hiện tại và base branch\u003c\/li\u003e\n  \u003cli\u003eGửi diff cho Claude Code CLI với prompt review chuyên biệt\u003c\/li\u003e\n  \u003cli\u003eClaude phân tích và trả về feedback có cấu trúc\u003c\/li\u003e\n  \u003cli\u003eKết quả được post dưới dạng comment trên PR\u003c\/li\u003e\n\u003c\/ol\u003e\n\n\u003ch2\u003eStage 2: Tự động sinh test cho code mới\u003c\/h2\u003e\n\u003cp\u003eCode mới thêm mà không có test là nợ kỹ thuật. Claude Code có thể phân tích code mới trong PR và sinh test case phù hợp.\u003c\/p\u003e\n\n\u003ch3\u003eWorkflow file: \u003ccode\u003e.github\/workflows\/claude-test-gen.yml\u003c\/code\u003e\n\u003c\/h3\u003e\n\u003cpre\u003e\u003ccode\u003ename: Claude Test Generator\n\non:\n  pull_request:\n    types: [opened, synchronize]\n    paths:\n      - 'src\/**\/*.ts'\n      - 'src\/**\/*.js'\n      - '!src\/**\/*.test.*'\n      - '!src\/**\/*.spec.*'\n\npermissions:\n  contents: write\n  pull-requests: write\n\njobs:\n  generate-tests:\n    runs-on: ubuntu-latest\n    timeout-minutes: 15\n\n    steps:\n      - name: Checkout code\n        uses: actions\/checkout@v4\n        with:\n          ref: ${{ github.head_ref }}\n          fetch-depth: 0\n\n      - name: Setup Node.js\n        uses: actions\/setup-node@v4\n        with:\n          node-version: '20'\n\n      - name: Install dependencies\n        run: npm ci\n\n      - name: Install Claude Code\n        run: npm install -g @anthropic-ai\/claude-code\n\n      - name: Find new\/modified source files\n        id: changed\n        run: |\n          git diff --name-only --diff-filter=AM origin\/${{ github.base_ref }}...HEAD             -- 'src\/**\/*.ts' 'src\/**\/*.js'             ':!src\/**\/*.test.*' ':!src\/**\/*.spec.*' \u0026gt; \/tmp\/changed-files.txt\n          echo \"count=$(wc -l \u0026lt; \/tmp\/changed-files.txt)\" \u0026gt;\u0026gt; $GITHUB_OUTPUT\n\n      - name: Generate tests with Claude\n        if: steps.changed.outputs.count \u0026gt; 0\n        env:\n          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}\n        run: |\n          while IFS= read -r file; do\n            test_file=\"${file%.ts}.test.ts\"\n            if [ ! -f \"$test_file\" ]; then\n              echo \"Generating tests for: $file\"\n              claude -p \"Read this source file and generate comprehensive unit tests.\n\n              Use the existing test framework in the project (check package.json).\n              Cover: happy path, edge cases, error handling.\n              Follow existing test patterns in the codebase.\n              Output ONLY the test file content, no explanation.\n\n              Source file: $(cat \"$file\")\n\n              Related imports and types context:\n              $(head -50 \"$file\")\"               --max-turns 1               --output-format text \u0026gt; \"$test_file\"\n            fi\n          done \u0026lt; \/tmp\/changed-files.txt\n\n      - name: Run generated tests\n        if: steps.changed.outputs.count \u0026gt; 0\n        run: |\n          npm test -- --passWithNoTests 2\u0026gt;\u0026amp;1 | tee \/tmp\/test-results.txt\n          echo \"test_exit_code=${PIPESTATUS[0]}\" \u0026gt;\u0026gt; $GITHUB_ENV\n\n      - name: Commit generated tests\n        if: steps.changed.outputs.count \u0026gt; 0 \u0026amp;\u0026amp; env.test_exit_code == '0'\n        run: |\n          git config user.name \"claude-code[bot]\"\n          git config user.email \"claude-code[bot]@users.noreply.github.com\"\n          git add '*.test.ts' '*.test.js'\n          git diff --cached --quiet || git commit -m \"test: auto-generate tests via Claude Code\"\n          git push\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eLưu ý quan trọng\u003c\/h3\u003e\n\u003cul\u003e\n  \u003cli\u003e\n\u003cstrong\u003ePath filter:\u003c\/strong\u003e Workflow chỉ trigger khi có thay đổi trong \u003ccode\u003esrc\/\u003c\/code\u003e, bỏ qua file test\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eKiểm tra trùng:\u003c\/strong\u003e Chỉ sinh test cho file chưa có test tương ứng\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eValidation:\u003c\/strong\u003e Test sinh ra được chạy ngay — nếu fail thì không commit\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eAuto-commit:\u003c\/strong\u003e Test pass sẽ tự commit vào PR branch, reviewer chỉ cần approve\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003ch2\u003eStage 3: Deploy Decision — Claude đánh giá trước khi lên production\u003c\/h2\u003e\n\u003cp\u003eĐây là stage quan trọng nhất và cũng cần cẩn thận nhất. Claude Code phân tích nhiều tín hiệu để đưa ra khuyến nghị deploy.\u003c\/p\u003e\n\n\u003ch3\u003eWorkflow file: \u003ccode\u003e.github\/workflows\/claude-deploy-decision.yml\u003c\/code\u003e\n\u003c\/h3\u003e\n\u003cpre\u003e\u003ccode\u003ename: Claude Deploy Decision\n\non:\n  workflow_dispatch:\n    inputs:\n      environment:\n        description: 'Target environment'\n        required: true\n        default: 'production'\n        type: choice\n        options:\n          - staging\n          - production\n\npermissions:\n  contents: read\n  deployments: write\n  issues: write\n\njobs:\n  deploy-analysis:\n    runs-on: ubuntu-latest\n    timeout-minutes: 10\n    environment: ${{ github.event.inputs.environment }}\n\n    steps:\n      - name: Checkout code\n        uses: actions\/checkout@v4\n        with:\n          fetch-depth: 50\n\n      - name: Install Claude Code\n        run: npm install -g @anthropic-ai\/claude-code\n\n      - name: Gather deployment context\n        id: context\n        run: |\n          # Recent commits since last release tag\n          LAST_TAG=$(git describe --tags --abbrev=0 2\u0026gt;\/dev\/null || echo \"HEAD~20\")\n          git log --oneline \"$LAST_TAG\"..HEAD \u0026gt; \/tmp\/commits.txt\n\n          # Changed files summary\n          git diff --stat \"$LAST_TAG\"..HEAD \u0026gt; \/tmp\/changes-stat.txt\n\n          # Check for migration files\n          find . -path \"*\/migrations\/*\" -newer \"$LAST_TAG\"             -type f 2\u0026gt;\/dev\/null \u0026gt; \/tmp\/migrations.txt || true\n\n      - name: Staging health check\n        if: github.event.inputs.environment == 'production'\n        id: health\n        run: |\n          # Replace with your staging URL\n          STAGING_URL=\"${{ vars.STAGING_URL }}\"\n          if [ -n \"$STAGING_URL\" ]; then\n            HTTP_CODE=$(curl -s -o \/dev\/null -w \"%{http_code}\" \"$STAGING_URL\/health\" || echo \"000\")\n            echo \"status_code=$HTTP_CODE\" \u0026gt;\u0026gt; $GITHUB_OUTPUT\n          else\n            echo \"status_code=skip\" \u0026gt;\u0026gt; $GITHUB_OUTPUT\n          fi\n\n      - name: Claude Deploy Analysis\n        env:\n          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}\n        run: |\n          claude -p \"You are a DevOps engineer evaluating a deployment to ${{ github.event.inputs.environment }}.\n          Analyze the following data and provide a deploy recommendation in Vietnamese.\n\n          ## Commits since last release:\n          $(cat \/tmp\/commits.txt)\n\n          ## Changed files:\n          $(cat \/tmp\/changes-stat.txt)\n\n          ## Database migrations:\n          $(cat \/tmp\/migrations.txt)\n\n          ## Staging health status: ${{ steps.health.outputs.status_code || 'N\/A' }}\n\n          Provide:\n          1. RISK LEVEL: LOW \/ MEDIUM \/ HIGH \/ CRITICAL\n          2. Key changes summary (3-5 bullet points)\n          3. Potential risks and mitigation\n          4. Database migration warnings (if any)\n          5. RECOMMENDATION: PROCEED \/ HOLD \/ ABORT\n          6. If HOLD or ABORT, explain what needs to be done first\n\n          Be conservative — when in doubt, recommend HOLD.\"           --max-turns 1           --output-format text \u0026gt; \/tmp\/deploy-decision.txt\n\n      - name: Post decision\n        uses: actions\/github-script@v7\n        with:\n          script: |\n            const fs = require('fs');\n            const decision = fs.readFileSync('\/tmp\/deploy-decision.txt', 'utf8');\n            const env = '${{ github.event.inputs.environment }}';\n            await github.rest.issues.create({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              title: `[Deploy ${env}] AI Analysis - ${new Date().toISOString().slice(0,10)}`,\n              body: '## 🚀 Deploy Decision Report\\n\\n' +\n                `**Environment:** ${env}\\n` +\n                `**Triggered by:** @${context.actor}\\n\\n` +\n                decision +\n                '\\n\\n---\\n*Analyzed by Claude Code*',\n              labels: ['deployment', env]\n            });\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eCách sử dụng\u003c\/h3\u003e\n\u003cp\u003eWorkflow này sử dụng \u003ccode\u003eworkflow_dispatch\u003c\/code\u003e — bạn trigger thủ công từ tab Actions trên GitHub khi chuẩn bị deploy. Claude sẽ:\u003c\/p\u003e\n\u003col\u003e\n  \u003cli\u003eThu thập tất cả commits kể từ release tag gần nhất\u003c\/li\u003e\n  \u003cli\u003ePhân tích file thay đổi và đánh giá phạm vi ảnh hưởng\u003c\/li\u003e\n  \u003cli\u003eKiểm tra có migration mới không (rủi ro database)\u003c\/li\u003e\n  \u003cli\u003ePing staging health endpoint (nếu deploy production)\u003c\/li\u003e\n  \u003cli\u003eTổng hợp tất cả dữ liệu và đưa ra khuyến nghị PROCEED \/ HOLD \/ ABORT\u003c\/li\u003e\n\u003c\/ol\u003e\n\n\u003ch2\u003eKiểm soát chi phí: Budget và Token Limits\u003c\/h2\u003e\n\u003cp\u003eChạy Claude Code trong CI\/CD có thể tốn kém nếu không kiểm soát. Dưới đây là các chiến lược quản lý chi phí hiệu quả.\u003c\/p\u003e\n\n\u003ch3\u003eGiới hạn token mỗi workflow run\u003c\/h3\u003e\n\u003cpre\u003e\u003ccode\u003e# Trong mỗi step gọi Claude, thêm flag --max-turns\nclaude -p \"...\" --max-turns 1 --output-format text\n\n# max-turns 1 đảm bảo Claude chỉ trả lời 1 lượt\n# Không cho phép multi-turn conversation trong CI\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eGiới hạn kích thước diff\u003c\/h3\u003e\n\u003cpre\u003e\u003ccode\u003e# Thêm step kiểm tra trước khi gọi Claude\n- name: Check diff size\n  id: check_size\n  run: |\n    DIFF_LINES=$(wc -l \u0026lt; \/tmp\/pr-diff.txt)\n    if [ \"$DIFF_LINES\" -gt 2000 ]; then\n      echo \"skip=true\" \u0026gt;\u0026gt; $GITHUB_OUTPUT\n      echo \"⚠️ Diff too large ($DIFF_LINES lines). Skipping AI review.\"\n    else\n      echo \"skip=false\" \u0026gt;\u0026gt; $GITHUB_OUTPUT\n    fi\n\n# Sau đó dùng condition\n- name: Claude Review\n  if: steps.check_size.outputs.skip != 'true'\n  ...\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eChỉ review file quan trọng\u003c\/h3\u003e\n\u003cpre\u003e\u003ccode\u003e# Filter chỉ lấy file source code, bỏ generated files\ngit diff origin\/main...HEAD   -- '*.ts' '*.js' '*.py' '*.go'   ':!*.min.js' ':!*.bundle.*' ':!package-lock.json' ':!yarn.lock'   \u0026gt; \/tmp\/pr-diff.txt\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eBudget monitoring với labels\u003c\/h3\u003e\n\u003cpre\u003e\u003ccode\u003e# Thêm label estimate cost vào PR\n- name: Estimate cost\n  run: |\n    TOKENS=$(wc -w \u0026lt; \/tmp\/pr-diff.txt)\n    # Rough estimate: 1 word ≈ 1.3 tokens, input + output\n    EST_COST=$(echo \"scale=4; $TOKENS * 1.3 * 2 * 0.000003\" | bc)\n    echo \"Estimated API cost: ~$$EST_COST\"\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eBảng ước tính chi phí\u003c\/h3\u003e\n\u003cp\u003eVới Claude Sonnet (giá tại thời điểm viết bài):\u003c\/p\u003e\n\u003cul\u003e\n  \u003cli\u003e\n\u003cstrong\u003ePR Review nhỏ\u003c\/strong\u003e (100-500 dòng diff): ~$0.01-0.03 \/ review\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003ePR Review trung bình\u003c\/strong\u003e (500-1500 dòng): ~$0.03-0.08 \/ review\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eTest generation\u003c\/strong\u003e (1 file): ~$0.02-0.05 \/ file\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eDeploy decision\u003c\/strong\u003e: ~$0.01-0.03 \/ lần\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eTeam 5 devs, ~20 PR\/tuần:\u003c\/strong\u003e ước tính ~$5-15\/tháng\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003cp\u003eSo với chi phí 1 bug lọt lên production hoặc thời gian review thủ công, đây là khoản đầu tư rất hợp lý.\u003c\/p\u003e\n\n\u003ch2\u003eWorkflow nâng cao: Security Scan\u003c\/h2\u003e\n\u003cp\u003eNgoài 3 stage chính, bạn có thể thêm workflow chuyên kiểm tra bảo mật:\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003ename: Claude Security Scan\n\non:\n  pull_request:\n    paths:\n      - 'src\/**'\n      - 'api\/**'\n      - 'server\/**'\n\njobs:\n  security-scan:\n    runs-on: ubuntu-latest\n    timeout-minutes: 10\n\n    steps:\n      - uses: actions\/checkout@v4\n        with:\n          fetch-depth: 0\n\n      - name: Install Claude Code\n        run: npm install -g @anthropic-ai\/claude-code\n\n      - name: Security Analysis\n        env:\n          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}\n        run: |\n          git diff origin\/${{ github.base_ref }}...HEAD             -- '*.ts' '*.js' '*.py' \u0026gt; \/tmp\/code-diff.txt\n\n          claude -p \"You are a security engineer. Analyze this code diff for vulnerabilities.\n\n          Check for:\n          - SQL\/NoSQL injection\n          - XSS (Cross-Site Scripting)\n          - SSRF (Server-Side Request Forgery)\n          - Hardcoded secrets, API keys, passwords\n          - Insecure deserialization\n          - Path traversal\n          - Missing authentication\/authorization checks\n          - Insecure cryptographic usage\n          - CSRF vulnerabilities\n\n          For each finding:\n          - Severity: CRITICAL \/ HIGH \/ MEDIUM \/ LOW\n          - File and line reference\n          - Description of the vulnerability\n          - Suggested fix with code example\n\n          If no security issues found, say so clearly.\n          Output in Vietnamese.\"           --max-turns 1           --output-format text \u0026gt; \/tmp\/security-report.txt\n\n      - name: Post security report\n        uses: actions\/github-script@v7\n        with:\n          script: |\n            const fs = require('fs');\n            const report = fs.readFileSync('\/tmp\/security-report.txt', 'utf8');\n            const hasCritical = report.includes('CRITICAL');\n            await github.rest.issues.createComment({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              issue_number: context.issue.number,\n              body: '## 🔒 Security Scan Report\\n\\n' + report +\n                '\\n\\n---\\n*Scanned by Claude Code*'\n            });\n            if (hasCritical) {\n              core.setFailed('Critical security issues found!');\n            }\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003cp\u003eKhi phát hiện lỗ hổng mức CRITICAL, workflow sẽ fail và chặn merge PR — buộc developer phải sửa trước khi merge.\u003c\/p\u003e\n\n\u003ch2\u003eTroubleshooting: Các vấn đề thường gặp\u003c\/h2\u003e\n\n\u003ch3\u003e1. Workflow timeout\u003c\/h3\u003e\n\u003cp\u003e\u003cstrong\u003eTriệu chứng:\u003c\/strong\u003e Job chạy quá 10 phút rồi bị kill.\u003c\/p\u003e\n\u003cp\u003e\u003cstrong\u003eNguyên nhân:\u003c\/strong\u003e Diff quá lớn hoặc Claude bị kẹt multi-turn.\u003c\/p\u003e\n\u003cp\u003e\u003cstrong\u003eGiải pháp:\u003c\/strong\u003e\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003e# Luôn dùng --max-turns 1\nclaude -p \"...\" --max-turns 1 --output-format text\n\n# Giới hạn kích thước diff gửi cho Claude\nhead -2000 \/tmp\/pr-diff.txt \u0026gt; \/tmp\/pr-diff-truncated.txt\n\n# Tăng timeout nếu cần\ntimeout-minutes: 15\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003e2. API key bị lộ trong logs\u003c\/h3\u003e\n\u003cp\u003e\u003cstrong\u003eTriệu chứng:\u003c\/strong\u003e Key hiển thị trong workflow logs.\u003c\/p\u003e\n\u003cp\u003e\u003cstrong\u003eGiải pháp:\u003c\/strong\u003e Luôn dùng GitHub Secrets, không truyền qua command line argument:\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003e# SAI - key có thể lộ trong process list\nclaude -p \"...\" --api-key sk-ant-xxx\n\n# ĐÚNG - dùng environment variable\nenv:\n  ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003e3. Claude trả về kết quả không nhất quán\u003c\/h3\u003e\n\u003cp\u003e\u003cstrong\u003eTriệu chứng:\u003c\/strong\u003e Cùng một diff, review lần 1 khác lần 2.\u003c\/p\u003e\n\u003cp\u003e\u003cstrong\u003eGiải pháp:\u003c\/strong\u003e Đây là bản chất của LLM. Để giảm thiểu:\u003c\/p\u003e\n\u003cul\u003e\n  \u003cli\u003eViết prompt cụ thể, có cấu trúc rõ ràng\u003c\/li\u003e\n  \u003cli\u003eYêu cầu output theo format cố định (severity levels, sections)\u003c\/li\u003e\n  \u003cli\u003eTập trung vào phát hiện lỗi nghiêm trọng, không quá quan tâm style suggestions\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003ch3\u003e4. Rate limit từ Anthropic API\u003c\/h3\u003e\n\u003cp\u003e\u003cstrong\u003eTriệu chứng:\u003c\/strong\u003e Error 429 Too Many Requests.\u003c\/p\u003e\n\u003cp\u003e\u003cstrong\u003eGiải pháp:\u003c\/strong\u003e\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003e# Thêm concurrency limit trong workflow\nconcurrency:\n  group: claude-review-${{ github.ref }}\n  cancel-in-progress: true\n\n# Đảm bảo chỉ 1 Claude review chạy tại một thời điểm cho mỗi branch\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003e5. Permission denied khi post comment\u003c\/h3\u003e\n\u003cp\u003e\u003cstrong\u003eTriệu chứng:\u003c\/strong\u003e Workflow thành công nhưng không post được comment lên PR.\u003c\/p\u003e\n\u003cp\u003e\u003cstrong\u003eGiải pháp:\u003c\/strong\u003e Kiểm tra phần \u003ccode\u003epermissions\u003c\/code\u003e trong workflow file:\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003epermissions:\n  contents: read\n  pull-requests: write  # Cần quyền này để comment\n  issues: write         # Cần nếu tạo issue\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003e6. Diff chứa binary files hoặc quá nhiều noise\u003c\/h3\u003e\n\u003cp\u003e\u003cstrong\u003eGiải pháp:\u003c\/strong\u003e Filter trước khi gửi cho Claude:\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003e# Bỏ binary, lock files, generated code\ngit diff origin\/main...HEAD   --diff-filter=ACMR   -- '*.ts' '*.js' '*.tsx' '*.jsx' '*.py' '*.go'   ':!**\/generated\/**'   ':!**\/*.min.*'   ':!*lock*'   \u0026gt; \/tmp\/clean-diff.txt\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eBest practices khi vận hành\u003c\/h2\u003e\n\u003cul\u003e\n  \u003cli\u003e\n\u003cstrong\u003eBắt đầu nhỏ:\u003c\/strong\u003e Chỉ bật PR review trước, sau 2-4 tuần mới thêm test gen và deploy decision\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eTune prompt liên tục:\u003c\/strong\u003e Review kết quả Claude hàng tuần, điều chỉnh prompt cho phù hợp với codebase\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eKhông thay thế human review:\u003c\/strong\u003e Claude Code là \"first pass\" — giúp reviewer tập trung vào kiến trúc và logic nghiệp vụ thay vì code style\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eMonitor chi phí:\u003c\/strong\u003e Set up billing alert trên Anthropic Console, track usage theo team\/repo\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eTạo CLAUDE.md:\u003c\/strong\u003e Đặt file \u003ccode\u003eCLAUDE.md\u003c\/code\u003e ở root repo để hướng dẫn Claude Code về convention, architecture và tech stack của project — giúp review chính xác hơn\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eVersion control workflow:\u003c\/strong\u003e Commit các workflow YAML vào repo, review thay đổi prompt như review code\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eFail-safe:\u003c\/strong\u003e Không bao giờ để Claude tự động deploy production mà không có human approval gate\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003ch2\u003eTổng hợp: Pipeline hoàn chỉnh\u003c\/h2\u003e\n\u003cp\u003eSau khi thiết lập xong, quy trình CI\/CD với Claude Code hoạt động như sau:\u003c\/p\u003e\n\u003col\u003e\n  \u003cli\u003e\n\u003cstrong\u003eDeveloper tạo PR\u003c\/strong\u003e → Claude tự động review code, post comment với phát hiện\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eDeveloper push thêm commits\u003c\/strong\u003e → Claude re-review, sinh test cho code mới\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003ePR merged vào main\u003c\/strong\u003e → Build, test, deploy staging tự động\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eChuẩn bị deploy production\u003c\/strong\u003e → Trigger Claude Deploy Decision, nhận báo cáo risk assessment\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eTeam lead review báo cáo\u003c\/strong\u003e → Quyết định PROCEED hoặc HOLD dựa trên khuyến nghị AI + judgment\u003c\/li\u003e\n\u003c\/ol\u003e\n\u003cp\u003eToàn bộ quy trình này giúp team phát hiện bug sớm hơn, viết test đầy đủ hơn, và deploy tự tin hơn — trong khi giảm tải cognitive cho reviewer và tiết kiệm thời gian đáng kể.\u003c\/p\u003e\n\n\u003ch2\u003eBước tiếp theo\u003c\/h2\u003e\n\u003cp\u003eBạn đã có đủ workflow YAML để bắt đầu tích hợp Claude Code vào CI\/CD pipeline. Hãy bắt đầu với PR Review workflow — đây là bước đơn giản nhất và mang lại giá trị nhanh nhất. Sau khi team quen thuộc, dần bổ sung thêm test generation và deploy decision.\u003c\/p\u003e\n\u003cp\u003eĐể tìm hiểu thêm các ứng dụng khác của Claude Code trong phát triển phần mềm, truy cập \u003ca href=\"\/en\/collections\/ung-dung\"\u003eThư viện Ứng dụng Claude\u003c\/a\u003e.\u003c\/p\u003e\n","brand":"Minh Tuấn","offers":[{"title":"Default Title","offer_id":47730152046804,"sku":null,"price":0.0,"currency_code":"VND","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0821\/0264\/9044\/files\/claude-code-github-actions-t_-d_ng-hoa-ci-cd-v_i-ai.jpg?v=1774715663","url":"https:\/\/claude.vn\/en\/products\/claude-code-github-actions-t%e1%bb%b1-d%e1%bb%99ng-hoa-ci-cd-v%e1%bb%9bi-ai","provider":"CLAUDE.VN","version":"1.0","type":"link"}