Skip to content
Merged
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
4 changes: 4 additions & 0 deletions doc/changes/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@
## Bugfix

* #563: Fixed merge-gate to prevent auto-merges from happening when integration tests failed

## Feature

* #829: Extended removing a job from a workflow to also remove it from the `needs` of another job
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ The PTB allows you to customise workflows by targeting specific jobs or steps:

.. note::

These operations do not currently cascade. For example, removing a job
without accounting for its downstream dependencies may result in errors.
You must manually adjust any subsequent steps that rely on the removed
job's or step's output.
These operations do not currently fully cascade. For example, removing a job will
remove it from the workflow and the needs of any subsequent job, but it does not
alter a matrix or steps relying on it. Thus, you must manually adjust any subsequent
steps relying on the removed job's or step's output.

To utilize this feature, create a ``.workflow-patcher.yml`` file in your project's
root directory, as specified further in :ref:`workflow_patcher`. This file will be
Expand Down
21 changes: 21 additions & 0 deletions exasol/toolbox/util/workflows/process_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,27 @@ def _remove_jobs(self, remove_jobs: CommentedMap) -> None:
self._verify_job_exists(job_name)
logger.debug(f"Remove job '{job_name}'")
self.jobs_dict.pop(job_name)
self._remove_job_from_needs(job_name=job_name)

def _remove_job_from_needs(self, job_name: str) -> None:
"""
Remove the job from the needs of subsequent jobs.
Comment thread
ArBridgeman marked this conversation as resolved.
This does NOT handle cases where the needed job is used for subsequent
operations in another job (e.g. when it is used to define the matrix).
"""
for other_job_name, other_job in self.jobs_dict.items():
needs = other_job.get("needs")
if needs is None:
continue

logger.debug(
f"Remove job '{job_name}' from needs of job '{other_job_name}'"
)
needs_without_removed_job = [need for need in needs if need != job_name]
if len(needs_without_removed_job) == 0:
other_job.pop("needs")
return
other_job["needs"] = needs_without_removed_job

def _verify_job_exists(self, job_name: str) -> None:
if job_name not in self.jobs_dict:
Expand Down
47 changes: 46 additions & 1 deletion test/unit/util/workflows/process_template_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@
id: check-out-repository
uses: actions/checkout@v6

fast-report:
name: Fast Report
needs:
- build-documentation-and-check-links
- run-unit-tests
uses: ./.github/workflows/report.yml
secrets: inherit
permissions:
contents: read

"""


Expand Down Expand Up @@ -79,6 +89,7 @@ def test__remove_jobs_works(
assert list(workflow_dict["jobs"].keys()) == [
"build-documentation-and-check-links",
"run-unit-tests",
"fast-report",
]
# The original and resulting workflows should have the same values here.
assert result["name"] == workflow_dict["name"]
Expand All @@ -87,7 +98,41 @@ def test__remove_jobs_works(
result["jobs"]["run-unit-tests"] == workflow_dict["jobs"]["run-unit-tests"]
)
# The resulting workflow has job "build-documentation-and-check-links" removed.
assert list(result["jobs"].keys()) == ["run-unit-tests"]
assert list(result["jobs"].keys()) == ["run-unit-tests", "fast-report"]
# fast-report still needs "run-unit-tests"
assert result["jobs"]["fast-report"]["needs"] == ["run-unit-tests"]

@staticmethod
def test__remove_jobs_works_removes_one_job(
workflow_name, workflow_dict, workflow_patcher, remove_job_yaml
):
workflow_modifier = WorkflowModifier(
workflow_dict=workflow_dict,
patch_yaml=workflow_patcher.extract_by_workflow(workflow_name),
)

workflow_modifier._remove_jobs(["run-unit-tests"])

result = workflow_modifier.workflow_dict
assert result["jobs"]["fast-report"]["needs"] == [
"build-documentation-and-check-links"
]

@staticmethod
def test__remove_jobs_works_removes_empty_needs(
workflow_name, workflow_dict, workflow_patcher, remove_job_yaml
):
workflow_modifier = WorkflowModifier(
workflow_dict=workflow_dict,
patch_yaml=workflow_patcher.extract_by_workflow(workflow_name),
)

workflow_modifier._remove_jobs(
["build-documentation-and-check-links", "run-unit-tests"]
)

result = workflow_modifier.workflow_dict
assert "needs" not in result["jobs"]["fast-report"]
Comment thread
ArBridgeman marked this conversation as resolved.

@staticmethod
@pytest.mark.parametrize(
Expand Down