From c5b4b1704007d528b1b4af736e681e2f22293df8 Mon Sep 17 00:00:00 2001 From: Lorenzo Mangani Date: Sun, 31 May 2026 09:31:59 +0200 Subject: [PATCH] Add GitHub Pages extension repo to Release workflow. Align MainDistributionPipeline on DuckDB v1.5.3, publish unsigned quackscale binaries to GitHub Pages on release, keep the linux QuackTail tarball on GitHub Releases, and document install paths in README. Co-authored-by: Cursor --- .../workflows/MainDistributionPipeline.yml | 4 +- .github/workflows/Release.yml | 156 ++++++++++++++++-- README.md | 28 ++++ docs/DEVELOPMENT.md | 20 ++- 4 files changed, 194 insertions(+), 14 deletions(-) diff --git a/.github/workflows/MainDistributionPipeline.yml b/.github/workflows/MainDistributionPipeline.yml index 0da6476..3af1d56 100644 --- a/.github/workflows/MainDistributionPipeline.yml +++ b/.github/workflows/MainDistributionPipeline.yml @@ -16,7 +16,7 @@ jobs: name: Build extension binaries uses: duckdb/extension-ci-tools/.github/workflows/_extension_distribution.yml@v1.5-variegata with: - duckdb_version: v1.5.2 + duckdb_version: v1.5.3 ci_tools_version: v1.5-variegata extension_name: quackscale extra_toolchains: 'go' @@ -27,7 +27,7 @@ jobs: name: Code Quality Check uses: duckdb/extension-ci-tools/.github/workflows/_extension_code_quality.yml@v1.5-variegata with: - duckdb_version: v1.5.2 + duckdb_version: v1.5.3 ci_tools_version: v1.5-variegata extension_name: quackscale format_checks: 'format;tidy' diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml index b37cb86..0f9a9b6 100644 --- a/.github/workflows/Release.yml +++ b/.github/workflows/Release.yml @@ -1,28 +1,164 @@ -# Build a Linux DuckDB binary with quackscale embedded and attach it to the GitHub release. -# E2e workflows download this artifact instead of compiling from source. +# Publish unsigned quackscale loadable binaries to GitHub Pages (INSTALL FROM …) +# and attach a linux QuackTail tarball (duckdb + extension) to GitHub Releases. +# +# One-time setup: repo Settings → Pages → Build and deployment → Source: GitHub Actions. +# +# Layout after deploy: +# https://quackscience.github.io/duckdb-quackscale/v1.5.3/linux_amd64/quackscale.duckdb_extension.gz +# +# Users: +# SET allow_unsigned_extensions = true; +# INSTALL quackscale FROM 'https://quackscience.github.io/duckdb-quackscale'; +# LOAD quackscale; +# +# Note: deploy-pages replaces the whole site each run (one DuckDB version hosted). name: Release on: release: types: [published] + workflow_dispatch: + inputs: + release_tag: + description: 'Git tag for QuackTail linux tarball (manual runs; optional)' + required: false + type: string + skip_pages: + description: 'Skip GitHub Pages packaging and deploy' + required: false + default: false + type: boolean + skip_tarball: + description: 'Skip QuackTail linux tarball upload' + required: false + default: false + type: boolean -permissions: - contents: write +concurrency: + group: pages + cancel-in-progress: false env: + EXT_NAME: quackscale DUCKDB_VERSION: v1.5.3 RELEASE_ASSET: quacktail-linux-amd64 + PAGES_BASE_URL: https://quackscience.github.io/duckdb-quackscale jobs: - build-linux: - name: Build QuackTail linux amd64 + build: + name: Build extension binaries + uses: duckdb/extension-ci-tools/.github/workflows/_extension_distribution.yml@v1.5-variegata + with: + duckdb_version: v1.5.3 + ci_tools_version: v1.5-variegata + extension_name: quackscale + extra_toolchains: go + exclude_archs: 'windows_amd64;windows_arm64;windows_amd64_mingw;wasm_mvp;wasm_eh;wasm_threads;osx_amd64' + + package-pages: + name: Package extension repository + runs-on: ubuntu-latest + needs: build + if: github.event_name == 'release' || inputs.skip_pages != true + steps: + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + pattern: ${{ env.EXT_NAME }}-${{ env.DUCKDB_VERSION }}-extension-* + + - name: Assemble GitHub Pages tree + shell: bash + run: | + set -euo pipefail + shopt -s nullglob + prefix="${EXT_NAME}-${DUCKDB_VERSION}-extension-" + found=0 + mkdir -p _site + for dir in artifacts/${prefix}*/; do + arch="$(basename "$dir")" + arch="${arch#${prefix}}" + src="${dir}${EXT_NAME}.duckdb_extension" + if [[ ! -f "$src" ]]; then + echo "::warning::no ${EXT_NAME}.duckdb_extension in ${dir}, skipping ${arch}" + continue + fi + out="_site/${DUCKDB_VERSION}/${arch}" + mkdir -p "$out" + cp "$src" work.bin + truncate -s -256 work.bin + dd if=/dev/zero bs=256 count=1 status=none >> work.bin + gzip -n < work.bin > "${out}/${EXT_NAME}.duckdb_extension.gz" + rm -f work.bin + echo "packaged ${arch}" + found=$((found + 1)) + done + if [[ "$found" -eq 0 ]]; then + echo "::error::no extension binaries found to package" + exit 1 + fi + echo "Packaged ${found} platform(s) for ${DUCKDB_VERSION}" + + - name: Write landing page + shell: bash + env: + PAGES_BASE_URL: ${{ env.PAGES_BASE_URL }} + EXT_NAME: ${{ env.EXT_NAME }} + DUCKDB_VERSION: ${{ env.DUCKDB_VERSION }} + run: | + set -euo pipefail + { + echo '' + echo 'quackscale extension repository' + echo '

