diff --git a/.github/actions/slack-notify/action.yml b/.github/actions/slack-notify/action.yml new file mode 100644 index 0000000000..400a5b0482 --- /dev/null +++ b/.github/actions/slack-notify/action.yml @@ -0,0 +1,60 @@ +name: 'Slack Notification' +description: 'Send Slack notification for workflow failures' +inputs: + webhook-url: + description: 'Slack webhook URL' + required: true + channel: + description: 'Slack channel to notify' + required: true + workflow-name: + description: 'Name of the workflow' + required: true + failed-jobs: + description: 'JSON object containing job results' + required: true + +runs: + using: 'composite' + steps: + - name: Parse failed jobs + id: parse-jobs + shell: bash + run: | + echo "Parsing job results..." + failed_list="" + + # Parse the JSON and extract failed jobs + echo '${{ inputs.failed-jobs }}' | jq -r 'to_entries[] | select(.value.result == "failure") | .key' | while read job; do + case $job in + "check-translations") failed_list="${failed_list}❌ Translation check\n" ;; + "knip") failed_list="${failed_list}❌ Knip analysis\n" ;; + "compile") failed_list="${failed_list}❌ Compile & lint\n" ;; + "platform-unit-test") failed_list="${failed_list}❌ Unit tests\n" ;; + "integration-test") failed_list="${failed_list}❌ Integration tests\n" ;; + esac + done + + # Remove trailing newline and save to output + echo "failed_jobs<> $GITHUB_OUTPUT + echo -e "$failed_list" | sed '/^$/d' >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Send Slack notification + uses: 8398a7/action-slack@v3 + with: + status: failure + channel: ${{ inputs.channel }} + text: | + 🚨 ${{ inputs.workflow-name }} workflow failed on main branch! + + Repository: ${{ github.repository }} + Commit: ${{ github.sha }} + Author: ${{ github.actor }} + + Failed jobs: + ${{ steps.parse-jobs.outputs.failed_jobs }} + + View details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + env: + SLACK_WEBHOOK_URL: ${{ inputs.webhook-url }} \ No newline at end of file diff --git a/.github/workflows/code-qa.yml b/.github/workflows/code-qa.yml index e34b0964ff..bca8fa0c1c 100644 --- a/.github/workflows/code-qa.yml +++ b/.github/workflows/code-qa.yml @@ -1,86 +1,102 @@ name: Code QA Roo Code on: - workflow_dispatch: - push: - branches: [main] - pull_request: - types: [opened, reopened, ready_for_review, synchronize] - branches: [main] + workflow_dispatch: + push: + branches: [main] + pull_request: + types: [opened, reopened, ready_for_review, synchronize] + branches: [main] jobs: - check-translations: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - name: Setup Node.js and pnpm - uses: ./.github/actions/setup-node-pnpm - - name: Verify all translations are complete - run: node scripts/find-missing-translations.js + check-translations: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Setup Node.js and pnpm + uses: ./.github/actions/setup-node-pnpm + - name: Verify all translations are complete + run: node scripts/find-missing-translations.js - knip: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - name: Setup Node.js and pnpm - uses: ./.github/actions/setup-node-pnpm - - name: Run knip checks - run: pnpm knip + knip: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Setup Node.js and pnpm + uses: ./.github/actions/setup-node-pnpm + - name: Run knip checks + run: pnpm knip - compile: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - name: Setup Node.js and pnpm - uses: ./.github/actions/setup-node-pnpm - - name: Lint - run: pnpm lint - - name: Check types - run: pnpm check-types + compile: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Setup Node.js and pnpm + uses: ./.github/actions/setup-node-pnpm + - name: Lint + run: pnpm lint + - name: Check types + run: pnpm check-types - platform-unit-test: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, windows-latest] - steps: - - name: Checkout code - uses: actions/checkout@v4 - - name: Setup Node.js and pnpm - uses: ./.github/actions/setup-node-pnpm - - name: Run unit tests - run: pnpm test + platform-unit-test: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest] + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Setup Node.js and pnpm + uses: ./.github/actions/setup-node-pnpm + - name: Run unit tests + run: pnpm test - check-openrouter-api-key: - runs-on: ubuntu-latest - outputs: - exists: ${{ steps.openrouter-api-key-check.outputs.defined }} - steps: - - name: Check if OpenRouter API key exists - id: openrouter-api-key-check - shell: bash - run: | - if [ "${{ secrets.OPENROUTER_API_KEY }}" != '' ]; then - echo "defined=true" >> $GITHUB_OUTPUT; - else - echo "defined=false" >> $GITHUB_OUTPUT; - fi + check-openrouter-api-key: + runs-on: ubuntu-latest + outputs: + exists: ${{ steps.openrouter-api-key-check.outputs.defined }} + steps: + - name: Check if OpenRouter API key exists + id: openrouter-api-key-check + shell: bash + run: | + if [ "${{ secrets.OPENROUTER_API_KEY }}" != '' ]; then + echo "defined=true" >> $GITHUB_OUTPUT; + else + echo "defined=false" >> $GITHUB_OUTPUT; + fi - integration-test: - runs-on: ubuntu-latest - needs: [check-openrouter-api-key] - if: needs.check-openrouter-api-key.outputs.exists == 'true' - steps: - - name: Checkout code - uses: actions/checkout@v4 - - name: Setup Node.js and pnpm - uses: ./.github/actions/setup-node-pnpm - - name: Create .env.local file - working-directory: apps/vscode-e2e - run: echo "OPENROUTER_API_KEY=${{ secrets.OPENROUTER_API_KEY }}" > .env.local - - name: Run integration tests - working-directory: apps/vscode-e2e - run: xvfb-run -a pnpm test:ci + integration-test: + runs-on: ubuntu-latest + needs: [check-openrouter-api-key] + if: needs.check-openrouter-api-key.outputs.exists == 'true' + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Setup Node.js and pnpm + uses: ./.github/actions/setup-node-pnpm + - name: Create .env.local file + working-directory: apps/vscode-e2e + run: echo "OPENROUTER_API_KEY=${{ secrets.OPENROUTER_API_KEY }}" > .env.local + - name: Run integration tests + working-directory: apps/vscode-e2e + run: xvfb-run -a pnpm test:ci + + notify-slack-on-failure: + runs-on: ubuntu-latest + needs: [check-translations, knip, compile, platform-unit-test, integration-test] + if: ${{ always() && github.event_name == 'push' && github.ref == 'refs/heads/main' && contains(needs.*.result, 'failure') }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Send Slack notification on failure + uses: ./.github/actions/slack-notify + with: + webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }} + channel: "#ci" + workflow-name: "Code QA" + failed-jobs: ${{ toJSON(needs) }}