From ba91b8e8f2b1d41261d9d24a63c8a57f7fcb196a Mon Sep 17 00:00:00 2001 From: Dag Brattli Date: Thu, 16 Apr 2026 02:14:33 +0200 Subject: [PATCH] ci: adopt EasyBuild.ShipIt for release automation Move release management to ShipIt with a single root CHANGELOG, matching the setup used in Fable.Actor and Fable.Beam. ShipIt opens a release PR on pushes to main and the publish workflow packs and pushes to NuGet when that PR is merged. Co-Authored-By: Claude Opus 4.6 (1M context) --- .config/dotnet-tools.json | 7 ++++ .github/workflows/publish.yml | 56 ++++++++++++++++++++++-------- CHANGELOG.md | 7 ++++ RELEASING.md | 65 +++++++++++++++++++++-------------- justfile | 17 +++++++-- 5 files changed, 109 insertions(+), 43 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index f613ab2..a6440fc 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -22,6 +22,13 @@ "fantomas" ], "rollForward": false + }, + "easybuild.shipit": { + "version": "2.0.0", + "commands": [ + "shipit" + ], + "rollForward": false } } } \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index aec29cc..7adc771 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,19 +1,49 @@ +name: Publish NuGet + on: - release: - types: [published] + push: + branches: [main] permissions: - contents: read - -name: Publish NuGet + contents: write + pull-requests: write jobs: - publish: + shipit-pr: + name: ShipIt - Pull Request + runs-on: ubuntu-latest + if: "!startsWith(github.event.head_commit.message, 'chore: release ')" + timeout-minutes: 10 + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v5 + with: + dotnet-version: | + 8.x + 9.x + 10.x + + - name: Install tools + run: dotnet tool restore + + - name: ShipIt (Pull Request) + run: dotnet shipit --pre-release rc + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + release: + name: Release runs-on: ubuntu-latest timeout-minutes: 10 + if: "startsWith(github.event.head_commit.message, 'chore: release ')" steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Setup .NET Core uses: actions/setup-dotnet@v5 @@ -26,16 +56,12 @@ jobs: - name: Install just uses: extractions/setup-just@v3 - - name: Restore dependencies + - name: Install tools run: | dotnet tool restore dotnet restore src - - name: Pack NuGet + - name: Build, pack and push + run: just release env: - TAG_NAME: ${{ github.event.release.tag_name }} - run: just pack-version ${TAG_NAME#v} - - - name: Push NuGet - run: dotnet nuget push src/bin/Release/*.nupkg -s https://api.nuget.org/v3/index.json -k ${{ secrets.NUGET_API_KEY }} - continue-on-error: false + NUGET_KEY: ${{ secrets.NUGET_API_KEY }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 974ef08..4dc8345 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ +--- +last_commit_released: 8223cc8eb8b2dcaa02c1a19566c5ed5d73242b11 +name: Fable.Python +--- + # Changelog +All notable changes to this project will be documented in this file. + ## [5.0.0-alpha.21.5](https://github.com/fable-compiler/Fable.Python/compare/v5.0.0-alpha.21.4...v5.0.0-alpha.21.5) (2025-12-21) ### Bug Fixes diff --git a/RELEASING.md b/RELEASING.md index 528c0bd..1164f26 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,37 +1,52 @@ -# Releasing Fable.Python +# Releasing -## Version Format +This project uses [EasyBuild.ShipIt](https://github.com/easybuild-org/EasyBuild.ShipIt) +for release automation and [Conventional Commits](https://www.conventionalcommits.org/) +for versioning. -Fable.Python uses the version format `X.Y.Z-alpha.N.P` where: +## Commit conventions -- `X.Y.Z-alpha.N` matches the Fable version (e.g., `5.0.0-alpha.22`) -- `P` is the patch version for Fable.Python releases (0, 1, 2, etc.) +PR titles must follow the conventional commit format (enforced by CI): -Example: `5.0.0-alpha.22.0`, `5.0.0-alpha.22.1`, `5.0.0-alpha.22.2` +| Prefix | Version bump | Example | +| --- | --- | --- | +| `feat:` | minor | `feat: add Pydantic field validators` | +| `fix:` | patch | `fix: correct FastAPI response type` | +| `feat!:` | major | `feat!: rename Flask decorator` | +| `chore:` | patch | `chore: update dependencies` | +| `docs:` | patch | `docs: update README` | +| `refactor:` | patch | `refactor: simplify JSON bindings` | -## Release Process +Other valid prefixes: `test`, `perf`, `ci`, `build`, `style`, `revert`. -1. Go to [GitHub Releases](https://github.com/fable-compiler/Fable.Python/releases) -2. Click **"Draft a new release"** -3. Create a new tag in the format `v5.0.0-alpha.22.0` (with `v` prefix) -4. Set the release title (e.g., `5.0.0-alpha.22.0`) -5. Write release notes (or use "Generate release notes") -6. For pre-release versions, check **"Set as a pre-release"** -7. Click **"Publish release"** +## Creating a release -The publish workflow will automatically build and push the NuGet package. +Releases are driven automatically by the `Publish NuGet` workflow on pushes to +`main`. ShipIt opens a `chore: release ...` PR that bumps the version in +`CHANGELOG.md`; merging that PR triggers the publish job, which packs and pushes +the NuGet package. -## Syncing with a New Fable Version +To run ShipIt locally (for example to preview the next version or cut a release +manually): -When Fable releases a new version (e.g., `5.0.0-alpha.23`): +```bash +just shipit +``` -1. Update the codebase to work with the new Fable version -2. Create a release with tag `v5.0.0-alpha.23.0` +This will: -## Version History Example +1. Analyze commits since the last release +2. Determine the next semantic version +3. Update `CHANGELOG.md` +4. Create a GitHub release with the version tag (e.g. `v5.0.0-rc.3`) -- `5.0.0-alpha.21.0` (initial sync with Fable 5.0.0-alpha.21) -- `5.0.0-alpha.21.1` (first patch) -- `5.0.0-alpha.21.2` (second patch) -- `5.0.0-alpha.22.0` (sync with Fable 5.0.0-alpha.22) -- `5.0.0-alpha.22.1` (first patch for alpha.22) +Merging a ShipIt release PR (or publishing a release tag) triggers the workflow +to: + +1. Pack the NuGet package (`Fable.Python`) using the version from `CHANGELOG.md` +2. Push it to nuget.org using the `NUGET_API_KEY` secret + +## Prerequisites + +- `NUGET_API_KEY` repository secret (glob pattern: `Fable.Python*`) +- `GITHUB_TOKEN` or `gh` CLI authenticated (for ShipIt to create releases) diff --git a/justfile b/justfile index c99c7a4..de53b89 100644 --- a/justfile +++ b/justfile @@ -61,15 +61,26 @@ test-python: build {{fable}} {{test_path}} --lang Python --outDir {{build_path}}/tests uv run pytest {{build_path}}/tests -# Create NuGet package -pack: build - dotnet pack {{src_path}} -c Release +# Create NuGet package with version from CHANGELOG.md +pack: + #!/usr/bin/env bash + set -euo pipefail + VERSION=$(grep -m1 '^## ' CHANGELOG.md | sed 's/^## \[\?\([^] ]*\).*/\1/') + dotnet pack {{src_path}} -c Release -p:PackageVersion=$VERSION -p:InformationalVersion=$VERSION # Create NuGet package with specific version (used in CI) # Note: FileVersion must be numeric-only (e.g., 5.0.0.0), so we don't set it for prerelease versions pack-version version: dotnet pack {{src_path}} -c Release -p:PackageVersion={{version}} -p:InformationalVersion={{version}} +# Release: pack and push to NuGet (used in CI) +release: pack + dotnet nuget push '{{src_path}}/bin/Release/*.nupkg' -s https://api.nuget.org/v3/index.json -k $NUGET_KEY + +# Run EasyBuild.ShipIt for release management +shipit *args: + dotnet shipit --pre-release rc {{args}} + # Format code with Fantomas format: dotnet fantomas {{src_path}} -r