quackscale

' + echo "

Unsigned DuckDB extension repository. Requires DuckDB ${DUCKDB_VERSION}.

" + echo '
SET allow_unsigned_extensions = true;'
+            echo "INSTALL ${EXT_NAME} FROM '${PAGES_BASE_URL}';"
+            echo "LOAD ${EXT_NAME};
" + echo '

Available binaries

' + } > _site/index.html + + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@v3 + with: + path: _site + + deploy-pages: + name: Deploy to GitHub Pages + runs-on: ubuntu-latest + needs: package-pages + if: github.event_name == 'release' || inputs.skip_pages != true + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + + build-quacktail-bundle: + name: Build QuackTail linux amd64 tarball runs-on: ubuntu-latest timeout-minutes: 90 + if: >- + (github.event_name == 'release') || + (github.event_name == 'workflow_dispatch' && inputs.skip_tarball != true && inputs.release_tag != '') + permissions: + contents: write + env: + RELEASE_TAG: ${{ github.event.release.tag_name || inputs.release_tag }} steps: - uses: actions/checkout@v4 with: - ref: ${{ github.event.release.tag_name }} + ref: ${{ github.event.release.tag_name || inputs.release_tag || github.ref }} submodules: recursive - uses: actions/setup-go@v5 @@ -51,15 +187,15 @@ jobs: cp build/release/extension/quackscale/quackscale.duckdb_extension \ "dist/${RELEASE_ASSET}/extension/quackscale/" { - echo "tag=${{ github.event.release.tag_name }}" + echo "tag=${RELEASE_TAG}" echo "duckdb=${{ env.DUCKDB_VERSION }}" echo "commit=${{ github.sha }}" } > "dist/${RELEASE_ASSET}/VERSION" - tar -czf "dist/${RELEASE_ASSET}-${{ github.event.release.tag_name }}.tar.gz" -C dist "${RELEASE_ASSET}" + tar -czf "dist/${RELEASE_ASSET}-${RELEASE_TAG}.tar.gz" -C dist "${RELEASE_ASSET}" ls -lh dist/ - name: Upload release assets uses: softprops/action-gh-release@v2 with: - tag_name: ${{ github.event.release.tag_name }} + tag_name: ${{ env.RELEASE_TAG }} files: dist/*.tar.gz diff --git a/README.md b/README.md index 26169ec..8cc19f2 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,34 @@ Do **not** copy the random `auth_token` from each `CALL quack_serve`. Use a flee --- +## Install + +QuackScale ships in two forms: a **loadable extension** (stock DuckDB + `INSTALL`) and a **QuackTail release bundle** (prebuilt `duckdb` binary for Linux CI and compose). + +### Loadable extension (GitHub Pages) + +Published on each [release](https://github.com/quackscience/duckdb-quackscale/releases) to a DuckDB custom extension repository. Requires **DuckDB v1.5.3** and unsigned extension support: + +```sql +SET allow_unsigned_extensions = true; +INSTALL quackscale FROM 'https://quackscience.github.io/duckdb-quackscale'; +LOAD quackscale; +``` + +CLI equivalent: `duckdb -unsigned` then `LOAD quackscale;` + +Install [Quack](https://duckdb.org/docs/current/quack/overview) from core separately (`INSTALL quack FROM core; LOAD quack;`) for `quack_serve`, `ATTACH`, and `quack_query`. + +### QuackTail release bundle (GitHub Releases) + +Linux amd64 tarball with `duckdb` and `extension/quackscale/quackscale.duckdb_extension` — used by [Headscale e2e CI](.github/workflows/headscale-e2e.yml) and `examples/` with `BUILD_FROM_SOURCE=0`. Download from [Releases](https://github.com/quackscience/duckdb-quackscale/releases) (`quacktail-linux-amd64-*.tar.gz`). + +### Build from source + +See [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for submodules, Go/libtailscale, and `make release`. + +--- + ## Quick start ### Server diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 82d5a47..13d40bc 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -72,12 +72,28 @@ When bumping the DuckDB target: |----------|---------|---------| | [headscale-e2e.yml](../.github/workflows/headscale-e2e.yml) | **Manual only** | Release-binary two-node e2e (no source build) | | [headscale-integration.yml](../.github/workflows/headscale-integration.yml) | PR | Source build + Headscale smoke | -| [Release.yml](../.github/workflows/Release.yml) | Release published | Build linux release tarball | +| [Release.yml](../.github/workflows/Release.yml) | Release published / manual | Extension repo → GitHub Pages; linux QuackTail tarball → Releases | | [libtailscale-integration.yml](../.github/workflows/libtailscale-integration.yml) | PR | libtailscale `go test` | | [MainDistributionPipeline.yml](../.github/workflows/MainDistributionPipeline.yml) | PR | Extension distribution CI | **E2e never runs on push/PR** and never compiles DuckDB in CI — use `workflow_dispatch` on `headscale-e2e` with a release tag. Full DuckLake compose demo is local dev only (`scripts/ci_compose_e2e.sh`). +### Release and GitHub Pages + +On **Release published** (or manual **Release** workflow): + +1. **build** — extension-ci-tools matrix (`quackscale` per platform, same exclusions as MainDistributionPipeline). +2. **package-pages** + **deploy-pages** — unsigned `.duckdb_extension.gz` under `v1.5.3/{arch}/` at `https://quackscience.github.io/duckdb-quackscale`. +3. **build-quacktail-bundle** — linux amd64 `quacktail-linux-amd64-{tag}.tar.gz` attached to the GitHub Release. + +**One-time repo setup:** Settings → Pages → Build and deployment → **Source: GitHub Actions**. + +**Manual Pages-only test:** Actions → Release → Run workflow → leave `release_tag` empty, uncheck skip_pages. + +**Manual tarball test:** provide an existing git tag in `release_tag`, uncheck skip_tarball. + +Each Pages deploy replaces the whole site (one DuckDB version hosted). To host multiple DuckDB versions, accumulate version directories in a follow-up change. + ## Roadmap (selected) | Item | Status | @@ -88,7 +104,7 @@ When bumping the DuckDB target: | `ATTACH … TYPE quacktail_lake` (Tier 3 native catalog) | Planned | | `ducklake_discover()` enriched discovery | Planned | | `quackscale_serve()` one-call server bootstrap | Planned | -| Community extension descriptor publish | Planned | +| Community extension descriptor publish | Done (GitHub Pages on release) | ## Risks