Skip to content

Commit 3be1e15

Browse files
Merge branch 'dev' into LEGLINK-186-KafkaRetryImplementation
2 parents 73b6246 + 3ceee7e commit 3be1e15

3 files changed

Lines changed: 167 additions & 15 deletions

File tree

Azure_Pipelines/_deploy_all_services.yml

Lines changed: 133 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pool:
99

1010
parameters:
1111
- name: environment
12-
displayName: Which environment is this for? (DEV | TEST | QA)
12+
displayName: Which environment is this for? (DEV | TEST | QA | QA2)
1313
type: string
1414
values:
1515
- dev-scale
@@ -80,9 +80,140 @@ jobs:
8080
artifact: 'deploy-changes-$(kube_namespace)'
8181
publishLocation: 'pipeline'
8282

83-
- job: Deploy
83+
- job: ValidateImages
8484
dependsOn: Summarize
8585
condition: succeeded()
86+
displayName: Validate all container images
87+
pool:
88+
vmImage: 'ubuntu-latest'
89+
90+
strategy:
91+
matrix:
92+
account:
93+
serviceName: account
94+
repoName: account
95+
96+
admin:
97+
serviceName: admin
98+
repoName: admin
99+
100+
admin-ui:
101+
serviceName: admin-ui
102+
repoName: admin-ui
103+
104+
audit:
105+
serviceName: audit
106+
repoName: audit
107+
108+
automation:
109+
serviceName: automation
110+
repoName: automation
111+
112+
census:
113+
serviceName: census
114+
repoName: census
115+
116+
data-acquisition:
117+
serviceName: data-acquisition
118+
repoName: dataacquisition
119+
120+
data-acquisition-worker:
121+
serviceName: data-acquisition-worker
122+
repoName: dataacquisition-worker
123+
124+
measure-eval:
125+
serviceName: measure
126+
repoName: measureeval
127+
128+
normalization:
129+
serviceName: normalization
130+
repoName: normalization
131+
132+
query-dispatch:
133+
serviceName: query-dispatch
134+
repoName: querydispatch
135+
136+
report:
137+
serviceName: report
138+
repoName: report
139+
140+
submission:
141+
serviceName: submission
142+
repoName: submission
143+
144+
tenant:
145+
serviceName: tenant
146+
repoName: tenant
147+
148+
terminology:
149+
serviceName: terminology
150+
repoName: terminology
151+
152+
validation:
153+
serviceName: validation
154+
repoName: validation
155+
156+
mock-dmrp:
157+
serviceName: mock-dmrp
158+
repoName: mock-dmrp
159+
160+
steps:
161+
162+
- task: Bash@3
163+
displayName: 'Determine image tag'
164+
inputs:
165+
targetType: inline
166+
script: |
167+
set -e
168+
169+
GIT_COMMIT=$(git rev-parse --short HEAD)
170+
IMAGE_TAG="$(Build.SourceBranchName)-${GIT_COMMIT}"
171+
172+
echo "Git commit: ${GIT_COMMIT}"
173+
echo "Image tag: ${IMAGE_TAG}"
174+
175+
echo "##vso[task.setvariable variable=GIT_COMMIT]${GIT_COMMIT}"
176+
echo "##vso[task.setvariable variable=IMAGE_TAG]${IMAGE_TAG}"
177+
178+
- task: AzureCLI@2
179+
displayName: 'Validate image exists for $(serviceName)'
180+
inputs:
181+
azureSubscription: 'NHSNLink-RG ARM'
182+
scriptType: bash
183+
scriptLocation: inlineScript
184+
inlineScript: |
185+
set -e
186+
187+
IMAGE_REPO="link-$(repoName)"
188+
IMAGE_TAG="$(IMAGE_TAG)"
189+
190+
echo "=========================================="
191+
echo "Validating container image"
192+
echo "=========================================="
193+
echo "Service: $(serviceName)"
194+
echo "Repository: ${IMAGE_REPO}"
195+
echo "Tag: ${IMAGE_TAG}"
196+
echo "Full image: $(containerRegistry)/${IMAGE_REPO}:${IMAGE_TAG}"
197+
echo "=========================================="
198+
199+
if ! az acr repository show \
200+
--name "$(containerRegistry)" \
201+
--image "${IMAGE_REPO}:${IMAGE_TAG}" \
202+
--output none; then
203+
204+
echo "##vso[task.logissue type=error]Image does NOT exist in ACR:"
205+
echo "##vso[task.logissue type=error]$(containerRegistry)/${IMAGE_REPO}:${IMAGE_TAG}"
206+
echo "##vso[task.logissue type=error]Deployment has been stopped for $(serviceName)."
207+
208+
exit 1
209+
fi
210+
211+
echo "Image exists in ACR."
212+
213+
214+
- job: Deploy
215+
dependsOn: ValidateImages
216+
condition: succeeded()
86217
displayName: Deploy multiple services
87218
pool:
88219
vmImage: 'ubuntu-latest'

Scripts/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ subfolder and is summarised at the end.
3434
| `set_kubernetes_services.bat <namespace> <registry> <image>` | Points a Kubernetes namespace at a registry and image. |
3535
| `aca-container-statuses.ps1` | Lists Azure Container App running state and replica bounds. |
3636
| `aca-logs.bat <container> rep\|rev <id>` | Tails Container App logs for a replica or revision. |
37-
| `get_deployed_commit.py <environment>` | Reports the commit currently deployed to `dev-scale`, `scale-test` or `scale-qa`. |
37+
| `get_deployed_commit.py <environment>` | Reports the commit currently deployed to `dev-scale`, `scale-test`, `scale-qa` or `scale-qa2`. |
3838
| `list-deploy-changes.py <from> <to>` | Lists the deployment-relevant changes between two git refs. |
3939
| `upload_to_share.py` | Uploads a directory to an Azure File Share. |
4040

