generated from freeCodeCamp/template
-
-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: assign translator or reviewer according to slash command (#313)
* feat: assign commenter as a translator * feat: assgin reviewer, organize scripts into separate files * fix: simplify message
- Loading branch information
Showing
3 changed files
with
184 additions
and
27 deletions.
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 |
---|---|---|
|
@@ -5,39 +5,41 @@ name: Issue Comments | |
permissions: | ||
issues: write | ||
jobs: | ||
check_comments: | ||
name: Check comments for commands | ||
validate_command: | ||
name: Validate command | ||
runs-on: ubuntu-latest | ||
|
||
# Run the jobs only if the new comment starts with '/' | ||
# Run the job only if the new comment starts with '/' | ||
if: | | ||
!github.event.issue.pull_request && startsWith(github.event.comment.body, '/') | ||
outputs: | ||
valid_command: ${{ steps.command_check.outputs.valid_command }} | ||
command: ${{ steps.command_check.outputs.command }} | ||
target_status: ${{ steps.command_check.outputs.target_status }} # Which status to move the card to | ||
steps: | ||
- name: Validate command | ||
id: command_check | ||
run: | | ||
if [[ "${{ github.event.comment.body }}" == /translate* ]]; then | ||
echo "COMMAND=translate" >> $GITHUB_ENV | ||
echo "TARGET_STATUS=in Translation" >> $GITHUB_ENV | ||
echo "VALID_COMMAND=true" >> $GITHUB_ENV | ||
echo "::set-output name=command::translate" | ||
echo "::set-output name=target_status::in Translation" | ||
echo "::set-output name=valid_command::true" | ||
elif [[ "${{ github.event.comment.body }}" == /review* ]]; then | ||
echo "COMMAND=review" >> $GITHUB_ENV | ||
echo "TARGET_STATUS=in Review" >> $GITHUB_ENV | ||
echo "VALID_COMMAND=true" >> $GITHUB_ENV | ||
echo "::set-output name=command::review" | ||
echo "::set-output name=target_status::in Review" | ||
echo "::set-output name=valid_command::true" | ||
else | ||
echo "::warning::Invalid command. The comment must start with /translate or /review." | ||
echo "VALID_COMMAND=false" >> $GITHUB_ENV | ||
echo "::set-output name=valid_command::false" | ||
fi | ||
# Reply to the user if the command was invalid | ||
- name: Comment on issue # Notify user if the command was invalid | ||
if: env.VALID_COMMAND == 'false' | ||
- name: Feedback for invalid command | ||
if: steps.command_check.outputs.valid_command != 'true' | ||
uses: actions/github-script@v7 | ||
with: | ||
script: | | ||
const issueComment = ` | ||
@${{ github.event.comment.user.login }} The command was invalid. The comment must start with /translate or /review. | ||
If you are not sure how to use the command, reach out to your language lead. Thank you for contributing! | ||
`; | ||
github.rest.issues.createComment({ | ||
issue_number: context.issue.number, | ||
|
@@ -47,14 +49,18 @@ jobs: | |
}); | ||
github-token: ${{ secrets.GITHUB_TOKEN }} | ||
|
||
# Update the status according to the command | ||
- name: Act on the command # Process valid commands | ||
if: env.VALID_COMMAND == 'true' | ||
run: | | ||
echo "The command is '${{ env.COMMAND }}'" | ||
echo "github.event.issue.node_id is ${{ github.event.issue.node_id }}" | ||
get_project_card_info: | ||
name: Get project card information | ||
needs: validate_command | ||
if: needs.validate_command.outputs.valid_command == 'true' | ||
runs-on: ubuntu-latest | ||
outputs: | ||
cardId: ${{ steps.get_card.outputs.cardId }} | ||
projectUrl: ${{ steps.get_card.outputs.projectUrl }} | ||
projectName: ${{ steps.get_card.outputs.projectName }} | ||
steps: | ||
- name: Get project card | ||
if: env.VALID_COMMAND == 'true' | ||
id: get_card | ||
uses: actions/github-script@v7 | ||
env: | ||
ISSUE_NODE_ID: ${{ github.event.issue.node_id }} | ||
|
@@ -69,6 +75,7 @@ jobs: | |
node { | ||
id | ||
url | ||
title | ||
items(first: 100) { | ||
edges { | ||
node { | ||
|
@@ -93,20 +100,59 @@ jobs: | |
}; | ||
const result = await github.graphql(query, variables); | ||
console.log(`Result: ${JSON.stringify(result)}`); | ||
const cardId = result.node.projectsV2.edges[0].node.items.edges.find(edge => edge.node.content.id === process.env.ISSUE_NODE_ID).node.id; | ||
const projectUrl = result.node.projectsV2.edges[0].node.url; | ||
const projectName = result.node.projectsV2.edges[0].node.title; | ||
console.log(`Card ID: ${cardId}`); | ||
console.log(`Project URL: ${projectUrl}`); | ||
console.log(`Project Name: ${projectName}`); | ||
core.setOutput('cardId', cardId); | ||
core.setOutput('projectUrl', projectUrl); | ||
core.setOutput('projectName', projectName); | ||
github-token: ${{ secrets.MOVE_CARDS_TOKEN }} | ||
id: get_card | ||
- name: Update project | ||
if: env.VALID_COMMAND == 'true' | ||
|
||
assign_issue: | ||
name: Assign issue | ||
needs: [validate_command, get_project_card_info] | ||
if: needs.validate_command.outputs.valid_command == 'true' | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout # Prepare to run the following scripts | ||
uses: actions/checkout@v3 | ||
- name: Assign issue to the commenter as translator | ||
if: needs.validate_command.outputs.command == 'translate' | ||
uses: actions/github-script@v7 | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
with: | ||
script: | | ||
const script = require('./scripts/assignTranslator.js'); | ||
await script({github, context, core}); | ||
- name: Assign issue to the reviewer | ||
if: needs.validate_command.outputs.command == 'review' | ||
uses: actions/github-script@v7 | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
with: | ||
script: | | ||
const script = require('./scripts/assignReviewer.js'); | ||
const projectName = '${{ needs.get_project_card_info.outputs.projectName }}'; | ||
await script({github, context, core, projectName}); | ||
update_project_card: | ||
name: Update project card | ||
needs: [validate_command, get_project_card_info, assign_issue] | ||
if: needs.validate_command.outputs.valid_command == 'true' | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Update project card status | ||
uses: titoportas/[email protected] | ||
with: | ||
project-url: ${{ steps.get_card.outputs.projectUrl }} | ||
project-url: ${{ needs.get_project_card_info.outputs.projectUrl }} | ||
github-token: ${{ secrets.MOVE_CARDS_TOKEN }} | ||
item-id: ${{ steps.get_card.outputs.cardId }} | ||
item-id: ${{ needs.get_project_card_info.outputs.cardId }} | ||
field-keys: Status | ||
field-values: ${{ env.TARGET_STATUS }} | ||
field-values: ${{ needs.validate_command.outputs.target_status }} |
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,64 @@ | ||
module.exports = async ({github, context, core, projectName}) => { | ||
let issueComment = ''; | ||
|
||
// List of the language leads | ||
const languageLeads = { | ||
spanish: 'RafaelDavisH', | ||
portuguese: 'DanielRosa74', | ||
italian: 'Dario-DC', | ||
japanese: 'sidemt', | ||
ukrainian: 'anastasiiauk', | ||
chinese: 'miyaliu666', | ||
korean: 'AlisonYoon', | ||
'test project': 'sidemt' // for testing | ||
} | ||
|
||
try { | ||
// Expecting the project name to be in "[NEWS I18N] - Spanish" format | ||
const language = projectName.split('-')[1].trim().toLowerCase(); | ||
const languageLead = languageLeads[language]; | ||
if (!languageLead) { | ||
throw new Error(`Language lead not found for language: ${language}`); | ||
} | ||
|
||
// Make sure that the current user is the translator for this article, | ||
// then assign it to the language lead for review | ||
const issue = await github.rest.issues.get({ | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
issue_number: context.issue.number | ||
}); | ||
|
||
if (issue.data.assignees.some(assignee => assignee.login === context.actor)) { | ||
const response = await github.rest.issues.addAssignees({ | ||
issue_number: context.issue.number, | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
assignees: [languageLead] | ||
}); | ||
if (response.status.toString().startsWith('2')) { | ||
issueComment = `@${ languageLead } This article is ready for review.`; | ||
} else { | ||
console.error('addAssignees returned HTTP status:', response.status); | ||
issueComment = `@${ context.actor } Something went wrong while assigning the issue to the reviewer. (HTTP status: ${ response.status }) | ||
Please contact your language lead if the problem persists.`; | ||
core.setFailed('addAssignees returned an unexpected HTTP status.'); | ||
} | ||
} else { | ||
issueComment = `@${ context.actor } Could not assign this issue to the reviewer. | ||
Check if you have translated this article as an assignee.`; | ||
core.setFailed('The commenter was not the translator of this issue.'); | ||
} | ||
} catch (error) { | ||
console.error('An error has occurred while assigning the issue:', error); | ||
issueComment = `@${ context.actor } An error has occurred while assigning the issue to the reviewer. | ||
Please contact your language lead if the problem persists.`; | ||
core.setFailed('An error has occurred while assigning the issue.'); | ||
} | ||
await github.rest.issues.createComment({ | ||
issue_number: context.issue.number, | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
body: issueComment | ||
}); | ||
} |
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,47 @@ | ||
module.exports = async ({github, context, core}) => { | ||
let issueComment = ''; | ||
|
||
// Check that no one else is assigned yet before assigning the current user | ||
try { | ||
const issue = await github.rest.issues.get({ | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
issue_number: context.issue.number | ||
}); | ||
|
||
if (issue.data.assignees.length === 0) { | ||
const response = await github.rest.issues.addAssignees({ | ||
issue_number: context.issue.number, | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
assignees: [context.actor] | ||
}); | ||
if (response.status.toString().startsWith('2')) { | ||
issueComment = `@${ context.actor } We have assigned this article to you.`; | ||
} else { | ||
console.error('addAssignees returned HTTP status:', response.status); | ||
issueComment = `@${ context.actor } Something went wrong while assigning the issue. (HTTP status: ${ response.status }) | ||
Please contact your language lead if the problem persists.`; | ||
core.setFailed('addAssignees returned an unexpected HTTP status.'); | ||
} | ||
} else if (issue.data.assignees.length === 1 && issue.data.assignees[0].login === context.actor) { | ||
issueComment = `@${ context.actor } The article is already assigned to you.`; | ||
core.setFailed('The article is already assigned to the commenter.'); | ||
} else { | ||
issueComment = `@${ context.actor } The article is already assigned to someone else. | ||
Please choose a different article to translate.`; | ||
core.setFailed('The article is already assigned to other contributor.'); | ||
} | ||
} catch (error) { | ||
console.error('An error has occurred while assigning the issue:', error); | ||
issueComment = `@${ context.actor } An error has occurred while assigning the issue to you. | ||
Please contact your language lead if the problem persists.`; | ||
core.setFailed('An error has occurred while assigning the issue.'); | ||
} | ||
await github.rest.issues.createComment({ | ||
issue_number: context.issue.number, | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
body: issueComment | ||
}); | ||
} |