From ca21ec5e76c4b2212407014990de8675d229ee04 Mon Sep 17 00:00:00 2001 From: George Stagg Date: Mon, 20 Apr 2026 09:52:15 +0100 Subject: [PATCH 1/2] Switch from .dmg to .pkg installation --- .github/workflows/release-packages.yml | 193 ++++++++++++++++++------- doc/get_started/installation.qmd | 4 +- doc/index.qmd | 2 +- ggsql-vscode/src/manager.ts | 3 + 4 files changed, 150 insertions(+), 52 deletions(-) diff --git a/.github/workflows/release-packages.yml b/.github/workflows/release-packages.yml index 70019455..82e91c81 100644 --- a/.github/workflows/release-packages.yml +++ b/.github/workflows/release-packages.yml @@ -122,46 +122,91 @@ jobs: APPLE_API_KEY_BASE64: ${{ secrets.GWS_APPLE_API_KEY_BASE64 }} APPLE_API_KEY: ${{ secrets.GWS_APPLE_API_KEY }} - - name: Configure macOS installer signing + - name: Import signing certificates env: - APPLE_SIGN_IDENTITY: ${{ secrets.GWS_APPLE_SIGN_IDENTITY }} + APPLICATION_P12: ${{ secrets.GWS_APPLE_SIGN_APPLICATION_P12 }} + INSTALLER_P12: ${{ secrets.GWS_APPLE_SIGN_INSTALLER_P12 }} + P12_PASSWORD: ${{ secrets.GWS_APPLE_SIGN_PW }} run: | - cat <> src/Cargo.toml - - [package.metadata.packager.macos] - signing-identity = "${APPLE_SIGN_IDENTITY}" - entitlements = "entitlements.plist" - EOF - - - name: Install cargo-packager - run: cargo install cargo-packager --locked + KEYCHAIN_PATH="$RUNNER_TEMP/signing.keychain-db" + KEYCHAIN_PW="$(openssl rand -hex 32)" + security create-keychain -p "$KEYCHAIN_PW" "$KEYCHAIN_PATH" + security set-keychain-settings "$KEYCHAIN_PATH" + security unlock-keychain -p "$KEYCHAIN_PW" "$KEYCHAIN_PATH" + echo -n "$APPLICATION_P12" | base64 --decode -o "$RUNNER_TEMP/app.p12" + echo -n "$INSTALLER_P12" | base64 --decode -o "$RUNNER_TEMP/inst.p12" + security import "$RUNNER_TEMP/app.p12" -P "$P12_PASSWORD" -k "$KEYCHAIN_PATH" -T /usr/bin/codesign -T /usr/bin/pkgbuild + security import "$RUNNER_TEMP/inst.p12" -P "$P12_PASSWORD" -k "$KEYCHAIN_PATH" -T /usr/bin/codesign -T /usr/bin/pkgbuild + security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PW" "$KEYCHAIN_PATH" + security list-keychains -d user -s "$KEYCHAIN_PATH" $(security list-keychains -d user | tr -d '"') + + - name: Compute version from tag + run: | + VERSION="${GITHUB_REF_NAME#v}" + echo "VERSION=$VERSION" >> "$GITHUB_ENV" - name: Build ggsql binary (x86_64) run: cargo build --release --bin ggsql --bin ggsql-jupyter - - name: Bundle and sign dynamic library dependencies + - name: Bundle dynamic library dependencies run: | - dylibbundler -cd -of -b -x target/release/ggsql -d ./libs/ -p @executable_path/../Resources/libs/ - dylibbundler -cd -of -b -x target/release/ggsql-jupyter -d ./libs/ -p @executable_path/../Resources/libs/ + dylibbundler -cd -of -b -x target/release/ggsql -d ./libs/ -p "@executable_path/../lib/ggsql$VERSION/" + dylibbundler -cd -of -b -x target/release/ggsql-jupyter -d ./libs/ -p "@executable_path/../lib/ggsql$VERSION/" - - name: Ad-hoc sign binaries + - name: Sign binaries and dylibs (Developer ID Application) + env: + SIGN_ID: "Developer ID Application: ${{ secrets.GWS_APPLE_SIGN_IDENTITY }}" run: | - codesign --force --sign - target/release/ggsql - codesign --force --sign - target/release/ggsql-jupyter - - - name: Build DMG installer (x86_64) - run: cargo packager --release --formats dmg + # Sign bundled dylibs first (inside-out), replacing dylibbundler's ad-hoc sigs + find ./libs -type f \( -name "*.dylib" -o -name "*.so" \) -print0 | \ + xargs -0 -I{} codesign --force --options runtime --timestamp --sign "$SIGN_ID" "{}" + # Then sign the executables with hardened runtime + entitlements + codesign --force --options runtime --timestamp \ + --entitlements src/entitlements.plist \ + --sign "$SIGN_ID" target/release/ggsql + codesign --force --options runtime --timestamp \ + --entitlements src/entitlements.plist \ + --sign "$SIGN_ID" target/release/ggsql-jupyter + + - name: Build and notarize PKG installer (x86_64) + # NOTE: --sign uses the Developer ID *Installer* cert (signs .pkg only), + # distinct from the Developer ID Application cert used to sign Mach-O above. env: - APPLE_CERTIFICATE: ${{ secrets.GWS_APPLE_SIGN_P12 }} - APPLE_CERTIFICATE_PASSWORD: ${{ secrets.GWS_APPLE_SIGN_PW }} + SIGN_ID: "Developer ID Installer: ${{ secrets.GWS_APPLE_SIGN_IDENTITY }}" APPLE_API_KEY: ${{ secrets.GWS_APPLE_API_KEY }} APPLE_API_ISSUER: ${{ secrets.GWS_APPLE_API_ISSUER }} - - - name: Upload DMG installer (x86_64) + run: | + PKG_NAME="ggsql_${VERSION}_x86_64.pkg" + mkdir -p pkg-payload/usr/local/bin "pkg-payload/usr/local/lib/ggsql$VERSION" + cp target/release/ggsql pkg-payload/usr/local/bin/ + cp target/release/ggsql-jupyter pkg-payload/usr/local/bin/ + cp -R ./libs/. "pkg-payload/usr/local/lib/ggsql$VERSION/" + mkdir -p pkg-scripts + cat > pkg-scripts/postinstall <> src/Cargo.toml - - [package.metadata.packager.macos] - signing-identity = "${APPLE_SIGN_IDENTITY}" - entitlements = "entitlements.plist" - EOF - - - name: Install cargo-packager - run: cargo install cargo-packager --locked + KEYCHAIN_PATH="$RUNNER_TEMP/signing.keychain-db" + KEYCHAIN_PW="$(openssl rand -hex 32)" + security create-keychain -p "$KEYCHAIN_PW" "$KEYCHAIN_PATH" + security set-keychain-settings "$KEYCHAIN_PATH" + security unlock-keychain -p "$KEYCHAIN_PW" "$KEYCHAIN_PATH" + echo -n "$APPLICATION_P12" | base64 --decode -o "$RUNNER_TEMP/app.p12" + echo -n "$INSTALLER_P12" | base64 --decode -o "$RUNNER_TEMP/inst.p12" + security import "$RUNNER_TEMP/app.p12" -P "$P12_PASSWORD" -k "$KEYCHAIN_PATH" -T /usr/bin/codesign -T /usr/bin/pkgbuild + security import "$RUNNER_TEMP/inst.p12" -P "$P12_PASSWORD" -k "$KEYCHAIN_PATH" -T /usr/bin/codesign -T /usr/bin/pkgbuild + security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PW" "$KEYCHAIN_PATH" + security list-keychains -d user -s "$KEYCHAIN_PATH" $(security list-keychains -d user | tr -d '"') + + - name: Compute version from tag + run: | + VERSION="${GITHUB_REF_NAME#v}" + echo "VERSION=$VERSION" >> "$GITHUB_ENV" - name: Build ggsql binary (aarch64) run: cargo build --release --bin ggsql --bin ggsql-jupyter - - name: Bundle and sign dynamic library dependencies + - name: Bundle dynamic library dependencies run: | - dylibbundler -cd -of -b -x target/release/ggsql -d ./libs/ -p @executable_path/../Resources/libs/ - dylibbundler -cd -of -b -x target/release/ggsql-jupyter -d ./libs/ -p @executable_path/../Resources/libs/ + dylibbundler -cd -of -b -x target/release/ggsql -d ./libs/ -p "@executable_path/../lib/ggsql$VERSION/" + dylibbundler -cd -of -b -x target/release/ggsql-jupyter -d ./libs/ -p "@executable_path/../lib/ggsql$VERSION/" - - name: Build DMG installer (aarch64) - run: cargo packager --release --formats dmg + - name: Sign binaries and dylibs (Developer ID Application) env: - APPLE_CERTIFICATE: ${{ secrets.GWS_APPLE_SIGN_P12 }} - APPLE_CERTIFICATE_PASSWORD: ${{ secrets.GWS_APPLE_SIGN_PW }} + SIGN_ID: "Developer ID Application: ${{ secrets.GWS_APPLE_SIGN_IDENTITY }}" + run: | + # Sign bundled dylibs first (inside-out), replacing dylibbundler's ad-hoc sigs + find ./libs -type f \( -name "*.dylib" -o -name "*.so" \) -print0 | \ + xargs -0 -I{} codesign --force --options runtime --timestamp --sign "$SIGN_ID" "{}" + # Then sign the executables with hardened runtime + entitlements + codesign --force --options runtime --timestamp \ + --entitlements src/entitlements.plist \ + --sign "$SIGN_ID" target/release/ggsql + codesign --force --options runtime --timestamp \ + --entitlements src/entitlements.plist \ + --sign "$SIGN_ID" target/release/ggsql-jupyter + + - name: Build and notarize PKG installer (aarch64) + # NOTE: --sign uses the Developer ID *Installer* cert (signs .pkg only), + # distinct from the Developer ID Application cert used to sign Mach-O above. + env: + SIGN_ID: "Developer ID Installer: ${{ secrets.GWS_APPLE_SIGN_IDENTITY }}" APPLE_API_KEY: ${{ secrets.GWS_APPLE_API_KEY }} APPLE_API_ISSUER: ${{ secrets.GWS_APPLE_API_ISSUER }} - - - name: Upload DMG installer (aarch64) + run: | + PKG_NAME="ggsql_${VERSION}_aarch64.pkg" + mkdir -p pkg-payload/usr/local/bin "pkg-payload/usr/local/lib/ggsql$VERSION" + cp target/release/ggsql pkg-payload/usr/local/bin/ + cp target/release/ggsql-jupyter pkg-payload/usr/local/bin/ + cp -R ./libs/. "pkg-payload/usr/local/lib/ggsql$VERSION/" + mkdir -p pkg-scripts + cat > pkg-scripts/postinstall < Date: Mon, 20 Apr 2026 09:54:17 +0100 Subject: [PATCH 2/2] Bump to version 0.2.7 --- Cargo.lock | 10 +++++----- Cargo.toml | 6 +++--- ggsql-jupyter/pyproject.toml | 2 +- ggsql-python/Cargo.toml | 2 +- ggsql-python/pyproject.toml | 2 +- ggsql-python/python/ggsql/__init__.py | 2 +- ggsql-vscode/CHANGELOG.md | 6 ++++++ ggsql-vscode/package-lock.json | 4 ++-- ggsql-vscode/package.json | 2 +- ggsql-wasm/demo/package-lock.json | 2 +- tree-sitter-ggsql/bindings/python/__init__.py | 2 +- tree-sitter-ggsql/package.json | 2 +- tree-sitter-ggsql/pyproject.toml | 2 +- tree-sitter-ggsql/tree-sitter.json | 2 +- 14 files changed, 26 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 57b3f9af..58c2e948 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1791,7 +1791,7 @@ dependencies = [ [[package]] name = "ggsql" -version = "0.2.6" +version = "0.2.7" dependencies = [ "anyhow", "arrow", @@ -1826,7 +1826,7 @@ dependencies = [ [[package]] name = "ggsql-jupyter" -version = "0.2.6" +version = "0.2.7" dependencies = [ "anyhow", "bytes", @@ -1851,7 +1851,7 @@ dependencies = [ [[package]] name = "ggsql-python" -version = "0.2.6" +version = "0.2.7" dependencies = [ "ggsql", "polars", @@ -1860,7 +1860,7 @@ dependencies = [ [[package]] name = "ggsql-wasm" -version = "0.2.6" +version = "0.2.7" dependencies = [ "csv", "ggsql", @@ -5822,7 +5822,7 @@ dependencies = [ [[package]] name = "tree-sitter-ggsql" -version = "0.2.6" +version = "0.2.7" dependencies = [ "cc", "tree-sitter", diff --git a/Cargo.toml b/Cargo.toml index 5d52275d..f4305baf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ default-members = [ resolver = "2" [workspace.package] -version = "0.2.6" +version = "0.2.7" edition = "2021" authors = ["ggsql Team"] license = "MIT" @@ -26,8 +26,8 @@ description = "A declarative visualization language that extends SQL with powerf [workspace.dependencies] # workspace packages -tree-sitter-ggsql = { path = "tree-sitter-ggsql", version = "0.2.6" } -ggsql = { path = "src", version = "0.2.6" } +tree-sitter-ggsql = { path = "tree-sitter-ggsql", version = "0.2.7" } +ggsql = { path = "src", version = "0.2.7" } # Parsing csscolorparser = "0.8.1" diff --git a/ggsql-jupyter/pyproject.toml b/ggsql-jupyter/pyproject.toml index 3da5355e..dc05f2ac 100644 --- a/ggsql-jupyter/pyproject.toml +++ b/ggsql-jupyter/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "maturin" [project] name = "ggsql-jupyter" -version = "0.2.6" +version = "0.2.7" description = "Jupyter kernel for ggsql - SQL extension for declarative data visualization" readme = "README.md" license = { text = "MIT" } diff --git a/ggsql-python/Cargo.toml b/ggsql-python/Cargo.toml index 1619eadb..d7381cd3 100644 --- a/ggsql-python/Cargo.toml +++ b/ggsql-python/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ggsql-python" -version = "0.2.6" +version = "0.2.7" edition = "2021" authors.workspace = true license.workspace = true diff --git a/ggsql-python/pyproject.toml b/ggsql-python/pyproject.toml index e38dfdd6..00e24b8c 100644 --- a/ggsql-python/pyproject.toml +++ b/ggsql-python/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "maturin" [project] name = "ggsql" -version = "0.2.6" +version = "0.2.7" description = "SQL extension for declarative data visualization" readme = "README.md" requires-python = ">=3.10" diff --git a/ggsql-python/python/ggsql/__init__.py b/ggsql-python/python/ggsql/__init__.py index 8d8caf2d..9b20a565 100644 --- a/ggsql-python/python/ggsql/__init__.py +++ b/ggsql-python/python/ggsql/__init__.py @@ -27,7 +27,7 @@ "execute", "render_altair", ] -__version__ = "0.2.6" +__version__ = "0.2.7" # Type alias for any Altair chart type AltairChart = Union[ diff --git a/ggsql-vscode/CHANGELOG.md b/ggsql-vscode/CHANGELOG.md index ef9bf01d..f90ceed8 100644 --- a/ggsql-vscode/CHANGELOG.md +++ b/ggsql-vscode/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 0.2.7 + +Alpha release. + +- Switch macOS installer from .dmg to .pkg + ## 0.2.6 Alpha release. diff --git a/ggsql-vscode/package-lock.json b/ggsql-vscode/package-lock.json index c2f7ce0d..3bdc77ab 100644 --- a/ggsql-vscode/package-lock.json +++ b/ggsql-vscode/package-lock.json @@ -1,12 +1,12 @@ { "name": "ggsql", - "version": "0.2.6", + "version": "0.2.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ggsql", - "version": "0.2.6", + "version": "0.2.7", "license": "MIT", "dependencies": { "toml": "^3.0.0" diff --git a/ggsql-vscode/package.json b/ggsql-vscode/package.json index b8510582..f1df3f6e 100644 --- a/ggsql-vscode/package.json +++ b/ggsql-vscode/package.json @@ -2,7 +2,7 @@ "name": "ggsql", "displayName": "ggsql", "description": "Syntax highlighting and language runtime for ggsql - SQL with declarative visualization", - "version": "0.2.6", + "version": "0.2.7", "publisher": "ggsql", "engines": { "vscode": "^1.75.0" diff --git a/ggsql-wasm/demo/package-lock.json b/ggsql-wasm/demo/package-lock.json index 5878685d..cab508ab 100644 --- a/ggsql-wasm/demo/package-lock.json +++ b/ggsql-wasm/demo/package-lock.json @@ -24,7 +24,7 @@ }, "../pkg": { "name": "ggsql-wasm", - "version": "0.2.6", + "version": "0.2.7", "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { diff --git a/tree-sitter-ggsql/bindings/python/__init__.py b/tree-sitter-ggsql/bindings/python/__init__.py index 9a6c7679..800d2fe1 100644 --- a/tree-sitter-ggsql/bindings/python/__init__.py +++ b/tree-sitter-ggsql/bindings/python/__init__.py @@ -31,5 +31,5 @@ except Exception as e: raise ImportError(f"Could not load tree-sitter-ggsql language: {e}") -__version__ = "0.2.6" +__version__ = "0.2.7" __all__ = ["language"] diff --git a/tree-sitter-ggsql/package.json b/tree-sitter-ggsql/package.json index fc759aa6..d6bcd197 100644 --- a/tree-sitter-ggsql/package.json +++ b/tree-sitter-ggsql/package.json @@ -1,6 +1,6 @@ { "name": "tree-sitter-ggsql", - "version": "0.2.6", + "version": "0.2.7", "description": "Tree-sitter grammar for ggsql visualization language", "main": "bindings/node", "repository": { diff --git a/tree-sitter-ggsql/pyproject.toml b/tree-sitter-ggsql/pyproject.toml index f7a8625d..c0cfe31c 100644 --- a/tree-sitter-ggsql/pyproject.toml +++ b/tree-sitter-ggsql/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "tree-sitter-ggsql" -version = "0.2.6" +version = "0.2.7" description = "Tree-sitter grammar for ggsql visualization language" readme = "README.md" license = {text = "MIT"} diff --git a/tree-sitter-ggsql/tree-sitter.json b/tree-sitter-ggsql/tree-sitter.json index 1d9cd3c8..1baced6e 100644 --- a/tree-sitter-ggsql/tree-sitter.json +++ b/tree-sitter-ggsql/tree-sitter.json @@ -14,7 +14,7 @@ } ], "metadata": { - "version": "0.2.6", + "version": "0.2.7", "license": "MIT", "description": "ggsql grammar for tree-sitter", "authors": [