Skip to content
Draft
2 changes: 1 addition & 1 deletion .github/workflows/build-and-publish.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .github/workflows/check-release-tag.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 8 additions & 8 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:

- name: Set up Python & Poetry Environment
id: set-up-python-and-poetry-environment
uses: exasol/python-toolbox/.github/actions/python-environment@v6
uses: exasol/python-toolbox/.github/actions/python-environment@v7
with:
python-version: "3.10"
poetry-version: "2.3.0"
Expand All @@ -42,7 +42,7 @@ jobs:

- name: Set up Python & Poetry Environment
id: set-up-python-and-poetry-environment
uses: exasol/python-toolbox/.github/actions/python-environment@v6
uses: exasol/python-toolbox/.github/actions/python-environment@v7
with:
python-version: "3.10"
poetry-version: "2.3.0"
Expand All @@ -67,7 +67,7 @@ jobs:

- name: Set up Python & Poetry Environment
id: set-up-python-and-poetry-environment
uses: exasol/python-toolbox/.github/actions/python-environment@v6
uses: exasol/python-toolbox/.github/actions/python-environment@v7
with:
python-version: ${{ matrix.python-versions }}
poetry-version: "2.3.0"
Expand Down Expand Up @@ -102,7 +102,7 @@ jobs:

- name: Set up Python & Poetry Environment
id: set-up-python-and-poetry-environment
uses: exasol/python-toolbox/.github/actions/python-environment@v6
uses: exasol/python-toolbox/.github/actions/python-environment@v7
with:
python-version: ${{ matrix.python-versions }}
poetry-version: "2.3.0"
Expand All @@ -128,7 +128,7 @@ jobs:

- name: Set up Python & Poetry Environment
id: set-up-python-and-poetry-environment
uses: exasol/python-toolbox/.github/actions/python-environment@v6
uses: exasol/python-toolbox/.github/actions/python-environment@v7
with:
python-version: ${{ matrix.python-versions }}
poetry-version: "2.3.0"
Expand Down Expand Up @@ -157,7 +157,7 @@ jobs:

- name: Set up Python & Poetry Environment
id: set-up-python-and-poetry-environment
uses: exasol/python-toolbox/.github/actions/python-environment@v6
uses: exasol/python-toolbox/.github/actions/python-environment@v7
with:
python-version: "3.10"
poetry-version: "2.3.0"
Expand All @@ -179,7 +179,7 @@ jobs:

- name: Set up Python & Poetry Environment
id: set-up-python-and-poetry-environment
uses: exasol/python-toolbox/.github/actions/python-environment@v6
uses: exasol/python-toolbox/.github/actions/python-environment@v7
with:
python-version: "3.10"
poetry-version: "2.3.0"
Expand Down Expand Up @@ -227,7 +227,7 @@ jobs:
fetch-depth: 0
- name: Set up Python & Poetry Environment
id: set-up-python-and-poetry-environment
uses: exasol/python-toolbox/.github/actions/python-environment@v6
uses: exasol/python-toolbox/.github/actions/python-environment@v7
with:
python-version: ${{ matrix.python-versions }}
poetry-version: "2.3.0"
Expand Down
100 changes: 100 additions & 0 deletions .github/workflows/dependency-update.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
name: Dependency Update
Comment thread
ArBridgeman marked this conversation as resolved.
Comment thread
Rimsha2535 marked this conversation as resolved.
Copy link
Copy Markdown
Collaborator

@ArBridgeman ArBridgeman Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need to add documentation to:
https://exasol.github.io/python-toolbox/main/user_guide/configuration.html

To do that, we typically create a sub-page in the relevant area. In this case, we have a nice page that we can add to:
https://exasol.github.io/python-toolbox/main/user_guide/features/github_workflows/github_project_configuration.html#

Under the section Secret, we should add the Slack token name, similar to how the PYPI_TOKEN was done. Maybe then, we should also provide a link using RST (not a hyperlink) to your Dependency Update section you wrote, but we could also leave that away.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Slack token name is INTEGRATION_TEAM_SECURITY_UPDATES_WEBHOOK,
and it's used for the SLACK_WEBHOOK_URL. We don't need to put SLACK_WEBHOOK_URL in the description, but it might be helpful to know that for what you're writing 😉

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we add the slack step to the dependency-update.yml, we should include Python in the title, so it's easy to search in the slack channel.


on:
schedule:
# Every Monday at 03:00 UTC
- cron: "0 3 * * 1"
workflow_dispatch:

jobs:
dependency-update:
name: Dependency Update
runs-on: "ubuntu-24.04"
permissions:
contents: write
pull-requests: write

