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..1f55f18 --- /dev/null +++ b/src/modules/status_last_updated_handler/config.ts @@ -0,0 +1,8 @@ +import {NEON_RELEASE_STATUS} from "../../shared/project_ids"; + +export const config = { + [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 new file mode 100644 index 0000000..ea74be6 --- /dev/null +++ b/src/modules/status_last_updated_handler/index.ts @@ -0,0 +1,52 @@ +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); + 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, + { + project_item_id: context.payload.projects_v2_item.node_id, + }); + const updatedAt = (projectsItem as any).node.fieldValueByName.updatedAt; + const params = { + project_id: projectId, + project_item_id: context.payload.projects_v2_item.node_id, + date_field_id: lastUpdatedFieldId, + 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: