-
Notifications
You must be signed in to change notification settings - Fork 4k
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
chore: add project prioritization automation actions #33050
Merged
+1,612
−0
Merged
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
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,22 @@ | ||
name: PR Prioritization | ||
on: | ||
pull_request_target: | ||
types: | ||
- labeled | ||
- opened | ||
- reopened | ||
- synchronize | ||
- ready_for_review | ||
|
||
jobs: | ||
prioritize: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Add PR to Project & Set Priority | ||
uses: actions/github-script@v7 | ||
with: | ||
github-token: ${{ secrets.PROJEN_GITHUB_TOKEN }} | ||
script: | | ||
const script = require('./scripts/prioritization/assign-priority.js') | ||
await script({github, context}) |
19 changes: 19 additions & 0 deletions
19
.github/workflows/project-prioritization-r2-assignment.yml
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,19 @@ | ||
name: PR Prioritization R2 Check | ||
on: | ||
schedule: | ||
- cron: '0 */6 * * 1-5' # Runs every 6 hours during weekdays | ||
workflow_dispatch: # Manual trigger | ||
|
||
jobs: | ||
update_project_status: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- name: Check and assign R2 Priority to PRs | ||
uses: actions/github-script@v7 | ||
with: | ||
github-token: ${{ secrets.PROJEN_GITHUB_TOKEN }} | ||
script: | | ||
const script = require('./scripts/prioritization/assign-r2-priority.js') | ||
await script({github}) |
18 changes: 18 additions & 0 deletions
18
.github/workflows/project-prioritization-r5-assignment.yml
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,18 @@ | ||
name: PR Prioritization R5 Check | ||
on: | ||
schedule: | ||
- cron: '0 6 * * 1-5' # Runs at 6AM every day during weekdays | ||
workflow_dispatch: # Manual trigger | ||
|
||
jobs: | ||
update_project_status: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Check and Assign R5 Priority to PRs | ||
uses: actions/github-script@v7 | ||
with: | ||
github-token: ${{ secrets.PROJEN_GITHUB_TOKEN }} | ||
script: | | ||
const script = require('./scripts/prioritization/assign-r5-priority.js') | ||
await script({github}) |
237 changes: 237 additions & 0 deletions
237
scripts/@aws-cdk/script-tests/prioritization/assign-priority.test.js
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,237 @@ | ||
const { PRIORITIES, LABELS, STATUS, ...PROJECT_CONFIG} = require('../../../../scripts/prioritization/project-config'); | ||
const { | ||
createMockPR, | ||
createMockGithub, | ||
OPTION_IDS | ||
} = require('./helpers/mock-data'); | ||
|
||
const assignPriority = require('../../../../scripts/prioritization/assign-priority'); | ||
|
||
|
||
describe('Priority Assignment (R1, R3, R4)', () => { | ||
let mockGithub; | ||
let mockContext; | ||
|
||
beforeEach(() => { | ||
mockGithub = createMockGithub(); | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
async function verifyProjectState(expectedPriority, expectedStatus) { | ||
const calls = mockGithub.graphql.mock.calls; | ||
|
||
if (!expectedPriority) { | ||
const priorityUpdateCall = calls.find(call => | ||
call[1].input?.fieldId === PROJECT_CONFIG.priorityFieldId | ||
); | ||
expect(priorityUpdateCall).toBeUndefined(); | ||
return; | ||
} | ||
|
||
const priorityUpdateCall = calls.find(call => | ||
call[1].input?.fieldId === PROJECT_CONFIG.priorityFieldId | ||
); | ||
const statusUpdateCall = calls.find(call => | ||
call[1].input?.fieldId === PROJECT_CONFIG.statusFieldId | ||
); | ||
|
||
// Verify priority was set correctly | ||
expect(priorityUpdateCall[1].input.value.singleSelectOptionId) | ||
.toBe(OPTION_IDS[expectedPriority]); | ||
|
||
// Verify status was set to Ready | ||
expect(statusUpdateCall[1].input.value.singleSelectOptionId) | ||
.toBe(OPTION_IDS[expectedStatus]); | ||
} | ||
|
||
describe('R1 Priority Tests', () => { | ||
test('should assign R1 and Ready status to non-draft PR with contribution/core label', async () => { | ||
const pr = createMockPR({ | ||
draft: false, | ||
labels: [LABELS.CORE] | ||
}); | ||
|
||
mockContext = { payload: { pull_request: pr } }; | ||
|
||
await assignPriority({ github: mockGithub, context: mockContext }); | ||
await verifyProjectState(PRIORITIES.R1, STATUS.READY); | ||
}); | ||
|
||
test('should assign R1 and Ready status to non-draft PR with contribution/core and needs-maintainer-review labels', async () => { | ||
const pr = createMockPR({ | ||
draft: false, | ||
labels: [LABELS.CORE, LABELS.MAINTAINER_REVIEW] | ||
}); | ||
|
||
mockContext = { payload: { pull_request: pr } }; | ||
|
||
await assignPriority({ github: mockGithub, context: mockContext }); | ||
await verifyProjectState(PRIORITIES.R1, STATUS.READY); | ||
}); | ||
|
||
test('should not add draft PR with contribution/core label to project', async () => { | ||
const pr = createMockPR({ | ||
draft: true, | ||
labels: [LABELS.CORE] | ||
}); | ||
|
||
mockContext = { payload: { pull_request: pr } }; | ||
|
||
await assignPriority({ github: mockGithub, context: mockContext }); | ||
await verifyProjectState(null); | ||
}); | ||
}); | ||
|
||
describe('R3 Priority Tests', () => { | ||
test('should assign R3 and Ready status to non-draft PR with needs-maintainer-review label', async () => { | ||
const pr = createMockPR({ | ||
draft: false, | ||
labels: [LABELS.MAINTAINER_REVIEW] | ||
}); | ||
|
||
mockContext = { payload: { pull_request: pr } }; | ||
|
||
await assignPriority({ github: mockGithub, context: mockContext }); | ||
await verifyProjectState(PRIORITIES.R3, STATUS.READY); | ||
}); | ||
|
||
test('should not assign R3 to draft PR with needs-maintainer-review label', async () => { | ||
const pr = createMockPR({ | ||
draft: true, | ||
labels: [LABELS.MAINTAINER_REVIEW] | ||
}); | ||
|
||
mockContext = { payload: { pull_request: pr } }; | ||
|
||
await assignPriority({ github: mockGithub, context: mockContext }); | ||
await verifyProjectState(null); | ||
}); | ||
}); | ||
|
||
describe('R4 Priority Tests', () => { | ||
test('should assign R4 and Ready status to PR with pr/reviewer-clarification-requested and needs-community-review labels', async () => { | ||
const pr = createMockPR({ | ||
draft: true, | ||
labels: [ | ||
LABELS.CLARIFICATION_REQUESTED, | ||
LABELS.COMMUNITY_REVIEW | ||
] | ||
}); | ||
|
||
mockContext = { payload: { pull_request: pr } }; | ||
|
||
await assignPriority({ github: mockGithub, context: mockContext }); | ||
await verifyProjectState(PRIORITIES.R4, STATUS.READY); | ||
}); | ||
|
||
test('should assign R4 and Ready status to PR with pr-linter/exemption-requested and needs-community-review labels', async () => { | ||
const pr = createMockPR({ | ||
draft: true, | ||
labels: [ | ||
LABELS.EXEMPTION_REQUESTED, | ||
LABELS.COMMUNITY_REVIEW | ||
] | ||
}); | ||
|
||
mockContext = { payload: { pull_request: pr } }; | ||
|
||
await assignPriority({ github: mockGithub, context: mockContext }); | ||
await verifyProjectState(PRIORITIES.R4, STATUS.READY); | ||
}); | ||
|
||
test('should assign R4 and Ready status to PR with pr/reviewer-clarification-requested and needs-maintainer-review labels', async () => { | ||
const pr = createMockPR({ | ||
draft: true, | ||
labels: [ | ||
LABELS.CLARIFICATION_REQUESTED, | ||
LABELS.MAINTAINER_REVIEW | ||
] | ||
}); | ||
|
||
mockContext = { payload: { pull_request: pr } }; | ||
|
||
await assignPriority({ github: mockGithub, context: mockContext }); | ||
await verifyProjectState(PRIORITIES.R4, STATUS.READY); | ||
}); | ||
|
||
test('should assign R4 and Ready status to PR with pr-linter/exemption-requested and needs-maintainer-review labels', async () => { | ||
const pr = createMockPR({ | ||
labels: [ | ||
LABELS.EXEMPTION_REQUESTED, | ||
LABELS.MAINTAINER_REVIEW | ||
] | ||
}); | ||
|
||
mockContext = { payload: { pull_request: pr } }; | ||
|
||
await assignPriority({ github: mockGithub, context: mockContext }); | ||
await verifyProjectState(PRIORITIES.R4, STATUS.READY); | ||
}); | ||
|
||
test('should assign R4 and Ready status to PR with pr/reviewer-clarification-requested label and no review labels', async () => { | ||
const pr = createMockPR({ | ||
labels: [LABELS.CLARIFICATION_REQUESTED] | ||
}); | ||
|
||
mockContext = { payload: { pull_request: pr } }; | ||
|
||
await assignPriority({ github: mockGithub, context: mockContext }); | ||
await verifyProjectState(PRIORITIES.R4, STATUS.READY); | ||
}); | ||
|
||
test('should assign R4 and Ready status to PR with pr-linter/exemption-requested label and no review labels', async () => { | ||
const pr = createMockPR({ | ||
draft: true, | ||
labels: [LABELS.EXEMPTION_REQUESTED] | ||
}); | ||
|
||
mockContext = { payload: { pull_request: pr } }; | ||
|
||
await assignPriority({ github: mockGithub, context: mockContext }); | ||
await verifyProjectState(PRIORITIES.R4, STATUS.READY); | ||
}); | ||
}); | ||
|
||
describe('Priority Precedence Tests', () => { | ||
test('should assign R1 over R3 when PR has both contribution/core and needs-maintainer-review labels', async () => { | ||
const pr = createMockPR({ | ||
draft: false, | ||
labels: [ | ||
LABELS.CORE, | ||
LABELS.MAINTAINER_REVIEW | ||
] | ||
}); | ||
|
||
mockContext = { payload: { pull_request: pr } }; | ||
|
||
await assignPriority({ github: mockGithub, context: mockContext }); | ||
await verifyProjectState(PRIORITIES.R1, STATUS.READY); | ||
}); | ||
|
||
test('should assign R1 over R4 when PR has both contribution/core and pr/reviewer-clarification-requested labels', async () => { | ||
const pr = createMockPR({ | ||
draft: false, | ||
labels: [ | ||
LABELS.CORE, | ||
LABELS.CLARIFICATION_REQUESTED | ||
] | ||
}); | ||
|
||
mockContext = { payload: { pull_request: pr } }; | ||
await assignPriority({ github: mockGithub, context: mockContext }); | ||
await verifyProjectState(PRIORITIES.R1, STATUS.READY); | ||
}); | ||
|
||
test('should not assign any priority when no matching labels', async () => { | ||
const pr = createMockPR({ | ||
draft: false, | ||
labels: [] | ||
}); | ||
|
||
mockContext = { payload: { pull_request: pr } }; | ||
|
||
await assignPriority({ github: mockGithub, context: mockContext }); | ||
await verifyProjectState(null); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.
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 the change made from the previous PR that was reverted due to issue when running the github actions on forked PR's. This change will run in the context of base repository which will have access to github token whereas
pull_request
will run in the context of the forked repo branch and doesn't have access to the github token which was the reason for the invalid token error.