Copilot commented on code in PR #24940:
URL: https://github.com/apache/pulsar/pull/24940#discussion_r2490977665
##########
.github/workflows/ci-pulsarbot.yaml:
##########
@@ -34,6 +34,233 @@ jobs:
steps:
- name: Execute pulsarbot command
id: pulsarbot
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: apache/pulsar-test-infra/pulsarbot@master
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ // Supported commands:
+ // - /pulsarbot rerun
+ // Reruns all completed workflows with conclusions of
failure/timed_out/skipped/cancelled
+ // If workflow is still running, cannot rerun whole workflow,
just suggest using "/pulsarbot rerun jobname"
+ // - /pulsarbot rerun jobname
+ // Matches job.name by keyword, reruns matching jobs (regardless
of current state, failures are logged)
+ // - /pulsarbot stop or /pulsarbot cancel
+ // Cancels all still running (queued/in_progress) workflow runs
associated with the current PR
+ const commentBody = context.payload.comment.body.trim();
+ const prefix = '/pulsarbot';
+ if (!commentBody.startsWith(prefix)) {
+ console.log('Not a pulsarbot command, skipping ...');
+ return;
+ }
+ if (!context.payload.issue || !context.payload.issue.pull_request)
{
+ console.error('This comment is not on a Pull Request. pulsarbot
only works on PRs.');
+ return;
+ }
+ const parts = commentBody.split(/\s+/);
+ const sub = (parts[1] || '').toLowerCase();
+ const arg = parts.length > 2 ? parts.slice(2).join(' ') : '';
+ const supported = ['rerun', 'stop', 'cancel',
'rerun-failure-checks'];
+ if (!supported.includes(sub)) {
+ console.log(`Unsupported command '${sub}'. Supported:
'/pulsarbot rerun [jobName?]', '/pulsarbot stop', '/pulsarbot cancel'.`);
+ return;
+ }
+ const prNum = context.payload.issue.number;
+ // Get PR info
+ let pr;
+ try {
+ ({ data: pr } = await github.rest.pulls.get({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: prNum
+ }));
+ } catch (e) {
+ console.error(`Failed to fetch PR #${prNum}: ${e.message}`);
+ return;
+ }
+ const headSha = pr.head.sha;
+ const prBranch = pr.head.ref;
+ const prUser = pr.user.login;
+ const prUrl = pr.html_url;
+ console.log(`pulsarbot handling PR #${prNum} ${prUrl}`);
+ console.log(`PR branch='${prBranch}', headSha='${headSha}',
author='${prUser}'`);
+ console.log(`Command parsed => sub='${sub}', arg='${arg || ''}'`);
+ // Fetch workflow runs in this repo triggered by this user on this
branch, then filter by headSha
+ let page = 1;
+ const allRunsRaw = [];
+ while (true) {
+ const { data } = await
github.rest.actions.listWorkflowRunsForRepo({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ actor: prUser,
+ branch: prBranch,
+ per_page: 100,
+ page
+ });
+ const wr = data.workflow_runs || [];
+ if (wr.length === 0) break;
+ allRunsRaw.push(...wr);
+ if (wr.length < 100) break;
+ page++;
+ }
+ const runsAtHead = allRunsRaw.filter(r => r.head_sha === headSha);
+ if (runsAtHead.length === 0) {
+ console.error(`No workflow runs found for head SHA ${headSha} on
branch ${prBranch}.`);
+ return;
+ }
+ // Only keep the latest run for each workflow_id
+ runsAtHead.sort((a, b) => {
+ if (a.workflow_id !== b.workflow_id) return a.workflow_id -
b.workflow_id;
+ return new Date(b.created_at) - new Date(a.created_at);
+ });
+ const latestRuns = [];
+ const seen = new Set();
+ for (const r of runsAtHead) {
+ if (!seen.has(r.workflow_id)) {
+ seen.add(r.workflow_id);
+ latestRuns.push(r);
+ }
+ }
+ function runKey(r) {
+ return `[run_id=${r.id}] ${r.name || '(unnamed)'} |
status=${r.status} | conclusion=${r.conclusion || '-'} | ${r.html_url}`;
+ }
+ console.log('--- Latest workflow runs for this PR headSHA (one per
workflow) ---');
+ for (const r of latestRuns) console.log('- ' + runKey(r));
+ // Utility: list all jobs in a run
+ async function listAllJobs(runId) {
+ let jobs = [];
+ let p = 1;
+ while (true) {
+ const { data } = await
github.rest.actions.listJobsForWorkflowRun({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ run_id: runId,
+ per_page: 100,
+ page: p
+ });
+ const js = data.jobs || [];
+ if (js.length === 0) break;
+ jobs.push(...js);
+ if (js.length < 100) break;
+ p++;
+ }
+ return jobs;
+ }
+ // Utility: rerun a single job
+ async function rerunJob(job, run) {
+ try {
+ if (github.rest.actions.reRunJobForWorkflowRun) {
+ await github.rest.actions.reRunJobForWorkflowRun({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ job_id: job.id
+ });
+ } else {
+ await github.request('POST
/repos/{owner}/{repo}/actions/jobs/{job_id}/rerun', {
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ job_id: job.id
+ });
+ }
Review Comment:
The fallback logic checks if `reRunJobForWorkflowRun` exists at runtime, but
this adds unnecessary complexity. The GitHub REST API for rerunning jobs should
be consistently available in the `@v7` version of `actions/github-script`.
Consider using only the primary method or documenting why the fallback is
necessary.
```suggestion
await github.rest.actions.reRunJobForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
job_id: job.id
});
```
##########
.github/workflows/ci-pulsarbot.yaml:
##########
@@ -34,6 +34,233 @@ jobs:
steps:
- name: Execute pulsarbot command
id: pulsarbot
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: apache/pulsar-test-infra/pulsarbot@master
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ // Supported commands:
+ // - /pulsarbot rerun
+ // Reruns all completed workflows with conclusions of
failure/timed_out/skipped/cancelled
+ // If workflow is still running, cannot rerun whole workflow,
just suggest using "/pulsarbot rerun jobname"
+ // - /pulsarbot rerun jobname
+ // Matches job.name by keyword, reruns matching jobs (regardless
of current state, failures are logged)
+ // - /pulsarbot stop or /pulsarbot cancel
+ // Cancels all still running (queued/in_progress) workflow runs
associated with the current PR
+ const commentBody = context.payload.comment.body.trim();
+ const prefix = '/pulsarbot';
+ if (!commentBody.startsWith(prefix)) {
+ console.log('Not a pulsarbot command, skipping ...');
+ return;
+ }
+ if (!context.payload.issue || !context.payload.issue.pull_request)
{
+ console.error('This comment is not on a Pull Request. pulsarbot
only works on PRs.');
+ return;
+ }
+ const parts = commentBody.split(/\s+/);
+ const sub = (parts[1] || '').toLowerCase();
+ const arg = parts.length > 2 ? parts.slice(2).join(' ') : '';
+ const supported = ['rerun', 'stop', 'cancel',
'rerun-failure-checks'];
+ if (!supported.includes(sub)) {
+ console.log(`Unsupported command '${sub}'. Supported:
'/pulsarbot rerun [jobName?]', '/pulsarbot stop', '/pulsarbot cancel'.`);
Review Comment:
The error message lists supported commands but omits 'rerun-failure-checks'
which is included in the supported array on line 62. The message should include
all supported commands or reference them generically.
```suggestion
console.log(`Unsupported command '${sub}'. Supported:
${supported.map(cmd => `'/pulsarbot ${cmd}'`).join(', ')}.`);
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]