Dev Daily #71
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Dev Daily | |
| on: | |
| schedule: | |
| # GitHub Actions schedule uses UTC. 16:00 UTC = 北京时间次日 00:00 | |
| - cron: "0 16 * * *" | |
| workflow_dispatch: | |
| concurrency: | |
| group: dev-nightly-fixed-release | |
| cancel-in-progress: true | |
| permissions: | |
| contents: write | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" | |
| FIXED_DEV_TAG: nightly-dev | |
| TARGET_BRANCH: dev | |
| ELECTRON_BUILDER_BINARIES_MIRROR: https://github.com/electron-userland/electron-builder-binaries/releases/download/ | |
| jobs: | |
| prepare: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| dev_version: ${{ steps.meta.outputs.dev_version }} | |
| steps: | |
| - name: Check out git repository | |
| uses: actions/checkout@v5 | |
| with: | |
| ref: ${{ env.TARGET_BRANCH }} | |
| fetch-depth: 0 | |
| - name: Install Node.js | |
| uses: actions/setup-node@v5 | |
| with: | |
| node-version: 24 | |
| cache: "npm" | |
| - name: Generate daily dev version | |
| id: meta | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| YEAR_2="$(TZ=Asia/Shanghai date +%y)" | |
| MONTH="$(TZ=Asia/Shanghai date +%-m)" | |
| DAY="$(TZ=Asia/Shanghai date +%-d)" | |
| DEV_VERSION="${YEAR_2}.${MONTH}.${DAY}" | |
| echo "dev_version=$DEV_VERSION" >> "$GITHUB_OUTPUT" | |
| echo "Dev version: $DEV_VERSION" | |
| - name: Recreate fixed prerelease | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| source .github/scripts/release-utils.sh | |
| recreate_fixed_prerelease "$GITHUB_REPOSITORY" "$FIXED_DEV_TAG" "$TARGET_BRANCH" "Daily Dev Build" "开发版发布页" | |
| dev-mac-arm64: | |
| needs: prepare | |
| runs-on: macos-14 | |
| steps: | |
| - name: Check out git repository | |
| uses: actions/checkout@v5 | |
| with: | |
| ref: ${{ env.TARGET_BRANCH }} | |
| fetch-depth: 0 | |
| - name: Install Node.js | |
| uses: actions/setup-node@v5 | |
| with: | |
| node-version: 24 | |
| cache: "npm" | |
| - name: Install Dependencies | |
| run: npm install | |
| - name: Ensure mac key helpers are executable | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| for file in \ | |
| resources/key/macos/universal/xkey_helper \ | |
| resources/key/macos/universal/image_scan_helper \ | |
| resources/key/macos/universal/xkey_helper_macos \ | |
| resources/key/macos/universal/libwx_key.dylib | |
| do | |
| if [ -f "$file" ]; then | |
| chmod +x "$file" | |
| ls -l "$file" | |
| fi | |
| done | |
| - name: Set dev version | |
| shell: bash | |
| run: npm version "${{ needs.prepare.outputs.dev_version }}" --no-git-tag-version --allow-same-version | |
| - name: Build Frontend & Type Check | |
| shell: bash | |
| run: | | |
| npx tsc | |
| npx vite build | |
| - name: Package macOS arm64 dev artifacts | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| export ELECTRON_BUILDER_BINARIES_MIRROR="https://github.com/electron-userland/electron-builder-binaries/releases/download/" | |
| echo "Using ELECTRON_BUILDER_BINARIES_MIRROR=$ELECTRON_BUILDER_BINARIES_MIRROR" | |
| if ! npx electron-builder --mac dmg zip --arm64 --publish never '--config.publish.channel=dev' '--config.artifactName=${productName}-dev-arm64.${ext}'; then | |
| echo "::warning::DMG packaging failed (hdiutil instability on runner). Retrying with ZIP only." | |
| npx electron-builder --mac zip --arm64 --publish never '--config.publish.channel=dev' '--config.artifactName=${productName}-dev-arm64.${ext}' | |
| fi | |
| - name: Upload macOS arm64 assets to fixed release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| source .github/scripts/release-utils.sh | |
| assets=() | |
| while IFS= read -r file; do | |
| assets+=("$file") | |
| done < <(find release -maxdepth 1 -type f | sort) | |
| if [ "${#assets[@]}" -eq 0 ]; then | |
| echo "No release files found in ./release" | |
| exit 1 | |
| fi | |
| upload_release_assets_with_retry "$GITHUB_REPOSITORY" "$FIXED_DEV_TAG" "${assets[@]}" | |
| dev-linux: | |
| needs: prepare | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check out git repository | |
| uses: actions/checkout@v5 | |
| with: | |
| ref: ${{ env.TARGET_BRANCH }} | |
| fetch-depth: 0 | |
| - name: Install Node.js | |
| uses: actions/setup-node@v5 | |
| with: | |
| node-version: 24 | |
| cache: "npm" | |
| - name: Install Dependencies | |
| run: npm install | |
| - name: Set dev version | |
| shell: bash | |
| run: npm version "${{ needs.prepare.outputs.dev_version }}" --no-git-tag-version --allow-same-version | |
| - name: Build Frontend & Type Check | |
| shell: bash | |
| run: | | |
| npx tsc | |
| npx vite build | |
| - name: Package Linux dev artifacts | |
| run: | | |
| npx electron-builder --linux --publish never '--config.publish.channel=dev' '--config.artifactName=${productName}-dev-linux.${ext}' | |
| - name: Upload Linux assets to fixed release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| source .github/scripts/release-utils.sh | |
| assets=() | |
| while IFS= read -r file; do | |
| assets+=("$file") | |
| done < <(find release -maxdepth 1 -type f | sort) | |
| if [ "${#assets[@]}" -eq 0 ]; then | |
| echo "No release files found in ./release" | |
| exit 1 | |
| fi | |
| upload_release_assets_with_retry "$GITHUB_REPOSITORY" "$FIXED_DEV_TAG" "${assets[@]}" | |
| dev-win-x64: | |
| needs: prepare | |
| runs-on: windows-latest | |
| steps: | |
| - name: Check out git repository | |
| uses: actions/checkout@v5 | |
| with: | |
| ref: ${{ env.TARGET_BRANCH }} | |
| fetch-depth: 0 | |
| - name: Install Node.js | |
| uses: actions/setup-node@v5 | |
| with: | |
| node-version: 24 | |
| cache: "npm" | |
| - name: Install Dependencies | |
| run: npm install | |
| - name: Set dev version | |
| shell: bash | |
| run: npm version "${{ needs.prepare.outputs.dev_version }}" --no-git-tag-version --allow-same-version | |
| - name: Build Frontend & Type Check | |
| shell: bash | |
| run: | | |
| npx tsc | |
| npx vite build | |
| - name: Package Windows x64 dev artifacts | |
| run: | | |
| npx electron-builder --win nsis --x64 --publish never '--config.publish.channel=dev' '--config.artifactName=${productName}-dev-x64-Setup.${ext}' | |
| - name: Upload Windows x64 assets to fixed release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| source .github/scripts/release-utils.sh | |
| assets=() | |
| while IFS= read -r file; do | |
| assets+=("$file") | |
| done < <(find release -maxdepth 1 -type f | sort) | |
| if [ "${#assets[@]}" -eq 0 ]; then | |
| echo "No release files found in ./release" | |
| exit 1 | |
| fi | |
| upload_release_assets_with_retry "$GITHUB_REPOSITORY" "$FIXED_DEV_TAG" "${assets[@]}" | |
| dev-win-arm64: | |
| needs: prepare | |
| runs-on: windows-latest | |
| steps: | |
| - name: Check out git repository | |
| uses: actions/checkout@v5 | |
| with: | |
| ref: ${{ env.TARGET_BRANCH }} | |
| fetch-depth: 0 | |
| - name: Install Node.js | |
| uses: actions/setup-node@v5 | |
| with: | |
| node-version: 24 | |
| cache: "npm" | |
| - name: Install Dependencies | |
| run: npm install | |
| - name: Set dev version | |
| shell: bash | |
| run: npm version "${{ needs.prepare.outputs.dev_version }}" --no-git-tag-version --allow-same-version | |
| - name: Build Frontend & Type Check | |
| shell: bash | |
| run: | | |
| npx tsc | |
| npx vite build | |
| - name: Package Windows arm64 dev artifacts | |
| run: | | |
| npx electron-builder --win nsis --arm64 --publish never '--config.publish.channel=dev-arm64' '--config.artifactName=${productName}-dev-arm64-Setup.${ext}' | |
| - name: Upload Windows arm64 assets to fixed release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| source .github/scripts/release-utils.sh | |
| assets=() | |
| while IFS= read -r file; do | |
| assets+=("$file") | |
| done < <(find release -maxdepth 1 -type f | sort) | |
| if [ "${#assets[@]}" -eq 0 ]; then | |
| echo "No release files found in ./release" | |
| exit 1 | |
| fi | |
| upload_release_assets_with_retry "$GITHUB_REPOSITORY" "$FIXED_DEV_TAG" "${assets[@]}" | |
| update-dev-release-notes: | |
| needs: | |
| - prepare | |
| - dev-mac-arm64 | |
| - dev-linux | |
| - dev-win-x64 | |
| - dev-win-arm64 | |
| if: always() && needs.prepare.result == 'success' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check out git repository | |
| uses: actions/checkout@v5 | |
| with: | |
| ref: ${{ env.TARGET_BRANCH }} | |
| fetch-depth: 1 | |
| - name: Update fixed dev release notes | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| TAG="${FIXED_DEV_TAG:-}" | |
| if [ -z "$TAG" ]; then | |
| echo "FIXED_DEV_TAG is empty, abort." | |
| exit 1 | |
| fi | |
| REPO="$GITHUB_REPOSITORY" | |
| RELEASE_PAGE="https://github.com/$REPO/releases/tag/$TAG" | |
| echo "Using release tag: $TAG" | |
| if ! gh api "repos/$REPO/releases/tags/$TAG" >/dev/null 2>&1; then | |
| echo "Release $TAG not found, skip notes update." | |
| exit 0 | |
| fi | |
| ASSETS_JSON="$(gh api "repos/$REPO/releases/tags/$TAG")" | |
| pick_asset() { | |
| local pattern="$1" | |
| echo "$ASSETS_JSON" | jq -r --arg p "$pattern" '[.assets[].name | select(test($p))][0] // ""' | |
| } | |
| WINDOWS_ASSET="$(pick_asset "dev-x64-Setup[.]exe$")" | |
| WINDOWS_ARM64_ASSET="$(pick_asset "dev-arm64-Setup[.]exe$")" | |
| MAC_ASSET="$(pick_asset "dev-arm64[.]dmg$")" | |
| if [ -z "$MAC_ASSET" ]; then | |
| MAC_ASSET="$(pick_asset "dev-arm64[.]zip$")" | |
| fi | |
| LINUX_TAR_ASSET="$(pick_asset "dev-linux[.]tar[.]gz$")" | |
| LINUX_APPIMAGE_ASSET="$(pick_asset "dev-linux[.]AppImage$")" | |
| build_link() { | |
| local name="$1" | |
| if [ -n "$name" ]; then | |
| echo "https://github.com/$REPO/releases/download/$TAG/$name" | |
| fi | |
| } | |
| WINDOWS_URL="$(build_link "$WINDOWS_ASSET")" | |
| WINDOWS_ARM64_URL="$(build_link "$WINDOWS_ARM64_ASSET")" | |
| MAC_URL="$(build_link "$MAC_ASSET")" | |
| LINUX_TAR_URL="$(build_link "$LINUX_TAR_ASSET")" | |
| LINUX_APPIMAGE_URL="$(build_link "$LINUX_APPIMAGE_ASSET")" | |
| cat > dev_release_notes.md <<EOF | |
| ## Daily Dev Build | |
| - 该发布页为 **开发版**。 | |
| - 当前构建版本:\`${{ needs.prepare.outputs.dev_version }}\` | |
| - 此版本为每日构建的开发版,包含最新的功能和修复,但可能不够稳定,仅推荐用于测试和验证。 | |
| ## 下载 | |
| - Windows x64: [点击下载](${WINDOWS_URL:-$RELEASE_PAGE}) | |
| - Windows arm64: [点击下载](${WINDOWS_ARM64_URL:-$RELEASE_PAGE}) | |
| - macOS(Apple Silicon): [点击下载](${MAC_URL:-$RELEASE_PAGE}) | |
| - Linux (.tar.gz): [点击下载](${LINUX_TAR_URL:-$RELEASE_PAGE}) | |
| - Linux (.AppImage): [点击下载](${LINUX_APPIMAGE_URL:-$RELEASE_PAGE}) | |
| ## macOS 安装提示 | |
| - 如果被系统提示已损坏,你需要在终端执行以下命令去除隔离标记: | |
| - \`xattr -dr com.apple.quarantine "/Applications/WeFlow.app"\` | |
| - 执行后重新打开 WeFlow。 | |
| ## 说明 | |
| - 该发布页的同名资源会被后续构建覆盖,请勿将其视作长期归档版本。 | |
| - 如某个平台资源暂未生成,请进入[发布页]($RELEASE_PAGE)查看最新状态 | |
| EOF | |
| update_release_notes() { | |
| local attempts=5 | |
| local delay_seconds=2 | |
| local i | |
| for ((i=1; i<=attempts; i++)); do | |
| if gh release edit "$TAG" --repo "$REPO" --title "Daily Dev Build" --notes-file dev_release_notes.md --prerelease >/dev/null 2>&1; then | |
| return 0 | |
| fi | |
| if [ "$i" -lt "$attempts" ]; then | |
| echo "Release update failed (attempt $i/$attempts), retry in ${delay_seconds}s..." | |
| sleep "$delay_seconds" | |
| fi | |
| done | |
| return 1 | |
| } | |
| update_release_notes | |
| source .github/scripts/release-utils.sh | |
| RELEASE_REST_ID="$(wait_for_release_id "$REPO" "$TAG" 12 2)" | |
| settle_release_state "$REPO" "$RELEASE_REST_ID" "$TAG" 12 2 | |
| print_release_state "$REPO" "$TAG" |