diff --git a/.github/workflows/reusable-ci-pipeline.yml b/.github/workflows/reusable-ci-pipeline.yml index b514b38..f642855 100644 --- a/.github/workflows/reusable-ci-pipeline.yml +++ b/.github/workflows/reusable-ci-pipeline.yml @@ -6,140 +6,142 @@ name: Reusable CI Pipeline on: workflow_call: - inputs: - node-version: - description: 'Node.js version' - required: false - type: string - default: '20' - python-version: - description: 'Python version' - required: false - type: string - default: '3.11' - run-tests: - description: 'Run tests' - required: false - type: boolean - default: true - run-lint: - description: 'Run linting' - required: false - type: boolean - default: true - run-security: - description: 'Run security scanning' - required: false - type: boolean - default: true - run-ai-review: - description: 'Run AI code review (PRs only)' - required: false - type: boolean - default: false - working-directory: - description: 'Working directory' - required: false - type: string - default: '.' - secrets: - ANTHROPIC_API_KEY: - required: false - SNYK_TOKEN: - required: false - - jobs: - detect: - name: Detect Language - runs-on: ubuntu-latest - outputs: - language: ${{ steps.detect.outputs.language }} - steps: - - uses: actions/checkout@v4 - - id: detect - working-directory: ${{ inputs.working-directory }} - run: | - if [ -f "package.json" ]; then - echo "language=node" >> $GITHUB_OUTPUT - elif [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then - echo "language=python" >> $GITHUB_OUTPUT - elif [ -f "go.mod" ]; then - echo "language=go" >> $GITHUB_OUTPUT - else - echo "language=unknown" >> $GITHUB_OUTPUT - fi - - lint: - name: Lint - needs: detect - if: inputs.run-lint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Setup Node.js - if: needs.detect.outputs.language == 'node' - uses: actions/setup-node@v4 - with: - node-version: ${{ inputs.node-version }} - cache: 'npm' - - name: Lint (Node) - if: needs.detect.outputs.language == 'node' - working-directory: ${{ inputs.working-directory }} - run: | - npm ci --ignore-scripts - npm run lint --if-present - - test: - name: Test - needs: detect - if: inputs.run-tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Setup Node.js - if: needs.detect.outputs.language == 'node' - uses: actions/setup-node@v4 - with: - node-version: ${{ inputs.node-version }} - cache: 'npm' - - name: Test (Node) - if: needs.detect.outputs.language == 'node' - working-directory: ${{ inputs.working-directory }} - run: | - npm ci - npm test --if-present - - security: - name: Security Scan - needs: detect - if: inputs.run-security - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: npm audit - if: needs.detect.outputs.language == 'node' - working-directory: ${{ inputs.working-directory }} - run: npm audit --audit-level=moderate || true - - name: Snyk scan - if: secrets.SNYK_TOKEN != '' - uses: snyk/actions/node@master - continue-on-error: true - env: - SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} - - ai-review: - name: AI Review - if: inputs.run-ai-review && github.event_name == 'pull_request' - runs-on: ubuntu-latest - permissions: - contents: read - pull-requests: write - steps: - - uses: actions/checkout@v4 - - name: Claude Review - if: secrets.ANTHROPIC_API_KEY != '' - uses: anthropics/claude-code-action@beta - with: - anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} - model: "claude-sonnet-4-20250514" - timeout_minutes: 10 + inputs: + node-version: + description: 'Node.js version' + required: false + type: string + default: '20' + python-version: + description: 'Python version' + required: false + type: string + default: '3.11' + run-tests: + description: 'Run tests' + required: false + type: boolean + default: true + run-lint: + description: 'Run linting' + required: false + type: boolean + default: true + run-security: + description: 'Run security scanning' + required: false + type: boolean + default: true + run-ai-review: + description: 'Run AI code review (PRs only)' + required: false + type: boolean + default: false + working-directory: + description: 'Working directory' + required: false + type: string + default: '.' + secrets: + ANTHROPIC_API_KEY: + required: false + SNYK_TOKEN: + required: false + +jobs: + detect: + name: Detect Language + runs-on: ubuntu-latest + outputs: + language: ${{ steps.detect.outputs.language }} + steps: + - uses: actions/checkout@v4 + - id: detect + working-directory: ${{ inputs.working-directory }} + run: | + if [ -f "package.json" ]; then + echo "language=node" >> $GITHUB_OUTPUT + elif [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then + echo "language=python" >> $GITHUB_OUTPUT + elif [ -f "go.mod" ]; then + echo "language=go" >> $GITHUB_OUTPUT + else + echo "language=unknown" >> $GITHUB_OUTPUT + fi + + lint: + name: Lint + needs: detect + if: inputs.run-lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup Node.js + if: needs.detect.outputs.language == 'node' + uses: actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version }} + cache: 'npm' + - name: Lint (Node) + if: needs.detect.outputs.language == 'node' + working-directory: ${{ inputs.working-directory }} + run: | + npm ci --ignore-scripts + npm run lint --if-present + + test: + name: Test + needs: detect + if: inputs.run-tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup Node.js + if: needs.detect.outputs.language == 'node' + uses: actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version }} + cache: 'npm' + - name: Test (Node) + if: needs.detect.outputs.language == 'node' + working-directory: ${{ inputs.working-directory }} + run: | + npm ci + npm test --if-present + + security: + name: Security Scan + needs: detect + if: inputs.run-security + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: npm audit + if: needs.detect.outputs.language == 'node' + working-directory: ${{ inputs.working-directory }} + run: npm audit --audit-level=moderate || true + - name: Snyk scan + if: env.SNYK_TOKEN != '' + uses: snyk/actions/node@master + continue-on-error: true + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + + ai-review: + name: AI Review + if: inputs.run-ai-review && github.event_name == 'pull_request' + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + steps: + - uses: actions/checkout@v4 + - name: Claude Review + if: env.ANTHROPIC_API_KEY != '' + uses: anthropics/claude-code-action@beta + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + model: "claude-sonnet-4-20250514" + timeout_minutes: 10