-
Notifications
You must be signed in to change notification settings - Fork 12
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
✨ reconcile issue reusable workflow #58
Merged
Merged
Changes from all commits
Commits
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 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,12 @@ | ||
name: Handle Issue Comment | ||
|
||
on: | ||
issue_comment: | ||
|
||
jobs: | ||
reconcile-issue-comment: | ||
permissions: | ||
contents: write | ||
issues: write | ||
pull-requests: write | ||
uses: ./.github/workflows/reconcile-issue-comment.yaml |
This file contains 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,25 @@ | ||
name: Reconcile GitHub Issue | ||
|
||
on: | ||
issues: | ||
types: | ||
- opened | ||
- edited | ||
- closed | ||
- reopened | ||
- labeled | ||
- unlabeled | ||
|
||
# This prevents potential race conditions by only allowing this action to handle | ||
# one update at a time for a given issue. | ||
concurrency: | ||
group: reconcile-issue-${{ github.event.issue.number }} | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
reconcile-issue: | ||
permissions: | ||
contents: write | ||
issues: write | ||
pull-requests: write | ||
uses: ./.github/workflows/reconcile-issue.yaml |
This file contains 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,116 @@ | ||
name: Reusable Reconcile Issue Comment | ||
|
||
on: | ||
workflow_call: | ||
|
||
jobs: | ||
event_type: | ||
name: Check event type | ||
runs-on: ubuntu-latest | ||
if: > | ||
github.event_name == 'issue_comment' && | ||
( | ||
github.event.action == 'created' || | ||
github.event.action == 'edited' | ||
) | ||
steps: | ||
- name: ok | ||
run: /bin/true | ||
|
||
addLabels: | ||
needs: event_type | ||
name: Add Labels | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: ok | ||
uses: actions/github-script@v7 | ||
with: | ||
script: | | ||
const commentRegex = /(<!--.*?-->)|(<!--[\S\s]+?-->)|(<!--[\S\s]*?$)/g; | ||
const labelRegex = /^(\/(area|kind|priority|sig|triage|wg))\s*(.*?)\s*$/gm; | ||
const removeLabelRegex = /^\/remove-(area|committee|kind|language|priority|sig|triage|wg)\s*(.*?)\s*$/gm; | ||
const labelsToAdd = []; | ||
const labelsToRemove = []; | ||
let match; | ||
|
||
const { data: comment } = await github.rest.issues.getComment({ | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
comment_id: context.payload.comment.id, | ||
}); | ||
|
||
const bodyWithoutComments = comment.body.replaceAll(commentRegex, ''); | ||
while ((match = labelRegex.exec(bodyWithoutComments)) !== null) { | ||
const keyword = match[2]; | ||
const text = match[3]; | ||
|
||
const labelToAdd = `${keyword}/${text}`; | ||
const labelExists = await github.rest.issues.getLabel({ | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
name: labelToAdd, | ||
}).catch(() => false); | ||
if (labelExists) { | ||
labelsToAdd.push(labelToAdd); | ||
} else { | ||
console.log(`label ${labelToAdd} does not exist on this repo`); | ||
} | ||
} | ||
console.log(labelsToAdd); | ||
|
||
while ((match = removeLabelRegex.exec(bodyWithoutComments)) !== null) { | ||
const keyword = match[1]; | ||
const text = match[2]; | ||
|
||
const labelToRemove = `${keyword}/${text}`; | ||
labelsToRemove.push(labelToRemove); | ||
} | ||
console.log(labelsToRemove); | ||
if (labelsToAdd.length == 0 && labelsToRemove.length == 0) { | ||
console.log("Nothing to do!"); | ||
return; | ||
} | ||
|
||
// If we make it this far, we should verify the commenter is at | ||
// least a collaborator. | ||
// TODO(djzager): Is this enough? | ||
const commenterLogin = comment.user.login; | ||
try { | ||
await github.rest.repos.checkCollaborator({ | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
username: commenterLogin, | ||
}); | ||
console.log(`Commenter ${commenterLogin} is a collaborator.`); | ||
} catch (error) { | ||
console.log(`Commenter ${commenterLogin} is not a collaborator.`); | ||
await github.rest.issues.createComment({ | ||
issue_number: context.issue.number, | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
body: "Only collaborators can add/remove labels", | ||
}); | ||
return; | ||
} | ||
|
||
// Add the labels | ||
if (labelsToAdd.length > 0) { | ||
await github.rest.issues.addLabels({ | ||
issue_number: context.issue.number, | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
labels: labelsToAdd | ||
}); | ||
} | ||
|
||
// Remove the labels | ||
if (labelsToRemove.length > 0) { | ||
for (const labelToRemove of labelsToRemove) { | ||
await github.rest.issues.removeLabel({ | ||
issue_number: context.issue.number, | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
name: labelToRemove | ||
}); | ||
} | ||
} |
This file contains 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,156 @@ | ||
name: Reusable Reconcile Issue | ||
|
||
on: | ||
workflow_call: | ||
|
||
jobs: | ||
event_type: | ||
name: Check event type | ||
runs-on: ubuntu-latest | ||
if: github.event_name == 'issues' || github.event_name == 'pull_request' | ||
steps: | ||
- name: ok | ||
run: /bin/true | ||
|
||
labels: | ||
needs: event_type | ||
name: Check labels | ||
runs-on: ubuntu-latest | ||
if: github.event.action != 'closed' | ||
steps: | ||
- name: triage | ||
uses: actions/github-script@v7 | ||
with: | ||
script: | | ||
// begin helper function for adding comments | ||
async function ensureComment(body, shouldExist) { | ||
// Try to find the comment | ||
for await (const { data: comments } of github.paginate.iterator( | ||
github.rest.issues.listComments, | ||
{ | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
issue_number: context.issue.number, | ||
} | ||
)) { | ||
const comment = comments.find( | ||
(comment) => | ||
comment.user && | ||
comment.user.login == "github-actions[bot]" && | ||
comment.body && | ||
comment.body.includes(body) | ||
); | ||
|
||
// If we find the comment...we are done | ||
if (comment) { | ||
if (!shouldExist) { | ||
await github.rest.issues.deleteComment({ | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
comment_id: comment.id, | ||
}); | ||
} | ||
return; | ||
} | ||
} | ||
|
||
// Create the comment if it doesn't exist | ||
if (shouldExist) { | ||
await github.rest.issues.createComment({ | ||
issue_number: context.issue.number, | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
body: body, | ||
}); | ||
} | ||
} | ||
// end helper function for adding comments | ||
|
||
const { data: issue } = await github.rest.issues.get({ | ||
issue_number: context.issue.number, | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
}); | ||
|
||
const labels = issue.labels.map(label => label.name); | ||
console.log(`Labels: ${labels}`); | ||
|
||
// triage label | ||
if (labels.some(label => label.match('^triage/accepted$'))) { | ||
if (labels.includes('needs-triage')) { | ||
await github.rest.issues.removeLabel({ | ||
issue_number: context.issue.number, | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
name: 'needs-triage' | ||
}); | ||
} | ||
} else { | ||
let comment = "This issue is currently awaiting triage.\n"; | ||
comment += "If contributors determine this is a relevant issue, they will accept it by applying the `triage/accepted` label and provide further guidance.\n"; | ||
comment += "The `triage/accepted` label can be added by org members."; | ||
await github.rest.issues.addLabels({ | ||
issue_number: context.issue.number, | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
labels: ['needs-triage'] | ||
}); | ||
await ensureComment(comment, true); | ||
} | ||
|
||
// kind label | ||
if (labels.some(label => label.match('^kind/'))) { | ||
if (labels.includes('needs-kind')) { | ||
await github.rest.issues.removeLabel({ | ||
issue_number: context.issue.number, | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
name: 'needs-kind' | ||
}); | ||
} | ||
} else { | ||
await github.rest.issues.addLabels({ | ||
issue_number: context.issue.number, | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
labels: ['needs-kind'] | ||
}); | ||
} | ||
|
||
// priority label | ||
if (labels.some(label => label.match('^priority/'))) { | ||
if (labels.includes('needs-priority')) { | ||
await github.rest.issues.removeLabel({ | ||
issue_number: context.issue.number, | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
name: 'needs-priority' | ||
}); | ||
} | ||
} else { | ||
await github.rest.issues.addLabels({ | ||
issue_number: context.issue.number, | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
labels: ['needs-priority'] | ||
}); | ||
} | ||
|
||
// good first issue | ||
let firstIssueComment = "This issue has been marked 'good first issue'\n"; | ||
firstIssueComment += "Please, make sure it aligns with the criteria found [here](https://contribute.cncf.io/maintainers/templates/issue-labels/#good-first-issue)\n"; | ||
if (labels.some(label => label.match('^good first issue$'))) { | ||
await ensureComment(firstIssueComment, true); | ||
} else { | ||
await ensureComment(firstIssueComment, false); | ||
} | ||
|
||
project: | ||
needs: event_type | ||
name: Add new issues to planning project | ||
runs-on: ubuntu-latest | ||
if: github.event.action == 'opened' | ||
steps: | ||
- uses: actions/add-to-project@v0.5.0 | ||
with: | ||
project-url: https://github.com/orgs/konveyor/projects/67 |
This file contains 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
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can this be a separate file? As inline YAML, it is harder to review the logic within it, because we lose syntax highlighting (which can make hard to maintain this in the future)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. I think what I will do is create an issue to rewrite it in golang to expand those that can help us maintain/fix it when it breaks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll write the issue for that after this merges so I can link to the source lines where we have javascript as inline YAML.