Scripts/get_deployed_commit.py

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
python3 scripts/get_deployed_commit.py <environment>
77
88
Arguments:
9-
environment: One of dev-scale | scale-test | scale-qa
9+
environment: One of dev-scale | scale-test | scale-qa | scale-qa2
1010
1111
Environment variables expected:
12-
DEV_BASE_URL, TEST_BASE_URL, QA_BASE_URL (from your Azure DevOps variable group)
12+
DEV_BASE_URL, TEST_BASE_URL, QA_BASE_URL, QA2_BASE_URL (from your Azure DevOps variable group)
1313
1414
Purpose:
1515
- Determines the correct BASE_URL from the environment.
@@ -22,7 +22,11 @@
2222
import json
2323
import urllib.request
2424

25-
REPO_COMMIT_ROOT = 'https://github.com/lantanagroup/link-cloud/commit/'
25+
REPO_COMMITS_API_ROOT = 'https://api.github.com/repos/lantanagroup/link-cloud/commits/'
26+
27+
# urlopen blocks indefinitely by default, which would hang the pipeline job rather than
28+
# fail it. Bound every HTTP call to the same budget.
29+
HTTP_TIMEOUT_SECONDS = 30
2630

2731
def fail(msg: str):
2832
print(f"ERROR: {msg}", file=sys.stderr)
@@ -43,6 +47,7 @@ def main():
4347
dev_url = os.getenv("DEV_BASE_URL", "")
4448
test_url = os.getenv("TEST_BASE_URL", "")
4549
qa_url = os.getenv("QA_BASE_URL", "")
50+
qa2_url = os.getenv("QA2_BASE_URL", "")
4651

4752
base_url = ""
4853
if input_value.startswith("https://"):
@@ -56,12 +61,14 @@ def main():
5661
base_url = test_url
5762
elif environment == "scale-qa":
5863
base_url = qa_url
64+
elif environment == "scale-qa2":
65+
base_url = qa2_url
5966
else:
60-
fail(f"Unknown environment '{environment}'. Expected one of: dev-scale | scale-test | scale-qa, or a direct https:// URL")
67+
fail(f"Unknown environment '{environment}'. Expected one of: dev-scale | scale-test | scale-qa | scale-qa2, or a direct https:// URL")
6168

6269
if not base_url:
6370
fail(f"BASE_URL is empty for environment '{environment}'. "
64-
f"Ensure DEV_BASE_URL / TEST_BASE_URL / QA_BASE_URL are defined.")
71+
f"Ensure DEV_BASE_URL / TEST_BASE_URL / QA_BASE_URL / QA2_BASE_URL are defined.")
6572

6673
print(f"Environment: {environment}")
6774
print(f"BASE_URL: {base_url}")
@@ -75,7 +82,7 @@ def main():
7582
info_url,
7683
headers={'Accept': 'application/json'}
7784
)
78-
with urllib.request.urlopen(request) as response:
85+
with urllib.request.urlopen(request, timeout=HTTP_TIMEOUT_SECONDS) as response:
7986
body = response.read().decode("utf-8")
8087
except Exception as e:
8188
fail(f"Failed to GET {info_url}: {e}")
@@ -96,20 +103,34 @@ def main():
96103
if not commit:
97104
fail("Could not find 'Commit' in /api/info response.")
98105

99-
# If we got a short hash, try to match it with the full hash from git log
106+
# If we got a short hash, resolve it to the full hash. list-deploy-changes.py fetches both
107+
# refs with 'git fetch origin <ref>', and GitHub only serves unadvertised objects by full SHA.
108+
# The 'sha' media type returns the 40-character hash as plain text.
100109
if len(commit) < 40: # Full SHA-1 hash is 40 characters
101110
print(f"Attempting to translate short commit hash {commit} to full commit hash")
102111
try:
103112
request = urllib.request.Request(
104-
f"{REPO_COMMIT_ROOT}{commit}",
105-
headers={'Accept': 'application/json'}
113+
f"{REPO_COMMITS_API_ROOT}{commit}",
114+
headers={'Accept': 'application/vnd.github.sha'}
106115
)
107-
with urllib.request.urlopen(request) as response:
108-
full_commit_data = json.loads(response.read().decode("utf-8"))
109-
commit = full_commit_data.get('payload', {}).get('commit', {}).get("sha2", commit)
116+
with urllib.request.urlopen(request, timeout=HTTP_TIMEOUT_SECONDS) as response:
117+
full_commit = response.read().decode("utf-8").strip()
118+
119+
if len(full_commit) == 40:
120+
commit = full_commit
121+
else:
122+
print(f"Warning: Unexpected response resolving full commit hash: '{full_commit[:100]}'", file=sys.stderr)
110123
except Exception as e:
111124
print(f"Warning: Could not resolve full commit hash: {e}", file=sys.stderr)
112125

126+
# A short hash breaks the downstream fetch in list-deploy-changes.py: 'git fetch origin
127+
# <ref>' is rejected for anything but a full SHA, and that failure is swallowed, so the
128+
# summary comes out empty with nothing in the log to explain it. Stop here instead of
129+
# publishing a FromCommit that cannot be used.
130+
if len(commit) < 40:
131+
fail(f"'{commit}' is not a full commit hash and could not be resolved to one. "
132+
f"'git fetch origin {commit}' would fail and the deployment summary would be empty.")
133+
113134
print(f"FromCommit: {commit}")
114135

115136
# 5. Emit Azure DevOps logging command

0 commit comments

Comments
 (0)