diff --git a/.agents/skills/release/SKILL.md b/.agents/skills/release/SKILL.md new file mode 100644 index 0000000..0a6d254 --- /dev/null +++ b/.agents/skills/release/SKILL.md @@ -0,0 +1,51 @@ +--- +name: release +description: Release harbor-hypeman to PyPI and GitHub. Use when asked to publish, release, cut a version, bump the package version, or verify a harbor-hypeman release. +--- + +# Release harbor-hypeman + +Publish immutable releases from version tags on `main`. PyPI authentication uses the `pypi` GitHub environment and Trusted Publishing; never add an API token. + +## Prepare the version + +1. Fetch `origin` and require a clean working tree. +2. Read the version from `pyproject.toml` and the latest `v*` tag. +3. If the current version is already greater than the latest tag, use it. Otherwise create a `hypeship/release-vX.Y.Z` branch and update: + - `project.version` in `pyproject.toml` + - the matching package version in `uv.lock` by running `uv lock` + - `CHANGELOG.md`, moving relevant entries from `Unreleased` into a dated version section +4. Run: + + ```bash + uv sync --locked --dev + uv run ruff format --check . + uv run ruff check . + uv run ty check + uv run pytest + uv build + ``` + +5. Commit, push, and open a ready-for-review release PR. Wait for required CI, BugBot, and review before merging. + +## Publish + +1. Return to `main`, fast-forward to `origin/main`, and verify the release workflow and version bump are present. +2. Require the release commit to be exactly `origin/main` and confirm the tag does not already exist locally or remotely. +3. Create and push an annotated tag: + + ```bash + git tag -a "vX.Y.Z" -m "Release vX.Y.Z" + git push origin "vX.Y.Z" + ``` + +4. Watch the `Release` workflow until it succeeds. It verifies the tag and version, runs all checks, publishes with PyPI Trusted Publishing, and creates the GitHub release. +5. Verify both release surfaces: + + ```bash + gh release view "vX.Y.Z" + curl -fsSL https://pypi.org/pypi/harbor-hypeman/json | jq -e '.info.version == "X.Y.Z"' + uv run --isolated --with "harbor-hypeman==X.Y.Z" python -c 'import harbor_hypeman' + ``` + +Never reuse a version already published to PyPI. If publication succeeded but a later step failed, repair that step without moving or recreating the tag. diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..90d048b --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,59 @@ +name: Release + +on: + push: + tags: + - "v*" + +permissions: + contents: read + +concurrency: + group: release-${{ github.ref }} + +jobs: + release: + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/harbor-hypeman + permissions: + contents: write + id-token: write + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + fetch-depth: 0 + - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 + with: + version: "0.12.3" + enable-cache: true + - run: uv python install 3.12 + - name: Verify release tag + shell: bash + run: | + set -euo pipefail + [[ "$GITHUB_REF_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]] + version=$(uv run --no-project --python 3.12 python -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])') + test "$GITHUB_REF_NAME" = "v$version" + git fetch origin main + test "$GITHUB_SHA" = "$(git rev-parse origin/main)" + - run: uv sync --locked --dev + - run: uv run ruff format --check . + - run: uv run ruff check . + - run: uv run ty check + - run: uv run pytest + - run: uv build + - name: Publish to PyPI + run: >- + uv publish + --trusted-publishing always + --check-url https://pypi.org/simple/harbor-hypeman/ + - name: Create GitHub release + env: + GH_TOKEN: ${{ github.token }} + run: >- + gh release create "$GITHUB_REF_NAME" dist/* + --verify-tag + --generate-notes + --title "harbor-hypeman $GITHUB_REF_NAME" diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..53f59b7 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,17 @@ +# Changelog + +All notable changes to this project are documented in this file. + +## [Unreleased] + +## [0.1.0] - 2026-08-17 + +### Added + +- Hypeman environment backend for Harbor. +- Dockerfile builds and prebuilt container images. +- Instance lifecycle, command execution, and file transfer support. +- CPU, memory, storage, and network configuration. + +[Unreleased]: https://github.com/kernel/harbor-hypeman/compare/v0.1.0...HEAD +[0.1.0]: https://github.com/kernel/harbor-hypeman/releases/tag/v0.1.0 diff --git a/pyproject.toml b/pyproject.toml index 86702a3..947e17d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,10 @@ dependencies = [ "pathspec>=1.0.3", ] +[project.urls] +Repository = "https://github.com/kernel/harbor-hypeman" +Changelog = "https://github.com/kernel/harbor-hypeman/blob/main/CHANGELOG.md" + [dependency-groups] dev = [ "pytest>=8.4.2",