1010import string
1111import requests
1212import time
13+ from requests .auth import HTTPBasicAuth
14+
15+ # This should be set to a known good version of regression test repo
16+ REGRESSION_TESTS_REPO_TAG = "v2.0.6"
1317
1418GITHUB_API_URL = "https://api.github.com/repos/NHSDigital/electronic-prescription-service-api-regression-tests/actions"
19+ GITHUB_RUN_URL = "https://github.com/NHSDigital/electronic-prescription-service-api-regression-tests/actions/runs"
20+
21+
22+ class BearerAuth (requests .auth .AuthBase ):
23+ def __init__ (self , token ):
24+ self .token = token
25+
26+ def __call__ (self , r ):
27+ r .headers ["authorization" ] = "Bearer " + self .token
28+ return r
1529
1630
1731def get_headers ():
1832 return {
1933 "Accept" : "application/vnd.github+json" ,
2034 "X-GitHub-Api-Version" : "2022-11-28" ,
21- "Authorization" : f"Bearer { arguments .token } " ,
2235 }
2336
2437
@@ -33,23 +46,23 @@ def generate_timestamp():
3346 return date_time
3447
3548
36- def trigger_test_run ():
37- pr_label = arguments .pr_label .lower ()
38- env = "INTERNAL-DEV" if arguments .env == "dev-pr" else arguments .env
49+ def trigger_test_run (env , pr_label , product , auth_header ):
3950 body = {
4051 "ref" : "main" ,
4152 "inputs" : {
4253 "id" : run_id ,
4354 "tags" : "@regression" ,
4455 "environment" : env ,
4556 "pull_request_id" : pr_label ,
46- "product" : "PFP-AWS" ,
57+ "product" : product ,
58+ "github_tag" : REGRESSION_TESTS_REPO_TAG
4759 },
4860 }
4961
5062 response = requests .post (
5163 url = f"{ GITHUB_API_URL } /workflows/regression_tests.yml/dispatches" ,
5264 headers = get_headers (),
65+ auth = auth_header ,
5366 json = body ,
5467 )
5568
@@ -59,28 +72,29 @@ def trigger_test_run():
5972 ), f"Failed to trigger test run. Expected 204, got { response .status_code } . Response: { response .text } "
6073
6174
62- def get_workflow_runs ():
75+ def get_workflow_runs (auth_header ):
6376 print (f"Getting workflow runs after date: { run_date_filter } " )
6477 response = requests .get (
6578 f"{ GITHUB_API_URL } /runs?created=%3E{ run_date_filter } " ,
6679 headers = get_headers (),
80+ auth = auth_header ,
6781 )
6882 assert (
6983 response .status_code == 200
7084 ), f"Unable to get workflow runs. Expected 200, got { response .status_code } "
7185 return response .json ()["workflow_runs" ]
7286
7387
74- def get_jobs_for_workflow (jobs_url ):
88+ def get_jobs_for_workflow (jobs_url , auth_header ):
7589 print ("Getting jobs for workflow..." )
76- response = requests .get (jobs_url , headers = get_headers (), )
90+ response = requests .get (jobs_url , auth = auth_header )
7791 assert (
7892 response .status_code == 200
7993 ), f"Unable to get workflow jobs. Expected 200, got { response .status_code } "
8094 return response .json ()["jobs" ]
8195
8296
83- def find_workflow ():
97+ def find_workflow (auth_header ):
8498 max_attempts = 5
8599 current_attempt = 0
86100
@@ -89,58 +103,64 @@ def find_workflow():
89103 current_attempt = current_attempt + 1
90104 print (f"Attempt { current_attempt } " )
91105
92- workflow_runs = get_workflow_runs ()
106+ workflow_runs = get_workflow_runs (auth_header )
93107 for workflow in workflow_runs :
94108 time .sleep (3 )
95109 current_workflow_id = workflow ["id" ]
96110 jobs_url = workflow ["jobs_url" ]
97111
98- list_of_jobs = get_jobs_for_workflow (jobs_url )
99- if is_correct_job (list_of_jobs ) is True :
100- print (f"Workflow Job found! Using ID: { current_workflow_id } " )
101- return current_workflow_id
112+ list_of_jobs = get_jobs_for_workflow (jobs_url , auth_header )
113+
114+ if list_of_jobs :
115+ job = list_of_jobs [0 ]
116+ steps = job ["steps" ]
117+
118+ if len (steps ) >= 2 :
119+ third_step = steps [2 ]
120+ if third_step ["name" ] == run_id :
121+ print (f"Workflow Job found! Using ID: { current_workflow_id } " )
122+ return current_workflow_id
123+ else :
124+ print ("Not enough steps have been executed for this run yet..." )
125+ else :
126+ print ("Jobs for this workflow run haven't populated yet..." )
102127 print (
103128 "Processed all available workflows but no jobs were matching the Unique ID were found!"
104129 )
105130
106131
107- def is_correct_job (list_of_jobs ):
108- job = list_of_jobs [0 ]
109- steps = job ["steps" ]
110-
111- if len (steps ) >= 2 :
112- third_step = steps [2 ]
113- if third_step ["name" ] == run_id :
114- return True
132+ def get_auth_header (is_called_from_github , token , user ):
133+ if (is_called_from_github ):
134+ return BearerAuth (token )
115135 else :
116- print ("Jobs for this workflow run haven't populated yet..." )
136+ user_credentials = user .split (":" )
137+ return HTTPBasicAuth (user_credentials [0 ], user_credentials [1 ])
117138
118139
119- def get_job ():
140+ def get_job (auth_header ):
120141 job_request_url = f"{ GITHUB_API_URL } /runs/{ workflow_id } /jobs"
121142 job_response = requests .get (
122143 job_request_url ,
123- headers = get_headers ()
144+ headers = get_headers (),
145+ auth = auth_header ,
124146 )
125147
126148 return job_response .json ()["jobs" ][0 ]
127149
128150
129- def check_job ():
151+ def check_job (auth_header ):
130152 print ("Checking job status, please wait..." )
131153 print ("Current status:" , end = " " )
132- job = get_job ()
154+ job = get_job (auth_header )
133155 job_status = job ["status" ]
134156
135157 while job_status != "completed" :
136158 print (job_status )
137159 time .sleep (10 )
138- job = get_job ()
160+ job = get_job (auth_header )
139161 job_status = job ["status" ]
140162
141- assert (
142- job ["conclusion" ] == "success"
143- ), "The regressions test step failed! There are likely test failures."
163+ return job ["conclusion" ]
144164
145165
146166if __name__ == "__main__" :
@@ -157,14 +177,52 @@ def check_job():
157177 help = "Please provide the environment you wish to run in." ,
158178 )
159179 parser .add_argument (
160- "--token" , required = True , help = "Please provide the authentication token."
180+ "--user" , required = False , help = "Please provide the user credentials."
181+ )
182+ parser .add_argument (
183+ '--is_called_from_github' ,
184+ default = False ,
185+ type = lambda x : (str (x ).lower () == 'true' ),
186+ help = "If this is being called from github actions rather than azure"
161187 )
188+ parser .add_argument (
189+ "--product" , required = True , help = "Please provide the product to run the tests for."
190+ )
191+ parser .add_argument (
192+ "--token" , required = False , help = "Please provide the authentication token."
193+ )
194+
162195 arguments = parser .parse_args ()
196+
197+ print (f"pr_label: { arguments .pr_label } " )
198+ print (f"env: { arguments .env } " )
199+ print (f"is_called_from_github: { arguments .is_called_from_github } " )
200+ print (f"product: { arguments .product } " )
201+ print (f"regression_tests_repo_tag: { REGRESSION_TESTS_REPO_TAG } " )
202+
163203 run_id = generate_unique_run_id ()
164204 run_date_filter = generate_timestamp ()
205+ auth_header = get_auth_header (arguments .is_called_from_github , arguments .token , arguments .user )
206+
207+ pr_label = arguments .pr_label .lower ()
208+ trigger_test_run (
209+ arguments .env ,
210+ pr_label ,
211+ arguments .product ,
212+ auth_header
213+ )
165214
166- trigger_test_run ()
215+ workflow_id = find_workflow (auth_header )
216+ job_status = check_job (auth_header )
217+ if job_status != "success" :
218+ if arguments .pr_label :
219+ pr_label = arguments .pr_label .lower ()
220+ env = f"PULL-REQUEST/{ pr_label } "
221+ else :
222+ env = arguments .env .upper ()
223+ print ("The regressions test step failed! There are likely test failures." )
224+ print (f"See { GITHUB_RUN_URL } /{ workflow_id } / for run details)" )
225+ print (f"See https://nhsdigital.github.io/eps-test-reports/{ arguments .product } /{ env } / for allure report" )
226+ raise Exception ("Regression test failed" )
167227
168- workflow_id = find_workflow ()
169- check_job ()
170228 print ("Success!" )
0 commit comments