Skip to content

Improvements to deployments #34

Improvements to deployments

Improvements to deployments #34

name: Deploy to Control Plane

Check failure on line 1 in .github/workflows/deploy-to-control-plane.yml

View workflow run for this annotation

GitHub Actions / Deploy to Control Plane

Invalid workflow file

The workflow is not valid. .github/workflows/deploy-to-control-plane.yml (Line: 3, Col: 11): Unexpected symbol: '?'. Located at position 114 within expression: github.event_name == 'pull_request' || (github.event_name == 'issue_comment' && github.event.issue.pull_request) ? 'Deploying Review App' : format('Deploying {0} to Staging App', github.ref_name)
run-name: "${{ github.event_name == 'pull_request' || (github.event_name == 'issue_comment' && github.event.issue.pull_request) ? 'Deploying Review App' : format('Deploying {0} to Staging App', github.ref_name) }}"
on:
pull_request:
types: [opened, synchronize, reopened]
issue_comment:
types: [created]
# Use concurrency to cancel in-progress runs
concurrency:
group: deploy-${{ github.event.pull_request.number || github.event.issue.number }}
cancel-in-progress: true
env:
APP_NAME: qa-react-webpack-rails-tutorial-pr-${{ github.event.pull_request.number || github.event.issue.number }}
CPLN_ORG: ${{ secrets.CPLN_ORG_STAGING }}
CPLN_TOKEN: ${{ secrets.CPLN_TOKEN_STAGING }}
PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }}
jobs:
deploy:
if: |
github.event_name == 'pull_request' ||
(github.event_name == 'issue_comment' &&
github.event.comment.body == '/deploy-review-app' &&
github.event.issue.pull_request)
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
pull-requests: write
issues: write
steps:
- name: Get PR HEAD Ref
if: ${{ github.event_name == 'issue_comment' }}
id: getRef
run: |
echo "PR_REF=$(gh pr view $PR_NUMBER --repo ${{ github.repository }} --json headRefName | jq -r '.headRefName')" >> $GITHUB_OUTPUT
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ steps.getRef.outputs.PR_REF || github.ref }}
- name: Setup Environment
uses: ./.github/actions/setup-environment
- name: Initialize Deployment
id: init-deployment
uses: actions/github-script@v7
with:
script: |
// Helper functions
const getWorkflowUrl = (runId) =>
`${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}`;
const getJobUrl = (runId, jobId, prNumber) =>
`${getWorkflowUrl(runId)}/job/${jobId}?pr=${prNumber}`;
// Get PR number consistently
const prNumber = process.env.PR_NUMBER;
// Create GitHub deployment
const deployment = await github.rest.repos.createDeployment({
owner: context.repo.owner,
repo: context.repo.repo,
ref: context.sha,
environment: 'review-app',
auto_merge: false,
required_contexts: []
});
// Get the job ID
const jobs = await github.rest.actions.listJobsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.runId
});
const jobId = jobs.data.jobs.find(job => job.name === 'deploy')?.id;
const jobUrl = getJobUrl(context.runId, jobId, prNumber);
// Create initial comment
const comment = await github.rest.issues.createComment({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
body: [
'🚀 Starting deployment for PR ' + prNumber,
'',
'[View Deployment Log](' + jobUrl + ')'
].join('\n')
});
// Set deployment status to in_progress
await github.rest.repos.createDeploymentStatus({
owner: context.repo.owner,
repo: context.repo.repo,
deployment_id: deployment.data.id,
state: 'in_progress',
description: 'Deployment is in progress'
});
return {
deploymentId: deployment.data.id,
commentId: comment.data.id,
workflowUrl: getWorkflowUrl(context.runId)
};
- name: Setup cpflow app
run: |
set -e
# Validate required environment variables
: "${APP_NAME:?APP_NAME environment variable is required}"
if ! cpflow exists -a ${{ env.APP_NAME }} ; then
echo "🔧 Setting up new application: ${{ env.APP_NAME }}"
if ! cpflow setup-app -a ${{ env.APP_NAME }}; then
echo "❌ Failed to setup application"
exit 1
fi
echo "✅ Application setup complete"
fi
- name: Deploy to Control Plane
id: deploy
uses: ./.github/actions/deploy-to-control-plane
env:
CPLN_TOKEN: ${{ secrets.CPLN_TOKEN_STAGING }}
CPLN_ORG: ${{ secrets.CPLN_ORG_STAGING }}
with:
app_name: ${{ env.APP_NAME }}
org: ${{ env.CPLN_ORG }}
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Update Status
if: always()
uses: actions/github-script@v7
with:
script: |
const isSuccess = '${{ job.status }}' === 'success';
const result = ${{ steps.init-deployment.outputs.result }};
const deploymentId = result.deploymentId;
const commentId = result.commentId;
const workflowUrl = result.workflowUrl;
const railsUrl = '${{ steps.deploy.outputs.rails_url }}';
const prNumber = process.env.PR_NUMBER;
// Update deployment status
const deploymentStatus = {
owner: context.repo.owner,
repo: context.repo.repo,
deployment_id: deploymentId,
state: isSuccess ? 'success' : 'failure',
description: isSuccess ? '✅ Deployment successful' : '❌ Deployment failed'
};
if (isSuccess) {
deploymentStatus.environment_url = railsUrl;
}
try {
await github.rest.repos.createDeploymentStatus(deploymentStatus);
} catch (error) {
console.error('Failed to update deployment status:', error);
throw error;
}
// Update the initial comment
const successMessage = [
'✅ Deployment Successful for PR ' + prNumber,
'',
'🚀 Rails App: [' + railsUrl + '](' + railsUrl + ')',
'',
'[View Workflow Status](' + workflowUrl + ')'
].join('\n');
const failureMessage = [
'❌ Deployment failed for PR ' + prNumber,
'',
'Commit: ' + context.sha.substring(0, 7),
'',
'[View Workflow Status](' + workflowUrl + ')'
].join('\n');
try {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: commentId,
body: isSuccess ? successMessage : failureMessage
});
} catch (error) {
console.error('Failed to update comment:', error);
throw error;
}