Skip to content

Commit 09235fd

Browse files
authored
chore: add addedon field automation in prioritization board (#33856)
### Issue # (if applicable) NA ### Reason for this change Currently in the Prioritization dasboard, we don't have a way to filter the PRs and Issues by date when it is added. ### Description of changes This PR enables automation for adding current date to the `AddedOn` column field in the Github Prioritization dasboard whenever new PR/Issues are being added to the dashboard. ### Describe any new or updated permissions being added NA ### Description of how you validated changes Tested in test dashboard. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent fb9fa74 commit 09235fd

9 files changed

+219
-7
lines changed

.github/workflows/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,8 @@ Owner: CDK Support team
128128

129129
[project-prioritization-needs-attention.yml](project-prioritization-needs-attention.yml): GitHub action that runs every day to update Needs Attention field in the prioritization project board.
130130
Owner: CDK Support team
131+
132+
### PR Prioritization AddedOn update
133+
134+
[project-prioritization-added-on.yml](project-prioritization-added-on.yml): GitHub action that runs every day to update AddedOn field in the prioritization project board.
135+
Owner: CDK Support team
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: PR Prioritization AddedOn update
2+
3+
on:
4+
schedule:
5+
- cron: '0 */6 * * 1-5' # Runs every 6 hours during weekdays
6+
workflow_dispatch: # Manual trigger
7+
8+
jobs:
9+
update_added_on:
10+
if: github.repository == 'aws/aws-cdk'
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
15+
- name: Update AddedOn field
16+
uses: actions/github-script@v7
17+
with:
18+
github-token: ${{ secrets.PROJEN_GITHUB_TOKEN }}
19+
script: |
20+
const script = require('./scripts/prioritization/update-added-on.js')
21+
await script({github})

scripts/prioritization/assign-bug-priority.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const { PRIORITIES, LABELS, STATUS, ...PROJECT_CONFIG } = require('./project-config');
22
const {
33
updateProjectField,
4+
updateProjectDateField,
45
addItemToProject,
56
fetchProjectFields,
67
fetchProjectItem,
@@ -74,7 +75,7 @@ module.exports = async ({ github, context }) => {
7475
(option) => option.name === STATUS.READY
7576
)?.id;
7677

77-
// Set both priority and Ready status for new items only
78+
// Set priority, Ready status and current date for new items
7879
await Promise.all([
7980
updateProjectField({
8081
github,
@@ -89,7 +90,14 @@ module.exports = async ({ github, context }) => {
8990
itemId: itemId,
9091
fieldId: PROJECT_CONFIG.statusFieldId,
9192
value: readyStatusId,
92-
})
93+
}),
94+
updateProjectDateField({
95+
github,
96+
projectId: PROJECT_CONFIG.projectId,
97+
itemId: itemId,
98+
fieldId: PROJECT_CONFIG.addedOnFieldId,
99+
date: new Date().toISOString(),
100+
})
93101
]);
94102
}
95103
}

