From f6a189ed10aa214c95e87c35072f816fedb7470e Mon Sep 17 00:00:00 2001 From: Melorise <0d00@0721.hk> Date: Sun, 23 Aug 2026 18:42:31 +0800 Subject: [PATCH] =?UTF-8?q?ci:=20=E6=B7=BB=E5=8A=A0=20Linux=20=E5=A4=9A?= =?UTF-8?q?=E6=9E=B6=E6=9E=84=E5=8F=91=E5=B8=83=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AI-assisted-by: Codex AI-model: gpt-5.6-sol AI-reasoning-effort: medium Co-authored-by: Codex --- .github/workflows/release.yml | 214 +++++++++++++++++++++++++++++++ CHANGELOG.md | 15 +++ packaging/electron-builder.yml | 5 +- packaging/nix/package.nix | 4 +- packaging/scripts/stage-linux.sh | 2 +- scripts/release-metadata.mjs | 35 +++++ 6 files changed, 269 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 CHANGELOG.md create mode 100644 scripts/release-metadata.mjs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..983e124 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,214 @@ +name: Release + +on: + workflow_dispatch: + +permissions: + contents: write + +concurrency: + group: release-master + cancel-in-progress: false + +jobs: + validate-release-branch: + name: 校验发布分支 + runs-on: ubuntu-24.04 + steps: + - name: 仅允许 master + run: | + test "$GITHUB_REF" = "refs/heads/master" || { + echo "Release workflow 仅允许从 master 手动触发。" >&2 + exit 1 + } + + update-flake-lock: + name: 更新 Nix 锁文件 + needs: validate-release-branch + runs-on: ubuntu-24.04 + outputs: + commit_sha: ${{ steps.commit.outputs.commit_sha }} + version: ${{ steps.metadata.outputs.version }} + steps: + - uses: actions/checkout@v4 + with: + ref: master + fetch-depth: 0 + + - uses: DeterminateSystems/nix-installer-action@v20 + + - name: 更新 flake.lock + run: nix flake update + + - id: commit + name: 提交锁文件更新 + env: + GIT_AUTHOR_NAME: github-actions[bot] + GIT_AUTHOR_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_NAME: github-actions[bot] + GIT_COMMITTER_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com + run: | + if [[ -n "$(git status --porcelain -- flake.lock)" ]]; then + git add flake.lock + git commit -m "build: 更新 flake.lock" \ + -m "AI-assisted-by: Codex" \ + -m "AI-model: gpt-5.6-sol" \ + -m "AI-reasoning-effort: medium" \ + -m "Co-authored-by: Codex " + git push origin HEAD:master + fi + echo "commit_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + + - id: metadata + name: 读取版本与更新日志 + run: | + version="$(node --input-type=module -e \"import p from './package.json' with { type: 'json' }; process.stdout.write(p.version)\")" + node scripts/release-metadata.mjs "$version" /tmp/release-notes.md + echo "version=$version" >> "$GITHUB_OUTPUT" + + package-linux: + name: ${{ matrix.arch }} deb 与 rpm + needs: update-flake-lock + strategy: + fail-fast: false + matrix: + include: + - arch: amd64 + deb_arch: amd64 + runner: ubuntu-24.04 + - arch: arm64 + deb_arch: arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ needs.update-flake-lock.outputs.commit_sha }} + + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + + - name: 安装系统构建依赖 + run: | + sudo apt-get update + sudo apt-get install --yes \ + build-essential cmake pkg-config rpm \ + libfcitx5core-dev libfcitx5utils-dev nlohmann-json3-dev + + - name: 构建 deb 与 rpm + env: + MELOASR_VERSION: ${{ needs.update-flake-lock.outputs.version }} + MELOASR_DEB_ARCH: ${{ matrix.deb_arch }} + run: | + npm ci + npm run package:deb + npm run package:rpm + mkdir -p release-artifacts + cp packaging/out/*.deb packaging/out/*.rpm release-artifacts/ + + - uses: actions/upload-artifact@v4 + with: + name: linux-packages-${{ matrix.arch }} + path: release-artifacts/ + if-no-files-found: error + + build-nix: + name: Nix ${{ matrix.system }} + needs: update-flake-lock + strategy: + fail-fast: false + matrix: + include: + - system: x86_64-linux + runner: ubuntu-24.04 + - system: aarch64-linux + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ needs.update-flake-lock.outputs.commit_sha }} + + - uses: DeterminateSystems/nix-installer-action@v20 + + - uses: cachix/cachix-action@v15 + with: + name: ${{ vars.CACHIX_CACHE_NAME }} + authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} + + - name: 校验并配置 Cachix + env: + CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} + CACHIX_CACHE_NAME: ${{ vars.CACHIX_CACHE_NAME }} + CACHIX_PUBLIC_KEY: ${{ vars.CACHIX_PUBLIC_KEY }} + run: | + test -n "$CACHIX_AUTH_TOKEN" + test -n "$CACHIX_CACHE_NAME" + test -n "$CACHIX_PUBLIC_KEY" + mkdir -p "$HOME/.config/nix" + { + echo "extra-substituters = https://$CACHIX_CACHE_NAME.cachix.org" + echo "extra-trusted-public-keys = $CACHIX_PUBLIC_KEY" + } >> "$HOME/.config/nix/nix.conf" + + - name: 构建、上传并更新最新 pin + env: + CACHIX_CACHE_NAME: ${{ vars.CACHIX_CACHE_NAME }} + run: | + nix build ".#packages.${{ matrix.system }}.meloasr" + store_path="$(readlink -f result)" + cachix push "$CACHIX_CACHE_NAME" "$store_path" + cachix pin --keep-revisions 1 "$CACHIX_CACHE_NAME" \ + "meloasr-${{ matrix.system }}" "$store_path" + printf '%s\n' "$store_path" > "meloasr-${{ matrix.system }}.txt" + + - uses: actions/upload-artifact@v4 + with: + name: nix-build-${{ matrix.system }} + path: meloasr-${{ matrix.system }}.txt + + publish-release: + name: 创建 GitHub Release + needs: [update-flake-lock, package-linux, build-nix] + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ needs.update-flake-lock.outputs.commit_sha }} + fetch-depth: 0 + + - name: 读取 release 元数据 + env: + VERSION: ${{ needs.update-flake-lock.outputs.version }} + run: | + node scripts/release-metadata.mjs "$VERSION" release-notes.md + if git ls-remote --exit-code --tags origin "refs/tags/v$VERSION"; then + echo "标签 v$VERSION 已存在,拒绝覆盖现有 release。" >&2 + exit 1 + fi + + - uses: actions/download-artifact@v4 + with: + pattern: linux-packages-* + path: release + merge-multiple: true + + - uses: actions/download-artifact@v4 + with: + pattern: nix-build-* + path: release + merge-multiple: true + + - name: 附带构建使用的 flake.lock + run: cp flake.lock release/flake.lock + + - uses: softprops/action-gh-release@v2 + with: + tag_name: v${{ needs.update-flake-lock.outputs.version }} + target_commitish: ${{ needs.update-flake-lock.outputs.commit_sha }} + name: MeloASR ${{ needs.update-flake-lock.outputs.version }} + body_path: release-notes.md + files: release/* + fail_on_unmatched_files: true diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..17966d9 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,15 @@ +# 更新日志 + +本项目遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/) 的格式。 + +## [0.1.7] - 2026-08-23 + +### 新增 + +- 提供基于 Fcitx5 的 Linux 实时语音输入流程、悬浮球、托盘与设置页。 +- 支持千问和元宝网页后端,以及 deb、rpm、Arch 与 Nix 分发配置。 + +### 修复 + +- 改进悬浮球、托盘状态和网页后端就绪状态的交互。 + diff --git a/packaging/electron-builder.yml b/packaging/electron-builder.yml index f451665..2a59326 100644 --- a/packaging/electron-builder.yml +++ b/packaging/electron-builder.yml @@ -10,13 +10,12 @@ files: - package.json extraResources: - - from: logo.png + - from: src/assets/logo.png to: logo.png linux: target: - dir executableName: meloasr - icon: logo.png + icon: src/assets/logo.png category: Utility - diff --git a/packaging/nix/package.nix b/packaging/nix/package.nix index e4f3a50..d40c1b1 100644 --- a/packaging/nix/package.nix +++ b/packaging/nix/package.nix @@ -12,7 +12,7 @@ stdenv.mkDerivation (finalAttrs: { pname = "meloasr"; - version = "0.1.7"; + version = (builtins.fromJSON (builtins.readFile ../../package.json)).version; src = ../..; @@ -70,7 +70,7 @@ stdenv.mkDerivation (finalAttrs: { "$out/etc/xdg/autostart/meloasr.desktop" install -Dm644 packaging/assets/meloasr.metainfo.xml \ "$out/share/metainfo/meloasr.metainfo.xml" - install -Dm644 logo.png \ + install -Dm644 src/assets/logo.png \ "$out/share/pixmaps/meloasr.png" cmake --install build/fcitx5 diff --git a/packaging/scripts/stage-linux.sh b/packaging/scripts/stage-linux.sh index a2f8092..620cb0a 100755 --- a/packaging/scripts/stage-linux.sh +++ b/packaging/scripts/stage-linux.sh @@ -34,7 +34,7 @@ install -Dm644 "${project_dir}/packaging/assets/meloasr-autostart.desktop" \ "${stage_dir}/etc/xdg/autostart/meloasr.desktop" install -Dm644 "${project_dir}/packaging/assets/meloasr.metainfo.xml" \ "${stage_dir}/usr/share/metainfo/meloasr.metainfo.xml" -install -Dm644 "${project_dir}/logo.png" \ +install -Dm644 "${project_dir}/src/assets/logo.png" \ "${stage_dir}/usr/share/pixmaps/meloasr.png" cmake -S "${project_dir}/linux/fcitx5" -B "${addon_build_dir}" \ diff --git a/scripts/release-metadata.mjs b/scripts/release-metadata.mjs new file mode 100644 index 0000000..b8a54b4 --- /dev/null +++ b/scripts/release-metadata.mjs @@ -0,0 +1,35 @@ +import { readFile, writeFile } from 'node:fs/promises'; +import { resolve } from 'node:path'; + +const [version] = process.argv.slice(2); + +if (!version) { + throw new Error('用法:node scripts/release-metadata.mjs <版本号> [输出文件]'); +} + +const root = resolve(import.meta.dirname, '..'); +const packageJson = JSON.parse(await readFile(resolve(root, 'package.json'), 'utf8')); +if (packageJson.version !== version) { + throw new Error(`package.json 版本为 ${packageJson.version},与请求版本 ${version} 不一致。`); +} + +const changelog = await readFile(resolve(root, 'CHANGELOG.md'), 'utf8'); +const heading = new RegExp(`^## \\[${version.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\$&')}\\](?:\\s|$).*$`, 'm'); +const match = heading.exec(changelog); +if (!match) { + throw new Error(`CHANGELOG.md 中缺少版本 ${version} 的二级标题。`); +} + +const start = match.index + match[0].length; +const next = /^##\s+\[/m.exec(changelog.slice(start)); +const notes = changelog.slice(start, next ? start + next.index : undefined).trim(); +if (!notes) { + throw new Error(`CHANGELOG.md 中版本 ${version} 没有发布说明。`); +} + +const output = process.argv[3]; +if (output) { + await writeFile(resolve(output), `${notes}\n`, 'utf8'); +} else { + process.stdout.write(`${notes}\n`); +}