Skip to content

CD

CD #82

Workflow file for this run

# Using multiple workflow .yaml files
# https://stackoverflow.com/questions/64009546/how-to-run-multiple-github-actions-workflows-from-sub-directories
# TODO
# Preventing concurrent workflows (e.g. multiple merges to master at once)
# https://github.blog/changelog/2021-04-19-github-actions-limit-workflow-run-or-job-concurrency/
# From: https://github.community/t/how-to-limit-concurrent-workflow-runs/16844/
#
# Further split sub-directories' actions/workflows for more granular control.
# - https://stackoverflow.com/questions/64009546/how-to-run-multiple-github-actions-workflows-from-sub-directories
# If we decide to use Docker - Using local Dockerfile in pipeline:
# steps:
# - name: Check out code
# uses: actions/checkout@v3
# - name: Build docker images
# run: docker build -t local < .devcontainer/Dockerfile # .devcontainer is the local path
# - name: Run tests
# run: docker run -it -v $PWD:/srv -w/srv local make test
# OR
# - name: Build docker images
# run: docker-compose build
# - name: Run tests
# run: docker-compose run test
# Ref: https://stackoverflow.com/questions/61154750/use-local-dockerfile-in-a-github-action
name: CD
on:
workflow_dispatch:
inputs:
clientVersion:
description: Custom version for the app rather than what's in the local config file (package.json, build.gradle, etc.); increments if 'true' is passed.
type: string
required: false
default: ""
# Publish your release in GitHub and have your pipeline react to deploy the package
release:
types: [ published ]
# Run the pipeline on merge to `master` and do the release/deploy then.
# pull_request:
# types: [ closed ]
# branches: [ master ]
#
# To run upon merge in general, apparently, there is no `merge` event, only `merge_group` which specifies merging
# when certain checks are required. Thus, mark "all checks" via `checks_requested`.
# See:
# - https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#merge_group
# merge_group:
# branches: [ checks_requested ]
#
# Run on CI completion (the `if:` in the `deploy` job below would need updating accordingly)
workflow_run:
workflows: [ 'CI' ]
types: [ completed ]
branches: [ master ]
defaults:
run:
shell: bash
working-directory: ./
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
gitUserName: ${{ github.actor }}
gitUserEmail: ${{ github.actor }}@users.noreply.github.com
nodeVersion: 16
clientVersion: "" # Can be declared via `env`, `workflow_dispatch.inputs`, or `release` -> `github.ref_name`
jobs:
cd-client:
runs-on: ubuntu-latest
outputs:
CLIENT_CACHE_ID: ${{ env.CLIENT_CACHE_ID }}
# Only run on merge to master, but not on PR to master since PRs are just drafts, not officially prod-ready code.
#
# Note: At least one job in each workflow must have no dependencies, i.e. no `needs` block.
# However, we can get around that using a conditional expression, i.e. `if` block.
#
# See:
# - https://github.community/t/depend-on-another-workflow/16311/3
# - https://stackoverflow.com/questions/66205887/only-run-github-actions-step-if-not-a-pull-request/66206183#66206183
# if: ${{ github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && (github.event.pull_request.merged || github.event.workflow_run.conclusion == 'success') }}
steps:
- name: CD - Abort run if CI failed
if: ${{ github.event.workflow_run.conclusion != null && github.event.workflow_run.conclusion != 'success' }}
# See:
# - Docs: https://docs.github.com/en/webhooks-and-events/webhooks/webhook-events-and-payloads#workflow_run
# - Example (SO post): https://stackoverflow.com/questions/67516571/github-action-triggered-by-success-of-a-different-action
run: |
echo "${{ github.event.workflow_run.name }} had conclusion of ${{ github.event.workflow_run.conclusion }}. Aborting..." >&2
exit 1
- name: CD:Client - Checkout repository branch
uses: actions/checkout@v3
- name: CD:Client - Set NodeJS version
uses: actions/setup-node@v3
with:
node-version: ${{ env.nodeVersion }}
# Consolidate any source of the new client version into one place, `env.clientVersion`, for ease of use
# throughout all other workflows/jobs/actions/steps.
#
# Since the only `release` event we listen to is `publish`, we can safely assume the ref-name is the tag name.
#
# See:
# - "Release" event and object info: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#release
- name: CD:Client - Set version number
run: |
if [[ "$GITHUB_EVENT_NAME" == 'release' ]]; then
echo "clientVersion=$GITHUB_REF_NAME" >> $GITHUB_ENV
elif [[ -n "${{ inputs.clientVersion }}" ]]; then
echo "clientVersion=${{ inputs.clientVersion }}" >> $GITHUB_ENV
fi
# It seems strangely difficult to link different workflows together without re-running them.
# As such, we can't just arbitrarily add a dependency on CI without making sure this CD run uses the
# correct respective CI run.
#
# Thus, rather than use the `gh` API or similar to get the previous CI run, simply re-init the front-end.
# This ensures the code used in this workflow is the correct version.
# i.e. We might have multiple CI/CD pipelines running at once, each with a different version of the code,
# so don't get the most up-to-date version of the code, rather get the version associated with this specific
# run (via the `CLIENT_CACHE_ID`).
#
# Note that we can't use the `needs` object here since this job needs to remain dependency-free.
- name: CD:Client CD - Init
uses: ./.github/workflows/actions/client/init
env:
GITHUB_TOKEN: ${{ env.GITHUB_TOKEN }}
gitUserName: ${{ env.gitUserName }}
gitUserEmail: ${{ env.gitUserEmail }}
nodeVersion: ${{ env.nodeVersion }}
- name: CD:Client - Output cache ID
id: cd-client-output-cache-id
run: |
echo "CLIENT_CACHE_ID=${{ env.CLIENT_CACHE_ID }}" >> $GITHUB_ENV
echo "CLIENT_CACHE_ID=${{ env.CLIENT_CACHE_ID }}" >> $GITHUB_OUTPUT
cd-deploy:
runs-on: ubuntu-latest
needs: [ cd-client ] # This automatically checks if `${{ needs.cd-client.result == 'success' }}` so job won't run if prev job was skipped or failed
env:
CLIENT_CACHE_ID: ${{ needs.cd-client.outputs.CLIENT_CACHE_ID }}
permissions:
pages: write # Grant write permissions to deploy to the `gh-pages` (or whatever is specified in "Settings") branch
id-token: write # to verify the deployment originates from an appropriate source
deployments: write
packages: write
actions: write
contents: write
steps:
- name: CD:Client - Checkout repository branch
uses: actions/checkout@v3
- name: CD:Client - Set NodeJS version
uses: actions/setup-node@v3
with:
node-version: ${{ env.nodeVersion }}
- name: CD:Client - Deploy website
uses: ./.github/workflows/actions/client/deploy
env:
GITHUB_TOKEN: ${{ env.GITHUB_TOKEN }}
gitUserName: ${{ env.gitUserName }}
gitUserEmail: ${{ env.gitUserEmail }}
nodeVersion: ${{ env.nodeVersion }}
clientVersion: ${{ env.clientVersion }}