Skip to content
Closed
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
93 changes: 91 additions & 2 deletions .github/workflows/release-tauri.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,20 @@ jobs:
include:
- platform: macos-latest
rust-target: aarch64-apple-darwin
updater-target: darwin
updater-arch: aarch64
- platform: windows-latest
rust-target: x86_64-pc-windows-msvc
updater-target: windows
updater-arch: x86_64
- platform: ubuntu-22.04
rust-target: x86_64-unknown-linux-gnu
updater-target: linux
updater-arch: x86_64
runs-on: ${{ matrix.platform }}
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
steps:
- uses: actions/checkout@v4

Expand Down Expand Up @@ -76,6 +85,17 @@ jobs:
working-directory: 'openless-all/app'
run: npm ci

- name: Check updater signing availability
if: startsWith(github.ref, 'refs/tags/v') && endsWith(github.ref, '-tauri')
shell: bash
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
run: |
if [ -z "${TAURI_SIGNING_PRIVATE_KEY:-}" ]; then
echo "::error::TAURI_SIGNING_PRIVATE_KEY is required for signed auto-update artifacts."
exit 1
fi

- name: Check Apple signing availability
if: matrix.platform == 'macos-latest' && startsWith(github.ref, 'refs/tags/v') && endsWith(github.ref, '-tauri')
shell: bash
Expand Down Expand Up @@ -159,19 +179,50 @@ jobs:
working-directory: 'openless-all/app'
env:
INSTALL: '0' # CI 不要装到 /Applications,也不要 reset TCC
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
run: bash scripts/build-mac.sh

# ── Windows:仅 Windows 跑通用 tauri build(Linux 用下方专用 step,避免重复构建)──
- name: Build (Windows)
if: matrix.platform == 'windows-latest'
shell: bash
working-directory: 'openless-all/app'
run: npm run tauri build
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
run: |
if [ -n "${TAURI_SIGNING_PRIVATE_KEY:-}" ]; then
npm run tauri -- build --config '{"bundle":{"createUpdaterArtifacts":true}}'
else
npm run tauri build
fi

# ── Linux:产 deb / rpm / AppImage ──
- name: Build (Linux)
if: matrix.platform == 'ubuntu-22.04'
shell: bash
working-directory: 'openless-all/app'
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
run: |
if [ -n "${TAURI_SIGNING_PRIVATE_KEY:-}" ]; then
npm run tauri -- build --bundles deb,rpm,appimage --config '{"bundle":{"createUpdaterArtifacts":true}}'
else
npm run tauri -- build --bundles deb,rpm,appimage
fi

- name: Write updater manifest
if: env.TAURI_SIGNING_PRIVATE_KEY != ''
shell: bash
working-directory: 'openless-all/app'
run: npm run tauri -- build --bundles deb,rpm,appimage
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
OPENLESS_UPDATE_TARGET: ${{ matrix.updater-target }}
OPENLESS_UPDATE_ARCH: ${{ matrix.updater-arch }}
OPENLESS_UPDATE_REPO: appergb/openless
run: node scripts/write-updater-manifest.mjs

