Skip to content

Project dates from status #48

Project dates from status

Project dates from status #48

Workflow file for this run

name: Project dates from status
on:
schedule:
- cron: '*/20 * * * *'
workflow_dispatch: {}
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
with:
github-token: ${{ secrets.GH_PROJECTS_PAT }}
script: |
const STATUS_IN_PROGRESS = 'In Progress';
const STATUS_DONE = 'Done';
const PROJECTS = [
{
number: 9,
projectId: 'PVT_kwDOCA2kqc4BUnfM',
statusFieldId: 'PVTSSF_lADOCA2kqc4BUnfMzhBucOc',
startDateFieldId: 'PVTF_lADOCA2kqc4BUnfMzhBuedg',
endDateFieldId: 'PVTF_lADOCA2kqc4BUnfMzhRbXSE',
},
{
number: 11,
projectId: 'PVT_kwDOCA2kqc4BV4Gu',
statusFieldId: 'PVTSSF_lADOCA2kqc4BV4GuzhRQrS8',
startDateFieldId: 'PVTF_lADOCA2kqc4BV4GuzhRQrT0',
endDateFieldId: 'PVTF_lADOCA2kqc4BV4GuzhRlSCM',
},
];
const today = new Date().toISOString().slice(0, 10);
async function listItems(projectId) {
const items = [];
let cursor = null;
while (true) {
const { node } = await github.graphql(
`query ($projectId: ID!, $cursor: String) {
node(id: $projectId) {
... on ProjectV2 {
items(first: 100, after: $cursor) {
pageInfo { hasNextPage endCursor }
nodes {
id
isArchived
fieldValues(first: 50) {
nodes {
... on ProjectV2ItemFieldSingleSelectValue {
name
field { ... on ProjectV2FieldCommon { id } }
}
... on ProjectV2ItemFieldDateValue {
date
field { ... on ProjectV2FieldCommon { id } }
}
}
}
}
}
}
}
}`,
{ projectId, cursor }
);
const page = node?.items;
if (!page) break;
items.push(...page.nodes);
if (!page.pageInfo.hasNextPage) break;
cursor = page.pageInfo.endCursor;
}
return items;
}
async function setDate(projectId, itemId, fieldId, value) {
await github.graphql(
`mutation ($projectId: ID!, $itemId: ID!, $fieldId: ID!, $value: Date!) {
updateProjectV2ItemFieldValue(
input: {
projectId: $projectId
itemId: $itemId
fieldId: $fieldId
value: { date: $value }
}
) { projectV2Item { id } }
}`,
{ projectId, itemId, fieldId, value }
);
}
let totalUpdates = 0;
for (const cfg of PROJECTS) {
const items = await listItems(cfg.projectId);
core.info(`project=${cfg.number} items=${items.length}`);
let updates = 0;
for (const it of items) {
if (it.isArchived) continue;
const fvs = it.fieldValues?.nodes ?? [];
const status = fvs.find((n) => n.field?.id === cfg.statusFieldId)?.name ?? null;
const startDate = fvs.find((n) => n.field?.id === cfg.startDateFieldId)?.date ?? null;
const endDate = fvs.find((n) => n.field?.id === cfg.endDateFieldId)?.date ?? null;
if (status === STATUS_IN_PROGRESS && !startDate) {
await setDate(cfg.projectId, it.id, cfg.startDateFieldId, today);
core.info(`project=${cfg.number} item=${it.id} set start_date=${today}`);
updates++;
}
if (status === STATUS_DONE && !endDate) {
await setDate(cfg.projectId, it.id, cfg.endDateFieldId, today);
core.info(`project=${cfg.number} item=${it.id} set end_date=${today}`);
updates++;
}
}
core.info(`project=${cfg.number} updates=${updates}`);
totalUpdates += updates;
}
core.info(`done updates=${totalUpdates}`);