-
Notifications
You must be signed in to change notification settings - Fork 225
Implementation of project board automations #3375
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
Merged
Merged
Changes from 26 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 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
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,38 @@ | ||
# 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 | ||
run: | | ||
echo "$EVENT_PAYLOAD" > event.json | ||
pnpm issues --event_name ${{ github.event_name }} --event_action ${{ github.event.action }} | ||
rm event.json | ||
env: | ||
EVENT_PAYLOAD: ${{ toJson(github.event) }}M | ||
working-directory: automations/js |
This file was deleted.
Oops, something went wrong.
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,78 @@ | ||
# Runs all automations related to PR events. | ||
# | ||
# See `issue_automations_init.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 files, loads the env vars and runs the automation script. | ||
|
||
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@v6 | ||
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: Perform PR automations | ||
run: | | ||
unzip event_info.zip | ||
source event_info.env | ||
pnpm prs --event_name "$EVENT_NAME" --event_action "$EVENT_ACTION" | ||
rm event_info.env | ||
rm event.json | ||
env: | ||
EVENT_PAYLOAD: ${{ toJson(github.event) }} | ||
working-directory: automations/js |
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,54 @@ | ||
# Initialises all automations related to PR events. | ||
# | ||
# See `issue_automations_init.yml` for the corresponding implementation for | ||
# issues. | ||
dhruvkb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# | ||
# 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 payload to a JSON file and the event name and action to | ||
# an environment file. | ||
# 3. It uploads the JSON file and the environment files as artifacts. | ||
# | ||
# continued in `pr_automations.yml`... | ||
|
||
name: PR automations init | ||
|
||
on: | ||
pull_request_target: | ||
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: | | ||
mkdir -p ./pr | ||
echo "$EVENT_PAYLOAD" > ./pr/event.json | ||
echo "export EVENT_NAME=$EVENT_NAME" > ./pr/event_info.env | ||
echo "export EVENT_ACTION=$EVENT_ACTION" >> ./pr/event_info.env | ||
env: | ||
EVENT_PAYLOAD: ${{ toJson(github.event) }} | ||
EVENT_NAME: ${{ github.event_name }} | ||
EVENT_ACTION: ${{ github.event.action }} | ||
|
||
- name: Upload event info as artifact | ||
uses: actions/upload-artifact@v3 | ||
with: | ||
name: event_info | ||
path: pr/ |
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,2 @@ | ||
# Event data payload used by project automations | ||
event.json |
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
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
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
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
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,77 @@ | ||
/** | ||
* This module handles all events related to issues. | ||
* | ||
* Invoke it from the CLI with | ||
* - the event name as the `--event_name` argument | ||
* - the event action as the `--event_action` argument | ||
* - the event payload in the `event.json` file in the project root | ||
*/ | ||
|
||
import { getBoard } from '../utils/projects.mjs' | ||
import { getEvent } from '../utils/event.mjs' | ||
|
||
const { eventAction, eventPayload } = getEvent() | ||
|
||
if ( | ||
eventPayload.issue.labels.some((label) => label.name === 'π§ project: thread') | ||
) | ||
// Do not add project threads to the Backlog board. | ||
process.exit(0) | ||
|
||
const backlogBoard = await getBoard('Backlog') | ||
const columns = backlogBoard.columns // computed property | ||
|
||
// Create new, or get the existing, card for the current issue. | ||
const card = await backlogBoard.addCard(eventPayload.issue.node_id) | ||
|
||
/** | ||
* Set the "Priority" custom field based on the issue's labels. | ||
*/ | ||
const syncPriority = async () => { | ||
const priority = eventPayload.issue.labels.find((label) => | ||
label.name.includes('priority') | ||
)?.name | ||
if (priority) | ||
await backlogBoard.setCustomChoiceField(card.id, 'Priority', priority) | ||
if (priority === 'π₯ priority: critical') | ||
await backlogBoard.moveCard(card.id, columns.ToDo) | ||
} | ||
|
||
switch (eventAction) { | ||
case 'opened': | ||
case 'reopened': | ||
if ( | ||
eventPayload.issue.labels.some( | ||
(label) => label.name === 'β status: blocked' | ||
) | ||
) | ||
await backlogBoard.moveCard(card.id, columns.Blocked) | ||
else await backlogBoard.moveCard(card.id, columns.Backlog) | ||
|
||
await syncPriority() | ||
break | ||
|
||
case 'closed': | ||
if (eventPayload.issue.state_reason === 'completed') | ||
await backlogBoard.moveCard(card.id, columns.Done) | ||
else await backlogBoard.moveCard(card.id, columns.Discarded) | ||
break | ||
|
||
case 'assigned': | ||
if (card.status === columns.Backlog) | ||
await backlogBoard.moveCard(card.id, columns.ToDo) | ||
break | ||
|
||
case 'labeled': | ||
if (eventPayload.label.name === 'β status: blocked') | ||
await backlogBoard.moveCard(card.id, columns.Blocked) | ||
await syncPriority() | ||
break | ||
|
||
case 'unlabeled': | ||
if (eventPayload.label.name === 'β status: blocked') | ||
// TODO: Move back to the column it came from. | ||
await backlogBoard.moveCard(card.id, columns.Backlog) | ||
await syncPriority() | ||
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.
Uh oh!
There was an error while loading. Please reload this page.