From 8fee0d8bfef9d1c24dc1f981170bf3b206899b2c Mon Sep 17 00:00:00 2001 From: Ohad Schneider Date: Sun, 19 Nov 2023 17:56:28 +0200 Subject: [PATCH 1/2] Edit existing initiative (#28) * edit existing initiative * minor refactor calculate markdown json in warnAndCommentAsync * node script test - take from env vars * add update-initiative explanation comment * fix findIndex testing function --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- .../generatePullRequestForNewInitiative.js | 66 ++++++++++++++----- scripts/gptGenerateJsonFromIssue.py | 7 +- ...est_generatePullRequestForNewInitiative.js | 8 +-- 3 files changed, 60 insertions(+), 21 deletions(-) diff --git a/scripts/generatePullRequestForNewInitiative.js b/scripts/generatePullRequestForNewInitiative.js index c4b8dd3f..c95503cb 100644 --- a/scripts/generatePullRequestForNewInitiative.js +++ b/scripts/generatePullRequestForNewInitiative.js @@ -66,7 +66,9 @@ module.exports = async ({github, context}) => { await createCommentAsync(`**WARNING**: ${warning} Automatic PR will NOT be generated -${json} +\`\`\`json +${JSON.stringify(json, null, 2)} +\`\`\` See GitHub Action logs for more details: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`); } @@ -164,9 +166,10 @@ The value of property \`${prop}\` (\`${value}\`) is already present in \`${linkJ \`\`\`json ${linksJsonString} \`\`\` -**If this is a mistake and it doesn't already exist:** edit the issue's title so that it starts with **\`[NEW-INITIATIVE-FORCE-PR]:\`**`, +**If this is a mistake and it doesn't already exist:** edit the issue's title so that it starts with **\`[FORCE-PR-NEW-INITIATIVE]:\`** +**If you wish to update an existing initiative:** edit the issue's title so that it starts with **\`[UPDATE-INITIATIVE]:\`**`, "Suspected existing initiative", - markdownNewInitiativeJson) + newInitiativeJson) return true; } } @@ -175,6 +178,26 @@ ${linksJsonString} return false; } + async function updateExistingInitiativeAsync(categoryJson, newInitiativeJson) { + const initiativeName = newInitiativeJson.name; + + if (!(initiativeName?.trim())) { + await warnAndCommentAsync("For update, you must provide a name that matches the name of an existing initiative", "no initiative name provided", newInitiativeJson); + return false; + } + + const existingCategoryIndex = categoryJson.links.findIndex((link => + link.name?.localeCompare(initiativeName, undefined, { sensitivity: 'accent' }) === 0 + )) + if (existingCategoryIndex === -1) { + await warnAndCommentAsync(`Could not find existing initiative '${initiativeName}' in category '${category}'`, "initiative not found", newInitiativeJson); + return false; + } + + categoryJson.links[existingCategoryIndex] = newInitiativeJson; + return true; + } + const tempFolder = process.env.TEMP || "/tmp"; const gptResponse = await fs.readFile(tempFolder + "/gpt-auto-comment.output", "utf8"); @@ -199,30 +222,43 @@ ${linksJsonString} return await warnAndCommentAsync("Could not process GPT response as JSON", e, jsonString); } - const markdownNewInitiativeJson = "```json\n" + JSON.stringify(newInitiativeJson, null, 2) + "\n```"; + // saving the category before we delete it from the object + category = newInitiativeJson.category + removeRedundantInitiativeJsonProperties(newInitiativeJson); + + const issueTitleUpper = process.env.ISSUE_TITLE.toLocaleUpperCase("en-us"); + const forceNewInitiative = issueTitleUpper.startsWith("[FORCE-PR-NEW-INITIATIVE]:"); + const updateInitiative = issueTitleUpper.startsWith("[UPDATE-INITIATIVE]:"); + + if (forceNewInitiative) { + console.warn("FORCE-PR requested: skipping existing initiative validation"); + } + else if (!updateInitiative && await detectExistingInitiativeAsync(newInitiativeJson)) { + return; + } let categoryLinksJsonFile; try { - categoryLinksJsonFile = `${process.env.GITHUB_WORKSPACE}/_data/links/${newInitiativeJson.category}/links.json`; + categoryLinksJsonFile = `${process.env.GITHUB_WORKSPACE}/_data/links/${category}/links.json`; console.log("resolved category links file: " + categoryLinksJsonFile); const categoryJsonString = await fs.readFile(categoryLinksJsonFile, "utf8"); categoryJson = JSON.parse(categoryJsonString); } catch (e) { - return await warnAndCommentAsync("Could not process category links JSON", e, markdownNewInitiativeJson); + return await warnAndCommentAsync("Could not process category links JSON", e, newInitiativeJson); } - removeRedundantInitiativeJsonProperties(newInitiativeJson); - - if (process.env.ISSUE_TITLE.toLocaleUpperCase("en-us").startsWith("[NEW-INITIATIVE-FORCE-PR]:")) { - console.warn("FORCE-PR requested: skipping existing initiative validation"); + if (updateInitiative) { + const edited = await updateExistingInitiativeAsync(categoryJson, newInitiativeJson, newInitiativeJson) + if (!edited) { + return; + } } - else if (await detectExistingInitiativeAsync(newInitiativeJson)) { - return; + else { + categoryJson.links.push(newInitiativeJson); } - categoryJson.links.push(newInitiativeJson); await fs.writeFile(categoryLinksJsonFile, JSON.stringify(categoryJson, null, 2), "utf8"); const branch = `auto-pr-${context.issue.number}`; @@ -230,7 +266,7 @@ ${linksJsonString} pushPrBranch(branch, categoryLinksJsonFile, newInitiativeJson.name); } catch (e) { - return await warnAndCommentAsync("encountered error during git execution", e, markdownNewInitiativeJson); + return await warnAndCommentAsync("encountered error during git execution", e, newInitiativeJson); } let pr; @@ -238,7 +274,7 @@ ${linksJsonString} pr = await createOrUpdatePullRequestAsync(branch, newInitiativeJson.name || "???"); } catch (e) { - return await warnAndCommentAsync("Could not create pull request", e, markdownNewInitiativeJson); + return await warnAndCommentAsync("Could not create pull request", e, newInitiativeJson); } console.log("resolved PR: " + JSON.stringify(pr)) diff --git a/scripts/gptGenerateJsonFromIssue.py b/scripts/gptGenerateJsonFromIssue.py index d99d8d0b..8e489616 100644 --- a/scripts/gptGenerateJsonFromIssue.py +++ b/scripts/gptGenerateJsonFromIssue.py @@ -1,5 +1,6 @@ import logging import os +import re import openai import yaml @@ -107,10 +108,12 @@ def ask_gpt_for_initiative_json(self, issue_body: str) -> str: logging.warn("GPT did not infer function calling, best-effort answer parsing will be performed") return response_message["content"] -def get_new_initiative_details() -> str: +def get_new_initiative_details() -> str: + prefixPattern = r'^\[.*-INITIATIVE\]:\s*' + initiative_details = f""" ### Initiative Display Name - {os.environ["ISSUE_TITLE"].replace("[NEW-INITIATIVE]:", "").replace("[NEW-INITIATIVE-FORCE-PR]:", "")} + {re.sub(prefixPattern, "", os.environ["ISSUE_TITLE"], flags=re.IGNORECASE)} {os.environ["ISSUE_BODY"]} """ diff --git a/scripts/test_generatePullRequestForNewInitiative.js b/scripts/test_generatePullRequestForNewInitiative.js index e41f8f97..2df01656 100644 --- a/scripts/test_generatePullRequestForNewInitiative.js +++ b/scripts/test_generatePullRequestForNewInitiative.js @@ -1,12 +1,12 @@ const context = { serverUrl: "https://github.com", - runId: 6762019754, + runId: process.env.GITHUB_RUN_ID, repo: { - owner: "ohadschn", - repo: "ConnectPortal" + owner: process.env.GITHUB_OWNER, + repo: process.env.GITHHUB_REPO }, issue: { - number: 10 + number: process.env.GITHUB_ISSUE_NUMBER } } From 51b16f1ee0ce756fdb7bf35c759d5a558d9f455f Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 19 Nov 2023 16:07:40 +0000 Subject: [PATCH 2/2] NewDealBabysitter --- _data/links/Children/Main/links.json | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/_data/links/Children/Main/links.json b/_data/links/Children/Main/links.json index f5b33bf5..f67e6db1 100644 --- a/_data/links/Children/Main/links.json +++ b/_data/links/Children/Main/links.json @@ -57,23 +57,16 @@ "website": "https://il.brainpop.com/" }, { - "displayName": "מערך בייביסיטר ארצי", + "displayName": "נסיון עריכה", "name": "NewDealBabysitter", - "shortDescription": "מערך בייביסיטר ארצי", - "description": "זקוקים/ות לבייביסיטר בזמן המלחמה? 'חוזה חדש' פה בשבילכם! משפחות רבות מוצאות עצמן במצב קשה בו אחד או יותר מהורי המשפחה אינו בבית, והמשפחה זקוקה לעזרה עם הילדים. לצורך כך הקמנו מערך ארצי של שמרטפים ושמרטפיות (הצטרפות מגיל 18). מוזמנים להצטרף לאחת מהקבוצות האזוריות, בה יבוצע חיבור בין משפחות הזקוקת לעזרה לבין המתנדבים שלנו.", - "initiativeValidationDetails": "Known organization from before the war", - "url": "https://www.new-deal.org.il/babysitter", - "website": "https://www.new-deal.org.il/babysitter", - "whatsapp": "https://chat.whatsapp.com/E7POYA8pBlu1C1EZy1fDLq", - "docs": "https://www.hopp.bio/new-deal", - "initiativeImage": "https://scontent.ftlv6-1.fna.fbcdn.net/v/t39.30808-6/307851307_420511490189366_1794830304047005228_n.png?_nc_cat=109&ccb=1-7&_nc_sid=5f2048&_nc_ohc=wuiPNY9ShrMAX8tE1tR&_nc_ht=scontent.ftlv6-1.fna&oh=00_AfBe0c3Ywgl9gSTeoSmWSjtCyX51nr97EMMExVLbo_z28Q&oe=65547942", + "shortDescription": "EditableFoo test2", + "description": "EditableFoo full test", + "initiativeValidationDetails": "source: trust me bro", + "url": "https://exampl.ecom", "tags": [ - "חוזה חדש", - "בייביסיטר", - "שמרטף", - "מלחמה", - "משפחה", - "ילדים" + "נסיון", + "עריכה", + "ביביסיטר" ] } ]