-
Notifications
You must be signed in to change notification settings - Fork 299
125 lines (107 loc) · 5.24 KB
/
Copy pathlast-reviewed-backfill.yml
File metadata and controls
125 lines (107 loc) · 5.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
name: Last Reviewed Date Backfill (One Time)
on:
workflow_dispatch:
inputs:
dry_run:
description: "Log actions only (no writes)"
type: boolean
default: true
permissions:
contents: read
pull-requests: read
repository-projects: write
jobs:
backfill:
runs-on: ubuntu-latest
steps:
- name: Backfill Last Reviewed Date
uses: actions/github-script@v6
with:
github-token: ${{ secrets.PROJECT_TOKEN }}
script: |
const dryRun = core.getInput('dry_run') === 'true';
const orgLogin = 'ArmDeveloperEcosystem';
const projectNumber = 4;
const ISO_CUTOFF = '2024-12-31';
const toDate = (iso) => new Date(iso + 'T00:00:00.000Z');
// 1) project
const proj = await github.graphql(
`query($org:String!,$num:Int!){ organization(login:$org){ projectV2(number:$num){ id } } }`,
{ org: orgLogin, num: projectNumber }
);
const projectId = proj.organization?.projectV2?.id;
if (!projectId) throw new Error('Project not found');
// 2) fields
const fields = (await github.graphql(
`query($id:ID!){ node(id:$id){ ... on ProjectV2 {
fields(first:50){ nodes{
__typename
... on ProjectV2Field{ id name dataType }
... on ProjectV2SingleSelectField{ id name options{ id name } }
} } } } }`, { id: projectId }
)).node.fields.nodes;
const dateFieldId = (n)=>fields.find(f=>f.__typename==='ProjectV2Field'&&f.name===n&&f.dataType==='DATE')?.id||null;
const statusField = fields.find(f=>f.__typename==='ProjectV2SingleSelectField' && f.name==='Status');
const statusFieldId = statusField?.id;
const publishId = dateFieldId('Publish Date');
const lrdId = dateFieldId('Last Reviewed Date');
if (!statusFieldId || !lrdId) throw new Error('Missing Status or Last Reviewed Date field');
// writers
const setDate = async (itemId, fieldId, iso) => {
if (dryRun) return console.log(`[DRY RUN] setDate item=${itemId} -> ${iso}`);
const m = `mutation($p:ID!,$i:ID!,$f:ID!,$d:Date!){
updateProjectV2ItemFieldValue(input:{projectId:$p,itemId:$i,fieldId:$f,value:{date:$d}}){
projectV2Item{ id }
}}`;
await github.graphql(m, { p: projectId, i: itemId, f: fieldId, d: iso });
};
// helpers
const getDate = (item,id)=>item.fieldValues.nodes.find(n=>n.__typename==='ProjectV2ItemFieldDateValue'&&n.field?.id===id)?.date||null;
const getStatus = (item)=>{ const n=item.fieldValues.nodes.find(n=>n.__typename==='ProjectV2ItemFieldSingleSelectValue'&&n.field?.id===statusFieldId); return n?.name||null; };
// iterate
async function* items(){ let cursor=null; for(;;){
const r=await github.graphql(
`query($org:String!,$num:Int!,$after:String){
organization(login:$org){ projectV2(number:$num){
items(first:100, after:$after){
nodes{
id
content{ __typename ... on PullRequest{ number repository{ name } } }
fieldValues(first:50){ nodes{
__typename
... on ProjectV2ItemFieldDateValue{ field{ ... on ProjectV2Field{ id name } } date }
... on ProjectV2ItemFieldSingleSelectValue{ field{ ... on ProjectV2SingleSelectField{ id name } } name optionId }
} }
}
pageInfo{ hasNextPage endCursor }
}
} } }`,
{ org: orgLogin, num: projectNumber, after: cursor }
);
const page=r.organization.projectV2.items;
for(const n of page.nodes) yield n;
if(!page.pageInfo.hasNextPage) break;
cursor=page.pageInfo.endCursor;
} }
let updates=0;
for await (const item of items()){
if (item.content?.__typename !== 'PullRequest') continue;
const status = getStatus(item);
if (status !== 'Done' && status !== 'Maintenance') continue;
const lrd = getDate(item, lrdId);
if (lrd) continue; // already has a value
if (status === 'Done') {
const publish = publishId ? getDate(item, publishId) : null;
if (publish) {
await setDate(item.id, lrdId, publish);
updates++; console.log(`[Backfill][Done] Set LRD=${publish}`);
} else {
console.log(`[Skip][Done] No Publish Date; not setting LRD`);
}
}
if (status === 'Maintenance') {
await setDate(item.id, lrdId, ISO_CUTOFF);
updates++; console.log(`[Backfill][Maintenance] Set LRD=${ISO_CUTOFF}`);
}
}
console.log(`Backfill complete. Items updated: ${updates}. Dry run: ${dryRun}`);