Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move workflow scripts to separate file to allow for testing #86

Merged
merged 1 commit into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 31 additions & 26 deletions .github/workflows/app-build-and-deploy.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# This workflow will build a docker image, push it to ghcr.io, and deploy it to an Azure WebApp.
# v1.1.0 - This tag coordinates the other reusable parts of this workflow.
# v2.0.0 - This tag coordinates the other reusable parts of this workflow.
# * app-build-docker-image.yml
# * app-deploy-to-azure.yml
# * app-is-deployable.yml
Expand Down Expand Up @@ -45,13 +45,18 @@ on:
description: 'postfix to apply to the base name for a secondary deploy site (e.g. -prod-europe, do not specify if no secondary site)'
type: string
default: ''
docker-build-args:
description: 'optionally pass in build args to the Docker build command (e.g. "MY_VAR=my_value")'
required: false
type: string


jobs:
determine-trigger:
name: Determine if this was triggered by a release or workflow_dispatch
runs-on: ubuntu-latest
outputs:
is-release: ${{ env.IS_RELEASE }}
is-release: "${{ env.IS_RELEASE }}"
steps:
- name: Check if this was triggered by a release
id: release
Expand All @@ -63,49 +68,49 @@ jobs:
runs-on: ubuntu-latest
needs: determine-trigger
outputs:
version: ${{ env.VERSION }}
version: "${{ env.VERSION }}"
steps:
- uses: actions/[email protected]
- name: Download package-lock.json
uses: actions/download-artifact@v4
with:
name: package-lock.json
path: .
- name: Checkout this repo
uses: actions/[email protected]
with:
repository: 'clearlydefined/operations'
ref: 'v2.0.0'
path: 'operations'
- name: Get version from package-lock.json
id: get_version
shell: bash
run: |
version='v'$(jq -r '.version' package-lock.json) # e.g. v1.2.0
if [[ ${{ inputs.deploy-env }} == 'prod' ]]; then
if [[ ${{ needs.determine-trigger.outputs.is-release }} == 'true' ]]; then
# validate the version when triggered by a release
if [[ $version != ${{ github.event.release.tag_name }} ]]; then
echo "Version in package-lock.json ($version) does not match the release tag (${{ github.event.release.tag_name }})"
exit 1
fi
fi
elif [[ ${{ inputs.deploy-env }} == 'dev' ]]; then
short_sha=$(echo "${{ github.sha }}" | cut -c 1-10)
version=$version'-dev-'$short_sha # e.g. v1.2.0-dev:1234567890
else
echo "Invalid deploy-env: ${{ inputs.deploy-env }}. Must be 'dev' or 'prod'"
exit 1
fi

script_log=$(./operations/scripts/app-workflows/get-version.sh \
"${{ inputs.deploy-env }}" \
"${{ needs.determine-trigger.outputs.is-release }}" \
"${{ github.event.release.tag_name }}" \
"${{ github.sha }}") || (echo "$script_log" && exit 1)
echo -e "---- script log\n$script_log\n----"; \
version=$(echo "$script_log" | tail -n 1)
echo "VERSION=$version" >> $GITHUB_ENV
echo "BuildAndDeploy: get-version -> outputs -> version: $version"


build-and-publish-image:
name: Build and publish Docker image
needs: get-version
uses: clearlydefined/operations/.github/workflows/app-build-docker-image.yml@v1.1.0
uses: clearlydefined/operations/.github/workflows/app-build-docker-image.yml@v2.0.0
secrets:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
PRODUCTION_DEPLOYERS: ${{ secrets.PRODUCTION_DEPLOYERS }}
with:
deploy-env: ${{ inputs.deploy-env }}
application-type: ${{ inputs.application-type }}
image-tag: ${{ needs.get-version.outputs.version }}
build-args: ${{ inputs.docker-build-args }}

deploy-primary-app-to-azure:
name: Deploy to primary Azure app
needs: [get-version, build-and-publish-image]
uses: clearlydefined/operations/.github/workflows/app-deploy-to-azure.yml@v1.1.0
uses: clearlydefined/operations/.github/workflows/app-deploy-to-azure.yml@v2.0.0
secrets:
AZURE_WEBAPP_PUBLISH_PROFILE: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
Expand All @@ -121,7 +126,7 @@ jobs:
name: Deploy to secondary Azure app
if: ${{ inputs.secondary-azure-app-name-postfix != '' }}
needs: [get-version, build-and-publish-image]
uses: clearlydefined/operations/.github/workflows/app-deploy-to-azure.yml@v1.1.0
uses: clearlydefined/operations/.github/workflows/app-deploy-to-azure.yml@v2.0.0
secrets:
AZURE_WEBAPP_PUBLISH_PROFILE: ${{ secrets.AZURE_SECONDARY_WEBAPP_PUBLISH_PROFILE }}
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
Expand Down
34 changes: 21 additions & 13 deletions .github/workflows/app-build-docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,18 @@ on:
description: 'the tag to use for the image (e.g. prod: v1.2.0, dev: v1.2.0+dev:1D3F567890)'
required: true
type: string
build-args:
description: 'optionally pass in build args to the Docker build command (e.g. "MY_VAR=my_value")'
required: false
type: string

