From c31e3d878d9cee404e97e55f2406ede8ab52e566 Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Sun, 26 Jan 2025 16:28:43 -1000 Subject: [PATCH 01/14] Fixed conflicts --- .github/workflows/delete-review-app.yml | 6 +++--- .github/workflows/deploy-to-control-plane.yml | 4 ++-- .github/workflows/help-command.yml | 18 ++---------------- .../promote-staging-to-production.yml | 2 +- 4 files changed, 8 insertions(+), 22 deletions(-) diff --git a/.github/workflows/delete-review-app.yml b/.github/workflows/delete-review-app.yml index fa24902c..5d3fa4b1 100644 --- a/.github/workflows/delete-review-app.yml +++ b/.github/workflows/delete-review-app.yml @@ -14,7 +14,7 @@ permissions: env: CPLN_ORG: ${{ secrets.CPLN_ORG }} - CPLN_TOKEN: ${{ secrets.CPLN_TOKEN }} + CPLN_TOKEN: ${{ secrets.CPLN_TOKEN_STAGING }} 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 }} @@ -34,7 +34,7 @@ jobs: - name: Validate Required Secrets run: | missing_secrets=() - for secret in "CPLN_TOKEN" "CPLN_ORG"; do + for secret in "CPLN_TOKEN_STAGING" "CPLN_ORG_STAGING"; do if [ -z "${!secret}" ]; then missing_secrets+=("$secret") fi @@ -122,7 +122,7 @@ jobs: org: ${{ env.CPLN_ORG }} github_token: ${{ secrets.GITHUB_TOKEN }} env: - CPLN_TOKEN: ${{ secrets.CPLN_TOKEN }} + CPLN_TOKEN: ${{ secrets.CPLN_TOKEN_STAGING }} - name: Update Delete Status if: always() diff --git a/.github/workflows/deploy-to-control-plane.yml b/.github/workflows/deploy-to-control-plane.yml index 9cdc4599..48ae85e9 100644 --- a/.github/workflows/deploy-to-control-plane.yml +++ b/.github/workflows/deploy-to-control-plane.yml @@ -16,8 +16,8 @@ concurrency: cancel-in-progress: true env: - CPLN_ORG: ${{ secrets.CPLN_ORG }} - CPLN_TOKEN: ${{ secrets.CPLN_TOKEN }} + CPLN_ORG: ${{ secrets.CPLN_ORG_STAGING }} + CPLN_TOKEN: ${{ secrets.CPLN_TOKEN_STAGING }} jobs: Process-Deployment-Command: diff --git a/.github/workflows/help-command.yml b/.github/workflows/help-command.yml index 8894d034..fee3075a 100644 --- a/.github/workflows/help-command.yml +++ b/.github/workflows/help-command.yml @@ -42,26 +42,12 @@ jobs: '- 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-review-app`', '', - '**Required Environment Variables:**', - '- `CPLN_TOKEN`: Control Plane authentication token', - '- `CPLN_ORG`: Control Plane organization name', - '', '### `/help`', 'Shows this detailed help message.', '', @@ -69,8 +55,8 @@ jobs: '## Environment Setup', '', '1. Set required secrets in your repository settings:', - ' - `CPLN_TOKEN`', - ' - `CPLN_ORG`', + ' - `CPLN_TOKEN_STAGING`', + ' - `CPLN_ORG_STAGING`', '', '2. Optional: Configure `WAIT_TIMEOUT` in GitHub Actions variables to customize deployment timeout', '', diff --git a/.github/workflows/promote-staging-to-production.yml b/.github/workflows/promote-staging-to-production.yml index 04148067..7c456727 100644 --- a/.github/workflows/promote-staging-to-production.yml +++ b/.github/workflows/promote-staging-to-production.yml @@ -25,7 +25,7 @@ jobs: - name: Setup Environment uses: ./.github/actions/setup-environment env: - CPLN_TOKEN: ${{ secrets.CPLN_TOKEN }} + CPLN_TOKEN: ${{ secrets.CPLN_TOKEN_STAGING }} - name: Promote Staging to Production id: promote From a4b0353c0aa7609d2c57aba637bf99d2ccd5d98c Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Sun, 26 Jan 2025 17:18:38 -1000 Subject: [PATCH 02/14] fix-missing-url --- .github/workflows/deploy-to-control-plane.yml | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/.github/workflows/deploy-to-control-plane.yml b/.github/workflows/deploy-to-control-plane.yml index 48ae85e9..de430457 100644 --- a/.github/workflows/deploy-to-control-plane.yml +++ b/.github/workflows/deploy-to-control-plane.yml @@ -148,14 +148,8 @@ jobs: const workflowUrl = await getWorkflowUrl(context.runId); core.exportVariable('WORKFLOW_URL', workflowUrl); - core.exportVariable('GET_CONSOLE_LINK', ` - function getConsoleLink(prNumber) { - return '🎮 [Control Plane Console](' + - 'https://console.cpln.io/console/org/' + process.env.CPLN_ORG + '/gvc/' + process.env.APP_NAME + '/-info)'; - } - `); - - name: Update Status - Building + - name: Set Console Link if: | (github.event_name == 'issue_comment' && github.event.issue.pull_request && @@ -164,14 +158,25 @@ jobs: uses: actions/github-script@v7 with: script: | - eval(process.env.GET_CONSOLE_LINK); + const consoleLink = '🎮 [Control Plane Console](https://console.cpln.io/console/org/' + + process.env.CPLN_ORG + '/gvc/' + process.env.APP_NAME + '/-info)'; + core.exportVariable('CONSOLE_LINK', consoleLink); + - name: Update Status - Building + if: | + (github.event_name == 'issue_comment' && + github.event.issue.pull_request && + github.event.comment.body == '/deploy-review-app') || + (steps.get-pr.outputs.has_pr == 'true' && steps.check-app.outputs.app_exists == 'true') + uses: actions/github-script@v7 + with: + script: | const buildingMessage = [ '🏗️ Building Docker image...', '', '📝 [View Build Logs](' + process.env.WORKFLOW_URL + ')', '', - getConsoleLink(process.env.PR_NUMBER) + process.env.CONSOLE_LINK ].join('\n'); await github.rest.issues.updateComment({ @@ -211,8 +216,6 @@ jobs: uses: actions/github-script@v7 with: script: | - eval(process.env.GET_CONSOLE_LINK); - const deployingMessage = [ '🚀 Deploying to Control Plane...', '', @@ -220,7 +223,7 @@ jobs: '', '📝 [View Deploy Logs](' + process.env.WORKFLOW_URL + ')', '', - getConsoleLink(process.env.PR_NUMBER) + process.env.CONSOLE_LINK ].join('\n'); await github.rest.issues.updateComment({ @@ -236,6 +239,7 @@ jobs: github.event.issue.pull_request && github.event.comment.body == '/deploy-review-app') || (steps.get-pr.outputs.has_pr == 'true' && steps.check-app.outputs.app_exists == 'true') + id: deploy uses: ./.github/actions/deploy-to-control-plane with: app_name: ${{ env.APP_NAME }} @@ -251,16 +255,14 @@ jobs: uses: actions/github-script@v7 with: script: | - eval(process.env.GET_CONSOLE_LINK); - const successMessage = [ '✅ Deployment successful!', '', - '🌐 Review app is ready at: ${{ env.REVIEW_APP_URL }}', + '🌐 Review app is ready at: ${{ steps.deploy.outputs.review_app_url }}', '', '📝 [View App Logs](' + process.env.WORKFLOW_URL + ')', '', - getConsoleLink(process.env.PR_NUMBER) + process.env.CONSOLE_LINK ].join('\n'); await github.rest.issues.updateComment({ From f168a9b7549d0fcdb8de110f1c9aeb4fcd889a9f Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Sun, 26 Jan 2025 17:31:16 -1000 Subject: [PATCH 03/14] fix-missing-url --- .github/workflows/deploy-to-control-plane.yml | 58 +++++++++---------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/.github/workflows/deploy-to-control-plane.yml b/.github/workflows/deploy-to-control-plane.yml index de430457..657c1bde 100644 --- a/.github/workflows/deploy-to-control-plane.yml +++ b/.github/workflows/deploy-to-control-plane.yml @@ -43,32 +43,30 @@ jobs: - name: Setup Environment uses: ./.github/actions/setup-environment - - name: Get PR Number for Push Event - if: github.event_name == 'push' - id: get-pr - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Set PR Number for Comment Event + if: | + (github.event_name == 'issue_comment' && + github.event.issue.pull_request && + github.event.comment.body == '/deploy-review-app') || + github.event_name == 'push' run: | - # Get PR number from branch - PR_NUMBER=$(gh pr list --head ${{ github.ref_name }} --json number --jq '.[0].number') - if [ -n "$PR_NUMBER" ]; then - echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV - echo "APP_NAME=qa-react-webpack-rails-tutorial-pr-$PR_NUMBER" >> $GITHUB_ENV - echo "has_pr=true" >> $GITHUB_OUTPUT + if [ "${{ github.event_name }}" = "issue_comment" ]; then + echo "PR_NUMBER=${{ github.event.issue.number }}" >> $GITHUB_ENV + echo "APP_NAME=qa-react-webpack-rails-tutorial-pr-${{ github.event.issue.number }}" >> $GITHUB_ENV else - echo "No PR found for this branch" - exit 0 + # For push events, get PR number from branch + PR_NUMBER=$(gh pr list --head ${{ github.ref_name }} --json number --jq '.[0].number') + if [ -n "$PR_NUMBER" ]; then + echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV + echo "APP_NAME=qa-react-webpack-rails-tutorial-pr-$PR_NUMBER" >> $GITHUB_ENV + fi fi - - - name: Set PR Number for Comment Event - if: github.event_name == 'issue_comment' - run: | - echo "PR_NUMBER=${{ github.event.issue.number }}" >> $GITHUB_ENV - echo "APP_NAME=qa-react-webpack-rails-tutorial-pr-${{ github.event.issue.number }}" >> $GITHUB_ENV + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Check if Review App Exists id: check-app - if: github.event_name == 'push' && steps.get-pr.outputs.has_pr == 'true' + if: github.event_name == 'push' && github.event_name != 'issue_comment' env: CPLN_TOKEN: ${{ secrets.CPLN_TOKEN }} run: | @@ -84,7 +82,7 @@ jobs: (github.event_name == 'issue_comment' && github.event.issue.pull_request && github.event.comment.body == '/deploy-review-app') || - (steps.get-pr.outputs.has_pr == 'true' && steps.check-app.outputs.app_exists == 'true') + (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') run: | PR_DATA=$(gh pr view ${{ env.PR_NUMBER }} --repo ${{ github.repository }} --json headRefName,headRefOid) echo "PR_REF=$(echo "$PR_DATA" | jq -r '.headRefName')" >> $GITHUB_OUTPUT @@ -97,7 +95,7 @@ jobs: (github.event_name == 'issue_comment' && github.event.issue.pull_request && github.event.comment.body == '/deploy-review-app') || - (steps.get-pr.outputs.has_pr == 'true' && steps.check-app.outputs.app_exists == 'true') + (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') id: create-comment uses: actions/github-script@v7 with: @@ -116,7 +114,7 @@ jobs: (github.event_name == 'issue_comment' && github.event.issue.pull_request && github.event.comment.body == '/deploy-review-app') || - (steps.get-pr.outputs.has_pr == 'true' && steps.check-app.outputs.app_exists == 'true') + (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') run: echo "COMMENT_ID=${{ fromJSON(steps.create-comment.outputs.result).commentId }}" >> $GITHUB_ENV - name: Set Workflow URL @@ -124,7 +122,7 @@ jobs: (github.event_name == 'issue_comment' && github.event.issue.pull_request && github.event.comment.body == '/deploy-review-app') || - (steps.get-pr.outputs.has_pr == 'true' && steps.check-app.outputs.app_exists == 'true') + (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') id: workflow-url uses: actions/github-script@v7 with: @@ -154,7 +152,7 @@ jobs: (github.event_name == 'issue_comment' && github.event.issue.pull_request && github.event.comment.body == '/deploy-review-app') || - (steps.get-pr.outputs.has_pr == 'true' && steps.check-app.outputs.app_exists == 'true') + (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') uses: actions/github-script@v7 with: script: | @@ -167,7 +165,7 @@ jobs: (github.event_name == 'issue_comment' && github.event.issue.pull_request && github.event.comment.body == '/deploy-review-app') || - (steps.get-pr.outputs.has_pr == 'true' && steps.check-app.outputs.app_exists == 'true') + (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') uses: actions/github-script@v7 with: script: | @@ -191,7 +189,7 @@ jobs: (github.event_name == 'issue_comment' && github.event.issue.pull_request && github.event.comment.body == '/deploy-review-app') || - (steps.get-pr.outputs.has_pr == 'true' && steps.check-app.outputs.app_exists == 'true') + (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') run: git checkout ${{ steps.getRef.outputs.PR_REF }} - name: Build Docker Image @@ -199,7 +197,7 @@ jobs: (github.event_name == 'issue_comment' && github.event.issue.pull_request && github.event.comment.body == '/deploy-review-app') || - (steps.get-pr.outputs.has_pr == 'true' && steps.check-app.outputs.app_exists == 'true') + (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') uses: ./.github/actions/build-docker-image with: app_name: ${{ env.APP_NAME }} @@ -212,7 +210,7 @@ jobs: (github.event_name == 'issue_comment' && github.event.issue.pull_request && github.event.comment.body == '/deploy-review-app') || - (steps.get-pr.outputs.has_pr == 'true' && steps.check-app.outputs.app_exists == 'true') + (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') uses: actions/github-script@v7 with: script: | @@ -238,7 +236,7 @@ jobs: (github.event_name == 'issue_comment' && github.event.issue.pull_request && github.event.comment.body == '/deploy-review-app') || - (steps.get-pr.outputs.has_pr == 'true' && steps.check-app.outputs.app_exists == 'true') + (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') id: deploy uses: ./.github/actions/deploy-to-control-plane with: From 3b60bfe1f26561c1845aa72ca0ad078201b0166d Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Sun, 26 Jan 2025 18:58:43 -1000 Subject: [PATCH 04/14] rework-main-job-deploy --- .../deploy-to-control-plane-staging.yml | 32 -- .github/workflows/deploy-to-control-plane.yml | 295 +++++++++--------- 2 files changed, 152 insertions(+), 175 deletions(-) delete mode 100644 .github/workflows/deploy-to-control-plane-staging.yml diff --git a/.github/workflows/deploy-to-control-plane-staging.yml b/.github/workflows/deploy-to-control-plane-staging.yml deleted file mode 100644 index 095c635a..00000000 --- a/.github/workflows/deploy-to-control-plane-staging.yml +++ /dev/null @@ -1,32 +0,0 @@ -# Control Plane GitHub Action - -name: Deploy Main Branch to Control Plane Staging - -# Controls when the workflow will run -on: - # Uncomment the lines you want actions that will cause the workflow to Triggers the workflow on push or pull request events but only for the main branch - push: - branches: [master] - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# Convert the GitHub secret variables to environment variables for use by the Control Plane CLI -env: - CPLN_ORG: ${{secrets.CPLN_ORG_STAGING}} - CPLN_TOKEN: ${{secrets.CPLN_TOKEN_STAGING}} - -jobs: - deploy-to-control-plane-staging: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 # Fetch all history for proper SHA handling - ref: master # Explicitly checkout master branch - - - uses: ./.github/actions/deploy-to-control-plane - with: - app_name: ${{ secrets.APP_NAME_STAGING }} - org: ${{ secrets.CPLN_ORG_STAGING }} diff --git a/.github/workflows/deploy-to-control-plane.yml b/.github/workflows/deploy-to-control-plane.yml index 657c1bde..866ab211 100644 --- a/.github/workflows/deploy-to-control-plane.yml +++ b/.github/workflows/deploy-to-control-plane.yml @@ -1,176 +1,189 @@ -name: Deploy Review App to Control Plane +name: Deploy to Control Plane -run-name: ${{ github.event_name == 'issue_comment' && 'Deploying Review App' || format('Updating Review App for {0}', github.ref_name) }} +run-name: ${{ github.event_name == 'issue_comment' && format('Deploying Review App for {0}', github.ref_name) || github.ref == '${{ steps.default-branch.outputs.name }}' && 'Deploying to Staging' || format('Deploying Review App for {0}', github.ref_name) }} on: issue_comment: types: [created] push: - branches-ignore: - - main # Don't run on main branch pushes - - master # Don't run on master branch pushes + branches: + - '**' # Allow all branches + - '!gh-pages' # Exclude gh-pages if it exists + + # Allow manual triggers + workflow_dispatch: # Use concurrency to cancel in-progress runs concurrency: - group: deploy-pr-${{ github.event.issue.number }} + group: ${{ github.ref == '${{ steps.default-branch.outputs.name }}' && 'deploy-staging' || format('deploy-pr-{0}', github.event.issue.number) }} cancel-in-progress: true -env: - CPLN_ORG: ${{ secrets.CPLN_ORG_STAGING }} - CPLN_TOKEN: ${{ secrets.CPLN_TOKEN_STAGING }} - jobs: - Process-Deployment-Command: + Process-Deployment: # For issue comments, only run on /deploy-review-app command - # For push events, only run if PR exists and has a review app + # For push events, run if it's master branch OR if PR exists and has a review app if: | (github.event_name == 'issue_comment' && github.event.issue.pull_request && github.event.comment.body == '/deploy-review-app') || - github.event_name == 'push' + github.event_name == 'push' || + github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest permissions: contents: read deployments: write pull-requests: write issues: write + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CPLN_ORG: ${{ secrets.CPLN_ORG_STAGING }} + CPLN_TOKEN: ${{ secrets.CPLN_TOKEN_STAGING }} + STAGING_APP_NAME: ${{ secrets.STAGING_APP_NAME }} + REVIEW_APP_PREFIX: ${{ secrets.REVIEW_APP_PREFIX }} + CPLN_APP_NAME: ${{ secrets.CPLN_APP_NAME || github.event.repository.name }} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Setup Environment - uses: ./.github/actions/setup-environment + - name: Verify Environment Variables + run: | + # Required environment variables + : "${CPLN_ORG:?Required environment variable not set}" + : "${CPLN_TOKEN:?Required environment variable not set}" + : "${REVIEW_APP_PREFIX:?Required environment variable not set}" + : "${STAGING_APP_NAME:?Required environment variable not set}" + + echo "All required environment variables are set" - - name: Set PR Number for Comment Event - if: | - (github.event_name == 'issue_comment' && - github.event.issue.pull_request && - github.event.comment.body == '/deploy-review-app') || - github.event_name == 'push' + - name: Setup Deployment Configuration + id: setup run: | - if [ "${{ github.event_name }}" = "issue_comment" ]; then - echo "PR_NUMBER=${{ github.event.issue.number }}" >> $GITHUB_ENV - echo "APP_NAME=qa-react-webpack-rails-tutorial-pr-${{ github.event.issue.number }}" >> $GITHUB_ENV - else - # For push events, get PR number from branch + # Function to set PR deployment environment + setup_pr_deployment() { + local pr_number=$1 + echo "PR_NUMBER=$pr_number" >> $GITHUB_ENV + echo "APP_NAME=${{ env.REVIEW_APP_PREFIX }}-pr-$pr_number" >> $GITHUB_ENV + echo "IS_STAGING=false" >> $GITHUB_ENV + + # Get PR ref and SHA + local pr_data=$(gh pr view $pr_number --repo ${{ github.repository }} --json headRefName,headRefOid) + echo "PR_REF=$(echo "$pr_data" | jq -r '.headRefName')" >> $GITHUB_OUTPUT + echo "PR_SHA=$(echo "$pr_data" | jq -r '.headRefOid')" >> $GITHUB_OUTPUT + } + + # Function to check if app exists + check_app_exists() { + local app_name=$1 + cpln workload get "$app_name" --org "${{ env.CPLN_ORG }}" > /dev/null 2>&1 + } + + # Function to exit with message when deployment is not needed + no_deployment() { + local message=$1 + echo "SHOULD_DEPLOY=false" >> $GITHUB_OUTPUT + echo "$message" + exit 0 + } + + # Get default branch + DEFAULT_BRANCH="refs/heads/$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name')" + echo "DEFAULT_BRANCH=$DEFAULT_BRANCH" >> $GITHUB_OUTPUT + + # Check if we should deploy + if [[ "${{ github.ref }}" == "$DEFAULT_BRANCH" ]]; then + echo "SHOULD_DEPLOY=true" >> $GITHUB_OUTPUT + echo "IS_STAGING=true" >> $GITHUB_ENV + echo "APP_NAME=${{ env.STAGING_APP_NAME }}" >> $GITHUB_ENV + elif [[ "${{ github.event_name }}" == "issue_comment" && + "${{ github.event.issue.pull_request }}" == "true" && + "${{ github.event.comment.body }}" == "/deploy-review-app" ]]; then + echo "SHOULD_DEPLOY=true" >> $GITHUB_OUTPUT + setup_pr_deployment "${{ github.event.issue.number }}" + elif [[ "${{ github.event_name }}" == "push" ]]; then PR_NUMBER=$(gh pr list --head ${{ github.ref_name }} --json number --jq '.[0].number') if [ -n "$PR_NUMBER" ]; then - echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV - echo "APP_NAME=qa-react-webpack-rails-tutorial-pr-$PR_NUMBER" >> $GITHUB_ENV + APP_NAME="${{ env.REVIEW_APP_PREFIX }}-pr-$PR_NUMBER" + if check_app_exists "$APP_NAME"; then + echo "SHOULD_DEPLOY=true" >> $GITHUB_OUTPUT + setup_pr_deployment "$PR_NUMBER" + else + no_deployment "No existing review app found for PR $PR_NUMBER" + fi + else + no_deployment "No PR found for this branch" fi + else + no_deployment "No deployment needed for this event" fi - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Check if Review App Exists - id: check-app - if: github.event_name == 'push' && github.event_name != 'issue_comment' - env: - CPLN_TOKEN: ${{ secrets.CPLN_TOKEN }} - run: | - if ! cpflow exists -a ${{ env.APP_NAME }}; then - echo "No review app exists for this PR" - exit 0 - fi - echo "app_exists=true" >> $GITHUB_OUTPUT - - name: Get PR HEAD Ref - id: getRef - if: | - (github.event_name == 'issue_comment' && - github.event.issue.pull_request && - github.event.comment.body == '/deploy-review-app') || - (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') - run: | - PR_DATA=$(gh pr view ${{ env.PR_NUMBER }} --repo ${{ github.repository }} --json headRefName,headRefOid) - echo "PR_REF=$(echo "$PR_DATA" | jq -r '.headRefName')" >> $GITHUB_OUTPUT - echo "PR_SHA=$(echo "$PR_DATA" | jq -r '.headRefOid')" >> $GITHUB_OUTPUT - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Create Initial Comment - if: | - (github.event_name == 'issue_comment' && - github.event.issue.pull_request && - github.event.comment.body == '/deploy-review-app') || - (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') - id: create-comment - uses: actions/github-script@v7 - with: - script: | - const result = await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: process.env.PR_NUMBER, - body: '🚀 Starting deployment process...' - }); - console.log('Created comment:', result.data.id); - return { commentId: result.data.id }; - - - name: Set Comment ID - if: | - (github.event_name == 'issue_comment' && - github.event.issue.pull_request && - github.event.comment.body == '/deploy-review-app') || - (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') - run: echo "COMMENT_ID=${{ fromJSON(steps.create-comment.outputs.result).commentId }}" >> $GITHUB_ENV + # Set console link after APP_NAME is set + echo "CONSOLE_LINK=[View in Control Plane Console](https://console.cpln.io/org/${{ env.CPLN_ORG }}/workload/$APP_NAME)" >> $GITHUB_ENV - name: Set Workflow URL - if: | - (github.event_name == 'issue_comment' && - github.event.issue.pull_request && - github.event.comment.body == '/deploy-review-app') || - (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') id: workflow-url uses: actions/github-script@v7 with: script: | - async function getWorkflowUrl(runId) { + try { const jobs = await github.rest.actions.listJobsForWorkflowRun({ owner: context.repo.owner, repo: context.repo.repo, - run_id: runId + run_id: context.runId }); - const currentJob = jobs.data.jobs.find(job => job.status === 'in_progress'); + const currentJob = jobs.data.jobs.find(job => job.name === 'Process-Deployment'); + if (!currentJob) { + console.log('Could not find Process-Deployment job, jobs found:', jobs.data.jobs.map(j => j.name)); + } const jobId = currentJob?.id; - if (!jobId) { - return `${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}`; - } + const workflowUrl = jobId + ? `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}/job/${jobId}` + : `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; - return `${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}/job/${jobId}`; + core.exportVariable('WORKFLOW_URL', workflowUrl); + console.log('Set WORKFLOW_URL to:', workflowUrl); + } catch (error) { + console.log('Error getting job details:', error); + // Fallback to run URL + const workflowUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; + core.exportVariable('WORKFLOW_URL', workflowUrl); + console.log('Fallback: Set WORKFLOW_URL to:', workflowUrl); } - - const workflowUrl = await getWorkflowUrl(context.runId); - core.exportVariable('WORKFLOW_URL', workflowUrl); - - name: Set Console Link - if: | - (github.event_name == 'issue_comment' && - github.event.issue.pull_request && - github.event.comment.body == '/deploy-review-app') || - (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') + - name: Create Initial Comment + if: env.IS_STAGING != 'true' + id: create-comment uses: actions/github-script@v7 with: script: | - const consoleLink = '🎮 [Control Plane Console](https://console.cpln.io/console/org/' + - process.env.CPLN_ORG + '/gvc/' + process.env.APP_NAME + '/-info)'; - core.exportVariable('CONSOLE_LINK', consoleLink); + const initialMessage = [ + '🚀 Deploying...', + '', + '📝 [View Deploy Logs](' + process.env.WORKFLOW_URL + ')', + '', + process.env.CONSOLE_LINK + ].join('\n'); + + const comment = await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: process.env.PR_NUMBER, + body: initialMessage + }); + + core.exportVariable('COMMENT_ID', comment.data.id); + console.log('Created comment:', comment.data.id); - name: Update Status - Building - if: | - (github.event_name == 'issue_comment' && - github.event.issue.pull_request && - github.event.comment.body == '/deploy-review-app') || - (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') + if: env.IS_STAGING != 'true' uses: actions/github-script@v7 with: script: | const buildingMessage = [ - '🏗️ Building Docker image...', + '🏗️ Building...', '', '📝 [View Build Logs](' + process.env.WORKFLOW_URL + ')', '', @@ -185,39 +198,23 @@ jobs: }); - name: Checkout PR Branch - if: | - (github.event_name == 'issue_comment' && - github.event.issue.pull_request && - github.event.comment.body == '/deploy-review-app') || - (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') - run: git checkout ${{ steps.getRef.outputs.PR_REF }} + if: env.IS_STAGING != 'true' + run: git checkout ${{ steps.setup.outputs.PR_REF }} - name: Build Docker Image - if: | - (github.event_name == 'issue_comment' && - github.event.issue.pull_request && - github.event.comment.body == '/deploy-review-app') || - (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') uses: ./.github/actions/build-docker-image with: app_name: ${{ env.APP_NAME }} org: ${{ env.CPLN_ORG }} - commit: ${{ steps.getRef.outputs.PR_SHA }} - PR_NUMBER: ${{ env.PR_NUMBER }} + commit: ${{ steps.setup.outputs.PR_SHA }} - name: Update Status - Deploying - if: | - (github.event_name == 'issue_comment' && - github.event.issue.pull_request && - github.event.comment.body == '/deploy-review-app') || - (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') + if: env.IS_STAGING != 'true' uses: actions/github-script@v7 with: script: | const deployingMessage = [ - '🚀 Deploying to Control Plane...', - '', - '⏳ Waiting for deployment to be ready...', + '🚀 Deploying...', '', '📝 [View Deploy Logs](' + process.env.WORKFLOW_URL + ')', '', @@ -232,11 +229,6 @@ jobs: }); - name: Deploy to Control Plane - if: | - (github.event_name == 'issue_comment' && - github.event.issue.pull_request && - github.event.comment.body == '/deploy-review-app') || - (github.event_name == 'push' && steps.check-app.outputs.app_exists == 'true') id: deploy uses: ./.github/actions/deploy-to-control-plane with: @@ -244,19 +236,16 @@ jobs: org: ${{ env.CPLN_ORG }} github_token: ${{ secrets.GITHUB_TOKEN }} wait_timeout: ${{ vars.WAIT_TIMEOUT || 900 }} - env: - CPLN_TOKEN: ${{ env.CPLN_TOKEN }} - PR_NUMBER: ${{ env.PR_NUMBER }} - name: Update Status - Success - if: success() + if: success() && env.IS_STAGING != 'true' uses: actions/github-script@v7 with: script: | const successMessage = [ '✅ Deployment successful!', '', - '🌐 Review app is ready at: ${{ steps.deploy.outputs.review_app_url }}', + '🌐 Review app is ready at: ${{ steps.deploy.outputs.REVIEW_APP_URL }}', '', '📝 [View App Logs](' + process.env.WORKFLOW_URL + ')', '', @@ -269,3 +258,23 @@ jobs: comment_id: process.env.COMMENT_ID, body: successMessage }); + + - name: Update Status - Failure + if: failure() && env.IS_STAGING != 'true' + uses: actions/github-script@v7 + with: + script: | + const failureMessage = [ + '❌ Deployment failed!', + '', + '📝 [View Deploy Logs](' + process.env.WORKFLOW_URL + ')', + '', + process.env.CONSOLE_LINK + ].join('\n'); + + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: process.env.COMMENT_ID, + body: failureMessage + }); From a00b7880ece5b0b33bbabdf5f1b4441e4a45e075 Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Sun, 26 Jan 2025 19:14:47 -1000 Subject: [PATCH 05/14] rework-main-job-deploy --- .github/workflows/deploy-to-control-plane.yml | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/.github/workflows/deploy-to-control-plane.yml b/.github/workflows/deploy-to-control-plane.yml index 866ab211..a3e5dce1 100644 --- a/.github/workflows/deploy-to-control-plane.yml +++ b/.github/workflows/deploy-to-control-plane.yml @@ -1,6 +1,6 @@ name: Deploy to Control Plane -run-name: ${{ github.event_name == 'issue_comment' && format('Deploying Review App for {0}', github.ref_name) || github.ref == '${{ steps.default-branch.outputs.name }}' && 'Deploying to Staging' || format('Deploying Review App for {0}', github.ref_name) }} +run-name: ${{ github.event_name == 'issue_comment' && format('Deploying Review App for {0}', github.ref_name) || github.ref == 'main' && 'Deploying to Staging' || format('Deploying Review App for {0}', github.ref_name) }} on: issue_comment: @@ -15,7 +15,7 @@ on: # Use concurrency to cancel in-progress runs concurrency: - group: ${{ github.ref == '${{ steps.default-branch.outputs.name }}' && 'deploy-staging' || format('deploy-pr-{0}', github.event.issue.number) }} + group: ${{ github.ref == 'main' && 'deploy-staging' || format('deploy-pr-{0}', github.event.issue.number) }} cancel-in-progress: true jobs: @@ -36,11 +36,10 @@ jobs: issues: write env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CPLN_ORG: ${{ secrets.CPLN_ORG_STAGING }} CPLN_TOKEN: ${{ secrets.CPLN_TOKEN_STAGING }} - STAGING_APP_NAME: ${{ secrets.STAGING_APP_NAME }} - REVIEW_APP_PREFIX: ${{ secrets.REVIEW_APP_PREFIX }} - CPLN_APP_NAME: ${{ secrets.CPLN_APP_NAME || github.event.repository.name }} + CPLN_ORG: ${{ secrets.CPLN_ORG_STAGING }} + STAGING_APP_NAME: ${{ vars.STAGING_APP_NAME }} + REVIEW_APP_PREFIX: ${{ vars.REVIEW_APP_PREFIX }} steps: - uses: actions/checkout@v4 @@ -57,6 +56,12 @@ jobs: echo "All required environment variables are set" + - name: Set Default Branch + id: default-branch + run: | + DEFAULT_BRANCH="main" + echo "DEFAULT_BRANCH=$DEFAULT_BRANCH" >> $GITHUB_ENV + - name: Setup Deployment Configuration id: setup run: | @@ -87,12 +92,8 @@ jobs: exit 0 } - # Get default branch - DEFAULT_BRANCH="refs/heads/$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name')" - echo "DEFAULT_BRANCH=$DEFAULT_BRANCH" >> $GITHUB_OUTPUT - # Check if we should deploy - if [[ "${{ github.ref }}" == "$DEFAULT_BRANCH" ]]; then + if [[ "${{ github.ref }}" == "${{ env.DEFAULT_BRANCH }}" ]]; then echo "SHOULD_DEPLOY=true" >> $GITHUB_OUTPUT echo "IS_STAGING=true" >> $GITHUB_ENV echo "APP_NAME=${{ env.STAGING_APP_NAME }}" >> $GITHUB_ENV From dec057b3cd95018271df648636fdee72b99b8c05 Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Sun, 26 Jan 2025 19:17:39 -1000 Subject: [PATCH 06/14] rework-main-job-deploy --- .github/workflows/deploy-to-control-plane.yml | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/.github/workflows/deploy-to-control-plane.yml b/.github/workflows/deploy-to-control-plane.yml index a3e5dce1..ef4bdd09 100644 --- a/.github/workflows/deploy-to-control-plane.yml +++ b/.github/workflows/deploy-to-control-plane.yml @@ -1,6 +1,6 @@ name: Deploy to Control Plane -run-name: ${{ github.event_name == 'issue_comment' && format('Deploying Review App for {0}', github.ref_name) || github.ref == 'main' && 'Deploying to Staging' || format('Deploying Review App for {0}', github.ref_name) }} +run-name: ${{ github.event_name == 'issue_comment' && format('Deploying Review App for {0}', github.ref_name) || github.ref == '${{ steps.default-branch.outputs.name }}' && 'Deploying to Staging' || format('Deploying Review App for {0}', github.ref_name) }} on: issue_comment: @@ -15,7 +15,7 @@ on: # Use concurrency to cancel in-progress runs concurrency: - group: ${{ github.ref == 'main' && 'deploy-staging' || format('deploy-pr-{0}', github.event.issue.number) }} + group: ${{ github.ref == '${{ steps.default-branch.outputs.name }}' && 'deploy-staging' || format('deploy-pr-{0}', github.event.issue.number) }} cancel-in-progress: true jobs: @@ -37,7 +37,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CPLN_TOKEN: ${{ secrets.CPLN_TOKEN_STAGING }} - CPLN_ORG: ${{ secrets.CPLN_ORG_STAGING }} + CPLN_ORG: ${{ vars.CPLN_ORG_STAGING }} STAGING_APP_NAME: ${{ vars.STAGING_APP_NAME }} REVIEW_APP_PREFIX: ${{ vars.REVIEW_APP_PREFIX }} @@ -48,19 +48,16 @@ jobs: - name: Verify Environment Variables run: | - # Required environment variables - : "${CPLN_ORG:?Required environment variable not set}" - : "${CPLN_TOKEN:?Required environment variable not set}" - : "${REVIEW_APP_PREFIX:?Required environment variable not set}" - : "${STAGING_APP_NAME:?Required environment variable not set}" + # Required secrets + : "${GITHUB_TOKEN:?Required secret GITHUB_TOKEN not set}" + : "${CPLN_TOKEN:?Required secret CPLN_TOKEN_STAGING not set}" - echo "All required environment variables are set" - - - name: Set Default Branch - id: default-branch - run: | - DEFAULT_BRANCH="main" - echo "DEFAULT_BRANCH=$DEFAULT_BRANCH" >> $GITHUB_ENV + # Required variables + : "${CPLN_ORG:?Required variable CPLN_ORG_STAGING not set}" + : "${STAGING_APP_NAME:?Required variable STAGING_APP_NAME not set}" + : "${REVIEW_APP_PREFIX:?Required variable REVIEW_APP_PREFIX not set}" + + echo "All required secrets and variables are set" - name: Setup Deployment Configuration id: setup @@ -92,8 +89,12 @@ jobs: exit 0 } + # Get default branch + DEFAULT_BRANCH="refs/heads/$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name')" + echo "DEFAULT_BRANCH=$DEFAULT_BRANCH" >> $GITHUB_OUTPUT + # Check if we should deploy - if [[ "${{ github.ref }}" == "${{ env.DEFAULT_BRANCH }}" ]]; then + if [[ "${{ github.ref }}" == "$DEFAULT_BRANCH" ]]; then echo "SHOULD_DEPLOY=true" >> $GITHUB_OUTPUT echo "IS_STAGING=true" >> $GITHUB_ENV echo "APP_NAME=${{ env.STAGING_APP_NAME }}" >> $GITHUB_ENV From c994d42193c0c8be0c399b4926ca9dead8c0843a Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Sun, 26 Jan 2025 19:20:05 -1000 Subject: [PATCH 07/14] rework-main-job-deploy --- .github/workflows/deploy-to-control-plane.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy-to-control-plane.yml b/.github/workflows/deploy-to-control-plane.yml index ef4bdd09..80a4d8f8 100644 --- a/.github/workflows/deploy-to-control-plane.yml +++ b/.github/workflows/deploy-to-control-plane.yml @@ -48,11 +48,11 @@ jobs: - name: Verify Environment Variables run: | - # Required secrets + # Required actions secrets : "${GITHUB_TOKEN:?Required secret GITHUB_TOKEN not set}" : "${CPLN_TOKEN:?Required secret CPLN_TOKEN_STAGING not set}" - # Required variables + # Required actions variables : "${CPLN_ORG:?Required variable CPLN_ORG_STAGING not set}" : "${STAGING_APP_NAME:?Required variable STAGING_APP_NAME not set}" : "${REVIEW_APP_PREFIX:?Required variable REVIEW_APP_PREFIX not set}" @@ -104,8 +104,12 @@ jobs: echo "SHOULD_DEPLOY=true" >> $GITHUB_OUTPUT setup_pr_deployment "${{ github.event.issue.number }}" elif [[ "${{ github.event_name }}" == "push" ]]; then - PR_NUMBER=$(gh pr list --head ${{ github.ref_name }} --json number --jq '.[0].number') + # Get PR number for the current branch, handling refs/heads/ prefix + BRANCH_NAME="${{ github.ref_name }}" + PR_NUMBER=$(gh pr list --head "$BRANCH_NAME" --json number,state --jq '.[] | select(.state=="OPEN") | .number') + if [ -n "$PR_NUMBER" ]; then + echo "Found PR #$PR_NUMBER for branch $BRANCH_NAME" APP_NAME="${{ env.REVIEW_APP_PREFIX }}-pr-$PR_NUMBER" if check_app_exists "$APP_NAME"; then echo "SHOULD_DEPLOY=true" >> $GITHUB_OUTPUT @@ -114,6 +118,7 @@ jobs: no_deployment "No existing review app found for PR $PR_NUMBER" fi else + echo "No open PR found for branch $BRANCH_NAME" no_deployment "No PR found for this branch" fi else @@ -156,7 +161,7 @@ jobs: } - name: Create Initial Comment - if: env.IS_STAGING != 'true' + if: env.IS_STAGING != 'true' && env.PR_NUMBER != '' id: create-comment uses: actions/github-script@v7 with: From 83cacaf3a1451c93ace746729b9ee866c2fb5558 Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Sun, 26 Jan 2025 19:27:18 -1000 Subject: [PATCH 08/14] rework-main-job-deploy --- .github/workflows/deploy-to-control-plane.yml | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/.github/workflows/deploy-to-control-plane.yml b/.github/workflows/deploy-to-control-plane.yml index 80a4d8f8..c8998ba6 100644 --- a/.github/workflows/deploy-to-control-plane.yml +++ b/.github/workflows/deploy-to-control-plane.yml @@ -59,22 +59,32 @@ jobs: echo "All required secrets and variables are set" + - name: Get PR Number for Push Event + if: github.event_name == 'push' + id: get-pr + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # Get PR number from branch + PR_NUMBER=$(gh pr list --head ${{ github.ref_name }} --json number --jq '.[0].number') + if [ -n "$PR_NUMBER" ]; then + echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV + echo "APP_NAME=${{ env.REVIEW_APP_PREFIX }}-pr-$PR_NUMBER" >> $GITHUB_ENV + echo "has_pr=true" >> $GITHUB_OUTPUT + else + echo "No PR found for this branch" + exit 0 + fi + + - name: Set PR Number for Comment Event + if: github.event_name == 'issue_comment' + run: | + echo "PR_NUMBER=${{ github.event.issue.number }}" >> $GITHUB_ENV + echo "APP_NAME=${{ env.REVIEW_APP_PREFIX }}-pr-${{ github.event.issue.number }}" >> $GITHUB_ENV + - name: Setup Deployment Configuration id: setup run: | - # Function to set PR deployment environment - setup_pr_deployment() { - local pr_number=$1 - echo "PR_NUMBER=$pr_number" >> $GITHUB_ENV - echo "APP_NAME=${{ env.REVIEW_APP_PREFIX }}-pr-$pr_number" >> $GITHUB_ENV - echo "IS_STAGING=false" >> $GITHUB_ENV - - # Get PR ref and SHA - local pr_data=$(gh pr view $pr_number --repo ${{ github.repository }} --json headRefName,headRefOid) - echo "PR_REF=$(echo "$pr_data" | jq -r '.headRefName')" >> $GITHUB_OUTPUT - echo "PR_SHA=$(echo "$pr_data" | jq -r '.headRefOid')" >> $GITHUB_OUTPUT - } - # Function to check if app exists check_app_exists() { local app_name=$1 @@ -93,40 +103,31 @@ jobs: DEFAULT_BRANCH="refs/heads/$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name')" echo "DEFAULT_BRANCH=$DEFAULT_BRANCH" >> $GITHUB_OUTPUT + # Set staging app name if this is the default branch + if [[ "${{ github.ref }}" == "$DEFAULT_BRANCH" ]]; then + echo "APP_NAME=${{ env.STAGING_APP_NAME }}" >> $GITHUB_ENV + echo "IS_STAGING=true" >> $GITHUB_ENV + fi + # Check if we should deploy if [[ "${{ github.ref }}" == "$DEFAULT_BRANCH" ]]; then echo "SHOULD_DEPLOY=true" >> $GITHUB_OUTPUT - echo "IS_STAGING=true" >> $GITHUB_ENV - echo "APP_NAME=${{ env.STAGING_APP_NAME }}" >> $GITHUB_ENV elif [[ "${{ github.event_name }}" == "issue_comment" && "${{ github.event.issue.pull_request }}" == "true" && "${{ github.event.comment.body }}" == "/deploy-review-app" ]]; then echo "SHOULD_DEPLOY=true" >> $GITHUB_OUTPUT - setup_pr_deployment "${{ github.event.issue.number }}" - elif [[ "${{ github.event_name }}" == "push" ]]; then - # Get PR number for the current branch, handling refs/heads/ prefix - BRANCH_NAME="${{ github.ref_name }}" - PR_NUMBER=$(gh pr list --head "$BRANCH_NAME" --json number,state --jq '.[] | select(.state=="OPEN") | .number') - - if [ -n "$PR_NUMBER" ]; then - echo "Found PR #$PR_NUMBER for branch $BRANCH_NAME" - APP_NAME="${{ env.REVIEW_APP_PREFIX }}-pr-$PR_NUMBER" - if check_app_exists "$APP_NAME"; then - echo "SHOULD_DEPLOY=true" >> $GITHUB_OUTPUT - setup_pr_deployment "$PR_NUMBER" - else - no_deployment "No existing review app found for PR $PR_NUMBER" - fi + elif [[ "${{ github.event_name }}" == "push" && "${{ steps.get-pr.outputs.has_pr }}" == "true" ]]; then + if check_app_exists "${{ env.APP_NAME }}"; then + echo "SHOULD_DEPLOY=true" >> $GITHUB_OUTPUT else - echo "No open PR found for branch $BRANCH_NAME" - no_deployment "No PR found for this branch" + no_deployment "No existing review app found for PR ${{ env.PR_NUMBER }}" fi else no_deployment "No deployment needed for this event" fi # Set console link after APP_NAME is set - echo "CONSOLE_LINK=[View in Control Plane Console](https://console.cpln.io/org/${{ env.CPLN_ORG }}/workload/$APP_NAME)" >> $GITHUB_ENV + echo "CONSOLE_LINK=[View in Control Plane Console](https://console.cpln.io/org/${{ env.CPLN_ORG }}/workload/${{ env.APP_NAME }})" >> $GITHUB_ENV - name: Set Workflow URL id: workflow-url @@ -161,7 +162,6 @@ jobs: } - name: Create Initial Comment - if: env.IS_STAGING != 'true' && env.PR_NUMBER != '' id: create-comment uses: actions/github-script@v7 with: From 1601222b4c88c438d4d072fb56c950d86267f7c3 Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Sun, 26 Jan 2025 19:32:38 -1000 Subject: [PATCH 09/14] rework-main-job-deploy --- .github/workflows/deploy-to-control-plane.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/deploy-to-control-plane.yml b/.github/workflows/deploy-to-control-plane.yml index c8998ba6..645caad3 100644 --- a/.github/workflows/deploy-to-control-plane.yml +++ b/.github/workflows/deploy-to-control-plane.yml @@ -59,6 +59,14 @@ jobs: echo "All required secrets and variables are set" + - name: Install Control Plane CLI + run: | + curl -L https://github.com/controlplane-com/cli/releases/latest/download/cpln-linux-amd64.tar.gz | tar xz + sudo mv cpln /usr/local/bin/ + curl -L https://github.com/controlplane-com/cpln-cli-flow/releases/latest/download/cpflow-linux-amd64.tar.gz | tar xz + sudo mv cpflow /usr/local/bin/ + cpln auth token "${{ env.CPLN_TOKEN }}" + - name: Get PR Number for Push Event if: github.event_name == 'push' id: get-pr From 077525e3a288a9960746b9cb31dd249b7748aae3 Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Sun, 26 Jan 2025 19:36:21 -1000 Subject: [PATCH 10/14] rework-main-job-deploy --- .github/workflows/deploy-to-control-plane.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/deploy-to-control-plane.yml b/.github/workflows/deploy-to-control-plane.yml index 645caad3..d43e7a0a 100644 --- a/.github/workflows/deploy-to-control-plane.yml +++ b/.github/workflows/deploy-to-control-plane.yml @@ -59,13 +59,8 @@ jobs: echo "All required secrets and variables are set" - - name: Install Control Plane CLI - run: | - curl -L https://github.com/controlplane-com/cli/releases/latest/download/cpln-linux-amd64.tar.gz | tar xz - sudo mv cpln /usr/local/bin/ - curl -L https://github.com/controlplane-com/cpln-cli-flow/releases/latest/download/cpflow-linux-amd64.tar.gz | tar xz - sudo mv cpflow /usr/local/bin/ - cpln auth token "${{ env.CPLN_TOKEN }}" + - name: Setup Environment + uses: ./.github/actions/setup-environment - name: Get PR Number for Push Event if: github.event_name == 'push' From 103f18d69379c8703d0d61f98eef732196b41556 Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Sun, 26 Jan 2025 19:39:18 -1000 Subject: [PATCH 11/14] updates --- .controlplane/controlplane.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.controlplane/controlplane.yml b/.controlplane/controlplane.yml index 53f68730..f394fe1c 100644 --- a/.controlplane/controlplane.yml +++ b/.controlplane/controlplane.yml @@ -38,7 +38,7 @@ aliases: release_script: release_script.sh apps: - react-webpack-rails-tutorial: + react-webpack-rails-tutorial-production: # Simulate Production Version <<: *common # Don't allow overriding the org and app by ENV vars b/c production is sensitive! From 01d78e050a3a6953559ee0811219bfc2eca08dac Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Sun, 26 Jan 2025 19:43:31 -1000 Subject: [PATCH 12/14] rework-main-job-deploy-experimental-refactor --- .github/workflows/deploy-to-control-plane.yml | 254 ++++-------------- 1 file changed, 57 insertions(+), 197 deletions(-) diff --git a/.github/workflows/deploy-to-control-plane.yml b/.github/workflows/deploy-to-control-plane.yml index d43e7a0a..837fad57 100644 --- a/.github/workflows/deploy-to-control-plane.yml +++ b/.github/workflows/deploy-to-control-plane.yml @@ -19,15 +19,52 @@ concurrency: cancel-in-progress: true jobs: - Process-Deployment: - # For issue comments, only run on /deploy-review-app command - # For push events, run if it's master branch OR if PR exists and has a review app + # Job to handle staging deployments + Deploy-Staging: + if: github.ref == format('refs/heads/{0}', github.event.repository.default_branch) + runs-on: ubuntu-latest + permissions: + contents: read + deployments: write + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CPLN_TOKEN: ${{ secrets.CPLN_TOKEN_STAGING }} + CPLN_ORG: ${{ vars.CPLN_ORG_STAGING }} + STAGING_APP_NAME: ${{ vars.STAGING_APP_NAME }} + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Verify Environment Variables + run: | + # Required actions secrets + : "${GITHUB_TOKEN:?Required secret GITHUB_TOKEN not set}" + : "${CPLN_TOKEN:?Required secret CPLN_TOKEN_STAGING not set}" + + # Required actions variables + : "${CPLN_ORG:?Required variable CPLN_ORG_STAGING not set}" + : "${STAGING_APP_NAME:?Required variable STAGING_APP_NAME not set}" + + - name: Setup Environment + uses: ./.github/actions/setup-environment + + - name: Deploy to Control Plane + id: deploy + uses: ./.github/actions/deploy-to-control-plane + with: + app_name: ${{ env.STAGING_APP_NAME }} + org: ${{ env.CPLN_ORG }} + github_token: ${{ secrets.GITHUB_TOKEN }} + + # Job to handle review app deployments + Deploy-Review-App: if: | (github.event_name == 'issue_comment' && github.event.issue.pull_request && github.event.comment.body == '/deploy-review-app') || - github.event_name == 'push' || - github.event_name == 'workflow_dispatch' + github.event_name == 'push' runs-on: ubuntu-latest permissions: contents: read @@ -38,9 +75,8 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CPLN_TOKEN: ${{ secrets.CPLN_TOKEN_STAGING }} CPLN_ORG: ${{ vars.CPLN_ORG_STAGING }} - STAGING_APP_NAME: ${{ vars.STAGING_APP_NAME }} REVIEW_APP_PREFIX: ${{ vars.REVIEW_APP_PREFIX }} - + steps: - uses: actions/checkout@v4 with: @@ -54,10 +90,7 @@ jobs: # Required actions variables : "${CPLN_ORG:?Required variable CPLN_ORG_STAGING not set}" - : "${STAGING_APP_NAME:?Required variable STAGING_APP_NAME not set}" : "${REVIEW_APP_PREFIX:?Required variable REVIEW_APP_PREFIX not set}" - - echo "All required secrets and variables are set" - name: Setup Environment uses: ./.github/actions/setup-environment @@ -69,10 +102,12 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | # Get PR number from branch - PR_NUMBER=$(gh pr list --head ${{ github.ref_name }} --json number --jq '.[0].number') + PR_DATA=$(gh pr list --head ${{ github.ref_name }} --json number,headRefOid --jq '.[0]') + PR_NUMBER=$(echo "$PR_DATA" | jq -r '.number') if [ -n "$PR_NUMBER" ]; then echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV echo "APP_NAME=${{ env.REVIEW_APP_PREFIX }}-pr-$PR_NUMBER" >> $GITHUB_ENV + echo "COMMIT_SHA=$(echo "$PR_DATA" | jq -r '.headRefOid')" >> $GITHUB_ENV echo "has_pr=true" >> $GITHUB_OUTPUT else echo "No PR found for this branch" @@ -82,209 +117,34 @@ jobs: - name: Set PR Number for Comment Event if: github.event_name == 'issue_comment' run: | + # Get PR data including the commit SHA + PR_DATA=$(gh pr view ${{ github.event.issue.number }} --json headRefOid --jq '.') echo "PR_NUMBER=${{ github.event.issue.number }}" >> $GITHUB_ENV echo "APP_NAME=${{ env.REVIEW_APP_PREFIX }}-pr-${{ github.event.issue.number }}" >> $GITHUB_ENV + echo "COMMIT_SHA=$(echo "$PR_DATA" | jq -r '.headRefOid')" >> $GITHUB_ENV - - name: Setup Deployment Configuration - id: setup + - name: Check Review App Exists + id: check-app run: | - # Function to check if app exists - check_app_exists() { - local app_name=$1 - cpln workload get "$app_name" --org "${{ env.CPLN_ORG }}" > /dev/null 2>&1 - } - - # Function to exit with message when deployment is not needed - no_deployment() { - local message=$1 - echo "SHOULD_DEPLOY=false" >> $GITHUB_OUTPUT - echo "$message" + if ! cpln workload get "${{ env.APP_NAME }}" --org "${{ env.CPLN_ORG }}" > /dev/null 2>&1; then + echo "Review app ${{ env.APP_NAME }} does not exist" exit 0 - } - - # Get default branch - DEFAULT_BRANCH="refs/heads/$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name')" - echo "DEFAULT_BRANCH=$DEFAULT_BRANCH" >> $GITHUB_OUTPUT - - # Set staging app name if this is the default branch - if [[ "${{ github.ref }}" == "$DEFAULT_BRANCH" ]]; then - echo "APP_NAME=${{ env.STAGING_APP_NAME }}" >> $GITHUB_ENV - echo "IS_STAGING=true" >> $GITHUB_ENV - fi - - # Check if we should deploy - if [[ "${{ github.ref }}" == "$DEFAULT_BRANCH" ]]; then - echo "SHOULD_DEPLOY=true" >> $GITHUB_OUTPUT - elif [[ "${{ github.event_name }}" == "issue_comment" && - "${{ github.event.issue.pull_request }}" == "true" && - "${{ github.event.comment.body }}" == "/deploy-review-app" ]]; then - echo "SHOULD_DEPLOY=true" >> $GITHUB_OUTPUT - elif [[ "${{ github.event_name }}" == "push" && "${{ steps.get-pr.outputs.has_pr }}" == "true" ]]; then - if check_app_exists "${{ env.APP_NAME }}"; then - echo "SHOULD_DEPLOY=true" >> $GITHUB_OUTPUT - else - no_deployment "No existing review app found for PR ${{ env.PR_NUMBER }}" - fi - else - no_deployment "No deployment needed for this event" fi - - # Set console link after APP_NAME is set - echo "CONSOLE_LINK=[View in Control Plane Console](https://console.cpln.io/org/${{ env.CPLN_ORG }}/workload/${{ env.APP_NAME }})" >> $GITHUB_ENV - - - name: Set Workflow URL - id: workflow-url - uses: actions/github-script@v7 - with: - script: | - try { - const jobs = await github.rest.actions.listJobsForWorkflowRun({ - owner: context.repo.owner, - repo: context.repo.repo, - run_id: context.runId - }); - - const currentJob = jobs.data.jobs.find(job => job.name === 'Process-Deployment'); - if (!currentJob) { - console.log('Could not find Process-Deployment job, jobs found:', jobs.data.jobs.map(j => j.name)); - } - const jobId = currentJob?.id; - - const workflowUrl = jobId - ? `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}/job/${jobId}` - : `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; - - core.exportVariable('WORKFLOW_URL', workflowUrl); - console.log('Set WORKFLOW_URL to:', workflowUrl); - } catch (error) { - console.log('Error getting job details:', error); - // Fallback to run URL - const workflowUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; - core.exportVariable('WORKFLOW_URL', workflowUrl); - console.log('Fallback: Set WORKFLOW_URL to:', workflowUrl); - } - - - name: Create Initial Comment - id: create-comment - uses: actions/github-script@v7 - with: - script: | - const initialMessage = [ - '🚀 Deploying...', - '', - '📝 [View Deploy Logs](' + process.env.WORKFLOW_URL + ')', - '', - process.env.CONSOLE_LINK - ].join('\n'); - - const comment = await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: process.env.PR_NUMBER, - body: initialMessage - }); - - core.exportVariable('COMMENT_ID', comment.data.id); - console.log('Created comment:', comment.data.id); - - - name: Update Status - Building - if: env.IS_STAGING != 'true' - uses: actions/github-script@v7 - with: - script: | - const buildingMessage = [ - '🏗️ Building...', - '', - '📝 [View Build Logs](' + process.env.WORKFLOW_URL + ')', - '', - process.env.CONSOLE_LINK - ].join('\n'); - - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: process.env.COMMENT_ID, - body: buildingMessage - }); - - - name: Checkout PR Branch - if: env.IS_STAGING != 'true' - run: git checkout ${{ steps.setup.outputs.PR_REF }} + echo "exists=true" >> $GITHUB_OUTPUT - name: Build Docker Image + if: steps.check-app.outputs.exists == 'true' || github.event_name == 'issue_comment' uses: ./.github/actions/build-docker-image with: app_name: ${{ env.APP_NAME }} org: ${{ env.CPLN_ORG }} - commit: ${{ steps.setup.outputs.PR_SHA }} - - - name: Update Status - Deploying - if: env.IS_STAGING != 'true' - uses: actions/github-script@v7 - with: - script: | - const deployingMessage = [ - '🚀 Deploying...', - '', - '📝 [View Deploy Logs](' + process.env.WORKFLOW_URL + ')', - '', - process.env.CONSOLE_LINK - ].join('\n'); - - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: process.env.COMMENT_ID, - body: deployingMessage - }); + commit: ${{ env.COMMIT_SHA }} - name: Deploy to Control Plane + if: steps.check-app.outputs.exists == 'true' || github.event_name == 'issue_comment' id: deploy uses: ./.github/actions/deploy-to-control-plane with: app_name: ${{ env.APP_NAME }} org: ${{ env.CPLN_ORG }} github_token: ${{ secrets.GITHUB_TOKEN }} - wait_timeout: ${{ vars.WAIT_TIMEOUT || 900 }} - - - name: Update Status - Success - if: success() && env.IS_STAGING != 'true' - uses: actions/github-script@v7 - with: - script: | - const successMessage = [ - '✅ Deployment successful!', - '', - '🌐 Review app is ready at: ${{ steps.deploy.outputs.REVIEW_APP_URL }}', - '', - '📝 [View App Logs](' + process.env.WORKFLOW_URL + ')', - '', - process.env.CONSOLE_LINK - ].join('\n'); - - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: process.env.COMMENT_ID, - body: successMessage - }); - - - name: Update Status - Failure - if: failure() && env.IS_STAGING != 'true' - uses: actions/github-script@v7 - with: - script: | - const failureMessage = [ - '❌ Deployment failed!', - '', - '📝 [View Deploy Logs](' + process.env.WORKFLOW_URL + ')', - '', - process.env.CONSOLE_LINK - ].join('\n'); - - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: process.env.COMMENT_ID, - body: failureMessage - }); From fafac826a20c1f14db5b34ba760df48e83219fdf Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Sun, 26 Jan 2025 19:46:53 -1000 Subject: [PATCH 13/14] rework-main-job-deploy-experimental-refactor --- .github/actions/setup-environment/action.yml | 11 +++++++++++ .github/workflows/deploy-to-control-plane.yml | 6 ++++++ 2 files changed, 17 insertions(+) diff --git a/.github/actions/setup-environment/action.yml b/.github/actions/setup-environment/action.yml index 829a9498..64c4c441 100644 --- a/.github/actions/setup-environment/action.yml +++ b/.github/actions/setup-environment/action.yml @@ -3,6 +3,14 @@ name: 'Setup Environment' description: 'Sets up Ruby, installs Control Plane CLI, cpflow gem, and sets up the default profile' +inputs: + cpln_token: + description: 'Control Plane token' + required: true + cpln_org: + description: 'Control Plane organization' + required: true + runs: using: 'composite' steps: @@ -21,6 +29,9 @@ runs: - name: Setup Control Plane Profile shell: bash + env: + CPLN_TOKEN: ${{ inputs.cpln_token }} + CPLN_ORG: ${{ inputs.cpln_org }} run: | if [ -z "$CPLN_TOKEN" ]; then echo " Error: CPLN_TOKEN environment variable is not set" diff --git a/.github/workflows/deploy-to-control-plane.yml b/.github/workflows/deploy-to-control-plane.yml index 837fad57..7e8eed5c 100644 --- a/.github/workflows/deploy-to-control-plane.yml +++ b/.github/workflows/deploy-to-control-plane.yml @@ -49,6 +49,9 @@ jobs: - name: Setup Environment uses: ./.github/actions/setup-environment + with: + cpln_token: ${{ secrets.CPLN_TOKEN_STAGING }} + cpln_org: ${{ env.CPLN_ORG }} - name: Deploy to Control Plane id: deploy @@ -94,6 +97,9 @@ jobs: - name: Setup Environment uses: ./.github/actions/setup-environment + with: + cpln_token: ${{ secrets.CPLN_TOKEN_STAGING }} + cpln_org: ${{ env.CPLN_ORG }} - name: Get PR Number for Push Event if: github.event_name == 'push' From af6bfc919b41f47c2fe2afa230f5c43c176764aa Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Sun, 26 Jan 2025 19:48:44 -1000 Subject: [PATCH 14/14] rework-main-job-deploy-experimental-refactor --- .github/actions/setup-environment/action.yml | 12 ++---------- .github/workflows/deploy-to-control-plane.yml | 12 ++++++------ 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/.github/actions/setup-environment/action.yml b/.github/actions/setup-environment/action.yml index 64c4c441..0244cf30 100644 --- a/.github/actions/setup-environment/action.yml +++ b/.github/actions/setup-environment/action.yml @@ -3,14 +3,6 @@ name: 'Setup Environment' description: 'Sets up Ruby, installs Control Plane CLI, cpflow gem, and sets up the default profile' -inputs: - cpln_token: - description: 'Control Plane token' - required: true - cpln_org: - description: 'Control Plane organization' - required: true - runs: using: 'composite' steps: @@ -30,8 +22,8 @@ runs: - name: Setup Control Plane Profile shell: bash env: - CPLN_TOKEN: ${{ inputs.cpln_token }} - CPLN_ORG: ${{ inputs.cpln_org }} + CPLN_TOKEN: ${{ env.CPLN_TOKEN }} + CPLN_ORG: ${{ env.CPLN_ORG }} run: | if [ -z "$CPLN_TOKEN" ]; then echo " Error: CPLN_TOKEN environment variable is not set" diff --git a/.github/workflows/deploy-to-control-plane.yml b/.github/workflows/deploy-to-control-plane.yml index 7e8eed5c..9a9b377a 100644 --- a/.github/workflows/deploy-to-control-plane.yml +++ b/.github/workflows/deploy-to-control-plane.yml @@ -49,9 +49,9 @@ jobs: - name: Setup Environment uses: ./.github/actions/setup-environment - with: - cpln_token: ${{ secrets.CPLN_TOKEN_STAGING }} - cpln_org: ${{ env.CPLN_ORG }} + env: + CPLN_TOKEN: ${{ secrets.CPLN_TOKEN_STAGING }} + CPLN_ORG: ${{ vars.CPLN_ORG_STAGING }} - name: Deploy to Control Plane id: deploy @@ -97,9 +97,9 @@ jobs: - name: Setup Environment uses: ./.github/actions/setup-environment - with: - cpln_token: ${{ secrets.CPLN_TOKEN_STAGING }} - cpln_org: ${{ env.CPLN_ORG }} + env: + CPLN_TOKEN: ${{ secrets.CPLN_TOKEN_STAGING }} + CPLN_ORG: ${{ vars.CPLN_ORG_STAGING }} - name: Get PR Number for Push Event if: github.event_name == 'push'