Skip to content

feat(agent): build the agent and PageBroker images for arm64 #5234

feat(agent): build the agent and PageBroker images for arm64

feat(agent): build the agent and PageBroker images for arm64 #5234

# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
name: Validate Issue Reference
# Every pull request must link at least one open issue that carries the
# approval label. The check re-runs automatically when the label is added to or
# removed from an issue, so contributors do not need to push an empty commit.
on:
pull_request:
types:
- opened
- reopened
- edited
- synchronize
- ready_for_review
- labeled
- unlabeled
issues:
types:
- labeled
- unlabeled
- closed
- reopened
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || format('issue-{0}', github.event.issue.number) }}
cancel-in-progress: true
permissions: {}
env:
# Label an issue must carry for a pull request referencing it to pass.
APPROVED_LABEL: approved
# Label on a pull request that waives the issue requirement.
BYPASS_LABEL: skip-issue-check
jobs:
validate:
name: PR links an approved issue
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
# Read the pull request body and the issues it references.
contents: read
pull-requests: read
issues: read
steps:
- name: Validate issue reference
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const { owner, repo } = context.repo;
const pr = context.payload.pull_request;
const approvedLabel = process.env.APPROVED_LABEL;
const bypassLabel = process.env.BYPASS_LABEL;
const labels = (pr.labels || []).map(l => l.name);
if (labels.includes(bypassLabel)) {
core.info(`Pull request is labeled "${bypassLabel}" - skipping the issue requirement.`);
return;
}
if (pr.user && pr.user.type === 'Bot') {
core.info(`Pull request was opened by ${pr.user.login} (bot) - skipping the issue requirement.`);
return;
}
if (pr.draft) {
core.info('Pull request is a draft - the check runs again when it is marked ready for review.');
return;
}
// Drop HTML comments, fenced code blocks, and inline code spans so
// template boilerplate, pasted logs, and prose such as `#123` are
// not mistaken for an issue reference. GitHub does not render a
// reference inside backticks as a link either.
const body = (pr.body || '')
.replace(/<!--[\s\S]*?-->/g, ' ')
.replace(/```[\s\S]*?```/g, ' ')
.replace(/`[^`\n]*`/g, ' ');
const escapeRegExp = s => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const references = new Set();
for (const m of body.matchAll(/#(\d+)\b/g)) {
references.add(Number(m[1]));
}
const urlPattern = new RegExp(
`https?://github\\.com/${escapeRegExp(owner)}/${escapeRegExp(repo)}/issues/(\\d+)`, 'gi');
for (const m of body.matchAll(urlPattern)) {
references.add(Number(m[1]));
}
const howTo =
`Link the issue from the pull request description, for example \`Fixes #123\` ` +
`or \`Fixes https://github.com/${owner}/${repo}/issues/123\`. ` +
`The issue must be open and labeled \`${approvedLabel}\` by a maintainer. ` +
`Maintainers can waive this by adding the \`${bypassLabel}\` label to the pull request.`;
if (references.size === 0) {
await core.summary
.addHeading('Issue reference missing')
.addRaw(howTo)
.write();
core.setFailed(`This pull request does not reference an issue. ${howTo}`);
return;
}
const numbers = [...references].sort((a, b) => a - b);
core.info(`Found issue reference(s): ${numbers.map(n => `#${n}`).join(', ')}`);
const problems = [];
let approvedIssue = null;
for (const number of numbers) {
let issue;
try {
issue = (await github.rest.issues.get({ owner, repo, issue_number: number })).data;
} catch (error) {
problems.push(error.status === 404
? `#${number} does not exist`
: `#${number} could not be read: ${error.message}`);
continue;
}
if (issue.pull_request) {
problems.push(`#${number} is a pull request, not an issue`);
continue;
}
if (issue.state === 'closed') {
problems.push(`#${number} is closed`);
continue;
}
const issueLabels = (issue.labels || []).map(l => (typeof l === 'string' ? l : l.name));
if (!issueLabels.includes(approvedLabel)) {
problems.push(`#${number} is open but is not labeled \`${approvedLabel}\``);
continue;
}
approvedIssue = number;
break;
}
if (approvedIssue === null) {
const details = problems.map(p => `- ${p}`).join('\n');
await core.summary
.addHeading('No approved issue referenced')
.addRaw(details, true)
.addRaw(howTo)
.write();
core.setFailed(
`None of the referenced issues are open and labeled "${approvedLabel}":\n${details}\n\n${howTo}`);
return;
}
core.info(`Issue #${approvedIssue} is open and labeled "${approvedLabel}".`);
await core.summary
.addHeading('Approved issue referenced')
.addRaw(`This pull request references #${approvedIssue}, which is open and labeled \`${approvedLabel}\`.`)
.write();
revalidate:
name: Re-run validation for linked pull requests
if: github.event_name == 'issues'
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
# Re-run this workflow for the pull requests affected by the issue change.
actions: write
contents: read
pull-requests: read
steps:
- name: Re-run affected pull request checks
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const { owner, repo } = context.repo;
const issueNumber = context.payload.issue.number;
const workflowFile = 'validate-issue-references.yaml';
const referencesIssue = (body) => {
const text = (body || '')
.replace(/<!--[\s\S]*?-->/g, ' ')
.replace(/```[\s\S]*?```/g, ' ')
.replace(/`[^`\n]*`/g, ' ');
return new RegExp(`(?:#|/issues/)${issueNumber}\\b`).test(text);
};
const pulls = await github.paginate(github.rest.pulls.list, {
owner, repo, state: 'open', per_page: 100,
});
const affected = pulls.filter(pr => referencesIssue(pr.body));
if (affected.length === 0) {
core.info(`No open pull request references issue #${issueNumber}.`);
return;
}
// A run that is still executing may have read the issue labels
// before this change landed, and GitHub offers no completion event
// to retry on, so wait for it rather than dropping the request.
const waitForCompletion = async (runId, prNumber) => {
const deadline = Date.now() + 10 * 60 * 1000;
while (Date.now() < deadline) {
await new Promise(resolve => setTimeout(resolve, 15000));
const { data: run } = await github.rest.actions.getWorkflowRun({
owner, repo, run_id: runId,
});
if (run.status === 'completed') {
return run;
}
}
core.warning(
`PR #${prNumber}: validation run ${runId} did not finish in time. ` +
'Re-run it by hand to pick up the label change.');
return null;
};
for (const pr of affected) {
const runs = await github.rest.actions.listWorkflowRuns({
owner, repo, workflow_id: workflowFile, head_sha: pr.head.sha, per_page: 20,
});
// Runs come back newest first; only the latest one shows on the PR.
let latest = runs.data.workflow_runs.find(run => run.event === 'pull_request');
if (!latest) {
core.info(`PR #${pr.number}: no validation run to re-run.`);
continue;
}
if (latest.status !== 'completed') {
core.info(
`PR #${pr.number}: validation run ${latest.id} is ${latest.status}; ` +
'waiting for it to finish before re-running.');
latest = await waitForCompletion(latest.id, pr.number);
if (!latest) {
continue;
}
}
try {
await github.rest.actions.reRunWorkflow({ owner, repo, run_id: latest.id });
core.info(`PR #${pr.number}: re-running validation (run ${latest.id}).`);
} catch (error) {
core.warning(`PR #${pr.number}: could not re-run ${latest.id}: ${error.message}`);
}
}