Skip to content
Draft
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
60 changes: 60 additions & 0 deletions .github/workflows/dependency-update.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Dependency Update
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.

You don't need to change it this time, but by convention, we normally name the branch feature/683-dependency-update-workflow.

By having the issue number in the branch name, we can better ensure that the branch name is unique. This can be helpful for locally checking out the branch as it makes it easily more identifiable.


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

- 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

- name: Update Dependencies
id: update-dependencies
run: poetry update

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

- name: Create Pull Request
id: create-pull-request
if: steps.check-for-poetry-lock-changes.outputs.changed == 'true'
uses: peter-evans/create-pull-request@v7
with:
commit-message: "Update poetry.lock"
branch: dependency-update/poetry-lock
delete-branch: true
title: "Update poetry.lock"
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`
14 changes: 14 additions & 0 deletions doc/github_actions/dependency_update.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
dependency-update
=================

This workflow updates the project dependencies using Poetry.

It first runs a dependency audit via ``nox -s dependency:audit`` and then updates the dependencies using ``poetry update``.
If the ``poetry.lock`` file changes, a pull request is created automatically.

Example Usage
-------------

.. code-block:: bash

tbx workflow install dependency-update
1 change: 1 addition & 0 deletions doc/github_actions/github_actions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@

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

on:
schedule:
# Every Monday at 03:00 UTC
- cron: "0 3 * * 1"
workflow_dispatch:
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.

workflow_dispatch usually only works if we've merged the branch to the default branch. Ideally, we'd like to test it out before then.

Was there an approach you and @kratz00 had discussed?


One idea is that we could use workflow_call and have .github/workflows/dependency-update.yml called by the ci.yml.


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

- 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
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.

We can ask the users of the python-toolbox what they'd prefer.

When I'd written that we perform a check by running poetry run -- nox -s dependency:audit, I had thought we could check to see if there are vulnerabilities detected or not. If there were vulnerabilities, then we'd proceed with updating the dependencies. Otherwise, we would skip the update.

One way to do this would be to check the length of the produced JSON;

# this will both print the results & output them to a json file
poetry run -- nox -s dependency:audit | tee vulnerabilities.json

LENGTH=$(jq 'length' vulnerabilities.json)
echo "count=$LENGTH" >> $GITHUB_OUTPUT

In the next step, where we run update-dependencies, we can add an if-statement

if: steps.audit-dependencies.outputs.count > 0


- name: Update Dependencies
id: update-dependencies
run: poetry update

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

- name: Create Pull Request
id: create-pull-request
if: steps.check-for-poetry-lock-changes.outputs.changed == 'true'
uses: peter-evans/create-pull-request@v7
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.

In general, we try not to use third-party GitHub actions. This is because they can pose a security risk. Currently, we still use the a few third-party actions, like ravsamhq/notify-slack-action, as there isn't a GitHub equivalent.

So for the "Create Pull Request", we'd prefer to use the GitHub provided commands, so this should look mostly the same as:
https://github.com/exasol/project-keeper/blob/main/.github/workflows/dependencies_update.yml#L120

Though, we do not need to have as many initial checks as is provided in:
https://github.com/exasol/project-keeper/blob/main/.github/workflows/dependencies_update.yml#L132

with:
commit-message: "Update poetry.lock"
branch: dependency-update/poetry-lock
delete-branch: true
title: "Update poetry.lock"
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`
25 changes: 17 additions & 8 deletions test/integration/tools/workflow_integration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def test_with_default(cli_runner):
"check-release-tag\n"
"checks\n"
"ci\n"
"dependency-update\n"
"gh-pages\n"
"matrix-all\n"
"matrix-exasol\n"
Expand All @@ -33,14 +34,20 @@ def test_with_columns(cli_runner):
result = cli_runner.invoke(CLI, ["list", "--columns"])

assert result.exit_code == 0
assert result.output == (
"build-and-publish cd check-release-tag checks ci "
"gh-pages\n"
"matrix-all matrix-exasol matrix-python merge-gate pr-merge "
"report \n"
"slow-checks \n"
)

assert "build-and-publish" in result.output
assert "cd" in result.output
assert "check-release-tag" in result.output
assert "checks" in result.output
assert "ci" in result.output
assert "dependency-update" in result.output
assert "gh-pages" in result.output
assert "matrix-all" in result.output
assert "matrix-exasol" in result.output
assert "matrix-python" in result.output
assert "merge-gate" in result.output
assert "pr-merge" in result.output
assert "report" in result.output
assert "slow-checks" in result.output

def test_show_workflow(cli_runner):
result = cli_runner.invoke(CLI, ["show", "checks"])
Expand All @@ -57,6 +64,7 @@ def test_show_workflow(cli_runner):
"check-release-tag",
"checks",
"ci",
"dependency-update",
"gh-pages",
"matrix-all",
"matrix-exasol",
Expand Down Expand Up @@ -92,6 +100,7 @@ def test_all_workflows(cli_runner, tmp_path):
"check-release-tag.yml",
"checks.yml",
"ci.yml",
"dependency-update.yml",
"gh-pages.yml",
"matrix-all.yml",
"matrix-exasol.yml",
Expand Down
Loading