steps:
- name: Check out Repository
id: check-out-repository
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Fail if not running on the default branch
id: check-branch
if: github.ref != format('refs/heads/{0}', github.event.repository.default_branch)
uses: actions/github-script@v8
with:
script: |
core.setFailed('Not running on the default branch. github.ref is ${{ github.ref }}')

- name: Set up Python & Poetry Environment
id: set-up-python-and-poetry-environment
uses: exasol/python-toolbox/.github/actions/python-environment@v6
with:
python-version: "3.10"
poetry-version: "2.3.0"

- name: Audit Dependencies
id: audit-dependencies
run: |
poetry run -- nox -s dependency:audit | tee vulnerabilities.json
LENGTH=$(jq 'length' vulnerabilities.json)
echo "count=$LENGTH" >> "$GITHUB_OUTPUT"

- name: Update Dependencies
id: update-dependencies
if: steps.audit-dependencies.outputs.count > 0
run: poetry update

- name: Check for poetry.lock Changes
id: check-for-poetry-lock-changes
if: steps.audit-dependencies.outputs.count > 0
run: |
if git diff --quiet -- poetry.lock; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi

- name: Configure git
id: configure-git
if: steps.check-for-poetry-lock-changes.outputs.changed == 'true'
run: |
git config --global user.email "opensource@exasol.com"
git config --global user.name "Automatic Dependency Updater"

- name: Create branch
id: create-branch
if: steps.check-for-poetry-lock-changes.outputs.changed == 'true'
run: |
branch_name="dependency-update/$(date "+%Y%m%d%H%M%S")"
echo "Creating branch $branch_name"
git switch -C "$branch_name"

- name: Commit changes & push
id: publish-branch
if: steps.check-for-poetry-lock-changes.outputs.changed == 'true'
run: |
branch_name=$(git rev-parse --abbrev-ref HEAD)
git add poetry.lock
git commit --message "Update poetry.lock"
git push --set-upstream origin "$branch_name"

- name: Create pull request
id: create-pr
if: steps.check-for-poetry-lock-changes.outputs.changed == 'true'
env:
GH_TOKEN: ${{ github.token }}
run: |-
BASE_BRANCH=$(gh repo view --json defaultBranchRef -q .defaultBranchRef.name)

gh pr create \
--base "$BASE_BRANCH" \
--title "Update dependencies to fix vulnerabilities ($(date '+%Y-%m-%d'))" \
--body "Automated dependency update for \`poetry.lock\`.

