-
Notifications
You must be signed in to change notification settings - Fork 217
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
Implementation of project board automations #3375
Merged
Merged
Changes from all commits
Commits
Show all changes
51 commits
Select commit
Hold shift + click to select a range
f57cfe1
Replace `@octokit/rest` with `octokit`
dhruvkb cfd9dd0
Create a util to get authenticated Octokit
dhruvkb 6a69665
Create a wrapper over GitHub's GraphQL APIs for Project v2
dhruvkb 6323f04
Install `yargs` to parse CLI arguments
dhruvkb 545eec7
Add utility to parse `event.json` files for project automations
dhruvkb 4da2af9
Add automations for issues, replacing old `new_issues.yml`
dhruvkb e1a4e2b
Merge branch 'main' of https://github.com/WordPress/openverse into prβ¦
dhruvkb 890bfa3
Clarify separation of event name and action
dhruvkb edb8724
Extract CLI parsing into a util to share between issues and PRs
dhruvkb 70aa34b
Fix documentation typo
dhruvkb f88417e
Add automations for PRs
dhruvkb a810bcd
Strip leading numbers from column names
dhruvkb 5d0ca31
Fix sync for PR automations
dhruvkb 208dc98
Document the project automation files
dhruvkb 2208c7e
Use `reviewDecision` to determine column placement
dhruvkb 5e3bc44
Use `init` function to populate extra PR info
dhruvkb 27693f2
Move critical issues directly to the "To Do" column
dhruvkb a3397f8
Move linked issues for PR open, reopen, edited and closed events
dhruvkb aa27065
Update documentation
dhruvkb f50cb20
Fix broken links
dhruvkb 3eb386f
Remove stray space
dhruvkb e82e840
Add steps to check out repo and setup CI environment
dhruvkb 25dfb8b
Ignore event data payload
dhruvkb 780713e
Allow PR automations to run on fork PRs as well
dhruvkb 1a5ce80
Expand documentation for the workflows
dhruvkb a56daa8
Fix typo in variable name
dhruvkb 5502d77
Fix incorrect file name
dhruvkb 53142df
Add braces around `if`-`else`
dhruvkb f4ba8ef
Add braces around each `case` of `switch`
dhruvkb aaf807f
Use a dict to get project number
dhruvkb d941bfa
Inject Octokit client into `PullRequest`
dhruvkb 1317936
Get project ID and fields in one request
dhruvkb 4fb2c87
Document constructors
dhruvkb 5fdc687
Inject Octokit client into `getProject`
dhruvkb adf5ba8
Clean up typehints
dhruvkb 85b8ec9
Nest everything under an exported `main` function
dhruvkb 85a9be5
Document the other responsibility of `syncPriority`
dhruvkb 760b2f6
Clarify the board associated with the `columns` variable
dhruvkb 9916a56
Use `action/github-script`
dhruvkb 51f3e78
Undo dependency changes
dhruvkb 1428f82
Undo collateral changes
dhruvkb cc28ea0
Remove unused code
dhruvkb ba06d19
Remove unnecessary Git-ignore file
dhruvkb 4e5a052
Fix type annotations for Octokit
dhruvkb c151464
Simplify `PullRequest` construction
dhruvkb 70c7d8c
Collect all relevant info in one file
dhruvkb b1a6be4
Make `columns` a field instead of computed property
dhruvkb 19e9d71
Extract methods outside `main`
dhruvkb a834ac3
Use the correct token
dhruvkb ae98281
Update comments to reflect code changes
dhruvkb 807c388
Use `pull_request` instead of `pull_request_target` because it doesn'β¦
dhruvkb 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
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,40 @@ | ||
# Runs all automations related to issue events. | ||
# | ||
# See `pr_automations_init.yml` and `pr_automations.yml` for the corresponding | ||
# implementation for PRs. | ||
name: Issue automations | ||
|
||
on: | ||
issues: | ||
types: | ||
- opened | ||
- reopened | ||
- closed | ||
- assigned | ||
- labeled | ||
- unlabeled | ||
|
||
jobs: | ||
run: | ||
name: Perform issue automations | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout repository | ||
uses: actions/checkout@v4 | ||
|
||
- name: Setup CI env | ||
uses: ./.github/actions/setup-env | ||
with: | ||
setup_python: false | ||
install_recipe: node-install | ||
|
||
- name: Perform issue automations | ||
uses: actions/github-script@v7 | ||
env: | ||
EVENT_NAME: ${{ github.event_name }} | ||
EVENT_ACTION: ${{ github.event.action }} | ||
with: | ||
github-token: ${{ secrets.GITHUB_TOKEN }} | ||
script: | | ||
const { main } = await import('./automations/js/project_automation/issues.mjs') | ||
await main(github, context) |
This file was deleted.
Oops, something went wrong.
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,80 @@ | ||
# Runs all automations related to PR events. | ||
# | ||
# See `issue_automations.yml` for the corresponding implementation for issues. | ||
# | ||
# The automations for PR events are a little more complex than those for issues | ||
# because PRs are a less secure environment. To avoid leaking secrets, we need | ||
# to run automations with code as it appears on `main`. | ||
# | ||
# `pull_request_target` serves this purpose but there is no corresponding | ||
# `_target` version for `pull_request_review`. So we take this roundabout | ||
# approach: | ||
# | ||
# This workflow waits for the `pr_automations_init.yml` workflow to complete and | ||
# then uses its exports to run automations from main, with access to secrets. | ||
# | ||
# ...continued from `pr_automations_init.yml` | ||
# | ||
# 4. This workflow runs after `pr_automations_init.yml` workflow completes. | ||
# 5. It downloads the artifacts from that workflow run. | ||
# 6. It extracts the JSON file from the ZIP to `/tmp`. | ||
# 7. It runs the automations as a script, which can access secrets. | ||
|
||
name: PR automations | ||
|
||
on: | ||
workflow_run: | ||
workflows: | ||
- PR automations init | ||
types: | ||
- completed | ||
|
||
jobs: | ||
run: | ||
name: Perform PR automations | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout repository | ||
uses: actions/checkout@v4 | ||
|
||
- name: Setup CI env | ||
uses: ./.github/actions/setup-env | ||
with: | ||
setup_python: false | ||
install_recipe: node-install | ||
|
||
# This step was copied from the GitHub docs. | ||
# Ref: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#using-data-from-the-triggering-workflow | ||
- name: Download artifact | ||
uses: actions/github-script@v7 | ||
with: | ||
script: | | ||
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
run_id: context.payload.workflow_run.id, | ||
}); | ||
let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => { | ||
return artifact.name == "event_info" | ||
})[0]; | ||
let download = await github.rest.actions.downloadArtifact({ | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
artifact_id: matchArtifact.id, | ||
archive_format: 'zip', | ||
}); | ||
let fs = require('fs'); | ||
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/event_info.zip`, Buffer.from(download.data)); | ||
|
||
- name: Unzip artifact | ||
run: | | ||
unzip event_info.zip | ||
mv event.json /tmp/event.json | ||
|
||
- name: Perform PR automations | ||
uses: actions/github-script@v7 | ||
with: | ||
github-token: ${{ secrets.GITHUB_TOKEN }} | ||
script: | | ||
const { main } = await import('./automations/js/project_automation/prs.mjs') | ||
await main(github) |
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,50 @@ | ||
# Initialises all automations related to PR events. | ||
# | ||
# See `issue_automations.yml` for the corresponding implementation for issues. | ||
# | ||
# The automations for PR events are a little more complex than those for issues | ||
# because PRs are a less secure environment. To avoid leaking secrets, we need | ||
# to run automations with code as it appears on `main`. | ||
# | ||
# `pull_request_target` serves this purpose but there is no corresponding | ||
# `_target` version for `pull_request_review`. So we take this roundabout | ||
# approach: | ||
# | ||
# 1. This workflow runs for the events and their subtypes we are interested in. | ||
# 2. It saves the event name, action and PR node ID to a JSON file. | ||
# 3. It uploads the JSON file as an artifact. | ||
# 4. Its completion triggers the `pr_automations.yml` workflow. | ||
# | ||
# continued in `pr_automations.yml`... | ||
|
||
name: PR automations init | ||
|
||
on: | ||
pull_request: | ||
types: | ||
- opened | ||
- reopened | ||
- edited | ||
- converted_to_draft | ||
- ready_for_review | ||
- closed | ||
pull_request_review: | ||
|
||
jobs: | ||
run: | ||
name: Save event info | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Save event info | ||
run: | | ||
echo '{"eventName": "'"$EVENT_NAME"'", "eventAction": "'"$EVENT_ACTION"'", "prNodeId": "'"$PR_NODE_ID"'"}' > /tmp/event.json | ||
env: | ||
EVENT_NAME: ${{ github.event_name }} | ||
EVENT_ACTION: ${{ github.event.action }} | ||
PR_NODE_ID: ${{ github.event.pull_request.node_id }} | ||
|
||
- name: Upload event info as artifact | ||
uses: actions/upload-artifact@v3 | ||
with: | ||
name: event_info | ||
path: /tmp/event.json |
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,91 @@ | ||
import { getBoard } from '../utils/projects.mjs' | ||
|
||
/** | ||
* Set the "Priority" custom field based on the issue's labels. Also move | ||
* the card for critical issues directly to the "π To Do" column. | ||
* | ||
* @param issue {import('@octokit/rest')} | ||
* @param board {import('../utils/projects.mjs').Project} | ||
* @param card {import('../utils/projects.mjs').Card} | ||
*/ | ||
async function syncPriority(issue, board, card) { | ||
const priority = issue.labels.find((label) => | ||
label.name.includes('priority') | ||
)?.name | ||
if (priority) { | ||
await board.setCustomChoiceField(card.id, 'Priority', priority) | ||
} | ||
if (priority === 'π₯ priority: critical') { | ||
await board.moveCard(card.id, board.columns.ToDo) | ||
} | ||
} | ||
|
||
/** | ||
* This is the entrypoint of the script. | ||
* | ||
* @param octokit {import('@octokit/rest').Octokit} the Octokit instance to use | ||
* @param context {import('@actions/github').context} info about the current event | ||
*/ | ||
export const main = async (octokit, context) => { | ||
const { EVENT_ACTION: eventAction } = process.env | ||
|
||
const issue = context.payload.issue | ||
const label = context.payload.label | ||
|
||
if (issue.labels.some((label) => label.name === 'π§ project: thread')) { | ||
// Do not add project threads to the Backlog board. | ||
process.exit(0) | ||
} | ||
|
||
const backlogBoard = await getBoard(octokit, 'Backlog') | ||
|
||
// Create new, or get the existing, card for the current issue. | ||
const card = await backlogBoard.addCard(issue.node_id) | ||
|
||
switch (eventAction) { | ||
case 'opened': | ||
case 'reopened': { | ||
if (issue.labels.some((label) => label.name === 'β status: blocked')) { | ||
await backlogBoard.moveCard(card.id, backlogBoard.columns.Blocked) | ||
} else { | ||
await backlogBoard.moveCard(card.id, backlogBoard.columns.Backlog) | ||
} | ||
|
||
await syncPriority(issue, backlogBoard, card) | ||
break | ||
} | ||
|
||
case 'closed': { | ||
if (issue.state_reason === 'completed') { | ||
await backlogBoard.moveCard(card.id, backlogBoard.columns.Done) | ||
} else { | ||
await backlogBoard.moveCard(card.id, backlogBoard.columns.Discarded) | ||
} | ||
break | ||
} | ||
|
||
case 'assigned': { | ||
if (card.status === backlogBoard.columns.Backlog) { | ||
await backlogBoard.moveCard(card.id, backlogBoard.columns.ToDo) | ||
} | ||
break | ||
} | ||
|
||
case 'labeled': { | ||
if (label.name === 'β status: blocked') { | ||
await backlogBoard.moveCard(card.id, backlogBoard.columns.Blocked) | ||
} | ||
await syncPriority(issue, backlogBoard, card) | ||
break | ||
} | ||
|
||
case 'unlabeled': { | ||
if (label.name === 'β status: blocked') { | ||
// TODO: Move back to the column it came from. | ||
await backlogBoard.moveCard(card.id, backlogBoard.columns.Backlog) | ||
} | ||
await syncPriority(issue, backlogBoard, card) | ||
break | ||
} | ||
} | ||
} |
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.
This is one thing that's bothering me a lot, it's two lines of Bash breaking up two
action/github-script
s. Surely it could be done inside JS? Or the previous step in Bash?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.
Could use https://www.npmjs.com/package/unzipper to do the unzipping in JavaScript? Converting the previous github script to bash looks more complicated to me (lots of gh cli response parsing π« ).