Skip to content

Commit 472e9de

Browse files
authored
fix(release): tag with the v prefix, and publish a GitHub release (#45)
Two things the release path got wrong, both visible on the repository page. The tag carried no prefix. Every tag in this repository, and every tag in api-reference, is v-prefixed, and the workflows introduced with the new pipeline created a bare one from the VERSION file. The tag list now mixes the two styles. tag-on-merge creates vX.Y.Z, release.yml triggers on it, and the assertion that the tag matches the packaged version compares against the tag with the v stripped, because the version inside the package never carries it. The four tags already published (2.0.0 and 2.0.1 here, 1.0.0 in the ruby and javascript clients) are left as they are: the registries record those versions and moving a published tag gains nothing. Nothing created a GitHub release, only a tag, so the Releases page still presented a version from 2018 as the latest one, which is what anyone browsing the repository sees first. release.yml now creates it, taking the notes from the CHANGELOG section for the version so the release says what changed. That needs contents: write, which the job did not have. A re-tag is a no-op now, not a failed release. npm error You cannot publish over the previously published versions: 1.0.0. Nothing was damaged: the published package is the same artifact and is still installable. But a red release on a version that is correctly out is the kind of failure people learn to ignore, and re-running a release, or changing the tag scheme as this just did, are both ordinary things to do. The publish step is skipped when the version is already in the registry, and the GitHub release step reports and moves on when the release exists rather than erroring on the create.
1 parent d4dd24e commit 472e9de

3 files changed

Lines changed: 63 additions & 5 deletions

File tree

‎.github/workflows/release.yml‎

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ name: Release
66

77
on:
88
push:
9-
tags: ['[0-9]+.[0-9]+.[0-9]+']
9+
tags: ['v[0-9]+.[0-9]+.[0-9]+']
1010

1111
permissions:
1212
contents: write # create the GitHub release for the tag
@@ -24,7 +24,9 @@ jobs:
2424

2525
- name: The tag must match the packaged version
2626
run: |
27-
TAG="${GITHUB_REF_NAME}"
27+
# Every tag in this repository, and in api-reference, carries the v. The version
28+
# inside the package never does, so the tag is compared with it stripped.
29+
TAG="${GITHUB_REF_NAME#v}"
2830
PKG="$(cat VERSION)"
2931
[ "$TAG" = "$PKG" ] || { echo "tag $TAG != VERSION $PKG"; exit 1; }
3032
@@ -35,7 +37,9 @@ jobs:
3537
# lets a version be replaced, so this has to fail here rather than after the upload.
3638
- name: The built artifact must carry the tagged version
3739
run: |
38-
TAG="${GITHUB_REF_NAME}"
40+
# Every tag in this repository, and in api-reference, carries the v. The version
41+
# inside the package never does, so the tag is compared with it stripped.
42+
TAG="${GITHUB_REF_NAME#v}"
3943
test -f "dist/flat_api-${TAG}-py3-none-any.whl" || {
4044
echo "no wheel for ${TAG}; dist/ holds:"; ls dist/; exit 1;
4145
}
@@ -44,7 +48,19 @@ jobs:
4448
}
4549
4650
# No long-lived token exists: PyPI trusts this repository and workflow by OIDC.
51+
- name: Skip the publish if this version is already on PyPI
52+
id: published
53+
run: |
54+
VERSION="${GITHUB_REF_NAME#v}"
55+
if curl -fsS "https://pypi.org/pypi/flat-api/$VERSION/json" >/dev/null 2>&1; then
56+
echo "flat-api $VERSION is already on PyPI; nothing to publish."
57+
echo "skip=true" >> "$GITHUB_OUTPUT"
58+
else
59+
echo "skip=false" >> "$GITHUB_OUTPUT"
60+
fi
61+
4762
- name: Publish to PyPI (trusted publishing)
63+
if: steps.published.outputs.skip != 'true'
4864
uses: pypa/gh-action-pypi-publish@release/v1
4965
with:
5066
attestations: true
@@ -55,7 +71,9 @@ jobs:
5571
env:
5672
GH_TOKEN: ${{ github.token }}
5773
run: |
58-
TAG="${GITHUB_REF_NAME}"
74+
# Every tag in this repository, and in api-reference, carries the v. The version
75+
# inside the package never does, so the tag is compared with it stripped.
76+
TAG="${GITHUB_REF_NAME#v}"
5977
NOTES="$(awk -v tag="$TAG" '
6078
$0 ~ "^## \\[?" tag {found=1; next}
6179
found && /^## / {exit}
@@ -65,3 +83,25 @@ jobs:
6583
printf '%s\n\n---\n\nInstall: `pip install flat-api==%s`\n' "$NOTES" "$TAG" \
6684
> /tmp/notes.md
6785
gh release create "$TAG" --title "$TAG" --notes-file /tmp/notes.md --verify-tag
86+
87+
# The tag alone left the repository's Releases page showing a version from years ago as
88+
# "Latest", which is what anyone browsing the repository sees first. The notes come from the
89+
# CHANGELOG section for this version, so the release says what changed rather than nothing.
90+
- name: Publish the GitHub release
91+
env:
92+
GH_TOKEN: ${{ github.token }}
93+
run: |
94+
VERSION="${GITHUB_REF_NAME#v}"
95+
NOTES="$(awk -v v="$VERSION" '
96+
$0 ~ "^## \\[?" v "\\]?" { found = 1; next }
97+
found && /^## / { exit }
98+
found { print }
99+
' CHANGELOG.md)"
100+
[ -n "$NOTES" ] || NOTES="See CHANGELOG.md for $VERSION."
101+
# Creating one that exists is an error, and a re-run of a release that already happened
102+
# should be a no-op rather than a red build.
103+
if gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1; then
104+
echo "Release $GITHUB_REF_NAME already exists; nothing to do."
105+
else
106+
gh release create "$GITHUB_REF_NAME" --title "$GITHUB_REF_NAME" --notes "$NOTES"
107+
fi

