@@ -34,17 +34,21 @@ jobs:
3434 issues : write
3535
3636 steps :
37- - uses : actions/checkout@v4
38-
3937 - name : Get PR HEAD Ref
4038 if : github.event_name == 'issue_comment'
4139 id : getRef
4240 run : |
43- PR_URL=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
44- -H "Accept: application/vnd.github.v3+json" \
45- "${{ github.event.issue.pull_request.url }}")
46- HEAD_REF=$(echo "$PR_URL" | jq -r .head.ref)
47- echo "ref=$HEAD_REF" >> "$GITHUB_OUTPUT"
41+ # For PR comments, get the actual PR head commit
42+ PR_DATA=$(gh pr view $PR_NUMBER --repo ${{ github.repository }} --json headRefName,headRefOid)
43+ echo "PR_REF=$(echo "$PR_DATA" | jq -r '.headRefName')" >> $GITHUB_OUTPUT
44+ echo "PR_SHA=$(echo "$PR_DATA" | jq -r '.headRefOid')" >> $GITHUB_OUTPUT
45+ env :
46+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
47+
48+ - uses : actions/checkout@v4
49+ with :
50+ fetch-depth : 0
51+ ref : ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || steps.getRef.outputs.PR_REF || github.ref }}
4852
4953 - name : Validate Required Secrets
5054 run : |
@@ -63,78 +67,229 @@ jobs:
6367 - name : Setup Environment
6468 uses : ./.github/actions/setup-environment
6569
66- - name : Create Initial Status Comment
67- id : init-status
70+ - name : Set shared functions
71+ id : shared-functions
72+ uses : actions/github-script@v7
73+ with :
74+ script : |
75+ core.exportVariable('GET_CONSOLE_LINK', `
76+ function getConsoleLink(prNumber) {
77+ return ' [Control Plane Console for Review App with PR #' + prNumber + '](' +
78+ 'https://console.cpln.io/org/' + process.env.CPLN_ORG + '/workloads/' + process.env.APP_NAME + ')';
79+ }
80+ `);
81+
82+ - name : Initialize Deployment
83+ id : init-deployment
6884 uses : actions/github-script@v7
6985 with :
7086 script : |
87+ eval(process.env.GET_CONSOLE_LINK);
88+
89+ async function getWorkflowUrl(runId) {
90+ // Get the current job ID
91+ const jobs = await github.rest.actions.listJobsForWorkflowRun({
92+ owner: context.repo.owner,
93+ repo: context.repo.repo,
94+ run_id: runId
95+ });
96+
97+ const currentJob = jobs.data.jobs.find(job => job.status === 'in_progress');
98+ const jobId = currentJob?.id;
99+
100+ if (!jobId) {
101+ console.log('Warning: Could not find current job ID');
102+ return `${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}`;
103+ }
104+
105+ return `${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}/job/${jobId}`;
106+ }
107+
108+ // Create initial deployment comment
71109 const comment = await github.rest.issues.createComment({
110+ owner: context.repo.owner,
111+ repo: context.repo.repo,
72112 issue_number: process.env.PR_NUMBER,
113+ body: ' Initializing deployment...'
114+ });
115+
116+ // Create GitHub deployment
117+ const deployment = await github.rest.repos.createDeployment({
73118 owner: context.repo.owner,
74119 repo: context.repo.repo,
75- body: '🚀 Starting deployment...'
120+ ref: context.sha,
121+ environment: 'review',
122+ auto_merge: false,
123+ required_contexts: []
76124 });
77- return { commentId: comment.data.id };
125+
126+ const workflowUrl = await getWorkflowUrl(context.runId);
127+
128+ return {
129+ deploymentId: deployment.data.id,
130+ commentId: comment.data.id,
131+ workflowUrl
132+ };
133+
134+ - name : Set comment ID and workflow URL
135+ run : |
136+ echo "COMMENT_ID=${{ fromJSON(steps.init-deployment.outputs.result).commentId }}" >> $GITHUB_ENV
137+ echo "WORKFLOW_URL=${{ fromJSON(steps.init-deployment.outputs.result).workflowUrl }}" >> $GITHUB_ENV
138+
139+ - name : Set commit hash
140+ run : |
141+ FULL_COMMIT="${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || steps.getRef.outputs.PR_SHA || github.sha }}"
142+ echo "COMMIT_HASH=${FULL_COMMIT:0:7}" >> $GITHUB_ENV
78143
79144 - name : Update Status - Building
80145 uses : actions/github-script@v7
81146 with :
82147 script : |
83- function getConsoleLink(prNumber) {
84- return `[Control Plane Console](https://console.cpln.io/org/${process.env.CPLN_ORG}/workloads/${process.env.APP_NAME})`;
85- }
148+ eval(process.env.GET_CONSOLE_LINK);
149+
150+ const buildingMessage = [
151+ ' Building Docker image for PR #' + process.env.PR_NUMBER + ', commit ' + '${{ env.COMMIT_HASH }}',
152+ '',
153+ ' [View Build Logs](' + process.env.WORKFLOW_URL + ')',
154+ '',
155+ getConsoleLink(process.env.PR_NUMBER)
156+ ].join('\n');
86157
87158 await github.rest.issues.updateComment({
88159 owner: context.repo.owner,
89160 repo: context.repo.repo,
90- comment_id: ${{ fromJSON(steps.init-status.outputs.result).commentId }},
91- body: [
92- '🏗️ Building review app...',
93- '',
94- getConsoleLink(process.env.PR_NUMBER)
95- ].join('\n')
161+ comment_id: process.env.COMMENT_ID,
162+ body: buildingMessage
96163 });
97164
98- - name : Deploy Review App
99- id : deploy
165+ - name : Build Docker Image
166+ uses : ./.github/actions/build-docker-image
167+ with :
168+ app_name : ${{ env.APP_NAME }}
169+ org : ${{ env.CPLN_ORG }}
170+ commit : ${{ env.COMMIT_HASH }}
171+ PR_NUMBER : ${{ env.PR_NUMBER }}
172+
173+ - name : Update Status - Deploying
174+ uses : actions/github-script@v7
175+ with :
176+ script : |
177+ eval(process.env.GET_CONSOLE_LINK);
178+
179+ const deployingMessage = [
180+ ' Deploying to Control Plane...',
181+ '',
182+ ' Waiting for deployment to be ready...',
183+ '',
184+ ' [View Deploy Logs](' + process.env.WORKFLOW_URL + ')',
185+ '',
186+ getConsoleLink(process.env.PR_NUMBER)
187+ ].join('\n');
188+
189+ await github.rest.issues.updateComment({
190+ owner: context.repo.owner,
191+ repo: context.repo.repo,
192+ comment_id: process.env.COMMENT_ID,
193+ body: deployingMessage
194+ });
195+
196+ - name : Deploy to Control Plane
100197 uses : ./.github/actions/deploy-to-control-plane
101198 with :
102199 app_name : ${{ env.APP_NAME }}
103200 org : ${{ env.CPLN_ORG }}
104- wait_timeout : 900
105201 github_token : ${{ secrets.GITHUB_TOKEN }}
106- env :
107- CPLN_TOKEN : ${{ secrets.CPLN_TOKEN }}
202+ wait_timeout : ${{ vars.WAIT_TIMEOUT || 900 }}
108203
109- - name : Update Status - Complete
110- if : always()
204+ - name : Update Status - Deployment Complete
111205 uses : actions/github-script@v7
112206 with :
113207 script : |
114- function getConsoleLink(prNumber) {
115- return `[Control Plane Console](https://console.cpln.io/org/${process.env.CPLN_ORG}/workloads/${process.env.APP_NAME})`;
116- }
117-
208+ eval(process.env.GET_CONSOLE_LINK);
209+
210+ const prNumber = process.env.PR_NUMBER;
211+ const appUrl = process.env.REVIEW_APP_URL;
212+ const workflowUrl = process.env.WORKFLOW_URL;
118213 const isSuccess = '${{ job.status }}' === 'success';
119- const railsUrl = '${{ steps.deploy.outputs.rails_url }}';
120214
215+ // Create GitHub deployment status
216+ const deploymentStatus = {
217+ owner: context.repo.owner,
218+ repo: context.repo.repo,
219+ deployment_id: ${{ fromJSON(steps.init-deployment.outputs.result).deploymentId }},
220+ state: isSuccess ? 'success' : 'failure',
221+ environment_url: isSuccess ? appUrl : undefined,
222+ log_url: workflowUrl,
223+ environment: 'review'
224+ };
225+
226+ await github.rest.repos.createDeploymentStatus(deploymentStatus);
227+
228+ // Define messages based on deployment status
121229 const successMessage = [
122- '✅ Review app deployed successfully! ',
230+ ' Deployment complete for PR #' + prNumber + ', commit ' + '${{ env.COMMIT_HASH }} ',
123231 '',
124- '🌐 [Rails App](' + railsUrl + ')',
232+ ' [Review App for PR #' + prNumber + ' ](' + appUrl + ')',
125233 '',
126- getConsoleLink(process.env.PR_NUMBER)
234+ ' [View Completed Action Build and Deploy Logs](' + workflowUrl + ')',
235+ '',
236+ getConsoleLink(prNumber)
127237 ].join('\n');
128238
129239 const failureMessage = [
130- '❌ Review app deployment failed ',
240+ ' Deployment failed for PR #' + prNumber + ', commit ' + '${{ env.COMMIT_HASH }} ',
131241 '',
132- getConsoleLink(process.env.PR_NUMBER)
242+ ' [View Deployment Logs with Errors](' + workflowUrl + ')',
243+ '',
244+ getConsoleLink(prNumber)
133245 ].join('\n');
134246
247+ // Update the existing comment
135248 await github.rest.issues.updateComment({
136249 owner: context.repo.owner,
137250 repo: context.repo.repo,
138- comment_id: ${{ fromJSON(steps.init-status.outputs.result).commentId }} ,
251+ comment_id: process.env.COMMENT_ID ,
139252 body: isSuccess ? successMessage : failureMessage
253+ });
254+
255+ show-help :
256+ if : |
257+ github.event_name == 'issue_comment' &&
258+ github.event.issue.pull_request &&
259+ github.event.comment.body == '/help'
260+ runs-on : ubuntu-latest
261+
262+ steps :
263+ - name : Show Available Commands
264+ uses : actions/github-script@v7
265+ with :
266+ script : |
267+ const helpMessage = [
268+ '## Available Commands',
269+ '',
270+ '### `/deploy-review-app`',
271+ 'Deploys your PR branch to a review environment on Control Plane.',
272+ '- Creates a new review app if one doesn\'t exist',
273+ '- Updates the existing review app if it already exists',
274+ '- Provides a unique URL to preview your changes',
275+ '- Shows build and deployment progress in real-time',
276+ '',
277+ '### `/delete-review-app`',
278+ 'Deletes the review app associated with this PR.',
279+ '- Removes all resources from Control Plane',
280+ '- Helpful for cleaning up when you\'re done testing',
281+ '- Can be re-deployed later using `/deploy-review-app`',
282+ '',
283+ '### `/help`',
284+ 'Shows this help message explaining available commands.',
285+ '',
286+ '---',
287+ '_Note: These commands only work in pull request comments._'
288+ ].join('\n');
289+
290+ await github.rest.issues.createComment({
291+ owner: context.repo.owner,
292+ repo: context.repo.repo,
293+ issue_number: context.payload.issue.number,
294+ body: helpMessage
140295 });
0 commit comments