Skip to content
Merged
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
75 changes: 75 additions & 0 deletions .github/workflows/release-splunk-ao.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: Release splunk-ao to PyPI

on:
workflow_dispatch:
inputs:
version:
description: 'Version to release (e.g., 0.1.0, 1.2.3, 1.2.3rc1, 1.2.3.post1). Must be an explicit version — bump keywords like "patch" or "minor" are not accepted.'
required: true
type: string

jobs:
build:
name: Build package
runs-on: ubuntu-latest
Comment on lines +12 to +14

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.

🟡 minor (security): The build job declares no permissions: block, so it inherits the repository's default GITHUB_TOKEN scope (often read/write). The publish job correctly scopes itself to id-token: write only. Given this PR's explicit supply-chain hardening focus (SHA pinning, OIDC publish), apply least privilege to the build job too — it only needs to read the checked-out repo. Consider adding permissions: contents: read to the build job (or a top-level workflow default).

Suggested change
build:
name: Build package
runs-on: ubuntu-latest
build:
name: Build package
runs-on: ubuntu-latest
permissions:
contents: read

🤖 Generated by Astra

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good point — added permissions: contents: read to the build job so it explicitly opts in to the minimum scope it needs rather than inheriting the repo-wide default. Applied the same to the test and build jobs across all five release workflows for consistency.

permissions:
contents: read
outputs:
version: ${{ steps.get-version.outputs.version }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: '3.11'

- name: Install Poetry
run: pipx install poetry==2.4.1

- name: Set version
env:
INPUT_VERSION: ${{ inputs.version }}
run: |
if ! printf '%s' "$INPUT_VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+((a|b|rc)[0-9]+)?(\.post[0-9]+)?(\.dev[0-9]+)?$'; then
echo "::error::Invalid version '${INPUT_VERSION}'. Expected an explicit version like 0.1.0, 1.2.3rc1, or 1.2.3.post1. Bump keywords like 'patch' or 'major' are not accepted."
exit 1
fi
sed -i "s/^version = \".*\"/version = \"${INPUT_VERSION}\"/" pyproject.toml
sed -i "s/__version__ = \".*\"/__version__ = \"${INPUT_VERSION}\"/" src/splunk_ao/__init__.py

- name: Get current version
id: get-version
run: echo "version=$(poetry version --short)" >> "$GITHUB_OUTPUT"

- name: Build package
Comment on lines +33 to +45

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.

🟡 minor (bug): poetry version "$INPUT_VERSION" interprets bump keywords (major, minor, patch, premajor, etc.) as bump rules rather than literal versions, whereas the sed line always writes the literal input string. If a maintainer enters patch, poetry bumps 0.1.0 -> 0.1.1 in pyproject.toml while __init__.py gets __version__ = "patch" — the built artifact then ships mismatched versions. The input is also otherwise unvalidated, so a typo like 1.0 or a value containing //" silently produces a bad build or breaks the sed expression. Validate the input against a version pattern up front so both files stay in sync.

Suggested change
run: |
poetry version "$INPUT_VERSION"
sed -i "s/__version__ = \".*\"/__version__ = \"${INPUT_VERSION}\"/" src/splunk_ao/__init__.py
- name: Get current version
id: get-version
run: echo "version=$(poetry version --short)" >> "$GITHUB_OUTPUT"
- name: Build package
- name: Set version
env:
INPUT_VERSION: ${{ inputs.version }}
run: |
if ! printf '%s' "$INPUT_VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+([abprc.][0-9]+)*$'; then
echo "::error::Invalid version '$INPUT_VERSION'; expected an explicit version like 0.1.0"
exit 1
fi
poetry version "$INPUT_VERSION"
sed -i "s/__version__ = \".*\"/__version__ = \"${INPUT_VERSION}\"/" src/splunk_ao/__init__.py

🤖 Generated by Astra

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch — both issues are now addressed in the latest commit:

  1. Version format validation: Added an upfront grep -Eq check that rejects anything that is not an explicit PEP 440 version number (e.g. 0.1.0, 1.2.3b1). Bump keywords like patch, major, or minor will now fail fast with a clear ::error:: message before touching any files.

  2. pyproject.toml update via sed: Switched from poetry version "$INPUT_VERSION" to sed for the pyproject.toml bump. This makes both file updates symmetric and removes the ambiguity between Poetry bump-rule keywords and literal version strings entirely, matching the approach used in the splunk-ao-adk and splunk-ao-a2a workflows.

run: poetry build

- name: Upload distributables
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: splunk-ao-${{ steps.get-version.outputs.version }}
path: dist/

publish:
name: Publish to PyPI
needs: build
runs-on: ubuntu-latest
permissions:
id-token: write # Required for OIDC trusted publishing
environment:
name: pypi
url: https://pypi.org/project/splunk-ao/

steps:
- name: Download distributables
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: splunk-ao-${{ needs.build.outputs.version }}
path: dist/

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1
with:
verbose: true
print-hash: true
Loading