diff --git a/.github/workflows/add-comment-on-pr-creation.yml b/.github/workflows/add-comment-on-pr-creation.yml index bd4b69de..eef586a6 100644 --- a/.github/workflows/add-comment-on-pr-creation.yml +++ b/.github/workflows/add-comment-on-pr-creation.yml @@ -1,20 +1,30 @@ -name: Add helper Comment on PR creation +name: Add Comment on PR Creation on: pull_request: types: [opened] jobs: - comment-on-pr: + add-comment: runs-on: ubuntu-latest + permissions: + pull-requests: write steps: - - name: Add GitHub Comment for review app instructions + name: Add GitHub Comment for review app instructions uses: actions/github-script@v7 with: script: | - github.rest.issues.createComment({ - issue_number: context.issue.number, + await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, - body: "Hi 👋 To deploy a review app, please comment `/deploy-review-app`" - }) + issue_number: context.payload.pull_request.number, + body: [ + "Hi 👋 Here are the commands available for this PR:", + "", + "- `/deploy-review-app`: Deploy your changes to a review environment", + "- `/delete-review-app`: Clean up the review environment when you're done", + "- `/help`: Show detailed information about all commands", + "", + "Use `/help` to see full documentation, including configuration options." + ].join("\n") + }); diff --git a/.github/workflows/delete-review-app.yml b/.github/workflows/delete-review-app.yml index 074b7c7e..caf90b18 100644 --- a/.github/workflows/delete-review-app.yml +++ b/.github/workflows/delete-review-app.yml @@ -1,6 +1,8 @@ name: Delete Review App on: + pull_request: + types: [closed] issue_comment: types: [created] @@ -13,33 +15,17 @@ permissions: env: CPLN_ORG: ${{ secrets.CPLN_ORG }} CPLN_TOKEN: ${{ secrets.CPLN_TOKEN }} - APP_NAME: qa-react-webpack-rails-tutorial-pr-${{ github.event.issue.number }} - PR_NUMBER: ${{ github.event.issue.number }} + APP_NAME: qa-react-webpack-rails-tutorial-pr-${{ github.event.pull_request.number || github.event.issue.number }} + PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} jobs: - debug-trigger: - if: always() - runs-on: ubuntu-latest - steps: - - name: Debug Trigger Conditions - env: - EVENT_NAME: ${{ github.event_name }} - IS_PR: ${{ toJSON(github.event.issue.pull_request) }} - COMMENT: ${{ github.event.comment.body }} - run: | - echo "Debug information for delete-review-app command:" - echo "Event name: $EVENT_NAME" - echo "Is PR (raw): $IS_PR" - echo "Comment body: $COMMENT" - echo "Raw event payload:" - echo '${{ toJSON(github.event) }}' - Process-Delete-Command: - needs: debug-trigger if: | - github.event_name == 'issue_comment' && - github.event.issue.pull_request && - github.event.comment.body == '/delete-review-app' + (github.event_name == 'issue_comment' && + github.event.issue.pull_request && + github.event.comment.body == '/delete-review-app') || + (github.event_name == 'pull_request' && + github.event.action == 'closed') runs-on: ubuntu-latest steps: @@ -55,23 +41,91 @@ jobs: done if [ ${#missing_secrets[@]} -ne 0 ]; then - echo " Required secrets are not set: ${missing_secrets[*]}" + echo "Required secrets are not set: ${missing_secrets[*]}" exit 1 fi - name: Setup Environment uses: ./.github/actions/setup-environment + - name: Set shared functions + id: shared-functions + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('GET_CONSOLE_LINK', ` + function getConsoleLink(prNumber) { + return ' [Control Plane Console for Review App with PR #' + prNumber + '](' + + 'https://console.cpln.io/org/' + process.env.CPLN_ORG + '/workloads/' + process.env.APP_NAME + ')'; + } + `); + + - name: Initialize Delete + id: init-delete + uses: actions/github-script@v7 + with: + script: | + eval(process.env.GET_CONSOLE_LINK); + + async function getWorkflowUrl(runId) { + // Get the current job ID + const jobs = await github.rest.actions.listJobsForWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: runId + }); + + const currentJob = jobs.data.jobs.find(job => job.status === 'in_progress'); + const jobId = currentJob?.id; + + if (!jobId) { + console.log('Warning: Could not find current job ID'); + return `${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}`; + } + + return `${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}/job/${jobId}`; + } + + const workflowUrl = await getWorkflowUrl(context.runId); + + const comment = await github.rest.issues.createComment({ + issue_number: process.env.PR_NUMBER, + owner: context.repo.owner, + repo: context.repo.repo, + body: [ + ' Starting app deletion...', + '', + ' [View Delete Logs](' + workflowUrl + ')', + '', + getConsoleLink(process.env.PR_NUMBER) + ].join('\n') + }); + + return { + commentId: comment.data.id, + workflowUrl + }; + + - name: Set workflow URL + run: | + echo "WORKFLOW_URL=${{ fromJSON(steps.init-delete.outputs.result).workflowUrl }}" >> $GITHUB_ENV + - name: Create Initial Delete Comment id: init-delete uses: actions/github-script@v7 with: script: | + let message = '🗑️ Starting app deletion'; + if ('${{ github.event_name }}' === 'pull_request') { + const merged = '${{ github.event.pull_request.merged }}' === 'true'; + message += merged ? ' (PR merged)' : ' (PR closed)'; + } + const comment = await github.rest.issues.createComment({ issue_number: process.env.PR_NUMBER, owner: context.repo.owner, repo: context.repo.repo, - body: ' Starting app deletion...' + body: message }); return { commentId: comment.data.id }; @@ -89,21 +143,28 @@ jobs: uses: actions/github-script@v7 with: script: | + eval(process.env.GET_CONSOLE_LINK); + const success = '${{ job.status }}' === 'success'; const prNumber = process.env.PR_NUMBER; - const cpConsoleUrl = `https://console.cpln.io/org/${process.env.CPLN_ORG}/workloads/${process.env.APP_NAME}`; - const message = success - ? ' Review app for PR #' + prNumber + ' was successfully deleted' - : [ - ' Review app for PR #' + prNumber + ' failed to be deleted', - '', - '[Control Plane Console for Review App with PR #' + prNumber + '](' + cpConsoleUrl + ')' - ].join('\n'); + const successMessage = [ + '✅ Review app for PR #' + prNumber + ' was successfully deleted', + '', + ' [View Completed Delete Logs](' + process.env.WORKFLOW_URL + ')' + ].join('\n'); + + const failureMessage = [ + '❌ Review app for PR #' + prNumber + ' failed to be deleted', + '', + ' [View Delete Logs with Errors](' + process.env.WORKFLOW_URL + ')', + '', + getConsoleLink(prNumber) + ].join('\n'); await github.rest.issues.updateComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: ${{ fromJSON(steps.init-delete.outputs.result).commentId }}, - body: message + body: success ? successMessage : failureMessage }); diff --git a/.github/workflows/deploy-to-control-plane.yml b/.github/workflows/deploy-to-control-plane.yml index ad1dbb49..2adad3d7 100644 --- a/.github/workflows/deploy-to-control-plane.yml +++ b/.github/workflows/deploy-to-control-plane.yml @@ -25,7 +25,7 @@ jobs: (github.event_name == 'pull_request') || (github.event_name == 'issue_comment' && github.event.issue.pull_request && - github.event.comment.body == '/deploy') + github.event.comment.body == '/deploy-review-app') runs-on: ubuntu-latest permissions: contents: read @@ -252,25 +252,7 @@ jobs: body: isSuccess ? successMessage : failureMessage }); - debug-help: - if: always() - runs-on: ubuntu-latest - steps: - - name: Debug Trigger Conditions - env: - EVENT_NAME: ${{ github.event_name }} - IS_PR: ${{ toJSON(github.event.issue.pull_request) }} - COMMENT: ${{ github.event.comment.body }} - run: | - echo "Debug information for help command:" - echo "Event name: $EVENT_NAME" - echo "Is PR (raw): $IS_PR" - echo "Comment body: $COMMENT" - echo "Raw event payload:" - echo '${{ toJSON(github.event) }}' - show-help: - needs: debug-help if: | github.event_name == 'issue_comment' && github.event.issue.pull_request && @@ -285,7 +267,7 @@ jobs: const helpMessage = [ '## Available Commands', '', - '### `/deploy`', + '### `/deploy-review-app`', 'Deploys your PR branch to a review environment on Control Plane.', '- Creates a new review app if one doesn\'t exist', '- Updates the existing review app if it already exists', @@ -296,7 +278,7 @@ jobs: 'Deletes the review app associated with this PR.', '- Removes all resources from Control Plane', '- Helpful for cleaning up when you\'re done testing', - '- Can be re-deployed later using `/deploy`', + '- Can be re-deployed later using `/deploy-review-app`', '', '### `/help`', 'Shows this help message explaining available commands.', @@ -310,95 +292,4 @@ jobs: repo: context.repo.repo, issue_number: context.payload.issue.number, body: helpMessage - }); - - debug-delete: - if: always() - runs-on: ubuntu-latest - steps: - - name: Debug Trigger Conditions - env: - EVENT_NAME: ${{ github.event_name }} - IS_PR: ${{ toJSON(github.event.issue.pull_request) }} - COMMENT: ${{ github.event.comment.body }} - run: | - echo "Debug information for delete-review-app command:" - echo "Event name: $EVENT_NAME" - echo "Is PR (raw): $IS_PR" - echo "Comment body: $COMMENT" - echo "Raw event payload:" - echo '${{ toJSON(github.event) }}' - - Process-Delete-Command: - needs: debug-delete - if: | - github.event_name == 'issue_comment' && - github.event.issue.pull_request && - github.event.comment.body == '/delete-review-app' - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Validate Required Secrets - run: | - missing_secrets=() - for secret in "CPLN_TOKEN" "CPLN_ORG"; do - if [ -z "${!secret}" ]; then - missing_secrets+=("$secret") - fi - done - - if [ ${#missing_secrets[@]} -ne 0 ]; then - echo "Required secrets are not set: ${missing_secrets[*]}" - exit 1 - fi - - - name: Setup Environment - uses: ./.github/actions/setup-environment - - - name: Create Initial Delete Comment - id: init-delete - uses: actions/github-script@v7 - with: - script: | - const comment = await github.rest.issues.createComment({ - issue_number: process.env.PR_NUMBER, - owner: context.repo.owner, - repo: context.repo.repo, - body: ' Starting app deletion...' - }); - return { commentId: comment.data.id }; - - - name: Delete Review App - uses: ./.github/actions/delete-control-plane-app - with: - app_name: ${{ env.APP_NAME }} - org: ${{ env.CPLN_ORG }} - github_token: ${{ secrets.GITHUB_TOKEN }} - env: - CPLN_TOKEN: ${{ secrets.CPLN_TOKEN }} - - - name: Update Delete Status - if: always() - uses: actions/github-script@v7 - with: - script: | - const success = '${{ job.status }}' === 'success'; - const prNumber = process.env.PR_NUMBER; - const cpConsoleUrl = `https://console.cpln.io/org/${process.env.CPLN_ORG}/workloads/${process.env.APP_NAME}`; - - const message = success - ? ' Review app for PR #' + prNumber + ' was successfully deleted' - : [ - ' Review app for PR #' + prNumber + ' failed to be deleted', - '', - ' [Control Plane Console for Review App with PR #' + prNumber + '](' + cpConsoleUrl + ')' - ].join('\n'); - - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: ${{ fromJSON(steps.init-delete.outputs.result).commentId }}, - body: message }); \ No newline at end of file diff --git a/.github/workflows/help-command.yml b/.github/workflows/help-command.yml index 20a0e828..ff59b65f 100644 --- a/.github/workflows/help-command.yml +++ b/.github/workflows/help-command.yml @@ -4,30 +4,17 @@ on: issue_comment: types: [created] +# Use concurrency to prevent duplicate runs +concurrency: + group: help-${{ github.event.issue.number }} + cancel-in-progress: true + permissions: issues: write pull-requests: write jobs: - debug-trigger: - if: always() - runs-on: ubuntu-latest - steps: - - name: Debug Trigger Conditions - env: - EVENT_NAME: ${{ github.event_name }} - IS_PR: ${{ toJSON(github.event.issue.pull_request) }} - COMMENT: ${{ github.event.comment.body }} - run: | - echo "Debug information for help command:" - echo "Event name: $EVENT_NAME" - echo "Is PR (raw): $IS_PR" - echo "Comment body: $COMMENT" - echo "Raw event payload:" - echo '${{ toJSON(github.event) }}' - show-help: - needs: debug-trigger if: | github.event_name == 'issue_comment' && github.event.issue.pull_request && @@ -39,52 +26,64 @@ jobs: uses: actions/github-script@v7 with: script: | - const helpMessage = [ - '## 📚 Available Commands', - '', - '### `/deploy`', - 'Deploys your PR branch to a review environment on Control Plane.', - '- Creates a new review app if one doesn\'t exist', - '- Updates the existing review app if it already exists', - '- Provides a unique URL to preview your changes', - '- Shows build and deployment progress in real-time', - '', - '**Required Environment Variables:**', - '- `CPLN_TOKEN`: Control Plane authentication token', - '- `CPLN_ORG`: Control Plane organization name', - '', - '**Optional Configuration:**', - '- `WAIT_TIMEOUT`: Deployment timeout in seconds (default: 900)', - ' - Must be a positive integer', - ' - Can be set in GitHub Actions variables', - ' - Applies to both deployment and workload readiness checks', - '', - '### `/delete-review-app`', - 'Deletes the review app associated with this PR.', - '- Removes all resources from Control Plane', - '- Helpful for cleaning up when you\'re done testing', - '- Can be re-deployed later using `/deploy`', - '', - '**Required Environment Variables:**', - '- `CPLN_TOKEN`: Control Plane authentication token', - '- `CPLN_ORG`: Control Plane organization name', - '', - '### `/help`', - 'Shows this help message explaining available commands and configuration.', - '', - '---', - '**Note:** These commands only work in pull request comments.', - '', - '**Environment Setup:**', - '1. Set required secrets in your repository settings:', - ' - `CPLN_TOKEN`', - ' - `CPLN_ORG`', - '2. Optional: Configure `WAIT_TIMEOUT` in GitHub Actions variables to customize deployment timeout' - ].join('\n'); - - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.payload.issue.number, - body: helpMessage - }); + try { + console.log('Creating help message...'); + const helpMessage = [ + '## 📚 Available Commands', + '', + '### `/deploy`', + 'Deploys your PR branch to a review environment on Control Plane.', + '- Creates a new review app if one doesn\'t exist', + '- Updates the existing review app if it already exists', + '- Provides a unique URL to preview your changes', + '- Shows build and deployment progress in real-time', + '', + '**Required Environment Variables:**', + '- `CPLN_TOKEN`: Control Plane authentication token', + '- `CPLN_ORG`: Control Plane organization name', + '', + '**Optional Configuration:**', + '- `WAIT_TIMEOUT`: Deployment timeout in seconds (default: 900)', + ' - Must be a positive integer', + ' - Can be set in GitHub Actions variables', + ' - Applies to both deployment and workload readiness checks', + '', + '### `/delete-review-app`', + 'Deletes the review app associated with this PR.', + '- Removes all resources from Control Plane', + '- Helpful for cleaning up when you\'re done testing', + '- Can be re-deployed later using `/deploy`', + '', + '**Required Environment Variables:**', + '- `CPLN_TOKEN`: Control Plane authentication token', + '- `CPLN_ORG`: Control Plane organization name', + '', + '### `/help`', + 'Shows this help message explaining available commands and configuration.', + '', + '---', + '**Note:** These commands only work in pull request comments.', + '', + '**Environment Setup:**', + '1. Set required secrets in your repository settings:', + ' - `CPLN_TOKEN`', + ' - `CPLN_ORG`', + '2. Optional: Configure `WAIT_TIMEOUT` in GitHub Actions variables to customize deployment timeout' + ].join('\n'); + + console.log('Issue number:', github.context.payload.issue.number); + console.log('Owner:', context.repo.owner); + console.log('Repo:', context.repo.repo); + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: github.context.payload.issue.number, + body: helpMessage + }); + + console.log('Help message posted successfully'); + } catch (error) { + console.error('Error posting help message:', error); + core.setFailed(`Failed to post help message: ${error.message}`); + }