Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
af6707c
Add update-project-version action
bkeryan May 21, 2025
80b02bd
update-project-version: Get script working
bkeryan May 21, 2025
269318a
update-project-version: Add a link to the workflow log.
bkeryan May 21, 2025
11893af
update-project-version: Fix handling of Boolean inputs
bkeryan May 21, 2025
14d54c4
update-project-version: Remove newlines from changed-files
bkeryan May 21, 2025
6610715
update-project-version: Reformat changed-files as a Markdown list
bkeryan May 21, 2025
96e22e2
update-project-version: Fix quoting
bkeryan May 21, 2025
81b06dd
update-project-version: Fix quoting, take 2
bkeryan May 21, 2025
058d8a6
update-project-version: Fix log URL
bkeryan May 21, 2025
62f543d
update-project-version: Fix log URL, take 2
bkeryan May 21, 2025
c8fe412
update-project-version: Fix log URL, take 3
bkeryan May 21, 2025
e183aae
README.md: Update version tags to v0.2
bkeryan May 21, 2025
5dde9e3
Add check-project-version action
bkeryan May 22, 2025
79db987
check-project-version: Fix here-document indentation
bkeryan May 22, 2025
8f37dc5
check-project-version: Here-doc take 2
bkeryan May 22, 2025
66bf384
check-project-version: Remove the `exit 1` because I think it's getti…
bkeryan May 22, 2025
bf42b85
check-project-version: Here-doc take 4
bkeryan May 22, 2025
c0c221e
check-project-version: Add debug echos
bkeryan May 22, 2025
82a0c8d
check-project-version: Here-doc take 5
bkeryan May 22, 2025
c2bec95
check-project-version: Here-doc take 6
bkeryan May 22, 2025
c09765b
check-project-version: Remove debug notices and restore `exit 1`
bkeryan May 22, 2025
275868c
update-project-version: Try to make release events use the right bran…
bkeryan May 22, 2025
89453df
update-project-version: Specify the base branch for create-pull-request
bkeryan Jun 3, 2025
60e0436
update-project-version: Set commit message to the same thing as the P…
bkeryan Jun 4, 2025
b3e9a55
github: Add PR/CI workflows to test the actions
bkeryan Jun 4, 2025
c2e7472
check-project-version: Use the project-directory input
bkeryan Jun 4, 2025
66638c7
github: Use outcome, not conclusion, to check whether a continue-on-e…
bkeryan Jun 4, 2025
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
178 changes: 169 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,34 @@

`ni/python-actions` is a Git repository containing reusable GitHub Actions for NI Python projects.

## Table of Contents

