Skip to content
Merged
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
64 changes: 46 additions & 18 deletions .github/workflows/python-nightly.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
name: python-nightly
name: python-publish

on:
schedule:
- cron: '17 8 * * *'
workflow_dispatch:
inputs:
channel:
description: Package channel to publish
required: true
default: nightly
type: choice
options:
- nightly
- stable

concurrency:
group: python-nightly-0.2.1
group: python-publish-${{ inputs.channel || 'nightly' }}
cancel-in-progress: false

permissions:
contents: read

env:
RELEASE_VERSION: 0.2.1
NIGHTLY_VERSION: 0.3.0

jobs:
build:
Expand All @@ -30,24 +39,43 @@ jobs:
with:
python-version: '3.12'

- name: Set the nightly version
- name: Select the publication version
id: version
env:
DISPATCH_CHANNEL: ${{ inputs.channel }}
run: |
commit="$(git rev-parse --short=12 HEAD)"
date_utc="$(date -u +%Y%m%d)"
version="$(python .github/scripts/nightly_version.py \
--release-version "$RELEASE_VERSION" \
--date "$date_utc" \
--run-number "$GITHUB_RUN_NUMBER")"
source_version="$(python -c 'import cmax; print(cmax.__version__)')"
channel="${DISPATCH_CHANNEL:-nightly}"
case "$channel" in
stable)
version="$source_version"
;;
nightly)
date_utc="$(date -u +%Y%m%d)"
version="$(python .github/scripts/nightly_version.py \
--release-version "$NIGHTLY_VERSION" \
--date "$date_utc" \
--run-number "$GITHUB_RUN_NUMBER")"
;;
*)
echo "Unknown publication channel: $channel" >&2
exit 1
;;
esac
echo "channel=$channel" >> "$GITHUB_OUTPUT"
echo "commit=$commit" >> "$GITHUB_OUTPUT"
echo "source_version=$source_version" >> "$GITHUB_OUTPUT"
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "### ClusterMAX nightly" >> "$GITHUB_STEP_SUMMARY"
echo "### ClusterMAX publication" >> "$GITHUB_STEP_SUMMARY"
echo "- Channel: \`$channel\`" >> "$GITHUB_STEP_SUMMARY"
echo "- Version: \`$version\`" >> "$GITHUB_STEP_SUMMARY"
echo "- Commit: \`$commit\`" >> "$GITHUB_STEP_SUMMARY"

- name: Build the nightly distributions
- name: Build the distributions
env:
CLUSTERMAX_BUILD_VERSION: ${{ steps.version.outputs.version }}
SOURCE_VERSION: ${{ steps.version.outputs.source_version }}
run: |
python -m pip install \
--require-hashes \
Expand All @@ -57,18 +85,18 @@ jobs:
python -m build --no-isolation
python -m twine check dist/*
check-wheel-contents dist/clustermax-*.whl
test "$(python -c 'import cmax; print(cmax.__version__)')" = "0.2.1"
test "$(python -c 'import cmax; print(cmax.__version__)')" = "$SOURCE_VERSION"

- name: Verify the nightly wheel
- name: Verify the wheel
env:
EXPECTED_VERSION: ${{ steps.version.outputs.version }}
run: |
python -m venv /tmp/clustermax-nightly
/tmp/clustermax-nightly/bin/pip install dist/clustermax-*.whl
python -m venv /tmp/clustermax-publication
/tmp/clustermax-publication/bin/pip install dist/clustermax-*.whl
cd /tmp
test "$(/tmp/clustermax-nightly/bin/cmax --version)" = "cmax ${EXPECTED_VERSION}"
/tmp/clustermax-nightly/bin/cmax audit --show
/tmp/clustermax-nightly/bin/cmax audit security --show
test "$(/tmp/clustermax-publication/bin/cmax --version)" = "cmax ${EXPECTED_VERSION}"
/tmp/clustermax-publication/bin/cmax audit --show
/tmp/clustermax-publication/bin/cmax audit security --show

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ cmax audit -h
cmax audit security -h
```

Nightly releases use the `0.2.1.devYYYYMMDDNN` format until the next major release, 3.0.
Nightly releases use the `0.3.0.devYYYYMMDDNN` format until the stable 0.3.0
release. This version is newer than stable 0.2.1 when `--pre` is enabled.

## Public documentation

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
from pathlib import Path
import unittest

from packaging.version import Version

SCRIPT_PATH = Path(__file__).parents[2] / ".github" / "scripts" / "nightly_version.py"

SCRIPT_PATH = Path(__file__).parents[1] / ".github" / "scripts" / "nightly_version.py"
SPEC = importlib.util.spec_from_file_location("nightly_version", SCRIPT_PATH)
assert SPEC is not None
assert SPEC.loader is not None
Expand All @@ -14,27 +16,32 @@
class NightlyVersionTests(unittest.TestCase):
def test_formats_the_first_daily_sequence_with_two_digits(self) -> None:
self.assertEqual(
NIGHTLY_VERSION.nightly_version("0.2.1", "20260826", 1),
"0.2.1.dev2026082601",
NIGHTLY_VERSION.nightly_version("0.3.0", "20260826", 1),
"0.3.0.dev2026082601",
)

def test_keeps_a_run_number_longer_than_two_digits(self) -> None:
self.assertEqual(
NIGHTLY_VERSION.nightly_version("0.2.1", "20260826", 123),
"0.2.1.dev20260826123",
NIGHTLY_VERSION.nightly_version("0.3.0", "20260826", 123),
"0.3.0.dev20260826123",
)

def test_next_release_nightly_is_newer_than_current_stable(self) -> None:
nightly = NIGHTLY_VERSION.nightly_version("0.3.0", "20260826", 1)

self.assertGreater(Version(nightly), Version("0.2.1"))

def test_rejects_an_invalid_release_version(self) -> None:
with self.assertRaisesRegex(ValueError, "X.Y.Z"):
NIGHTLY_VERSION.nightly_version("0.2", "20260826", 1)

def test_rejects_an_invalid_calendar_date(self) -> None:
with self.assertRaisesRegex(ValueError, "valid UTC calendar date"):
NIGHTLY_VERSION.nightly_version("0.2.1", "20260230", 1)
NIGHTLY_VERSION.nightly_version("0.3.0", "20260230", 1)

def test_rejects_a_nonpositive_run_number(self) -> None:
with self.assertRaisesRegex(ValueError, "positive integer"):
NIGHTLY_VERSION.nightly_version("0.2.1", "20260826", 0)
NIGHTLY_VERSION.nightly_version("0.3.0", "20260826", 0)


if __name__ == "__main__":
Expand Down