-
Notifications
You must be signed in to change notification settings - Fork 19
156 lines (140 loc) · 6.13 KB
/
Copy pathfeature.yml
File metadata and controls
156 lines (140 loc) · 6.13 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
name: Deploy feature branch to test slot
# Any push to a branch other than `main` builds a fresh image and deploys it
# to the deployment slot configured by `TEST_*` repository variables,
# so maintainers can preview feature branches before merging. Forks supply
# their own variables and secrets; no deployment coordinates live in source.
on:
push:
branches-ignore: [main]
paths:
- "src/Dashboard/**"
- ".github/workflows/feature.yml"
workflow_dispatch:
permissions:
id-token: write
contents: read
env:
ACR_NAME: ${{ vars.TEST_ACR_NAME }}
ACR_LOGIN: ${{ vars.TEST_ACR_LOGIN_SERVER }}
IMAGE: ${{ vars.TEST_CONTAINER_IMAGE }}
WEBAPP_NAME: ${{ vars.TEST_WEBAPP_NAME }}
SLOT_NAME: ${{ vars.TEST_SLOT_NAME }}
RESOURCE_GROUP: ${{ vars.TEST_RESOURCE_GROUP }}
VERIFY_URL: ${{ vars.TEST_VERIFY_URL }}
# Only one deploy at a time: every branch targets the same configured test slot.
concurrency:
group: test-slot-deploy
cancel-in-progress: true
jobs:
deploy:
name: Build & Deploy to test slot
runs-on: ubuntu-latest
# Dependabot-triggered runs don't get access to repo secrets, so azure/login
# would fail. Skip — these PRs are reviewed and merged via main.yml.
if: github.actor != 'dependabot[bot]'
steps:
# Shallow checkout — we no longer need full git history (build number
# comes from github.run_number instead of `git rev-list --count HEAD`).
- uses: actions/checkout@v7
- name: Azure Login (OIDC)
uses: azure/login@v3
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Validate deployment configuration
shell: bash
run: |
for name in ACR_NAME ACR_LOGIN IMAGE WEBAPP_NAME SLOT_NAME RESOURCE_GROUP VERIFY_URL; do
if [ -z "${!name}" ]; then
echo "Missing GitHub repository variable for test: $name" >&2
exit 1
fi
done
- name: Login to ACR
run: az acr login --name ${{ env.ACR_NAME }}
- name: Set build metadata
id: meta
run: |
BRANCH="${GITHUB_REF#refs/heads/}"
TAG_BRANCH=$(echo "$BRANCH" | tr '/' '-' | tr '[:upper:]' '[:lower:]')
echo "branch=$BRANCH" >> $GITHUB_OUTPUT
echo "tag_branch=$TAG_BRANCH" >> $GITHUB_OUTPUT
echo "sha=${GITHUB_SHA::7}" >> $GITHUB_OUTPUT
echo "build=${{ github.run_number }}" >> $GITHUB_OUTPUT
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Build & push Docker image
uses: docker/build-push-action@v7
with:
context: src/Dashboard
push: true
provenance: false
# We deliberately do NOT push :latest — that tag belongs to prod.
tags: |
${{ env.IMAGE }}:test-${{ steps.meta.outputs.tag_branch }}
${{ env.IMAGE }}:test-${{ steps.meta.outputs.sha }}
build-args: |
BUILD_SHA=${{ steps.meta.outputs.sha }}
BUILD_NUMBER=${{ steps.meta.outputs.build }}
BUILD_BRANCH=${{ steps.meta.outputs.branch }}
# Registry-mode cache lives in ACR and is shared across every
# branch + every workflow run. Far bigger than the 10GB GHA cache
# and survives indefinitely. We read from both the per-feature
# buildcache and the prod buildcache (warm baseline).
cache-from: |
type=registry,ref=${{ env.IMAGE }}:buildcache
type=registry,ref=${{ env.IMAGE }}:buildcache-main
cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max,image-manifest=true,oci-mediatypes=true
# `az webapp config container set` triggers App Service to re-pull and
# restart the slot, so an explicit `webapp restart` is redundant.
- name: Point test slot at new image
run: |
az webapp config container set \
--name ${{ env.WEBAPP_NAME }} \
--resource-group ${{ env.RESOURCE_GROUP }} \
--slot ${{ env.SLOT_NAME }} \
--container-image-name ${{ env.IMAGE }}:test-${{ steps.meta.outputs.sha }} \
--container-registry-url https://${{ env.ACR_LOGIN }} \
--output none
- name: Configure App Service settings (test slot)
env:
AOAI_ENDPOINT: ${{ secrets.AZURE_OPENAI_ENDPOINT }}
run: |
if [ -z "$AOAI_ENDPOINT" ]; then
echo "Missing GitHub secret for test: AZURE_OPENAI_ENDPOINT" >&2
exit 1
fi
az webapp config appsettings set \
--name ${{ env.WEBAPP_NAME }} \
--resource-group ${{ env.RESOURCE_GROUP }} \
--slot ${{ env.SLOT_NAME }} \
--settings AzureOpenAI__Endpoint="$AOAI_ENDPOINT" \
--output none
- name: Verify deployment
run: |
for attempt in $(seq 1 24); do
payload=$(curl --connect-timeout 10 --max-time 20 -sf "${VERIFY_URL%/}/api/version" || true)
sha=$(jq -r '.sha // empty' <<<"$payload")
build=$(jq -r '.build // empty' <<<"$payload")
branch=$(jq -r '.branch // empty' <<<"$payload")
if [[ "$sha" == "${{ steps.meta.outputs.sha }}" && "$build" == "${{ steps.meta.outputs.build }}" && "$branch" == "${{ steps.meta.outputs.branch }}" ]]; then
echo "Verified test build $build ($sha) on $branch."
exit 0
fi
echo "Waiting for expected test build (attempt $attempt/24)..."
sleep 5
done
echo "Expected test SHA/build/branch did not become active." >&2
exit 1
- name: Summary
run: |
{
echo "### Test slot deployed :rocket:"
echo ""
echo "- **Branch:** \`${{ steps.meta.outputs.branch }}\`"
echo "- **Build:** \`${{ steps.meta.outputs.build }}\`"
echo "- **SHA:** \`${{ steps.meta.outputs.sha }}\`"
echo "- **Image:** \`${{ env.IMAGE }}:test-${{ steps.meta.outputs.sha }}\`"
echo "- **URL:** ${VERIFY_URL}"
} >> $GITHUB_STEP_SUMMARY