|
1 | | -# Build a Linux DuckDB binary with quackscale embedded and attach it to the GitHub release. |
2 | | -# E2e workflows download this artifact instead of compiling from source. |
| 1 | +# Publish unsigned quackscale loadable binaries to GitHub Pages (INSTALL FROM …) |
| 2 | +# and attach a linux QuackTail tarball (duckdb + extension) to GitHub Releases. |
| 3 | +# |
| 4 | +# One-time setup: repo Settings → Pages → Build and deployment → Source: GitHub Actions. |
| 5 | +# |
| 6 | +# Layout after deploy: |
| 7 | +# https://quackscience.github.io/duckdb-quackscale/v1.5.3/linux_amd64/quackscale.duckdb_extension.gz |
| 8 | +# |
| 9 | +# Users: |
| 10 | +# SET allow_unsigned_extensions = true; |
| 11 | +# INSTALL quackscale FROM 'https://quackscience.github.io/duckdb-quackscale'; |
| 12 | +# LOAD quackscale; |
| 13 | +# |
| 14 | +# Note: deploy-pages replaces the whole site each run (one DuckDB version hosted). |
3 | 15 | name: Release |
4 | 16 |
|
5 | 17 | on: |
6 | 18 | release: |
7 | 19 | types: [published] |
| 20 | + workflow_dispatch: |
| 21 | + inputs: |
| 22 | + release_tag: |
| 23 | + description: 'Git tag for QuackTail linux tarball (manual runs; optional)' |
| 24 | + required: false |
| 25 | + type: string |
| 26 | + skip_pages: |
| 27 | + description: 'Skip GitHub Pages packaging and deploy' |
| 28 | + required: false |
| 29 | + default: false |
| 30 | + type: boolean |
| 31 | + skip_tarball: |
| 32 | + description: 'Skip QuackTail linux tarball upload' |
| 33 | + required: false |
| 34 | + default: false |
| 35 | + type: boolean |
8 | 36 |
|
9 | | -permissions: |
10 | | - contents: write |
| 37 | +concurrency: |
| 38 | + group: pages |
| 39 | + cancel-in-progress: false |
11 | 40 |
|
12 | 41 | env: |
| 42 | + EXT_NAME: quackscale |
13 | 43 | DUCKDB_VERSION: v1.5.3 |
14 | 44 | RELEASE_ASSET: quacktail-linux-amd64 |
| 45 | + PAGES_BASE_URL: https://quackscience.github.io/duckdb-quackscale |
15 | 46 |
|
16 | 47 | jobs: |
17 | | - build-linux: |
18 | | - name: Build QuackTail linux amd64 |
| 48 | + build: |
| 49 | + name: Build extension binaries |
| 50 | + uses: duckdb/extension-ci-tools/.github/workflows/_extension_distribution.yml@v1.5-variegata |
| 51 | + with: |
| 52 | + duckdb_version: v1.5.3 |
| 53 | + ci_tools_version: v1.5-variegata |
| 54 | + extension_name: quackscale |
| 55 | + extra_toolchains: go |
| 56 | + exclude_archs: 'windows_amd64;windows_arm64;windows_amd64_mingw;wasm_mvp;wasm_eh;wasm_threads;osx_amd64' |
| 57 | + |
| 58 | + package-pages: |
| 59 | + name: Package extension repository |
| 60 | + runs-on: ubuntu-latest |
| 61 | + needs: build |
| 62 | + if: github.event_name == 'release' || inputs.skip_pages != true |
| 63 | + steps: |
| 64 | + - name: Download build artifacts |
| 65 | + uses: actions/download-artifact@v4 |
| 66 | + with: |
| 67 | + path: artifacts |
| 68 | + pattern: ${{ env.EXT_NAME }}-${{ env.DUCKDB_VERSION }}-extension-* |
| 69 | + |
| 70 | + - name: Assemble GitHub Pages tree |
| 71 | + shell: bash |
| 72 | + run: | |
| 73 | + set -euo pipefail |
| 74 | + shopt -s nullglob |
| 75 | + prefix="${EXT_NAME}-${DUCKDB_VERSION}-extension-" |
| 76 | + found=0 |
| 77 | + mkdir -p _site |
| 78 | + for dir in artifacts/${prefix}*/; do |
| 79 | + arch="$(basename "$dir")" |
| 80 | + arch="${arch#${prefix}}" |
| 81 | + src="${dir}${EXT_NAME}.duckdb_extension" |
| 82 | + if [[ ! -f "$src" ]]; then |
| 83 | + echo "::warning::no ${EXT_NAME}.duckdb_extension in ${dir}, skipping ${arch}" |
| 84 | + continue |
| 85 | + fi |
| 86 | + out="_site/${DUCKDB_VERSION}/${arch}" |
| 87 | + mkdir -p "$out" |
| 88 | + cp "$src" work.bin |
| 89 | + truncate -s -256 work.bin |
| 90 | + dd if=/dev/zero bs=256 count=1 status=none >> work.bin |
| 91 | + gzip -n < work.bin > "${out}/${EXT_NAME}.duckdb_extension.gz" |
| 92 | + rm -f work.bin |
| 93 | + echo "packaged ${arch}" |
| 94 | + found=$((found + 1)) |
| 95 | + done |
| 96 | + if [[ "$found" -eq 0 ]]; then |
| 97 | + echo "::error::no extension binaries found to package" |
| 98 | + exit 1 |
| 99 | + fi |
| 100 | + echo "Packaged ${found} platform(s) for ${DUCKDB_VERSION}" |
| 101 | +
|
| 102 | + - name: Write landing page |
| 103 | + shell: bash |
| 104 | + env: |
| 105 | + PAGES_BASE_URL: ${{ env.PAGES_BASE_URL }} |
| 106 | + EXT_NAME: ${{ env.EXT_NAME }} |
| 107 | + DUCKDB_VERSION: ${{ env.DUCKDB_VERSION }} |
| 108 | + run: | |
| 109 | + set -euo pipefail |
| 110 | + { |
| 111 | + echo '<!DOCTYPE html>' |
| 112 | + echo '<html lang="en"><head><meta charset="utf-8"><title>quackscale extension repository</title></head><body>' |
| 113 | + echo '<h1>quackscale</h1>' |
| 114 | + echo "<p>Unsigned DuckDB extension repository. Requires DuckDB ${DUCKDB_VERSION}.</p>" |
| 115 | + echo '<pre>SET allow_unsigned_extensions = true;' |
| 116 | + echo "INSTALL ${EXT_NAME} FROM '${PAGES_BASE_URL}';" |
| 117 | + echo "LOAD ${EXT_NAME};</pre>" |
| 118 | + echo '<h2>Available binaries</h2><ul>' |
| 119 | + while IFS= read -r rel; do |
| 120 | + echo " <li><a href=\"${rel}\">${rel}</a></li>" |
| 121 | + done < <(cd _site && find . -name '*.duckdb_extension.gz' | sort | sed 's|^\./||') |
| 122 | + echo '</ul></body></html>' |
| 123 | + } > _site/index.html |
| 124 | +
|
| 125 | + - name: Upload Pages artifact |
| 126 | + uses: actions/upload-pages-artifact@v3 |
| 127 | + with: |
| 128 | + path: _site |
| 129 | + |
| 130 | + deploy-pages: |
| 131 | + name: Deploy to GitHub Pages |
| 132 | + runs-on: ubuntu-latest |
| 133 | + needs: package-pages |
| 134 | + if: github.event_name == 'release' || inputs.skip_pages != true |
| 135 | + permissions: |
| 136 | + pages: write |
| 137 | + id-token: write |
| 138 | + environment: |
| 139 | + name: github-pages |
| 140 | + url: ${{ steps.deployment.outputs.page_url }} |
| 141 | + steps: |
| 142 | + - name: Deploy to GitHub Pages |
| 143 | + id: deployment |
| 144 | + uses: actions/deploy-pages@v4 |
| 145 | + |
| 146 | + build-quacktail-bundle: |
| 147 | + name: Build QuackTail linux amd64 tarball |
19 | 148 | runs-on: ubuntu-latest |
20 | 149 | timeout-minutes: 90 |
| 150 | + if: >- |
| 151 | + (github.event_name == 'release') || |
| 152 | + (github.event_name == 'workflow_dispatch' && inputs.skip_tarball != true && inputs.release_tag != '') |
| 153 | + permissions: |
| 154 | + contents: write |
| 155 | + env: |
| 156 | + RELEASE_TAG: ${{ github.event.release.tag_name || inputs.release_tag }} |
21 | 157 |
|
22 | 158 | steps: |
23 | 159 | - uses: actions/checkout@v4 |
24 | 160 | with: |
25 | | - ref: ${{ github.event.release.tag_name }} |
| 161 | + ref: ${{ github.event.release.tag_name || inputs.release_tag || github.ref }} |
26 | 162 | submodules: recursive |
27 | 163 |
|
28 | 164 | - uses: actions/setup-go@v5 |
@@ -51,15 +187,15 @@ jobs: |
51 | 187 | cp build/release/extension/quackscale/quackscale.duckdb_extension \ |
52 | 188 | "dist/${RELEASE_ASSET}/extension/quackscale/" |
53 | 189 | { |
54 | | - echo "tag=${{ github.event.release.tag_name }}" |
| 190 | + echo "tag=${RELEASE_TAG}" |
55 | 191 | echo "duckdb=${{ env.DUCKDB_VERSION }}" |
56 | 192 | echo "commit=${{ github.sha }}" |
57 | 193 | } > "dist/${RELEASE_ASSET}/VERSION" |
58 | | - tar -czf "dist/${RELEASE_ASSET}-${{ github.event.release.tag_name }}.tar.gz" -C dist "${RELEASE_ASSET}" |
| 194 | + tar -czf "dist/${RELEASE_ASSET}-${RELEASE_TAG}.tar.gz" -C dist "${RELEASE_ASSET}" |
59 | 195 | ls -lh dist/ |
60 | 196 |
|
61 | 197 | - name: Upload release assets |
62 | 198 | uses: softprops/action-gh-release@v2 |
63 | 199 | with: |
64 | | - tag_name: ${{ github.event.release.tag_name }} |
| 200 | + tag_name: ${{ env.RELEASE_TAG }} |
65 | 201 | files: dist/*.tar.gz |
0 commit comments