From d39750012f7982c25a7a7675a749b67791a7561a Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 14 Apr 2026 19:40:06 +0000 Subject: [PATCH 1/5] ci: always auto-tag master merges and align release channels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - auto-tag-release: fire on every master PR merge (patch default), not just labeled PRs — ensures every master merge triggers a v* tag which in turn drives PyPI + Docker + GitHub Release via release.yml - release: remove publish-testpypi-master job (master no longer publishes to TestPyPI; stable releases flow through v* tags only) - release: remove master from on.push.branches (no direct branch publish from master; all PyPI releases are tag-driven) - release: decouple github-release from publish-docker so GitHub Release and PyPI versions stay aligned regardless of Docker status - release: update channel mapping comment to reflect three-lane model: dev → TestPyPI (0.0.0.devN), stage → TestPyPI (0.0.0aN), master → PyPI (vX.Y.Z via auto-tag) https://claude.ai/code/session_011TVGTau9dgMHDuCo9qrDNV --- .github/workflows/auto-tag-release.yml | 3 ++ .github/workflows/release.yml | 56 +++----------------------- 2 files changed, 8 insertions(+), 51 deletions(-) diff --git a/.github/workflows/auto-tag-release.yml b/.github/workflows/auto-tag-release.yml index 41ced50..4b3290c 100644 --- a/.github/workflows/auto-tag-release.yml +++ b/.github/workflows/auto-tag-release.yml @@ -10,9 +10,12 @@ permissions: jobs: tag: + # Always fire on master merges (defaults to patch bump). + # Fire on stage/dev only when a release:* label is present. if: > github.event.pull_request.merged == true && ( + github.event.pull_request.base.ref == 'master' || contains(github.event.pull_request.labels.*.name, 'release:patch') || contains(github.event.pull_request.labels.*.name, 'release:minor') || contains(github.event.pull_request.labels.*.name, 'release:major') diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4cebc9b..632556e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,7 +3,6 @@ name: Release on: push: branches: - - master - stage - dev tags: @@ -17,10 +16,10 @@ permissions: jobs: # ── Publish channel builds to TestPyPI on branch merges ─────────────── # Channel mapping: - # - dev -> 0.0.0.devN - # - stage -> 0.0.0aN - # - master -> 0.0.0rcN - # Stable PyPI releases remain tag-based (vX.Y.Z). + # - dev -> 0.0.0.devN (TestPyPI) + # - stage -> 0.0.0aN (TestPyPI) + # - master -> stable vX.Y.Z via auto-tagged v* from auto-tag-release.yml (PyPI) + # Stable PyPI releases are tag-based (vX.Y.Z); master branch push triggers no direct publish. publish-testpypi-dev: if: github.ref == 'refs/heads/dev' runs-on: ubuntu-latest @@ -109,51 +108,6 @@ jobs: password: ${{ secrets.TEST_PYPI_API_TOKEN }} skip-existing: true - publish-testpypi-master: - if: github.ref == 'refs/heads/master' - runs-on: ubuntu-latest - environment: testpypi - permissions: - contents: read - steps: - - name: Verify TestPyPI token is configured - run: | - if [ -z "${{ secrets.TEST_PYPI_API_TOKEN }}" ]; then - echo "::error::Missing secret TEST_PYPI_API_TOKEN (Settings → Secrets and variables → Actions)." - echo "Create an API token on TestPyPI for the `faster-api-web` project and add it as TEST_PYPI_API_TOKEN." - exit 1 - fi - - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - uses: actions/setup-python@v5 - with: - python-version: "3.13" - - - name: Install build tools - run: pip install build - - - name: Build channel package (master) - env: - SETUPTOOLS_SCM_PRETEND_VERSION: 0.0.0rc${{ github.run_number }} - run: python -m build - - - name: Upload package artifact (master channel) - uses: actions/upload-artifact@v4 - with: - name: dist-master - path: dist/ - - - name: Publish to TestPyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - repository-url: https://test.pypi.org/legacy/ - user: __token__ - password: ${{ secrets.TEST_PYPI_API_TOKEN }} - skip-existing: true - # ── Gate: only release from master ────────────────────────────────── check-branch: if: startsWith(github.ref, 'refs/tags/v') @@ -277,7 +231,7 @@ jobs: # ── Step 5: Create GitHub Release with artifacts ─────────────────── github-release: - needs: [build, publish-pypi, publish-docker] + needs: [build, publish-pypi] if: startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest permissions: From abab6dd1de35081d0384ca706df0e77efdbe6c19 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 14 Apr 2026 19:50:15 +0000 Subject: [PATCH 2/5] fix: resolve ruff I001 and mypy no-any-return errors blocking Python 3.13 CI - benchmarks/update_readme_benchmarks.py: remove extra blank line after import block (ruff I001 - import block un-sorted or un-formatted) - FasterAPI/response.py: cast msgspec.json.encode() return value to bytes in JSONResponse._render so mypy strict no-any-return check passes (msgspec stubs type the return as Any; cast is zero-cost at runtime) https://claude.ai/code/session_011TVGTau9dgMHDuCo9qrDNV --- FasterAPI/response.py | 4 ++-- benchmarks/update_readme_benchmarks.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/FasterAPI/response.py b/FasterAPI/response.py index b87fbd5..5c405ad 100644 --- a/FasterAPI/response.py +++ b/FasterAPI/response.py @@ -4,7 +4,7 @@ import mimetypes from collections.abc import AsyncIterator, Iterator from pathlib import Path -from typing import Any +from typing import Any, cast import msgspec.json @@ -71,7 +71,7 @@ class JSONResponse(Response): media_type = "application/json" def _render(self, content: Any) -> bytes: - return msgspec.json.encode(content) + return cast(bytes, msgspec.json.encode(content)) class HTMLResponse(Response): diff --git a/benchmarks/update_readme_benchmarks.py b/benchmarks/update_readme_benchmarks.py index 955e80a..9fb2b58 100644 --- a/benchmarks/update_readme_benchmarks.py +++ b/benchmarks/update_readme_benchmarks.py @@ -4,7 +4,6 @@ import re from pathlib import Path - README_PATH = Path("README.md") BENCH_JSON = Path("bench_results.json") ROUTING_JSON = Path("routing_results.json") From 0d4d0bbfa55b6f49c549d680e0b178c3604ba059 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 15 Apr 2026 04:21:20 +0000 Subject: [PATCH 3/5] ci: remove dev branch trigger, make Codecov non-blocking https://claude.ai/code/session_011TVGTau9dgMHDuCo9qrDNV --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e8bec51..8fb9a04 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: [master, stage, dev] + branches: [master, stage] pull_request: - branches: [master, stage, dev] + branches: [master, stage] permissions: contents: read @@ -50,6 +50,6 @@ jobs: with: files: coverage.xml flags: python${{ matrix.python-version }} - fail_ci_if_error: true + fail_ci_if_error: false env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} From 3511c15e9c628698b2967112d97174b0d8135bf6 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 15 Apr 2026 04:21:42 +0000 Subject: [PATCH 4/5] ci: sync final 2-branch workflow files to feature branch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Align feature branch with the rebuilt stage content: - release.yml: 2-branch model (stage → TestPyPI, v* tag → PyPI) - auto-tag-release.yml: master+stage only, no dev-v prefix https://claude.ai/code/session_011TVGTau9dgMHDuCo9qrDNV --- .github/workflows/auto-tag-release.yml | 6 +-- .github/workflows/release.yml | 55 +++----------------------- 2 files changed, 7 insertions(+), 54 deletions(-) diff --git a/.github/workflows/auto-tag-release.yml b/.github/workflows/auto-tag-release.yml index 4b3290c..dd30055 100644 --- a/.github/workflows/auto-tag-release.yml +++ b/.github/workflows/auto-tag-release.yml @@ -3,7 +3,7 @@ name: Auto Tag Release on: pull_request: types: [closed] - branches: [master, stage, dev] + branches: [master, stage] permissions: contents: write @@ -11,7 +11,7 @@ permissions: jobs: tag: # Always fire on master merges (defaults to patch bump). - # Fire on stage/dev only when a release:* label is present. + # Fire on stage only when a release:* label is present. if: > github.event.pull_request.merged == true && ( @@ -43,8 +43,6 @@ jobs: TARGET_BRANCH="${{ github.event.pull_request.base.ref }}" if [ "$TARGET_BRANCH" = "stage" ]; then BASE_PREFIX="stage-v" - elif [ "$TARGET_BRANCH" = "dev" ]; then - BASE_PREFIX="dev-v" fi LAST_TAG="$(git tag -l "${BASE_PREFIX}*" --sort=-v:refname | sed -n '1p')" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 632556e..a8cb3ef 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,7 +4,6 @@ on: push: branches: - stage - - dev tags: - "v*" @@ -14,56 +13,12 @@ permissions: packages: write jobs: - # ── Publish channel builds to TestPyPI on branch merges ─────────────── + # ── Publish pre-release builds to TestPyPI on stage merges ─────────── # Channel mapping: - # - dev -> 0.0.0.devN (TestPyPI) - # - stage -> 0.0.0aN (TestPyPI) - # - master -> stable vX.Y.Z via auto-tagged v* from auto-tag-release.yml (PyPI) - # Stable PyPI releases are tag-based (vX.Y.Z); master branch push triggers no direct publish. - publish-testpypi-dev: - if: github.ref == 'refs/heads/dev' - runs-on: ubuntu-latest - environment: testpypi - permissions: - contents: read - steps: - - name: Verify TestPyPI token is configured - run: | - if [ -z "${{ secrets.TEST_PYPI_API_TOKEN }}" ]; then - echo "::error::Missing secret TEST_PYPI_API_TOKEN (Settings → Secrets and variables → Actions)." - exit 1 - fi - - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - uses: actions/setup-python@v5 - with: - python-version: "3.13" - - - name: Install build tools - run: pip install build - - - name: Build channel package (dev) - env: - SETUPTOOLS_SCM_PRETEND_VERSION: 0.0.0.dev${{ github.run_number }} - run: python -m build - - - name: Upload package artifact (dev channel) - uses: actions/upload-artifact@v4 - with: - name: dist-dev - path: dist/ - - - name: Publish to TestPyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - repository-url: https://test.pypi.org/legacy/ - user: __token__ - password: ${{ secrets.TEST_PYPI_API_TOKEN }} - skip-existing: true - + # - stage -> 0.0.0aN (TestPyPI pre-release) + # - master -> vX.Y.Z (PyPI stable, via auto-tag from auto-tag-release.yml) + # Stable PyPI releases are tag-based (vX.Y.Z); master branch push triggers + # the auto-tag workflow which creates the tag that drives this pipeline. publish-testpypi-stage: if: github.ref == 'refs/heads/stage' runs-on: ubuntu-latest From 0de6b749eb44ba23ba39e4eac8c2e93b83b6903e Mon Sep 17 00:00:00 2001 From: Eshwar Chandra Vidhyasagar Thedla Date: Thu, 16 Apr 2026 20:50:26 -0500 Subject: [PATCH 5/5] =?UTF-8?q?chore:=20mark=20branch=20for=20deletion=20?= =?UTF-8?q?=E2=80=94=20superseded=20by=20master?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .branch-cleanup | 1 + 1 file changed, 1 insertion(+) create mode 100644 .branch-cleanup diff --git a/.branch-cleanup b/.branch-cleanup new file mode 100644 index 0000000..f0b519f --- /dev/null +++ b/.branch-cleanup @@ -0,0 +1 @@ +This branch has been superseded by master and can be safely deleted.