Skip to content

Commit 5a95dda

Browse files
committed
Apply review comments
1 parent 0fc2f14 commit 5a95dda

1 file changed

Lines changed: 93 additions & 58 deletions

File tree

  • src/ci/github-actions

‎src/ci/github-actions/ci.py‎

Lines changed: 93 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@ def add_job_properties(jobs: List[Dict], prefix: str) -> List[Job]:
3434
"""
3535
modified_jobs= []
3636
forjobinjobs:
37-
job=dict(job)
38-
job["image"] =get_job_image(job)
39-
job["name"] =f"{prefix} - {job['name']}"
40-
modified_jobs.append(job)
37+
# Create a copy of the `job` dictionary to avoid modifying `jobs`
38+
new_job=dict(job)
39+
new_job["image"] =get_job_image(new_job)
40+
new_job["name"] =f"{prefix} - {new_job['name']}"
41+
modified_jobs.append(new_job)
4142
returnmodified_jobs
4243

4344

@@ -46,11 +47,15 @@ def add_base_env(jobs: List[Job], environment: Dict[str, str]) -> List[Job]:
4647
Prepends `environment` to the `env` attribute of each job.
4748
The `env` of each job has higher precedence than `environment`.
4849
"""
50+
modified_jobs= []
4951
forjobinjobs:
5052
env=environment.copy()
5153
env.update(job.get("env", {}))
52-
job["env"] =env
53-
returnjobs
54+
55+
new_job=dict(job)
56+
new_job["env"] =env
57+
modified_jobs.append(new_job)
58+
returnmodified_jobs
5459

5560

5661
@dataclasses.dataclass
@@ -123,7 +128,9 @@ def find_run_type(ctx: GitHubCtx) -> Optional[WorkflowRunType]:
123128

124129
defcalculate_jobs(run_type: WorkflowRunType, job_data: Dict[str, Any]) ->List[Job]:
125130
ifisinstance(run_type, PRRunType):
126-
returnadd_base_env(add_job_properties(job_data["pr"], "PR"), job_data["envs"]["pr"])
131+
returnadd_base_env(
132+
add_job_properties(job_data["pr"], "PR"), job_data["envs"]["pr"]
133+
)
127134
elifisinstance(run_type, TryRunType):
128135
jobs=job_data["try"]
129136
custom_jobs=run_type.custom_jobs
@@ -188,95 +195,123 @@ def format_run_type(run_type: WorkflowRunType) -> str:
188195
raiseAssertionError()
189196

190197

191-
defget_job_image(job) ->str:
198+
defget_job_image(job: Job) ->str:
192199
"""
193200
By default, the Docker image of a job is based on its name.
194201
However, it can be overridden by its IMAGE environment variable.
195202
"""
196-
returnjob.get("env", {}).get("IMAGE", job["name"])
203+
env=job.get("env", {})
204+
# Return the IMAGE environment variable if it exists, otherwise return the job name
205+
returnenv.get("IMAGE", job["name"])
197206

198207

199-
defrun_workflow_locally(job_data: Dict[str, Any], job_name: str, pr_jobs: bool):
200-
DOCKER_DIR=Path(__file__).absolute().parent.parent/"docker"
208+
defis_linux_job(job: Job) ->bool:
209+
return"ubuntu"injob["os"]
201210

202-
jobs=job_data["pr"] ifpr_jobselsejob_data["auto"]
203-
jobs= [jobforjobinjobsifjob.get("name") ==job_name]
211+
212+
deffind_linux_job(job_data: Dict[str, Any], job_name: str, pr_jobs: bool) ->Job:
213+
candidates=job_data["pr"] ifpr_jobselsejob_data["auto"]
214+
jobs= [jobforjobincandidatesifjob.get("name") ==job_name]
204215
iflen(jobs) ==0:
205-
raiseException(f"Job `{job_name}` not found in {'pr'ifpr_jobselse'auto'} jobs")
216+
available_jobs="\n".join(
217+
sorted(job["name"] forjobincandidatesifis_linux_job(job))
218+
)
219+
raiseException(f"""Job `{job_name}` not found in {'pr'ifpr_jobselse'auto'} jobs.
220+
The following jobs are available:
221+
{available_jobs}""")
206222
assertlen(jobs) ==1
223+
207224
job=jobs[0]
208-
if"ubuntu"notinjob["os"]:
225+
ifnotis_linux_job(job):
209226
raiseException("Only Linux jobs can be executed locally")
227+
returnjob
228+
229+
230+
defrun_workflow_locally(job_data: Dict[str, Any], job_name: str, pr_jobs: bool):
231+
DOCKER_DIR=Path(__file__).absolute().parent.parent/"docker"
232+
233+
job=find_linux_job(job_data, job_name=job_name, pr_jobs=pr_jobs)
210234

