Git of record moves to git.hanzo.ai; GitHub becomes a mirror.
- .gitea/workflows/{ci,publish}.yml — native pipeline on hanzo-build-linux-amd64
act_runners. publish.yml pulls Chrome Web Store + Firefox AMO + npm creds from
KMS via the machine identity (no store cred in any Actions secret store).
- deploy/kms/extension-publish-kms-sync.yaml — KMSSecret CR; canonical KMS path
hanzo:/extension-publish (env prod) for the store creds.
- .github/workflows/sync.yml — mirror main+tags to git.hanzo.ai (the only thing
GitHub does as system of record; no-op until HANZO_GIT_TOKEN seeded).
- .github/workflows/publish.yml — remove store-publish steps (CWS/AMO/VSCE/OVSX/
JetBrains — all no-ops today, those secrets never existed on GitHub). Keep the
live npm publish (interim) + the downloadable GitHub Release.
- docs: PUBLISHING.md + LLM.md rewritten to the native topology.
Non-breaking: npm publish (@hanzo/browser-extension) untouched. No store publish
in this pass. Gated on operator: seed KMS store values, Gitea secrets, mirror.
693 lines
29 KiB
YAML
693 lines
29 KiB
YAML
name: Publish
|
|
|
|
# Store-publish (Chrome Web Store, Firefox AMO, VS Code, Open VSX, JetBrains) and
|
|
# every store credential have moved to the native pipeline on Hanzo Git:
|
|
# .gitea/workflows/publish.yml — reads creds from KMS (deploy/kms/…), NOT GitHub.
|
|
# GitHub retains only: build + the downloadable GitHub Release (mirror
|
|
# distribution), and the live npm publish (interim — migrates to native once the
|
|
# KMS NPM_TOKEN is seeded and the native run is verified green).
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'v*'
|
|
release:
|
|
types: [published]
|
|
workflow_dispatch:
|
|
inputs:
|
|
version:
|
|
description: 'Version to publish (e.g., 1.7.18)'
|
|
required: true
|
|
type: string
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
jobs:
|
|
# ─── npm publish gate (the one store credential still on GitHub) ───
|
|
secrets:
|
|
name: Check npm token
|
|
runs-on: hanzo-build-linux-amd64
|
|
outputs:
|
|
has-npm: ${{ steps.check.outputs.has-npm }}
|
|
steps:
|
|
- name: Check npm token
|
|
id: check
|
|
run: echo "has-npm=${{ secrets.NPM_TOKEN != '' }}" >> $GITHUB_OUTPUT
|
|
|
|
# ─── Chrome + Firefox ───
|
|
browser:
|
|
name: Chrome + Firefox
|
|
runs-on: hanzo-build-linux-amd64
|
|
needs: secrets
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: pnpm/action-setup@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22'
|
|
cache: 'pnpm'
|
|
- run: pnpm install --frozen-lockfile
|
|
|
|
- name: Build
|
|
working-directory: packages/browser
|
|
run: node src/build.js
|
|
|
|
- name: Package
|
|
working-directory: packages/browser
|
|
run: |
|
|
# web-ext (already used for linting below) does the zipping — the
|
|
# arc runner image has no `zip` binary. The old `zip -r ../../../…`
|
|
# also escaped dist/, so the artifact globs and the store upload
|
|
# never saw the files. The Safari bundle comes from the dedicated
|
|
# macOS job — the Linux build has no Xcode and emits no safari
|
|
# manifest, so packaging it here would ship junk.
|
|
VERSION=$(node -p "require('./package.json').version")
|
|
npx web-ext build --source-dir dist/browser-extension/chrome --artifacts-dir dist --filename hanzo-ai-chrome-v${VERSION}.zip --overwrite-dest
|
|
npx web-ext build --source-dir dist/browser-extension/firefox --artifacts-dir dist --filename hanzo-ai-firefox-v${VERSION}.zip --overwrite-dest
|
|
# Edge uses the Chrome zip (Chromium-compatible)
|
|
cp dist/hanzo-ai-chrome-v${VERSION}.zip dist/hanzo-ai-edge-v${VERSION}.zip
|
|
|
|
- name: Upload browser zips
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: hanzo-ai-browser
|
|
path: |
|
|
packages/browser/dist/hanzo-ai-chrome-v*.zip
|
|
packages/browser/dist/hanzo-ai-edge-v*.zip
|
|
packages/browser/dist/hanzo-ai-firefox-v*.zip
|
|
|
|
- name: Lint Firefox
|
|
working-directory: packages/browser
|
|
run: npx web-ext lint --source-dir dist/browser-extension/firefox
|
|
continue-on-error: true
|
|
|
|
# ─── Safari (macOS + iOS) ───
|
|
safari:
|
|
name: Safari (macOS + iOS)
|
|
runs-on: macos-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: pnpm/action-setup@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22'
|
|
cache: 'pnpm'
|
|
- run: pnpm install --frozen-lockfile
|
|
|
|
- name: Build
|
|
working-directory: packages/browser
|
|
run: node src/build.js
|
|
|
|
- name: Build Safari macOS
|
|
working-directory: packages/browser
|
|
run: |
|
|
xcodebuild -project "dist/safari/Hanzo AI/Hanzo AI.xcodeproj" \
|
|
-scheme "Hanzo AI (macOS)" -configuration Release \
|
|
CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO \
|
|
-derivedDataPath dist/safari-build-macos
|
|
continue-on-error: true
|
|
|
|
- name: Build Safari iOS
|
|
working-directory: packages/browser
|
|
run: |
|
|
xcodebuild -project "dist/safari/Hanzo AI/Hanzo AI.xcodeproj" \
|
|
-scheme "Hanzo AI (iOS)" -configuration Release \
|
|
-sdk iphoneos \
|
|
CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO \
|
|
-derivedDataPath dist/safari-build-ios
|
|
continue-on-error: true
|
|
|
|
# Package the built .app(s) so the GitHub Release Safari link resolves — the
|
|
# unsigned bundle a developer sideloads (source + built products).
|
|
- name: Package Safari for release
|
|
working-directory: packages/browser
|
|
run: |
|
|
VERSION=${GITHUB_REF_NAME#v}
|
|
cd dist
|
|
# Zip the whole Safari output tree: the Xcode project (build.js always
|
|
# emits dist/safari — a developer opens it to build+sign+sideload) plus any
|
|
# built .app products. Guard so a `zip` exit code (e.g. 12 "nothing to do")
|
|
# never blanks the release asset; only skip if there is genuinely nothing.
|
|
TARGETS=$(ls -d safari safari-build-macos safari-build-ios 2>/dev/null || true)
|
|
if [ -n "$TARGETS" ]; then
|
|
zip -r -y "/tmp/hanzo-ai-safari-v${VERSION}.zip" $TARGETS || true
|
|
fi
|
|
ls -la /tmp/hanzo-ai-safari-v*.zip 2>/dev/null || echo "no Safari output produced"
|
|
continue-on-error: true
|
|
|
|
- name: Upload Safari bundle
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: hanzo-ai-safari
|
|
path: /tmp/hanzo-ai-safari-v*.zip
|
|
continue-on-error: true
|
|
|
|
# ─── VS Code + Cursor + Windsurf + Antigravity + Open VSX ───
|
|
vscode:
|
|
name: VS Code Marketplace
|
|
runs-on: hanzo-build-linux-amd64
|
|
needs: secrets
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: pnpm/action-setup@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22'
|
|
cache: 'pnpm'
|
|
- run: pnpm install --frozen-lockfile
|
|
- run: npm i -g @vscode/vsce ovsx
|
|
|
|
- name: Build
|
|
working-directory: packages/vscode
|
|
run: |
|
|
node scripts/compile-main.js || true
|
|
npm run build:mcp
|
|
|
|
- name: Package VSIX
|
|
working-directory: packages/vscode
|
|
run: vsce package --no-dependencies
|
|
|
|
- name: Package DXT
|
|
working-directory: packages/vscode
|
|
run: npm run package:dxt
|
|
|
|
- name: Prepare release artifacts
|
|
working-directory: packages/vscode
|
|
run: |
|
|
VERSION=$(node -p "require('./package.json').version")
|
|
mkdir -p release-assets
|
|
# VS Code / Cursor / Windsurf / Antigravity are identical VSIX, named per IDE
|
|
VSIX=$(ls *.vsix | head -1)
|
|
cp "$VSIX" "release-assets/hanzo-ai-vscode-v${VERSION}.vsix"
|
|
cp "$VSIX" "release-assets/hanzo-ai-cursor-v${VERSION}.vsix"
|
|
cp "$VSIX" "release-assets/hanzo-ai-windsurf-v${VERSION}.vsix"
|
|
cp "$VSIX" "release-assets/hanzo-ai-antigravity-v${VERSION}.vsix"
|
|
# DXT for Claude Code/Desktop
|
|
cp dist/hanzoai-${VERSION}.dxt "release-assets/hanzo-ai-claude-v${VERSION}.dxt" || true
|
|
|
|
- name: Upload IDE artifacts
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: hanzo-ai-ide
|
|
path: packages/vscode/release-assets/*
|
|
|
|
# ─── npm (all @hanzo/* workspace packages) ───
|
|
npm:
|
|
name: npm
|
|
runs-on: hanzo-build-linux-amd64
|
|
needs: secrets
|
|
if: needs.secrets.outputs.has-npm == 'true'
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: pnpm/action-setup@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22'
|
|
cache: 'pnpm'
|
|
registry-url: 'https://registry.npmjs.org'
|
|
- run: pnpm install --frozen-lockfile
|
|
|
|
# Shared libraries first: their consumers (slack, teams) import the built
|
|
# dist at publish time, so @hanzo/cards must exist before the rest build.
|
|
- name: Build shared libraries
|
|
run: pnpm --filter @hanzo/cards build
|
|
|
|
# Build everything with a build script. Guarded with `|| true` so a package
|
|
# whose toolchain is absent on the runner (jupyter→jupyterlab, desktop→cargo)
|
|
# cannot abort the publish of the rest.
|
|
- name: Build all packages
|
|
run: pnpm -r --if-present run build || true
|
|
|
|
# Recursive publish: skips private (root, apps/site), skips versions already
|
|
# on npm (e.g. @hanzo/mcp), rewrites workspace:* → the real version, and
|
|
# publishes in topological order so @hanzo/cards lands before its consumers.
|
|
# --ignore-scripts is required: raycast (hanzo-ai) and vscode (hanzo-ide)
|
|
# define a `publish` lifecycle script targeting their own stores (Raycast /
|
|
# VS Marketplace); without this flag those scripts run mid-publish, fail, and
|
|
# abort every package after them. Builds already ran above, so no publish-time
|
|
# script is needed. `|| true` keeps one bad package from blocking the rest.
|
|
- name: Publish all
|
|
run: |
|
|
# setup-node writes a ${NODE_AUTH_TOKEN}-templated .npmrc that `npm` expands
|
|
# but `pnpm publish` does not reliably read — write the token literally so
|
|
# pnpm authenticates (a 404 on PUT is npm's obscured "unauthenticated").
|
|
echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" >> .npmrc
|
|
echo "@hanzo:registry=https://registry.npmjs.org/" >> .npmrc
|
|
npm whoami || echo "::warning::npm whoami failed — NPM_TOKEN invalid or lacks @hanzo publish rights"
|
|
pnpm -r publish --access public --no-git-checks --ignore-scripts --report-summary || true
|
|
env:
|
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
|
|
# ─── JetBrains Marketplace ───
|
|
jetbrains:
|
|
name: JetBrains
|
|
runs-on: hanzo-build-linux-amd64
|
|
needs: secrets
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-java@v4
|
|
with:
|
|
java-version: '17'
|
|
distribution: 'temurin'
|
|
|
|
# Always build the downloadable plugin zip so the GitHub Release link works
|
|
# even when the Marketplace token is absent (publish below is token-gated).
|
|
- name: Build plugin
|
|
working-directory: packages/jetbrains
|
|
run: ./gradlew buildPlugin
|
|
|
|
- name: Package for release
|
|
working-directory: packages/jetbrains
|
|
run: |
|
|
VERSION=${GITHUB_REF_NAME#v}
|
|
ZIP=$(ls build/distributions/*.zip | head -1)
|
|
cp "$ZIP" "/tmp/hanzo-ai-jetbrains-v${VERSION}.zip"
|
|
|
|
- name: Upload JetBrains plugin
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: hanzo-ai-jetbrains
|
|
path: /tmp/hanzo-ai-jetbrains-v*.zip
|
|
|
|
# ─── Microsoft Office add-in (Word / Excel / PowerPoint) ───
|
|
office:
|
|
name: Office Add-in
|
|
runs-on: hanzo-build-linux-amd64
|
|
needs: secrets
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: pnpm/action-setup@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22'
|
|
cache: 'pnpm'
|
|
- run: pnpm install --frozen-lockfile
|
|
|
|
- name: Build + package
|
|
run: |
|
|
VERSION=${GITHUB_REF_NAME#v}
|
|
pnpm --filter @hanzo/office-addin build
|
|
cd packages/office/dist && npx --yes bestzip "/tmp/hanzo-ai-office-v${VERSION}.zip" .
|
|
|
|
- name: Upload Office add-in
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: hanzo-ai-office
|
|
path: /tmp/hanzo-ai-office-v*.zip
|
|
|
|
# ─── Microsoft Outlook mail add-in ───
|
|
outlook:
|
|
name: Outlook Add-in
|
|
runs-on: hanzo-build-linux-amd64
|
|
needs: secrets
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: pnpm/action-setup@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22'
|
|
cache: 'pnpm'
|
|
- run: pnpm install --frozen-lockfile
|
|
|
|
- name: Build + package
|
|
run: |
|
|
VERSION=${GITHUB_REF_NAME#v}
|
|
pnpm --filter @hanzo/outlook-addin build
|
|
cd packages/outlook/dist && npx --yes bestzip "/tmp/hanzo-ai-outlook-v${VERSION}.zip" .
|
|
|
|
- name: Upload Outlook add-in
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: hanzo-ai-outlook
|
|
path: /tmp/hanzo-ai-outlook-v*.zip
|
|
|
|
# ─── Figma plugin ───
|
|
figma:
|
|
name: Figma Plugin
|
|
runs-on: hanzo-build-linux-amd64
|
|
needs: secrets
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: pnpm/action-setup@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22'
|
|
cache: 'pnpm'
|
|
- run: pnpm install --frozen-lockfile
|
|
|
|
- name: Build + package
|
|
run: |
|
|
VERSION=${GITHUB_REF_NAME#v}
|
|
pnpm --filter @hanzo/cards build
|
|
pnpm --filter @hanzo/figma build
|
|
# dist/ = manifest.json + code.js + ui.html. Import via
|
|
# Figma → Plugins → Development → Import plugin from manifest.
|
|
cd packages/figma/dist && npx --yes bestzip "/tmp/hanzo-ai-figma-v${VERSION}.zip" .
|
|
|
|
- name: Upload Figma plugin
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: hanzo-ai-figma
|
|
path: /tmp/hanzo-ai-figma-v*.zip
|
|
|
|
# ─── Sketch plugin ───
|
|
sketch:
|
|
name: Sketch Plugin
|
|
runs-on: hanzo-build-linux-amd64
|
|
needs: secrets
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: pnpm/action-setup@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22'
|
|
cache: 'pnpm'
|
|
- run: pnpm install --frozen-lockfile
|
|
|
|
- name: Build + package
|
|
run: |
|
|
VERSION=${GITHUB_REF_NAME#v}
|
|
pnpm --filter @hanzo/cards build
|
|
pnpm --filter @hanzo/sketch build
|
|
# dist/ contains the "Hanzo AI.sketchplugin" bundle; zip from dist so the
|
|
# bundle sits at the archive root (double-click to install into Sketch).
|
|
cd packages/sketch/dist && npx --yes bestzip "/tmp/hanzo-ai-sketch-v${VERSION}.zip" .
|
|
|
|
- name: Upload Sketch plugin
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: hanzo-ai-sketch
|
|
path: /tmp/hanzo-ai-sketch-v*.zip
|
|
|
|
# ─── Microsoft Teams app ───
|
|
teams:
|
|
name: Teams App
|
|
runs-on: hanzo-build-linux-amd64
|
|
needs: secrets
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: pnpm/action-setup@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22'
|
|
cache: 'pnpm'
|
|
- run: pnpm install --frozen-lockfile
|
|
|
|
- name: Build + package
|
|
env:
|
|
# The manifest builder substitutes the bot app id into the sideloadable
|
|
# package and errors on unset placeholders. Use the registered bot id when
|
|
# available; otherwise a nil-GUID placeholder so the release asset always
|
|
# builds (sideloaders replace it with their own Azure Bot registration).
|
|
MICROSOFT_APP_ID: ${{ secrets.MICROSOFT_APP_ID != '' && secrets.MICROSOFT_APP_ID || '00000000-0000-0000-0000-000000000000' }}
|
|
run: |
|
|
VERSION=${GITHUB_REF_NAME#v}
|
|
pnpm --filter @hanzo/cards build
|
|
pnpm --filter @hanzo/teams build
|
|
# The teams `package` script emits dist/hanzo-teams.zip (manifest + icons).
|
|
pnpm --filter @hanzo/teams package
|
|
cp packages/teams/dist/hanzo-teams.zip "/tmp/hanzo-ai-teams-v${VERSION}.zip"
|
|
|
|
- name: Upload Teams app
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: hanzo-ai-teams
|
|
path: /tmp/hanzo-ai-teams-v*.zip
|
|
|
|
# ─── Zendesk Support app ───
|
|
zendesk:
|
|
name: Zendesk App
|
|
runs-on: hanzo-build-linux-amd64
|
|
needs: secrets
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: pnpm/action-setup@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22'
|
|
cache: 'pnpm'
|
|
- run: pnpm install --frozen-lockfile
|
|
|
|
- name: Build + package
|
|
run: |
|
|
VERSION=${GITHUB_REF_NAME#v}
|
|
pnpm --filter @hanzo/cards build
|
|
pnpm --filter @hanzo/zendesk build
|
|
# dist/ is the ZAF v2 app (manifest.json + assets/ + translations/).
|
|
cd packages/zendesk/dist && npx --yes bestzip "/tmp/hanzo-ai-zendesk-v${VERSION}.zip" .
|
|
|
|
- name: Upload Zendesk app
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: hanzo-ai-zendesk
|
|
path: /tmp/hanzo-ai-zendesk-v*.zip
|
|
|
|
# ─── Desktop app — per-OS Tauri installers ───
|
|
desktop:
|
|
name: Desktop (${{ matrix.os }})
|
|
runs-on: ${{ matrix.os }}
|
|
needs: secrets
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
os: [macos-latest, windows-latest, ubuntu-latest]
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: pnpm/action-setup@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22'
|
|
cache: 'pnpm'
|
|
- uses: dtolnay/rust-toolchain@stable
|
|
|
|
- name: Install Tauri Linux deps
|
|
if: matrix.os == 'ubuntu-latest'
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y \
|
|
libwebkit2gtk-4.1-dev libgtk-3-dev \
|
|
libayatana-appindicator3-dev librsvg2-dev patchelf
|
|
|
|
- run: pnpm install
|
|
|
|
- name: Build frontend
|
|
run: pnpm --filter @hanzo/desktop build
|
|
|
|
- name: Build Tauri installers
|
|
run: pnpm --filter @hanzo/desktop tauri:build
|
|
continue-on-error: true
|
|
|
|
# Collect the native installer(s) and rename to a stable, per-OS release name.
|
|
# Signing/notarization is future work — a per-OS failure must not block others.
|
|
- name: Package for release (macOS)
|
|
if: matrix.os == 'macos-latest'
|
|
continue-on-error: true
|
|
run: |
|
|
VERSION=${GITHUB_REF_NAME#v}
|
|
mkdir -p desktop-artifacts
|
|
DMG=$(ls packages/desktop/src-tauri/target/release/bundle/dmg/*.dmg 2>/dev/null | head -1)
|
|
if [ -n "$DMG" ]; then cp "$DMG" "desktop-artifacts/hanzo-ai-desktop-macos-v${VERSION}.dmg"; fi
|
|
ls -la desktop-artifacts/ || echo "no macOS installer produced"
|
|
|
|
- name: Package for release (Windows)
|
|
if: matrix.os == 'windows-latest'
|
|
continue-on-error: true
|
|
shell: bash
|
|
run: |
|
|
VERSION=${GITHUB_REF_NAME#v}
|
|
mkdir -p desktop-artifacts
|
|
MSI=$(ls packages/desktop/src-tauri/target/release/bundle/msi/*.msi 2>/dev/null | head -1)
|
|
EXE=$(ls packages/desktop/src-tauri/target/release/bundle/nsis/*.exe 2>/dev/null | head -1)
|
|
if [ -n "$MSI" ]; then cp "$MSI" "desktop-artifacts/hanzo-ai-desktop-windows-v${VERSION}.msi"; fi
|
|
if [ -n "$EXE" ]; then cp "$EXE" "desktop-artifacts/hanzo-ai-desktop-windows-v${VERSION}.exe"; fi
|
|
ls -la desktop-artifacts/ || echo "no Windows installer produced"
|
|
|
|
- name: Package for release (Linux)
|
|
if: matrix.os == 'ubuntu-latest'
|
|
continue-on-error: true
|
|
run: |
|
|
VERSION=${GITHUB_REF_NAME#v}
|
|
mkdir -p desktop-artifacts
|
|
APPIMAGE=$(ls packages/desktop/src-tauri/target/release/bundle/appimage/*.AppImage 2>/dev/null | head -1)
|
|
DEB=$(ls packages/desktop/src-tauri/target/release/bundle/deb/*.deb 2>/dev/null | head -1)
|
|
if [ -n "$APPIMAGE" ]; then cp "$APPIMAGE" "desktop-artifacts/hanzo-ai-desktop-linux-v${VERSION}.AppImage"; fi
|
|
if [ -n "$DEB" ]; then cp "$DEB" "desktop-artifacts/hanzo-ai-desktop-linux-v${VERSION}.deb"; fi
|
|
ls -la desktop-artifacts/ || echo "no Linux installer produced"
|
|
|
|
- name: Upload Desktop installer
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: hanzo-ai-desktop-${{ runner.os }}
|
|
path: desktop-artifacts/*
|
|
if-no-files-found: ignore
|
|
continue-on-error: true
|
|
|
|
# ─── JupyterLab extension (Python wheel) ───
|
|
jupyter:
|
|
name: JupyterLab Extension
|
|
runs-on: hanzo-build-linux-amd64
|
|
needs: secrets
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: pnpm/action-setup@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22'
|
|
cache: 'pnpm'
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: '3.11'
|
|
- run: pnpm install --frozen-lockfile
|
|
|
|
# JupyterLab provides `jlpm` (the yarn wrapper the labextension build calls) and
|
|
# the `build` frontend. Install it BEFORE the labextension build, else
|
|
# `jlpm build:lib` fails with `jlpm: not found` and skips the whole release.
|
|
- name: Install JupyterLab toolchain
|
|
continue-on-error: true
|
|
run: python -m pip install --upgrade jupyterlab build
|
|
|
|
# Build the PROD labextension via pnpm (NOT jlpm). jlpm is yarn, which refuses to
|
|
# `install` inside this pnpm monorepo ("not part of the project"). Running the
|
|
# scripts through pnpm uses the already-installed node_modules and produces
|
|
# hanzo_jupyter/labextension/static/style.js — the hook's skip-if-exists target,
|
|
# so the wheel build below skips jlpm entirely.
|
|
- name: Build labextension (prod, via pnpm)
|
|
continue-on-error: true
|
|
run: |
|
|
pnpm --filter @hanzo/jupyter run build:lib:prod
|
|
pnpm --filter @hanzo/jupyter run build:labextension
|
|
|
|
- name: Build wheel
|
|
continue-on-error: true
|
|
working-directory: packages/jupyter
|
|
run: |
|
|
VERSION=${GITHUB_REF_NAME#v}
|
|
# skip-if-exists (hanzo_jupyter/labextension/static/style.js) is satisfied by
|
|
# the prod labextension above, so hatch-jupyter-builder does NOT invoke jlpm.
|
|
python -m build --wheel
|
|
mkdir -p /tmp/jupyter
|
|
WHL=$(ls dist/hanzo_jupyter-*.whl dist/hanzo_ai_jupyter-*.whl 2>/dev/null | head -1)
|
|
if [ -n "$WHL" ]; then
|
|
# Rename to the tag version so the advertised release link resolves even
|
|
# if pyproject's version has not been synced to the tag.
|
|
cp "$WHL" "/tmp/jupyter/hanzo_jupyter-${VERSION}-py3-none-any.whl"
|
|
fi
|
|
ls -la /tmp/jupyter/ || echo "no wheel produced"
|
|
|
|
- name: Upload JupyterLab wheel
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: hanzo-ai-jupyter
|
|
path: /tmp/jupyter/*.whl
|
|
if-no-files-found: ignore
|
|
continue-on-error: true
|
|
|
|
# ─── GitHub Release with downloadable artifacts ───
|
|
release:
|
|
name: GitHub Release
|
|
runs-on: hanzo-build-linux-amd64
|
|
needs: [browser, safari, vscode, jetbrains, office, outlook, figma, sketch, teams, zendesk, desktop, jupyter]
|
|
if: startsWith(github.ref, 'refs/tags/v')
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/download-artifact@v4
|
|
with:
|
|
path: artifacts
|
|
|
|
- name: Determine version
|
|
id: version
|
|
run: echo "version=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT
|
|
|
|
- name: Create GitHub Release
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
generate_release_notes: false
|
|
body: |
|
|
## IDE Extensions
|
|
|
|
| IDE | Platform | Download |
|
|
|-----|----------|----------|
|
|
| **VS Code** | Windows / macOS / Linux | [`hanzo-ai-vscode-v${{ steps.version.outputs.version }}.vsix`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-vscode-v${{ steps.version.outputs.version }}.vsix) |
|
|
| **Cursor** | Windows / macOS / Linux | [`hanzo-ai-cursor-v${{ steps.version.outputs.version }}.vsix`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-cursor-v${{ steps.version.outputs.version }}.vsix) |
|
|
| **Windsurf** | Windows / macOS / Linux | [`hanzo-ai-windsurf-v${{ steps.version.outputs.version }}.vsix`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-windsurf-v${{ steps.version.outputs.version }}.vsix) |
|
|
| **Antigravity** | Windows / macOS / Linux | [`hanzo-ai-antigravity-v${{ steps.version.outputs.version }}.vsix`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-antigravity-v${{ steps.version.outputs.version }}.vsix) |
|
|
| **Claude Desktop/Code** | Windows / macOS / Linux | [`hanzo-ai-claude-v${{ steps.version.outputs.version }}.dxt`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-claude-v${{ steps.version.outputs.version }}.dxt) |
|
|
| **JetBrains** | Windows / macOS / Linux | [`hanzo-ai-jetbrains-v${{ steps.version.outputs.version }}.zip`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-jetbrains-v${{ steps.version.outputs.version }}.zip) |
|
|
|
|
## Microsoft Office
|
|
|
|
| App | Platform | Download |
|
|
|-----|----------|----------|
|
|
| **Word · Excel · PowerPoint** | Windows / macOS / Web / iPad | [`hanzo-ai-office-v${{ steps.version.outputs.version }}.zip`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-office-v${{ steps.version.outputs.version }}.zip) |
|
|
| **Outlook** | Windows / macOS / Web | [`hanzo-ai-outlook-v${{ steps.version.outputs.version }}.zip`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-outlook-v${{ steps.version.outputs.version }}.zip) |
|
|
|
|
> Office: unzip and sideload `manifest.xml` via the M365 admin center, or Insert → Add-ins → Upload My Add-in.
|
|
|
|
## Browser Extensions
|
|
|
|
| Browser | Platform | Download |
|
|
|---------|----------|----------|
|
|
| **Chrome** | Windows / macOS / Linux | [`hanzo-ai-chrome-v${{ steps.version.outputs.version }}.zip`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-chrome-v${{ steps.version.outputs.version }}.zip) |
|
|
| **Edge** | Windows / macOS / Linux | [`hanzo-ai-edge-v${{ steps.version.outputs.version }}.zip`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-edge-v${{ steps.version.outputs.version }}.zip) |
|
|
| **Firefox** | Windows / macOS / Linux | [`hanzo-ai-firefox-v${{ steps.version.outputs.version }}.zip`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-firefox-v${{ steps.version.outputs.version }}.zip) |
|
|
| **Safari** | macOS / iOS | [`hanzo-ai-safari-v${{ steps.version.outputs.version }}.zip`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-safari-v${{ steps.version.outputs.version }}.zip) |
|
|
|
|
> Chrome zip also works for Brave, Opera, Vivaldi, Arc.
|
|
> Cursor, Windsurf, and Antigravity use the VS Code VSIX format.
|
|
|
|
## Design Tools
|
|
|
|
| App | Platform | Download |
|
|
|-----|----------|----------|
|
|
| **Figma** | Windows / macOS / Web | [`hanzo-ai-figma-v${{ steps.version.outputs.version }}.zip`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-figma-v${{ steps.version.outputs.version }}.zip) |
|
|
| **Sketch** | macOS | [`hanzo-ai-sketch-v${{ steps.version.outputs.version }}.zip`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-sketch-v${{ steps.version.outputs.version }}.zip) |
|
|
|
|
> Figma: unzip and import `manifest.json` via Figma → Plugins → Development → Import plugin from manifest.
|
|
> Sketch: unzip and double-click `Hanzo AI.sketchplugin`.
|
|
|
|
## Team Apps
|
|
|
|
| App | Platform | Download |
|
|
|-----|----------|----------|
|
|
| **Microsoft Teams** | Windows / macOS / Web | [`hanzo-ai-teams-v${{ steps.version.outputs.version }}.zip`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-teams-v${{ steps.version.outputs.version }}.zip) |
|
|
| **Zendesk** | Web | [`hanzo-ai-zendesk-v${{ steps.version.outputs.version }}.zip`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-zendesk-v${{ steps.version.outputs.version }}.zip) |
|
|
|
|
> Teams: sideload the zip via Teams → Apps → Manage your apps → Upload an app. Set your own Azure Bot app id before publishing.
|
|
> Zendesk: upload the zip via the Zendesk Admin Center → Apps and integrations → Upload private app.
|
|
|
|
## Desktop App
|
|
|
|
| OS | Format | Download |
|
|
|----|--------|----------|
|
|
| **macOS** | `.dmg` | [`hanzo-ai-desktop-macos-v${{ steps.version.outputs.version }}.dmg`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-desktop-macos-v${{ steps.version.outputs.version }}.dmg) |
|
|
| **Windows** | `.msi` / `.exe` | [`hanzo-ai-desktop-windows-v${{ steps.version.outputs.version }}.msi`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-desktop-windows-v${{ steps.version.outputs.version }}.msi) · [`.exe`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-desktop-windows-v${{ steps.version.outputs.version }}.exe) |
|
|
| **Linux** | `.AppImage` / `.deb` | [`hanzo-ai-desktop-linux-v${{ steps.version.outputs.version }}.AppImage`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-desktop-linux-v${{ steps.version.outputs.version }}.AppImage) · [`.deb`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo-ai-desktop-linux-v${{ steps.version.outputs.version }}.deb) |
|
|
|
|
> Desktop installers are unsigned for now — macOS: right-click → Open; Windows: "More info" → Run anyway.
|
|
|
|
## Data Science
|
|
|
|
| App | Platform | Download |
|
|
|-----|----------|----------|
|
|
| **JupyterLab** | Windows / macOS / Linux | [`hanzo_jupyter-${{ steps.version.outputs.version }}-py3-none-any.whl`](https://github.com/hanzoai/extension/releases/download/${{ github.ref_name }}/hanzo_jupyter-${{ steps.version.outputs.version }}-py3-none-any.whl) |
|
|
|
|
> Jupyter: `pip install hanzo_jupyter-*.whl` then restart JupyterLab.
|
|
|
|
**Install**: `code --install-extension hanzo-ai-vscode-v${{ steps.version.outputs.version }}.vsix`
|
|
**Antigravity**: `antigravity --install-extension hanzo-ai-antigravity-v${{ steps.version.outputs.version }}.vsix`
|
|
files: |
|
|
artifacts/hanzo-ai-browser/*
|
|
artifacts/hanzo-ai-ide/*
|
|
artifacts/hanzo-ai-jetbrains/*
|
|
artifacts/hanzo-ai-office/*
|
|
artifacts/hanzo-ai-outlook/*
|
|
artifacts/hanzo-ai-safari/*
|
|
artifacts/hanzo-ai-figma/*
|
|
artifacts/hanzo-ai-sketch/*
|
|
artifacts/hanzo-ai-teams/*
|
|
artifacts/hanzo-ai-zendesk/*
|
|
artifacts/hanzo-ai-desktop-*/*
|
|
artifacts/hanzo-ai-jupyter/*
|