-
Notifications
You must be signed in to change notification settings - Fork 0
Add pr comment trigger action #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
gnpar
wants to merge
2
commits into
main
Choose a base branch
from
pr-comment-trigger
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# PR Comment Trigger | ||
|
||
This action simplifies the creation of workflows that trigger on a comment on a PR. | ||
|
||
It checks that the comment matches a specific pattern, optionally extracting data from it, and returns the context of the PR. | ||
|
||
Inputs that it receives: | ||
|
||
- `match`: The regex pattern to match the comment against. By default, it will match any comment. | ||
- `ack`: A thumbs up reaction is added to the comment if it matched. Enabled by default. | ||
|
||
Notice that you'll need to grant the workflow `issues: write` permission for the ack to work. | ||
|
||
Outputs: | ||
|
||
- pr-number: The PR number where the triggering comment was added | ||
- pr-head-sha: The SHA of the HEAD commit of the PR | ||
- pr-head-ref: The PR branch | ||
- pr-base-ref: The base branch of the PR | ||
- comment-body: The full comment body | ||
- matches: A JSON object with the regex matches | ||
- match-found: Whether the regex matched or not | ||
- comment-id: The ID of the triggering comment | ||
|
||
Notice that you will also have a lot of information available in the context for `issue_comment`: | ||
|
||
- `github.event.comment`: The [full comment object](https://docs.github.com/en/rest/issues/comments?apiVersion=2022-11-28#get-an-issue-comment) | ||
- `github.event.issue`: The [full issue object](https://docs.github.com/en/rest/issues/issues?apiVersion=2022-11-28#get-an-issue) | ||
- [And more](https://docs.github.com/en/webhooks/webhook-events-and-payloads#issue_comment) | ||
|
||
## Usage | ||
|
||
Here's a simple workflow that uses this action: | ||
|
||
```yaml | ||
name: Trigger on a PR comment | ||
|
||
permissions: | ||
issues: write # Required to ack the comment | ||
|
||
on: | ||
issue_comment: | ||
types: [created] | ||
|
||
jobs: | ||
check-comment: | ||
# It's recommended that you use the action in a separate job. | ||
# This makes it easier to skip the rest of the workflow if there was no match. | ||
|
||
# The match on the comment body is not necessary, but it's a good way to skip unrelated comments quickly. | ||
if: ${{ github.event.issue.pull_request && startsWith(github.event.comment.body, '/foo') }} | ||
|
||
runs-on: ubuntu-latest | ||
|
||
outputs: | ||
match-found: ${{ steps.comment-check.outputs.match-found }} | ||
matches: ${{ steps.comment-check.outputs.matches }} | ||
pr-head-sha: ${{ steps.comment-check.outputs.pr-head-sha }} | ||
pr-head-ref: ${{ steps.comment-check.outputs.pr-head-ref }} | ||
pr-base-ref: ${{ steps.comment-check.outputs.pr-base-ref }} | ||
steps: | ||
- id: comment-check | ||
uses: ensuro/github-actions/pr-comment-trigger@pr-comment-trigger # Use a tag or commit hash here | ||
with: | ||
match: "^/foo (?<bar>.*?) (?<baz>.*?)$" | ||
|
||
process-command: | ||
needs: check-comment | ||
if: ${{ needs.check-comment.outputs.match-found == 'true' }} | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Process Command | ||
run: | | ||
echo "Processing /check on PR #${{ github.event.issue.number }} ${{ needs.check-comment.outputs.pr-head-ref }} -> ${{ needs.check-comment.outputs.pr-base-ref }}" >> $GITHUB_STEP_SUMMARY | ||
echo "bar: ${{ fromJson(needs.check-comment.outputs.matches).bar }}" >> $GITHUB_STEP_SUMMARY | ||
echo "baz: ${{ fromJson(needs.check-comment.outputs.matches).baz }}" >> $GITHUB_STEP_SUMMARY | ||
``` | ||
|
||
Notice that this job will be associated with the main branch and not with the PR. If you want to provide feedback on the PR besides the reaction, you can use checks and/or comments on the PR. | ||
|
||
A more comprehensive workflow example showcasing this is provided in the [examples](./examples) directory. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
name: "PR Comment Trigger" | ||
description: "Processes PR comments and extracts information based on regex patterns" | ||
|
||
inputs: | ||
match: | ||
description: "Regex pattern to match against the comment" | ||
required: false | ||
default: "" | ||
ack: | ||
description: "Whether to acknowledge the comment with a reaction. Requires permission to write on issues." | ||
required: false | ||
default: "true" | ||
|
||
outputs: | ||
pr-number: | ||
description: "PR number" | ||
value: ${{ fromJson(steps.process-comment.outputs.result).prNumber }} | ||
pr-head-sha: | ||
description: "HEAD SHA of the PR" | ||
value: ${{ fromJson(steps.process-comment.outputs.result).prHeadSha }} | ||
pr-head-ref: | ||
description: "HEAD branch reference of the PR" | ||
value: ${{ fromJson(steps.process-comment.outputs.result).prHeadRef }} | ||
pr-base-ref: | ||
description: "Base branch reference of the PR (usually main)" | ||
value: ${{ fromJson(steps.process-comment.outputs.result).prBaseRef }} | ||
comment-body: | ||
description: "Full comment body" | ||
value: ${{ fromJson(steps.process-comment.outputs.result).commentBody }} | ||
matches: | ||
description: "JSON object with regex matches" | ||
value: ${{ toJson(fromJson(steps.process-comment.outputs.result).matches) }} | ||
match-found: | ||
description: "Whether the regex matched or not" | ||
value: ${{ fromJson(steps.process-comment.outputs.result).matchFound }} | ||
comment-id: | ||
description: "The ID of the triggering comment" | ||
value: ${{ fromJson(steps.process-comment.outputs.result).commentId }} | ||
|
||
runs: | ||
using: "composite" | ||
|
||
steps: | ||
- name: Process PR Comment | ||
id: process-comment | ||
uses: actions/github-script@v7 | ||
with: | ||
script: | | ||
const commentBody = context.payload.comment.body; | ||
const issueNumber = context.payload.issue.number; | ||
const commentId = context.payload.comment.id; | ||
|
||
// Get PR details | ||
const { data: pr } = await github.rest.pulls.get({ | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
pull_number: issueNumber | ||
}); | ||
|
||
const result = { | ||
prNumber: issueNumber, | ||
prHeadSha: pr.head.sha, | ||
prHeadRef: pr.head.ref, | ||
prBaseRef: pr.base.ref, | ||
commentBody: commentBody, | ||
commentId: commentId, | ||
matches: {}, | ||
matchFound: true | ||
}; | ||
|
||
// Process regex match if pattern provided | ||
const matchPattern = '${{ inputs.match }}'; | ||
if (matchPattern) { | ||
try { | ||
const regex = new RegExp(matchPattern, 'm'); | ||
const match = regex.exec(commentBody); | ||
|
||
if (match) { | ||
result.matchFound = true; | ||
|
||
// Add numbered groups | ||
for (let i = 1; i < match.length; i++) { | ||
result.matches[i-1] = match[i] || ""; | ||
} | ||
|
||
// Add named groups if they exist | ||
if (match.groups) { | ||
Object.assign(result.matches, match.groups); | ||
} | ||
|
||
if ('${{ inputs.ack }}'.toLowerCase() === 'true') { | ||
// React to the comment with a thumbs up | ||
await github.rest.reactions.createForIssueComment({ | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
comment_id: commentId, | ||
content: '+1', | ||
}); | ||
} | ||
} else { | ||
result.matchFound = false; | ||
} | ||
} catch (error) { | ||
console.log(`Error processing regex: ${error.message}`); | ||
} | ||
} | ||
|
||
return result; | ||
- name: Debug | ||
shell: bash | ||
run: | | ||
echo ${{ steps.process-comment.outputs.result }} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
name: Trigger on a PR comment | ||
|
||
permissions: | ||
pull-requests: write # Required to add a comment | ||
checks: write # Required to add a check | ||
issues: write # Required to react to the triggering comment | ||
|
||
on: | ||
issue_comment: | ||
types: [created] | ||
|
||
jobs: | ||
check-comment: | ||
if: ${{ github.event.issue.pull_request && startsWith(github.event.comment.body, '/foo') }} | ||
runs-on: ubuntu-latest | ||
outputs: | ||
match-found: ${{ steps.comment-check.outputs.match-found }} | ||
matches: ${{ steps.comment-check.outputs.matches }} | ||
pr-head-sha: ${{ steps.comment-check.outputs.pr-head-sha }} | ||
pr-head-ref: ${{ steps.comment-check.outputs.pr-head-ref }} | ||
pr-base-ref: ${{ steps.comment-check.outputs.pr-base-ref }} | ||
steps: | ||
- id: comment-check | ||
name: Check PR Comment | ||
uses: ensuro/github-actions/pr-comment-trigger@pr-comment-trigger # Use a tag or commit hash here | ||
with: | ||
match: "^/foo (?<bar>.*?) (?<baz>.*?)$" | ||
|
||
- name: Debug Outputs | ||
run: | | ||
echo "Match found: ${{ steps.comment-check.outputs.match-found }}" | ||
echo "Matches: ${{ steps.comment-check.outputs.matches }}" | ||
echo "PR head SHA: ${{ steps.comment-check.outputs.pr-head-sha }}" | ||
|
||
process-command: | ||
needs: check-comment | ||
if: ${{ needs.check-comment.outputs.match-found == 'true' }} | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Create a check | ||
id: create-check | ||
uses: actions/github-script@v7 | ||
with: | ||
script: | | ||
const { data: check } = await github.rest.checks.create({ | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
name: 'Command: Check Transaction', | ||
head_sha: '${{ needs.check-comment.outputs.pr-head-sha }}', | ||
status: 'in_progress', | ||
output: { | ||
title: 'Transaction Check Initiated', | ||
summary: 'Processing the check transaction command...' | ||
} | ||
}); | ||
return check.id; | ||
|
||
- name: Process Command | ||
run: | | ||
echo "Processing PR #${{ github.event.issue.number }} ${{ needs.check-comment.outputs.pr-head-ref }} -> ${{ needs.check-comment.outputs.pr-base-ref }}" | ||
echo "Bar: ${{ fromJson(needs.check-comment.outputs.matches).bar }}" | ||
echo "Baz: ${{ fromJson(needs.check-comment.outputs.matches).baz }}" | ||
|
||
- name: Comment on PR | ||
id: comment | ||
uses: actions/github-script@v7 | ||
with: | ||
script: | | ||
const matches = JSON.parse(`${{ needs.check-comment.outputs.matches }}`); | ||
|
||
const comment = `## Foo command was executed | ||
**Bar**: ${matches.bar || "unknown"} | ||
**Baz**: \`${matches.baz || "unknown"}\` | ||
**Status**: ✅ Success | ||
|
||
*This check was triggered by a [comment](${{ github.event.comment.html_url }})*`; | ||
|
||
const posted = await github.rest.issues.createComment({ | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
issue_number: ${{ github.event.issue.number }}, | ||
body: comment | ||
}); | ||
|
||
return posted.url | ||
|
||
- name: Complete the check | ||
uses: actions/github-script@v7 | ||
if: always() # The check should be completed even if the job fails | ||
with: | ||
script: | | ||
await github.rest.checks.update({ | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
check_run_id: ${{ steps.create-check.outputs.result }}, | ||
status: 'completed', | ||
conclusion: '${{ job.status }}', | ||
output: { | ||
title:'Transaction Check Finished', | ||
summary: 'See ${{ steps.comment.outputs.result }}' | ||
} | ||
}); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.