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
38 changes: 38 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,44 @@ jobs:
path: dist/sql.html
retention-days: 14

# Release-bundle smoke test: assemble the curl|sh artifact, extract it, and boot
# the zero-dep Python runner exactly as an end user would — proving the bundle
# layout, the SPA-path discovery, and config.json generation all work before a
# tag ever cuts a real release.
bundle:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: npm install --no-audit --no-fund
- name: Build release bundle
run: build/bundle.sh
- name: Extract + boot the runner (as a user would)
run: |
set -euo pipefail
tmp=$(mktemp -d)
tar -C "$tmp" -xzf dist/altinity-sql-browser.tar.gz --strip-components=1
for f in sql.html local.py sql-browser.xml run.sh VERSION; do
test -f "$tmp/$f" || { echo "missing $f in bundle" >&2; exit 1; }
done
python3 -c "import ast,sys; ast.parse(open(sys.argv[1]).read())" "$tmp/local.py"
# No LOCAL_CH_CONFIG: the runner discovers the bundled sql-browser.xml
# next to local.py, proving the merge/discovery path end to end.
# SQL_BROWSER_PROBE=0: don't depend on reaching external demo hosts from CI.
SQL_BROWSER_PROBE=0 PORT=8901 "$tmp/run.sh" &
pid=$!
for i in $(seq 1 20); do curl -fsS "http://localhost:8901/sql" >/dev/null 2>&1 && break; sleep 0.5; done
curl -fsS "http://localhost:8901/sql" >/dev/null
curl -fsS "http://localhost:8901/config.json" \
| python3 -c "import sys,json; assert json.load(sys.stdin)['hosts'], 'no hosts parsed'"
kill "$pid"
- name: Lint the installer (shellcheck)
run: |
sudo apt-get update -qq && sudo apt-get install -y -qq shellcheck
shellcheck install.sh build/bundle.sh

# Real-browser regression tests (Playwright). Runs on Linux runners where the
# Gecko/Chromium binaries launch normally — separate from the unit suite so a
# missing browser binary can't mask a unit failure, and vice versa. The
Expand Down
33 changes: 33 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: release

# Cut a release by pushing a tag, e.g.: git tag v0.1.0 && git push origin v0.1.0
on:
push:
tags: ['v*']

permissions:
contents: write # create the GitHub Release + upload assets

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: npm install --no-audit --no-fund
- name: Test (coverage gate)
run: npm test
- name: Build release bundle
run: build/bundle.sh "${GITHUB_REF_NAME#v}"
- name: Create GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "$GITHUB_REF_NAME" \
--title "$GITHUB_REF_NAME" \
--generate-notes \
dist/altinity-sql-browser.tar.gz \
dist/altinity-sql-browser.tar.gz.sha256 \
dist/sql.html
41 changes: 40 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,31 @@ npm run dev # build + serve dist/ at http://localhost:8900

### Run locally against your own ClickHouse

`npm run local` builds the SPA and serves it as a static page on localhost:
**Install (no clone, no Node — just `python3`):**

```bash
curl -fsSL https://raw.githubusercontent.com/Altinity/altinity-sql-browser/main/install.sh | sh
altinity-sql-browser # serve → open http://localhost:8900/sql
```