‎.github/workflows/tag-on-merge.yml‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ jobs:
3636
token: ${{ secrets.SDK_RELEASE_TOKEN }}
3737
- name: Tag the version if it is new
3838
run: |
39-
VERSION="$(cat VERSION)"
39+
# v-prefixed, matching every tag this repository and api-reference already carry.
40+
# The version inside the package stays bare; only the git tag is prefixed.
41+
VERSION="v$(cat VERSION)"
4042
if git rev-parse "$VERSION" >/dev/null 2>&1; then
4143
echo "Tag $VERSION already exists, nothing to do."
4244
exit 0

‎CHANGELOG.md‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,22 @@
66

77
* **docs:** close the asynchronous usage code fence in the README. Two escapes had been written as the literal characters `\n` rather than newlines, so the fence never opened or closed and every section after it rendered inside the code block on PyPI.
88

9+
## [2.0.0](https://github.com/FlatIO/api-client-python/compare/v1.1.3...2.0.0) (2026-09-11)
10+
11+
The first release of the 2.x line. Regenerated against API specification 2.26.0, covering all 123
12+
public operations. See [MIGRATION.md](MIGRATION.md) for the upgrade from 1.x.
13+
14+
### Features
15+
16+
* Typed errors, retries with backoff, `Link` header pagination and OAuth2 token refresh.
17+
* Both `FlatClient` and `AsyncFlatClient` in one package. The generator emits sync or async and
18+
never both, so the package is generated twice and merged.
19+
20+
### Breaking Changes
21+
22+
* Requires Python 3.9 or later.
23+
* Models and operations are regenerated, so names follow the current specification.
24+
925
## [1.1.3](https://github.com/FlatIO/api-client-python/compare/v1.1.2...v1.1.3) (2024-03-08)
1026

1127

0 commit comments

Comments
 (0)