From dd51b46d541a7879d98fefa0c97378626cf34ad6 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Tue, 24 Dec 2024 22:25:06 +0100 Subject: [PATCH 01/30] ci: updating the ssh-action version --- .github/workflows/deploy-chatbot.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 11389e0..3ae5be5 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -32,6 +32,7 @@ jobs: if [[ "$COMMENT_BODY" =~ --project[[:space:]]+\"([^\"]+)\" ]]; then PROJECT="${BASH_REMATCH[1]}" echo "Project: $PROJECT" + # TODO: else stopping the workflow if no env present fi # Parse infra @@ -45,6 +46,10 @@ jobs: echo "project=$PROJECT" >> $GITHUB_OUTPUT echo "infra=$INFRA" >> $GITHUB_OUTPUT + # TODO: from here, isolate them in independent workflows + # and just call them depending on the input by having just + # a simple and unique trigger deployment + # Step 2: Validate and Trigger Deploy Workflow - name: Trigger Deployment Workflow if: steps.parse_command.outputs.environment != '' && steps.parse_command.outputs.project != '' @@ -67,7 +72,7 @@ jobs: # Step 3: Deploy Infra (if requested) - name: Deploy Infra if: steps.parse_command.outputs.infra != '' - uses: appleboy/ssh-action@v0.1.5 + uses: appleboy/ssh-action@v1.2.0 with: host: ${{ secrets.SSH_HOST }} username: ${{ secrets.SSH_USERNAME }} @@ -101,7 +106,7 @@ jobs: const project = `${{ steps.parse_command.outputs.project }}`; const infra = `${{ steps.parse_command.outputs.infra }}`; const prNumber = context.payload.issue.number; - + let message = "🚀 Deployment triggered:\n"; if (project) { message += `- Project: \`${project}\`\n`; From 4f5edb62b0d804f892a6c9fb6b5a33117d0372c0 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Tue, 24 Dec 2024 22:39:35 +0100 Subject: [PATCH 02/30] ci: debugging the step 1 of the parse command on step 2 --- .github/workflows/deploy-chatbot.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 3ae5be5..67c83b2 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -52,7 +52,6 @@ jobs: # Step 2: Validate and Trigger Deploy Workflow - name: Trigger Deployment Workflow - if: steps.parse_command.outputs.environment != '' && steps.parse_command.outputs.project != '' uses: actions/github-script@v6 with: script: | From f6783c21eeade0202afe204d7d9addd39989ddb8 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Tue, 24 Dec 2024 22:49:26 +0100 Subject: [PATCH 03/30] ci(fix): should correctly capture both the --environment and --project arguments when the command is provided --- .github/workflows/deploy-chatbot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 67c83b2..491a350 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -29,7 +29,7 @@ jobs: fi # Parse project - if [[ "$COMMENT_BODY" =~ --project[[:space:]]+\"([^\"]+)\" ]]; then + if [[ "$COMMENT_BODY" =~ --project[[:space:]]+([a-zA-Z0-9_-]+) ]]; then PROJECT="${BASH_REMATCH[1]}" echo "Project: $PROJECT" # TODO: else stopping the workflow if no env present From 13d8308b8c6bac9b2746db67dfd445c7b71d2325 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Wed, 25 Dec 2024 13:23:59 +0100 Subject: [PATCH 04/30] ci(local): Adding configuration for ACT to locally run the GH actions --- .actrc | 2 + .github/workflows/deploy-chatbot.yml | 81 +++++++++++++++++----------- .gitignore | 2 + 3 files changed, 53 insertions(+), 32 deletions(-) create mode 100644 .actrc diff --git a/.actrc b/.actrc new file mode 100644 index 0000000..f6ed481 --- /dev/null +++ b/.actrc @@ -0,0 +1,2 @@ +--action-offline-mode + diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 491a350..4d8358f 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -1,22 +1,29 @@ -name: Handle PRE env deployment commands in PR Comments +name: Handle deployment commands in PR Comments on: issue_comment: types: - created +permissions: + actions: write + jobs: handle-slash-command: runs-on: ubuntu-latest steps: - # Step 1: Parse Deployment Command - name: Parse Deployment Command id: parse_command run: | COMMENT_BODY="${{ github.event.comment.body }}" + if [[ "$env.ACT" ]]; then + echo "Setting the command as a mock since it's running locally with ACT" + COMMENT_BODY='/deploy --environment pre --project ag-summoners-sync' + fi + echo "Comment received: $COMMENT_BODY" - + # Initialize variables ENVIRONMENT="" PROJECT="" @@ -46,6 +53,42 @@ jobs: echo "project=$PROJECT" >> $GITHUB_OUTPUT echo "infra=$INFRA" >> $GITHUB_OUTPUT + - name: Notify the user + uses: actions/github-script@v6 + with: + script: | + const environment = `${{ steps.parse_command.outputs.environment }}`; + console.log(`ENVIRONMENT: ${environment}`); + const project = `${{ steps.parse_command.outputs.project }}`; + const infra = `${{ steps.parse_command.outputs.infra }}`; + + let message = "🚀 Deployment action received:\n"; + if (project) { + message += `- Project: \`${project}\`\n`; + } + if (environment) { + message += `- Environment: \`${environment}\`\n`; + } + if (infra) { + message += `- Infrastructure: \`${infra}\`\n`; + } + + if (${{ env.ACT }}) { + console.log(`Action is being runned locally by 'ACT'. + Skipping the notify user on PR, but output would have been: + ${message}`); + return; + } + + const prNumber = context.payload.issue.number; + + github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: message, + }); + # TODO: from here, isolate them in independent workflows # and just call them depending on the input by having just # a simple and unique trigger deployment @@ -53,13 +96,15 @@ jobs: # Step 2: Validate and Trigger Deploy Workflow - name: Trigger Deployment Workflow uses: actions/github-script@v6 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: script: | const environment = `${{ steps.parse_command.outputs.environment }}`; const project = `${{ steps.parse_command.outputs.project }}`; const workflowId = `deploy-${environment}.yml`; - console.log(`Triggering workflow: ${workflowId} for project: ${project}`); + console.log(`🚀 Triggering workflow: ${workflowId} for project: ${project}`); github.rest.actions.createWorkflowDispatch({ owner: 'zerodaycode', @@ -96,31 +141,3 @@ jobs: ;; esac - # Step 4: Post Confirmation Comment - - name: Post Comment to PR - uses: actions/github-script@v6 - with: - script: | - const environment = `${{ steps.parse_command.outputs.environment }}`; - const project = `${{ steps.parse_command.outputs.project }}`; - const infra = `${{ steps.parse_command.outputs.infra }}`; - const prNumber = context.payload.issue.number; - - let message = "🚀 Deployment triggered:\n"; - if (project) { - message += `- Project: \`${project}\`\n`; - } - if (environment) { - message += `- Environment: \`${environment}\`\n`; - } - if (infra) { - message += `- Infrastructure: \`${infra}\`\n`; - } - - github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - body: message, - }); - diff --git a/.gitignore b/.gitignore index ddf87e0..2751a9c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ +.secrets + .nvim/ .idea/ From 3acc8187aa0ce943e37096e04c62d3f250a1e63e Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Wed, 25 Dec 2024 13:27:29 +0100 Subject: [PATCH 05/30] ci(local): Adding configuration for ACT to locally run the GH actions --- .github/workflows/deploy-chatbot.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 4d8358f..a833338 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -73,7 +73,9 @@ jobs: message += `- Infrastructure: \`${infra}\`\n`; } - if (${{ env.ACT }}) { + let localRun = ${{ env.ACT }} || false + + if (localRun) { console.log(`Action is being runned locally by 'ACT'. Skipping the notify user on PR, but output would have been: ${message}`); From dc99172f3a03914ecb299e505575df04fd768370 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Wed, 25 Dec 2024 13:28:47 +0100 Subject: [PATCH 06/30] ci: raising the github script version to 7 --- .github/workflows/deploy-chatbot.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index a833338..7d199c7 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -54,7 +54,7 @@ jobs: echo "infra=$INFRA" >> $GITHUB_OUTPUT - name: Notify the user - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const environment = `${{ steps.parse_command.outputs.environment }}`; @@ -97,7 +97,7 @@ jobs: # Step 2: Validate and Trigger Deploy Workflow - name: Trigger Deployment Workflow - uses: actions/github-script@v6 + uses: actions/github-script@v7 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: From ca75432cb85f04d6d320f5206c510bf31c8da808 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Wed, 25 Dec 2024 13:46:04 +0100 Subject: [PATCH 07/30] fix: wrong JS syntax for checking a non present env var on the cloud runners --- .github/workflows/deploy-chatbot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 7d199c7..99e3997 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -73,7 +73,7 @@ jobs: message += `- Infrastructure: \`${infra}\`\n`; } - let localRun = ${{ env.ACT }} || false + const localRun = `${{ env.ACT }}` === "true"; if (localRun) { console.log(`Action is being runned locally by 'ACT'. From d487c8f69269cef3f2f5303737ac79f9c07962ec Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Wed, 25 Dec 2024 13:58:05 +0100 Subject: [PATCH 08/30] chore(ci): avoiding to override the GITHUB_TOKEN var --- .github/workflows/deploy-chatbot.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 99e3997..42dbce7 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -98,8 +98,6 @@ jobs: # Step 2: Validate and Trigger Deploy Workflow - name: Trigger Deployment Workflow uses: actions/github-script@v7 - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: script: | const environment = `${{ steps.parse_command.outputs.environment }}`; From f957c65b998fb401899b8c96eeaf89d18d3312d3 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Wed, 25 Dec 2024 14:09:07 +0100 Subject: [PATCH 09/30] chore(ci): removing manually set permissions --- .github/workflows/deploy-chatbot.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 42dbce7..cf67e13 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -5,9 +5,6 @@ on: types: - created -permissions: - actions: write - jobs: handle-slash-command: runs-on: ubuntu-latest From b83cd3c8711056994fa4be6de84f6939e4c7ebce Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Wed, 25 Dec 2024 17:31:33 +0100 Subject: [PATCH 10/30] ci: getting org oauth from the zdc's app --- .actrc | 3 +-- .github/workflows/deploy-chatbot.yml | 15 ++++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.actrc b/.actrc index f6ed481..c36d7de 100644 --- a/.actrc +++ b/.actrc @@ -1,2 +1 @@ ---action-offline-mode - +--action-offline-mode \ No newline at end of file diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index cf67e13..32c0ba5 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -6,7 +6,7 @@ on: - created jobs: - handle-slash-command: + handle-deployment-on-pr-comment: runs-on: ubuntu-latest steps: @@ -50,12 +50,19 @@ jobs: echo "project=$PROJECT" >> $GITHUB_OUTPUT echo "infra=$INFRA" >> $GITHUB_OUTPUT + - name: Get GH Zero Day Code APP token + uses: actions/create-github-app-token@v1 + id: zdc-app-token + with: + app-id: ${{ vars.ZDC_AUTH_APP_ID }} + private-key: ${{ secrets.ZDC_AUTH_PRIVATE_KEY }} + owner: ${{ github.repository_owner }} + - name: Notify the user uses: actions/github-script@v7 with: script: | const environment = `${{ steps.parse_command.outputs.environment }}`; - console.log(`ENVIRONMENT: ${environment}`); const project = `${{ steps.parse_command.outputs.project }}`; const infra = `${{ steps.parse_command.outputs.infra }}`; @@ -92,7 +99,6 @@ jobs: # and just call them depending on the input by having just # a simple and unique trigger deployment - # Step 2: Validate and Trigger Deploy Workflow - name: Trigger Deployment Workflow uses: actions/github-script@v7 with: @@ -104,13 +110,12 @@ jobs: console.log(`🚀 Triggering workflow: ${workflowId} for project: ${project}`); github.rest.actions.createWorkflowDispatch({ - owner: 'zerodaycode', + owner: context.repo.owner, repo: project, workflow_id: workflowId, ref: 'main', // TODO: Change branch to ref }); - # Step 3: Deploy Infra (if requested) - name: Deploy Infra if: steps.parse_command.outputs.infra != '' uses: appleboy/ssh-action@v1.2.0 From 75180265f76f8712a0c4284c1d9adddc657e272f Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Wed, 25 Dec 2024 18:17:49 +0100 Subject: [PATCH 11/30] ci: adding the new JWT token form the auth app to the run workflow on other repo step --- .github/workflows/deploy-chatbot.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 32c0ba5..80a39c8 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -11,6 +11,7 @@ jobs: steps: - name: Parse Deployment Command + if: ${{ !env.ACT }} id: parse_command run: | COMMENT_BODY="${{ github.event.comment.body }}" @@ -52,7 +53,7 @@ jobs: - name: Get GH Zero Day Code APP token uses: actions/create-github-app-token@v1 - id: zdc-app-token + id: zdc-auth-app-token with: app-id: ${{ vars.ZDC_AUTH_APP_ID }} private-key: ${{ secrets.ZDC_AUTH_PRIVATE_KEY }} @@ -102,6 +103,7 @@ jobs: - name: Trigger Deployment Workflow uses: actions/github-script@v7 with: + github-token: ${{ steps.zdc-auth-app-token.outputs.token }} script: | const environment = `${{ steps.parse_command.outputs.environment }}`; const project = `${{ steps.parse_command.outputs.project }}`; From 3f985a16c74efc2b7525bd88fe45c25f2d032520 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Wed, 25 Dec 2024 21:51:49 +0100 Subject: [PATCH 12/30] ci: better configuration for using the ZDC Auth Oauth app in the cloud or PATs on local envs --- .github/workflows/deploy-chatbot.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 80a39c8..8a16114 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -11,7 +11,6 @@ jobs: steps: - name: Parse Deployment Command - if: ${{ !env.ACT }} id: parse_command run: | COMMENT_BODY="${{ github.event.comment.body }}" @@ -37,7 +36,9 @@ jobs: if [[ "$COMMENT_BODY" =~ --project[[:space:]]+([a-zA-Z0-9_-]+) ]]; then PROJECT="${BASH_REMATCH[1]}" echo "Project: $PROJECT" - # TODO: else stopping the workflow if no env present + else + echo "No environment specified. Aborting workflow." + exit 1 # Aborts the workflow # TODO: pass it as an output to the user notifier step fi # Parse infra @@ -52,6 +53,7 @@ jobs: echo "infra=$INFRA" >> $GITHUB_OUTPUT - name: Get GH Zero Day Code APP token + if: ${{ !env.ACT }} uses: actions/create-github-app-token@v1 id: zdc-auth-app-token with: @@ -67,7 +69,10 @@ jobs: const project = `${{ steps.parse_command.outputs.project }}`; const infra = `${{ steps.parse_command.outputs.infra }}`; - let message = "🚀 Deployment action received:\n"; + const actor = `${{ github.event.comment.user.login }}`; + const username = (actor !== "") ? actor : 'Unknown'; + + let message = `🚀 Deployment action request received from user: ${username}\n`; if (project) { message += `- Project: \`${project}\`\n`; } @@ -103,19 +108,17 @@ jobs: - name: Trigger Deployment Workflow uses: actions/github-script@v7 with: - github-token: ${{ steps.zdc-auth-app-token.outputs.token }} + github-token: ${{ steps.zdc-auth-app-token.outputs.token || github.token }} script: | const environment = `${{ steps.parse_command.outputs.environment }}`; const project = `${{ steps.parse_command.outputs.project }}`; const workflowId = `deploy-${environment}.yml`; - console.log(`🚀 Triggering workflow: ${workflowId} for project: ${project}`); - github.rest.actions.createWorkflowDispatch({ owner: context.repo.owner, repo: project, workflow_id: workflowId, - ref: 'main', // TODO: Change branch to ref + ref: 'main', // TODO: Change branch to ref if pre, otherwise PRO should be only on main }); - name: Deploy Infra From e963d011dfe00d9960ad1e7f97d4102905474109 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Thu, 26 Dec 2024 17:43:28 +0100 Subject: [PATCH 13/30] ci: updating the message with the workflow status after being triggered --- .actrc | 3 +- .github/workflows/deploy-chatbot.yml | 93 ++++++++++++++----- .../workflows/mock_payloads/deploy_act.json | 18 ++++ 3 files changed, 92 insertions(+), 22 deletions(-) create mode 100644 .github/workflows/mock_payloads/deploy_act.json diff --git a/.actrc b/.actrc index c36d7de..e83d2f2 100644 --- a/.actrc +++ b/.actrc @@ -1 +1,2 @@ ---action-offline-mode \ No newline at end of file +--action-offline-mode +-e .github/workflows/mock_payloads/deploy_act.json \ No newline at end of file diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 8a16114..145843d 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -13,8 +13,9 @@ jobs: - name: Parse Deployment Command id: parse_command run: | + WORKFLOW_LOCAL_RUN="${{ !github.event.act }}" COMMENT_BODY="${{ github.event.comment.body }}" - if [[ "$env.ACT" ]]; then + if [[ WORKFLOW_LOCAL_RUN ]]; then echo "Setting the command as a mock since it's running locally with ACT" COMMENT_BODY='/deploy --environment pre --project ag-summoners-sync' fi @@ -53,7 +54,7 @@ jobs: echo "infra=$INFRA" >> $GITHUB_OUTPUT - name: Get GH Zero Day Code APP token - if: ${{ !env.ACT }} + if: ${{ !github.event.act }} uses: actions/create-github-app-token@v1 id: zdc-auth-app-token with: @@ -63,6 +64,7 @@ jobs: - name: Notify the user uses: actions/github-script@v7 + id: notify_user with: script: | const environment = `${{ steps.parse_command.outputs.environment }}`; @@ -72,6 +74,8 @@ jobs: const actor = `${{ github.event.comment.user.login }}`; const username = (actor !== "") ? actor : 'Unknown'; + const prNumber = context.payload.issue.number; + let message = `🚀 Deployment action request received from user: ${username}\n`; if (project) { message += `- Project: \`${project}\`\n`; @@ -83,30 +87,29 @@ jobs: message += `- Infrastructure: \`${infra}\`\n`; } - const localRun = `${{ env.ACT }}` === "true"; - - if (localRun) { + if (${{ github.event.act }}) { console.log(`Action is being runned locally by 'ACT'. Skipping the notify user on PR, but output would have been: ${message}`); - return; + return { comment_id: 10 } // arbitraty mocked comment number; + } else { + github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: message, + }); + console.log(`Comment REST returned data: ${JSON.stringify(comment, null, 2)}`); + return { "comment_id": comment.data.id }; } - const prNumber = context.payload.issue.number; - - github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - body: message, - }); - # TODO: from here, isolate them in independent workflows # and just call them depending on the input by having just # a simple and unique trigger deployment - name: Trigger Deployment Workflow uses: actions/github-script@v7 + id: trigger_deployment_workflow with: github-token: ${{ steps.zdc-auth-app-token.outputs.token || github.token }} script: | @@ -114,12 +117,30 @@ jobs: const project = `${{ steps.parse_command.outputs.project }}`; const workflowId = `deploy-${environment}.yml`; - github.rest.actions.createWorkflowDispatch({ - owner: context.repo.owner, - repo: project, - workflow_id: workflowId, - ref: 'main', // TODO: Change branch to ref if pre, otherwise PRO should be only on main - }); + let result = ""; + let details = ""; + + try { + await github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: project, + workflow_id: workflowId, + ref: 'main', // TODO: Change branch to ref if pre, otherwise PRO should be only on main + }); + status = 'OK'; + details = 'succedeed'; + } catch (ex) { + console.log(`FAILED TO TRIGGER WORKFLOW:\n${ex}`); + status = 'ERR'; + details = `Failed to trigger the workflow ${workflowId} on repo: ${project}`; + } + + // Return triggered details + return { + workflow_name: workflowId, + status: status, + details: details, + }; - name: Deploy Infra if: steps.parse_command.outputs.infra != '' @@ -148,3 +169,33 @@ jobs: ;; esac + - name: Update Deployment Status + uses: actions/github-script@v7 + id: update-comment-with-deployment-status + with: + script: | + const workflowLocalRun = ${{ github.event.act }}; + + const commentOnPr = `${{ steps.notify_user.outputs.result }}`; + const commentId = JSON.parse(commentOnPr).comment_id; + console.log(`Updating comment with id ${commentId} for workflow status`); + + const workflowDispatchResult = `${{ steps.trigger_deployment_workflow.outputs.result }}`; + console.log(`Trigger deployment status: ${workflowDispatchResult}`); + const workflowDetails = JSON.parse(workflowDispatchResult); + + const runUrl = ""; // TODO: empty for now + + const statusIcon = workflowDetails.status === 'OK' ? '✅' : '❌'; + const statusMsg = workflowDetails.details; + const message = `${statusIcon} Deployment ${statusMsg}. [View Workflow](${runUrl})`; + console.log(message); + + if (!workflowLocalRun) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: commentId, + body: message, + }); + } diff --git a/.github/workflows/mock_payloads/deploy_act.json b/.github/workflows/mock_payloads/deploy_act.json new file mode 100644 index 0000000..3c3da08 --- /dev/null +++ b/.github/workflows/mock_payloads/deploy_act.json @@ -0,0 +1,18 @@ +{ + "act": true, + "comment": { + "body": "/deploy --environment pre --project ag-summoners-sync", + "user": { + "login": "TheRustifyer" + } + }, + "issue": { + "number": 4 + }, + "repository": { + "name": "app-summoners-sync", + "owner": { + "login": "zerodaycode" + } + } + } \ No newline at end of file From 9618e307867340ea4ad517fd54be8435e7f2479e Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Thu, 26 Dec 2024 18:17:01 +0100 Subject: [PATCH 14/30] fix: missing 'truthy' boolean comparisons on empty substitutions --force --- .github/workflows/deploy-chatbot.yml | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 145843d..a9ef2a7 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -87,20 +87,25 @@ jobs: message += `- Infrastructure: \`${infra}\`\n`; } - if (${{ github.event.act }}) { + if (`${{ github.event.act }}` === 'true') { console.log(`Action is being runned locally by 'ACT'. Skipping the notify user on PR, but output would have been: ${message}`); return { comment_id: 10 } // arbitraty mocked comment number; } else { - github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - body: message, - }); - console.log(`Comment REST returned data: ${JSON.stringify(comment, null, 2)}`); - return { "comment_id": comment.data.id }; + let comment = {}; + try { + comment = await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: message, + }); + return { "comment_id": comment.data.id }; + } catch (ex) { + console.log("Failed to POST the comment on the PR to notify the user due to =[> " + ex + "]"); + return { "comment_id": null }; + } } # TODO: from here, isolate them in independent workflows @@ -174,7 +179,7 @@ jobs: id: update-comment-with-deployment-status with: script: | - const workflowLocalRun = ${{ github.event.act }}; + const workflowLocalRun = `${{ github.event.act }}` === 'true'; const commentOnPr = `${{ steps.notify_user.outputs.result }}`; const commentId = JSON.parse(commentOnPr).comment_id; From b4be2ef2c4d54cfa72feaff85d9d418e8a977f06 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Thu, 26 Dec 2024 18:34:34 +0100 Subject: [PATCH 15/30] feat: Introducing a new step on the action to retrieve the running workflows on the target project --- .github/workflows/deploy-chatbot.yml | 77 ++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 20 deletions(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index a9ef2a7..8201ae6 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -11,7 +11,7 @@ jobs: steps: - name: Parse Deployment Command - id: parse_command + id: parse-command run: | WORKFLOW_LOCAL_RUN="${{ !github.event.act }}" COMMENT_BODY="${{ github.event.comment.body }}" @@ -64,12 +64,12 @@ jobs: - name: Notify the user uses: actions/github-script@v7 - id: notify_user + id: notify-user with: script: | - const environment = `${{ steps.parse_command.outputs.environment }}`; - const project = `${{ steps.parse_command.outputs.project }}`; - const infra = `${{ steps.parse_command.outputs.infra }}`; + const environment = `${{ steps.parse-command.outputs.environment }}`; + const project = `${{ steps.parse-command.outputs.project }}`; + const infra = `${{ steps.parse-command.outputs.infra }}`; const actor = `${{ github.event.comment.user.login }}`; const username = (actor !== "") ? actor : 'Unknown'; @@ -91,7 +91,7 @@ jobs: console.log(`Action is being runned locally by 'ACT'. Skipping the notify user on PR, but output would have been: ${message}`); - return { comment_id: 10 } // arbitraty mocked comment number; + return { comment_id: 10, message: message } // arbitraty mocked comment number; } else { let comment = {}; try { @@ -101,7 +101,7 @@ jobs: issue_number: prNumber, body: message, }); - return { "comment_id": comment.data.id }; + return { comment_id: comment.data.id, message: message }; } catch (ex) { console.log("Failed to POST the comment on the PR to notify the user due to =[> " + ex + "]"); return { "comment_id": null }; @@ -114,12 +114,12 @@ jobs: - name: Trigger Deployment Workflow uses: actions/github-script@v7 - id: trigger_deployment_workflow + id: trigger-deployment-workflow with: github-token: ${{ steps.zdc-auth-app-token.outputs.token || github.token }} script: | - const environment = `${{ steps.parse_command.outputs.environment }}`; - const project = `${{ steps.parse_command.outputs.project }}`; + const environment = `${{ steps.parse-command.outputs.environment }}`; + const project = `${{ steps.parse-command.outputs.project }}`; const workflowId = `deploy-${environment}.yml`; let result = ""; @@ -142,20 +142,20 @@ jobs: // Return triggered details return { - workflow_name: workflowId, + workflowId: workflowId, status: status, details: details, }; - name: Deploy Infra - if: steps.parse_command.outputs.infra != '' + if: steps.parse-command.outputs.infra != '' uses: appleboy/ssh-action@v1.2.0 with: host: ${{ secrets.SSH_HOST }} username: ${{ secrets.SSH_USERNAME }} key: ${{ secrets.SSH_KEY }} script: | - case "${{ steps.parse_command.outputs.infra }}" in + case "${{ steps.parse-command.outputs.infra }}" in postgres) echo "Deploying Postgres..." docker run -d --name postgres --restart always -e POSTGRES_PASSWORD=mysecretpassword postgres @@ -170,7 +170,7 @@ jobs: docker run -d --name redis --restart always redis ;; *) - echo "Unknown infra: ${{ steps.parse_command.outputs.infra }}" + echo "Unknown infra: ${{ steps.parse-command.outputs.infra }}" ;; esac @@ -181,19 +181,20 @@ jobs: script: | const workflowLocalRun = `${{ github.event.act }}` === 'true'; - const commentOnPr = `${{ steps.notify_user.outputs.result }}`; - const commentId = JSON.parse(commentOnPr).comment_id; + const commentOnPr = ${{ steps.notify-user.outputs.result }}; + const commentId = commentOnPr.comment_id; console.log(`Updating comment with id ${commentId} for workflow status`); - const workflowDispatchResult = `${{ steps.trigger_deployment_workflow.outputs.result }}`; - console.log(`Trigger deployment status: ${workflowDispatchResult}`); - const workflowDetails = JSON.parse(workflowDispatchResult); + const workflowDetails = ${{ steps.trigger-deployment-workflow.outputs.result }}; + console.log(`Trigger deployment status: ${JSON.stringify(workflowDetails, null, 2)}`); const runUrl = ""; // TODO: empty for now const statusIcon = workflowDetails.status === 'OK' ? '✅' : '❌'; const statusMsg = workflowDetails.details; - const message = `${statusIcon} Deployment ${statusMsg}. [View Workflow](${runUrl})`; + + const previousMsgData = commentOnPr.message; + const message = `${previousMsgData}\n${statusIcon} Deployment ${statusMsg}. [View Workflow](${runUrl})`; console.log(message); if (!workflowLocalRun) { @@ -204,3 +205,39 @@ jobs: body: message, }); } + + - name: Wait for Deployment + id: wait-for-deployment + uses: actions/github-script@v7 + with: + script: | + const project = `${{ steps.trigger-deployment-workflow.outputs.project }}`; + const workflowName = `${{ steps.trigger-deployment-workflow.outputs.workflowId }}`; + const pollInterval = 10 * 1000; // 10 seconds + + console.log(`Polling for workflow status: ${workflowName} in ${project}`); + + let status = 'in_progress'; + let conclusion = ''; + while (status === 'in_progress') { + const runs = await github.rest.actions.listWorkflowRuns({ + owner: context.repo.owner, + repo: project, + workflow_id: workflowName, + branch: 'main', + status: 'in_progress', + }); + + if (runs.data.workflow_runs.length > 0) { + const run = runs.data.workflow_runs[0]; // TODO: not really take the first one, should be fix later + status = run.status; + conclusion = run.conclusion; + + if (status === 'completed') { + console.log(`Workflow completed with status: ${conclusion}`); + return { status: conclusion, run_url: run.html_url }; + } + } + + await new Promise(resolve => setTimeout(resolve, pollInterval)); + } From 273e419a9ba65685257d0ef21630703ba5ca32fb Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Thu, 26 Dec 2024 20:43:09 +0100 Subject: [PATCH 16/30] feat(ci): completed the basic approach to launch a deploy on an artifact on other project/repo --- .github/workflows/deploy-chatbot.yml | 40 +++------------------------- 1 file changed, 3 insertions(+), 37 deletions(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 8201ae6..4feaf07 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -188,7 +188,9 @@ jobs: const workflowDetails = ${{ steps.trigger-deployment-workflow.outputs.result }}; console.log(`Trigger deployment status: ${JSON.stringify(workflowDetails, null, 2)}`); - const runUrl = ""; // TODO: empty for now + const owner = `${{ github.event.repository.owner.login }}`; + const project = `${{ github.event.repository.name }}`; + const runUrl = `https://github.com/${owner}/${project}/actions`; const statusIcon = workflowDetails.status === 'OK' ? '✅' : '❌'; const statusMsg = workflowDetails.details; @@ -205,39 +207,3 @@ jobs: body: message, }); } - - - name: Wait for Deployment - id: wait-for-deployment - uses: actions/github-script@v7 - with: - script: | - const project = `${{ steps.trigger-deployment-workflow.outputs.project }}`; - const workflowName = `${{ steps.trigger-deployment-workflow.outputs.workflowId }}`; - const pollInterval = 10 * 1000; // 10 seconds - - console.log(`Polling for workflow status: ${workflowName} in ${project}`); - - let status = 'in_progress'; - let conclusion = ''; - while (status === 'in_progress') { - const runs = await github.rest.actions.listWorkflowRuns({ - owner: context.repo.owner, - repo: project, - workflow_id: workflowName, - branch: 'main', - status: 'in_progress', - }); - - if (runs.data.workflow_runs.length > 0) { - const run = runs.data.workflow_runs[0]; // TODO: not really take the first one, should be fix later - status = run.status; - conclusion = run.conclusion; - - if (status === 'completed') { - console.log(`Workflow completed with status: ${conclusion}`); - return { status: conclusion, run_url: run.html_url }; - } - } - - await new Promise(resolve => setTimeout(resolve, pollInterval)); - } From 447153b1c5e9eac75f2f32da0533b71eb3526700 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Thu, 26 Dec 2024 20:45:23 +0100 Subject: [PATCH 17/30] fix(ci): wrong upstream url project --- .github/workflows/deploy-chatbot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 4feaf07..3fd3de4 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -189,7 +189,7 @@ jobs: console.log(`Trigger deployment status: ${JSON.stringify(workflowDetails, null, 2)}`); const owner = `${{ github.event.repository.owner.login }}`; - const project = `${{ github.event.repository.name }}`; + const project = `${{ steps.parse-command.outputs.project }}`; const runUrl = `https://github.com/${owner}/${project}/actions`; const statusIcon = workflowDetails.status === 'OK' ? '✅' : '❌'; From 71daa3d8f4168a44b0f1f5699bec49e47b18ef79 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Thu, 26 Dec 2024 23:36:34 +0100 Subject: [PATCH 18/30] ci: refactoring steps with scripts with inlined JS into JS modules --- .github/workflows/deploy-chatbot.yml | 58 ++++++---------------------- actions_scripts/notify_user.js | 47 ++++++++++++++++++++++ 2 files changed, 58 insertions(+), 47 deletions(-) create mode 100644 actions_scripts/notify_user.js diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 3fd3de4..629781b 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -11,7 +11,7 @@ jobs: steps: - name: Parse Deployment Command - id: parse-command + id: parse_command run: | WORKFLOW_LOCAL_RUN="${{ !github.event.act }}" COMMENT_BODY="${{ github.event.comment.body }}" @@ -62,51 +62,15 @@ jobs: private-key: ${{ secrets.ZDC_AUTH_PRIVATE_KEY }} owner: ${{ github.repository_owner }} + - uses: actions/checkout@v4 + - name: Notify the user uses: actions/github-script@v7 id: notify-user with: script: | - const environment = `${{ steps.parse-command.outputs.environment }}`; - const project = `${{ steps.parse-command.outputs.project }}`; - const infra = `${{ steps.parse-command.outputs.infra }}`; - - const actor = `${{ github.event.comment.user.login }}`; - const username = (actor !== "") ? actor : 'Unknown'; - - const prNumber = context.payload.issue.number; - - let message = `🚀 Deployment action request received from user: ${username}\n`; - if (project) { - message += `- Project: \`${project}\`\n`; - } - if (environment) { - message += `- Environment: \`${environment}\`\n`; - } - if (infra) { - message += `- Infrastructure: \`${infra}\`\n`; - } - - if (`${{ github.event.act }}` === 'true') { - console.log(`Action is being runned locally by 'ACT'. - Skipping the notify user on PR, but output would have been: - ${message}`); - return { comment_id: 10, message: message } // arbitraty mocked comment number; - } else { - let comment = {}; - try { - comment = await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - body: message, - }); - return { comment_id: comment.data.id, message: message }; - } catch (ex) { - console.log("Failed to POST the comment on the PR to notify the user due to =[> " + ex + "]"); - return { "comment_id": null }; - } - } + const script = require('./actions_scripts/notify_user.js') + await script({github, context, steps}) # TODO: from here, isolate them in independent workflows # and just call them depending on the input by having just @@ -118,8 +82,8 @@ jobs: with: github-token: ${{ steps.zdc-auth-app-token.outputs.token || github.token }} script: | - const environment = `${{ steps.parse-command.outputs.environment }}`; - const project = `${{ steps.parse-command.outputs.project }}`; + const environment = `${{ steps.parse_command.outputs.environment }}`; + const project = `${{ steps.parse_command.outputs.project }}`; const workflowId = `deploy-${environment}.yml`; let result = ""; @@ -148,14 +112,14 @@ jobs: }; - name: Deploy Infra - if: steps.parse-command.outputs.infra != '' + if: steps.parse_command.outputs.infra != '' uses: appleboy/ssh-action@v1.2.0 with: host: ${{ secrets.SSH_HOST }} username: ${{ secrets.SSH_USERNAME }} key: ${{ secrets.SSH_KEY }} script: | - case "${{ steps.parse-command.outputs.infra }}" in + case "${{ steps.parse_command.outputs.infra }}" in postgres) echo "Deploying Postgres..." docker run -d --name postgres --restart always -e POSTGRES_PASSWORD=mysecretpassword postgres @@ -170,7 +134,7 @@ jobs: docker run -d --name redis --restart always redis ;; *) - echo "Unknown infra: ${{ steps.parse-command.outputs.infra }}" + echo "Unknown infra: ${{ steps.parse_command.outputs.infra }}" ;; esac @@ -189,7 +153,7 @@ jobs: console.log(`Trigger deployment status: ${JSON.stringify(workflowDetails, null, 2)}`); const owner = `${{ github.event.repository.owner.login }}`; - const project = `${{ steps.parse-command.outputs.project }}`; + const project = `${{ steps.parse_command.outputs.project }}`; const runUrl = `https://github.com/${owner}/${project}/actions`; const statusIcon = workflowDetails.status === 'OK' ? '✅' : '❌'; diff --git a/actions_scripts/notify_user.js b/actions_scripts/notify_user.js new file mode 100644 index 0000000..481f23b --- /dev/null +++ b/actions_scripts/notify_user.js @@ -0,0 +1,47 @@ +module.exports = async ({github, context, steps}) => { + console.log(`GITHUB: ${JSON.stringify(github, null, 2)}`); + console.log(`CTX: ${JSON.stringify(context, null, 2)}`); + console.log(`STEPS: ${JSON.stringify(steps, null, 2)}`); + + const environment = steps.parse_command.outputs.environment; + const project = steps.parse_command.outputs.project; + const infra = steps.parse_command.outputs.infra; + + const actor = github.event.comment.user.login; + console.log(`Actor: ${actor}`) + const username = (actor !== "") ? actor : 'Unknown'; + + const prNumber = context.payload.issue.number; + + let message = `🚀 Deployment action request received from user: ${username}\n`; + if (project) { + message += `- Project: \`${project}\`\n`; + } + if (environment) { + message += `- Environment: \`${environment}\`\n`; + } + if (infra) { + message += `- Infrastructure: \`${infra}\`\n`; + } + + if (`${ github.event.act }` === 'true') { + console.log(`Action is being runned locally by 'ACT'. + Skipping the notify user on PR, but output would have been: + ${message}`); + return { comment_id: 10, message: message } // arbitraty mocked comment number; + } else { + let comment = {}; + try { + comment = await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: message, + }); + return { comment_id: comment.data.id, message: message }; + } catch (ex) { + console.log("Failed to POST the comment on the PR to notify the user due to =[> " + ex + "]"); + return { "comment_id": null }; + } + } +} \ No newline at end of file From 149eb6725a753f464bd8aba27620df81dbebbedb Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Thu, 26 Dec 2024 23:51:42 +0100 Subject: [PATCH 19/30] ci: logging the data that we can pass to the action --- .github/workflows/deploy-chatbot.yml | 3 ++- actions_scripts/notify_user.js | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 629781b..8fef45c 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -69,8 +69,9 @@ jobs: id: notify-user with: script: | + console.log(context) const script = require('./actions_scripts/notify_user.js') - await script({github, context, steps}) + await script({github, context}) # TODO: from here, isolate them in independent workflows # and just call them depending on the input by having just diff --git a/actions_scripts/notify_user.js b/actions_scripts/notify_user.js index 481f23b..51d10f4 100644 --- a/actions_scripts/notify_user.js +++ b/actions_scripts/notify_user.js @@ -1,7 +1,10 @@ module.exports = async ({github, context, steps}) => { console.log(`GITHUB: ${JSON.stringify(github, null, 2)}`); console.log(`CTX: ${JSON.stringify(context, null, 2)}`); - console.log(`STEPS: ${JSON.stringify(steps, null, 2)}`); + console.log(`process: ${JSON.stringify(process.env, null, 2)}`); + const {SHA} = process.env + console.log(`SHA: ${SHA}`) + // console.log(`STEPS: ${JSON.stringify(steps, null, 2)}`); const environment = steps.parse_command.outputs.environment; const project = steps.parse_command.outputs.project; From 051a99698c7fafcf0e508daafc1dd2d10cdb4c23 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Fri, 27 Dec 2024 11:29:44 +0100 Subject: [PATCH 20/30] ci: workaround for the undefined steps --- .github/workflows/deploy-chatbot.yml | 3 ++- actions_scripts/notify_user.js | 15 +++------------ 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 8fef45c..e9aa0f5 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -69,7 +69,8 @@ jobs: id: notify-user with: script: | - console.log(context) + console.log(github) + console.log(`GITHUB: ${JSON.stringify(github, null, 2)}`); const script = require('./actions_scripts/notify_user.js') await script({github, context}) diff --git a/actions_scripts/notify_user.js b/actions_scripts/notify_user.js index 51d10f4..e21a4a7 100644 --- a/actions_scripts/notify_user.js +++ b/actions_scripts/notify_user.js @@ -1,16 +1,7 @@ -module.exports = async ({github, context, steps}) => { - console.log(`GITHUB: ${JSON.stringify(github, null, 2)}`); +module.exports = async ({github, context, environment, project, infra}) => { console.log(`CTX: ${JSON.stringify(context, null, 2)}`); - console.log(`process: ${JSON.stringify(process.env, null, 2)}`); - const {SHA} = process.env - console.log(`SHA: ${SHA}`) - // console.log(`STEPS: ${JSON.stringify(steps, null, 2)}`); - const environment = steps.parse_command.outputs.environment; - const project = steps.parse_command.outputs.project; - const infra = steps.parse_command.outputs.infra; - - const actor = github.event.comment.user.login; + const actor = context.actor; console.log(`Actor: ${actor}`) const username = (actor !== "") ? actor : 'Unknown'; @@ -27,7 +18,7 @@ module.exports = async ({github, context, steps}) => { message += `- Infrastructure: \`${infra}\`\n`; } - if (`${ github.event.act }` === 'true') { + if (context.payload.act === 'true') { console.log(`Action is being runned locally by 'ACT'. Skipping the notify user on PR, but output would have been: ${message}`); From 84cdfd9e609eabf52cadb3aaaa0afe94fe3f1da5 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Fri, 27 Dec 2024 12:12:25 +0100 Subject: [PATCH 21/30] ci(fix): solving weird action context to JS syntax empty conversions --- .github/workflows/deploy-chatbot.yml | 26 +- .../workflows/mock_payloads/deploy_act.json | 315 +++++++++++++++++- actions_scripts/notify_user.js | 12 +- 3 files changed, 323 insertions(+), 30 deletions(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index e9aa0f5..7452f8d 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -11,7 +11,7 @@ jobs: steps: - name: Parse Deployment Command - id: parse_command + id: parse-command run: | WORKFLOW_LOCAL_RUN="${{ !github.event.act }}" COMMENT_BODY="${{ github.event.comment.body }}" @@ -69,10 +69,13 @@ jobs: id: notify-user with: script: | - console.log(github) - console.log(`GITHUB: ${JSON.stringify(github, null, 2)}`); const script = require('./actions_scripts/notify_user.js') - await script({github, context}) + + const environment = `${{ steps.parse-command.outputs.result.environment }}`; + const project = `${{ steps.parse-command.outputs.result.project }}`; + const infra = `${{ steps.parse-command.outputs.result.infra }}`; + + return await script({github, context, environment, project, infra}) # TODO: from here, isolate them in independent workflows # and just call them depending on the input by having just @@ -84,8 +87,8 @@ jobs: with: github-token: ${{ steps.zdc-auth-app-token.outputs.token || github.token }} script: | - const environment = `${{ steps.parse_command.outputs.environment }}`; - const project = `${{ steps.parse_command.outputs.project }}`; + const environment = `${{ steps.parse-command.outputs.environment }}`; + const project = `${{ steps.parse-command.outputs.project }}`; const workflowId = `deploy-${environment}.yml`; let result = ""; @@ -114,14 +117,14 @@ jobs: }; - name: Deploy Infra - if: steps.parse_command.outputs.infra != '' + if: steps.parse-command.outputs.infra != '' uses: appleboy/ssh-action@v1.2.0 with: host: ${{ secrets.SSH_HOST }} username: ${{ secrets.SSH_USERNAME }} key: ${{ secrets.SSH_KEY }} script: | - case "${{ steps.parse_command.outputs.infra }}" in + case "${{ steps.parse-command.outputs.infra }}" in postgres) echo "Deploying Postgres..." docker run -d --name postgres --restart always -e POSTGRES_PASSWORD=mysecretpassword postgres @@ -136,7 +139,7 @@ jobs: docker run -d --name redis --restart always redis ;; *) - echo "Unknown infra: ${{ steps.parse_command.outputs.infra }}" + echo "Unknown infra: ${{ steps.parse-command.outputs.infra }}" ;; esac @@ -146,8 +149,9 @@ jobs: with: script: | const workflowLocalRun = `${{ github.event.act }}` === 'true'; + console.log("Is local run: " + workflowLocalRun); - const commentOnPr = ${{ steps.notify-user.outputs.result }}; + const commentOnPr = JSON.parse(`${{ steps.notify-user.outputs.result }}`); const commentId = commentOnPr.comment_id; console.log(`Updating comment with id ${commentId} for workflow status`); @@ -155,7 +159,7 @@ jobs: console.log(`Trigger deployment status: ${JSON.stringify(workflowDetails, null, 2)}`); const owner = `${{ github.event.repository.owner.login }}`; - const project = `${{ steps.parse_command.outputs.project }}`; + const project = `${{ steps.parse-command.outputs.project }}`; const runUrl = `https://github.com/${owner}/${project}/actions`; const statusIcon = workflowDetails.status === 'OK' ? '✅' : '❌'; diff --git a/.github/workflows/mock_payloads/deploy_act.json b/.github/workflows/mock_payloads/deploy_act.json index 3c3da08..6aa8a20 100644 --- a/.github/workflows/mock_payloads/deploy_act.json +++ b/.github/workflows/mock_payloads/deploy_act.json @@ -1,18 +1,307 @@ { - "act": true, - "comment": { - "body": "/deploy --environment pre --project ag-summoners-sync", - "user": { - "login": "TheRustifyer" - } + "act": true, + "action": "created", + "comment": { + "author_association": "MEMBER", + "body": "/deploy --environment pre --project ag-summoners-sync", + "created_at": "2024-12-27T10:30:39Z", + "html_url": "https://github.com/zerodaycode/app-summoners-sync/pull/4#issuecomment-2563559471", + "id": 2563559471, + "issue_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/issues/4", + "node_id": "IC_kwDONduBec6YzNAv", + "performed_via_github_app": null, + "reactions": { + "+1": 0, + "-1": 0, + "confused": 0, + "eyes": 0, + "heart": 0, + "hooray": 0, + "laugh": 0, + "rocket": 0, + "total_count": 0, + "url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/issues/comments/2563559471/reactions" }, - "issue": { - "number": 4 + "updated_at": "2024-12-27T10:30:39Z", + "url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/issues/comments/2563559471", + "user": { + "avatar_url": "https://avatars.githubusercontent.com/u/68871459?v=4", + "events_url": "https://api.github.com/users/TheRustifyer/events{/privacy}", + "followers_url": "https://api.github.com/users/TheRustifyer/followers", + "following_url": "https://api.github.com/users/TheRustifyer/following{/other_user}", + "gists_url": "https://api.github.com/users/TheRustifyer/gists{/gist_id}", + "gravatar_id": "", + "html_url": "https://github.com/TheRustifyer", + "id": 68871459, + "login": "TheRustifyer", + "node_id": "MDQ6VXNlcjY4ODcxNDU5", + "organizations_url": "https://api.github.com/users/TheRustifyer/orgs", + "received_events_url": "https://api.github.com/users/TheRustifyer/received_events", + "repos_url": "https://api.github.com/users/TheRustifyer/repos", + "site_admin": false, + "starred_url": "https://api.github.com/users/TheRustifyer/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/TheRustifyer/subscriptions", + "type": "User", + "url": "https://api.github.com/users/TheRustifyer", + "user_view_type": "public" + } + }, + "issue": { + "active_lock_reason": null, + "assignee": { + "avatar_url": "https://avatars.githubusercontent.com/u/68871459?v=4", + "events_url": "https://api.github.com/users/TheRustifyer/events{/privacy}", + "followers_url": "https://api.github.com/users/TheRustifyer/followers", + "following_url": "https://api.github.com/users/TheRustifyer/following{/other_user}", + "gists_url": "https://api.github.com/users/TheRustifyer/gists{/gist_id}", + "gravatar_id": "", + "html_url": "https://github.com/TheRustifyer", + "id": 68871459, + "login": "TheRustifyer", + "node_id": "MDQ6VXNlcjY4ODcxNDU5", + "organizations_url": "https://api.github.com/users/TheRustifyer/orgs", + "received_events_url": "https://api.github.com/users/TheRustifyer/received_events", + "repos_url": "https://api.github.com/users/TheRustifyer/repos", + "site_admin": false, + "starred_url": "https://api.github.com/users/TheRustifyer/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/TheRustifyer/subscriptions", + "type": "User", + "url": "https://api.github.com/users/TheRustifyer", + "user_view_type": "public" }, - "repository": { - "name": "app-summoners-sync", - "owner": { - "login": "zerodaycode" + "assignees": [ + { + "avatar_url": "https://avatars.githubusercontent.com/u/68871459?v=4", + "events_url": "https://api.github.com/users/TheRustifyer/events{/privacy}", + "followers_url": "https://api.github.com/users/TheRustifyer/followers", + "following_url": "https://api.github.com/users/TheRustifyer/following{/other_user}", + "gists_url": "https://api.github.com/users/TheRustifyer/gists{/gist_id}", + "gravatar_id": "", + "html_url": "https://github.com/TheRustifyer", + "id": 68871459, + "login": "TheRustifyer", + "node_id": "MDQ6VXNlcjY4ODcxNDU5", + "organizations_url": "https://api.github.com/users/TheRustifyer/orgs", + "received_events_url": "https://api.github.com/users/TheRustifyer/received_events", + "repos_url": "https://api.github.com/users/TheRustifyer/repos", + "site_admin": false, + "starred_url": "https://api.github.com/users/TheRustifyer/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/TheRustifyer/subscriptions", + "type": "User", + "url": "https://api.github.com/users/TheRustifyer", + "user_view_type": "public" + } + ], + "author_association": "MEMBER", + "body": null, + "closed_at": null, + "comments": 9, + "comments_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/issues/4/comments", + "created_at": "2024-12-24T21:15:11Z", + "draft": false, + "events_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/issues/4/events", + "html_url": "https://github.com/zerodaycode/app-summoners-sync/pull/4", + "id": 2758305614, + "labels": [ + { + "color": "96E282", + "default": false, + "description": "", + "id": 7925191365, + "name": "ci", + "node_id": "LA_kwDONduBec8AAAAB2GDSxQ", + "url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/labels/ci" } + ], + "labels_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/issues/4/labels{/name}", + "locked": false, + "milestone": null, + "node_id": "PR_kwDONduBec6GMCkB", + "number": 4, + "performed_via_github_app": null, + "pull_request": { + "diff_url": "https://github.com/zerodaycode/app-summoners-sync/pull/4.diff", + "html_url": "https://github.com/zerodaycode/app-summoners-sync/pull/4", + "merged_at": null, + "patch_url": "https://github.com/zerodaycode/app-summoners-sync/pull/4.patch", + "url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/pulls/4" + }, + "reactions": { + "+1": 0, + "-1": 0, + "confused": 0, + "eyes": 0, + "heart": 0, + "hooray": 0, + "laugh": 0, + "rocket": 0, + "total_count": 0, + "url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/issues/4/reactions" + }, + "repository_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync", + "state": "open", + "state_reason": null, + "timeline_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/issues/4/timeline", + "title": "Initial general CI workflows", + "updated_at": "2024-12-27T10:30:39Z", + "url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/issues/4", + "user": { + "avatar_url": "https://avatars.githubusercontent.com/u/68871459?v=4", + "events_url": "https://api.github.com/users/TheRustifyer/events{/privacy}", + "followers_url": "https://api.github.com/users/TheRustifyer/followers", + "following_url": "https://api.github.com/users/TheRustifyer/following{/other_user}", + "gists_url": "https://api.github.com/users/TheRustifyer/gists{/gist_id}", + "gravatar_id": "", + "html_url": "https://github.com/TheRustifyer", + "id": 68871459, + "login": "TheRustifyer", + "node_id": "MDQ6VXNlcjY4ODcxNDU5", + "organizations_url": "https://api.github.com/users/TheRustifyer/orgs", + "received_events_url": "https://api.github.com/users/TheRustifyer/received_events", + "repos_url": "https://api.github.com/users/TheRustifyer/repos", + "site_admin": false, + "starred_url": "https://api.github.com/users/TheRustifyer/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/TheRustifyer/subscriptions", + "type": "User", + "url": "https://api.github.com/users/TheRustifyer", + "user_view_type": "public" } - } \ No newline at end of file + }, + "organization": { + "avatar_url": "https://avatars.githubusercontent.com/u/72573064?v=4", + "description": "", + "events_url": "https://api.github.com/orgs/zerodaycode/events", + "hooks_url": "https://api.github.com/orgs/zerodaycode/hooks", + "id": 72573064, + "issues_url": "https://api.github.com/orgs/zerodaycode/issues", + "login": "zerodaycode", + "members_url": "https://api.github.com/orgs/zerodaycode/members{/member}", + "node_id": "MDEyOk9yZ2FuaXphdGlvbjcyNTczMDY0", + "public_members_url": "https://api.github.com/orgs/zerodaycode/public_members{/member}", + "repos_url": "https://api.github.com/orgs/zerodaycode/repos", + "url": "https://api.github.com/orgs/zerodaycode" + }, + "repository": { + "allow_forking": true, + "archive_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/{archive_format}{/ref}", + "archived": false, + "assignees_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/assignees{/user}", + "blobs_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/git/blobs{/sha}", + "branches_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/branches{/branch}", + "clone_url": "https://github.com/zerodaycode/app-summoners-sync.git", + "collaborators_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/collaborators{/collaborator}", + "comments_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/comments{/number}", + "commits_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/commits{/sha}", + "compare_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/compare/{base}...{head}", + "contents_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/contents/{+path}", + "contributors_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/contributors", + "created_at": "2024-12-15T00:48:55Z", + "custom_properties": {}, + "default_branch": "develop", + "deployments_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/deployments", + "description": "A general purpose repository for holding the docs, assets, demo vids, configuration scripts and many more!", + "disabled": false, + "downloads_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/downloads", + "events_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/events", + "fork": false, + "forks": 0, + "forks_count": 0, + "forks_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/forks", + "full_name": "zerodaycode/app-summoners-sync", + "git_commits_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/git/commits{/sha}", + "git_refs_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/git/refs{/sha}", + "git_tags_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/git/tags{/sha}", + "git_url": "git://github.com/zerodaycode/app-summoners-sync.git", + "has_discussions": false, + "has_downloads": true, + "has_issues": true, + "has_pages": false, + "has_projects": true, + "has_wiki": true, + "homepage": null, + "hooks_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/hooks", + "html_url": "https://github.com/zerodaycode/app-summoners-sync", + "id": 903577977, + "is_template": false, + "issue_comment_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/issues/comments{/number}", + "issue_events_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/issues/events{/number}", + "issues_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/issues{/number}", + "keys_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/keys{/key_id}", + "labels_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/labels{/name}", + "language": "JavaScript", + "languages_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/languages", + "license": null, + "merges_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/merges", + "milestones_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/milestones{/number}", + "mirror_url": null, + "name": "app-summoners-sync", + "node_id": "R_kgDONduBeQ", + "notifications_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/notifications{?since,all,participating}", + "open_issues": 3, + "open_issues_count": 3, + "owner": { + "avatar_url": "https://avatars.githubusercontent.com/u/72573064?v=4", + "events_url": "https://api.github.com/users/zerodaycode/events{/privacy}", + "followers_url": "https://api.github.com/users/zerodaycode/followers", + "following_url": "https://api.github.com/users/zerodaycode/following{/other_user}", + "gists_url": "https://api.github.com/users/zerodaycode/gists{/gist_id}", + "gravatar_id": "", + "html_url": "https://github.com/zerodaycode", + "id": 72573064, + "login": "zerodaycode", + "node_id": "MDEyOk9yZ2FuaXphdGlvbjcyNTczMDY0", + "organizations_url": "https://api.github.com/users/zerodaycode/orgs", + "received_events_url": "https://api.github.com/users/zerodaycode/received_events", + "repos_url": "https://api.github.com/users/zerodaycode/repos", + "site_admin": false, + "starred_url": "https://api.github.com/users/zerodaycode/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/zerodaycode/subscriptions", + "type": "Organization", + "url": "https://api.github.com/users/zerodaycode", + "user_view_type": "public" + }, + "private": false, + "pulls_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/pulls{/number}", + "pushed_at": "2024-12-27T10:30:10Z", + "releases_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/releases{/id}", + "size": 30, + "ssh_url": "git@github.com:zerodaycode/app-summoners-sync.git", + "stargazers_count": 0, + "stargazers_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/stargazers", + "statuses_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/statuses/{sha}", + "subscribers_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/subscribers", + "subscription_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/subscription", + "svn_url": "https://github.com/zerodaycode/app-summoners-sync", + "tags_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/tags", + "teams_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/teams", + "topics": [], + "trees_url": "https://api.github.com/repos/zerodaycode/app-summoners-sync/git/trees{/sha}", + "updated_at": "2024-12-27T10:30:13Z", + "url": "https://api.github.com/repos/zerodaycode/app-summoners-sync", + "visibility": "public", + "watchers": 0, + "watchers_count": 0, + "web_commit_signoff_required": false + }, + "sender": { + "avatar_url": "https://avatars.githubusercontent.com/u/68871459?v=4", + "events_url": "https://api.github.com/users/TheRustifyer/events{/privacy}", + "followers_url": "https://api.github.com/users/TheRustifyer/followers", + "following_url": "https://api.github.com/users/TheRustifyer/following{/other_user}", + "gists_url": "https://api.github.com/users/TheRustifyer/gists{/gist_id}", + "gravatar_id": "", + "html_url": "https://github.com/TheRustifyer", + "id": 68871459, + "login": "TheRustifyer", + "node_id": "MDQ6VXNlcjY4ODcxNDU5", + "organizations_url": "https://api.github.com/users/TheRustifyer/orgs", + "received_events_url": "https://api.github.com/users/TheRustifyer/received_events", + "repos_url": "https://api.github.com/users/TheRustifyer/repos", + "site_admin": false, + "starred_url": "https://api.github.com/users/TheRustifyer/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/TheRustifyer/subscriptions", + "type": "User", + "url": "https://api.github.com/users/TheRustifyer", + "user_view_type": "public" + } +} \ No newline at end of file diff --git a/actions_scripts/notify_user.js b/actions_scripts/notify_user.js index e21a4a7..c8b0eb0 100644 --- a/actions_scripts/notify_user.js +++ b/actions_scripts/notify_user.js @@ -1,9 +1,9 @@ module.exports = async ({github, context, environment, project, infra}) => { - console.log(`CTX: ${JSON.stringify(context, null, 2)}`); + const localRun = context.payload.act; + const isLocalRun = (localRun !== undefined) ? localRun : false; const actor = context.actor; - console.log(`Actor: ${actor}`) - const username = (actor !== "") ? actor : 'Unknown'; + const username = (actor !== undefined && actor !== "") ? actor : 'Unknown'; const prNumber = context.payload.issue.number; @@ -18,9 +18,9 @@ module.exports = async ({github, context, environment, project, infra}) => { message += `- Infrastructure: \`${infra}\`\n`; } - if (context.payload.act === 'true') { + if (isLocalRun) { console.log(`Action is being runned locally by 'ACT'. - Skipping the notify user on PR, but output would have been: + Skipping the REST request to post a message for notify the user on PR, but output would have been: ${message}`); return { comment_id: 10, message: message } // arbitraty mocked comment number; } else { @@ -35,7 +35,7 @@ module.exports = async ({github, context, environment, project, infra}) => { return { comment_id: comment.data.id, message: message }; } catch (ex) { console.log("Failed to POST the comment on the PR to notify the user due to =[> " + ex + "]"); - return { "comment_id": null }; + return { comment_id: null }; } } } \ No newline at end of file From 686cacf79ca9964e325fac9c0f077102796ff782 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Fri, 27 Dec 2024 13:16:37 +0100 Subject: [PATCH 22/30] ci(refactor): splitting the JS code on the notify-user module to make it more readable --- .github/workflows/deploy-chatbot.yml | 13 ++-- actions_scripts/notify_user.js | 90 +++++++++++++++++----------- 2 files changed, 60 insertions(+), 43 deletions(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 7452f8d..6a5e7c9 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -69,11 +69,11 @@ jobs: id: notify-user with: script: | - const script = require('./actions_scripts/notify_user.js') + const environment = `${{ steps.parse-command.outputs.environment }}`; + const project = `${{ steps.parse-command.outputs.project }}`; + const infra = `${{ steps.parse-command.outputs.infra }}`; - const environment = `${{ steps.parse-command.outputs.result.environment }}`; - const project = `${{ steps.parse-command.outputs.result.project }}`; - const infra = `${{ steps.parse-command.outputs.result.infra }}`; + const script = require('./actions_scripts/notify_user.js') return await script({github, context, environment, project, infra}) @@ -149,14 +149,11 @@ jobs: with: script: | const workflowLocalRun = `${{ github.event.act }}` === 'true'; - console.log("Is local run: " + workflowLocalRun); - const commentOnPr = JSON.parse(`${{ steps.notify-user.outputs.result }}`); + const commentOnPr = ${{ steps.notify-user.outputs.result }}; const commentId = commentOnPr.comment_id; - console.log(`Updating comment with id ${commentId} for workflow status`); const workflowDetails = ${{ steps.trigger-deployment-workflow.outputs.result }}; - console.log(`Trigger deployment status: ${JSON.stringify(workflowDetails, null, 2)}`); const owner = `${{ github.event.repository.owner.login }}`; const project = `${{ steps.parse-command.outputs.project }}`; diff --git a/actions_scripts/notify_user.js b/actions_scripts/notify_user.js index c8b0eb0..842d057 100644 --- a/actions_scripts/notify_user.js +++ b/actions_scripts/notify_user.js @@ -1,41 +1,61 @@ module.exports = async ({github, context, environment, project, infra}) => { - const localRun = context.payload.act; - const isLocalRun = (localRun !== undefined) ? localRun : false; + const isLocalRun = ciLocalRun(context); - const actor = context.actor; - const username = (actor !== undefined && actor !== "") ? actor : 'Unknown'; + const username = getUsername(context); + const prNumber = context.payload.issue.number; + const message = generatePrCommentMsg(username, environment, project, infra); - const prNumber = context.payload.issue.number; - - let message = `🚀 Deployment action request received from user: ${username}\n`; - if (project) { - message += `- Project: \`${project}\`\n`; - } - if (environment) { - message += `- Environment: \`${environment}\`\n`; - } - if (infra) { - message += `- Infrastructure: \`${infra}\`\n`; + if (isLocalRun) { + logMessageOnLocalEnv(message); + return { comment_id: 10, message: message } // arbitraty mocked comment number; + } else { + try { + const comment = createPrComment(github, context, prNumber, message); + return { comment_id: comment.data.id, message: message }; + } catch (ex) { + console.log("Failed to POST the comment on the PR to notify the user due to =[> " + ex + "]"); + return { comment_id: null }; } + } +} - if (isLocalRun) { - console.log(`Action is being runned locally by 'ACT'. - Skipping the REST request to post a message for notify the user on PR, but output would have been: - ${message}`); - return { comment_id: 10, message: message } // arbitraty mocked comment number; - } else { - let comment = {}; - try { - comment = await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - body: message, - }); - return { comment_id: comment.data.id, message: message }; - } catch (ex) { - console.log("Failed to POST the comment on the PR to notify the user due to =[> " + ex + "]"); - return { comment_id: null }; - } - } +function ciLocalRun(context) { + const localRun = context.payload.act; + return(localRun !== undefined) ? localRun : false; +} + +function getUsername(context) { + const actor = context.actor; + return (actor !== undefined && actor !== "") ? actor : 'Unknown'; + // TODO: throw ex when undefined or non valid actor +} + +function generatePrCommentMsg(username, environment, project, infra) { + let message = `🚀 Deployment action request received from user: ${username}\n`; + if (project) { + message += `- Project: \`${project}\`\n`; + } + if (environment) { + message += `- Environment: \`${environment}\`\n`; + } + if (infra) { + message += `- Infrastructure: \`${infra}\`\n`; + } + + return message; +} + +async function createPrComment(github, context, prNumber, message) { + return await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: message, + }); +} + +function logMessageOnLocalEnv(message) { + console.log(`Action is being runned locally by 'ACT'. + Skipping the REST request to post a message for notify the user on PR, but output would have been: + ${message}`); } \ No newline at end of file From 588db6df0326ef34c1b20568af466075173f2579 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Fri, 27 Dec 2024 13:22:10 +0100 Subject: [PATCH 23/30] ci(fix): missing await on createComment fn --- actions_scripts/notify_user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions_scripts/notify_user.js b/actions_scripts/notify_user.js index 842d057..f062b1f 100644 --- a/actions_scripts/notify_user.js +++ b/actions_scripts/notify_user.js @@ -10,7 +10,7 @@ module.exports = async ({github, context, environment, project, infra}) => { return { comment_id: 10, message: message } // arbitraty mocked comment number; } else { try { - const comment = createPrComment(github, context, prNumber, message); + const comment = await createPrComment(github, context, prNumber, message); return { comment_id: comment.data.id, message: message }; } catch (ex) { console.log("Failed to POST the comment on the PR to notify the user due to =[> " + ex + "]"); From 8652621209bd92c365ba308035b6e6a61949aff3 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Fri, 27 Dec 2024 16:52:11 +0100 Subject: [PATCH 24/30] ci: converting the new JS script to an ES module. Added local type-safety checks --- .github/workflows/deploy-chatbot.yml | 9 +- .gitignore | 2 + actions_scripts/notify_user.js | 78 ++++- actions_scripts/package.json | 3 + package-lock.json | 432 +++++++++++++++++++++++++++ package.json | 5 + 6 files changed, 507 insertions(+), 22 deletions(-) create mode 100644 actions_scripts/package.json create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 6a5e7c9..7d22cd4 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -73,13 +73,8 @@ jobs: const project = `${{ steps.parse-command.outputs.project }}`; const infra = `${{ steps.parse-command.outputs.infra }}`; - const script = require('./actions_scripts/notify_user.js') - - return await script({github, context, environment, project, infra}) - - # TODO: from here, isolate them in independent workflows - # and just call them depending on the input by having just - # a simple and unique trigger deployment + const { default: notifyUser } = await import('${{ github.workspace }}/actions_scripts/notify_user.js') + return await notifyUser({github, context, environment, project, infra}) - name: Trigger Deployment Workflow uses: actions/github-script@v7 diff --git a/.gitignore b/.gitignore index 2751a9c..723ef1d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ .nvim/ .idea/ + +node_modules/ \ No newline at end of file diff --git a/actions_scripts/notify_user.js b/actions_scripts/notify_user.js index f062b1f..2bc1188 100644 --- a/actions_scripts/notify_user.js +++ b/actions_scripts/notify_user.js @@ -1,4 +1,15 @@ -module.exports = async ({github, context, environment, project, infra}) => { +// Main function to notify the user about deployment actions. +/** + * Notify the user about the deployment action. + * @param {Object} options - The options for the notification. + * @param {Object} options.github - GitHub API client provided by actions/github-script. + * @param {Object} options.context - Context object from GitHub Actions, containing payload and environment details. + * @param {string} options.environment - Deployment environment (e.g., pre, prod). + * @param {string} options.project - Project name associated with the deployment. + * @param {string} options.infra - Infrastructure type (e.g., postgres, redis). + * @returns {Object} - An object containing the comment ID and the message content. + */ +export default async ({ github, context, environment, project, infra }) => { const isLocalRun = ciLocalRun(context); const username = getUsername(context); @@ -7,44 +18,76 @@ module.exports = async ({github, context, environment, project, infra}) => { if (isLocalRun) { logMessageOnLocalEnv(message); - return { comment_id: 10, message: message } // arbitraty mocked comment number; + // Return a mock comment ID for local testing purposes. + return { comment_id: 1010101010, message: message }; } else { try { const comment = await createPrComment(github, context, prNumber, message); return { comment_id: comment.data.id, message: message }; } catch (ex) { - console.log("Failed to POST the comment on the PR to notify the user due to =[> " + ex + "]"); + console.log("Failed to POST the comment on the PR to notify the user due to =[> " + ex + "]"); return { comment_id: null }; } } -} +}; +// Helper function to determine if the workflow is running locally. +/** + * Check if the current run is a local run (e.g., with ACT). + * @param {Object} context - GitHub Actions context object. + * @returns {boolean} - True if running locally, false otherwise. + */ function ciLocalRun(context) { const localRun = context.payload.act; - return(localRun !== undefined) ? localRun : false; + return (localRun !== undefined) ? localRun : false; } +// Helper function to retrieve the username of the actor triggering the workflow. +/** + * Get the username of the actor from the context. + * @param {Object} context - GitHub Actions context object. + * @returns {string} - The username of the actor. + * @throws {Error} - if the parsed actor text is non validdfd + */ function getUsername(context) { const actor = context.actor; - return (actor !== undefined && actor !== "") ? actor : 'Unknown'; - // TODO: throw ex when undefined or non valid actor + if (actor !== undefined && actor !== "") + return actor; + else + throw new Error("Unable to determine the actor (user) that triggered this deploy. Leaving..."); } +// Helper function to generate the PR comment message. +/** + * Generate the content of the PR comment to notify the user. + * @param {string} username - Username of the actor triggering the workflow. + * @param {string} environment - Deployment environment (e.g., pre, pre-pro, pro). + * @param {string} project - Project name associated with the deployment. + * @param {string} infra - Infrastructure entity (e.g., postgres, redis). + * @returns {string} - The formatted message to be posted on the PR. + */ function generatePrCommentMsg(username, environment, project, infra) { let message = `🚀 Deployment action request received from user: ${username}\n`; - if (project) { + + if (project) message += `- Project: \`${project}\`\n`; - } - if (environment) { + if (environment) message += `- Environment: \`${environment}\`\n`; - } - if (infra) { + if (infra) message += `- Infrastructure: \`${infra}\`\n`; - } return message; } +// Helper function to create a PR comment via the GitHub API. +/** + * Post a comment on the PR to notify the user. + * @param {Object} github - GitHub API client. + * @param {Object} context - GitHub Actions context object. + * @param {number} prNumber - Pull request number. + * @param {string} message - Message content to be posted. + * @returns {Object} - The response object from the GitHub API. + */ async function createPrComment(github, context, prNumber, message) { return await github.rest.issues.createComment({ owner: context.repo.owner, @@ -54,8 +97,13 @@ async function createPrComment(github, context, prNumber, message) { }); } +// Helper function to log the PR comment message in a local environment. +/** + * Log the message locally for debugging when running with ACT. + * @param {string} message - Message content to be logged. + */ function logMessageOnLocalEnv(message) { console.log(`Action is being runned locally by 'ACT'. - Skipping the REST request to post a message for notify the user on PR, but output would have been: + Skipping the REST request to post a message for notifying the user on PR, but the output would have been: ${message}`); -} \ No newline at end of file +} diff --git a/actions_scripts/package.json b/actions_scripts/package.json new file mode 100644 index 0000000..96ae6e5 --- /dev/null +++ b/actions_scripts/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b6f46fd --- /dev/null +++ b/package-lock.json @@ -0,0 +1,432 @@ +{ + "name": "app-summoners-sync", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "@types/github-script": "github:actions/github-script" + } + }, + "node_modules/@actions/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", + "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@actions/exec": "^1.1.1", + "@actions/http-client": "^2.0.1" + } + }, + "node_modules/@actions/exec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", + "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@actions/io": "^1.0.1" + } + }, + "node_modules/@actions/github": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@actions/github/-/github-6.0.0.tgz", + "integrity": "sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@actions/http-client": "^2.2.0", + "@octokit/core": "^5.0.1", + "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/plugin-rest-endpoint-methods": "^10.0.0" + } + }, + "node_modules/@actions/glob": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@actions/glob/-/glob-0.4.0.tgz", + "integrity": "sha512-+eKIGFhsFa4EBwaf/GMyzCdWrXWymGXfFmZU3FHQvYS8mPcHtTtZONbkcqqUMzw9mJ/pImEBFET1JNifhqGsAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@actions/core": "^1.9.1", + "minimatch": "^3.0.4" + } + }, + "node_modules/@actions/http-client": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", + "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tunnel": "^0.0.6", + "undici": "^5.25.4" + } + }, + "node_modules/@actions/io": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", + "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz", + "integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.3.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.5.tgz", + "integrity": "sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.0.tgz", + "integrity": "sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/request": "^8.3.0", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz", + "integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz", + "integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^20.0.0" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.1.tgz", + "integrity": "sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", + "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^20.0.0" + } + }, + "node_modules/@octokit/plugin-retry": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-6.1.0.tgz", + "integrity": "sha512-WrO3bvq4E1Xh1r2mT9w6SDFg01gFmP81nIG77+p/MqW1JeXXgL++6umim3t6x0Zj5pZm3rXAN+0HEjmmdhIRig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^13.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/request": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.0.tgz", + "integrity": "sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^9.0.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.0.tgz", + "integrity": "sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.1.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/types": { + "version": "13.6.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.6.2.tgz", + "integrity": "sha512-WpbZfZUcZU77DrSW4wbsSgTPfKcp286q3ItaIgvSbBpZJlu6mnYXAkjZz6LVZPXkEvLIM8McanyZejKTYUHipA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^22.2.0" + } + }, + "node_modules/@types/github-script": { + "name": "github-script", + "version": "7.0.1", + "resolved": "git+ssh://git@github.com/actions/github-script.git#4020e461acd7a80762cdfff123a1fde368246fa4", + "dev": true, + "license": "MIT", + "dependencies": { + "@actions/core": "^1.10.1", + "@actions/exec": "^1.1.1", + "@actions/github": "^6.0.0", + "@actions/glob": "^0.4.0", + "@actions/io": "^1.1.3", + "@octokit/core": "^5.0.1", + "@octokit/plugin-request-log": "^4.0.0", + "@octokit/plugin-retry": "^6.0.1", + "@types/node": "^20.9.0" + }, + "engines": { + "node": ">=20.0.0 <21.0.0" + } + }, + "node_modules/@types/node": { + "version": "20.17.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.10.tgz", + "integrity": "sha512-/jrvh5h6NXhEauFFexRin69nA0uHJ5gwk4iDivp/DeoEua3uwCUto6PC86IpRITBOs4+6i2I56K5x5b6WYGXHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/universal-user-agent": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..fb11d56 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "devDependencies": { + "@types/github-script": "github:actions/github-script" + } +} From 66478accaea05f61a019d1d79ed8d06bfeb47529 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Fri, 27 Dec 2024 17:28:21 +0100 Subject: [PATCH 25/30] ci: refactoring common helper functions into their own modules --- actions_scripts/helpers.js | 28 ++++++++++++++++++++++++++ actions_scripts/notify_user.js | 30 +++------------------------- actions_scripts/package.json | 3 --- actions_scripts/update_pr_comment.js | 0 package.json | 1 + 5 files changed, 32 insertions(+), 30 deletions(-) create mode 100644 actions_scripts/helpers.js delete mode 100644 actions_scripts/package.json create mode 100644 actions_scripts/update_pr_comment.js diff --git a/actions_scripts/helpers.js b/actions_scripts/helpers.js new file mode 100644 index 0000000..edad459 --- /dev/null +++ b/actions_scripts/helpers.js @@ -0,0 +1,28 @@ +// Contains helper functions made to be reusable across the JS scripts +// of the notifications + +// Helper function to determine if the workflow is running locally. +/** + * Check if the current run is a local run (e.g., with ACT). + * @param {Object} context - GitHub Actions context object. + * @returns {boolean} - True if running locally, false otherwise. + */ +export function ciLocalRun(context) { + const localRun = context.payload.act; + return (localRun !== undefined) ? localRun : false; +} + +// Helper function to retrieve the username of the actor triggering the workflow. +/** + * Get the username of the actor from the context. + * @param {Object} context - GitHub Actions context object. + * @returns {string} - The username of the actor. + * @throws {Error} - if the parsed actor text is non validdfd + */ +export function extractUsername(context) { + const actor = context.actor; + if (actor !== undefined && actor !== "") + return actor; + else + throw new Error("Unable to determine the actor (user) that triggered this deploy. Leaving..."); +} \ No newline at end of file diff --git a/actions_scripts/notify_user.js b/actions_scripts/notify_user.js index 2bc1188..d50d6a5 100644 --- a/actions_scripts/notify_user.js +++ b/actions_scripts/notify_user.js @@ -1,3 +1,5 @@ +import { ciLocalRun, extractUsername } from "./helpers.js"; + // Main function to notify the user about deployment actions. /** * Notify the user about the deployment action. @@ -12,7 +14,7 @@ export default async ({ github, context, environment, project, infra }) => { const isLocalRun = ciLocalRun(context); - const username = getUsername(context); + const username = extractUsername(context); const prNumber = context.payload.issue.number; const message = generatePrCommentMsg(username, environment, project, infra); @@ -31,32 +33,6 @@ export default async ({ github, context, environment, project, infra }) => { } }; -// Helper function to determine if the workflow is running locally. -/** - * Check if the current run is a local run (e.g., with ACT). - * @param {Object} context - GitHub Actions context object. - * @returns {boolean} - True if running locally, false otherwise. - */ -function ciLocalRun(context) { - const localRun = context.payload.act; - return (localRun !== undefined) ? localRun : false; -} - -// Helper function to retrieve the username of the actor triggering the workflow. -/** - * Get the username of the actor from the context. - * @param {Object} context - GitHub Actions context object. - * @returns {string} - The username of the actor. - * @throws {Error} - if the parsed actor text is non validdfd - */ -function getUsername(context) { - const actor = context.actor; - if (actor !== undefined && actor !== "") - return actor; - else - throw new Error("Unable to determine the actor (user) that triggered this deploy. Leaving..."); -} - // Helper function to generate the PR comment message. /** * Generate the content of the PR comment to notify the user. diff --git a/actions_scripts/package.json b/actions_scripts/package.json deleted file mode 100644 index 96ae6e5..0000000 --- a/actions_scripts/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "module" -} \ No newline at end of file diff --git a/actions_scripts/update_pr_comment.js b/actions_scripts/update_pr_comment.js new file mode 100644 index 0000000..e69de29 diff --git a/package.json b/package.json index fb11d56..e658149 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,5 @@ { + "type": "module", "devDependencies": { "@types/github-script": "github:actions/github-script" } From a489b740b403e7563f986fe6eb3521fa30ae16bc Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Fri, 27 Dec 2024 22:08:59 +0100 Subject: [PATCH 26/30] ci: refactoring the parse-command step --- .github/workflows/deploy-chatbot.yml | 53 ++++----------------- actions_scripts/notify_user.js | 1 - actions_scripts/parse_deployment_command.js | 48 +++++++++++++++++++ actions_scripts/update_pr_comment.js | 0 4 files changed, 57 insertions(+), 45 deletions(-) create mode 100644 actions_scripts/parse_deployment_command.js delete mode 100644 actions_scripts/update_pr_comment.js diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 7d22cd4..2ba7f28 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -9,50 +9,17 @@ jobs: handle-deployment-on-pr-comment: runs-on: ubuntu-latest - steps: + steps: + - uses: actions/checkout@v4 + - name: Parse Deployment Command + uses: actions/github-script@v7 id: parse-command - run: | - WORKFLOW_LOCAL_RUN="${{ !github.event.act }}" - COMMENT_BODY="${{ github.event.comment.body }}" - if [[ WORKFLOW_LOCAL_RUN ]]; then - echo "Setting the command as a mock since it's running locally with ACT" - COMMENT_BODY='/deploy --environment pre --project ag-summoners-sync' - fi - - echo "Comment received: $COMMENT_BODY" - - # Initialize variables - ENVIRONMENT="" - PROJECT="" - INFRA="" - - # Parse environment - if [[ "$COMMENT_BODY" =~ --environment[[:space:]]+([a-zA-Z0-9_-]+) ]]; then - ENVIRONMENT="${BASH_REMATCH[1]}" - echo "Environment: $ENVIRONMENT" - fi - - # Parse project - if [[ "$COMMENT_BODY" =~ --project[[:space:]]+([a-zA-Z0-9_-]+) ]]; then - PROJECT="${BASH_REMATCH[1]}" - echo "Project: $PROJECT" - else - echo "No environment specified. Aborting workflow." - exit 1 # Aborts the workflow # TODO: pass it as an output to the user notifier step - fi - - # Parse infra - if [[ "$COMMENT_BODY" =~ --infra[[:space:]]+([a-zA-Z0-9_-]+) ]]; then - INFRA="${BASH_REMATCH[1]}" - echo "Infra: $INFRA" - fi - - # Output parsed values - echo "environment=$ENVIRONMENT" >> $GITHUB_OUTPUT - echo "project=$PROJECT" >> $GITHUB_OUTPUT - echo "infra=$INFRA" >> $GITHUB_OUTPUT - + with: + script: | + const { default: parseDeployCommand } = await import('${{ github.workspace }}/actions_scripts/parse_deployment_command.js') + parseDeployCommand({context, core}) + - name: Get GH Zero Day Code APP token if: ${{ !github.event.act }} uses: actions/create-github-app-token@v1 @@ -62,8 +29,6 @@ jobs: private-key: ${{ secrets.ZDC_AUTH_PRIVATE_KEY }} owner: ${{ github.repository_owner }} - - uses: actions/checkout@v4 - - name: Notify the user uses: actions/github-script@v7 id: notify-user diff --git a/actions_scripts/notify_user.js b/actions_scripts/notify_user.js index d50d6a5..3290e73 100644 --- a/actions_scripts/notify_user.js +++ b/actions_scripts/notify_user.js @@ -1,6 +1,5 @@ import { ciLocalRun, extractUsername } from "./helpers.js"; -// Main function to notify the user about deployment actions. /** * Notify the user about the deployment action. * @param {Object} options - The options for the notification. diff --git a/actions_scripts/parse_deployment_command.js b/actions_scripts/parse_deployment_command.js new file mode 100644 index 0000000..5cb396f --- /dev/null +++ b/actions_scripts/parse_deployment_command.js @@ -0,0 +1,48 @@ +/** + * Parse the input command of the user in the PR. + * @param {Object} options - The options for the notification. + * @param {Object} options.context - Context object from GitHub Actions, containing payload and environment details. + * @param {Object} options.core module for interacting with GitHub Actions workflow commands and outputs. +*/ +export default ({context, core}) => { + const localRun = !context.payload.act; + let commentBody = context.payload.comment?.body || ''; + + if (localRun) + console.log("Setting the command as a mock since it's running locally with ACT"); + console.log(`Comment received: ${commentBody}`); + + // Initialize variables + let environment = ''; + let project = ''; + let infra = ''; + + // Parse environment + const environmentMatch = commentBody.match(/--environment\s+([a-zA-Z0-9_-]+)/); + if (environmentMatch) { + environment = environmentMatch[1]; + console.log(`Environment: ${environment}`); + } + + // Parse project + const projectMatch = commentBody.match(/--project\s+([a-zA-Z0-9_-]+)/); + if (projectMatch) { + project = projectMatch[1]; + console.log(`Project: ${project}`); + } else { + core.setFailed("No project specified. Aborting workflow."); + return; + } + + // Parse infra + const infraMatch = commentBody.match(/--infra\s+([a-zA-Z0-9_-]+)/); + if (infraMatch) { + infra = infraMatch[1]; + console.log(`Infra: ${infra}`); + } + + // Set outputs + core.setOutput("environment", environment); + core.setOutput("project", project); + core.setOutput("infra", infra); +}; \ No newline at end of file diff --git a/actions_scripts/update_pr_comment.js b/actions_scripts/update_pr_comment.js deleted file mode 100644 index e69de29..0000000 From abadcb07920fcf778198d9b48ec881cda3fd0e64 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Sat, 28 Dec 2024 12:02:53 +0100 Subject: [PATCH 27/30] ci: refactoring the update-pr-comment-step from inlined on yml to JS (ES) module --- .github/workflows/deploy-chatbot.yml | 50 +++++++++------------------- actions_scripts/helpers.js | 16 ++++++++- actions_scripts/update_pr_comment.js | 34 +++++++++++++++++++ 3 files changed, 64 insertions(+), 36 deletions(-) create mode 100644 actions_scripts/update_pr_comment.js diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 2ba7f28..f2c1007 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -14,7 +14,7 @@ jobs: - name: Parse Deployment Command uses: actions/github-script@v7 - id: parse-command + id: parse_command with: script: | const { default: parseDeployCommand } = await import('${{ github.workspace }}/actions_scripts/parse_deployment_command.js') @@ -31,24 +31,24 @@ jobs: - name: Notify the user uses: actions/github-script@v7 - id: notify-user + id: notify_user with: script: | - const environment = `${{ steps.parse-command.outputs.environment }}`; - const project = `${{ steps.parse-command.outputs.project }}`; - const infra = `${{ steps.parse-command.outputs.infra }}`; + const environment = `${{ steps.parse_command.outputs.environment }}`; + const project = `${{ steps.parse_command.outputs.project }}`; + const infra = `${{ steps.parse_command.outputs.infra }}`; const { default: notifyUser } = await import('${{ github.workspace }}/actions_scripts/notify_user.js') return await notifyUser({github, context, environment, project, infra}) - name: Trigger Deployment Workflow uses: actions/github-script@v7 - id: trigger-deployment-workflow + id: trigger_deployment_workflow with: github-token: ${{ steps.zdc-auth-app-token.outputs.token || github.token }} script: | - const environment = `${{ steps.parse-command.outputs.environment }}`; - const project = `${{ steps.parse-command.outputs.project }}`; + const environment = `${{ steps.parse_command.outputs.environment }}`; + const project = `${{ steps.parse_command.outputs.project }}`; const workflowId = `deploy-${environment}.yml`; let result = ""; @@ -77,14 +77,14 @@ jobs: }; - name: Deploy Infra - if: steps.parse-command.outputs.infra != '' + if: steps.parse_command.outputs.infra != '' uses: appleboy/ssh-action@v1.2.0 with: host: ${{ secrets.SSH_HOST }} username: ${{ secrets.SSH_USERNAME }} key: ${{ secrets.SSH_KEY }} script: | - case "${{ steps.parse-command.outputs.infra }}" in + case "${{ steps.parse_command.outputs.infra }}" in postgres) echo "Deploying Postgres..." docker run -d --name postgres --restart always -e POSTGRES_PASSWORD=mysecretpassword postgres @@ -99,7 +99,7 @@ jobs: docker run -d --name redis --restart always redis ;; *) - echo "Unknown infra: ${{ steps.parse-command.outputs.infra }}" + echo "Unknown infra: ${{ steps.parse_command.outputs.infra }}" ;; esac @@ -108,29 +108,9 @@ jobs: id: update-comment-with-deployment-status with: script: | - const workflowLocalRun = `${{ github.event.act }}` === 'true'; + const steps = ${{ toJSON(steps) }}; - const commentOnPr = ${{ steps.notify-user.outputs.result }}; - const commentId = commentOnPr.comment_id; + const { default: updatePrComment } = + await import('${{ github.workspace }}/actions_scripts/update_pr_comment.js') - const workflowDetails = ${{ steps.trigger-deployment-workflow.outputs.result }}; - - const owner = `${{ github.event.repository.owner.login }}`; - const project = `${{ steps.parse-command.outputs.project }}`; - const runUrl = `https://github.com/${owner}/${project}/actions`; - - const statusIcon = workflowDetails.status === 'OK' ? '✅' : '❌'; - const statusMsg = workflowDetails.details; - - const previousMsgData = commentOnPr.message; - const message = `${previousMsgData}\n${statusIcon} Deployment ${statusMsg}. [View Workflow](${runUrl})`; - console.log(message); - - if (!workflowLocalRun) { - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: commentId, - body: message, - }); - } + await updatePrComment(github, context, steps) \ No newline at end of file diff --git a/actions_scripts/helpers.js b/actions_scripts/helpers.js index edad459..a2d155d 100644 --- a/actions_scripts/helpers.js +++ b/actions_scripts/helpers.js @@ -17,7 +17,7 @@ export function ciLocalRun(context) { * Get the username of the actor from the context. * @param {Object} context - GitHub Actions context object. * @returns {string} - The username of the actor. - * @throws {Error} - if the parsed actor text is non validdfd + * @throws {Error} - if the parsed actor text is non valid */ export function extractUsername(context) { const actor = context.actor; @@ -25,4 +25,18 @@ export function extractUsername(context) { return actor; else throw new Error("Unable to determine the actor (user) that triggered this deploy. Leaving..."); +} + +// Helper function to retrieve the owner of the repository in which the action has been triggered. +/** + * Get the username of the actor from the context. + * @param {Object} context - GitHub Actions context object. + * @returns {string} - The owner of the repository. + */ +export function getRepoOwner(context) { + const owner = context.payload.organization.login; + if (owner !== undefined && owner !== "") + return owner; + else + throw new Error("Unable to parse the owner name of the repository. Leaving..."); } \ No newline at end of file diff --git a/actions_scripts/update_pr_comment.js b/actions_scripts/update_pr_comment.js new file mode 100644 index 0000000..2c8f7e1 --- /dev/null +++ b/actions_scripts/update_pr_comment.js @@ -0,0 +1,34 @@ +import { ciLocalRun, getRepoOwner } from "./helpers.js"; + +/** + * Takes the previous posted message as a comment on the PR that triggered + * the deploy command in order to add it the status of the deployment to + * that message + */ +export default async (github, context, steps) => { + const isLocalRun = ciLocalRun(context); + + const repoOwner = getRepoOwner(context); + const targetRepo = steps.parse_command.outputs.project; + + const previousPrComment = JSON.parse(steps.notify_user.outputs.result); + const commentId = previousPrComment.comment_id; + const runUrl = `https://github.com/${repoOwner}/${targetRepo}/actions`; + + const workflowExecution = JSON.parse(steps.trigger_deployment_workflow.outputs.result); + const statusIcon = workflowExecution.status === 'OK' ? '✅' : '❌'; + const statusMsg = workflowExecution.details; + + const previousMsgData = previousPrComment.message; + const message = `${previousMsgData}\n${statusIcon} Deployment ${statusMsg}. [View Workflow](${runUrl})`; + console.log(`Message: ${message}`); + + if (!isLocalRun) { + await github.rest.issues.updateComment({ + owner: repoOwner, + repo: context.repo.repo, + comment_id: commentId, + body: message, + }); + } +} \ No newline at end of file From b5142fb19c9daa8494f2b0fe4ec3c952b4fc09d0 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Sat, 28 Dec 2024 12:06:47 +0100 Subject: [PATCH 28/30] ci: refactoring the update-pr-comment-step from inlined on yml to JS (ES) module --- .github/workflows/deploy-chatbot.yml | 6 ++++-- actions_scripts/notify_user.js | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index f2c1007..8eb84ec 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -38,8 +38,10 @@ jobs: const project = `${{ steps.parse_command.outputs.project }}`; const infra = `${{ steps.parse_command.outputs.infra }}`; - const { default: notifyUser } = await import('${{ github.workspace }}/actions_scripts/notify_user.js') - return await notifyUser({github, context, environment, project, infra}) + const { default: notifyUser } = + await import('${{ github.workspace }}/actions_scripts/notify_user.js') + + return await notifyUser(github, context, steps) - name: Trigger Deployment Workflow uses: actions/github-script@v7 diff --git a/actions_scripts/notify_user.js b/actions_scripts/notify_user.js index 3290e73..c399b17 100644 --- a/actions_scripts/notify_user.js +++ b/actions_scripts/notify_user.js @@ -10,7 +10,9 @@ import { ciLocalRun, extractUsername } from "./helpers.js"; * @param {string} options.infra - Infrastructure type (e.g., postgres, redis). * @returns {Object} - An object containing the comment ID and the message content. */ -export default async ({ github, context, environment, project, infra }) => { +export default async (options) => { + const { github, context, environment, project, infra } = options; + const isLocalRun = ciLocalRun(context); const username = extractUsername(context); From 3c2483aca563d377d89ab395de12ec89881727b9 Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Sat, 28 Dec 2024 12:11:03 +0100 Subject: [PATCH 29/30] ci: minor code fmt and refactors --- .github/workflows/deploy-chatbot.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index 8eb84ec..bb851b9 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -17,8 +17,10 @@ jobs: id: parse_command with: script: | - const { default: parseDeployCommand } = await import('${{ github.workspace }}/actions_scripts/parse_deployment_command.js') - parseDeployCommand({context, core}) + const { default: parseDeployCommand } = + await import('${{ github.workspace }}/actions_scripts/parse_deployment_command.js'); + + parseDeployCommand({context, core}); - name: Get GH Zero Day Code APP token if: ${{ !github.event.act }} @@ -39,9 +41,9 @@ jobs: const infra = `${{ steps.parse_command.outputs.infra }}`; const { default: notifyUser } = - await import('${{ github.workspace }}/actions_scripts/notify_user.js') + await import('${{ github.workspace }}/actions_scripts/notify_user.js'); - return await notifyUser(github, context, steps) + return await notifyUser({github, context, environment, project, infra}); - name: Trigger Deployment Workflow uses: actions/github-script@v7 @@ -113,6 +115,6 @@ jobs: const steps = ${{ toJSON(steps) }}; const { default: updatePrComment } = - await import('${{ github.workspace }}/actions_scripts/update_pr_comment.js') + await import('${{ github.workspace }}/actions_scripts/update_pr_comment.js'); - await updatePrComment(github, context, steps) \ No newline at end of file + await updatePrComment(github, context, steps); \ No newline at end of file From dffea0726dc06ed0339fea5cec03b3048d02e42b Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Sat, 28 Dec 2024 12:23:52 +0100 Subject: [PATCH 30/30] ci: core.setFailed on the catch of REST requests --- .github/workflows/deploy-chatbot.yml | 2 +- actions_scripts/notify_user.js | 12 ++++++------ actions_scripts/update_pr_comment.js | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/deploy-chatbot.yml b/.github/workflows/deploy-chatbot.yml index bb851b9..61d75f7 100644 --- a/.github/workflows/deploy-chatbot.yml +++ b/.github/workflows/deploy-chatbot.yml @@ -43,7 +43,7 @@ jobs: const { default: notifyUser } = await import('${{ github.workspace }}/actions_scripts/notify_user.js'); - return await notifyUser({github, context, environment, project, infra}); + return await notifyUser({github, context, core, environment, project, infra}); - name: Trigger Deployment Workflow uses: actions/github-script@v7 diff --git a/actions_scripts/notify_user.js b/actions_scripts/notify_user.js index c399b17..3d4c3b9 100644 --- a/actions_scripts/notify_user.js +++ b/actions_scripts/notify_user.js @@ -5,14 +5,15 @@ import { ciLocalRun, extractUsername } from "./helpers.js"; * @param {Object} options - The options for the notification. * @param {Object} options.github - GitHub API client provided by actions/github-script. * @param {Object} options.context - Context object from GitHub Actions, containing payload and environment details. + * @param {Object} options.core - Core object from GitHub Actions, containing actions to perform over the workflow. * @param {string} options.environment - Deployment environment (e.g., pre, prod). * @param {string} options.project - Project name associated with the deployment. * @param {string} options.infra - Infrastructure type (e.g., postgres, redis). * @returns {Object} - An object containing the comment ID and the message content. */ export default async (options) => { - const { github, context, environment, project, infra } = options; - + const { github, context, core, environment, project, infra } = options; + const isLocalRun = ciLocalRun(context); const username = extractUsername(context); @@ -22,14 +23,13 @@ export default async (options) => { if (isLocalRun) { logMessageOnLocalEnv(message); // Return a mock comment ID for local testing purposes. - return { comment_id: 1010101010, message: message }; + return { id: 1010101010, message: message }; } else { try { const comment = await createPrComment(github, context, prNumber, message); - return { comment_id: comment.data.id, message: message }; + return { id: comment.data.id, message: message }; } catch (ex) { - console.log("Failed to POST the comment on the PR to notify the user due to =[> " + ex + "]"); - return { comment_id: null }; + core.setFailed("Failed to POST the comment on the PR to notify the user due to =[> " + ex + "]"); } } }; diff --git a/actions_scripts/update_pr_comment.js b/actions_scripts/update_pr_comment.js index 2c8f7e1..0d2c14d 100644 --- a/actions_scripts/update_pr_comment.js +++ b/actions_scripts/update_pr_comment.js @@ -12,7 +12,7 @@ export default async (github, context, steps) => { const targetRepo = steps.parse_command.outputs.project; const previousPrComment = JSON.parse(steps.notify_user.outputs.result); - const commentId = previousPrComment.comment_id; + const commentId = previousPrComment.id; const runUrl = `https://github.com/${repoOwner}/${targetRepo}/actions`; const workflowExecution = JSON.parse(steps.trigger_deployment_workflow.outputs.result); @@ -27,7 +27,7 @@ export default async (github, context, steps) => { await github.rest.issues.updateComment({ owner: repoOwner, repo: context.repo.repo, - comment_id: commentId, + id: commentId, body: message, }); }