This PR was created by the dependency update workflow after running:
- \`poetry run -- nox -s dependency:audit\`
- \`poetry update\`"
Comment thread
ArBridgeman marked this conversation as resolved.
2 changes: 1 addition & 1 deletion .github/workflows/gh-pages.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .github/workflows/matrix-all.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .github/workflows/matrix-exasol.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .github/workflows/matrix-python.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .github/workflows/report.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .github/workflows/slow-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:

- name: Set up Python & Poetry Environment
id: set-up-python-and-poetry-environment
uses: exasol/python-toolbox/.github/actions/python-environment@v6
uses: exasol/python-toolbox/.github/actions/python-environment@v7
with:
python-version: ${{ matrix.python-version }}
poetry-version: "2.3.0"
Expand Down
14 changes: 14 additions & 0 deletions doc/user_guide/features/github_workflows/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ Workflows
- Pull request and monthly
- Executes the continuous integration suite by calling ``merge-gate.yml`` and
``report.yml``. See :ref:`ci_yml` for a graph of workflow calls.
* - ``dependency-update.yml``
- Weekly and manual
- Audits project dependencies for known vulnerabilities, updates them with Poetry when needed, and creates a pull request if the ``poetry.lock`` was changed.
* - ``gh-pages.yml``
- Workflow call
- Builds the documentation and deploys it to GitHub Pages.
Expand Down Expand Up @@ -97,6 +100,17 @@ Workflows
CI Actions
----------

Dependency Update
^^^^^^^^^^^^^^^^^

The ``dependency-update.yml`` workflow is used to resolve vulnerabilities by updating our project dependencies.

It can be triggered manually and is also scheduled to run weekly.

The workflow first audits dependencies for known vulnerabilities. If vulnerabilities
are detected, it updates the dependencies using Poetry. When the ``poetry.lock`` is changed,
then it creates a pull request with the update.

.. _ci_yml:

Pull Request
Copy link
Copy Markdown
Collaborator

@ArBridgeman ArBridgeman Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should also add a changelog entry for this in doc/changes/unreleased.md.
You can check out doc/changes/changes_6.3.0.md for inspiration.

For adding it to the changelog:

  1. Add an entry under the section Features. We tend to keep these to a short sentence description that follows the format:
  • #<GitHub issue number>: <Past tense verb> <clause describing the changes>
  1. Depending on the change, we add a longer description under Summary. In this case, I think it's worthwhile to add a few sentences and link to the documentation . This is because the CI will change for other projects due to this.

Expand Down
100 changes: 100 additions & 0 deletions exasol/toolbox/templates/github/workflows/dependency-update.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
name: Dependency Update

on:
schedule:
# Every Monday at 03:00 UTC
- cron: "0 3 * * 1"
workflow_dispatch:
Comment thread
ArBridgeman marked this conversation as resolved.

jobs:
dependency-update:
name: Dependency Update
runs-on: "(( os_version ))"
permissions:
contents: write
pull-requests: write

steps:
- name: Check out Repository
id: check-out-repository
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Fail if not running on the default branch
id: check-branch
if: github.ref != format('refs/heads/{0}', github.event.repository.default_branch)
uses: actions/github-script@v8
with:
script: |
core.setFailed('Not running on the default branch. github.ref is ${{ github.ref }}')

- name: Set up Python & Poetry Environment
id: set-up-python-and-poetry-environment
uses: exasol/python-toolbox/.github/actions/python-environment@v6
with:
python-version: "(( minimum_python_version ))"
poetry-version: "(( dependency_manager_version ))"

- name: Audit Dependencies
id: audit-dependencies
run: |
poetry run -- nox -s dependency:audit | tee vulnerabilities.json
LENGTH=$(jq 'length' vulnerabilities.json)
echo "count=$LENGTH" >> "$GITHUB_OUTPUT"

- name: Update Dependencies
id: update-dependencies
if: steps.audit-dependencies.outputs.count > 0
run: poetry update

- name: Check for poetry.lock Changes
id: check-for-poetry-lock-changes
if: steps.audit-dependencies.outputs.count > 0
run: |
if git diff --quiet -- poetry.lock; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi

- name: Configure git
id: configure-git
if: steps.check-for-poetry-lock-changes.outputs.changed == 'true'
run: |
git config --global user.email "opensource@exasol.com"
git config --global user.name "Automatic Dependency Updater"

- name: Create branch
id: create-branch
if: steps.check-for-poetry-lock-changes.outputs.changed == 'true'
run: |
branch_name="dependency-update/$(date "+%Y%m%d%H%M%S")"
echo "Creating branch $branch_name"
git switch -C "$branch_name"

- name: Commit changes & push
id: publish-branch
if: steps.check-for-poetry-lock-changes.outputs.changed == 'true'
run: |
branch_name=$(git rev-parse --abbrev-ref HEAD)
git add poetry.lock
git commit --message "Update poetry.lock"
git push --set-upstream origin "$branch_name"

- name: Create pull request
id: create-pr
if: steps.check-for-poetry-lock-changes.outputs.changed == 'true'
env:
GH_TOKEN: ${{ github.token }}
run: |
BASE_BRANCH=$(gh repo view --json defaultBranchRef -q .defaultBranchRef.name)

gh pr create \
Comment thread
Rimsha2535 marked this conversation as resolved.
--base "$BASE_BRANCH" \
--title "Update dependencies to fix vulnerabilities ($(date '+%Y-%m-%d'))" \
--body "Automated dependency update for \`poetry.lock\`.

This PR was created by the dependency update workflow after running:
- \`poetry run -- nox -s dependency:audit\`
- \`poetry update\`"
2 changes: 1 addition & 1 deletion exasol/toolbox/util/dependencies/audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ def load_from_pip_audit(cls, working_directory: Path) -> Vulnerabilities:

vulnerabilities = []
for entry in audit_dict["dependencies"]:
for vuln_entry in entry["vulns"]:
for vuln_entry in entry.get("vulns", []):
vulnerabilities.append(
Vulnerability.from_audit_entry(
package_name=entry["name"],
Expand Down
2 changes: 1 addition & 1 deletion test/integration/project-template/nox_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,4 @@ def test_install_github_workflows(self, poetry_path, run_command):
assert output.returncode == 0

file_list = run_command(["ls", ".github/workflows"]).stdout.splitlines()
assert len(file_list) == 13
assert len(file_list) == 14
Comment thread
Rimsha2535 marked this conversation as resolved.
2 changes: 1 addition & 1 deletion test/unit/nox/_workflow_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class TestGenerateWorkflow:
@staticmethod
@pytest.mark.parametrize(
"nox_session_runner_posargs, expected_count",
[(ALL, 13), *[(key, 1) for key in WORKFLOW_TEMPLATE_OPTIONS.keys()]],
[(ALL, 14), *[(key, 1) for key in WORKFLOW_TEMPLATE_OPTIONS.keys()]],
indirect=["nox_session_runner_posargs"],
)
def test_works_as_expected(
Expand Down
Loading