scripts/prioritization/assign-priority.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
const { PRIORITIES, LABELS, STATUS, ...PROJECT_CONFIG } = require('./project-config');
1111
const {
1212
updateProjectField,
13+
updateProjectDateField,
1314
addItemToProject,
1415
fetchProjectFields,
1516
fetchProjectItem,
@@ -129,7 +130,7 @@ module.exports = async ({ github, context }) => {
129130
(option) => option.name === STATUS.READY
130131
)?.id;
131132

132-
// Set both priority and Ready status for new items
133+
// Set priority, Ready status and current date for new items
133134
await Promise.all([
134135
updateProjectField({
135136
github,
@@ -144,6 +145,13 @@ module.exports = async ({ github, context }) => {
144145
itemId: itemId,
145146
fieldId: PROJECT_CONFIG.statusFieldId,
146147
value: readyStatusId,
148+
}),
149+
updateProjectDateField({
150+
github,
151+
projectId: PROJECT_CONFIG.projectId,
152+
itemId: itemId,
153+
fieldId: PROJECT_CONFIG.addedOnFieldId,
154+
date: new Date().toISOString(),
147155
})
148156
]);
149157
}

scripts/prioritization/assign-r2-priority.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const { PRIORITIES, LABELS, STATUS, ...PROJECT_CONFIG } = require("./project-con
99

1010
const {
1111
updateProjectField,
12+
updateProjectDateField,
1213
addItemToProject,
1314
fetchProjectFields,
1415
fetchOpenPullRequests,
@@ -126,7 +127,7 @@ module.exports = async ({ github }) => {
126127
});
127128
itemId = addResult.addProjectV2ItemById.item.id;
128129

129-
// Set both priority and initial status for new items
130+
// Set priority, Ready status and current date for new items
130131
await Promise.all([
131132
updateProjectField({
132133
github,
@@ -141,6 +142,13 @@ module.exports = async ({ github }) => {
141142
itemId: itemId,
142143
fieldId: PROJECT_CONFIG.statusFieldId,
143144
value: readyStatusId,
145+
}),
146+
updateProjectDateField({
147+
github,
148+
projectId: PROJECT_CONFIG.projectId,
149+
itemId: itemId,
150+
fieldId: PROJECT_CONFIG.addedOnFieldId,
151+
date: new Date().toISOString(),
144152
})
145153
]);
146154
}

scripts/prioritization/assign-r5-priority.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const { PRIORITIES, LABELS, STATUS, DAYS_THRESHOLD, ...PROJECT_CONFIG } = requir
1010

1111
const {
1212
updateProjectField,
13+
updateProjectDateField,
1314
addItemToProject,
1415
fetchProjectFields,
1516
fetchOpenPullRequests,
@@ -120,7 +121,7 @@ module.exports = async ({ github }) => {
120121
contentId: pr.id,
121122
});
122123

123-
// Set initial priority and status
124+
// Set priority, Ready status and current date for new items
124125
await Promise.all([
125126
updateProjectField({
126127
github,
@@ -135,6 +136,13 @@ module.exports = async ({ github }) => {
135136
itemId: addResult.addProjectV2ItemById.item.id,
136137
fieldId: PROJECT_CONFIG.statusFieldId,
137138
value: readyStatusId,
139+
}),
140+
updateProjectDateField({
141+
github,
142+
projectId: PROJECT_CONFIG.projectId,
143+
itemId: itemId,
144+
fieldId: PROJECT_CONFIG.addedOnFieldId,
145+
date: new Date().toISOString(),
138146
})
139147
]);
140148
} catch (error) {

scripts/prioritization/project-api.js

+60-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,45 @@ const updateProjectField = async ({
3535
}
3636
);
3737
};
38-
38+
39+
/**
40+
* Updates a date field value for an item in a GitHub Project.
41+
* @param {Object} params - The parameters for updating the project field
42+
* @param {Object} params.github - The GitHub API client
43+
* @param {string} params.projectId - The ID of the project
44+
* @param {string} params.itemId - The ID of the item to update
45+
* @param {string} params.fieldId - The ID of the field to update
46+
* @param {string} params.date - The date string in ISO format
47+
* @returns {Promise<Object>} The GraphQL mutation response
48+
*/
49+
const updateProjectDateField = async ({
50+
github,
51+
projectId,
52+
itemId,
53+
fieldId,
54+
date,
55+
}) => {
56+
return github.graphql(
57+
`
58+
mutation($input: UpdateProjectV2ItemFieldValueInput!) {
59+
updateProjectV2ItemFieldValue(input: $input) {
60+
projectV2Item {
61+
id
62+
}
63+
}
64+
}
65+
`,
66+
{
67+
input: {
68+
projectId,
69+
itemId,
70+
fieldId,
71+
value: { date },
72+
},
73+
}
74+
);
75+
};
76+
3977
/**
4078
* Adds an item (PR) to a GitHub Project.
4179
* @param {Object} params - The parameters for adding an item to the project
@@ -233,6 +271,18 @@ const updateProjectField = async ({
233271
items(first: 100, after: $cursor) {
234272
nodes {
235273
id
274+
createdAt
275+
type
276+
content {
277+
... on Issue {
278+
id
279+
number
280+
}
281+
... on PullRequest {
282+
id
283+
number
284+
}
285+
}
236286
fieldValues(first: 20) {
237287
nodes {
238288
... on ProjectV2ItemFieldSingleSelectValue {
@@ -244,6 +294,14 @@ const updateProjectField = async ({
244294
}
245295
updatedAt
246296
}
297+
... on ProjectV2ItemFieldDateValue {
298+
date
299+
field {
300+
... on ProjectV2Field {
301+
name
302+
}
303+
}
304+
}
247305
}
248306
}
249307
}
@@ -261,6 +319,7 @@ const updateProjectField = async ({
261319

262320
module.exports = {
263321
updateProjectField,
322+
updateProjectDateField,
264323
addItemToProject,
265324
fetchProjectFields,
266325
fetchOpenPullRequests,

scripts/prioritization/project-config.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const NEEDS_ATTENTION_STATUS = {
4545

4646
/**
4747
* Project configuration for GitHub project automation.
48-
* Note: For projectId, priorityFieldId, statusFieldId, and attentionFieldId,
48+
* Note: For projectId, priorityFieldId, statusFieldId, attentionFieldId and addedOnFieldId,
4949
* refer to Setup section in README.md on how to retrieve these values using GraphQL query.
5050
* These IDs need to be updated only when project fields are modified.
5151
*/
@@ -57,6 +57,7 @@ module.exports = {
5757
priorityFieldId: 'PVTSSF_lADOACIPmc4Av_32zgmVmPs',
5858
statusFieldId: 'PVTSSF_lADOACIPmc4Av_32zgmVmF8',
5959
attentionFieldId: 'PVTSSF_lADOACIPmc4Av_32zgmZDdo',
60+
addedOnFieldId: 'PVTF_lADOACIPmc4Av_32zgqbglg',
6061
LABELS,
6162
PRIORITIES,
6263
STATUS,
+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/**
2+
* Updates the "Added On" date for project items that have empty "Added On" field
3+
* by using the project item's createdAt timestamp from GitHub API.
4+
* This handles items that were added to the board manually.
5+
*/
6+
7+
const { ...PROJECT_CONFIG } = require('./project-config');
8+
const {
9+
fetchProjectItems,
10+
updateProjectDateField,
11+
} = require('./project-api');
12+
13+
module.exports = async ({ github }) => {
14+
// Get today's date at start of day (UTC)
15+
const today = new Date();
16+
today.setUTCHours(0, 0, 0, 0);
17+
18+
try {
19+
let allItems = [];
20+
let hasNextPage = true;
21+
let cursor = null;
22+
23+
// Fetch project items with pagination
24+
while (hasNextPage) {
25+
const result = await fetchProjectItems({
26+
github,
27+
org: PROJECT_CONFIG.org,
28+
number: PROJECT_CONFIG.projectNumber,
29+
cursor,
30+
});
31+
32+
const items = result.organization.projectV2.items;
33+
34+
// Filter items created today
35+
const todayItems = items.nodes.filter(item => {
36+
const itemDate = new Date(item.createdAt);
37+
return itemDate >= today;
38+
});
39+
40+
if (todayItems.length > 0) {
41+
allItems = allItems.concat(todayItems);
42+
}
43+
44+
hasNextPage = items.pageInfo.hasNextPage;
45+
cursor = items.pageInfo.endCursor;
46+
}
47+
48+
console.log(`Processing ${allItems.length} items created today for AddedOn dates`);
49+
50+
// Process each item
51+
for (const item of allItems) {
52+
const itemType = item.type;
53+
const itemNumber = item.content?.number;
54+
55+
try {
56+
// Find the AddedOn field value
57+
const addedOnField = item.fieldValues.nodes.find(
58+
(field) => field.field?.name === 'AddedOn'
59+
);
60+
61+
// If AddedOn is empty
62+
if (!addedOnField || !addedOnField.date) {
63+
console.log(`Processing ${itemType} #${itemNumber} - Adding missing AddedOn date`);
64+
65+
await updateProjectDateField({
66+
github,
67+
projectId: PROJECT_CONFIG.projectId,
68+
itemId: item.id,
69+
fieldId: PROJECT_CONFIG.addedOnFieldId,
70+
date: item.createdAt,
71+
});
72+
73+
console.log(`Updated AddedOn date for ${itemType} #${itemNumber} with creation date ${item.createdAt}`);
74+
} else {
75+
console.log(`Skipping ${itemType} #${itemNumber} - AddedOn date already set`);
76+
}
77+
} catch (error) {
78+
console.error(`Error processing ${itemType} #${itemNumber}:`, error.message);
79+
continue;
80+
}
81+
}
82+
83+
if (allItems.length === 0) {
84+
console.log('No items found that were created today');
85+
} else {
86+
console.log(`Successfully processed ${allItems.length} items`);
87+
}
88+
89+
console.log('Completed processing today\'s items for AddedOn dates');
90+
} catch (error) {
91+
console.error('Error updating AddedOn dates:', error.message);
92+
throw error;
93+
}
94+
};

0 commit comments

Comments
 (0)