Files
goodbuddy/.github/workflows/packages.yml
T
mesalogo dc8f86ff3e feat: add trusted mirror update source
Version checks and downloads previously depended on GitHub Release. About & Updates now offers GitHub or a validated mirror source, keeps the selector beneath the startup-check switch, and disables it when startup checks are off.

The website resolves platform downloads from a bounded OSS release index with a GitHub fallback. Tagged releases publish and verify immutable OSS assets through OIDC before switching the latest-version index; deployment requires the configured Alibaba Cloud environment variables and role.

Release note: “关于与更新”新增 GitHub 与镜像节点选择,启动检查、手动检查和下载页使用同一可信来源;官网下载也可按系统、架构和安装包类型直接选择。
2026-08-17 17:20:24 +08:00

312 lines
10 KiB
YAML

name: Cross-platform packages
on:
workflow_dispatch:
push:
branches:
- main
tags:
- 'v*'
permissions:
contents: read
concurrency:
group: packages-${{ github.ref }}
cancel-in-progress: ${{ github.ref_type != 'tag' }}
jobs:
validate:
name: Validate source
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 24
cache: npm
- name: Verify release tag version
if: github.ref_type == 'tag'
run: node -e "const p=require('./package.json'); const expected='v'+p.version; if(process.env.GITHUB_REF_NAME!==expected){throw new Error('Expected tag '+expected+', received '+process.env.GITHUB_REF_NAME)}"
- name: Verify bilingual release notes
if: github.ref_type == 'tag'
run: npm run release:notes:verify
- name: Install dependencies
run: npm ci
- name: Run validators
run: |
npm test
npm run typecheck
npm run lint
- name: Build production bundle
run: npm run build:bundle
- name: Upload production bundle
if: github.event_name == 'workflow_dispatch' || github.ref_type == 'tag'
uses: actions/upload-artifact@v7
with:
name: goodbuddy-production-bundle
path: out
if-no-files-found: error
retention-days: 1
package:
name: ${{ matrix.platform }} ${{ matrix.arch }}
if: github.event_name == 'workflow_dispatch' || github.ref_type == 'tag'
needs: validate
strategy:
fail-fast: false
matrix:
include:
- platform: windows
arch: x64
runner: windows-2025
- platform: windows
arch: arm64
runner: windows-2025
- platform: macos
arch: x64
runner: macos-15-intel
- platform: macos
arch: arm64
runner: macos-15
- platform: linux
arch: x64
runner: ubuntu-24.04
- platform: linux
arch: arm64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
timeout-minutes: 75
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 24
cache: npm
- name: Cache packaging toolsets
uses: actions/cache@v6
with:
path: |
${{ runner.temp }}/electron
${{ runner.temp }}/electron-builder
key: packaging-${{ runner.os }}-${{ matrix.arch }}-${{ hashFiles('package-lock.json') }}
restore-keys: packaging-${{ runner.os }}-${{ matrix.arch }}-
- name: Install dependencies
run: npm ci
env:
ELECTRON_CACHE: ${{ runner.temp }}/electron
- name: Download production bundle
uses: actions/download-artifact@v8
with:
name: goodbuddy-production-bundle
path: out
- name: Build and verify release packages
run: npm run release:package -- --platform ${{ matrix.platform }} --arch ${{ matrix.arch }} --skip-build
env:
ELECTRON_CACHE: ${{ runner.temp }}/electron
ELECTRON_BUILDER_CACHE: ${{ runner.temp }}/electron-builder
- name: Upload release packages
uses: actions/upload-artifact@v7
with:
name: goodbuddy-${{ matrix.platform }}-${{ matrix.arch }}
path: dist/release/${{ matrix.platform }}-${{ matrix.arch }}
if-no-files-found: error
compression-level: 0
retention-days: 30
release:
name: Publish GitHub and OSS release
if: github.event_name == 'push' && github.ref_type == 'tag'
needs: package
runs-on: ubuntu-24.04
timeout-minutes: 35
environment:
name: aliyun-oss-release
permissions:
contents: write
actions: read
id-token: write
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: actions/setup-node@v7
with:
node-version: 24
- name: Verify release tag
shell: bash
run: |
set -euo pipefail
expected="v$(node -p "require('./package.json').version")"
test "$GITHUB_REF_NAME" = "$expected"
test "$(git rev-parse "refs/tags/$GITHUB_REF_NAME^{commit}")" = "$GITHUB_SHA"
- name: Prepare bilingual release notes
run: node build/release-notes.cjs --output release-notes.md
- name: Download Windows packages
uses: actions/download-artifact@v8
with:
pattern: goodbuddy-windows-*
path: dist/release-downloads
- name: Download macOS packages
uses: actions/download-artifact@v8
with:
pattern: goodbuddy-macos-*
path: dist/release-downloads
- name: Download Linux packages
uses: actions/download-artifact@v8
with:
pattern: goodbuddy-linux-*
path: dist/release-downloads
- name: Verify and aggregate release assets
run: node build/aggregate-release.cjs --input dist/release-downloads --output dist/release-upload
- name: Verify OSS release configuration
shell: bash
env:
OSS_BUCKET: ${{ vars.ALIYUN_OSS_BUCKET }}
OSS_ENDPOINT: ${{ vars.ALIYUN_OSS_ENDPOINT }}
OIDC_PROVIDER_ARN: ${{ vars.ALIYUN_OIDC_PROVIDER_ARN }}
ROLE_ARN: ${{ vars.ALIYUN_ROLE_ARN }}
run: |
set -euo pipefail
test -n "$OSS_BUCKET"
test -n "$OSS_ENDPOINT"
test -n "$OIDC_PROVIDER_ARN"
test -n "$ROLE_ARN"
case "$OSS_BUCKET" in
*[!a-z0-9-]*|'') echo "OSS Bucket 名称无效" >&2; exit 1 ;;
esac
case "$OSS_ENDPOINT" in
https://oss-*.aliyuncs.com) ;;
*) echo "OSS Endpoint 必须使用标准 HTTPS 地址" >&2; exit 1 ;;
esac
case "$OIDC_PROVIDER_ARN" in
acs:ram::*:oidc-provider/*) ;;
*) echo "OIDC Provider ARN 无效" >&2; exit 1 ;;
esac
case "$ROLE_ARN" in
acs:ram::*:role/*) ;;
*) echo "RAM Role ARN 无效" >&2; exit 1 ;;
esac
- name: Authenticate to Alibaba Cloud
uses: aliyun/configure-aliyun-credentials-action@v1
with:
role-to-assume: ${{ vars.ALIYUN_ROLE_ARN }}
oidc-provider-arn: ${{ vars.ALIYUN_OIDC_PROVIDER_ARN }}
role-session-name: goodbuddy-release-${{ github.run_id }}
role-session-expiration: 3600
audience: sts.aliyuncs.com
- name: Install ossutil
shell: bash
run: |
set -euo pipefail
version="2.3.0"
archive="$RUNNER_TEMP/ossutil.zip"
directory="$RUNNER_TEMP/ossutil"
curl --fail --silent --show-error --location \
"https://gosspublic.alicdn.com/ossutil/v2/$version/ossutil-$version-linux-amd64.zip" \
--output "$archive"
mkdir "$directory"
unzip -q "$archive" -d "$directory"
binary="$(find "$directory" -type f -name ossutil -print -quit)"
test -n "$binary"
chmod +x "$binary"
echo "$(dirname "$binary")" >> "$GITHUB_PATH"
- name: Prepare OSS website release index
id: oss-release
shell: bash
env:
OSS_BUCKET: ${{ vars.ALIYUN_OSS_BUCKET }}
OSS_ENDPOINT: ${{ vars.ALIYUN_OSS_ENDPOINT }}
run: |
set -euo pipefail
endpoint_host="${OSS_ENDPOINT#https://}"
base_url="https://${OSS_BUCKET}.${endpoint_host}/releases/${GITHUB_REF_NAME}/"
node build/create-site-release.cjs \
--manifest dist/release-upload/release-manifest.json \
--base-url "$base_url" \
--output dist/site-release.json
echo "base-url=$base_url" >> "$GITHUB_OUTPUT"
- name: Upload immutable release assets to OSS
shell: bash
env:
OSS_BUCKET: ${{ vars.ALIYUN_OSS_BUCKET }}
OSS_ENDPOINT: ${{ vars.ALIYUN_OSS_ENDPOINT }}
run: |
set -euo pipefail
export OSS_ACCESS_KEY_ID="$ALIBABA_CLOUD_ACCESS_KEY_ID"
export OSS_ACCESS_KEY_SECRET="$ALIBABA_CLOUD_ACCESS_KEY_SECRET"
export OSS_SESSION_TOKEN="$ALIBABA_CLOUD_SECURITY_TOKEN"
test -n "$OSS_ACCESS_KEY_ID"
test -n "$OSS_ACCESS_KEY_SECRET"
test -n "$OSS_SESSION_TOKEN"
for file in dist/release-upload/* dist/site-release.json; do
name="$(basename "$file")"
ossutil cp "$file" \
"oss://${OSS_BUCKET}/releases/${GITHUB_REF_NAME}/${name}" \
--endpoint "$OSS_ENDPOINT" \
--update
done
- name: Verify public OSS release assets
run: node build/verify-site-release.cjs --manifest dist/site-release.json
- name: Create or update draft GitHub release
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
tag="$GITHUB_REF_NAME"
version="$(node -p "require('./package.json').version")"
if gh release view "$tag" >/dev/null 2>&1; then
gh release edit "$tag" --draft --title "GoodBuddy $version" --notes-file release-notes.md
else
gh release create "$tag" --draft --verify-tag --title "GoodBuddy $version" --notes-file release-notes.md
fi
gh release upload "$tag" dist/release-upload/* --clobber
gh release edit "$tag" --draft=false --latest
- name: Point website to verified OSS release
shell: bash
env:
OSS_BUCKET: ${{ vars.ALIYUN_OSS_BUCKET }}
OSS_ENDPOINT: ${{ vars.ALIYUN_OSS_ENDPOINT }}
run: |
set -euo pipefail
export OSS_ACCESS_KEY_ID="$ALIBABA_CLOUD_ACCESS_KEY_ID"
export OSS_ACCESS_KEY_SECRET="$ALIBABA_CLOUD_ACCESS_KEY_SECRET"
export OSS_SESSION_TOKEN="$ALIBABA_CLOUD_SECURITY_TOKEN"
ossutil cp dist/site-release.json \
"oss://${OSS_BUCKET}/releases/latest.json" \
--endpoint "$OSS_ENDPOINT" \
--force