This downloads the latest [release](https://github.com/Altinity/altinity-sql-browser/releases)
bundle (the prebuilt single-file SPA + the zero-dependency Python runner) into
`~/.altinity-sql-browser` and installs a launcher in `~/.local/bin`. Overrides:
`ASB_VERSION` (tag to install), `ASB_HOME`, `ASB_BIN`.

The installer also writes a sample **`~/.clickhouse-client/sql-browser.xml`** (a few
public demo clusters) — under a separate name, so it **never replaces your real
`config.xml`**. The runner **merges** connections from both files (your `config.xml`
wins on a name clash), so a fresh machine has something to connect to immediately.
The picker uses `<http_port>` if set; otherwise, since a cluster may serve the
HTTP interface on either port, at startup the runner **probes both standard ports**
(`443` then `8443` for secure, `8123` then `80` for plain) and uses whichever
answers `Ok.` on `/ping`. The native `<port>` (9440/9000) is never used — it's a
different interface. The probe **prints a reachability table** and skips any host
with no HTTP interface on any port (e.g. a native-only endpoint) so it isn't a dead
pick. Set `SQL_BROWSER_PROBE=0` to skip probing and keep all hosts (`8443`/`8123`).

**From a checkout** (also builds the SPA, needs Node):

```bash
npm run local # build + serve → open http://localhost:8900/sql
Expand Down Expand Up @@ -414,6 +438,21 @@ The harness (`tests/e2e/`) serves the repo over HTTP and imports the actual
source as native ESM — no bundling, always current. It is **not** part of
`npm test` or the coverage gate.

## Releasing

Releases are cut by pushing a version tag — `.github/workflows/release.yml` then
runs the coverage gate, assembles the bundle, and publishes a GitHub Release:

```bash
git tag v0.1.0 && git push origin v0.1.0
```

The release attaches `altinity-sql-browser.tar.gz` (+ `.sha256`) and the raw
`sql.html`. The bundle is built by `build/bundle.sh` (also runnable locally), and
every PR smoke-tests it in CI (`bundle` job: extract → boot the runner → fetch
`/sql` + `/config.json`). The `curl | sh` `install.sh` resolves the latest tag and
installs that artifact.

## License

Apache-2.0.
69 changes: 69 additions & 0 deletions build/bundle.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/usr/bin/env bash
# Assemble the release bundle for the local runner:
# dist/altinity-sql-browser.tar.gz (+ .sha256)
#
# Contents (under a single top dir so `tar --strip-components=1` is clean):
# altinity-sql-browser/
# sql.html — the prebuilt single-file SPA
# local.py — the zero-dep Python runner (serves SPA + config.json)
# sql-browser.xml — sample public-demo connections (merged with the
# user's ~/.clickhouse-client/config.xml by the runner)
# run.sh — self-resolving launcher (python3 local.py)
# VERSION
# README.txt
#
# Builds the SPA first. Used by .github/workflows/release.yml and runnable
# locally. Pass a version as $1, else it's read from package.json.
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
VERSION="${1:-$(node -p "require('$ROOT/package.json').version")}"
OUT="$ROOT/dist"
STAGE="$OUT/bundle/altinity-sql-browser"

echo "==> Building SPA"
node "$ROOT/build/build.mjs"

echo "==> Staging bundle ($VERSION)"
rm -rf "$OUT/bundle"
mkdir -p "$STAGE"
cp "$OUT/sql.html" "$STAGE/sql.html"
cp "$ROOT/build/local.py" "$STAGE/local.py"
cp "$ROOT/deploy/sql-browser.xml" "$STAGE/sql-browser.xml"
printf '%s\n' "$VERSION" > "$STAGE/VERSION"

cat > "$STAGE/run.sh" <<'EOF'
#!/bin/sh
# Launch the Altinity SQL Browser local runner. Serves the bundled sql.html and a
# config.json generated from your ~/.clickhouse-client/config.xml.
# PORT=8900 LOCAL_CH_CONFIG=~/.clickhouse-client/config.xml ./run.sh
DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
exec python3 "$DIR/local.py" "$@"
EOF
chmod +x "$STAGE/run.sh"

cat > "$STAGE/README.txt" <<'EOF'
Altinity SQL Browser — local runner
===================================

Requires only python3 (preinstalled on macOS/Linux).

./run.sh # serve http://localhost:8900/sql

It merges connections from your ~/.clickhouse-client/config.xml and the bundled
sql-browser.xml (public demos) and offers each in the login picker — your own
config wins on a name clash. Run ./install.sh (curl|sh) to also copy
sql-browser.xml into ~/.clickhouse-client/.

Env: PORT (default 8900), LOCAL_CH_CONFIG (override with one explicit file),
SQL_BROWSER_SPA.

Source & docs: https://github.com/Altinity/altinity-sql-browser
EOF

echo "==> Archiving"
TARBALL="altinity-sql-browser.tar.gz"
tar -C "$OUT/bundle" -czf "$OUT/$TARBALL" altinity-sql-browser
( cd "$OUT" && { sha256sum "$TARBALL" 2>/dev/null || shasum -a 256 "$TARBALL"; } > "$TARBALL.sha256" )
echo " $OUT/$TARBALL"
echo " $OUT/$TARBALL.sha256"
Loading
Loading