From 00d7246e6ff299826c8d69b8d399146039c3da64 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 3 Nov 2026 18:27:10 +0000 Subject: [PATCH 1/2] Release automatically when the version changes Add a release job to the CI workflow that runs after the tests on every push to the default branch. It reads vsn from src/ipdata.app.src and, when the tag vX.Y.Z does not exist yet, creates the tag and the GitHub release with gh release create. The publish job now also runs when that job created a tag, in the same workflow run, because a tag created with the workflow's own token does not start another run. A tag pushed by hand still publishes as before. Co-Authored-By: Claude Fable 5.1 --- .github/workflows/publish.yml | 63 +++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ad38095..bbe1054 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -68,10 +68,69 @@ jobs: - name: Run xref run: rebar3 xref + release: + name: Tag and release + needs: test + # Only a push to the default branch can create a release: pull requests + # and tag pushes skip this job. + 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@v7 + + - name: Read the version + id: version + run: | + version="$(sed -nE 's/.*\{vsn, *"([^"]+)".*/\1/p' src/ipdata.app.src | head -1)" + if [ -z "$version" ]; then + echo "::error file=src/ipdata.app.src::no vsn found" + exit 1 + fi + 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: | + # git ls-remote --exit-code exits with 2 when the tag does not exist. + status=0 + git ls-remote --exit-code --tags origin "refs/tags/$TAG" >/dev/null || status=$? + case "$status" in + 0) + echo "Tag $TAG already exists; nothing to release." + echo "created=false" >> "$GITHUB_OUTPUT" + exit 0 + ;; + 2) + ;; + *) + echo "::error::git ls-remote failed with status $status" + exit "$status" + ;; + esac + gh release create "$TAG" --target "$GITHUB_SHA" --title "$TAG" --generate-notes + echo "created=true" >> "$GITHUB_OUTPUT" + publish: name: Publish to Hex.pm - needs: test - if: startsWith(github.ref, 'refs/tags/v') + needs: [test, release] + # A tag created by the release job with the workflow's own token does not + # start another run, so the package is published here, in the same run. + # A tag pushed by hand is published too; the release job is skipped then, + # which is why the condition does not rely on the implicit success(). + if: >- + ${{ !cancelled() && needs.test.result == 'success' && + (needs.release.outputs.created == 'true' || startsWith(github.ref, 'refs/tags/v')) }} runs-on: ubuntu-latest permissions: contents: read From 62037aa3473737dfdb9e452f3406e5597a07a581 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 3 Nov 2026 18:27:10 +0000 Subject: [PATCH 2/2] Document the release process in the README Add a Releasing section after Testing: bump vsn in a pull request, merge, and CI tags the merge commit, creates the release and publishes to Hex.pm. Co-Authored-By: Claude Fable 5.1 --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 74eb48c..c7b1f19 100644 --- a/README.md +++ b/README.md @@ -274,6 +274,10 @@ Some feeds, for example ipdata's own `vpn` feed, carry none of `first_seen`, `la rebar3 ct ``` +## Releasing + +Bump `vsn` in `src/ipdata.app.src` in a pull request and merge it. CI then tags the merge commit `vx.y.z`, creates the GitHub release and publishes the package and its documentation to [Hex.pm](https://hex.pm/packages/ipdata). A merge whose version is already tagged publishes nothing. + ## License MIT - see [LICENSE](LICENSE) for details.