Skip to content
This repository was archived by the owner on Nov 9, 2023. It is now read-only.

Commit 4b4e9be

Browse files
committed
new pipelines
1 parent ec2b0d9 commit 4b4e9be

8 files changed

Lines changed: 491 additions & 0 deletions

File tree

.github/scripts/release.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/bin/bash
2+
3+
VER=$1
4+
5+
if [[ -z "$VER" ]]; then
6+
echo "Error! Supply version tag!"
7+
exit 1
8+
fi
9+
10+
read -r -d '' NOTES << EOM
11+
\`\`\`
12+
docker pull ghcr.io/benc-uk/python-demoapp:$VER
13+
\`\`\`
14+
15+
\`\`\`
16+
docker run --rm -it -p 5000:5000 ghcr.io/benc-uk/python-demoapp:$VER
17+
\`\`\`
18+
EOM
19+
20+
gh release create $VER --title "Release v$VER" -n "$NOTES"

.github/scripts/url-check.sh

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#!/bin/bash
2+
3+
declare -i time=60
4+
declare -i delay=5
5+
declare -i count=5
6+
declare -i okCount=0
7+
declare -i elapsed=0
8+
declare isUp="false"
9+
10+
# Display usage
11+
usage(){
12+
echo -e "\e[32m╭──────────────────────────────────────────────────────────────╮"
13+
echo -e "│ 🌍 \e[94murl-check.sh \e[96mCheck URL endpoint for HTTP responses 🚀\e[32m │"
14+
echo -e "╰──────────────────────────────────────────────────────────────╯"
15+
echo -e "\n\e[95mParameters:\e[37m"
16+
echo -e " -u, --url \e[33mURL to check (required)\e[37m"
17+
echo -e " [-t, --time] \e[33mMaximum number of seconds to poll for \e[92m(default: 60)\e[37m"
18+
echo -e " [-d, --delay] \e[33mDelay in seconds between requests \e[92m(default: 5)\e[37m"
19+
echo -e " [-c, --count] \e[33mHow many successes to receive before exiting \e[92m(default: 5)\e[37m"
20+
echo -e " [-s, --search] \e[33mOptional content check, grep for this string in HTTP body \e[92m(default: none)\e[37m"
21+
echo -e " [-h, --help] \e[33mShow this help text\e[37m"
22+
}
23+
24+
OPTS=`getopt -o u:t:d:c:s:h --long url:,time:,delay:,count:,search:,help -n 'parse-options' -- "$@"`
25+
if [ $? != 0 ] ; then echo "Failed parsing options." >&2 ; usage; exit 1 ; fi
26+
eval set -- "$OPTS"
27+
28+
while true; do
29+
case "$1" in
30+
-u | --url ) url="$2"; shift; shift;;
31+
-t | --time ) time="$2"; shift; shift;;
32+
-d | --delay ) delay="$2"; shift; shift;;
33+
-c | --count ) count="$2"; shift; shift;;
34+
-s | --search ) search="$2"; shift; shift;;
35+
-h | --help ) HELP=true; shift ;;
36+
-- ) shift; break ;;
37+
* ) break ;;
38+
esac
39+
done
40+
41+
if [[ ${HELP} = true ]] || [ -z ${url} ]; then
42+
usage
43+
exit 0
44+
fi
45+
46+
# Check for impossible parameter combination ie. too many checks and delays in given time limit
47+
if (( $delay * $count > $time)); then
48+
echo -e "\e[31m### Error! The time ($time) provided is too short given the delay ($delay) and count ($count)\e[0m"
49+
exit 1
50+
fi
51+
52+
echo -e "\n\e[36m### Polling \e[33m$url\e[36m for ${time}s, to get $count OK results, with a ${delay}s delay\e[0m\n"
53+
54+
# Generate tmp filename
55+
tmpfile=$(echo $url | md5sum)
56+
57+
# Main loop
58+
while [ "$isUp" != "true" ]
59+
do
60+
# Break out of loop if max time has elapsed
61+
if (( $elapsed >= $time )); then break; fi
62+
timestamp=$(date "+%Y/%m/%d %H:%M:%S")
63+
64+
# Main CURL test, output to file and return http_code
65+
urlstatus=$(curl -o "/tmp/$tmpfile" --silent --write-out '%{http_code}' "$url")
66+
67+
if [ $urlstatus -eq 000 ]; then
68+
# Code 000 means DNS, network error or malformed URL
69+
msg="\e[95mSite not found or other error"
70+
else
71+
if (( $urlstatus >= 200 )) && (( $urlstatus < 300 )); then
72+
# Check returned content with grep if check specified
73+
if [ ! -z "$search" ]; then
74+
grep -q "$search" "/tmp/$tmpfile"
75+
# Only count as a success if string grep passed
76+
if (( $? == 0)); then
77+
((okCount=okCount + 1))
78+
msg="✅ \e[32m$urlstatus 🔍 Content check for '$search' passed"
79+
else
80+
msg="❌ \e[91m$urlstatus 🔍 Content check for '$search' failed"
81+
fi
82+
else
83+
# Good status code
84+
((okCount=okCount + 1))
85+
msg="✅ \e[32m$urlstatus "
86+
fi
87+
88+
if (( $okCount >= $count )); then isUp="true"; fi
89+
else
90+
# Bad status code
91+
msg="❌ \e[91m$urlstatus "
92+
fi
93+
fi
94+
95+
# Output message + timestamp then delay
96+
echo -e "### $timestamp: $msg\e[0m"
97+
sleep $delay
98+
((elapsed=elapsed + delay))
99+
done
100+
101+
rm "/tmp/$tmpfile"
102+
# Final result check
103+
if [ "$isUp" == "true" ]; then
104+
echo -e "\n\e[32m### Result: $url is UP! 🤩\e[0m"
105+
exit 0
106+
else
107+
echo -e "\n\e[91m### Result: $url is DOWN! 😢\e[0m"
108+
exit 1
109+
fi
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#
2+
# Deploy to Azure Kubernetes Service using Helm
3+
# Using Bicep for infrastructure as code
4+
#
5+
6+
name: CD Release - AKS
7+
8+
on:
9+
workflow_dispatch:
10+
inputs:
11+
IMAGE_TAG:
12+
description: "Image tag to be deployed"
13+
required: true
14+
default: "latest"
15+
16+
# Note. Required secrets: CR_PAT & AZURE_CREDENTIALS
17+
18+
env:
19+
IMAGE_REG: ghcr.io
20+
IMAGE_REPO: benc-uk/python-demoapp
21+
AKS_NAME: benc
22+
AKS_RES_GROUP: aks
23+
HELM_RELEASE: python
24+
HELM_NAMESPACE: demoapps
25+
INGRESS_DNS_HOST: python-demoapp.kube.benco.io
26+
27+
jobs:
28+
#
29+
# Deploy to Kubernetes (AKS)
30+
#
31+
deploy-aks:
32+
name: Deploy to AKS with Helm
33+
runs-on: ubuntu-latest
34+
outputs:
35+
deployment_id: ${{ steps.deploy.outputs.deployment_id }}
36+
37+
steps:
38+
- name: "Checkout"
39+
uses: actions/checkout@v1
40+
41+
- name: "Start deployment"
42+
id: deploy
43+
uses: chrnorm/deployment-action@v1.2.0
44+
with:
45+
ref: ${{ github.event.ref }}
46+
token: ${{ github.token }}
47+
environment: AKS - ${{ env.HELM_RELEASE }}
48+
49+
- name: "Login to Azure"
50+
uses: azure/login@v1
51+
with:
52+
creds: ${{ secrets.AZURE_CREDENTIALS }}
53+
54+
- name: "Get AKS credentials"
55+
run: |
56+
az aks get-credentials -n $AKS_NAME -g $AKS_RES_GROUP
57+
58+
- name: "Helm release"
59+
run: |
60+
helm upgrade ${{ env.HELM_RELEASE }} \
61+
https://code.benco.io/helm-charts/webapp-1.2.0.tgz \
62+
--install \
63+
--namespace ${{ env.HELM_NAMESPACE }} \
64+
--values ./kubernetes/app.yaml \
65+
--set image.tag=${{ github.event.inputs.IMAGE_TAG }},image.repository=${{ env.IMAGE_REG }}/${{ env.IMAGE_REPO }},env.AAD_REDIRECT_URL_BASE=https://${{ env.INGRESS_DNS_HOST }},ingress.host=${{ env.INGRESS_DNS_HOST }}
66+
67+
- name: "End deployment - failure"
68+
if: ${{ failure() }}
69+
uses: chrnorm/deployment-status@v1.0.0
70+
with:
71+
token: ${{ github.token }}
72+
state: failure
73+
deployment_id: ${{ needs.deploy-bicep.outputs.deployment_id }}
74+
75+
#
76+
# Post deployment testing stage
77+
#
78+
validate-deployment:
79+
name: "Run Deployment Tests"
80+
needs: deploy-aks
81+
runs-on: ubuntu-latest
82+
steps:
83+
- name: "Checkout"
84+
uses: actions/checkout@v2
85+
86+
- name: "Validate site is running"
87+
run: .github/scripts/url-check.sh -u https://${{ env.INGRESS_DNS_HOST }} -s "Python Flask" -t 200
88+
89+
- name: "Run API tests"
90+
run: |
91+
npm install newman --silent
92+
node_modules/newman/bin/newman.js run src/tests/postman_collection.json --global-var apphost=${{ env.INGRESS_DNS_HOST }}
93+
94+
- name: "End deployment - success"
95+
if: ${{ success() }}
96+
uses: chrnorm/deployment-status@v1.0.0
97+
with:
98+
token: ${{ github.token }}
99+
state: success
100+
deployment_id: ${{ needs.deploy-aks.outputs.deployment_id }}
101+
environment_url: https://${{ env.INGRESS_DNS_HOST }}
102+
103+
- name: "End deployment - failure"
104+
if: ${{ failure() }}
105+
uses: chrnorm/deployment-status@v1.0.0
106+
with:
107+
token: ${{ github.token }}
108+
state: failure
109+
deployment_id: ${{ needs.deploy-aks.outputs.deployment_id }}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#
2+
# Deploy to Azure App Service as a containerized Web App
3+
# Using Bicep for infrastructure as code
4+
#
5+
6+
name: CD Release - Webapp
7+
8+
on:
9+
workflow_dispatch:
10+
inputs:
11+
IMAGE_TAG:
12+
description: "Image tag to be deployed"
13+
required: true
14+
default: "latest"
15+
16+
# Note. Required secrets: CR_PAT & AZURE_CREDENTIALS
17+
18+
env:
19+
IMAGE_REG: ghcr.io
20+
IMAGE_REPO: benc-uk/python-demoapp
21+
APP_NAME: python-demoapp
22+
ARM_SUB_ID: 52512f28-c6ed-403e-9569-82a9fb9fec91
23+
ARM_REGION: westeurope
24+
ARM_RES_GROUP: apps
25+
26+
jobs:
27+
#
28+
# Deploy Azure infra (App Service) using Bicep
29+
#
30+
deploy-infra:
31+
name: "Deploy Infra"
32+
runs-on: ubuntu-latest
33+
outputs:
34+
deployment_id: ${{ steps.deploy.outputs.deployment_id }}
35+
36+
steps:
37+
- name: "Checkout"
38+
uses: actions/checkout@v2
39+
40+
- name: "Start deployment"
41+
id: deploy
42+
uses: chrnorm/deployment-action@v1.2.0
43+
with:
44+
ref: ${{ github.event.ref }}
45+
token: ${{ github.token }}
46+
environment: App Service - ${{ env.APP_NAME }}
47+
48+
- name: "Run Bicep compiler"
49+
run: |
50+
wget https://github.com/Azure/bicep/releases/download/v0.1.37-alpha/bicep-linux-x64 -qO bicep
51+
chmod +x bicep
52+
./bicep build webapp.bicep
53+
working-directory: ./infra
54+
55+
- name: "Login to Azure"
56+
uses: azure/login@v1
57+
with:
58+
creds: ${{ secrets.AZURE_CREDENTIALS }}
59+
60+
- name: "Create resource group"
61+
run: az group create --name ${{ env.ARM_RES_GROUP }} --location ${{ env.ARM_REGION }}
62+
63+
- name: "Deploy resources"
64+
uses: azure/arm-deploy@v1
65+
with:
66+
subscriptionId: ${{ env.ARM_SUB_ID }}
67+
resourceGroupName: ${{ env.ARM_RES_GROUP }}
68+
template: ./infra/webapp.json
69+
parameters: webappName=${{ env.APP_NAME }} webappImage=${{ env.IMAGE_REG }}/${{ env.IMAGE_REPO }}:${{ github.event.inputs.IMAGE_TAG }} weatherKey=${{ secrets.WEATHER_API_KEY }}
70+
deploymentName: webapp-deploy-${{ github.run_id }}
71+
72+
- name: "End deployment - failure"
73+
if: ${{ failure() }}
74+
uses: chrnorm/deployment-status@v1.0.0
75+
with:
76+
token: ${{ github.token }}
77+
state: failure
78+
deployment_id: ${{ needs.deploy-bicep.outputs.deployment_id }}
79+
80+
#
81+
# Post deployment testing stage
82+
#
83+
validate-deployment:
84+
name: "Run Deployment Tests"
85+
needs: deploy-infra
86+
runs-on: ubuntu-latest
87+
steps:
88+
- name: "Checkout"
89+
uses: actions/checkout@v2
90+
91+
- name: "Validate site is running"
92+
run: .github/scripts/url-check.sh -u https://${{ env.APP_NAME }}.azurewebsites.net/ -s "Python Flask" -t 200
93+
94+
- name: "Run API tests"
95+
run: |
96+
npm install newman --silent
97+
node_modules/newman/bin/newman.js run src/tests/postman_collection.json --global-var apphost=${{ env.APP_NAME }}.azurewebsites.net
98+
99+
- name: "End deployment - success"
100+
if: ${{ success() }}
101+
uses: chrnorm/deployment-status@v1.0.0
102+
with:
103+
token: ${{ github.token }}
104+
state: success
105+
deployment_id: ${{ needs.deploy-infra.outputs.deployment_id }}
106+
environment_url: https://${{ env.APP_NAME }}.azurewebsites.net/
107+
108+
- name: "End deployment - failure"
109+
if: ${{ failure() }}
110+
uses: chrnorm/deployment-status@v1.0.0
111+
with:
112+
token: ${{ github.token }}
113+
state: failure
114+
deployment_id: ${{ needs.deploy-infra.outputs.deployment_id }}

0 commit comments

Comments
 (0)