Skip to content

build

build #1020

Workflow file for this run

# build - github workflow
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
# https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions
name: build
# name of GitHub event that triggers workflow
# https://help.github.com/en/actions/reference/events-that-trigger-workflows#watch-event-watch
on:
# trigger via webhook
# https://github.com/adamrushuk/devops-lab/blob/master/TriggerCustomAction.ps1#L28
repository_dispatch:
types: [build]
# enable manual workflow
# https://docs.github.com/en/actions/configuring-and-managing-workflows/configuring-a-workflow#manually-running-a-workflow
workflow_dispatch:
inputs: {}
# permissions for oidc login
# https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect
permissions:
id-token: write # This is required for requesting the JWT
contents: read # This is required for actions/checkout
# global environment variables
# https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables
env:
# prefix: used for some globally unique name requirements
PREFIX: arshz
# debug
CI_DEBUG: true
# azure creds (used with OIDC auth)
ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
# other
# prod or staging.
# "" disables cert-manager annotations (use if you already have an existing TLS secret)
CERT_API_ENVIRONMENT: ""
DNS_RG_NAME: rg-dns
EMAIL_ADDRESS: certadmin@domain.com
ENABLE_TLS_INGRESS: true
FORCE_TEST_FAIL: false
K8S_TLS_SECRET_NAME: tls-secret
KEY_VAULT_CERT_NAME: wildcard-thehypepipe-co-uk
KEY_VAULT_NAME: kv-rush-aqy2
KEY_VAULT_RESOURCE_GROUP_NAME: rg-keyvault-acmebot
# NOTE: "eastus" is cheaper than "uksouth"
LOCATION: eastus
NEXUS_USER_USERNAME: demo_user
ROOT_DOMAIN_NAME: thehypepipe.co.uk
# STORAGE_KEY: 'env var set by Get-StorageKey.ps1'
VELERO_ENABLED: true
WEAVE_SCOPE_ENABLED: false
# terraform
TF_IN_AUTOMATION: "true"
TF_INPUT: "false"
# https://developer.hashicorp.com/terraform/internals/debugging
TF_LOG: "ERROR" # TRACE, DEBUG, INFO, WARN or ERROR
TF_PLAN: "tfplan"
# https://github.com/hashicorp/terraform/releases
TF_VERSION: "1.6.6"
TF_WORKING_DIR: ./terraform
# azurerm provider oidc
# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_oidc
# https://developer.hashicorp.com/terraform/language/settings/backends/azurerm#oidc_request_token
ARM_USE_OIDC: "true"
# Env var concatenation is currently not supported at Workflow or Job scope. See workaround below:
# https://github.community/t5/GitHub-Actions/How-can-we-concatenate-multiple-env-vars-at-workflow-and-job/td-p/48489
jobs:
build-and-deploy:
# always pin versions
# view installed software: https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
# https://github.com/actions/runner-images?tab=readme-ov-file#available-images
runs-on: ubuntu-22.04
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idenvironment
environment:
name: dev
url: "https://argocd.${{ env.ROOT_DOMAIN_NAME }}"
# only run if owner triggered action
if: github.actor == github.event.repository.owner.login
steps:
# Checkout
# https://github.com/marketplace/actions/checkout
- uses: actions/checkout@v4
# specify different branch
# NOT required as I've changed the default branch to develop
# with:
# ref: develop
# Init tasks - inc Env var concatenation
# https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#environment-files
- name: Init tasks - inc Env var concatenation (Workaround)
run: |
chmod -R +x ./scripts/
echo "AKS_CLUSTER_NAME=${{ env.PREFIX }}-aks-001" >> $GITHUB_ENV
echo "AKS_RG_NAME=${{ env.PREFIX }}-rg-aks-dev-001" >> $GITHUB_ENV
echo "ARGOCD_FQDN=argocd.${{ env.ROOT_DOMAIN_NAME }}" >> $GITHUB_ENV
echo "DNS_DOMAIN_NAME=nexus.${{ env.ROOT_DOMAIN_NAME }}" >> $GITHUB_ENV
echo "DOCKER_FQDN=docker.${{ env.ROOT_DOMAIN_NAME }}" >> $GITHUB_ENV
echo "TERRAFORM_STORAGE_ACCOUNT=${{ env.PREFIX }}sttfstate${{ env.LOCATION }}001" >> $GITHUB_ENV
echo "TERRAFORM_STORAGE_CONTAINER=terraform" >> $GITHUB_ENV
echo "TERRAFORM_STORAGE_RG=${{ env.PREFIX }}-rg-tfstate-dev-001" >> $GITHUB_ENV
echo "VELERO_STORAGE_ACCOUNT=${{ env.PREFIX }}stbckuksouth001" >> $GITHUB_ENV
# Login
# https://github.com/Azure/login
- name: Login via OIDC to Azure Public Cloud (az cli and az powershell)
uses: azure/login@v1
with:
client-id: ${{ secrets.ARM_CLIENT_ID }}
tenant-id: ${{ secrets.ARM_TENANT_ID }}
subscription-id: ${{ secrets.ARM_SUBSCRIPTION_ID }}
enable-AzPSSession: true
# This is required when developing after the initial build, and the AKS cluster may have been stopped
# Ensure AKS cluster is running, else timeouts will occur on k8s Terraform apply tasks
- name: Start AKS Cluster
continue-on-error: true
run: ./scripts/start_aks_cluster.sh
# Prereqs
- name: Create Storage Account for Terraform state
run: ./scripts/storage_create.sh
# TODO remove this step
# - name: Lookup Storage Key
# run: ./scripts/storage_key.sh
- name: Replace tokens in Terraform config files
run: pwsh -command "./scripts/Replace-Tokens.ps1"
env:
ARGOCD_ADMIN_PASSWORD: ${{ secrets.ARGOCD_ADMIN_PASSWORD }}
HELM_CHART_REPO_DEPLOY_PRIVATE_KEY: ${{ secrets.HELM_CHART_REPO_DEPLOY_PRIVATE_KEY }}
IFTTT_WEBHOOK_KEY: ${{ secrets.IFTTT_WEBHOOK_KEY }}
# Terraform
# https://github.com/hashicorp/setup-terraform
- uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ env.TF_VERSION }}
- name: Terraform Init / Validate
run: |
echo 'Running terraform init...'
terraform init \
-backend-config="resource_group_name=$TERRAFORM_STORAGE_RG" \
-backend-config="storage_account_name=$TERRAFORM_STORAGE_ACCOUNT"
# validate
echo 'Running terraform validate...'
terraform validate
working-directory: ${{ env.TF_WORKING_DIR }}
# https://github.com/aquasecurity/tfsec-action
- name: Run tfsec security scan
uses: aquasecurity/tfsec-action@v1.0.3
with:
working_directory: ${{ env.TF_WORKING_DIR }}
soft_fail: true
# https://github.com/bridgecrewio/checkov-action
- name: Run Checkov security scan
id: checkov
uses: bridgecrewio/checkov-action@master
with:
directory: ${{ env.TF_WORKING_DIR }}
# check: CKV_AWS_1 # optional: run only a specific check_id. can be comma separated list
# optional: skip a specific check_id. can be comma separated list
skip_check: CKV2_AZURE_1,CKV_AZURE_4,CKV_AZURE_6,CKV2_AZURE_8,CKV2_AZURE_21,CKV_AZURE_33,CKV_AZURE_35,CKV_AZURE_117,CKV_AZURE_141
quiet: true # optional: display only failed checks
soft_fail: true # optional: do not return an error code if there are failed checks
framework: terraform # optional: run only on a specific infrastructure {cloudformation,terraform,kubernetes,all}
output_format: sarif # optional: the output format, one of: cli, json, junitxml, github_failed_only, or sarif. Default: sarif
download_external_modules: true # optional: download external terraform modules from public git repositories and terraform registry
# log_level: DEBUG # optional: set log level. Default WARNING
# config_file: path/this_file
- name: 👀 Terraform Plan
id: plan
run: terraform plan -out=${{ env.TF_PLAN }}
working-directory: ${{ env.TF_WORKING_DIR }}
- name: 🚀 Terraform Apply
run: ./scripts/terraform_apply.sh
# only apply if changes are present
# https://www.terraform.io/docs/commands/plan.html#detailed-exitcode
# if: steps.plan.outputs.exitcode == 2
env:
TF_PLAN: ${{ env.TF_PLAN }}
# Kubernetes
- name: Deploy kubernetes manifests
run: ./scripts/k8s_manifests_apply.sh
- name: Wait for resources to be "Ready"
run: ./scripts/wait.sh
# Ansible
- name: Run Ansible playbook
run: ./scripts/ansible.sh
env:
NEXUS_ADMIN_PASSWORD: ${{ secrets.NEXUS_ADMIN_PASSWORD }}
NEXUS_USER_PASSWORD: ${{ secrets.NEXUS_USER_PASSWORD }}
# Docker
# https://github.com/Azure/docker-login
- name: Docker repo login
uses: Azure/docker-login@v1
with:
login-server: ${{ env.DOCKER_FQDN }}
username: ${{ env.NEXUS_USER_USERNAME }}
password: ${{ secrets.NEXUS_USER_PASSWORD }}
- name: Push images to Docker repo
run: ./scripts/push_docker_images.sh
# TODO: Remove once issue has been fixed
- name: Fix Function App version
run: pwsh -command "./scripts/Fix-FunctionApp.ps1"
env:
FUNCTION_APP_NAME: "${{ env.PREFIX }}-funcapp"
FUNCTION_APP_RG: "${{ env.PREFIX }}-rg-aks-dev-001"
# Pester tests
- name: 🧪 Run Pester tests
continue-on-error: true
run: pwsh -command "./scripts/Start-Test.ps1"
# https://github.com/actions/upload-artifact
- name: Archive test artifacts
uses: actions/upload-artifact@v3
with:
name: test-results
path: test/pester-test-results.xml
if: always()
# remove NuGet proxy repo so pester report step doesnt fail
- name: Unregister NuGet proxy repo
run: pwsh -command "Unregister-PSRepository -Name nuget.org-proxy -Verbose"
# Shows at the bottom of a run: https://github.com/adamrushuk/devops-lab/runs/1035347513?check_suite_focus=true
# https://github.com/zyborg/pester-tests-report
# - name: Pester report
# uses: zyborg/pester-tests-report@v1
# with:
# test_results_path: test/pester-test-results.xml
# report_name: pester_tests
# report_title: Pester Tests
# github_token: ${{ secrets.GITHUB_TOKEN }}
# - uses: dorny/test-reporter@v1.6.0
# with:
# # artifact: test-results # artifact name
# name: Pester Tests Results # Name of the check run which will be created
# path: 'test/pester-test-results.xml' # Path to test results (inside artifact .zip)
# reporter: java-junit # Format of test results
# Notify
- name: Notify slack
continue-on-error: true
env:
SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }}
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
run: ./scripts/send_slack_message.sh "[devops-lab] Build complete"
# used for any windows-only tasks
test-windows:
needs: build-and-deploy
# https://github.com/actions/runner-images?tab=readme-ov-file#available-images
runs-on: windows-2022
# https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idenvironment
environment:
name: dev
# only run if owner triggered action
if: github.actor == github.event.repository.owner.login
steps:
# Checkout
- uses: actions/checkout@v4
# Init tasks - inc Env var concatenation
# https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#environment-files
- name: Init tasks - inc Env var concatenation (Workaround)
# * NOTE: different syntax required for Windows agents
run: |
echo "AKS_RG_NAME=${{ env.PREFIX }}-rg-aks-dev-001" | Out-File -Append -Encoding utf8 -FilePath "$env:GITHUB_ENV"
echo "AKS_CLUSTER_NAME=${{ env.PREFIX }}-aks-001" | Out-File -Append -Encoding utf8 -FilePath "$env:GITHUB_ENV"
echo "DNS_DOMAIN_NAME=nexus.${{ env.ROOT_DOMAIN_NAME }}" | Out-File -Append -Encoding utf8 -FilePath "$env:GITHUB_ENV"
# Login
# https://github.com/Azure/login
- name: Login via OIDC to Azure Public Cloud (az cli and az powershell)
uses: azure/login@v1
with:
client-id: ${{ secrets.ARM_CLIENT_ID }}
tenant-id: ${{ secrets.ARM_TENANT_ID }}
subscription-id: ${{ secrets.ARM_SUBSCRIPTION_ID }}
enable-AzPSSession: true
# Chocolatey
- name: Test Nexus Chocolatey proxy repo
run: |
choco install velero --source "https://${{ env.DNS_DOMAIN_NAME }}/repository/chocolatey-proxy/"
# Velero CLI
- name: Test Velero CLI
# NOTE: Some functions cast values to a string to perform comparisons
# https://docs.github.com/en/free-pro-team@latest/actions/reference/context-and-expression-syntax-for-github-actions#functions
# ! WARNING: only single quotes work for boolean comparison
if: env.VELERO_ENABLED == 'true'
run: |
az aks get-credentials --resource-group "${{ env.AKS_RG_NAME }}" --name "${{ env.AKS_CLUSTER_NAME }}" --overwrite-existing --admin
echo "`nVelero version info:"
velero version || true
echo "`nVelero backup location info:"
velero backup-location get
echo "`nVelero backup info:"
velero backup get