Skip to content

Commit

Permalink
move workflow scripts to separate file to allow for testing
Browse files Browse the repository at this point in the history
update version to v1.1.1
  • Loading branch information
elrayle committed Jul 11, 2024
1 parent d68d580 commit 54d9f4b
Show file tree
Hide file tree
Showing 15 changed files with 322 additions and 54 deletions.
47 changes: 23 additions & 24 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.
# v1.1.1 - 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 @@ -65,35 +65,34 @@ jobs:
outputs:
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: 'v1.1.1'
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/[email protected].0
uses: clearlydefined/operations/.github/workflows/[email protected].1
secrets:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
PRODUCTION_DEPLOYERS: ${{ secrets.PRODUCTION_DEPLOYERS }}
Expand All @@ -105,7 +104,7 @@ jobs:
deploy-primary-app-to-azure:
name: Deploy to primary Azure app
needs: [get-version, build-and-publish-image]
uses: clearlydefined/operations/.github/workflows/[email protected].0
uses: clearlydefined/operations/.github/workflows/[email protected].1
secrets:
AZURE_WEBAPP_PUBLISH_PROFILE: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
Expand All @@ -121,7 +120,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/[email protected].0
uses: clearlydefined/operations/.github/workflows/[email protected].1
secrets:
AZURE_WEBAPP_PUBLISH_PROFILE: ${{ secrets.AZURE_SECONDARY_WEBAPP_PUBLISH_PROFILE }}
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
Expand Down
26 changes: 14 additions & 12 deletions .github/workflows/app-build-docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ on:

jobs:
check-deployable:
uses: clearlydefined/operations/.github/workflows/[email protected].0
uses: clearlydefined/operations/.github/workflows/[email protected].1
with:
deploy-env: ${{ inputs.deploy-env }}
secrets:
Expand All @@ -44,20 +44,22 @@ jobs:
outputs:
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: 'v1.1.1'
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"
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 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/[email protected].0
uses: clearlydefined/operations/.github/workflows/[email protected].1
with:
deploy-env: ${{ inputs.deploy-env }}
secrets:
Expand Down
41 changes: 24 additions & 17 deletions .github/workflows/app-is-deployable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,45 @@ jobs:
outputs:
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: 'v1.1.1'
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: 'v1.1.1'
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: |
echo "ORG_ID=${{ env.ORG_ID }}"
user="${{ github.actor }}"
org_id=${{ env.ORG_ID }}
org_name=${{ github.repository_owner }}
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: CI

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"
17 changes: 17 additions & 0 deletions tests/scripts/app-workflows/fixtures/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions tests/scripts/app-workflows/test-confirm-dev.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env bats

load 'test_helpers'

@test "deploy to dev environment" {
run ./scripts/app-workflows/confirm-dev.sh dev
test_value 0 "$status"
test_value "Deploying to dev environment" "${lines[0]}"
test_value "confirm-dev -> outputs -> is_dev: true" "${lines[1]}"
test_value true "${lines[2]}"
}

@test "deploy to prod environment" {
run ./scripts/app-workflows/confirm-dev.sh prod
test_value 0 "$status"
test_value "Deploying to prod or UNKNOWN environment" "${lines[0]}"
test_value "confirm-dev -> outputs -> is_dev: false" "${lines[1]}"
test_value false "${lines[2]}"
}

@test "deploy to anything else defaults to prod environment for tighter restrictions" {
run ./scripts/app-workflows/confirm-dev.sh UNKNOWN_ENV
test_value 0 "$status"
test_value "Deploying to prod or UNKNOWN environment" "${lines[0]}"
test_value "confirm-dev -> outputs -> is_dev: false" "${lines[1]}"
test_value false "${lines[2]}"
}
23 changes: 23 additions & 0 deletions tests/scripts/app-workflows/test-determine-image-name.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bats

load 'test_helpers'

@test "deploy to dev environment" {
run ./scripts/app-workflows/determine-image-name.sh test-org/test-repo dev test-tag
test_value 0 "$status"
test_value "determine_image_name -> outputs -> image_name_with_tag: ghcr.io/test-org/test-repo-dev:test-tag" "${lines[0]}"
test_value ghcr.io/test-org/test-repo-dev:test-tag "${lines[1]}"
}

@test "deploy to prod environment" {
run ./scripts/app-workflows/determine-image-name.sh test-org/test-repo prod test-tag
test_value 0 "$status"
test_value "determine_image_name -> outputs -> image_name_with_tag: ghcr.io/test-org/test-repo:test-tag" "${lines[0]}"
test_value ghcr.io/test-org/test-repo:test-tag "${lines[1]}"
}

@test "invalid deploy environment" {
run ./scripts/app-workflows/determine-image-name.sh test-org/test-repo BAD_ENV test-tag
test_value 1 "$status"
test_value "ERROR: Invalid deploy environment: BAD_ENV. Must be 'dev' or 'prod'" "${lines[0]}"
}
Loading

0 comments on commit 54d9f4b

Please sign in to comment.