From 9c15471b74813684910a629ba6c78be1eb59d60e Mon Sep 17 00:00:00 2001 From: Pratyush Sharma <56130065+pratyush618@users.noreply.github.com> Date: Wed, 6 May 2026 23:42:43 +0530 Subject: [PATCH 1/5] fix(packaging): include compiled dashboard in wheel and sdist `python-source` only auto-packages .py/.pyi/py.typed; static SPA assets need explicit opt-in. Without this, every wheel since 0.12.0 shipped an empty static/ and `taskito dashboard` returned "Dashboard assets not bundled" at runtime. --- pyproject.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 72fd3f7..34d04f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,12 @@ manifest-path = "crates/taskito-python/Cargo.toml" python-source = "py_src" module-name = "taskito._taskito" features = ["extension-module", "postgres", "redis", "workflows"] +# Maturin's `python-source` only auto-packages Python sources (`.py`, `.pyi`, +# `py.typed`). The compiled dashboard SPA must be opted in explicitly so it +# ships in both the wheel and the sdist. +include = [ + { path = "py_src/taskito/static/dashboard/**/*", format = ["wheel", "sdist"] }, +] [project.scripts] taskito = "taskito.cli:main" From dcd600379b097b8701213cc71d65bb98c184c3e3 Mon Sep 17 00:00:00 2001 From: Pratyush Sharma <56130065+pratyush618@users.noreply.github.com> Date: Wed, 6 May 2026 23:42:53 +0530 Subject: [PATCH 2/5] ci(release): build dashboard before maturin and verify per wheel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a composite action consumed by both publish.yml (release) and dashboard.yml (CI) so pnpm/Node versions and the build pipeline have a single source of truth. publish.yml gains a build-dashboard job whose output every wheel/sdist job downloads and checks for index.html before invoking maturin — a missing dashboard now fails CI loudly instead of shipping silently. --- .github/actions/dashboard-build/action.yml | 50 ++++++++++++++ .github/workflows/dashboard.yml | 41 ++++------- .github/workflows/publish.yml | 79 +++++++++++++++++++++- 3 files changed, 141 insertions(+), 29 deletions(-) create mode 100644 .github/actions/dashboard-build/action.yml diff --git a/.github/actions/dashboard-build/action.yml b/.github/actions/dashboard-build/action.yml new file mode 100644 index 0000000..3a27bdf --- /dev/null +++ b/.github/actions/dashboard-build/action.yml @@ -0,0 +1,50 @@ +name: Build dashboard +description: >- + Sets up Node and pnpm, installs dashboard dependencies, generates the + TanStack Router tree, and runs the Vite production build. Output is + written to `py_src/taskito/static/dashboard/` for packaging into the + Python wheel. + +# Single source of truth for dashboard build tooling versions. Both the +# release pipeline (`publish.yml`) and the dashboard CI (`dashboard.yml`) +# consume this action so the assets shipped in wheels are byte-identical +# to what CI tests. + +runs: + using: composite + steps: + - name: Set up pnpm + uses: pnpm/action-setup@v6 + with: + version: "10.30.3" + + - name: Set up Node.js + uses: actions/setup-node@v6 + with: + node-version: "22" + cache: pnpm + cache-dependency-path: dashboard/pnpm-lock.yaml + + - name: Install dashboard dependencies + shell: bash + working-directory: dashboard + run: pnpm install --frozen-lockfile + + - name: Generate TanStack Router tree + shell: bash + working-directory: dashboard + run: pnpm exec tsr generate + + - name: Vite production build + shell: bash + working-directory: dashboard + run: pnpm exec vite build + + - name: Verify build output + shell: bash + run: | + set -euo pipefail + if [ ! -f py_src/taskito/static/dashboard/index.html ]; then + echo "::error::Dashboard build did not produce py_src/taskito/static/dashboard/index.html" + exit 1 + fi diff --git a/.github/workflows/dashboard.yml b/.github/workflows/dashboard.yml index d652702..b4ce0d8 100644 --- a/.github/workflows/dashboard.yml +++ b/.github/workflows/dashboard.yml @@ -6,47 +6,34 @@ on: paths: - "dashboard/**" - ".github/workflows/dashboard.yml" + - ".github/actions/dashboard-build/**" pull_request: branches: [master] paths: - "dashboard/**" - ".github/workflows/dashboard.yml" + - ".github/actions/dashboard-build/**" concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -defaults: - run: - working-directory: dashboard - jobs: ci: name: lint · typecheck · test · build runs-on: ubuntu-latest timeout-minutes: 10 + defaults: + run: + working-directory: dashboard steps: - uses: actions/checkout@v6 - - name: Set up pnpm - uses: pnpm/action-setup@v6 - with: - version: "10.30.3" - - - name: Set up Node.js - uses: actions/setup-node@v6 - with: - node-version: "22" - cache: "pnpm" - cache-dependency-path: dashboard/pnpm-lock.yaml - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Generate route tree - # TanStack Router's file-based tree is a build artifact; tsc needs - # it to resolve route imports. - run: pnpm exec tsr generate + # The composite action handles pnpm + Node setup, install, route-tree + # generation, and the Vite build. It is the same action used by the + # release pipeline, so dashboard CI exercises the exact build path + # whose output ships in the wheel. + - uses: ./.github/actions/dashboard-build - name: Biome (lint + format) run: pnpm exec biome ci src/ @@ -57,11 +44,9 @@ jobs: - name: Unit tests (vitest) run: pnpm exec vitest run - - name: Build - run: pnpm exec vite build - - name: Bundle size summary if: always() + working-directory: ${{ github.workspace }} run: | set -e { @@ -69,10 +54,10 @@ jobs: echo echo "| File | Size | Gzipped |" echo "|------|-----:|--------:|" - find ../py_src/taskito/static/dashboard -type f \( -name "*.js" -o -name "*.css" -o -name "*.html" \) | sort | while read -r f; do + find py_src/taskito/static/dashboard -type f \( -name "*.js" -o -name "*.css" -o -name "*.html" \) | sort | while read -r f; do raw=$(stat -c%s "$f") gz=$(gzip -c "$f" | wc -c) - printf "| \`%s\` | %s | %s |\n" "${f#../py_src/taskito/static/dashboard/}" "$(numfmt --to=iec --suffix=B "$raw")" "$(numfmt --to=iec --suffix=B "$gz")" + printf "| \`%s\` | %s | %s |\n" "${f#py_src/taskito/static/dashboard/}" "$(numfmt --to=iec --suffix=B "$raw")" "$(numfmt --to=iec --suffix=B "$gz")" done } >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 047b21c..9db78f3 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -8,7 +8,24 @@ permissions: contents: read jobs: + build-dashboard: + name: Build dashboard assets + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - uses: ./.github/actions/dashboard-build + + - name: Upload dashboard artifact + uses: actions/upload-artifact@v7 + with: + name: dashboard-dist + path: py_src/taskito/static/dashboard + if-no-files-found: error + retention-days: 1 + build-wheels-linux: + needs: build-dashboard runs-on: ${{ matrix.os }} strategy: matrix: @@ -20,6 +37,16 @@ jobs: steps: - uses: actions/checkout@v6 + - name: Download dashboard assets + uses: actions/download-artifact@v8 + with: + name: dashboard-dist + path: py_src/taskito/static/dashboard + + - name: Verify dashboard assets present + shell: bash + run: test -f py_src/taskito/static/dashboard/index.html + - name: Build wheels uses: PyO3/maturin-action@v1 with: @@ -34,8 +61,10 @@ jobs: with: name: wheels-linux-${{ matrix.target }} path: dist/*.whl + if-no-files-found: error build-wheels-musllinux: + needs: build-dashboard runs-on: ${{ matrix.os }} strategy: matrix: @@ -47,6 +76,16 @@ jobs: steps: - uses: actions/checkout@v6 + - name: Download dashboard assets + uses: actions/download-artifact@v8 + with: + name: dashboard-dist + path: py_src/taskito/static/dashboard + + - name: Verify dashboard assets present + shell: bash + run: test -f py_src/taskito/static/dashboard/index.html + - name: Build wheels uses: PyO3/maturin-action@v1 with: @@ -61,8 +100,10 @@ jobs: with: name: wheels-musllinux-${{ matrix.target }} path: dist/*.whl + if-no-files-found: error build-wheels-macos: + needs: build-dashboard runs-on: macos-latest strategy: matrix: @@ -72,6 +113,16 @@ jobs: steps: - uses: actions/checkout@v6 + - name: Download dashboard assets + uses: actions/download-artifact@v8 + with: + name: dashboard-dist + path: py_src/taskito/static/dashboard + + - name: Verify dashboard assets present + shell: bash + run: test -f py_src/taskito/static/dashboard/index.html + - name: Set up Python 3.10 uses: actions/setup-python@v6 with: @@ -103,8 +154,10 @@ jobs: with: name: wheels-macos-${{ matrix.target }} path: dist/*.whl + if-no-files-found: error build-wheels-windows: + needs: build-dashboard runs-on: windows-latest strategy: matrix: @@ -113,6 +166,16 @@ jobs: steps: - uses: actions/checkout@v6 + - name: Download dashboard assets + uses: actions/download-artifact@v8 + with: + name: dashboard-dist + path: py_src/taskito/static/dashboard + + - name: Verify dashboard assets present + shell: bash + run: test -f py_src/taskito/static/dashboard/index.html + - name: Set up Python 3.10 uses: actions/setup-python@v6 with: @@ -144,12 +207,24 @@ jobs: with: name: wheels-windows-${{ matrix.target }} path: dist/*.whl + if-no-files-found: error build-sdist: + needs: build-dashboard runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 + - name: Download dashboard assets + uses: actions/download-artifact@v8 + with: + name: dashboard-dist + path: py_src/taskito/static/dashboard + + - name: Verify dashboard assets present + shell: bash + run: test -f py_src/taskito/static/dashboard/index.html + - name: Build sdist uses: PyO3/maturin-action@v1 with: @@ -161,6 +236,7 @@ jobs: with: name: sdist path: dist/*.tar.gz + if-no-files-found: error publish: needs: [build-wheels-linux, build-wheels-musllinux, build-wheels-macos, build-wheels-windows, build-sdist] @@ -169,9 +245,10 @@ jobs: permissions: id-token: write steps: - - name: Download all artifacts + - name: Download wheel and sdist artifacts uses: actions/download-artifact@v8 with: + pattern: "{wheels-*,sdist}" path: dist merge-multiple: true From b266b9fa6959ffe56dc02fcd6f883ba04c29d474 Mon Sep 17 00:00:00 2001 From: Pratyush Sharma <56130065+pratyush618@users.noreply.github.com> Date: Wed, 6 May 2026 23:43:03 +0530 Subject: [PATCH 3/5] chore: release 0.12.1 --- crates/taskito-async/Cargo.toml | 2 +- crates/taskito-core/Cargo.toml | 2 +- crates/taskito-python/Cargo.toml | 2 +- crates/taskito-workflows/Cargo.toml | 2 +- docs/content/docs/more/changelog.mdx | 12 ++++++++++++ py_src/taskito/__init__.py | 2 +- pyproject.toml | 2 +- 7 files changed, 18 insertions(+), 6 deletions(-) diff --git a/crates/taskito-async/Cargo.toml b/crates/taskito-async/Cargo.toml index fa20139..da71bd9 100644 --- a/crates/taskito-async/Cargo.toml +++ b/crates/taskito-async/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "taskito-async" -version = "0.12.0" +version = "0.12.1" edition = "2021" [dependencies] diff --git a/crates/taskito-core/Cargo.toml b/crates/taskito-core/Cargo.toml index c9982eb..b763243 100644 --- a/crates/taskito-core/Cargo.toml +++ b/crates/taskito-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "taskito-core" -version = "0.12.0" +version = "0.12.1" edition = "2021" [features] diff --git a/crates/taskito-python/Cargo.toml b/crates/taskito-python/Cargo.toml index 07b1563..17b455b 100644 --- a/crates/taskito-python/Cargo.toml +++ b/crates/taskito-python/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "taskito-python" -version = "0.12.0" +version = "0.12.1" edition = "2021" [features] diff --git a/crates/taskito-workflows/Cargo.toml b/crates/taskito-workflows/Cargo.toml index 3883fe9..9a57557 100644 --- a/crates/taskito-workflows/Cargo.toml +++ b/crates/taskito-workflows/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "taskito-workflows" -version = "0.12.0" +version = "0.12.1" edition = "2021" [dependencies] diff --git a/docs/content/docs/more/changelog.mdx b/docs/content/docs/more/changelog.mdx index c3f60d7..a8a9ccc 100644 --- a/docs/content/docs/more/changelog.mdx +++ b/docs/content/docs/more/changelog.mdx @@ -5,6 +5,18 @@ description: "Release history for taskito — every notable change, fix, and fea All notable changes to taskito are documented here. +## 0.12.1 + +### Fixed + +- **PyPI wheels and sdist now bundle the compiled dashboard.** A regression in 0.12.0 shipped wheels with an empty `taskito/static/` directory because the release pipeline ran `maturin build` without first building the dashboard frontend. End users hit `Dashboard assets not bundled` when running `taskito dashboard`. The release pipeline now builds the dashboard once in a dedicated job, distributes it to every wheel/sdist job as a build artifact, and verifies `static/dashboard/index.html` is present before each `maturin build` invocation — preventing the regression class entirely. + +### Internal + +- **`.github/actions/dashboard-build/`** — composite action centralizing pnpm/Node toolchain versions and the dashboard build steps. Consumed by both `publish.yml` (release) and `dashboard.yml` (CI), so the assets shipped in a wheel are produced by the exact same build path that CI tests on every PR. + +--- + ## 0.12.0 ### Added diff --git a/py_src/taskito/__init__.py b/py_src/taskito/__init__.py index caa29dd..baa36d1 100644 --- a/py_src/taskito/__init__.py +++ b/py_src/taskito/__init__.py @@ -99,4 +99,4 @@ __version__ = _get_version("taskito") except PackageNotFoundError: - __version__ = "0.12.0" + __version__ = "0.12.1" diff --git a/pyproject.toml b/pyproject.toml index 34d04f8..8307412 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "maturin" [project] name = "taskito" -version = "0.12.0" +version = "0.12.1" description = "Rust-powered task queue for Python. No broker required." requires-python = ">=3.10" license = { file = "LICENSE" } From 2a9e7d3bcac380e29b2b74a90ced634d69db7a7a Mon Sep 17 00:00:00 2001 From: Pratyush Sharma <56130065+pratyush618@users.noreply.github.com> Date: Wed, 6 May 2026 23:52:54 +0530 Subject: [PATCH 4/5] Clean up comments in action.yml Removed comments about the dashboard build tooling versions. --- .github/actions/dashboard-build/action.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/actions/dashboard-build/action.yml b/.github/actions/dashboard-build/action.yml index 3a27bdf..60f6f36 100644 --- a/.github/actions/dashboard-build/action.yml +++ b/.github/actions/dashboard-build/action.yml @@ -5,11 +5,6 @@ description: >- written to `py_src/taskito/static/dashboard/` for packaging into the Python wheel. -# Single source of truth for dashboard build tooling versions. Both the -# release pipeline (`publish.yml`) and the dashboard CI (`dashboard.yml`) -# consume this action so the assets shipped in wheels are byte-identical -# to what CI tests. - runs: using: composite steps: From 24f8a78dd9304972bbde2e3bc62ed1f946db45b7 Mon Sep 17 00:00:00 2001 From: Pratyush Sharma <56130065+pratyush618@users.noreply.github.com> Date: Wed, 6 May 2026 23:53:42 +0530 Subject: [PATCH 5/5] Clean up comments in dashboard.yml Removed comments about the composite action in the dashboard workflow. --- .github/workflows/dashboard.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/dashboard.yml b/.github/workflows/dashboard.yml index b4ce0d8..a450069 100644 --- a/.github/workflows/dashboard.yml +++ b/.github/workflows/dashboard.yml @@ -28,11 +28,6 @@ jobs: working-directory: dashboard steps: - uses: actions/checkout@v6 - - # The composite action handles pnpm + Node setup, install, route-tree - # generation, and the Vite build. It is the same action used by the - # release pipeline, so dashboard CI exercises the exact build path - # whose output ships in the wheel. - uses: ./.github/actions/dashboard-build - name: Biome (lint + format)