outputs:
docker-image-name-with-tag:
value: ${{ jobs.determine-image-name.outputs.docker-image-name-with-tag }}

jobs:
check-deployable:
uses: clearlydefined/operations/.github/workflows/app-is-deployable.yml@v1.1.0
uses: clearlydefined/operations/.github/workflows/app-is-deployable.yml@v2.0.0
with:
deploy-env: ${{ inputs.deploy-env }}
secrets:
Expand All @@ -42,22 +46,25 @@ jobs:
name: Determine Image Name
runs-on: ubuntu-latest
outputs:
docker-image-name-with-tag: ${{ env.DOCKER_IMAGE_NAME_WITH_TAG }}
docker-image-name-with-tag: "${{ env.DOCKER_IMAGE_NAME_WITH_TAG }}"
steps:
- name: Checkout this repo
uses: actions/[email protected]
with:
repository: 'clearlydefined/operations'
ref: 'v2.0.0'
path: 'operations'
- name: Determine Docker Image Name
id: determine_image_name
run: |
image_base_name=ghcr.io/${{ github.repository }} # e.g. ghcr.io/clearlydefined/service
if [[ ${{ inputs.deploy-env }} == 'prod' ]] ; then
image_name_with_tag=$image_base_name':${{ inputs.image-tag }}'
elif [[ ${{ inputs.deploy-env }} == 'dev' ]] ; then
image_name_with_tag=$image_base_name'-dev:${{ inputs.image-tag }}'
else
echo "Invalid deploy-env: ${{ inputs.deploy-env }}. Must be 'dev' or 'prod'"
exit 1
fi
echo "DOCKER_IMAGE_NAME_WITH_TAG=$image_name_with_tag" >> $GITHUB_ENV
echo "DetermineImageName: determine_image_name -> outputs -> image_name_with_tag: $image_name_with_tag"
echo "BUILD_ARGS=${{ inputs.build-args }}"
script_log=$(./operations/scripts/app-workflows/determine-image-name.sh \
"${{ github.repository }}" \
"${{ inputs.deploy-env }}" \
"${{ inputs.image-tag }}") || (echo "$script_log" && exit 1)
echo -e "---- script log\n$script_log\n----"; \
image_name=$(echo "$script_log" | tail -n 1)
echo "DOCKER_IMAGE_NAME_WITH_TAG=$image_name" >> $GITHUB_ENV

