Skip to content

Commit 095e09e

Browse files
authored
Bugfix/898 improve code related to bug in dependency update (#915)
* Updated poetry.lock * Add git function to test uncommitted path changes * Add git function for add & commit * Add report_json for more human readable performance * Add DependencyUpdater * Add vulnerabilities:update nox session * Update workflow and documentation; exclude templates from pre-commit hook * Prepare release 10.2.0
1 parent 1196fc1 commit 095e09e

25 files changed

Lines changed: 788 additions & 370 deletions

File tree

.github/actions/security-issues/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ runs:
3939
- name: Install Python Toolbox / Security tool
4040
shell: bash
4141
run: |
42-
pip install exasol-toolbox==10.1.0
42+
pip install exasol-toolbox==10.2.0
4343
4444
- name: Create Security Issue Report
4545
shell: bash

.github/workflows/dependency-update.yml

Lines changed: 31 additions & 40 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.pre-commit-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ repos:
3535
rev: v5.0.0
3636
hooks:
3737
- id: check-yaml
38+
exclude: ^exasol/toolbox/templates/github/workflows/
3839
stages: [ pre-commit ]
3940
- id: end-of-file-fixer
4041
stages: [ pre-commit ]

doc/changes/changelog.md

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

doc/changes/changes_10.2.0.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# 10.2.0 - 2026-07-07
2+
3+
## Summary
4+
5+
This minor release adds automated vulnerability updates through Nox session
6+
`vulnerabilities:update` and improves the `dependency-update.yml`. It also includes a
7+
few workflow-related bug fixes and documentation updates.
8+
9+
## Bug
10+
11+
* #909: Updated `cd.yml` workflow so that `cd-extension.yml` workflow depends on `build-and-publish`. This ensures that the custom release workflow only runs when the PyPi release was successful.
12+
* #910: Added `gh-pages.yml` to be ignored when `has_documentation=False` in the `PROJECT_CONFIG`
13+
14+
## Feature
15+
16+
* #898: Created Nox session `vulnerabilities:update` to automatically resolve
17+
vulnerable dependencies and report the result for the dependency update workflow
18+
19+
## Dependency Updates
20+
21+
### `main`
22+
23+
* Updated dependency `coverage:7.14.3` to `7.15.0`
24+
* Updated dependency `typer:0.26.7` to `0.26.8`

doc/changes/unreleased.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
11
# Unreleased
22

33
## Summary
4-
5-
## Bug
6-
7-
* #909: Updated `cd.yml` workflow so that `cd-extension.yml` workflow depends on `build-and-publish`. This ensures that the custom release workflow only runs when the PyPi release was successful.
8-
* #910: Add `gh-pages.yml` to be ignored when `has_documentation=False` in the `PROJECT_CONFIG`

doc/user_guide/features/github_workflows/index.rst

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ Workflows
3939
The PTB allows for two categories of workflows:
4040
#. those maintained by the PTB, which can be modified using the :ref:`workflow_patcher`.
4141
#. custom workflows, which are project-owned.
42-
43-
Custom workflows can optionally be
42+
43+
Custom workflows can optionally be
4444
* seeded by the PTB, i.e. PTB generates an initial version but ignores future changes.
4545
* extend PTB-provided workflows, i.e. ending in `-extension.yml`
46-
46+
4747
Besides that, you can also create individual workflow files which are ignored by the PTB.
4848

4949
Maintained by the PTB
@@ -311,14 +311,17 @@ checks for known vulnerabilities and tries to fix them by updating dependencies.
311311
:start-at: on:
312312
:end-at: workflow_dispatch:
313313

314-
The workflow first audits dependencies for known vulnerabilities:
314+
The workflow runs a dedicated ``vulnerabilities:update`` nox session that audits the
315+
current dependency set and attempts to resolve any detected vulnerabilities:
315316

316317
* If no vulnerabilities are detected, then no update is needed.
317-
* If vulnerabilities are detected, it updates the dependencies using ``poetry update``.
318+
* If vulnerabilities are detected, the session updates the dependencies and
319+
records the outcome for the pull request.
318320

319-
* If the ``poetry.lock`` is unchanged, then no further action is taken.
320-
* If the ``poetry.lock`` is changed, then it creates a branch, stages the commit,
321-
creates a pull request, and sends a Slack notification.
321+
* If the update makes no effective change, then no further action is taken.
322+
* If the update changes the dependency state, then the workflow pushes the
323+
resulting commit, includes the post-update summary in the PR description,
324+
opens a pull request, and sends a Slack notification.
322325

323326
Afterwards, users need to perform some manual steps which are described in the PR description.
324327

doc/user_guide/features/managing_dependencies/index.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,17 @@ Managing Dependencies and Vulnerabilities
1919
- ``report.yml``
2020
- Uses ``pip-licenses`` to return packages with their licenses.
2121
* - ``dependency:audit``
22-
- ``dependency-update.yml``
22+
- No
2323
- Uses ``pip-audit`` to report active vulnerabilities in our dependencies.
2424
* - ``vulnerabilities:resolved``
2525
- No
2626
- Uses ``pip-audit`` to report known vulnerabilities in dependencies that
2727
have been resolved in comparison to the last release.
28+
* - ``vulnerabilities:update``
29+
- ``dependency-update.yml``
30+
- Uses ``pip-audit`` to update dependencies and commit ``poetry.lock`` when
31+
vulnerabilities are found. It also produces a concise JSON summary for
32+
the pull request description.
2833
* - ``workflow:audit``
2934
- ``checks.yml``
3035
- Uses ``zizmor`` to audit GitHub actions and workflows for security issues

exasol/toolbox/nox/_dependencies.py

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
from __future__ import annotations
22

3+
import argparse
34
import json
45
from pathlib import Path
56

67
import nox
78
from nox import Session
89

10+
from exasol.toolbox.nox._shared import validate_path_within_root
911
from exasol.toolbox.util.dependencies.audit import (
1012
PipAuditException,
1113
Vulnerabilities,
@@ -18,9 +20,18 @@
1820
)
1921
from exasol.toolbox.util.dependencies.poetry_dependencies import get_dependencies
2022
from exasol.toolbox.util.dependencies.track_vulnerabilities import DependenciesAudit
23+
from exasol.toolbox.util.dependencies.update_dependencies import DependencyUpdater
2124
from noxconfig import PROJECT_CONFIG
2225

2326

27+
def _format_update_vulnerabilities_message(was_updated: bool, report_json: str) -> str:
28+
if not was_updated:
29+
return "No vulnerable dependencies were found."
30+
if report_json == "[]":
31+
return "No vulnerable dependencies remain after updating."
32+
return report_json
33+
34+
2435
@nox.session(name="dependency:licenses", python=False)
2536
def dependency_licenses(session: Session) -> None:
2637
"""Report licenses for all dependencies."""
@@ -35,16 +46,51 @@ def dependency_licenses(session: Session) -> None:
3546
@nox.session(name="dependency:audit", python=False)
3647
def audit(session: Session) -> None:
3748
"""Report known vulnerabilities."""
38-
3949
try:
40-
vulnerabilities = Vulnerabilities.load_from_pip_audit(working_directory=Path())
50+
vulnerabilities = Vulnerabilities.load_from_pip_audit(
51+
working_directory=PROJECT_CONFIG.root_path
52+
)
4153
except PipAuditException as e:
4254
session.error(e.returncode, e.stdout, e.stderr)
4355

4456
security_issue_dict = vulnerabilities.security_issue_dict
4557
print(json.dumps(security_issue_dict, indent=2))
4658

4759

60+
@nox.session(name="vulnerabilities:update", python=False)
61+
def update_vulnerabilities(session: Session) -> None:
62+
"""
63+
Update vulnerabilities and optionally save the JSON of remaining vulnerabilities
64+
to a file provided on the command line.
65+
"""
66+
parser = argparse.ArgumentParser(
67+
prog="nox -s vulnerabilities:update",
68+
description="Update vulnerable dependencies and optionally write a report file.",
69+
)
70+
parser.add_argument(
71+
"report_filename",
72+
nargs="?",
73+
help="Optional filename for the JSON report of remaining vulnerabilities.",
74+
)
75+
args = parser.parse_args(session.posargs)
76+
77+
try:
78+
dependency_updater = DependencyUpdater(root_path=PROJECT_CONFIG.root_path)
79+
was_updated, report_json = dependency_updater.update_vulnerable_dependencies()
80+
except PipAuditException as e:
81+
session.error(e.returncode, e.stdout, e.stderr)
82+
83+
if args.report_filename is None:
84+
print(_format_update_vulnerabilities_message(was_updated, report_json))
85+
return
86+
87+
report_path = validate_path_within_root(
88+
PROJECT_CONFIG.root_path / args.report_filename
89+
)
90+
report_path.parent.mkdir(parents=True, exist_ok=True)
91+
report_path.write_text(report_json + "\n", encoding="utf-8")
92+
93+
4894
@nox.session(name="vulnerabilities:resolved", python=False)
4995
def report_resolved_vulnerabilities(session: Session) -> None:
5096
"""Report resolved vulnerabilities in dependencies."""

exasol/toolbox/nox/_release.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,14 @@ def _get_changelogs(version: Version) -> Changelog:
6262
)
6363

