76d991c447
Auto Update PR / update-prs (push) Has been cancelled
CI / format-check (push) Has been cancelled
CI / test (3.10) (push) Has been cancelled
CI / test (3.11) (push) Has been cancelled
CI / test (3.12) (push) Has been cancelled
CI / live-api-tests (push) Has been cancelled
CI / plugin-integration-test (push) Has been cancelled
CI / ollama-integration-test (push) Has been cancelled
CI / test-fork-pr (push) Has been cancelled
158 lines
5.7 KiB
YAML
158 lines
5.7 KiB
YAML
name: Revalidate PR
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
pr_number:
|
|
description: 'PR number to validate'
|
|
required: true
|
|
type: string
|
|
|
|
permissions:
|
|
contents: read
|
|
pull-requests: write
|
|
issues: write
|
|
checks: write
|
|
statuses: write
|
|
|
|
jobs:
|
|
revalidate:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Get PR data
|
|
id: pr_data
|
|
uses: actions/github-script@v9
|
|
with:
|
|
script: |
|
|
const { data: pr } = await github.rest.pulls.get({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
pull_number: ${{ inputs.pr_number }}
|
|
});
|
|
|
|
core.info(`Validating PR #${pr.number}: ${pr.title}`);
|
|
core.info(`Author: ${pr.user.login}`);
|
|
core.info(`Changes: +${pr.additions} -${pr.deletions}`);
|
|
|
|
// Store head SHA for creating status
|
|
core.setOutput('head_sha', pr.head.sha);
|
|
|
|
return pr;
|
|
|
|
- name: Create pending status
|
|
uses: actions/github-script@v9
|
|
with:
|
|
script: |
|
|
await github.rest.repos.createCommitStatus({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
sha: '${{ steps.pr_data.outputs.head_sha }}',
|
|
state: 'pending',
|
|
context: 'Manual Validation',
|
|
description: 'Running validation checks...'
|
|
});
|
|
|
|
- name: Validate PR
|
|
id: validate
|
|
uses: actions/github-script@v9
|
|
with:
|
|
script: |
|
|
const pr = ${{ steps.pr_data.outputs.result }};
|
|
const errors = [];
|
|
let passed = true;
|
|
|
|
// Check size
|
|
const totalChanges = pr.additions + pr.deletions;
|
|
const MAX_LINES = 1000;
|
|
if (totalChanges > MAX_LINES) {
|
|
errors.push(`PR size (${totalChanges} lines) exceeds ${MAX_LINES} line limit`);
|
|
passed = false;
|
|
}
|
|
|
|
// Check template
|
|
const body = pr.body || '';
|
|
const requiredSections = ["# Description", "Fixes #", "# How Has This Been Tested?", "# Checklist"];
|
|
const missingSections = requiredSections.filter(section => !body.includes(section));
|
|
|
|
if (missingSections.length > 0) {
|
|
errors.push(`Missing PR template sections: ${missingSections.join(', ')}`);
|
|
passed = false;
|
|
}
|
|
|
|
if (body.match(/Replace this with|Choose one:|Fixes #\[issue number\]/i)) {
|
|
errors.push('PR template contains unmodified placeholders');
|
|
passed = false;
|
|
}
|
|
|
|
// Check linked issue
|
|
const issueMatch = body.match(/(?:Fixes|Closes|Resolves)\s+#(\d+)/i);
|
|
if (!issueMatch) {
|
|
errors.push('No linked issue found');
|
|
passed = false;
|
|
}
|
|
|
|
// Store results
|
|
core.setOutput('passed', passed);
|
|
core.setOutput('errors', errors.join('; '));
|
|
core.setOutput('totalChanges', totalChanges);
|
|
core.setOutput('hasTemplate', missingSections.length === 0);
|
|
core.setOutput('hasIssue', !!issueMatch);
|
|
|
|
if (!passed) {
|
|
core.setFailed(errors.join('; '));
|
|
}
|
|
|
|
- name: Update commit status
|
|
if: always()
|
|
uses: actions/github-script@v9
|
|
with:
|
|
script: |
|
|
const passed = ${{ steps.validate.outputs.passed }};
|
|
const errors = '${{ steps.validate.outputs.errors }}';
|
|
|
|
await github.rest.repos.createCommitStatus({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
sha: '${{ steps.pr_data.outputs.head_sha }}',
|
|
state: passed ? 'success' : 'failure',
|
|
context: 'Manual Validation',
|
|
description: passed ? 'All validation checks passed' : errors.substring(0, 140),
|
|
target_url: `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`
|
|
});
|
|
|
|
- name: Add validation comment
|
|
if: always()
|
|
uses: actions/github-script@v9
|
|
with:
|
|
script: |
|
|
const pr = ${{ steps.pr_data.outputs.result }};
|
|
const passed = ${{ steps.validate.outputs.passed }};
|
|
const totalChanges = ${{ steps.validate.outputs.totalChanges }};
|
|
const hasTemplate = ${{ steps.validate.outputs.hasTemplate }};
|
|
const hasIssue = ${{ steps.validate.outputs.hasIssue }};
|
|
const errors = '${{ steps.validate.outputs.errors }}'.split('; ').filter(e => e);
|
|
|
|
let body = `### Manual Validation Results\n\n`;
|
|
body += `**Status**: ${passed ? '✅ Passed' : '❌ Failed'}\n\n`;
|
|
body += `| Check | Status | Details |\n`;
|
|
body += `|-------|--------|----------|\n`;
|
|
body += `| PR Size | ${totalChanges <= 1000 ? '✅' : '❌'} | ${totalChanges} lines ${totalChanges > 1000 ? '(exceeds 1000 limit)' : ''} |\n`;
|
|
body += `| Template | ${hasTemplate ? '✅' : '❌'} | ${hasTemplate ? 'Complete' : 'Missing required sections'} |\n`;
|
|
body += `| Linked Issue | ${hasIssue ? '✅' : '❌'} | ${hasIssue ? 'Found' : 'Missing Fixes/Closes #XXX'} |\n`;
|
|
|
|
if (errors.length > 0) {
|
|
body += `\n**Errors:**\n`;
|
|
errors.forEach(error => {
|
|
body += `- ❌ ${error}\n`;
|
|
});
|
|
}
|
|
|
|
body += `\n[View workflow run](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})`;
|
|
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: pr.number,
|
|
body: body
|
|
});
|