diff --git a/bennettbot/job_configs.py b/bennettbot/job_configs.py index 6c21ae5..5fe1005 100644 --- a/bennettbot/job_configs.py +++ b/bennettbot/job_configs.py @@ -303,6 +303,11 @@ "restricted": True, "description": "Report GitHub Actions workflow runs", "jobs": { + "check_links": { + "run_args_template": "python jobs.py custom --job-name check-links", + "report_stdout": True, + "report_format": "blocks", + }, "display_emoji_key": { "run_args_template": "python jobs.py key", "report_stdout": True, @@ -325,6 +330,12 @@ }, }, "slack": [ + { + "command": "check-links", + "help": "Summarise GitHub Actions workflow runs for link-checking workflows in website repos.", + "action": "schedule_job", + "job_type": "check_links", + }, { "command": "key", "help": "Show the emoji key being used in the workflow summaries.", @@ -350,6 +361,7 @@ "action": "schedule_job", "job_type": "show", }, + ] }, "techsupport": { diff --git a/tests/workspace/test_workflows.py b/tests/workspace/test_workflows.py index d59aac7..42164eb 100644 --- a/tests/workspace/test_workflows.py +++ b/tests/workspace/test_workflows.py @@ -689,3 +689,89 @@ def test_main_show_invalid_target(): }, }, ] + + +@patch( + "workspace.workflows.config.CUSTOM_JOBS", + { + "check-links": { + "header_text": "Link-checking workflows", + "workflows": { + "opensafely/documentation": [82728346], + "ebmdatalab/bennett.ox.ac.uk": [82728346], + "ebmdatalab/opensafely.org": [82728346], + "ebmdatalab/team-manual": [82728346], + }, + } + }, +) +@use_mock_results( + [ + { + "org": "opensafely", + "repo": "documentation", + "team": "Tech shared", + "conclusions": ["success"] * 5, + }, + { + "org": "ebmdatalab", + "repo": "team-manual", + "team": "Tech shared", + "conclusions": ["failure"] * 5, + }, + { + "org": "ebmdatalab", + "repo": "bennett.ox.ac.uk", + "team": "Tech shared", + "conclusions": ["success"] * 5, + }, + { + "org": "ebmdatalab", + "repo": "opensafely.org", + "team": "Tech shared", + "conclusions": ["failure"] * 5, + }, + ] +) +def test_check_links(): + args = jobs.get_command_line_parser().parse_args( + "custom --job-name check-links".split() + ) + blocks = json.loads(jobs.get_blocks_for_custom_workflow_list(args)) + assert blocks == [ + { # Only 1 emoji should appear for each repo + "type": "header", + "text": { + "type": "plain_text", + "text": "Link-checking workflows", + }, + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": ": :large_green_circle:", + }, + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": ": :large_green_circle:", + }, + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": ": :red_circle:", + }, + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": ": :red_circle:", + }, + }, + ] diff --git a/workspace/workflows/config.py b/workspace/workflows/config.py index 2e0cf84..4304a82 100644 --- a/workspace/workflows/config.py +++ b/workspace/workflows/config.py @@ -69,7 +69,7 @@ }, "opensafely.org": { "org": "ebmdatalab", - "team": "Team REX", + "team": "Tech shared", }, "opencodelists": { "org": "opensafely-core", @@ -153,3 +153,15 @@ 31178226, # Check links (expected to break, notifications handled elsewhere) ], } + +CUSTOM_JOBS = { + "check-links": { + "header_text": "Link-checking workflows", + "workflows": { + "opensafely/documentation": [25878886], + "ebmdatalab/bennett.ox.ac.uk": [42498719], + "ebmdatalab/opensafely.org": [26433647], + "ebmdatalab/team-manual": [31178226], + }, + } +} diff --git a/workspace/workflows/jobs.py b/workspace/workflows/jobs.py index 757587b..0fb7177 100644 --- a/workspace/workflows/jobs.py +++ b/workspace/workflows/jobs.py @@ -313,6 +313,23 @@ def _main(org, repo, skip_successful=False) -> str: return report_invalid_org(org) +def get_blocks_for_custom_workflow_list(args): + job_config = config.CUSTOM_JOBS[args.job_name] + header_text = job_config["header_text"] + workflows = job_config["workflows"] + conclusions = {} + for location, workflow_ids in workflows.items(): + wf_conclusions = RepoWorkflowReporter(location).get_latest_conclusions() + conclusions[location] = [ + wf_conclusions.get(wf_id, "missing") for wf_id in workflow_ids + ] + blocks = [ + get_header_block(header_text), + *[get_summary_block(loc, conc) for loc, conc in conclusions.items()], + ] + return json.dumps(blocks) + + def get_text_blocks_for_key(args) -> str: blocks = get_basic_header_and_text_blocks( header_text="Workflow status emoji key", @@ -331,6 +348,11 @@ def get_command_line_parser(): # pragma: no cover show_parser.add_argument("--skip-successful", action="store_true", default=False) show_parser.set_defaults(func=main) + # Custom tasks + custom_parser = subparsers.add_parser("custom") + custom_parser.add_argument("--job-name", required=True) + custom_parser.set_defaults(func=get_blocks_for_custom_workflow_list) + # Display key key_parser = subparsers.add_parser("key") key_parser.set_defaults(func=get_text_blocks_for_key)