Skip to content

Commit b731dde

Browse files
committed
brought in changes from master
1 parent ebf0795 commit b731dde

File tree

8 files changed

+467
-96
lines changed

8 files changed

+467
-96
lines changed

.github/actions/deploy-to-control-plane/action.yml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ inputs:
1616
wait_timeout:
1717
description: 'Timeout in seconds for waiting for workloads to be ready'
1818
required: false
19-
default: 600
19+
default: '900'
2020

2121
outputs:
2222
review_app_url:
@@ -26,6 +26,21 @@ outputs:
2626
runs:
2727
using: "composite"
2828
steps:
29+
- name: Validate Required Secrets
30+
shell: bash
31+
run: |
32+
missing_secrets=()
33+
for secret in "CPLN_TOKEN" "CPLN_ORG"; do
34+
if [ -z "${!secret}" ]; then
35+
missing_secrets+=("$secret")
36+
fi
37+
done
38+
39+
if [ ${#missing_secrets[@]} -ne 0 ]; then
40+
echo "Required secrets are not set: ${missing_secrets[*]}"
41+
exit 1
42+
fi
43+
2944
- name: Setup Environment
3045
uses: ./.github/actions/setup-environment
3146

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
#!/bin/bash
22

33
# This script handles the deployment to Control Plane and extracts the Rails URL
4-
#
4+
#
55
# Required environment variables:
66
# - APP_NAME: Name of the application to deploy
77
# - CPLN_ORG: Control Plane organization
88
#
9+
# Optional environment variables:
10+
# - WAIT_TIMEOUT: Timeout in seconds for deployment (default: 900)
11+
# Must be a positive integer
12+
#
913
# Outputs:
1014
# - rails_url: URL of the deployed Rails application
1115

@@ -15,29 +19,48 @@ set -e
1519
: "${APP_NAME:?APP_NAME environment variable is required}"
1620
: "${CPLN_ORG:?CPLN_ORG environment variable is required}"
1721

18-
# Set deployment timeout (15 minutes)
19-
TIMEOUT=900
22+
# Set and validate deployment timeout
23+
WAIT_TIMEOUT=${WAIT_TIMEOUT:-900}
24+
if ! [[ "${WAIT_TIMEOUT}" =~ ^[0-9]+$ ]]; then
25+
echo "❌ Invalid timeout value: ${WAIT_TIMEOUT}"
26+
exit 1
27+
fi
2028

2129
TEMP_OUTPUT=$(mktemp)
2230
trap 'rm -f "$TEMP_OUTPUT"' EXIT
2331

2432
# Deploy the application
25-
echo "🚀 Deploying to Control Plane..."
26-
if timeout "$TIMEOUT" cpflow deploy-image -a "$APP_NAME" --run-release-phase --org "$CPLN_ORG" --verbose | tee "$TEMP_OUTPUT"; then
27-
# Extract Rails URL from deployment output
28-
RAILS_URL=$(grep -oP 'https://rails-[^[:space:]]*\.cpln\.app(?=\s|$)' "$TEMP_OUTPUT" | head -n1)
29-
if [ -n "$RAILS_URL" ]; then
30-
echo "rails_url=$RAILS_URL" >> "$GITHUB_OUTPUT"
31-
echo "✅ Deployment successful"
32-
echo "🚀 Rails URL: $RAILS_URL"
33-
else
34-
echo "❌ Failed to extract Rails URL from deployment output"
35-
exit 1
36-
fi
37-
elif [ $? -eq 124 ]; then
38-
echo "❌ Deployment timed out after $TIMEOUT seconds"
39-
exit 1
40-
else
41-
echo "❌ Deployment to Control Plane failed"
42-
exit 1
33+
echo "🚀 Deploying to Control Plane (timeout: ${WAIT_TIMEOUT}s)"
34+
if ! timeout "${WAIT_TIMEOUT}" cpflow deploy-image -a "$APP_NAME" --run-release-phase --org "$CPLN_ORG" --verbose 2>&1 | tee "$TEMP_OUTPUT"; then
35+
echo "❌ Deployment failed"
36+
echo "Full output:"
37+
cat "$TEMP_OUTPUT"
38+
exit 1
39+
fi
40+
41+
# Extract app URL from deployment output
42+
RAILS_URL=$(grep -oP 'https://rails-[^[:space:]]*\.cpln\.app(?=\s|$)' "$TEMP_OUTPUT" | head -n1)
43+
if [ -z "$RAILS_URL" ]; then
44+
echo "❌ Failed to get app URL from deployment output"
45+
echo "Full output:"
46+
cat "$TEMP_OUTPUT"
47+
exit 1
48+
fi
49+
50+
# Wait for all workloads to be ready
51+
echo "⏳ Waiting for all workloads to be ready (timeout: ${WAIT_TIMEOUT}s)"
52+
if ! timeout "${WAIT_TIMEOUT}" bash -c "cpflow ps:wait -a \"$APP_NAME\"" 2>&1 | tee -a "$TEMP_OUTPUT"; then
53+
TIMEOUT_EXIT=$?
54+
if [ ${TIMEOUT_EXIT} -eq 124 ]; then
55+
echo "❌ Timed out waiting for workloads after ${WAIT_TIMEOUT} seconds"
56+
else
57+
echo "❌ Workloads did not become ready"
58+
fi
59+
echo "Full output:"
60+
cat "$TEMP_OUTPUT"
61+
exit 1
4362
fi
63+
64+
echo "✅ Deployment successful"
65+
echo "🌐 Rails URL: $RAILS_URL"
66+
echo "rails_url=$RAILS_URL" >> "$GITHUB_OUTPUT"

.github/actions/setup-environment/action.yml

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
name: 'Setup Environment'
44
description: 'Sets up Ruby, installs Control Plane CLI, cpflow gem, and sets up the default profile'
55

6+
inputs:
7+
token:
8+
description: 'Control Plane token'
9+
required: true
10+
org:
11+
description: 'Control Plane organization'
12+
required: true
13+
614
runs:
715
using: 'composite'
816
steps:
@@ -22,19 +30,22 @@ runs:
2230
- name: Setup Control Plane Profile
2331
shell: bash
2432
run: |
25-
if [ -z "$CPLN_TOKEN" ]; then
26-
echo " Error: CPLN_TOKEN environment variable is not set"
33+
TOKEN="${{ inputs.token }}"
34+
ORG="${{ inputs.org }}"
35+
36+
if [ -z "$TOKEN" ]; then
37+
echo " Error: Control Plane token not provided"
2738
exit 1
2839
fi
2940
30-
if [ -z "$CPLN_ORG" ]; then
31-
echo " Error: CPLN_ORG environment variable is not set"
41+
if [ -z "$ORG" ]; then
42+
echo " Error: Control Plane organization not provided"
3243
exit 1
3344
fi
3445
3546
echo "Setting up Control Plane profile..."
36-
echo "Organization: $CPLN_ORG"
37-
cpln profile update default --org "$CPLN_ORG" --token "$CPLN_TOKEN"
47+
echo "Organization: $ORG"
48+
cpln profile update default --org "$ORG" --token "$TOKEN"
3849
3950
echo "Setting up Docker login for Control Plane registry..."
40-
cpln image docker-login --org "$CPLN_ORG"
51+
cpln image docker-login --org "$ORG"
Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,30 @@
1-
name: Add helper Comment on PR creation
1+
name: Add Comment on PR Creation
22

33
on:
44
pull_request:
55
types: [opened]
66

77
jobs:
8-
comment-on-pr:
8+
add-comment:
99
runs-on: ubuntu-latest
10+
permissions:
11+
pull-requests: write
1012
steps:
11-
- name: Add GitHub Comment for review app instructions
12-
uses: actions/github-script@v7
13-
with:
14-
script: |
15-
github.rest.issues.createComment({
16-
issue_number: context.issue.number,
17-
owner: context.repo.owner,
18-
repo: context.repo.repo,
19-
body: "Hi 👋 To deploy a review app, please comment `/deploy-review-app`"
20-
})
13+
- uses: actions/github-script@v7
14+
name: Add GitHub Comment for review app instructions
15+
with:
16+
script: |
17+
await github.rest.issues.createComment({
18+
owner: context.repo.owner,
19+
repo: context.repo.repo,
20+
issue_number: context.payload.pull_request.number,
21+
body: [
22+
"Hi 👋 Here are the commands available for this PR:",
23+
"",
24+
"- `/deploy-review-app`: Deploy your changes to a review environment",
25+
"- `/delete-review-app`: Clean up the review environment when you're done",
26+
"- `/help`: Show detailed information about all commands",
27+
"",
28+
"Use `/help` to see full documentation, including configuration options."
29+
].join("\n")
30+
});

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

Lines changed: 103 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
name: Delete Review App
22

33
on:
4+
pull_request:
5+
types: [closed]
46
issue_comment:
57
types: [created]
68

@@ -12,14 +14,18 @@ permissions:
1214

1315
env:
1416
CPLN_ORG: ${{ secrets.CPLN_ORG_STAGING }}
15-
CPLN_TOKEN: ${{ secrets.CPLN_TOKEN_STAGING }}
17+
CPLN_TOKEN: ${{ secrets.CPLN_TOKEN }}
18+
APP_NAME: qa-react-webpack-rails-tutorial-pr-${{ github.event.pull_request.number || github.event.issue.number }}
19+
PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }}
1620

