Skip to content

Commit 7a6ec87

Browse files
authored
Merge 6131ce6 into 586dac3
2 parents 586dac3 + 6131ce6 commit 7a6ec87

File tree

6 files changed

+173
-109
lines changed

6 files changed

+173
-109
lines changed

.controlplane/controlplane.yml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,24 @@ aliases:
3939

4040
apps:
4141
react-webpack-rails-tutorial-production:
42-
# Simulate Production Version
42+
# Simulate Production Version. Create with this command:
43+
# cpflow apply-template app postgres redis daily-task rails -a react-webpack-rails-tutorial-production -o shakacode-open-source-examples-production
4344
<<: *common
4445
# Don't allow overriding the org and app by ENV vars b/c production is sensitive!
4546
allow_org_override_by_env: false
4647
allow_app_override_by_env: false
4748

48-
# Use a different organization for production.
49-
cpln_org: shakacode-open-source-examples
49+
# Use a different organization only for production.
50+
cpln_org: shakacode-open-source-examples-production
5051

5152
upstream: react-webpack-rails-tutorial-staging
5253

5354
react-webpack-rails-tutorial-staging:
5455
<<: *common
55-
# QA Apps are like Heroku review apps, but the use `prefix` so you can run a commmand like
56-
# this to create a QA app for the tutorial app.
57-
# `cpflow setup gvc postgres redis rails -a qa-react-webpack-rails-tutorial-pr-1234`
5856
qa-react-webpack-rails-tutorial:
57+
# Review Apps are like Heroku review apps, but the use `prefix` so you can run a command like
58+
# this to create a QA app for the tutorial app.
59+
# `cpflow setup-app -a qa-react-webpack-rails-tutorial-pr-1234`
5960
<<: *common
6061
# Order matters!
6162
setup_app_templates:
Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,29 @@
11
name: 'Validate Required Variables'
22
description: 'Validates that all required secrets and variables for Control Plane operations'
33

