name: 发布 Linux 服务端安装包 # 为什么单独有这个 workflow: # Linux 包的依赖(@libsql/linux-x64-gnu、@prisma/adapter-libsql 等)是平台相关的, # 在 Windows 开发机上 npm install 出来的 node_modules 装到 Linux 跑不起来, # 所以 Linux 包必须在 Linux 上构建。这个 workflow 用 ubuntu runner 产出 # classhelper-server-linux-x64-<版本>.tar.gz 并挂到 GitHub Release 上, # 服务器上的 `classhelper upgrade` 就是从这里下载 + 校验 sha256 的。 # # 用法: # 1. 先在本地按惯例打出 Windows 包并发 Release(vX.Y.Z); # 2. 到 Actions 页面手动运行本 workflow,填 tag(例如 v1.1.2); # 3. 跑完 Release 里会多出 Linux 包与更新后的 SHA256SUMS-<版本>.txt。 # # 也可以只跑构建不挂 Release(attach=false),产物在 workflow 的 Artifacts 里。 on: workflow_dispatch: inputs: tag: description: '要构建并挂载的 Release tag(例如 v1.1.2)' required: true type: string attach: description: '构建后上传到该 Release' required: false default: true type: boolean push: tags: - 'v*' permissions: contents: write jobs: build-linux-package: runs-on: ubuntu-22.04 timeout-minutes: 40 steps: - name: 确定 tag id: ref run: | if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then echo "tag=${{ inputs.tag }}" >> "$GITHUB_OUTPUT" echo "attach=${{ inputs.attach }}" >> "$GITHUB_OUTPUT" else echo "tag=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT" echo "attach=true" >> "$GITHUB_OUTPUT" fi - name: 检出代码 uses: actions/checkout@v4 with: ref: ${{ steps.ref.outputs.tag }} - name: 安装 Node 22 uses: actions/setup-node@v4 with: node-version: '22' - name: 安装 pnpm uses: pnpm/action-setup@v4 with: version: 11.8.0 run_install: false - name: 安装依赖 run: pnpm install --frozen-lockfile - name: 生成 Prisma Client # 必须显式生成:packages/server/src/generated/prisma 是 gitignored 的,CI 上全新检出没有它。 # 少了这一步,`tsc` 会因为 Prisma 类型解析不到而把回调参数全推成 any,报出一大片 # "TS7006 Parameter 'item' implicitly has an 'any' type" / "TS2339 Property 'id' does not exist # on type '{}'" —— 看着像代码写错了,实际是缺生成物(本机因为早就生成过,永远踩不到)。 # deploy/Dockerfile 的构建阶段有同样的步骤与注释。 run: pnpm --filter @classhelper/server db:generate - name: 构建 Linux 安装包 run: pnpm dist:server:linux - name: 展示产物 run: ls -la releases/server/*/linux-x64/ - name: 上传构建产物(Artifacts) uses: actions/upload-artifact@v4 with: name: classhelper-server-linux-x64 path: | releases/server/*/linux-x64/classhelper-server-linux-x64-*.tar.gz releases/server/*/linux-x64/classhelper-server-linux-x64-*.tar.gz.sha256 if-no-files-found: error retention-days: 30 - name: 挂到 Release 并更新 SHA256SUMS if: steps.ref.outputs.attach == 'true' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} TAG: ${{ steps.ref.outputs.tag }} run: | set -euo pipefail VERSION="${TAG#v}" ARTIFACT_DIR="releases/server/${VERSION}/linux-x64" TARBALL="${ARTIFACT_DIR}/classhelper-server-linux-x64-${VERSION}.tar.gz" SHAFILE="${TARBALL}.sha256" SUMS="releases/SHA256SUMS-${VERSION}.txt" if [ ! -f "$TARBALL" ]; then echo "::error::没有找到 $TARBALL(tag 与 package.json 的版本号对得上吗?)" exit 1 fi # .sha256 必须跟着一起传:它是独立发布的资产,只更新 tar.gz 会让这个文件指向旧哈希, # 拿它校验的人会得到 mismatch(classhelper upgrade 用的是 --sha256/这个文件,不是 SHA256SUMS)。 if [ ! -f "$SHAFILE" ]; then sha256sum "$TARBALL" | sed "s#${ARTIFACT_DIR}/##" > "$SHAFILE" fi # 取回已有的校验清单(Windows 包那几行),只替换/追加本包这一行,其余内容原样保留。 # 注意**不要**用 `sort -u` 去重:那份文件是人读的(表头 + 体积 + 说明),排序会把它们打散。 gh release download "$TAG" --pattern "SHA256SUMS-*.txt" --dir releases --clobber || true DOWNLOADED="$(ls releases/SHA256SUMS-*.txt 2>/dev/null | head -n 1 || true)" if [ -n "$DOWNLOADED" ] && [ "$DOWNLOADED" != "$SUMS" ]; then mv "$DOWNLOADED" "$SUMS"; fi touch "$SUMS" grep -v "^[0-9a-f]\{64\} classhelper-server-linux-" "$SUMS" > "${SUMS}.new" || true printf '%s %s\n' "$(sha256sum "$TARBALL" | awk '{print $1}')" "$(basename "$TARBALL")" >> "${SUMS}.new" mv "${SUMS}.new" "$SUMS" gh release upload "$TAG" "$TARBALL" "$SHAFILE" "$SUMS" --clobber echo "已上传:" cat "$SHAFILE" cat "$SUMS"