1721
jobs:
1822
Process-Delete-Command:
1923
if: |
20-
github.event_name == 'issue_comment' &&
21-
github.event.issue.pull_request &&
22-
github.event.comment.body == '/delete-review-app'
24+
(github.event_name == 'issue_comment' &&
25+
github.event.issue.pull_request &&
26+
github.event.comment.body == '/delete-review-app') ||
27+
(github.event_name == 'pull_request' &&
28+
github.event.action == 'closed')
2329
runs-on: ubuntu-latest
2430

2531
steps:
@@ -37,24 +43,97 @@ jobs:
3743

3844
- uses: actions/checkout@v4
3945

46+
- name: Validate Required Secrets
47+
run: |
48+
missing_secrets=()
49+
for secret in "CPLN_TOKEN" "CPLN_ORG"; do
50+
if [ -z "${!secret}" ]; then
51+
missing_secrets+=("$secret")
52+
fi
53+
done
54+
55+
if [ ${#missing_secrets[@]} -ne 0 ]; then
56+
echo "Required secrets are not set: ${missing_secrets[*]}"
57+
exit 1
58+
fi
59+
4060
- name: Setup Environment
4161
uses: ./.github/actions/setup-environment
4262

63+
- name: Set shared functions
64+
id: shared-functions
65+
uses: actions/github-script@v7
66+
with:
67+
script: |
68+
core.exportVariable('GET_CONSOLE_LINK', `
69+
function getConsoleLink(prNumber) {
70+
return '🎮 [Control Plane Console](' +
71+
'https://console.cpln.io/console/org/' + process.env.CPLN_ORG + '/gvc/' + process.env.APP_NAME + '/-info)';
72+
}
73+
`);
74+
75+
- name: Setup Workflow URL
76+
id: setup-workflow-url
77+
uses: actions/github-script@v7
78+
with:
79+
script: |
80+
async function getWorkflowUrl(runId) {
81+
// Get the current job ID
82+
const jobs = await github.rest.actions.listJobsForWorkflowRun({
83+
owner: context.repo.owner,
84+
repo: context.repo.repo,
85+
run_id: runId
86+
});
87+
88+
const currentJob = jobs.data.jobs.find(job => job.status === 'in_progress');
89+
const jobId = currentJob?.id;
90+
91+
if (!jobId) {
92+
console.log('Warning: Could not find current job ID');
93+
return `${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}`;
94+
}
95+
96+
return `${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}/job/${jobId}`;
97+
}
98+
99+
const workflowUrl = await getWorkflowUrl(context.runId);
100+
core.exportVariable('WORKFLOW_URL', workflowUrl);
101+
return { workflowUrl };
102+
43103
- name: Create Initial Delete Comment
44-
id: init-delete
104+
id: create-delete-comment
45105
uses: actions/github-script@v7
46106
with:
47107
script: |
108+
eval(process.env.GET_CONSOLE_LINK);
109+
110+
let message = '🗑️ Starting app deletion';
111+
if ('${{ github.event_name }}' === 'pull_request') {
112+
const merged = '${{ github.event.pull_request.merged }}' === 'true';
113+
message += merged ? ' (PR merged)' : ' (PR closed)';
114+
}
115+
48116
const comment = await github.rest.issues.createComment({
49117
issue_number: process.env.PR_NUMBER,
50118
owner: context.repo.owner,
51119
repo: context.repo.repo,
52120
body: '🗑️ Starting app deletion...'
121+
body: [
122+
message,
123+
'',
124+
' 🗑️ [View Delete Logs](' + process.env.WORKFLOW_URL + ')',
125+
'',
126+
getConsoleLink(process.env.PR_NUMBER)
127+
].join('\n')
53128
});
54129
return { commentId: comment.data.id };
55130
56131
- name: Delete Review App
57132
uses: ./.github/actions/delete-control-plane-app
133+
with:
134+
app_name: ${{ env.APP_NAME }}
135+
org: ${{ env.CPLN_ORG }}
136+
github_token: ${{ secrets.GITHUB_TOKEN }}
58137
env:
59138
APP_NAME: ${{ env.APP_NAME }}
60139
CPLN_ORG: ${{ secrets.CPLN_ORG }}
@@ -65,21 +144,31 @@ jobs:
65144
uses: actions/github-script@v7
66145
with:
67146
script: |
147+
eval(process.env.GET_CONSOLE_LINK);
148+
68149
const success = '${{ job.status }}' === 'success';
69150
const prNumber = process.env.PR_NUMBER;
70151
const cpConsoleUrl = `https://console.cpln.io/org/${process.env.CPLN_ORG}/workloads/${process.env.APP_NAME}`;
71152
72-
const message = success
73-
? '✅ Review app for PR #' + prNumber + ' was successfully deleted'
74-
: [
75-
'❌ Review app for PR #' + prNumber + ' failed to be deleted',
76-
'',
77-
'[View in Control Plane Console](' + cpConsoleUrl + ')'
78-
].join('\n');
153+
const successMessage = [
154+
'✅ Review app for PR #' + prNumber + ' was successfully deleted',
155+
'',
156+
' [View Completed Delete Logs](' + process.env.WORKFLOW_URL + ')',
157+
'',
158+
' [Control Plane Organization](https://console.cpln.io/console/org/' + process.env.CPLN_ORG + '/-info)'
159+
].join('\n');
160+
161+
const failureMessage = [
162+
'❌ Review app for PR #' + prNumber + ' failed to be deleted',
163+
'',
164+
' [View Delete Logs with Errors](' + process.env.WORKFLOW_URL + ')',
165+
'',
166+
getConsoleLink(prNumber)
167+
].join('\n');
79168
80169
await github.rest.issues.updateComment({
81170
owner: context.repo.owner,
82171
repo: context.repo.repo,
83-
comment_id: ${{ fromJSON(steps.init-delete.outputs.result).commentId }},
84-
body: message
172+
comment_id: ${{ fromJSON(steps.create-delete-comment.outputs.result).commentId }},
173+
body: success ? successMessage : failureMessage
85174
});

0 commit comments

Comments
 (0)