build-docker-image:
name: Build Image
Expand All @@ -80,6 +87,7 @@ jobs:
context: .
push: true
file: Dockerfile
build-args: ${{ inputs.build-args }}
tags: ${{ needs.determine-image-name.outputs.docker-image-name-with-tag }}
labels: |
env=${{ inputs.deploy-env }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/app-deploy-to-azure.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ on:

jobs:
check-deployable:
uses: clearlydefined/operations/.github/workflows/app-is-deployable.yml@v1.1.0
uses: clearlydefined/operations/.github/workflows/app-is-deployable.yml@v2.0.0
with:
deploy-env: ${{ inputs.deploy-env }}
secrets:
Expand Down
46 changes: 26 additions & 20 deletions .github/workflows/app-is-deployable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,43 +20,49 @@ jobs:
confirm-dev:
runs-on: ubuntu-latest
outputs:
is-dev: ${{ env.IS_DEV }}
is-dev: "${{ env.IS_DEV }}"
steps:
# erring on the side of caution by assuming everything is prod unless it is identified as dev and ends in -dev
- name: Checkout this repo
uses: actions/[email protected]
with:
repository: 'clearlydefined/operations'
ref: 'v2.0.0'
path: 'operations'
- id: confirm-dev
shell: bash
run: |
is_dev=false
if [[ "${{ inputs.deploy-env }}" == 'dev' ]]; then
is_dev=true
echo "Deploying to dev environment"
else
echo "Deploying to prod or UNKNOWN environment"
fi
script_log=$(./operations/scripts/app-workflows/confirm-dev.sh \
"${{ inputs.deploy-env }}") || (echo "$script_log" && exit 1)
echo -e "---- script log\n$script_log\n----"; \
is_dev=$(echo "$script_log" | tail -n 1)
echo "IS_DEV=$is_dev" >> $GITHUB_ENV
echo "Deployable: confirm-dev -> outputs -> is-dev: $is_dev"


deployable:
runs-on: ubuntu-latest
needs: confirm-dev
# run deployable check for anything that is NOT dev (most conservative approach)
if: ${{ needs.confirm-dev.outputs.is-dev != 'true' }}
steps:
steps:
- name: Checkout this repo
uses: actions/[email protected]
with:
repository: 'clearlydefined/operations'
ref: 'v2.0.0'
path: 'operations'

- name: Get organization ID
run: |
org_name=${{ github.repository_owner }}
org_info=$(curl \
-H "Authorization: token ${{ secrets.DEPLOY_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/orgs/$org_name)
org_id=$(echo "$org_info" | jq .id)
script_log=$(./operations/scripts/app-workflows/get-org-id.sh \
"${{ github.repository_owner }}") || (echo "$script_log" && exit 1)
echo -e "---- script log\n$script_log\n----"; \
org_id=$(echo "$script_log" | tail -n 1)
echo "ORG_ID=$org_id" >> $GITHUB_ENV

- name: Check team membership
run: |
user="${{ github.actor }}"
org_id=${{ env.ORG_ID }}
org_name=${{ github.repository_owner }}
org_id="${{ env.ORG_ID }}"
org_name="${{ github.repository_owner }}"

team_info=$(curl \
-H "Authorization: token ${{ secrets.DEPLOY_TOKEN }}" \
Expand Down
26 changes: 26 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Run Tests

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
test:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Install Bats
run: |
git clone https://github.com/bats-core/bats-core.git
cd bats-core
sudo ./install.sh /usr/local

- name: Run Bats tests
run: bats ./tests/scripts/app-workflows/*.bats
21 changes: 21 additions & 0 deletions scripts/app-workflows/confirm-dev.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash

# Inputs
# $1 - deploy_env: environment to deploy (i.e. dev | prod) - used as a label for the Docker image
#
# Outputs
# is-dev: 'true' if deploying to dev environment, 'false' otherwise

deploy_env="$1"

# erring on the side of caution by assuming everything is prod unless it is identified as dev and ends in -dev
is_dev='false'
if [[ "$deploy_env" == 'dev' ]]; then
is_dev='true'
echo "Deploying to dev environment"
else
echo "Deploying to prod or UNKNOWN environment"
fi

echo "confirm-dev -> outputs -> is_dev: $is_dev"
echo $is_dev
26 changes: 26 additions & 0 deletions scripts/app-workflows/determine-image-name.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash

# Inputs
# $1 - repo: the orgname/reponame where the image will be published (e.g. 'clearlydefined/service')
# $2 - deploy_env: environment to deploy (i.e. dev | prod) - used as a label for the Docker image
# $3 - image-tag: the tag to use for the image (e.g. prod: v1.2.0, dev: v1.2.0+dev:1D3F567890)
#
# Outputs
# image_name_with_tag: the full image name with tag (e.g. ghcr.io/clearlydefined/service:v1.2.0)

repo="$1"
deploy_env="$2"
image_tag="$3"

image_base_name="ghcr.io/$repo" # e.g. ghcr.io/clearlydefined/service
if [[ "$deploy_env" == 'prod' ]] ; then
image_name_with_tag="$image_base_name:$image_tag"
elif [[ "$deploy_env" == 'dev' ]] ; then
image_name_with_tag="$image_base_name-dev:$image_tag"
else
echo "ERROR: Invalid deploy environment: $deploy_env. Must be 'dev' or 'prod'"
exit 1
fi

echo "determine_image_name -> outputs -> image_name_with_tag: $image_name_with_tag"
echo "$image_name_with_tag"
19 changes: 19 additions & 0 deletions scripts/app-workflows/get-org-id.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash

# Inputs
# $1 - org_name: the orgname of the repo (e.g. 'clearlydefined/service' has owner 'clearlydefined')
#
# Outputs
# org_id: the id of the organization that owns the repo

org_name="$1"

org_info=$(curl -s -H "Accept: application/vnd.github.v3+json" "https://api.github.com/orgs/$org_name")
org_id=$(echo "$org_info" | jq .id)
if [[ "$org_id" == "null" ]]; then
echo "ERROR: Organization not found: $org_name"
exit 1
fi

echo "get-org-id -> outputs -> org_id: $org_id"
echo $org_id
37 changes: 37 additions & 0 deletions scripts/app-workflows/get-version.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/bin/bash

# Inputs
# $1 - deploy_env: environment to deploy (i.e. dev | prod) - used as a label for the Docker image
# $2 - is_release: true if the deployment is triggered by a release, false otherwise
# $3 - release_tag: the tag of the release that triggered the deployment (empty if not a release)
# $4 - sha: the git sha of the commit being deployed
# $5 - lock_file: the path to the package-lock.json file (default: /package-lock.json)
#
# Outputs
# version: the version of the package to deploy (e.g. v1.2.0, v1.2.0-dev-1234567890)

deploy_env="$1"
is_release="$2"
release_tag="$3"
sha="$4"
lock_file="${5:-package-lock.json}"

version='v'$(jq -r '.version' $lock_file) # e.g. v1.2.0
if [[ "$deploy_env" == 'prod' ]]; then
if [[ "$is_release" == 'true' ]]; then
# validate the version when triggered by a release
if [[ "$version" != "$release_tag" ]]; then
echo "ERROR: Version in package-lock.json ($version) does not match the release tag ($release_tag)"
exit 1
fi
fi
elif [[ "$deploy_env" == 'dev' ]]; then
short_sha=$(echo "$sha" | cut -c 1-10)
version=$version'-dev-'$short_sha # e.g. v1.2.0-dev-1234567890
else
echo "ERROR: Invalid deploy environment: $deploy_env. Must be 'dev' or 'prod'"
exit 1
fi

echo "get-version.sh -> outputs -> version: $version"
echo "$version"
Loading
Loading