From 75890eac59a937352113bdb3ed882dae4402f0b0 Mon Sep 17 00:00:00 2001 From: Polina Semenova Date: Fri, 3 May 2024 16:16:49 +0200 Subject: [PATCH 1/2] add status_last_updated_handler --- src/modules/index.ts | 3 +- .../status_last_updated_handler/config.ts | 5 +++ .../status_last_updated_handler/index.ts | 43 +++++++++++++++++++ src/shared/graphql_queries.ts | 32 +++++++++++++- src/shared/project_ids.ts | 7 +++ src/webhooks.ts | 1 + 6 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 src/modules/status_last_updated_handler/config.ts create mode 100644 src/modules/status_last_updated_handler/index.ts diff --git a/src/modules/index.ts b/src/modules/index.ts index 2996942..8041310 100644 --- a/src/modules/index.ts +++ b/src/modules/index.ts @@ -1,4 +1,5 @@ export * from './sync_roadmap_ship_target_with_subtasks'; export * from './deploy_preview_label_handler'; export * from './deploy_notifications'; -export * from './engineering_projects_manager'; \ No newline at end of file +export * from './engineering_projects_manager'; +export * from './status_last_updated_handler'; \ No newline at end of file diff --git a/src/modules/status_last_updated_handler/config.ts b/src/modules/status_last_updated_handler/config.ts new file mode 100644 index 0000000..3f5a884 --- /dev/null +++ b/src/modules/status_last_updated_handler/config.ts @@ -0,0 +1,5 @@ +import {NEON_RELEASE_STATUS} from "../../shared/project_ids"; + +export const config = { + [NEON_RELEASE_STATUS.projectId]: NEON_RELEASE_STATUS.statusLastUpdatedFieldId, +} \ No newline at end of file diff --git a/src/modules/status_last_updated_handler/index.ts b/src/modules/status_last_updated_handler/index.ts new file mode 100644 index 0000000..cd92c8f --- /dev/null +++ b/src/modules/status_last_updated_handler/index.ts @@ -0,0 +1,43 @@ +import {Probot} from "probot"; +import {config} from "./config"; +import { + projectV2ItemStatusFieldValue, + setDateField +} from "../../shared/graphql_queries"; +import {logger} from "../../shared/logger"; +import {isDryRun} from "../../shared/utils"; + +export const status_last_updated_handler = (app: Probot) => { + app.on(["projects_v2_item.edited", "projects_v2_item.created"], async (context) => { + // we use this event instead issue.edited because in this event we will get the project_node_id + logger("info", "status_last_updated_handler fired with payload", context.payload) + if (!(Object.keys(config)).includes(context.payload.projects_v2_item.project_node_id)) { + logger("info", 'status_last_updated_handler skipped because not configured for the project') + return; + } + + try { + const projectsItem = await context.octokit.graphql( + projectV2ItemStatusFieldValue, + { + project_item_id: context.payload.projects_v2_item.node_id, + }); + const updatedAt = (projectsItem as any).node.fieldValueByName.updatedAt; + const params = { + project_id: context.payload.projects_v2_item.project_node_id, + project_item_id: context.payload.projects_v2_item.node_id, + date_field_id: config[context.payload.projects_v2_item.project_node_id], + value: updatedAt, + }; + logger("info", "Update project v2 item with", params); + if (!isDryRun()) { + const res = await context.octokit.graphql( + setDateField, + params); + logger("info", "Item updated with result", res); + } + } catch(e) { + logger("error", "Failed to update Status last updated field", e); + } + }); +} \ No newline at end of file diff --git a/src/shared/graphql_queries.ts b/src/shared/graphql_queries.ts index 2e03318..b3fb341 100644 --- a/src/shared/graphql_queries.ts +++ b/src/shared/graphql_queries.ts @@ -141,4 +141,34 @@ query($id: ID!){ } } } -` \ No newline at end of file +` + +export const projectV2ItemStatusFieldValue = ` +query ($project_item_id: ID!) { + node(id: $project_item_id) { + ... on ProjectV2Item { + id, + fieldValueByName(name: "Status") { + __typename, + ... on ProjectV2ItemFieldSingleSelectValue { + id, + name, + updatedAt, + } + } + } + } +}` + +export const setDateField = ` + mutation ($project_id: ID!, $project_item_id: ID!, $date_field_id: ID!, $value: Date!) { + updateProjectV2ItemFieldValue(input: { + projectId: $project_id, + itemId: $project_item_id, + fieldId: $date_field_id, + value: { date: $value } + }) { + projectV2Item { id } + } + } + ` \ No newline at end of file diff --git a/src/shared/project_ids.ts b/src/shared/project_ids.ts index d77bea3..136ed89 100644 --- a/src/shared/project_ids.ts +++ b/src/shared/project_ids.ts @@ -110,4 +110,11 @@ export const ALL_EPICS = { projectId: 'PVT_kwDOBKF3Cs4AUkqb', roadmapTargetShipQuarterFieldId: 'PVTF_lADOBKF3Cs4AUkqbzgNJOys', roadmapTargetShipMonthFieldId: 'PVTF_lADOBKF3Cs4AUkqbzgNJOyo', +} + +// project id: 79 +export const NEON_RELEASE_STATUS = { + projectId: 'PVT_kwDOBKF3Cs4AfDv2', + statusLastUpdatedFieldId: 'PVTF_lADOBKF3Cs4AfDv2zgZ0RRw', + statusFieldId: 'PVTSSF_lADOBKF3Cs4AfDv2zgUgpnk', } \ No newline at end of file diff --git a/src/webhooks.ts b/src/webhooks.ts index 38ec637..4300f3f 100644 --- a/src/webhooks.ts +++ b/src/webhooks.ts @@ -8,6 +8,7 @@ export = (app: Probot) => { l.engineering_projects_manager_listener(app); l.pull_request_label_change_listener(app); l.workflow_notifications_listener(app); + l.status_last_updated_handler(app); // // we can also: From 5270b1e214d66b1f7edf46a971c99a84ce552178 Mon Sep 17 00:00:00 2001 From: Polina Semenova Date: Fri, 3 May 2024 16:35:48 +0200 Subject: [PATCH 2/2] only update field if the status field was changed --- .../status_last_updated_handler/config.ts | 5 ++++- .../status_last_updated_handler/index.ts | 17 +++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/modules/status_last_updated_handler/config.ts b/src/modules/status_last_updated_handler/config.ts index 3f5a884..1f55f18 100644 --- a/src/modules/status_last_updated_handler/config.ts +++ b/src/modules/status_last_updated_handler/config.ts @@ -1,5 +1,8 @@ import {NEON_RELEASE_STATUS} from "../../shared/project_ids"; export const config = { - [NEON_RELEASE_STATUS.projectId]: NEON_RELEASE_STATUS.statusLastUpdatedFieldId, + [NEON_RELEASE_STATUS.projectId]: { + statusLastUpdatedFieldId: NEON_RELEASE_STATUS.statusLastUpdatedFieldId, + statusFieldId: NEON_RELEASE_STATUS.statusFieldId + }, } \ No newline at end of file diff --git a/src/modules/status_last_updated_handler/index.ts b/src/modules/status_last_updated_handler/index.ts index cd92c8f..ea74be6 100644 --- a/src/modules/status_last_updated_handler/index.ts +++ b/src/modules/status_last_updated_handler/index.ts @@ -10,12 +10,21 @@ import {isDryRun} from "../../shared/utils"; export const status_last_updated_handler = (app: Probot) => { app.on(["projects_v2_item.edited", "projects_v2_item.created"], async (context) => { // we use this event instead issue.edited because in this event we will get the project_node_id - logger("info", "status_last_updated_handler fired with payload", context.payload) - if (!(Object.keys(config)).includes(context.payload.projects_v2_item.project_node_id)) { + logger("info", "status_last_updated_handler fired with payload", context.payload); + const projectId = context.payload.projects_v2_item.project_node_id; + const statusFieldId = config[projectId].statusFieldId; + const lastUpdatedFieldId = config[projectId].statusLastUpdatedFieldId; + if (!(Object.keys(config)).includes(projectId) || !statusFieldId || !lastUpdatedFieldId) { logger("info", 'status_last_updated_handler skipped because not configured for the project') return; } + // @ts-ignore + if (context.payload.changes && context.payload.changes.fieldId !== statusFieldId) { + logger("info", 'status_last_updated_handler skipped because changes are not in status field') + return; + } + try { const projectsItem = await context.octokit.graphql( projectV2ItemStatusFieldValue, @@ -24,9 +33,9 @@ export const status_last_updated_handler = (app: Probot) => { }); const updatedAt = (projectsItem as any).node.fieldValueByName.updatedAt; const params = { - project_id: context.payload.projects_v2_item.project_node_id, + project_id: projectId, project_item_id: context.payload.projects_v2_item.node_id, - date_field_id: config[context.payload.projects_v2_item.project_node_id], + date_field_id: lastUpdatedFieldId, value: updatedAt, }; logger("info", "Update project v2 item with", params);