- [`ni/python-actions`](#nipython-actions)
- [Table of Contents](#table-of-contents)
- [`ni/python-actions/setup-python`](#nipython-actionssetup-python)
- [Usage](#usage)
- [Inputs](#inputs)
- [`python-version`](#python-version)
- [Outputs](#outputs)
- [`python-version`](#python-version-1)
- [`python-path`](#python-path)
- [`ni/python-actions/setup-poetry`](#nipython-actionssetup-poetry)
- [Usage](#usage-1)
- [Inputs](#inputs-1)
- [`poetry-version`](#poetry-version)
- [`ni/python-actions/check-project-version`](#nipython-actionscheck-project-version)
- [Usage](#usage-2)
- [Inputs](#inputs-2)
- [`project-directory`](#project-directory)
- [`expected-version`](#expected-version)
- [`ni/python-actions/update-project-version`](#nipython-actionsupdate-project-version)
- [Usage](#usage-3)
- [Inputs](#inputs-3)
- [`project-directory`](#project-directory-1)
- [`branch-prefix`](#branch-prefix)
- [`create-pull-request`](#create-pull-request)
- [`version-rule` and `use-dev-suffix`](#version-rule-and-use-dev-suffix)

## `ni/python-actions/setup-python`

The `setup-python` action installs Python and adds it to the PATH.
Expand All @@ -15,20 +43,21 @@ By default, this action installs Python 3.11.9.

```yaml
steps:
- uses: ni/python-actions/setup-python@v0.1.0
- uses: ni/python-actions/setup-python@v0.2
```

### Inputs

#### `python-version`

You can specify the `python-version` input for testing with multiple versions of Python:

```yaml
strategy:
matrix:
python-version: [3.9, '3.10', 3.11, 3.12, 3.13]
steps:
- uses: ni/python-actions/setup-python@v0.1.0
- uses: ni/python-actions/setup-python@v0.2
with:
python-version: ${{ matrix.python-version }}
```
Expand All @@ -38,9 +67,10 @@ steps:
#### `python-version`

You can use the `python-version` output to get the actual version of Python, which is useful for caching:

```yaml
steps:
- uses: ni/python-actions/setup-python@v0.1.0
- uses: ni/python-actions/setup-python@v0.2
id: setup-python
- uses: actions/cache@v4
with:
Expand All @@ -54,9 +84,10 @@ steps:
containing the Python installation.

You can also use the `python-path` output to get the path to the Python interpreter:

```yaml
steps:
- uses: ni/python-actions/setup-python@v0.1.0
- uses: ni/python-actions/setup-python@v0.2
id: setup-python
- run: pipx install <package> --python ${{ steps.setup-python.outputs.python-version }}
```
Expand All @@ -75,8 +106,8 @@ By default, this action installs Poetry 1.8.2.

```yaml
steps:
- uses: ni/python-actions/setup-python@v0.1.0
- uses: ni/python-actions/setup-poetry@v0.1.0
- uses: ni/python-actions/setup-python@v0.2
- uses: ni/python-actions/setup-poetry@v0.2
- run: poetry install -v
```

Expand All @@ -86,9 +117,138 @@ steps:

```yaml
steps:
- uses: ni/python-actions/setup-python@v0.1.0
- uses: ni/python-actions/setup-poetry@v0.1.0
- uses: ni/python-actions/setup-python@v0.2
- uses: ni/python-actions/setup-poetry@v0.2
with:
poetry-version: 2.1.3
- run: poetry install -v
```
```

## `ni/python-actions/check-project-version`

The `check-project-version` action uses Poetry to get the version of a Python project and checks
that it matches an expected version. By default, this action checks against `github.ref_name`, which
is the GitHub release tag for GitHub release events.

This action requires Poetry, so you must call `setup-python` and `setup-poetry` first.

### Usage

```yaml
steps:
- uses: ni/python-actions/[email protected]
- uses: ni/python-actions/[email protected]
- uses: ni/python-actions/[email protected]
if: github.event_name == 'release'
```

### Inputs

#### `project-directory`

You can specify `project-directory` to check a project located in a subdirectory.

```yaml
- uses: ni/python-actions/[email protected]
with:
project-directory: packages/foo
```

#### `expected-version`

You can specify `expected-version` to check against something other than `github.ref_name`.

```yaml
- uses: ni/python-actions/[email protected]
with:
expected-version: ${{ steps.get-expected-version.outputs.version }}
```

## `ni/python-actions/update-project-version`

The `update-project-version` action uses Poetry to update the version of a Python project and
creates a pull request to modify its `pyproject.toml` file.

This action requires Poetry, so you must call `setup-python` and `setup-poetry` first.

Creating a pull request requires the workflow or job to have the following `GITHUB_TOKEN`
permissions:

```yaml
permissions:
contents: write
pull-requests: write
````

### Usage

```yaml
steps:
- uses: ni/python-actions/[email protected]
- uses: ni/python-actions/[email protected]
- uses: ni/python-actions/[email protected]
```

### Inputs

#### `project-directory`

You can specify `project-directory` to update a project located in a subdirectory.

```yaml
- uses: ni/python-actions/[email protected]
with:
project-directory: packages/foo
```

#### `branch-prefix`

You can specify `branch-prefix` to customize the pull request branch names. The default value of
`users/build/` generates pull requests with names like `users/build/update-project-version-main` and
`users/build/update-project-version-releases-1.1`.

```yaml
- uses: ni/python-actions/[email protected]
with:
branch-prefix: users/python-build/
```

#### `create-pull-request`

You can use `create-pull-request` and `project-directory` to update multiple projects with a single
pull request.

```yaml
- uses: ni/python-actions/[email protected]
with:
project-directory: packages/foo
create-pull-request: false
- uses: ni/python-actions/[email protected]
with:
project-directory: packages/bar
create-pull-request: false
- uses: ni/python-actions/[email protected]
with:
project-directory: packages/baz
create-pull-request: true
```

#### `version-rule` and `use-dev-suffix`

You can specify `version-rule` and `use-dev-suffix` to customize the versioning scheme.

- `version-rule` specifies the rule for updating the version number. For example, `major` will
update 1.0.0 -> 2.0.0, while `patch` will update 1.0.0 -> 1.0.1. See [the docs for `poetry
version`](https://python-poetry.org/docs/cli/#version) for the list of rules and their behavior.
- `use-dev-suffix` specifies whether to use development versions like `1.0.0.dev0`.

The defaults are `version-rule=patch` and `use-dev-suffix=true`, which have the following behavior:

| Old Version | New Version |
| ----------- | ----------- |
| 1.0.0 | 1.0.1.dev0 |
| 1.0.1.dev0 | 1.0.1.dev1 |
| 1.0.1.dev1 | 1.0.1.dev2 |

When you are ready to exit the "dev" phase, you should manually update the version number to the
desired release version before creating a release in GitHub.
44 changes: 44 additions & 0 deletions check-project-version/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Check project version
description: Check the version of a Python project against an expected version, such as a release tag.
inputs:
project-directory:
description: Path to the directory containing pyproject.toml.
default: ${{ github.workspace }}
expected-version:
description: >
The expected version. By default, this is `github.ref_name`, which is the
tag for a `release` event. If the version has a leading 'v', it will be
stripped.
default: ${{ github.ref_name }}
runs:
using: composite
steps:
- name: Check project version
run: |
project_version="$(poetry version --short)"
expected_version="${{ inputs.expected-version }}"
# Strip the leading 'v', in case this is a GitHub release tag.
expected_version="${expected_version#v}"

error_message="$(cat <<EOF
The project version in pyproject.toml does not match the expected version.

If this workflow was triggered by a GitHub release, verify that the
release was tagged with the correct version. If they don't match, you
should either update pyproject.toml or delete and re-create the release
with the correct tag.

Project version: $project_version
Expected version: $expected_version
EOF
)"

# Convert newline to %0A so that GitHub includes the entire error message
# in the annotation.
error_message="$(echo "$error_message" | sed -z 's/\n/%0A/g;s/%0A$/\n/')"

if [ x"$project_version" != x"$expected_version" ]; then
echo "::error title=Project Version Error::$error_message"
exit 1
fi
shell: bash
62 changes: 62 additions & 0 deletions update-project-version/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Update project version
description: Update the version of a Python project and create a pull request.
inputs:
project-directory:
description: Path to the directory containing pyproject.toml.
default: ${{ github.workspace }}
branch-prefix:
description: The branch prefix to use when creating pull requests.
default: users/build/
create-pull-request:
description: >
Specifies whether to create a pull request. Set this to false to update
the project version without creating a pull request.
default: true
version-rule:
description: >
Specifies the rule for how to update the version number, such as "major",
"minor", or "patch". See https://python-poetry.org/docs/cli/#version for
the list of rules and their behavior.
default: patch
use-dev-suffix:
description: Specifies whether to use development versions like "1.0.0.dev0".
default: true
runs:
using: composite
steps:
- name: Set variables
id: set-vars
run: |
base_branch=$(git symbolic-ref --short HEAD)
base_branch_no_slashes=$(echo $base_branch | tr '/' '-')
echo "base-branch=$base_branch" >> "$GITHUB_OUTPUT"
echo "branch-name=${{ inputs.branch-prefix }}update-project-version-$base_branch_no_slashes" >> "$GITHUB_OUTPUT"
shell: bash
- name: Update the version in pyproject.toml
run: python ${{ github.action_path }}/update_version.py ${{ inputs.version-rule }} ${{ inputs.use-dev-suffix == 'true' && '--dev' || '' }}
shell: bash
working-directory: ${{ inputs.project-directory }}
- name: Get changed files
id: get-changed-files
run: |
echo "changed-files<<EOF" >> "$GITHUB_OUTPUT"
# Prefix with "- " to generate a Markdown list.
git diff --name-only | awk '{ print "-", $0 }' >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
shell: bash
- name: Create pull request
if: inputs.create-pull-request == 'true'
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
with:
branch: ${{ steps.set-vars.outputs.branch-name }}
title: "chore: Update project version - ${{ steps.set-vars.outputs.base-branch }}"
# The workflow log currently points to the run, not the specific job
# within that run. Linking to a specific job requires the numeric job id,
# which is not available in the github context.
# https://stackoverflow.com/questions/71240338/obtain-job-id-from-a-workflow-run-using-contexts
body: |
This PR updates the versions of the following Python projects:

${{ steps.get-changed-files.outputs.changed-files }}

This PR was generated by [ni/python-actions/update-project-version](https://github.com/ni/python-actions/). View the [workflow log](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}).
Loading