Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions .dev/test-version

This file was deleted.

21 changes: 21 additions & 0 deletions .github/instructions/release.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Release Instructions

Releases are driven by `v*` git tags. Pushing a tag triggers
`.github/workflows/release.yml`, which runs the test suite, publishes the
package to PyPI (`make publish`), then extracts the matching `## vX.Y.Z`
section from `docs/release-notes.md` and publishes it as the GitHub Release
body (re-runs update the existing release instead of failing).

## Cutting a release

1. Bump `version` in `pyproject.toml`. That is the single source of truth —
`fluid.__version__` is read from the installed package metadata, so there
is nothing else to edit.
2. Add a `## vX.Y.Z` section at the top of `docs/release-notes.md` describing
the changes. The release workflow fails if this section is missing.
3. Commit and push to `main`; let the `build` workflow pass.
4. Run `make release` — it reads the version from `pyproject.toml`, asks for
confirmation, then creates and pushes the `vX.Y.Z` tag. The `release`
workflow takes it from there.

Do not publish to PyPI manually; let the tagged workflow do it.
6 changes: 0 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ jobs:
timeout-minutes: 5
env:
PYTHON_ENV: ci
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
FLUID_FLAMEGRAPH_EXECUTABLE: "./flamegraph.pl"
strategy:
matrix:
Expand Down Expand Up @@ -50,8 +49,6 @@ jobs:
run: ./.dev/install-flamegraph
- name: run lint
run: make lint-test
- name: test version
run: make test-version
- name: build docs
run: make docs
- name: tests
Expand All @@ -62,9 +59,6 @@ jobs:
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./build/coverage.xml
- name: publish
if: ${{ github.ref == 'refs/heads/main' && matrix.python-version == '3.14' && github.event.head_commit.message == 'release' }}
run: make publish
- name: publish-docs
if: ${{ github.ref == 'refs/heads/main' && matrix.python-version == '3.14' }}
run: make docs-publish
85 changes: 85 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: release

# Triggered by `v*` tags (push one with `make release`). Runs the test suite,
# publishes the package to PyPI, then extracts the matching section from
# docs/release-notes.md and publishes it as the GitHub Release body. Re-runs
# idempotently update an existing release rather than failing.

on:
push:
tags:
- "v*"

permissions:
contents: write

jobs:
release:
runs-on: ubuntu-latest
timeout-minutes: 10
env:
PYTHON_ENV: ci
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
FLUID_FLAMEGRAPH_EXECUTABLE: "./flamegraph.pl"

services:
postgres:
image: postgres:15
ports:
- 5432:5432
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: test_db

steps:
- name: checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.14"
- name: Start Redis
uses: supercharge/redis-github-action@1.2.0
with:
redis-version: 7
- name: Install dependencies
run: make install
- name: Install flamegraph
env:
FG_PATH: "."
run: ./.dev/install-flamegraph
- name: run lint
run: make lint-test
- name: build docs
run: make docs
- name: tests
run: make test
- name: publish to PyPI
run: make publish
- name: Extract release notes
run: |
TAG="${GITHUB_REF_NAME}"
awk -v tag="## ${TAG}" '
$0 == tag { in_section = 1; next }
/^## / && in_section { exit }
in_section { print }
' docs/release-notes.md > /tmp/notes.md
if [ ! -s /tmp/notes.md ]; then
echo "No section '## ${TAG}' found in docs/release-notes.md" >&2
exit 1
fi
echo "--- extracted notes for ${TAG} ---"
cat /tmp/notes.md
- name: Publish GitHub Release
run: |
TAG="${GITHUB_REF_NAME}"
if gh release view "$TAG" >/dev/null 2>&1; then
gh release edit "$TAG" --notes-file /tmp/notes.md
else
gh release create "$TAG" --title "$TAG" --notes-file /tmp/notes.md
fi
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
@.github/instructions/makefile.instructions.md
@.github/instructions/code.instructions.md
@.github/instructions/tests.instructions.md
@.github/instructions/release.instructions.md
17 changes: 12 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,24 @@ outdated: ## Show outdated packages
uv tree --outdated

.PHONY: publish
publish: ## release to pypi and github tag
publish: ## release to pypi
@uv build && uv publish --token $(PYPI_TOKEN)

.PHONY: readme
readme: ## generate readme.md
cp docs/index.md readme.md

.PHONY: release
release: ## tag current version (from pyproject.toml) and push
$(eval VERSION := $(shell grep '^version' pyproject.toml | head -1 | sed 's/version = "\(.*\)"/\1/'))
@read -p "Tagging with v$(VERSION), are you sure? [Y/n] " ans; \
ans=$${ans:-Y}; \
if [ "$$ans" = "Y" ] || [ "$$ans" = "y" ]; then \
git tag -a v$(VERSION) -m "v$(VERSION)" && git push origin v$(VERSION); \
else \
echo "Aborted."; \
fi

.PHONY: taplo-fmt
taplo-fmt: ## format toml files with taplo
taplo fmt
Expand All @@ -65,10 +76,6 @@ test: ## test with coverage
-m "not flaky" \
--cov --cov-report xml --cov-report html

.PHONY: test-version
test-version: ## check version compatibility
@./.dev/test-version

.PHONY: upgrade
upgrade: ## upgrade all packages via uv
uv lock --upgrade
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<h1>
<a href="https://fluid.quantmind.com/">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://fluid.quantmind.com/assets/fluid-banner-dark.svg">
<img alt="aio-fluid — async utilities for backend Python services" src="https://fluid.quantmind.com/assets/fluid-banner-light.svg" width="300">
<source media="(prefers-color-scheme: dark)" srcset="https://fluid.quantmind.com/assets/fluid-banner-light.svg" style="max-width: 400px; width: 100%;">
<img alt="aio-fluid — async utilities for backend Python services" src="https://fluid.quantmind.com/assets/fluid-banner-dark.svg" style="max-width: 400px; width: 100%;">
</picture>
</a>
</h1>
Expand Down
10 changes: 10 additions & 0 deletions docs/release-notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Release Notes

## v2.2.4

Bug-fix release for the task scheduler.

- Fix task interruption handling. ([#89](https://github.com/quantmind/aio-fluid/pull/89))
- Fix stale concurrent tasks not being released. ([#88](https://github.com/quantmind/aio-fluid/pull/88))
- Fix task abort behaviour. ([#87](https://github.com/quantmind/aio-fluid/pull/87))
- Patch `pydanclick` to work with `StrEnum`. ([#86](https://github.com/quantmind/aio-fluid/pull/86))
Loading