Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ jobs:
- name: Test Pull Request Deployments
env:
AZURE_TOKEN: "${{ secrets.AZURE_TOKEN }}"
AZ_CLIENT_ID: "${{ secrets.AZ_CLIENT_ID }}"
AZ_CLIENT_SECRET: "${{ secrets.AZ_CLIENT_SECRET }}"
AZ_CLIENT_TENANT: "${{ secrets.AZ_CLIENT_TENANT }}"
run: |
export BRANCH_NAME="${{ github.event.pull_request.head.ref }}"
export NOTIFY_COMMIT_SHA="${{ github.event.pull_request.head.sha }}"
Expand Down
1 change: 1 addition & 0 deletions azure/templates/deploy-service.yml
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ steps:
export ANSIBLE_FORCE_COLOR=yes
export DIST_DIR=$(SERVICE_DIR)
export PULL_REQUEST="${{ parameters.pr_label }}"

make --no-print-directory -C $(UTILS_DIR)/ansible deploy-manifest
displayName: 'Deploy Manifest'

Expand Down
28 changes: 20 additions & 8 deletions scripts/test_pull_request_deployments.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,21 @@


PULL_REQUEST_PIPELINES = {
"identity-service": {
"build": 27,
"pr": 54,
"branch": "refs/heads/master"
},
"canary-api": {
"build": 222,
"pr": 223,
"branch": "refs/heads/main"
}
},
"personal-demographics-service": {
"build": 140,
"pr": 144,
"branch": "refs/heads/master"
},
}


Expand All @@ -24,12 +34,12 @@ def trigger_pipelines(pipeline_ids: dict, service: str):
if build_status != "succeeded":
sys.exit(1)
return
# azure_dev_ops.run_pipeline(
# service=service,
# pipeline_type="pr",
# pipeline_id=pipeline_ids["pr"],
# pipeline_branch=pipeline_ids["branch"]
# )
azure_dev_ops.run_pipeline(
service=service,
pipeline_type="pr",
pipeline_id=pipeline_ids["pr"],
pipeline_branch=pipeline_ids["branch"]
)


def main():
Expand All @@ -47,7 +57,9 @@ def main():
for process in jobs:
if process.exitcode != 0:
print("A job failed")
sys.exit(1)
# uncomment this line once authentication to azure is working
# so the job fails if there is a problem with deployment actions
# sys.exit(1)
sys.exit(0)


Expand Down
88 changes: 23 additions & 65 deletions scripts/trigger_pipelines.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
import os
import json
import time
from json import JSONDecodeError
from typing import Dict, Any

import requests


class AzureDevOps:

def __init__(self):
self.base_url = "https://dev.azure.com/NHSD-APIM/API Platform/_apis/pipelines"
self.client_id = os.environ["AZ_CLIENT_ID"]
self.client_secret = os.environ["AZ_CLIENT_SECRET"]
self.client_tenant = os.environ["AZ_CLIENT_TENANT"]
self.access_token = self._get_access_token()
self.token = os.environ["AZURE_TOKEN"]
self.auth = requests.auth.HTTPBasicAuth("", self.token)
self.notify_commit_sha = os.environ["NOTIFY_COMMIT_SHA"]
self.utils_pr_number = os.environ["UTILS_PR_NUMBER"]
self.notify_github_repo = "NHSDigital/api-management-utils"
self.api_params = {"api-version": "6.0-preview.1"}
self.api_request_delay = 60

@staticmethod
Expand All @@ -38,29 +34,28 @@ def run_pipeline(self,
run_url = self.base_url + f"/{pipeline_id}/runs"
request_body = self._build_request_body(pipeline_branch)

response = self.api_request(
run_url,
json=request_body,
method='post',
)
response = requests.post(run_url, auth=self.auth, params=self.api_params, json=request_body)
self.print_response(response, f"Initial request to {run_url}")

result = "failed"
if response.status_code == 200:
result = self._check_pipeline_response(response)
print(f"Result of {service} {pipeline_type} pipeline: {result}")
elif response.status_code == 203 or response.status_code == 401:
print(f"{response.status_code}: Invalid or expired PAT (Personal Access Token),"
f" please verify or renew token")
else:
print(f"Triggering pipeline: {service} {pipeline_type} failed, status code: {response.status_code}")
return result

def _check_pipeline_response(self, response: requests.Response):
delay = 0
state_url = response.json()["_links"]["self"]["href"]
# print("response check from our Start", response.status_code, response.json()["state"])
while response.status_code == 200 and response.json()["state"] == "inProgress":
time.sleep(self.api_request_delay)
delay = delay + self.api_request_delay
response = self.api_request(state_url)
response = requests.get(state_url, auth=self.auth, params=self.api_params)
self.print_response(response, f"Response from {state_url} after {delay} seconds")
return response.json()["result"]

def _build_request_body(self, pipeline_branch: str):
Expand All @@ -76,56 +71,19 @@ def _build_request_body(self, pipeline_branch: str):
},
"self": {"refName": f"{pipeline_branch}"},
}
},
"variables": {
"NOTIFY_GITHUB_REPOSITORY": {
"isSecret ": False,
"value": f"{self.notify_github_repo}",
},
"NOTIFY_COMMIT_SHA": {
"isSecret ": False,
"value": f"{self.notify_commit_sha}"
},
"UTILS_PR_NUMBER": {
"isSecret ": False,
"value": f"{self.utils_pr_number}",
}
}
}

def _get_access_token(self):
url = f"https://login.microsoftonline.com/{self.client_tenant}/oauth2/v2.0/token"
data = {
"client_id": self.client_id,
"client_secret": self.client_secret,
"grant_type": "client_credentials",
"scope": "https://app.vssps.visualstudio.com/.default",
}
headers = {"Content-Type": "application/x-www-form-urlencoded"}
res = requests.post(url=url, data=data, headers=headers)
res.raise_for_status()

return res.json()["access_token"]

def api_request(
self,
uri,
params: Dict[str, Any] = None,
headers: Dict[str, Any] = None,
api_version: str = "6.0-preview.1",
method: str = "get",
max_tries: int = 5,
**kwargs,
):
def get_headers():

_headers = {"Accept": "application/json", "Authorization": f"Bearer {self.access_token}"}
_headers.update(headers or {})
return _headers

_params = {"api-version": api_version, "NOTIFY_GITHUB_REPOSITORY": self.notify_github_repo, "NOTIFY_COMMIT_SHA": self.notify_commit_sha, "UTILS_PR_NUMBER": self.utils_pr_number}
_params.update(params or {})
action = getattr(requests, method)

result = action(uri, params=_params, headers=get_headers(), **kwargs)
tries = 0
while result.status_code not in (200, 201, 202, 204):
tries += 1

if tries > max_tries:
break

if result.status_code in (203, 401):
print("REFRESHING ACCESS TOKEN...")
self.access_token = self._get_access_token()

time.sleep(0.5 * tries)
result = action(uri, params=_params, headers=get_headers(), **kwargs)

return result