Skip to content

Merge pull request #115 from bcgov/testing-deploy-3 #74

Merge pull request #115 from bcgov/testing-deploy-3

Merge pull request #115 from bcgov/testing-deploy-3 #74

Workflow file for this run

name: Merge to Main
on:
push:
branches:
- main
paths-ignore:
- ".github/ISSUE_TEMPLATE/*"
- "**.md"
workflow_dispatch:
env:
REGISTRY: ghcr.io
NAME: nr-ticdi
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: true
jobs:
# https://github.com/marketplace/actions/ghcr-io-container-cleanup
cleanup-ghcr:
name: Cleanup Container Registry
runs-on: ubuntu-22.04
steps:
- name: Delete old packages
uses: davahome/[email protected]
with:
delete_untagged: 1
keep_versions: 10
keep_versions_untagged: 0
minimum_days: 14
owner: orgs/bcgov
package: ${{ github.event.repository.name }}
skip_tags: prod-frontend,prod-backend
token: ${{ secrets.GHCR_TOKEN }}
codeql:
name: Semantic Code Analysis
runs-on: ubuntu-22.04
permissions:
actions: read
contents: read
security-events: write
steps:
- uses: actions/checkout@v3
- name: Initialize
uses: github/codeql-action/init@v2
with:
languages: javascript
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
# SonarCloud runs in the main branch are needed to compare against PRs
# sonarcloud:
# name: Static Analysis
# runs-on: ubuntu-22.04
# steps:
# - uses: actions/checkout@v3
# # Disable shallow clone for SonarCloud analysis
# with:
# fetch-depth: 0
# - name: Backend Tests
# run: |
# cd frontend
# npm ci
# npm run test:cov
# - name: Frontend Tests
# run: |
# cd frontend
# npm ci
# npm run test:cov
# - name: SonarCloud Scan
# uses: SonarSource/sonarcloud-github-action@master
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
# with:
# args: >
# -Dsonar.exclusions=**/test/**,.github/**/*
# -Dsonar.organization=bcgov-sonarcloud
# -Dsonar.javascript.lcov.reportPaths=backend/coverage/lcov.info,frontend/coverage/lcov.info
# -Dsonar.cobertura.reportPaths=backend/coverage/cobertura-coverage.xml,frontend/coverage/cobertura-coverage.xml
# -Dsonar.project.monorepo.enabled=true
# -Dsonar.projectKey=${{ github.event.repository.name }}
# -Dsonar.sources=backend,frontend
# -Dsonar.tests=backend/test,frontend/test
deploy-test:
name: TEST Deployment
needs:
- cleanup-ghcr
- codeql
# - sonarcloud
runs-on: ubuntu-22.04
environment:
name: test
env:
ZONE: test
steps:
- uses: actions/checkout@v3
- name: Deploy
run: |
# Login to OpenShift and select project
oc login --token=${{ secrets.OC_TOKEN }} --server=${{ secrets.OC_SERVER }}
oc project ${{ secrets.OC_NAMESPACE }}
# Do not replace database; 'oc create' kicks up an error if objects already exist
oc process -f .github/openshift/deploy.database.yml -p ZONE=${{ env.ZONE }} | oc create -f - || true
# Process and apply deployment templates
oc process -f .github/openshift/deploy.backend.yml -p ZONE=${{ env.ZONE }} \
-p PROMOTE=${{ github.repository }}:${{ env.ZONE }}-backend | oc apply -f -
oc process -f .github/openshift/deploy.frontend.yml -p ZONE=${{ env.ZONE }} \
-p PROMOTE=${{ github.repository }}:${{ env.ZONE }}-frontend | oc apply -f -
# Follow any active rollouts (see deploymentconfigs)
oc rollout status dc/${{ env.NAME }}-${{ env.ZONE }}-database -w
oc rollout status dc/${{ env.NAME }}-${{ env.ZONE }}-backend -w
oc rollout status dc/${{ env.NAME }}-${{ env.ZONE }}-frontend -w
# Remove completed build runs, build pods and deployment pods
for p in $(oc get po | grep "Completed" | awk '{print $1}')
do
oc delete po ${p}
done
zap-backend:
name: Backend Pen Tests
needs:
- deploy-test
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: ZAP Scan
uses: zaproxy/[email protected]
with:
target: https://${{ env.NAME }}-test-backend.apps.silver.devops.gov.bc.ca/
cmd_options: "-a"
allow_issue_writing: false
fail_action: false
zap-frontend:
name: Frontend Pen Tests
needs:
- deploy-test
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: ZAP Scan
uses: zaproxy/[email protected]
with:
target: https://${{ env.NAME }}-test-frontend.apps.silver.devops.gov.bc.ca/
cmd_options: "-a"
allow_issue_writing: false
fail_action: false
# https://github.com/snyk/cli, https://github.com/snyk/actions
# Note: using free tier - called late in pipeline to limit runs
# snyk:
# name: Vulnerability Report
# needs:
# - zap-backend
# - zap-frontend
# runs-on: ubuntu-22.04
# steps:
# - uses: actions/checkout@v3
#
# - name: Run Snyk to check for vulnerabilities
# uses: snyk/actions/node@master
# continue-on-error: true # To make sure that SARIF upload gets called
# env:
# SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
# with:
# args: --all-projects --severity-threshold=high --sarif-file-output=snyk.sarif
# - name: Upload result to GitHub Code Scanning
# uses: github/codeql-action/upload-sarif@v2
# with:
# sarif_file: snyk.sarif
# https://github.com/marketplace/actions/aqua-security-trivy
trivy-repo:
name: Repository Report
needs:
- zap-backend
- zap-frontend
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Run Trivy vulnerability scanner in repo mode
uses: aquasecurity/[email protected]
with:
scan-type: "fs"
format: "sarif"
output: "trivy-results.sarif"
ignore-unfixed: true
severity: "CRITICAL,HIGH"
security-checks: "vuln,secret,config"
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: "trivy-results.sarif"
image-backend:
name: Backend Image Handling
needs:
- zap-backend
- zap-frontend
outputs:
build: ${{ steps.check.outputs.build }}
env:
COMPONENT: backend
PREV: test
ZONE: prod
runs-on: ubuntu-22.04
steps:
- name: Check for image changes
id: check
run: |
# Vars
IMG_PREV="${{ env.REGISTRY }}/${{ github.repository }}:${{ env.PREV }}-${{ env.COMPONENT }}"
IMG_ZONE="${{ env.REGISTRY }}/${{ github.repository }}:${{ env.ZONE }}-${{ env.COMPONENT }}"
# Pull previous image; grab SHA
docker pull "${IMG_PREV}"
SHA_PREV=$(docker inspect -f '{{.Id}}' "${IMG_PREV}")
# Use blank SHA for promoted image, unless a real one exists instead
docker pull "${IMG_ZONE}" && \
SHA_ZONE=$(docker inspect -f '{{.Id}}' "${IMG_ZONE}") ||
SHA_ZONE=""
# Output SHAs
echo -e "\n${IMG_PREV}: ${SHA_PREV}"
echo -e "${IMG_ZONE}: ${SHA_ZONE}\n"
# If different, then trigger updates
if [[ "${SHA_PREV}" != "${SHA_ZONE}" ]]; then
echo "::set-output name=build::true"
echo "Image has changed"
exit 0
fi
echo "Image promotion not required"
image-frontend:
name: Frontend Image Handling
needs:
- zap-backend
- zap-frontend
outputs:
build: ${{ steps.check.outputs.build }}
env:
COMPONENT: frontend
PREV: test
ZONE: prod
runs-on: ubuntu-22.04
steps:
- name: Check for image changes
id: check
run: |
# Vars
IMG_PREV="${{ env.REGISTRY }}/${{ github.repository }}:${{ env.PREV }}-${{ env.COMPONENT }}"
IMG_ZONE="${{ env.REGISTRY }}/${{ github.repository }}:${{ env.ZONE }}-${{ env.COMPONENT }}"
# Pull previous image; grab SHA
docker pull "${IMG_PREV}"
SHA_PREV=$(docker inspect -f '{{.Id}}' "${IMG_PREV}")
# Use blank SHA for promoted image, unless a real one exists instead
docker pull "${IMG_ZONE}" && \
SHA_ZONE=$(docker inspect -f '{{.Id}}' "${IMG_ZONE}") ||
SHA_ZONE=""
# Output SHAs
echo -e "\n${IMG_PREV}: ${SHA_PREV}"
echo -e "${IMG_ZONE}: ${SHA_ZONE}\n"
# If different, then trigger updates
if [[ "${SHA_PREV}" != "${SHA_ZONE}" ]]; then
echo "::set-output name=build::true"
echo "Image has changed"
exit 0
fi
echo "Image promotion not required"
deploy-prod:
name: PROD Deployment
needs:
- image-backend
- image-frontend
# - snyk
- trivy-repo
runs-on: ubuntu-22.04
environment:
name: prod
env:
ZONE: prod
PREV: test
steps:
- name: Remove any stale backend images
if: needs.image-backend.outputs.build == 'true'
env:
COMPONENT: backend
run: |
# Login to OpenShift and select project
oc login --token=${{ secrets.OC_TOKEN }} --server=${{ secrets.OC_SERVER }}
oc project ${{ secrets.OC_NAMESPACE }}
oc delete is/${{ env.NAME }}-${{ env.ZONE}}-${{ env.COMPONENT }} || true
- name: Remove any stale frontend images
if: needs.image-frontend.outputs.build == 'true'
env:
COMPONENT: frontend
run: |
# Login to OpenShift and select project
oc login --token=${{ secrets.OC_TOKEN }} --server=${{ secrets.OC_SERVER }}
oc project ${{ secrets.OC_NAMESPACE }}
oc delete is/${{ env.NAME }}-${{ env.ZONE}}-${{ env.COMPONENT }} || true
- uses: actions/checkout@v3
- name: Deploy
run: |
# Login to OpenShift and select project
oc login --token=${{ secrets.OC_TOKEN }} --server=${{ secrets.OC_SERVER }}
oc project ${{ secrets.OC_NAMESPACE }}
# Do not replace database; 'oc create' kicks up an error if objects already exist
oc process -f .github/openshift/deploy.database.yml -p ZONE=${{ env.ZONE }} | oc create -f - || true
# Process and apply deployment templates
oc process -f .github/openshift/deploy.backend.yml -p ZONE=${{ env.ZONE }} \
-p PROMOTE=${{ github.repository }}:${{ env.PREV }}-backend | oc apply -f -
oc process -f .github/openshift/deploy.frontend.yml -p ZONE=${{ env.ZONE }} \
-p PROMOTE=${{ github.repository }}:${{ env.PREV }}-frontend | oc apply -f -
# Follow any active rollouts (see deploymentconfigs)
oc rollout status dc/${{ env.NAME }}-${{ env.ZONE }}-database -w
oc rollout status dc/${{ env.NAME }}-${{ env.ZONE }}-backend -w
oc rollout status dc/${{ env.NAME }}-${{ env.ZONE }}-frontend -w
# Remove completed build runs, build pods and deployment pods
for p in $(oc get po | grep "Completed" | awk '{print $1}')
do
oc delete po ${p}
done
- name: Promote Backend Image to PROD
uses: shrink/actions-docker-registry-tag@v3
with:
registry: ${{ env.REGISTRY }}
repository: ${{ github.repository }}
target: ${{ env.PREV }}-backend
tags: |
prod-backend
- name: Promote Frontend Image to PROD
uses: shrink/actions-docker-registry-tag@v3
with:
registry: ${{ env.REGISTRY }}
repository: ${{ github.repository }}
target: ${{ env.PREV }}-frontend
tags: |
prod-frontend
# # Uncomment to for development and troubleshooting
# # https://docs.github.com/en/actions/learn-github-actions/contexts
# view-context:
# name: View GitHub Context
# runs-on: ubuntu-22.04
# steps:
# - name: Echo GitHub context
# uses: satackey/[email protected]
# with:
# script: |
# const github = require('@actions/github');
# console.log(JSON.stringify(github, null, 2));