211235
custom_env= {}
212-
custom_env["DEPLOY"] ="1"
236+
# Replicate src/ci/scripts/setup-environment.sh
237+
# Adds custom environment variables to the job
238+
ifjob_name.startswith("dist-"):
239+
ifjob_name.endswith("-alt"):
240+
custom_env["DEPLOY_ALT"] ="1"
241+
else:
242+
custom_env["DEPLOY"] ="1"
213243
custom_env.update({k: str(v) for (k, v) injob.get("env", {}).items()})
214244

215-
args= [
216-
str(DOCKER_DIR/"run.sh"),
217-
get_job_image(job)
218-
]
245+
args= [str(DOCKER_DIR/"run.sh"), get_job_image(job)]
219246
env_formatted= [f"{k}={v}"for (k, v) insorted(custom_env.items())]
220247
print(f"Executing `{' '.join(env_formatted)}{' '.join(args)}`")
221248

222249
env=os.environ.copy()
223250
env.update(custom_env)
224251

225-
process=subprocess.Popen(args, env=env)
226-
try:
227-
process.wait()
228-
exceptKeyboardInterrupt:
229-
process.kill()
252+
subprocess.run(args, env=env)
230253

231254

232-
if__name__=="__main__":
233-
logging.basicConfig(level=logging.INFO)
255+
defcalculate_job_matrix(job_data: Dict[str, Any]):
256+
github_ctx=get_github_ctx()
234257

235-
withopen(JOBS_YAML_PATH) asf:
236-
data=yaml.safe_load(f)
258+
run_type=find_run_type(github_ctx)
259+
logging.info(f"Job type: {run_type}")
237260

261+
withopen(CI_DIR/"channel") asf:
262+
channel=f.read().strip()
263+
264+
jobs= []
265+
ifrun_typeisnotNone:
266+
jobs=calculate_jobs(run_type, job_data)
267+
jobs=skip_jobs(jobs, channel)
268+
269+
ifnotjobs:
270+
raiseException("Scheduled job list is empty, this is an error")
271+
272+
run_type=format_run_type(run_type)
273+
274+
logging.info(f"Output:\n{yaml.dump(dict(jobs=jobs, run_type=run_type), indent=4)}")
275+
print(f"jobs={json.dumps(jobs)}")
276+
print(f"run_type={run_type}")
277+
278+
279+
defcreate_cli_parser():
238280
parser=argparse.ArgumentParser(
239-
prog="ci.py",
240-
description="Generate or run CI workflows"
281+
prog="ci.py", description="Generate or run CI workflows"
282+
)
283+
subparsers=parser.add_subparsers(
284+
help="Command to execute", dest="command", required=True
285+
)
286+
subparsers.add_parser(
287+
"calculate-job-matrix",
288+
help="Generate a matrix of jobs that should be executed in CI",
289+
)
290+
run_parser=subparsers.add_parser(
291+
"run-local", help="Run a CI jobs locally (on Linux)"
241292
)
242-
generate_matrix=argparse.ArgumentParser()
243-
subparsers=parser.add_subparsers(help="Command to execute", dest="command", required=True)
244-
subparsers.add_parser("calculate-job-matrix")
245-
run_parser=subparsers.add_parser("run-local")
246293
run_parser.add_argument(
247294
"job_name",
248295
help="CI job that should be executed. By default, a merge (auto) "
249-
"job with the given name will be executed"
296+
"job with the given name will be executed",
250297
)
251298
run_parser.add_argument(
252-
"--pr",
253-
action="store_true",
254-
help="Run a PR job instead of an auto job"
299+
"--pr", action="store_true", help="Run a PR job instead of an auto job"
255300
)
256-
args=parser.parse_args()
257-
258-
ifargs.command=="calculate-job-matrix":
259-
github_ctx=get_github_ctx()
301+
returnparser
260302

261-
run_type=find_run_type(github_ctx)
262-
logging.info(f"Job type: {run_type}")
263303

264-
withopen(CI_DIR/"channel") asf:
265-
channel=f.read().strip()
266-
267-
jobs= []
268-
ifrun_typeisnotNone:
269-
jobs=calculate_jobs(run_type, data)
270-
jobs=skip_jobs(jobs, channel)
304+
if__name__=="__main__":
305+
logging.basicConfig(level=logging.INFO)
271306

272-
ifnotjobs:
273-
raiseException("Scheduled job list is empty, this is an error")
307+
withopen(JOBS_YAML_PATH) asf:
308+
data=yaml.safe_load(f)
274309

275-
run_type=format_run_type(run_type)
310+
parser=create_cli_parser()
311+
args=parser.parse_args()
276312

277-
logging.info(f"Output:\n{yaml.dump(dict(jobs=jobs, run_type=run_type), indent=4)}")
278-
print(f"jobs={json.dumps(jobs)}")
279-
print(f"run_type={run_type}")
313+
ifargs.command=="calculate-job-matrix":
314+
calculate_job_matrix(data)
280315
elifargs.command=="run-local":
281316
run_workflow_locally(data, args.job_name, args.pr)
282317
else:

0 commit comments

Comments
 (0)