mirror of
https://github.com/containers/ramalama.git
synced 2026-02-05 15:47:26 +01:00
177 lines
6.5 KiB
YAML
177 lines
6.5 KiB
YAML
name: Approve Command
|
|
|
|
on:
|
|
issue_comment:
|
|
types: [created]
|
|
|
|
jobs:
|
|
approve:
|
|
name: Handle /approve command
|
|
# Only run on pull request comments with /approve command
|
|
if: github.event.issue.pull_request
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
pull-requests: write
|
|
contents: read
|
|
issues: write
|
|
|
|
steps:
|
|
- name: Check /approve command and PR status
|
|
id: check_command
|
|
uses: actions/github-script@v8
|
|
with:
|
|
script: |
|
|
try {
|
|
// Check if comment contains /approve command (as a standalone command)
|
|
const comment = context.payload.comment.body.trim();
|
|
const approvePattern = /^\/approve\s*$/m;
|
|
const hasApproveCommand = approvePattern.test(comment);
|
|
|
|
core.setOutput('has_approve_command', hasApproveCommand);
|
|
|
|
if (!hasApproveCommand) {
|
|
core.info('Comment does not contain /approve command');
|
|
return false;
|
|
}
|
|
|
|
// Check if PR is open
|
|
const pr_number = context.payload.issue.number;
|
|
const { data: pr } = await github.rest.pulls.get({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
pull_number: pr_number
|
|
});
|
|
|
|
const isOpen = pr.state === 'open';
|
|
core.setOutput('pr_is_open', isOpen);
|
|
|
|
if (!isOpen) {
|
|
core.info(`PR #${pr_number} is not open (state: ${pr.state})`);
|
|
}
|
|
|
|
return hasApproveCommand && isOpen;
|
|
} catch (error) {
|
|
core.setFailed(`Error checking command and PR status: ${error.message}`);
|
|
return false;
|
|
}
|
|
|
|
- name: Check if commenter has write access
|
|
if: steps.check_command.outputs.has_approve_command == 'true' && steps.check_command.outputs.pr_is_open == 'true'
|
|
id: check_access
|
|
uses: actions/github-script@v8
|
|
with:
|
|
script: |
|
|
try {
|
|
const { data: permission } = await github.rest.repos.getCollaboratorPermissionLevel({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
username: context.payload.comment.user.login
|
|
});
|
|
|
|
const hasAccess = ['admin', 'write', 'maintain'].includes(permission.permission);
|
|
core.setOutput('has_access', hasAccess);
|
|
|
|
if (!hasAccess) {
|
|
core.info(`User ${context.payload.comment.user.login} does not have sufficient permissions (${permission.permission})`);
|
|
}
|
|
|
|
return hasAccess;
|
|
} catch (error) {
|
|
core.setFailed(`Error checking permissions: ${error.message}`);
|
|
return false;
|
|
}
|
|
|
|
- name: React to comment
|
|
if: steps.check_access.outputs.has_access == 'true'
|
|
uses: actions/github-script@v8
|
|
with:
|
|
script: |
|
|
await github.rest.reactions.createForIssueComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
comment_id: context.payload.comment.id,
|
|
content: 'rocket'
|
|
});
|
|
|
|
- name: Approve PR
|
|
if: steps.check_access.outputs.has_access == 'true'
|
|
uses: actions/github-script@v8
|
|
with:
|
|
script: |
|
|
try {
|
|
const pr_number = context.payload.issue.number;
|
|
|
|
// Check if the user has already approved
|
|
const { data: reviews } = await github.rest.pulls.listReviews({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
pull_number: pr_number
|
|
});
|
|
|
|
// Find all reviews by the user
|
|
const userReviews = reviews.filter(
|
|
review => review.user.login === context.payload.comment.user.login
|
|
);
|
|
|
|
// Get the latest review by the user (by submitted_at)
|
|
const latestReview = userReviews.sort(
|
|
(a, b) => new Date(b.submitted_at) - new Date(a.submitted_at)
|
|
)[0];
|
|
|
|
// Only block approval if the latest review is APPROVED and not DISMISSED
|
|
const existingApproval = latestReview && latestReview.state === 'APPROVED';
|
|
|
|
if (existingApproval) {
|
|
core.info(`User ${context.payload.comment.user.login} has already approved this PR`);
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: pr_number,
|
|
body: '✅ You have already approved this PR.'
|
|
});
|
|
return;
|
|
}
|
|
|
|
// Create approval review
|
|
await github.rest.pulls.createReview({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
pull_number: pr_number,
|
|
event: 'APPROVE',
|
|
body: 'Approved via /approve command'
|
|
});
|
|
|
|
core.info(`PR #${pr_number} approved by ${context.payload.comment.user.login}`);
|
|
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: pr_number,
|
|
body: `✅ PR approved by @${context.payload.comment.user.login} via /approve command`
|
|
});
|
|
} catch (error) {
|
|
core.setFailed(`Failed to approve PR: ${error.message}`);
|
|
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: context.payload.issue.number,
|
|
body: `❌ Failed to approve PR: ${error.message}`
|
|
});
|
|
}
|
|
|
|
- name: Notify insufficient permissions
|
|
if: |
|
|
steps.check_command.outputs.has_approve_command == 'true' &&
|
|
steps.check_command.outputs.pr_is_open == 'true' &&
|
|
steps.check_access.outputs.has_access != 'true'
|
|
uses: actions/github-script@v8
|
|
with:
|
|
script: |
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: context.payload.issue.number,
|
|
body: `❌ @${context.payload.comment.user.login} does not have sufficient permissions to approve PRs. Only maintainers and collaborators with write access can use the /approve command.`
|
|
});
|