mirror of
https://github.com/Cleanuparr/Cleanuparr.git
synced 2026-03-25 17:41:57 -04:00
182 lines
6.5 KiB
YAML
182 lines
6.5 KiB
YAML
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: write
|
|
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: 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;
|
|
}
|
|
|
|
try {
|
|
await github.rest.reactions.createForIssueComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
comment_id: context.payload.comment.id,
|
|
content: 'eyes'
|
|
});
|
|
} catch (e) {
|
|
console.log(`Could not add reaction: ${e}`);
|
|
}
|
|
|
|
// 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
|
|
});
|