6464

65-
def _add_files_to_index(session: Session, files: list[Path]) -> None:
66-
for file in files:
67-
session.run("git", "add", f"{file}")
65+
def _collect_release_files(session: Session, pm) -> tuple[Path, ...]:
66+
return tuple(
67+
path
68+
for plugin_files in pm.hook.prepare_release_add_files(
69+
session=session, config=PROJECT_CONFIG
70+
)
71+
for path in plugin_files
72+
)
6873

6974

7075
class ReleaseError(Exception):
@@ -120,9 +125,7 @@ def prepare_release(session: Session) -> None:
120125
if not args.no_branch and not args.no_add:
121126
Git.create_and_switch_to_branch(f"release/prepare-{new_version}")
122127

123-
changed_files = (
124-
_get_changelogs(version=new_version).prepare_release().get_changed_files()
125-
)
128+
changelogs = _get_changelogs(version=new_version).prepare_release()
126129

127130
pm = NoxTasks.plugin_manager(PROJECT_CONFIG)
128131
pm.hook.prepare_release_update_version(
@@ -132,15 +135,10 @@ def prepare_release(session: Session) -> None:
132135
if args.no_add:
133136
return
134137

135-
changed_files += [
136-
PROJECT_CONFIG.root_path / PoetryFiles.pyproject_toml,
137-
]
138-
results = pm.hook.prepare_release_add_files(session=session, config=PROJECT_CONFIG)
139-
changed_files += [f for plugin_response in results for f in plugin_response]
140-
_add_files_to_index(
141-
session,
142-
changed_files,
143-
)
138+
version_files = (PROJECT_CONFIG.root_path / PoetryFiles.pyproject_toml,)
139+
release_files = _collect_release_files(session=session, pm=pm)
140+
changed_files = changelogs.get_changed_files() + release_files + version_files
141+
Git.add(changed_files)
144142
session.run("git", "commit", "-m", f"Prepare release {new_version}")
145143

146144
if not args.no_pr:

0 commit comments

Comments
 (0)