# ── 收集产物 ──
- name: List artifacts (debug)
Expand Down Expand Up @@ -206,6 +257,17 @@ jobs:
openless-all/app/src-tauri/target/release/bundle/dmg/*.dmg
if-no-files-found: error

- name: Upload macOS updater artifacts
if: matrix.platform == 'macos-latest' && env.TAURI_SIGNING_PRIVATE_KEY != ''
uses: actions/upload-artifact@v4
with:
name: openless-macos-arm64-updater
path: |
openless-all/app/src-tauri/target/release/bundle/macos/*.app.tar.gz
openless-all/app/src-tauri/target/release/bundle/macos/*.app.tar.gz.sig
openless-all/app/src-tauri/target/release/bundle/latest-darwin-aarch64.json
if-no-files-found: error

- name: Upload Windows artifacts
if: matrix.platform == 'windows-latest'
uses: actions/upload-artifact@v4
Expand All @@ -216,6 +278,17 @@ jobs:
openless-all/app/src-tauri/target/release/bundle/msi/*.msi
if-no-files-found: error

- name: Upload Windows updater artifacts
if: matrix.platform == 'windows-latest' && env.TAURI_SIGNING_PRIVATE_KEY != ''
uses: actions/upload-artifact@v4
with:
name: openless-windows-x64-updater
path: |
openless-all/app/src-tauri/target/release/bundle/nsis/*.exe.sig
openless-all/app/src-tauri/target/release/bundle/msi/*.msi.sig
openless-all/app/src-tauri/target/release/bundle/latest-windows-x86_64.json
if-no-files-found: error

- name: Upload Linux artifacts
if: matrix.platform == 'ubuntu-22.04'
uses: actions/upload-artifact@v4
Expand All @@ -227,6 +300,16 @@ jobs:
openless-all/app/src-tauri/target/release/bundle/appimage/*.AppImage
if-no-files-found: error

- name: Upload Linux updater artifacts
if: matrix.platform == 'ubuntu-22.04' && env.TAURI_SIGNING_PRIVATE_KEY != ''
uses: actions/upload-artifact@v4
with:
name: openless-linux-x64-updater
path: |
openless-all/app/src-tauri/target/release/bundle/appimage/*.AppImage.sig
openless-all/app/src-tauri/target/release/bundle/latest-linux-x86_64.json
if-no-files-found: error

# ── tag 推送时,同步上传到 GitHub Release ──
- name: Create / update release
if: startsWith(github.ref, 'refs/tags/v') && endsWith(github.ref, '-tauri')
Expand All @@ -239,8 +322,14 @@ jobs:
generate_release_notes: true
files: |
openless-all/app/src-tauri/target/release/bundle/dmg/*.dmg
openless-all/app/src-tauri/target/release/bundle/macos/*.app.tar.gz
openless-all/app/src-tauri/target/release/bundle/macos/*.app.tar.gz.sig
openless-all/app/src-tauri/target/release/bundle/nsis/*.exe
openless-all/app/src-tauri/target/release/bundle/nsis/*.exe.sig
openless-all/app/src-tauri/target/release/bundle/msi/*.msi
openless-all/app/src-tauri/target/release/bundle/msi/*.msi.sig
openless-all/app/src-tauri/target/release/bundle/deb/*.deb
openless-all/app/src-tauri/target/release/bundle/rpm/*.rpm
openless-all/app/src-tauri/target/release/bundle/appimage/*.AppImage
openless-all/app/src-tauri/target/release/bundle/appimage/*.AppImage.sig
openless-all/app/src-tauri/target/release/bundle/latest-*.json
14 changes: 12 additions & 2 deletions openless-all/app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions openless-all/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"dependencies": {
"@tauri-apps/api": "^2.1.1",
"@tauri-apps/plugin-shell": "^2.0.1",
"@tauri-apps/plugin-updater": "^2.10.1",
"i18next": "^26.0.8",
"react": "^18.3.1",
"react-dom": "^18.3.1",
Expand Down
6 changes: 5 additions & 1 deletion openless-all/app/scripts/build-mac.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ else
fi

echo "▶ tauri build"
npm run tauri build
TAURI_BUILD_ARGS=(build)
if [ -n "${TAURI_SIGNING_PRIVATE_KEY:-}" ] || [ -n "${TAURI_SIGNING_PRIVATE_KEY_PATH:-}" ]; then
TAURI_BUILD_ARGS+=(--config '{"bundle":{"createUpdaterArtifacts":true}}')
fi
npm run tauri -- "${TAURI_BUILD_ARGS[@]}"

echo "▶ 校验 Info.plist / 签名"
/usr/libexec/PlistBuddy -c "Print :NSMicrophoneUsageDescription" "$INFO" >/dev/null
Expand Down
63 changes: 63 additions & 0 deletions openless-all/app/scripts/write-updater-manifest.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env node
import { existsSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
import { basename, join } from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';

const target = process.env.OPENLESS_UPDATE_TARGET;
const arch = process.env.OPENLESS_UPDATE_ARCH;
const repo = process.env.OPENLESS_UPDATE_REPO || 'appergb/openless';

if (!target || !arch) {
throw new Error('OPENLESS_UPDATE_TARGET and OPENLESS_UPDATE_ARCH are required');
}

const packageJson = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
const bundleDir = fileURLToPath(new URL('../src-tauri/target/release/bundle/', import.meta.url));

const candidatesByTarget = {
darwin: ['macos/OpenLess.app.tar.gz'],
windows: ['nsis/OpenLess_*_x64-setup.exe', 'nsis/OpenLess*_x64-setup.exe'],
linux: ['appimage/OpenLess_*.AppImage', 'appimage/OpenLess*.AppImage'],
};

function findFirst(patterns) {
for (const pattern of patterns) {
if (!pattern.includes('*')) {
const path = join(bundleDir, pattern);
if (existsSync(path)) return path;
continue;
}
const [dir, namePattern] = pattern.split('/');
const dirPath = join(bundleDir, dir);
if (!existsSync(dirPath)) continue;
const prefix = namePattern.split('*')[0];
const suffix = namePattern.split('*').at(-1);
const match = readdirSync(dirPath)
.filter(name => name.startsWith(prefix) && name.endsWith(suffix))
.sort()[0];
if (match) return join(dirPath, match);
}
}

const artifact = findFirst(candidatesByTarget[target] || []);
if (!artifact) {
throw new Error(`No updater artifact found for ${target} in ${bundleDir}`);
}

const signaturePath = `${artifact}.sig`;
if (!existsSync(signaturePath)) {
throw new Error(`Missing updater signature: ${signaturePath}`);
}

const assetName = basename(artifact);
const manifestName = `latest-${target}-${arch}.json`;
const manifest = {
version: packageJson.version,
pub_date: new Date().toISOString(),
url: `https://github.com/${repo}/releases/latest/download/${assetName}`,
signature: readFileSync(signaturePath, 'utf8').trim(),
};

writeFileSync(join(bundleDir, manifestName), `${JSON.stringify(manifest, null, 2)}\n`);
console.log(`Wrote ${manifestName} for ${assetName}`);
Loading
Loading