Skip to content

Commit

Permalink
feat: assign translator or reviewer according to slash command (#313)
Browse files Browse the repository at this point in the history
* feat: assign commenter as a translator

* feat: assgin reviewer, organize scripts into separate files

* fix: simplify message
  • Loading branch information
sidemt authored Apr 19, 2024
1 parent 23274dc commit 3d224a5
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 27 deletions.
100 changes: 73 additions & 27 deletions .github/workflows/slash-command-action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 }}
Expand All @@ -69,6 +75,7 @@ jobs:
node {
id
url
title
items(first: 100) {
edges {
node {
Expand All @@ -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 }}
64 changes: 64 additions & 0 deletions scripts/assignReviewer.js
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
});
}
47 changes: 47 additions & 0 deletions scripts/assignTranslator.js
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
});
}

0 comments on commit 3d224a5

Please sign in to comment.