4+
inputs:
5+
CPLN_TOKEN_STAGING:
6+
required: true
7+
description: 'Control Plane Staging Token'
8+
CPLN_TOKEN_PRODUCTION:
9+
required: true
10+
description: 'Control Plane Production Token'
11+
CPLN_ORG_STAGING:
12+
required: true
13+
description: 'Control Plane Staging Organization'
14+
CPLN_ORG_PRODUCTION:
15+
required: true
16+
description: 'Control Plane Production Organization'
17+
REVIEW_APP_PREFIX:
18+
required: true
19+
description: 'Review App Prefix'
20+
PRODUCTION_APP_NAME:
21+
required: true
22+
description: 'Production App Name'
23+
STAGING_APP_NAME:
24+
required: true
25+
description: 'Staging App Name'
26+
427
runs:
528
using: 'composite'
629
steps:
@@ -10,19 +33,37 @@ runs:
1033
missing=()
1134
1235
# Check required secrets
13-
if [ -z "$CPLN_TOKEN_STAGING" ]; then
36+
if [ -z "${{ inputs.CPLN_TOKEN_STAGING }}" ]; then
1437
missing+=("Secret: CPLN_TOKEN_STAGING")
1538
fi
39+
40+
if [ -z "${{ inputs.CPLN_TOKEN_PRODUCTION }}" ]; then
41+
missing+=("Secret: CPLN_TOKEN_PRODUCTION")
42+
fi
1643
1744
# Check required variables
18-
if [ -z "$CPLN_ORG_STAGING" ]; then
45+
if [ -z "${{ inputs.CPLN_ORG_STAGING }}" ]; then
1946
missing+=("Variable: CPLN_ORG_STAGING")
2047
fi
21-
if [ -z "$REVIEW_APP_PREFIX" ]; then
48+
49+
if [ -z "${{ inputs.CPLN_ORG_PRODUCTION }}" ]; then
50+
missing+=("Variable: CPLN_ORG_PRODUCTION")
51+
fi
52+
53+
if [ -z "${{ inputs.REVIEW_APP_PREFIX }}" ]; then
2254
missing+=("Variable: REVIEW_APP_PREFIX")
2355
fi
56+
57+
if [ -z "${{ inputs.PRODUCTION_APP_NAME }}" ]; then
58+
missing+=("Variable: PRODUCTION_APP_NAME")
59+
fi
60+
61+
if [ -z "${{ inputs.STAGING_APP_NAME }}" ]; then
62+
missing+=("Variable: STAGING_APP_NAME")
63+
fi
2464
2565
if [ ${#missing[@]} -ne 0 ]; then
26-
echo "Required secrets/variables are not set: ${missing[*]}"
66+
echo "Missing required secrets/variables:"
67+
printf '%s\n' "${missing[@]}"
2768
exit 1
2869
fi

.github/workflows/delete-review-app.yml

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ jobs:
4444

4545
- name: Validate Required Secrets and Variables
4646
uses: ./.github/actions/validate-required-vars
47+
with:
48+
CPLN_TOKEN_STAGING: ${{ secrets.CPLN_TOKEN_STAGING }}
49+
CPLN_TOKEN_PRODUCTION: ${{ secrets.CPLN_TOKEN_PRODUCTION }}
50+
CPLN_ORG_STAGING: ${{ vars.CPLN_ORG_STAGING }}
51+
CPLN_ORG_PRODUCTION: ${{ vars.CPLN_ORG_PRODUCTION }}
52+
REVIEW_APP_PREFIX: ${{ vars.REVIEW_APP_PREFIX }}
53+
PRODUCTION_APP_NAME: ${{ vars.PRODUCTION_APP_NAME }}
54+
STAGING_APP_NAME: ${{ vars.STAGING_APP_NAME }}
4755

4856
- name: Setup Environment
4957
uses: ./.github/actions/setup-environment
@@ -108,7 +116,6 @@ jobs:
108116
issue_number: process.env.PR_NUMBER,
109117
owner: context.repo.owner,
110118
repo: context.repo.repo,
111-
body: '🗑️ Starting app deletion...'
112119
body: [
113120
message,
114121
'',
@@ -125,10 +132,6 @@ jobs:
125132
app_name: ${{ env.APP_NAME }}
126133
org: ${{ env.CPLN_ORG }}
127134
github_token: ${{ secrets.GITHUB_TOKEN }}
128-
env:
129-
APP_NAME: ${{ env.APP_NAME }}
130-
CPLN_ORG: ${{ secrets.CPLN_ORG }}
131-
CPLN_TOKEN: ${{ secrets.CPLN_TOKEN }}
132135

133136
- name: Update Delete Status
134137
if: always()
@@ -163,3 +166,15 @@ jobs:
163166
comment_id: ${{ fromJSON(steps.create-delete-comment.outputs.result).commentId }},
164167
body: success ? successMessage : failureMessage
165168
});
169+
170+
- name: Debug Environment
171+
run: |
172+
echo "Organization: ${{ env.CPLN_ORG }}"
173+
echo "App Name: ${{ env.APP_NAME }}"
174+
echo "PR Number: ${{ env.PR_NUMBER }}"
175+
# Don't echo the actual token, but verify it exists
176+
if [ -n "${{ env.CPLN_TOKEN }}" ]; then
177+
echo "CPLN_TOKEN is set"
178+
else
179+
echo "CPLN_TOKEN is empty"
180+
fi

.github/workflows/deploy-to-control-plane-review-app.yml

Lines changed: 72 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@ run-name: Deploy PR Review App - PR #${{ github.event.pull_request.number || git
55
on:
66
pull_request:
77
types: [opened, synchronize, reopened]
8-
push:
9-
branches:
10-
- '**' # Any branch
11-
- '!main' # Except main
12-
- '!master' # Except master
138
issue_comment:
149
types: [created]
1510
workflow_dispatch:
@@ -71,6 +66,14 @@ jobs:
7166

7267
- name: Validate Required Secrets and Variables
7368
uses: ./.github/actions/validate-required-vars
69+
with:
70+
CPLN_TOKEN_STAGING: ${{ secrets.CPLN_TOKEN_STAGING }}
71+
CPLN_TOKEN_PRODUCTION: ${{ secrets.CPLN_TOKEN_PRODUCTION }}
72+
CPLN_ORG_STAGING: ${{ vars.CPLN_ORG_STAGING }}
73+
CPLN_ORG_PRODUCTION: ${{ vars.CPLN_ORG_PRODUCTION }}
74+
REVIEW_APP_PREFIX: ${{ vars.REVIEW_APP_PREFIX }}
75+
PRODUCTION_APP_NAME: ${{ vars.PRODUCTION_APP_NAME }}
76+
STAGING_APP_NAME: ${{ vars.STAGING_APP_NAME }}
7477

7578
- name: Get PR HEAD Ref
7679
id: getRef
@@ -131,9 +134,9 @@ jobs:
131134
fi
132135
fi
133136
134-
# Extract and set PR data
137+
# Set PR_NUMBER and override APP_NAME with validated PR number
135138
echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV
136-
echo "APP_NAME=${{ vars.REVIEW_APP_PREFIX }}-$PR_NUMBER" >> $GITHUB_ENV
139+
echo "APP_NAME=${{ vars.REVIEW_APP_PREFIX }}-pr-$PR_NUMBER" >> $GITHUB_ENV
137140
echo "PR_REF=$(echo $PR_DATA | jq -r .headRefName)" >> $GITHUB_OUTPUT
138141
echo "PR_SHA=$(echo $PR_DATA | jq -r .headRefOid)" >> $GITHUB_ENV
139142
@@ -170,42 +173,16 @@ jobs:
170173
exit 0
171174
fi
172175
176+
# Validate supported event types
173177
if ! [[ "${{ github.event_name }}" == "workflow_dispatch" || \
174178
"${{ github.event_name }}" == "issue_comment" || \
175-
"${{ github.event_name }}" == "pull_request" || \
176-
"${{ github.event_name }}" == "push" ]]; then
179+
"${{ github.event_name }}" == "pull_request" ]]; then
177180
echo "Error: Unsupported event type ${{ github.event_name }}"
178181
exit 1
179182
fi
180183
181-
# Set DO_DEPLOY based on event type and conditions
182-
if [[ "${{ github.event_name }}" == "pull_request" && \
183-
("${{ github.event.action }}" == "opened" || \
184-
"${{ github.event.action }}" == "synchronize" || \
185-
"${{ github.event.action }}" == "reopened") ]]; then
186-
echo "DO_DEPLOY=true" >> $GITHUB_ENV
187-
elif [[ "${{ github.event_name }}" == "push" ]]; then
188-
echo "DO_DEPLOY=true" >> $GITHUB_ENV
189-
elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
190-
echo "DO_DEPLOY=true" >> $GITHUB_ENV
191-
elif [[ "${{ github.event_name }}" == "issue_comment" ]]; then
192-
if [[ "${{ github.event.issue.pull_request }}" ]]; then
193-
# Trim spaces and check for exact command
194-
COMMENT_BODY=$(echo "${{ github.event.comment.body }}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
195-
if [[ "$COMMENT_BODY" == "/deploy-review-app" ]]; then
196-
echo "DO_DEPLOY=true" >> $GITHUB_ENV
197-
else
198-
echo "DO_DEPLOY=false" >> $GITHUB_ENV
199-
echo "Skipping deployment - comment '$COMMENT_BODY' does not match '/deploy-review-app'"
200-
fi
201-
else
202-
echo "DO_DEPLOY=false" >> $GITHUB_ENV
203-
echo "Skipping deployment for non-PR comment"
204-
fi
205-
fi
206-
207184
- name: Setup Control Plane App if Not Existing
208-
if: env.DO_DEPLOY == 'true' && env.APP_EXISTS == 'false'
185+
if: env.DO_DEPLOY != 'false' && env.APP_EXISTS == 'false'
209186
env:
210187
CPLN_TOKEN: ${{ secrets.CPLN_TOKEN_STAGING }}
211188
run: |
@@ -222,7 +199,17 @@ jobs:
222199
owner: context.repo.owner,
223200
repo: context.repo.repo,
224201
issue_number: process.env.PR_NUMBER,
225-
body: '🚀 Starting deployment process...\n\n' + process.env.CONSOLE_LINK
202+
body: [
203+
`🏗️ Building Docker image for PR [#${process.env.PR_NUMBER}](${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/pull/${process.env.PR_NUMBER}), commit [${context.sha.substring(0, 7)}](${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/commit/${context.sha})`,
204+
'',
205+
'🚀 Deploying to Control Plane...',
206+
'',
207+
'⏳ Waiting for deployment to be ready...',
208+
'',
209+
`📝 [View Build and Deploy Logs](${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}/job/${context.job})`,
210+
'',
211+
process.env.CONSOLE_LINK
212+
].join('\n')
226213
});
227214
core.setOutput('comment-id', result.data.id);
228215
@@ -252,7 +239,7 @@ jobs:
252239
};
253240
254241
const workflowUrl = await getWorkflowUrl(context.runId);
255-
core.exportVariable('WORKFLOW_URL', workflowUrl);
242+
core.exportVariable('BUILD_LOGS_URL', workflowUrl);
256243
core.exportVariable('CONSOLE_LINK',
257244
'🎮 [Control Plane Console](' +
258245
'https://console.cpln.io/console/org/' + process.env.CPLN_ORG + '/gvc/' + process.env.APP_NAME + '/-info)'
@@ -309,25 +296,6 @@ jobs:
309296
token: ${{ secrets.CPLN_TOKEN_STAGING }}
310297
org: ${{ vars.CPLN_ORG_STAGING }}
311298

312-
- name: Update Status - Building
313-
uses: actions/github-script@v7
314-
with:
315-
script: |
316-
const buildingMessage = [
317-
'🏗️ Building Docker image for PR #${{ needs.process-deployment.outputs.pr_number }}, commit ${{ needs.process-deployment.outputs.pr_sha }}',
318-
'',
319-
'📝 [View Build Logs](${{ env.WORKFLOW_URL }})',
320-
'',
321-
process.env.CONSOLE_LINK
322-
].join('\n');
323-
324-
await github.rest.issues.updateComment({
325-
owner: context.repo.owner,
326-
repo: context.repo.repo,
327-
comment_id: ${{ needs.process-deployment.outputs.comment_id }},
328-
body: buildingMessage
329-
});
330-
331299
- name: Build Docker Image
332300
id: build
333301
uses: ./.github/actions/build-docker-image
@@ -355,21 +323,43 @@ jobs:
355323
uses: actions/github-script@v7
356324
with:
357325
script: |
358-
const deployingMessage = [
359-
'🚀 Deploying to Control Plane...',
360-
'',
361-
'⏳ Waiting for deployment to be ready...',
362-
'',
363-
'📝 [View Deploy Logs](${{ env.WORKFLOW_URL }})',
364-
'',
365-
process.env.CONSOLE_LINK
366-
].join('\n');
326+
// Create deployment status for deploying state
327+
await github.rest.repos.createDeploymentStatus({
328+
owner: context.repo.owner,
329+
repo: context.repo.repo,
330+
deployment_id: ${{ needs.process-deployment.outputs.deployment_id }},
331+
state: 'in_progress',
332+
description: 'Deployment in progress',
333+
log_url: process.env.BUILD_LOGS_URL
334+
});
335+
336+
// Get the current job URL and ID
337+
const { data: jobs } = await github.rest.actions.listJobsForWorkflowRun({
338+
owner: context.repo.owner,
339+
repo: context.repo.repo,
340+
run_id: context.runId
341+
});
367342
343+
const currentJob = jobs.jobs.find(job => job.name === context.job);
344+
const currentJobUrl = `${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}/job/${currentJob.id}?pr=${process.env.PR_NUMBER}`;
345+
346+
// Update the PR comment with correct job URLs
368347
await github.rest.issues.updateComment({
369348
owner: context.repo.owner,
370349
repo: context.repo.repo,
371-
comment_id: ${{ steps.create-comment.outputs.comment-id }},
372-
body: deployingMessage
350+
comment_id: ${{ needs.build.outputs.comment_id }},
351+
body: [
352+
`🏗️ Built Docker image for PR [#${process.env.PR_NUMBER}](${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/pull/${process.env.PR_NUMBER}), commit [${process.env.PR_SHA.substring(0, 7)}](${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/commit/${process.env.PR_SHA})`,
353+
'',
354+
'🚀 Deploying to Control Plane...',
355+
'',
356+
'⏳ Waiting for deployment to be ready...',
357+
'',
358+
process.env.CONSOLE_LINK,
359+
'',
360+
`📝 [View Build Logs](${process.env.BUILD_LOGS_URL}?pr=${process.env.PR_NUMBER})`,
361+
`📝 [View Deploy Logs](${currentJobUrl})`
362+
].join('\n')
373363
});
374364
375365
- name: Deploy to Control Plane
@@ -395,14 +385,24 @@ jobs:
395385
396386
const consoleLink = process.env.CONSOLE_LINK;
397387
388+
// Get current job ID for accurate logs URL
389+
const { data: jobs } = await github.rest.actions.listJobsForWorkflowRun({
390+
owner: context.repo.owner,
391+
repo: context.repo.repo,
392+
run_id: context.runId
393+
});
394+
395+
const currentJob = jobs.jobs.find(job => job.name === context.job);
396+
const logsUrl = `${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}/job/${currentJob.id}?pr=${prNumber}`;
397+
398398
// Create GitHub deployment status
399399
const deploymentStatus = {
400400
owner: context.repo.owner,
401401
repo: context.repo.repo,
402402
deployment_id: ${{ steps.init-deployment.outputs.result }},
403403
state: isSuccess ? 'success' : 'failure',
404404
environment_url: isSuccess ? appUrl : undefined,
405-
log_url: workflowUrl,
405+
log_url: logsUrl,
406406
environment: 'review'
407407
};
408408
@@ -415,21 +415,21 @@ jobs:
415415
'🚀 [Review App for PR #' + prNumber + '](' + appUrl + ')',
416416
consoleLink,
417417
'',
418-
'📋 [View Completed Action Build and Deploy Logs](' + workflowUrl + ')'
418+
`📝 [View Build and Deploy Logs](${logsUrl})`,
419419
].join('\n');
420420
421421
const failureMessage = [
422422
'❌ Deployment failed for PR #' + prNumber + ', commit ' + '${{ env.PR_SHA }}',
423423
'',
424424
consoleLink,
425425
'',
426-
'📋 [View Deployment Logs with Errors](' + workflowUrl + ')'
426+
`📝 [View Build and Deploy Logs with Errors](${logsUrl})`,
427427
].join('\n');
428428
429429
// Update the existing comment
430430
await github.rest.issues.updateComment({
431431
owner: context.repo.owner,
432432
repo: context.repo.repo,
433-
comment_id: ${{ steps.create-comment.outputs.comment-id }},
433+
comment_id: ${{ needs.build.outputs.comment_id }},
434434
body: isSuccess ? successMessage : failureMessage
435435
});

0 commit comments

Comments
 (0)