ci.yml•5.63 kB
name: CI
on:
push:
branches: [main]
pull_request:
types: [opened, synchronize, reopened, edited]
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
permissions:
pull-requests: write
strategy:
matrix:
node-version: [20.x, 22.x]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Validate PR title
if: github.event_name == 'pull_request'
id: validate-title
run: |
PR_TITLE="${{ github.event.pull_request.title }}"
echo "Validating PR title: $PR_TITLE"
if [[ "$PR_TITLE" =~ ^(BREAKING|breaking|feat|FEAT|fix|FIX): ]]; then
echo "✅ PR title format is valid"
else
echo "❌ PR title must start with 'BREAKING:', 'feat:', or 'fix:' (case-insensitive)"
echo "Examples:"
echo " - BREAKING: Remove deprecated tools"
echo " - feat: Add new preference validation feature"
echo " - fix: Fix typo in tool description"
exit 1
fi
- name: Comment on PR title failure
if: failure() && steps.validate-title.outcome == 'failure' && github.event_name == 'pull_request' && matrix.node-version == '20.x'
uses: actions/github-script@v7
with:
script: |
const prNumber = context.payload.pull_request.number;
const comment = '## ❌ Invalid PR Title Format\n\n' +
'Your PR title must start with one of: `BREAKING:`, `feat:`, or `fix:` (case-insensitive)\n\n' +
'**Current title:** "' + context.payload.pull_request.title + '"\n\n' +
'**Examples of valid titles:**\n' +
'- `BREAKING: Remove deprecated tool` (breaking change → major version)\n' +
'- `feat: Add new preference validation feature` (new features → minor version)\n' +
'- `fix: Fix typo in tool description` (bug fixes → patch version)\n\n' +
'Please edit your PR title and the CI will run again automatically.';
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: comment
});
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Build project
run: npm run build
- name: Run tests
run: npm test
- name: Run tests with coverage
id: coverage
run: npm run test:coverage
- name: Comment on coverage failure
if: failure() && steps.coverage.outcome == 'failure' && github.event_name == 'pull_request' && matrix.node-version == '20.x'
uses: actions/github-script@v7
with:
script: |
const prNumber = context.payload.pull_request.number;
const comment = '## ❌ Test Coverage Below Threshold\n\n' +
'Your test coverage is below the required 80% threshold.\n\n' +
'**To fix this:**\n' +
'```bash\n' +
'# Check current coverage\n' +
'npm run test:coverage\n\n' +
'# Add tests for uncovered code\n' +
'# Then verify coverage passes\n' +
'npm run verify\n' +
'```\n\n' +
'Please add tests to cover the missing code paths.';
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: comment
});
- name: Upload coverage reports
if: matrix.node-version == '20.x'
uses: codecov/codecov-action@v3
with:
file: ./coverage/lcov.info
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false
- name: Comment on PR failure
if: failure() && github.event_name == 'pull_request' && matrix.node-version == '20.x'
uses: actions/github-script@v7
with:
script: |
const prNumber = context.payload.pull_request.number;
const workflowUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
const comment = '## ❌ CI Failed\n\n' +
'The CI build has failed for this PR. Please check the logs and fix the issues.\n\n' +
'**Common fixes:**\n' +
'- **PR Title:** Must start with `BREAKING:`, `feat:`, or `fix:` (case-insensitive)\n' +
'- **Linting:** Run `npm run lint` locally\n' +
'- **Build:** Run `npm run build` locally\n' +
'- **Tests:** Run `npm test` locally\n' +
'- **Coverage:** Run `npm run test:coverage` locally\n\n' +
'**Quick verification:**\n' +
'```bash\n' +
'npm run verify\n' +
'```\n\n' +
'**CI Logs:** [View details](' + workflowUrl + ')\n\n' +
'Once fixed, push your changes and CI will run again automatically.';
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: comment
});
console.log(`Posted failure comment to PR #${prNumber}`);