Skip to content

Continuous Delivery #76

Continuous Delivery

Continuous Delivery #76

name: Continuous Delivery
on:
workflow_dispatch:
inputs:
merge:
description: Merge staging into main first? (y/N)
required: false
default: 'n'
concurrency:
group: cd-${{ github.ref_name }}
env:
PROJECT_NAME: arora-discord
jobs:
branch_check:
name: Branch Check
runs-on: ubuntu-latest
steps:
- name: Validate branch
run: |
if [ "$GITHUB_REF_NAME" != 'staging' ] && [ "$GITHUB_REF_NAME" != 'main' ]; then
echo 'This workflow can only be run on branches staging and main.'
exit 1
fi
metadata:
name: Metadata
runs-on: ubuntu-latest
needs: branch_check
outputs:
has_diff: ${{ steps.get_metadata.outputs.has_diff }}
stage: ${{ steps.get_metadata.outputs.stage }}
steps:
- name: Checkout code
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- name: Get metadata
id: get_metadata
env:
INPUT_MERGE: ${{ github.event.inputs.merge }}
run: |
if [ "$GITHUB_REF_NAME" = 'main' ]; then
if [ "${INPUT_MERGE,,}" = 'y' ]; then
git fetch origin staging
if ! git diff origin/main origin/staging --exit-code; then
echo 'has_diff=true' >> "$GITHUB_OUTPUT"
else
echo 'has_diff=false' >> "$GITHUB_OUTPUT"
fi
fi
echo 'stage=production' >> "$GITHUB_OUTPUT"
else
echo 'stage=staging' >> "$GITHUB_OUTPUT"
fi
merge:
name: Merge
runs-on: ubuntu-latest
needs: metadata
if: github.event.inputs.merge == 'y'
outputs:
sha: ${{ steps.get_sha.outputs.sha }}
steps:
- name: Validate inputs
env:
HAS_DIFF: ${{ fromJSON(needs.metadata.outputs.has_diff || false) }}
run: |
if [ "$GITHUB_REF_NAME" != 'main' ]; then
echo 'Can only merge when the workflow target branch is main.'
exit 1
fi
if ! $HAS_DIFF; then
echo 'There is no diff so a merge is not necessary, skipping next steps.'
fi
- name: Checkout code
if: fromJSON(needs.metadata.outputs.has_diff)
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- name: Run merge
if: fromJSON(needs.metadata.outputs.has_diff)
uses: devmasx/merge-branch@854d3ac71ed1e9deb668e0074781b81fdd6e771f # renovate: tag=v1.4.0
with:
type: now
from_branch: staging
target_branch: main
github_token: ${{ github.token }}
- name: Get merge commit SHA
id: get_sha
if: fromJSON(needs.metadata.outputs.has_diff)
run: |
git fetch origin main
echo 'sha='"$(git rev-parse origin/main)" >> "$GITHUB_OUTPUT"
continuous_integration:
name: Continuous Integration
needs: [metadata, merge]
if: fromJSON(needs.metadata.outputs.has_diff)
uses: guidojw/arora-discord/.github/workflows/continuous-integration.yml@staging
with:
sha: ${{ needs.merge.outputs.sha }}
publish_image:
name: Publish Image
needs: [metadata, merge]
if: fromJSON(needs.metadata.outputs.has_diff)
uses: guidojw/arora-discord/.github/workflows/publish-image.yml@staging
with:
sha: ${{ needs.merge.outputs.sha }}
secrets:
sentry_auth_token: ${{ secrets.SENTRY_AUTH_TOKEN }}
deploy:
name: Deploy
runs-on: ubuntu-latest
needs: [metadata, merge, continuous_integration, publish_image]
if: |
(github.ref_name == 'staging' || github.ref_name == 'main') && ((github.ref_name == 'main' &&
github.event.inputs.merge == 'y' && fromJSON(needs.metadata.outputs.has_diff) && success()) ||
((github.event.inputs.merge != 'y' || !fromJSON(needs.metadata.outputs.has_diff)) && !cancelled()))
steps:
- name: Checkout code
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
with:
ref: ${{ needs.merge.outputs.sha }}
- name: Start deployment
uses: bobheadxi/deployments@88ce5600046c82542f8246ac287d0a53c461bca3 # v1.4.0
id: start_deployment
with:
step: start
env: ${{ needs.metadata.outputs.stage }}
- name: Deploy
uses: appleboy/ssh-action@55dabf81b49d4120609345970c91507e2d734799 # v1.0.0
env:
STAGE: ${{ needs.metadata.outputs.stage }}
with:
host: ${{ secrets.SSH_HOST }}
username: github-actions
key: ${{ secrets.SSH_PRIVATE_KEY }}
envs: PROJECT_NAME,STAGE
script: |
cd /opt/docker/$PROJECT_NAME/$STAGE
docker-compose pull
if [ "$STAGE" = 'production' ]; then
docker-compose run --rm nsadmin yarn run typeorm migration:run -d dist/configs/data-source.js
docker-compose run --rm nsadmin node bin/update-commands.js
docker-compose run --rm tradmin node bin/update-commands.js
else
docker-compose run --rm app yarn run typeorm migration:run -d dist/configs/data-source.js
docker-compose run --rm app node bin/update-commands.js
fi
docker-compose up -d
- name: Finalize Sentry release
uses: getsentry/action-release@4744f6a65149f441c5f396d5b0877307c0db52c7 # v1.4.1
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ vars.SENTRY_ORG_NAME }}
SENTRY_PROJECT: ${{ env.PROJECT_NAME }}
with:
environment: ${{ needs.metadata.outputs.stage }}
version: ${{ needs.merge.outputs.sha }}
set_commits: skip
- name: Finish deployment
uses: bobheadxi/deployments@88ce5600046c82542f8246ac287d0a53c461bca3 # v1.4.0
if: steps.start_deployment.conclusion == 'success' && always()
with:
step: finish
status: ${{ job.status }}
deployment_id: ${{ steps.start_deployment.outputs.deployment_id }}
env: ${{ needs.metadata.outputs.stage }}
update_check_run:
name: Update Check Run
runs-on: ubuntu-latest
needs: [branch_check, metadata, merge, continuous_integration, publish_image, deploy]
if: (github.ref_name == 'staging' || github.ref_name == 'main') && always()
steps:
- name: Get conclusion
id: get_conclusion
env:
RESULTS: ${{ join(needs.*.result, ' ') }}
run: |
echo 'conclusion=success' >> "$GITHUB_OUTPUT"
for RESULT in $RESULTS; do
if [ "$RESULT" = 'cancelled' ] || [ "$RESULT" = 'failure' ]; then
echo 'conclusion='"$RESULT" >> "$GITHUB_OUTPUT"
break
fi
done
- name: Update Continuous Delivery check run
uses: guidojw/actions/update-check-run@870d7c8de5aeb08420bb88d8fbddb0222a9eac61 # v1.4.0
with:
app_id: ${{ vars.GH_APP_ID }}
private_key: ${{ secrets.GH_APP_PRIVATE_KEY }}
sha: ${{ needs.merge.outputs.sha }}
name: Continuous Delivery
conclusion: ${{ steps.get_conclusion.outputs.conclusion }}
details_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}