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]

Reply via email to