From 298916bcb996bb1a54ae19166117b0b04dd86e47 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 3 Nov 2026 18:29:45 +0000 Subject: [PATCH 1/2] Tag, release and publish from CI when the version changes After the test matrix, a release job on pushes to the default branch reads $VERSION from lib/Net/IPData.pm and, when the tag vX.Y.Z does not exist yet, creates the tag and the GitHub release with generated notes. A tag created with the workflow's own token starts no other workflow run, so the CPAN upload runs in the same run: release.yml is now also callable (workflow_call with a tag input; the release trigger stays) and ci.yml calls it with inherited secrets. A merge whose version is already tagged publishes nothing. Co-Authored-By: Claude Fable 5.1 --- .github/workflows/ci.yml | 67 +++++++++++++++++++++++++++++++++++ .github/workflows/release.yml | 9 +++++ 2 files changed, 76 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e34e6f7..3183ba1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,3 +28,70 @@ jobs: - name: Test run: make test + + # After a merge to the default branch, tag the version declared in + # lib/Net/IPData.pm and create its GitHub release, unless that tag exists. + release: + needs: test + if: github.event_name == 'push' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch) + runs-on: ubuntu-latest + permissions: + contents: write + concurrency: + group: release + cancel-in-progress: false + outputs: + tag: ${{ steps.version.outputs.tag }} + created: ${{ steps.release.outputs.created }} + steps: + - uses: actions/checkout@v5 + + - name: Read the module version + id: version + run: | + VERSION=$(sed -nE "s/.*VERSION *= *['\"]([^'\"]+)['\"].*/\1/p" lib/Net/IPData.pm | head -1) + if [ -z "$VERSION" ]; then + echo "::error::no \$VERSION found in lib/Net/IPData.pm" + exit 1 + fi + echo "Module version $VERSION, tag v$VERSION" + echo "tag=v$VERSION" >> "$GITHUB_OUTPUT" + + - name: Create the tag and the GitHub release + id: release + env: + GH_TOKEN: ${{ github.token }} + TAG: ${{ steps.version.outputs.tag }} + run: | + set +e + git ls-remote --exit-code --tags origin "refs/tags/$TAG" > /dev/null + status=$? + set -e + case $status in + 0) + echo "Tag $TAG already exists; nothing to release" + echo "created=false" >> "$GITHUB_OUTPUT" + ;; + 2) + gh release create "$TAG" --target "$GITHUB_SHA" --title "$TAG" --generate-notes + echo "Created tag and release $TAG" + echo "created=true" >> "$GITHUB_OUTPUT" + ;; + *) + echo "::error::git ls-remote failed with status $status" + exit "$status" + ;; + esac + + # A tag created with the workflow's own token starts no other workflow run, + # so the CPAN upload happens here, in the same run, through the callable + # release workflow. + publish: + needs: release + if: needs.release.outputs.created == 'true' + permissions: + contents: read + uses: ./.github/workflows/release.yml + with: + tag: ${{ needs.release.outputs.tag }} + secrets: inherit diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 54079c2..2a5cbe4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,12 +3,21 @@ name: Release to CPAN on: release: types: [published] + workflow_call: + inputs: + tag: + description: Tag of the release to upload (for example v1.2.0) + required: true + type: string jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 + with: + # the tag passed by the calling workflow, or the published release's tag + ref: ${{ inputs.tag || github.event.release.tag_name }} - uses: shogo82148/actions-setup-perl@v1 with: From 8b280c6ca41d925ace751cec261e59b018848ab5 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 3 Nov 2026 18:29:45 +0000 Subject: [PATCH 2/2] Document the CI release process Add a Releasing section to the README and a Changes entry: bump $VERSION and date the Changes entry in a pull request, merge, and CI tags, releases and uploads to CPAN. Co-Authored-By: Claude Fable 5.1 --- Changes | 5 +++++ README.md | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/Changes b/Changes index c2ba90b..a79c742 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,10 @@ Revision history for Net-IPData +Unreleased + - Releases are made by CI: merging a pull request that bumps $VERSION + tags vX.Y.Z, creates the GitHub release and uploads the distribution + to CPAN; a merge whose version is already tagged publishes nothing + 1.1.0 2026-11-03 - The API server's TLS certificate is now verified with every HTTP::Tiny version: verify_SSL => 1 is passed explicitly (HTTP::Tiny before 0.083 diff --git a/README.md b/README.md index 763fb4f..185b396 100644 --- a/README.md +++ b/README.md @@ -312,6 +312,15 @@ Run the full suite including live API tests: IPDATA_API_KEY=your_key_here make test ``` +## Releasing + +Releases are made by CI; nothing is tagged by hand. To publish a new version: + +1. In a pull request, bump `$VERSION` in `lib/Net/IPData.pm` and give the `Unreleased` entry in `Changes` its version number and date. +2. Merge it. CI tags the merge commit `vX.Y.Z`, creates the GitHub release with generated notes and uploads the distribution to CPAN. + +A merge whose version is already tagged publishes nothing. The release trigger is kept, so publishing a GitHub release by hand still uploads its tag to CPAN. + ## License This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.