Repository navigation
189 lines (170 loc) · 8.25 KB
/
Copy pathsamples.yml
File metadata and controls
189 lines (170 loc) · 8.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
name: Test samples on LocalStack for Azure
# Creates the AKS cluster on the LocalStack for Azure emulator, deploys a sample's Python or .NET web
# app with its numbered scripts, one job per app, and checks the app end to end with
# tests/test-vacation-planner.sh. As in the Samples CI of localstack-azure-samples, a pull request or a
# push runs the apps it changes (every app when a file all of them use changes), and a manual run can
# choose to run every app.
on:
push:
branches:
- main
paths-ignore:
- '**.md'
pull_request:
branches:
- main
workflow_dispatch:
inputs:
run_mode:
description: "'all' runs every sample, 'changed' runs only the samples with modified files"
required: false
type: choice
options:
- all
- changed
default: changed
permissions: {}
# A new push to the same pull request cancels the run it supersedes: with one job per sample and
# language, a stale run would otherwise hold up to twenty runners for the length of a deployment
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
setup:
name: Select samples
# Pull requests from forks get no secrets, so lstk could not start the emulator there
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
matrix: ${{ steps.select.outputs.matrix }}
has_samples: ${{ steps.select.outputs.has_samples }}
steps:
- name: Check out repo
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
# The full history, so that 'changed' mode can compare with the base commit
fetch-depth: 0
- name: Select the samples to run
id: select
env:
# Pull requests and pushes have no inputs: they run the samples they change
RUN_MODE: ${{ inputs.run_mode || 'changed' }}
EVENT_NAME: ${{ github.event_name }}
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
PUSH_BEFORE_SHA: ${{ github.event.before }}
run: |
# Every app a job can deploy, as samples/<sample>/<language>, so a new sample needs no change here
apps=$(printf '%s\n' samples/*/*/scripts/05-deploy-app.sh | sed 's|/scripts/05-deploy-app\.sh$||')
selected=$apps
if [ "$RUN_MODE" = changed ]; then
case $EVENT_NAME in
pull_request) base=$PR_BASE_SHA ;;
push) base=$PUSH_BEFORE_SHA ;;
*) base=origin/main ;;
esac
if git rev-parse --quiet --verify "$base^{commit}" > /dev/null; then
changed=$(git diff --name-only "$base...HEAD")
echo "Files changed since $base:"
echo "$changed"
# Every job creates the cluster with the same script and checks the app with the same test, so a
# change to either, or to this workflow, runs every app; otherwise an app runs when its folder changes
shared='^(scripts/01-system-assigned-managed-identity\.sh|tests/test-vacation-planner\.sh|\.github/workflows/samples\.yml)$'
if ! grep -q -E "$shared" <<< "$changed"; then
selected=$(while read -r app; do
if grep -q "^$app/" <<< "$changed"; then echo "$app"; fi
done <<< "$apps")
fi
else
# A push that creates the branch or rewrites its history leaves no base commit to compare with
echo "Base commit '$base' not found: running every sample"
fi
fi
matrix=$(jq -n -R -c '[inputs | select(length > 0) | split("/") | {sample: .[1], language: .[2]}] | {include: .}' <<< "$selected")
echo "Samples to run: $(jq -r '[.include[] | "\(.sample) (\(.language))"] | if length > 0 then join(", ") else "none" end' <<< "$matrix")"
{
echo "matrix=$matrix"
echo "has_samples=$(jq '.include | length > 0' <<< "$matrix")"
} >> "$GITHUB_OUTPUT"
sample:
name: ${{ matrix.sample }} (${{ matrix.language }})
needs: setup
# Skip the job when the run changes no sample
if: needs.setup.outputs.has_samples == 'true'
runs-on: ubuntu-latest
timeout-minutes: 60
permissions:
contents: read
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.setup.outputs.matrix) }}
env:
SAMPLE: ${{ matrix.sample }}
LANGUAGE: ${{ matrix.language }}
steps:
- name: Check out repo
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Install lstk
# Pinned like actions/checkout, so an lstk release cannot change every run at once: bump it deliberately
run: npm install -g @localstack/lstk@1.4.0
- name: Install sqlcmd
# The Azure SQL Database sample seeds its database with sqlcmd, which the runner image does not ship
if: matrix.sample == 'web-app-sql-database'
run: |
sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list
curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc > /dev/null
curl -fsSL "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/prod.list" | sudo tee /etc/apt/sources.list.d/mssql-release.list > /dev/null
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install -y mssql-tools18
echo "/opt/mssql-tools18/bin" >> "$GITHUB_PATH"
- name: Create the SSH key the cluster script provisions the node pools with
run: ssh-keygen -t rsa -b 4096 -N '' -f ~/.ssh/id_rsa -q
- name: Start the LocalStack for Azure emulator
env:
LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}
# lstk forwards LOCALSTACK_-prefixed variables to the emulator. The Azure SQL Database sample
# needs the SQL Server EULA accepted, as its README and the localstack-azure-samples CI do
LOCALSTACK_MSSQL_ACCEPT_EULA: "Y"
# The emulator looks up the k3d release behind each AKS cluster on api.github.com. Anonymous
# calls share the runner IP's 60 requests an hour, which twenty parallel jobs can exhaust, so pass
# the run's own read-only token, as the localstack-azure-samples CI does
LOCALSTACK_GITHUB_API_TOKEN: ${{ github.token }}
run: |
lstk start --type azure --non-interactive
lstk az start-interception
# The script prompts for the network configuration and both node pool sizes:
# pick option 1 (Azure network plugin and policy) and keep the default sizes
- name: Create the AKS cluster
working-directory: scripts
run: printf '1\n\n\n' | ./01-system-assigned-managed-identity.sh
- name: Deploy the sample
working-directory: samples/${{ matrix.sample }}/${{ matrix.language }}/scripts
env:
# Answer the Azure Files sample's two provisioning menus; the other samples do not read these
PROVISIONING_MODE: static
FILE_SHARE_PROTOCOL: smb
run: |
./01-deploy-resources.sh
./02-build-docker-image.sh
./04-push-docker-image.sh
./05-deploy-app.sh
- name: Test the web app
run: |
variables="samples/$SAMPLE/$LANGUAGE/scripts/00-variables.sh"
namespace=$(sed -n "s/^NAMESPACE=\"\(.*\)\"/\1/p" "$variables")
service=$(sed -n "s/^SERVICE_NAME=\"\(.*\)\"/\1/p" "$variables")
./tests/test-vacation-planner.sh "$namespace" "$service"
- name: Show cluster state and emulator logs
if: failure()
run: |
kubectl get pods --all-namespaces -o wide || true
kubectl get events --all-namespaces --sort-by=.lastTimestamp | tail -50 || true
for ns in $(kubectl get namespaces -o name | sed 's|namespace/||' | grep vacation-planner); do
kubectl describe pods --namespace "$ns" | tail -80 || true
kubectl logs --namespace "$ns" --all-containers --tail=100 -l "app=$ns" || true
done
lstk logs | tail -300 || true