Add Windows build trigger on PR comment (#508)

This commit is contained in:
Flaminel
2026-03-17 11:29:50 +02:00
committed by GitHub
parent 87bb92fac0
commit f26768bcf7
3 changed files with 194 additions and 2 deletions

View File

@@ -2,6 +2,12 @@ name: Build Frontend
on:
workflow_call:
inputs:
ref:
description: 'Git ref to checkout (branch, tag, or SHA). Defaults to github.ref_name.'
type: string
required: false
default: ''
jobs:
build-frontend:
@@ -22,7 +28,7 @@ jobs:
timeout-minutes: 1
with:
repository: ${{ github.repository }}
ref: ${{ github.ref_name }}
ref: ${{ inputs.ref || github.ref_name }}
token: ${{ env.REPO_READONLY_PAT }}
- name: Setup Node.js

View File

@@ -8,6 +8,11 @@ on:
type: string
required: false
default: ''
ref:
description: 'Git ref to checkout (branch, tag, or SHA). Defaults to github.ref_name.'
type: string
required: false
default: ''
jobs:
build-windows-installer:
@@ -58,7 +63,7 @@ jobs:
uses: actions/checkout@v4
with:
repository: ${{ env.githubRepository }}
ref: ${{ github.ref_name }}
ref: ${{ inputs.ref || github.ref_name }}
token: ${{ env.REPO_READONLY_PAT }}
- name: Download frontend artifact

181
.github/workflows/pr-build.yml vendored Normal file
View File

@@ -0,0 +1,181 @@
name: PR Build (Comment Triggered)
on:
issue_comment:
types: [created]
concurrency:
group: pr-build-${{ github.event.issue.number }}
cancel-in-progress: true
permissions:
issues: write
pull-requests: read
actions: read
jobs:
validate:
runs-on: ubuntu-latest
if: github.event.issue.pull_request != null
outputs:
build_windows: ${{ steps.parse.outputs.build_windows }}
pr_ref: ${{ steps.parse.outputs.pr_ref }}
pr_sha: ${{ steps.parse.outputs.pr_sha }}
pr_number: ${{ steps.parse.outputs.pr_number }}
steps:
- name: React to comment
uses: actions/github-script@v7
with:
script: |
await github.rest.reactions.createForIssueComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: context.payload.comment.id,
content: 'eyes'
});
- name: Parse command and check permissions
id: parse
uses: actions/github-script@v7
with:
script: |
const comment = context.payload.comment.body.trim();
// Parse supported commands
const commands = {
'/build-windows': 'build_windows'
};
const command = commands[comment];
if (!command) {
console.log(`Comment "${comment}" is not a recognized build command, skipping.`);
core.setOutput('build_windows', 'false');
return;
}
// Fetch PR details
const pr = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number
});
// Verify PR is open
if (pr.data.state !== 'open') {
console.log('PR is not open, skipping.');
core.setOutput('build_windows', 'false');
return;
}
// Block fork PRs — fork code should not run with access to secrets
const isFork = pr.data.head.repo.full_name !== context.repo.owner + '/' + context.repo.repo;
if (isFork) {
console.log(`PR is from fork ${pr.data.head.repo.full_name}, blocking build.`);
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: 'On-demand builds are not available for PRs from forks.'
});
core.setOutput('build_windows', 'false');
return;
}
// Verify commenter has write access
let permission = 'none';
try {
const resp = await github.rest.repos.getCollaboratorPermissionLevel({
owner: context.repo.owner,
repo: context.repo.repo,
username: context.payload.comment.user.login
});
permission = resp.data.permission;
} catch (_) {}
if (!['admin', 'write'].includes(permission)) {
console.log(`User ${context.payload.comment.user.login} has '${permission}' permission — insufficient.`);
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `@${context.payload.comment.user.login} Only collaborators with write access can trigger builds.`
});
core.setOutput('build_windows', 'false');
return;
}
console.log(`User ${context.payload.comment.user.login} has '${permission}' permission — proceeding with ${command}.`);
core.setOutput(command, 'true');
// Export PR details for downstream jobs
core.setOutput('pr_ref', pr.data.head.ref);
core.setOutput('pr_sha', pr.data.head.sha);
core.setOutput('pr_number', String(pr.data.number));
build-frontend:
needs: validate
if: needs.validate.outputs.build_windows == 'true'
uses: ./.github/workflows/build-frontend.yml
with:
ref: ${{ needs.validate.outputs.pr_ref }}
secrets: inherit
build-windows:
needs: [validate, build-frontend]
if: needs.validate.outputs.build_windows == 'true'
uses: ./.github/workflows/build-windows-installer.yml
with:
ref: ${{ needs.validate.outputs.pr_ref }}
secrets: inherit
post-result:
needs: [validate, build-windows]
if: always() && needs.validate.outputs.build_windows == 'true'
runs-on: ubuntu-latest
steps:
- name: Post result comment
uses: actions/github-script@v7
with:
script: |
const buildResult = '${{ needs.build-windows.result }}';
const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
const prRef = '${{ needs.validate.outputs.pr_ref }}';
const prSha = '${{ needs.validate.outputs.pr_sha }}';
const shortSha = prSha.substring(0, 7);
// Skip comment for skipped builds
if (buildResult === 'skipped') {
console.log('Build was skipped, no comment needed.');
return;
}
let body;
if (buildResult === 'success') {
body = [
`Windows installer build **succeeded** for \`${prRef}\` (\`${shortSha}\`).`,
``,
`**Download:** open the [workflow run](${runUrl}), scroll to the **Artifacts** section at the bottom.`,
`The artifact \`Cleanuparr-windows-installer\` is retained for 30 days.`
].join('\n');
} else if (buildResult === 'cancelled') {
body = [
`Windows installer build was **cancelled** for \`${prRef}\` (\`${shortSha}\`).`,
``,
`See the [workflow run](${runUrl}) for details.`
].join('\n');
} else {
body = [
`Windows installer build **failed** for \`${prRef}\` (\`${shortSha}\`).`,
``,
`See the [workflow run](${runUrl}) for details.`
].join('\n');
}
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: parseInt('${{ needs.validate.outputs.pr_number }}'),
body
});