Skip to content

v5.4.20

v5.4.20 #195

Workflow file for this run

name: Release Build(发布构建)
permissions:
contents: write
on:
release:
types: [ created ] # 当创建新的 Release 时触发
workflow_dispatch: { } # 支持手动触发
env:
JAVA_VERSION: '17'
JAVA_DISTRIBUTION: 'jetbrains' # 使用 JetBrains Runtime(JBR),为 Swing 应用优化
JLINK_MODULES: 'java.base,java.desktop,java.logging,jdk.unsupported,java.naming,java.net.http,java.prefs,java.sql,java.security.sasl,java.security.jgss,jdk.crypto.ec,java.management,java.management.rmi,jdk.crypto.cryptoki'
# 通用 Java 选项(所有平台共享)
JAVA_OPTIONS_COMMON: '-Xms512m|-Xmx1g|-XX:MaxMetaspaceSize=256m|-XX:MetaspaceSize=128m|-XX:MaxDirectMemorySize=256m|-XX:+UseG1GC|-XX:MaxGCPauseMillis=200|-XX:InitiatingHeapOccupancyPercent=45|-XX:+UseStringDeduplication|-XX:+HeapDumpOnOutOfMemoryError|-XX:HeapDumpPath=./dumps|-Dfile.encoding=UTF-8|-Dswing.aatext=true|-Djava.net.preferIPv4Stack=true|-Dhttp.keepAlive=true'
# Windows 特定选项
JAVA_OPTIONS_WINDOWS: '-Djavax.accessibility.assistive_technologies='
# macOS 特定选项
JAVA_OPTIONS_MACOS: '-Dsun.java2d.metal=false|-Dapple.awt.application.appearance=system|--add-opens java.desktop/java.awt=ALL-UNNAMED|--add-opens java.desktop/sun.lwawt=ALL-UNNAMED|--add-opens java.desktop/sun.lwawt.macosx=ALL-UNNAMED|--add-exports java.desktop/com.apple.eawt=ALL-UNNAMED'
# Linux 特定选项
JAVA_OPTIONS_LINUX: '-Dawt.useSystemAAFontSettings=on|--add-opens=java.desktop/sun.awt.X11=ALL-UNNAMED'
jobs:
# 提取版本号,供所有 job 复用
get-version:
name: Get Version(获取版本号)
runs-on: ubuntu-latest
if: github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')
outputs:
version: ${{ steps.extract_version.outputs.version }}
steps:
- name: Checkout(检出代码)
uses: actions/checkout@v4
with:
ref: ${{ github.event_name == 'release' && github.event.release.tag_name || github.ref_name }}
- name: Setup Java(配置 Java)
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DISTRIBUTION }}
java-version: ${{ env.JAVA_VERSION }}
cache: 'maven'
check-latest: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Extract version(提取版本号)
id: extract_version
run: |
VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
echo "Version: $VERSION"
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Validate release source and version(校验默认分支与版本一致性)
shell: bash
run: |
set -euo pipefail
DEFAULT_BRANCH="${{ github.event.repository.default_branch }}"
CURRENT_REF="${{ github.ref_name }}"
VERSION="${{ steps.extract_version.outputs.version }}"
if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "$CURRENT_REF" != "$DEFAULT_BRANCH" ]; then
echo "workflow_dispatch is only allowed from the default branch: ${DEFAULT_BRANCH}" >&2
exit 1
fi
if [ "${{ github.event_name }}" = "release" ]; then
TAG_NAME="${{ github.event.release.tag_name }}"
TARGET_COMMITISH="${{ github.event.release.target_commitish }}"
EXPECTED_TAG="v${VERSION}"
if [ "$TARGET_COMMITISH" != "$DEFAULT_BRANCH" ]; then
echo "Release must target default branch ${DEFAULT_BRANCH}, got ${TARGET_COMMITISH}" >&2
exit 1
fi
if [ "$TAG_NAME" != "$EXPECTED_TAG" ]; then
echo "Release tag ${TAG_NAME} does not match pom version ${VERSION}" >&2
exit 1
fi
fi
# 构建 Fat JAR(跨平台),供所有平台复用
build-jar-artifact:
name: Build Fat JAR(构建跨平台 JAR)
runs-on: ubuntu-latest
needs: [ get-version ]
if: github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')
steps:
- name: Checkout(检出代码)
uses: actions/checkout@v4
- name: Setup Java(配置 Java)
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DISTRIBUTION }}
java-version: ${{ env.JAVA_VERSION }}
cache: 'maven'
check-latest: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build with Maven(使用 Maven 构建 Fat JAR)
run: mvn -B clean package -DskipTests
- name: Upload JAR for reuse(上传 JAR 供其他 job 复用)
uses: actions/upload-artifact@v4
with:
name: app-jar
path: easy-postman-app/target/easy-postman-${{ needs.get-version.outputs.version }}.jar
retention-days: 1
build-windows-portable:
name: Build Windows Portable(构建 Windows 绿色版)
runs-on: windows-latest
needs: [ get-version, build-jar-artifact ]
if: github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')
steps:
- name: Checkout(检出代码)
uses: actions/checkout@v4
- name: Setup Java(配置 Java)
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DISTRIBUTION }}
java-version: ${{ env.JAVA_VERSION }}
check-latest: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Download Fat JAR(下载跨平台 Fat JAR)
uses: actions/download-artifact@v4
with:
name: app-jar
path: target
- name: Create runtime with jlink(使用 jlink 创建 Windows 精简 JRE)
shell: pwsh
run: |
$runtimeDir = "target\runtime"
if (Test-Path $runtimeDir) { Remove-Item -Recurse -Force $runtimeDir }
jlink `
--add-modules $env:JLINK_MODULES `
--strip-java-debug-attributes `
--strip-native-commands `
--strip-debug `
--no-header-files `
--no-man-pages `
--compress=2 `
--verbose `
--output $runtimeDir
# 验证 JRE 大小
$size = (Get-ChildItem -Path $runtimeDir -Recurse | Measure-Object -Property Length -Sum).Sum / 1MB
Write-Host "✅ JRE 创建成功,大小: $([math]::Round($size, 2)) MB"
- name: Prepare dist-input(准备打包输入目录)
shell: pwsh
run: |
$version = "${{ needs.get-version.outputs.version }}"
$jarNameWithVersion = "easy-postman-$version.jar"
$jarName = "easy-postman.jar"
$distInputDir = "target\dist-input"
if (Test-Path $distInputDir) { Remove-Item -Recurse -Force $distInputDir }
New-Item -ItemType Directory -Path $distInputDir | Out-Null
Copy-Item "target\$jarNameWithVersion" -Destination "$distInputDir\$jarName"
- name: Create app-image with jpackage(创建应用镜像,免安装)
shell: pwsh
run: |
$version = "${{ needs.get-version.outputs.version }}"
$jarName = "easy-postman.jar"
$appImageDir = "target\app-image"
if (Test-Path $appImageDir) { Remove-Item -Recurse -Force $appImageDir }
# 解析通用 Java 选项
$javaOptsCommon = $env:JAVA_OPTIONS_COMMON -split '\|'
# 解析 Windows 特定选项
$javaOptsWindows = $env:JAVA_OPTIONS_WINDOWS -split '\|'
# 构建 jpackage 参数列表
$jpackageArgs = @(
'--type', 'app-image',
'--input', 'target\dist-input',
'--main-jar', $jarName,
'--main-class', 'com.laker.postman.App',
'--runtime-image', 'target\runtime',
'--dest', 'target',
'--icon', 'assets\win\EasyPostman.ico',
'--name', 'EasyPostman',
'--app-version', $version,
'--vendor', 'Laker',
'--copyright', '© 2025 Laker'
)
# 添加通用 Java 选项
foreach ($opt in $javaOptsCommon) {
$jpackageArgs += '--java-options'
$jpackageArgs += $opt
}
# 添加 Windows 特定选项
foreach ($opt in $javaOptsWindows) {
if ($opt -ne '') {
$jpackageArgs += '--java-options'
$jpackageArgs += $opt
}
}
# 执行 jpackage
& jpackage @jpackageArgs
- name: Package portable version(打包绿色版为 ZIP)
shell: pwsh
run: |
$version = "${{ needs.get-version.outputs.version }}"
$appImageDir = "target\EasyPostman"
$zipName = "EasyPostman-$version-windows-x64-portable.zip"
if (-not (Test-Path "dist")) { New-Item -ItemType Directory -Path "dist" | Out-Null }
# 创建 .portable 标识文件,用于运行时检测便携版
$portableMarker = Join-Path $appImageDir ".portable"
"This is a portable version" | Out-File -FilePath $portableMarker -Encoding UTF8
Write-Host "Created .portable marker file"
# 压缩为 ZIP
Compress-Archive -Path $appImageDir -DestinationPath "dist\$zipName" -Force
Write-Host "✅ Created portable version: $zipName"
- name: Upload as Artifact(上传为构建产物)
uses: actions/upload-artifact@v4
with:
name: EasyPostman-Windows-Portable
path: dist/*-portable.zip
retention-days: 7
build-windows-exe:
name: Build Windows EXE Installer(构建 Windows EXE 安装程序)
runs-on: windows-latest
needs: [ get-version, build-jar-artifact ]
if: github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')
steps:
- name: Checkout(检出代码)
uses: actions/checkout@v4
- name: Setup Java(配置 Java)
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DISTRIBUTION }}
java-version: ${{ env.JAVA_VERSION }}
check-latest: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Download Fat JAR(下载跨平台 Fat JAR)
uses: actions/download-artifact@v4
with:
name: app-jar
path: target
- name: Install Inno Setup(安装 Inno Setup)
shell: pwsh
run: |
Write-Host "📦 Installing Inno Setup..."
choco install innosetup -y --no-progress
# 刷新环境变量
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
# 验证安装
$iscc = Get-Command iscc -ErrorAction SilentlyContinue
if ($iscc) {
Write-Host "✅ Inno Setup installed: $($iscc.Source)"
# 显示版本信息(iscc 不带参数会显示版本和帮助)
& iscc 2>&1 | Select-Object -First 5
} else {
Write-Error "❌ Inno Setup installation failed"
exit 1
}
- name: Create runtime with jlink(使用 jlink 创建 Windows 精简 JRE)
shell: pwsh
run: |
$runtimeDir = "target\runtime"
if (Test-Path $runtimeDir) { Remove-Item -Recurse -Force $runtimeDir }
jlink `
--add-modules $env:JLINK_MODULES `
--strip-java-debug-attributes `
--strip-native-commands `
--strip-debug `
--no-header-files `
--no-man-pages `
--compress=2 `
--verbose `
--output $runtimeDir
# 验证 JRE 大小
$size = (Get-ChildItem -Path $runtimeDir -Recurse | Measure-Object -Property Length -Sum).Sum / 1MB
Write-Host "✅ JRE 创建成功,大小: $([math]::Round($size, 2)) MB"
- name: Prepare dist-input(准备打包输入目录)
shell: pwsh
run: |
$version = "${{ needs.get-version.outputs.version }}"
$jarNameWithVersion = "easy-postman-$version.jar"
$jarName = "easy-postman.jar"
$distInputDir = "target\dist-input"
if (Test-Path $distInputDir) { Remove-Item -Recurse -Force $distInputDir }
New-Item -ItemType Directory -Path $distInputDir | Out-Null
Copy-Item "target\$jarNameWithVersion" -Destination "$distInputDir\$jarName"
- name: Create app-image with jpackage(创建应用镜像)
shell: pwsh
run: |
$version = "${{ needs.get-version.outputs.version }}"
$jarName = "easy-postman.jar"
# 解析通用 Java 选项
$javaOptsCommon = $env:JAVA_OPTIONS_COMMON -split '\|'
# 解析 Windows 特定选项
$javaOptsWindows = $env:JAVA_OPTIONS_WINDOWS -split '\|'
# 构建 jpackage 参数列表
$jpackageArgs = @(
'--type', 'app-image',
'--input', 'target\dist-input',
'--main-jar', $jarName,
'--main-class', 'com.laker.postman.App',
'--runtime-image', 'target\runtime',
'--dest', 'target',
'--icon', 'assets\win\EasyPostman.ico',
'--name', 'EasyPostman',
'--app-version', $version,
'--vendor', 'Laker',
'--copyright', '© 2025 Laker'
)
# 添加通用 Java 选项
foreach ($opt in $javaOptsCommon) {
$jpackageArgs += '--java-options'
$jpackageArgs += $opt
}
# 添加 Windows 特定选项
foreach ($opt in $javaOptsWindows) {
if ($opt -ne '') {
$jpackageArgs += '--java-options'
$jpackageArgs += $opt
}
}
# 执行 jpackage
& jpackage @jpackageArgs
Write-Host "✅ App image created at: target\EasyPostman"
- name: Create EXE with Inno Setup(使用 Inno Setup 创建 EXE 安装程序)
shell: pwsh
run: |
$version = "${{ needs.get-version.outputs.version }}"
$issScript = "build\easy-postman.iss"
$arch = "x64" # 当前构建为 x64,未来可扩展为 arm64
# 确保输出目录存在
if (-not (Test-Path "dist")) {
New-Item -ItemType Directory -Path "dist" | Out-Null
}
Write-Host "🔨 Building EXE installer with Inno Setup..."
Write-Host " Version: $version"
Write-Host " Architecture: $arch"
Write-Host " Script: $issScript"
Write-Host " Source: target\EasyPostman"
# 验证源目录存在
if (-not (Test-Path "target\EasyPostman")) {
Write-Error "❌ Source directory not found: target\EasyPostman"
exit 1
}
# 运行 Inno Setup 编译器
# 注意:路径相对于 ISS 脚本位置(build 目录),所以需要 ..\
& iscc `
"/DMyAppVersion=$version" `
"/DMyAppSourceDir=..\target\EasyPostman" `
"/DMyOutputDir=..\dist" `
"/DMyArch=$arch" `
$issScript
if ($LASTEXITCODE -ne 0) {
Write-Error "❌ Inno Setup compilation failed with exit code: $LASTEXITCODE"
exit 1
}
# 验证 EXE 文件
$expectedExeName = "EasyPostman-$version-windows-$arch.exe"
$exeFile = Get-Item "dist\$expectedExeName" -ErrorAction SilentlyContinue
if ($exeFile) {
Write-Host "✅ EXE installer created successfully!"
Write-Host " File: $($exeFile.Name)"
Write-Host " Size: $([math]::Round($exeFile.Length / 1MB, 2)) MB"
Write-Host " Path: $($exeFile.FullName)"
} else {
Write-Error "❌ Expected EXE file not found: $expectedExeName"
Write-Host "Files in dist folder:"
Get-ChildItem "dist" | ForEach-Object { Write-Host " - $($_.Name)" }
exit 1
}
- name: Upload as Artifact(上传为构建产物)
uses: actions/upload-artifact@v4
with:
name: EasyPostman-Windows-EXE
path: dist/*.exe
retention-days: 7
build-macos-intel:
name: Build macOS Intel DMG(构建 macOS Intel 版安装包)
runs-on: macos-15-intel # Intel x86_64
needs: [ get-version, build-jar-artifact ]
if: github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')
steps:
- name: Checkout(检出代码)
uses: actions/checkout@v4
- name: Setup Java(配置 Java)
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DISTRIBUTION }}
java-version: ${{ env.JAVA_VERSION }}
check-latest: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Download Fat JAR(下载跨平台 Fat JAR)
uses: actions/download-artifact@v4
with:
name: app-jar
path: target
- name: Create runtime with jlink(使用 jlink 创建 macOS Intel 精简 JRE)
run: |
rm -rf target/runtime
# 创建 macOS Intel 平台的 JRE
jlink \
--add-modules ${{ env.JLINK_MODULES }} \
--strip-java-debug-attributes \
--strip-native-commands \
--strip-debug \
--no-header-files \
--no-man-pages \
--compress=2 \
--verbose \
--output target/runtime
# 验证 JRE 大小
echo "✅ JRE 创建成功,大小: $(du -sh target/runtime | cut -f1)"
- name: Prepare dist-input(准备打包输入目录)
run: |
VERSION="${{ needs.get-version.outputs.version }}"
rm -rf target/dist-input
mkdir -p target/dist-input
cp target/easy-postman-$VERSION.jar target/dist-input/easy-postman.jar
- name: Create DMG with jpackage(使用 jpackage 创建 DMG 镜像)
run: |
VERSION="${{ needs.get-version.outputs.version }}"
mkdir -p dist
# 解析通用 Java 选项
IFS='|' read -ra JAVA_OPTS_COMMON <<< "${{ env.JAVA_OPTIONS_COMMON }}"
# 解析 macOS 特定选项
IFS='|' read -ra JAVA_OPTS_MACOS <<< "${{ env.JAVA_OPTIONS_MACOS }}"
# 构建 jpackage 参数数组
JPACKAGE_ARGS=(
--input target/dist-input
--main-jar "easy-postman.jar"
--main-class com.laker.postman.App
--runtime-image target/runtime
--type dmg
--name "EasyPostman"
--app-version "$VERSION"
--dest dist
--icon assets/mac/EasyPostman.icns
--vendor "Laker"
--copyright "© 2025 Laker"
)
# 添加通用 Java 选项
for opt in "${JAVA_OPTS_COMMON[@]}"; do
JPACKAGE_ARGS+=(--java-options "$opt")
done
# 添加 macOS 特定选项
for opt in "${JAVA_OPTS_MACOS[@]}"; do
if [ -n "$opt" ]; then
JPACKAGE_ARGS+=(--java-options "$opt")
fi
done
# 执行 jpackage
jpackage "${JPACKAGE_ARGS[@]}"
# 重命名为 Intel 版本(使用标准架构标识)
mv dist/EasyPostman-$VERSION.dmg dist/EasyPostman-$VERSION-macos-x86_64.dmg
echo "✅ Created: EasyPostman-$VERSION-macos-x86_64.dmg"
- name: Upload as Artifact(上传为构建产物)
uses: actions/upload-artifact@v4
with:
name: EasyPostman-macOS-Intel-DMG
path: dist/*-macos-x86_64.dmg
retention-days: 7
build-macos-arm:
name: Build macOS Apple Silicon DMG(构建 macOS Apple Silicon 版安装包)
runs-on: macos-latest # Apple Silicon (M1/M2/M3/M4)
needs: [ get-version, build-jar-artifact ]
if: github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')
steps:
- name: Checkout(检出代码)
uses: actions/checkout@v4
- name: Setup Java(配置 Java)
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DISTRIBUTION }}
java-version: ${{ env.JAVA_VERSION }}
check-latest: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Download Fat JAR(下载跨平台 Fat JAR)
uses: actions/download-artifact@v4
with:
name: app-jar
path: target
- name: Create runtime with jlink(使用 jlink 创建 macOS ARM 精简 JRE)
run: |
rm -rf target/runtime
# 创建 macOS ARM 平台的 JRE
jlink \
--add-modules ${{ env.JLINK_MODULES }} \
--strip-java-debug-attributes \
--strip-native-commands \
--strip-debug \
--no-header-files \
--no-man-pages \
--compress=2 \
--verbose \
--output target/runtime
# 验证 JRE 大小
echo "✅ JRE 创建成功,大小: $(du -sh target/runtime | cut -f1)"
- name: Prepare dist-input(准备打包输入目录)
run: |
VERSION="${{ needs.get-version.outputs.version }}"
rm -rf target/dist-input
mkdir -p target/dist-input
cp target/easy-postman-$VERSION.jar target/dist-input/easy-postman.jar
- name: Create DMG with jpackage(使用 jpackage 创建 DMG 镜像)
run: |
VERSION="${{ needs.get-version.outputs.version }}"
mkdir -p dist
# 解析通用 Java 选项
IFS='|' read -ra JAVA_OPTS_COMMON <<< "${{ env.JAVA_OPTIONS_COMMON }}"
# 解析 macOS 特定选项
IFS='|' read -ra JAVA_OPTS_MACOS <<< "${{ env.JAVA_OPTIONS_MACOS }}"
# 构建 jpackage 参数数组
JPACKAGE_ARGS=(
--input target/dist-input
--main-jar "easy-postman.jar"
--main-class com.laker.postman.App
--runtime-image target/runtime
--type dmg
--name "EasyPostman"
--app-version "$VERSION"
--dest dist
--icon assets/mac/EasyPostman.icns
--vendor "Laker"
--copyright "© 2025 Laker"
)
# 添加通用 Java 选项
for opt in "${JAVA_OPTS_COMMON[@]}"; do
JPACKAGE_ARGS+=(--java-options "$opt")
done
# 添加 macOS 特定选项
for opt in "${JAVA_OPTS_MACOS[@]}"; do
if [ -n "$opt" ]; then
JPACKAGE_ARGS+=(--java-options "$opt")
fi
done
# 执行 jpackage
jpackage "${JPACKAGE_ARGS[@]}"
# 重命名为 ARM 版本(使用标准架构标识)
mv dist/EasyPostman-$VERSION.dmg dist/EasyPostman-$VERSION-macos-arm64.dmg
echo "✅ Created: EasyPostman-$VERSION-macos-arm64.dmg"
- name: Upload as Artifact(上传为构建产物)
uses: actions/upload-artifact@v4
with:
name: EasyPostman-macOS-ARM-DMG
path: dist/*-macos-arm64.dmg
retention-days: 7
build-jar:
name: Build Standalone JAR(构建独立 JAR 包)
runs-on: ubuntu-latest
needs: [ get-version, build-jar-artifact ]
if: github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')
steps:
- name: Download JAR artifact(下载已构建的 JAR)
uses: actions/download-artifact@v4
with:
name: app-jar
path: dist
- name: Upload as Artifact(上传为构建产物)
uses: actions/upload-artifact@v4
with:
name: EasyPostman-Standalone-JAR
path: dist/*.jar
retention-days: 7
build-ubuntu-amd64:
name: Build Ubuntu DEB amd64(构建 Ubuntu x64 安装包)
runs-on: ubuntu-22.04
needs: [ get-version, build-jar-artifact ]
if: github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')
steps:
- name: Checkout(检出代码)
uses: actions/checkout@v4
- name: Setup Java(配置 Java)
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DISTRIBUTION }}
java-version: ${{ env.JAVA_VERSION }}
check-latest: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Download Fat JAR(下载跨平台 Fat JAR)
uses: actions/download-artifact@v4
with:
name: app-jar
path: target
- name: Install dependencies(安装系统依赖)
run: |
sudo apt-get update
# 安装 GTK3、WebKit、打包工具,以及 DEB 兼容重打包所需压缩工具
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev binutils zstd xz-utils
- name: Create runtime with jlink(使用 jlink 创建 Linux 精简 JRE)
run: |
rm -rf target/runtime
# 创建 Linux 平台的 JRE
jlink \
--add-modules ${{ env.JLINK_MODULES }} \
--strip-debug \
--no-header-files \
--no-man-pages \
--compress=2 \
--output target/runtime
- name: Prepare dist-input(准备打包输入目录)
run: |
VERSION="${{ needs.get-version.outputs.version }}"
rm -rf target/dist-input
mkdir -p target/dist-input
cp target/easy-postman-$VERSION.jar target/dist-input/easy-postman.jar
- name: Create DEB with jpackage(使用 jpackage 创建 DEB 安装包)
run: |
VERSION="${{ needs.get-version.outputs.version }}"
mkdir -p dist
# 解析通用 Java 选项
IFS='|' read -ra JAVA_OPTS_COMMON <<< "${{ env.JAVA_OPTIONS_COMMON }}"
# 解析 Linux 特定选项
IFS='|' read -ra JAVA_OPTS_LINUX <<< "${{ env.JAVA_OPTIONS_LINUX }}"
# 构建 jpackage 参数数组
JPACKAGE_ARGS=(
--input target/dist-input
--main-jar "easy-postman.jar"
--main-class com.laker.postman.App
--runtime-image target/runtime
--type deb
--name "EasyPostman"
--app-version "$VERSION"
--dest dist
--vendor "Laker"
--copyright "© 2025 Laker"
--description "A modern API testing tool similar to Postman"
--linux-shortcut
--linux-menu-group "Development"
--linux-app-category "Development"
)
# 添加通用 Java 选项
for opt in "${JAVA_OPTS_COMMON[@]}"; do
JPACKAGE_ARGS+=(--java-options "$opt")
done
# 添加 Linux 特定选项
for opt in "${JAVA_OPTS_LINUX[@]}"; do
if [ -n "$opt" ]; then
JPACKAGE_ARGS+=(--java-options "$opt")
fi
done
# 执行 jpackage
jpackage "${JPACKAGE_ARGS[@]}"
- name: Repack DEB members to xz(重打包为 xz 兼容格式)
run: |
DEB_FILE=$(find dist -maxdepth 1 -type f -name "*.deb" | sort | tail -n 1)
if [ -z "$DEB_FILE" ]; then
echo "No DEB file generated by jpackage" >&2
exit 1
fi
bash build/repack-deb-to-xz.sh "$DEB_FILE"
echo "Repacked package:"
ar t "$DEB_FILE"
- name: Rename amd64 DEB to stable release name(统一 amd64 包名)
run: |
VERSION="${{ needs.get-version.outputs.version }}"
ORIGINAL_DEB=$(find dist -maxdepth 1 -type f -name "*.deb" | sort | tail -n 1)
if [ -z "$ORIGINAL_DEB" ]; then
echo "No DEB file available for renaming" >&2
exit 1
fi
TARGET_DEB="dist/EasyPostman-${VERSION}-linux-amd64.deb"
mv "$ORIGINAL_DEB" "$TARGET_DEB"
echo "Generated amd64 DEB:"
ls -1 "$TARGET_DEB"
- name: Upload as Artifact(上传为构建产物)
uses: actions/upload-artifact@v4
with:
name: EasyPostman-Ubuntu-DEB-amd64
path: dist/*-linux-amd64.deb
retention-days: 7
build-ubuntu-arm64:
name: Build Ubuntu DEB arm64(构建 Ubuntu ARM64 安装包)
runs-on: ubuntu-22.04-arm
needs: [ get-version, build-jar-artifact ]
if: github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')
steps:
- name: Checkout(检出代码)
uses: actions/checkout@v4
- name: Setup Java(配置 Java)
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DISTRIBUTION }}
java-version: ${{ env.JAVA_VERSION }}
check-latest: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Download Fat JAR(下载跨平台 Fat JAR)
uses: actions/download-artifact@v4
with:
name: app-jar
path: target
- name: Install dependencies(安装系统依赖)
run: |
sudo apt-get update
# 安装 GTK3、WebKit、打包工具,以及 DEB 兼容重打包所需压缩工具
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev binutils zstd xz-utils
- name: Create runtime with jlink(使用 jlink 创建 Linux 精简 JRE)
run: |
rm -rf target/runtime
# 创建 Linux 平台的 JRE
jlink \
--add-modules ${{ env.JLINK_MODULES }} \
--strip-debug \
--no-header-files \
--no-man-pages \
--compress=2 \
--output target/runtime
- name: Prepare dist-input(准备打包输入目录)
run: |
VERSION="${{ needs.get-version.outputs.version }}"
rm -rf target/dist-input
mkdir -p target/dist-input
cp target/easy-postman-$VERSION.jar target/dist-input/easy-postman.jar
- name: Create DEB with jpackage(使用 jpackage 创建 DEB 安装包)
run: |
VERSION="${{ needs.get-version.outputs.version }}"
mkdir -p dist
# 解析通用 Java 选项
IFS='|' read -ra JAVA_OPTS_COMMON <<< "${{ env.JAVA_OPTIONS_COMMON }}"
# 解析 Linux 特定选项
IFS='|' read -ra JAVA_OPTS_LINUX <<< "${{ env.JAVA_OPTIONS_LINUX }}"
# 构建 jpackage 参数数组
JPACKAGE_ARGS=(
--input target/dist-input
--main-jar "easy-postman.jar"
--main-class com.laker.postman.App
--runtime-image target/runtime
--type deb
--name "EasyPostman"
--app-version "$VERSION"
--dest dist
--vendor "Laker"
--copyright "© 2025 Laker"
--description "A modern API testing tool similar to Postman"
--linux-shortcut
--linux-menu-group "Development"
--linux-app-category "Development"
)
# 添加通用 Java 选项
for opt in "${JAVA_OPTS_COMMON[@]}"; do
JPACKAGE_ARGS+=(--java-options "$opt")
done
# 添加 Linux 特定选项
for opt in "${JAVA_OPTS_LINUX[@]}"; do
if [ -n "$opt" ]; then
JPACKAGE_ARGS+=(--java-options "$opt")
fi
done
# 执行 jpackage
jpackage "${JPACKAGE_ARGS[@]}"
- name: Repack DEB members to xz(重打包为 xz 兼容格式)
run: |
DEB_FILE=$(find dist -maxdepth 1 -type f -name "*.deb" | sort | tail -n 1)
if [ -z "$DEB_FILE" ]; then
echo "No DEB file generated by jpackage" >&2
exit 1
fi
bash build/repack-deb-to-xz.sh "$DEB_FILE"
echo "Repacked package:"
ar t "$DEB_FILE"
- name: Create generic and compatibility ARM64 variants(生成通用 ARM64 和兼容版安装包)
run: |
VERSION="${{ needs.get-version.outputs.version }}"
ORIGINAL_DEB=$(find dist -maxdepth 1 -type f -name "*.deb" | sort | tail -n 1)
if [ -z "$ORIGINAL_DEB" ]; then
echo "No DEB file available for renaming" >&2
exit 1
fi
GENERIC_DEB="dist/EasyPostman-${VERSION}-linux-arm64.deb"
COMPAT_DEB="dist/EasyPostman-${VERSION}-linux-arm64-compat.deb"
mv "$ORIGINAL_DEB" "$GENERIC_DEB"
cp "$GENERIC_DEB" "$COMPAT_DEB"
echo "Generated ARM64 variants:"
ls -1 "$GENERIC_DEB" "$COMPAT_DEB"
- name: Upload as Artifact(上传为构建产物)
uses: actions/upload-artifact@v4
with:
name: EasyPostman-Ubuntu-DEB-arm64
path: |
dist/*-linux-arm64.deb
dist/*-linux-arm64-compat.deb
retention-days: 7
build-rpm-amd64:
name: Build RPM amd64(构建 RPM x64 安装包)
runs-on: ubuntu-22.04
needs: [ get-version, build-jar-artifact ]
if: github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')
steps:
- name: Checkout(检出代码)
uses: actions/checkout@v4
- name: Setup Java(配置 Java)
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DISTRIBUTION }}
java-version: ${{ env.JAVA_VERSION }}
check-latest: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Download Fat JAR(下载跨平台 Fat JAR)
uses: actions/download-artifact@v4
with:
name: app-jar
path: target
- name: Install dependencies(安装系统依赖)
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev binutils rpm
- name: Create runtime with jlink(使用 jlink 创建 Linux 精简 JRE)
run: |
rm -rf target/runtime
jlink \
--add-modules ${{ env.JLINK_MODULES }} \
--strip-debug \
--no-header-files \
--no-man-pages \
--compress=2 \
--output target/runtime
- name: Prepare dist-input(准备打包输入目录)
run: |
VERSION="${{ needs.get-version.outputs.version }}"
rm -rf target/dist-input
mkdir -p target/dist-input
cp target/easy-postman-$VERSION.jar target/dist-input/easy-postman.jar
- name: Create RPM with jpackage(使用 jpackage 创建 RPM 安装包)
run: |
VERSION="${{ needs.get-version.outputs.version }}"
mkdir -p dist
IFS='|' read -ra JAVA_OPTS_COMMON <<< "${{ env.JAVA_OPTIONS_COMMON }}"
IFS='|' read -ra JAVA_OPTS_LINUX <<< "${{ env.JAVA_OPTIONS_LINUX }}"
JPACKAGE_ARGS=(
--input target/dist-input
--main-jar "easy-postman.jar"
--main-class com.laker.postman.App
--runtime-image target/runtime
--type rpm
--name "EasyPostman"
--app-version "$VERSION"
--dest dist
--vendor "Laker"
--copyright "© 2025 Laker"
--description "A modern API testing tool similar to Postman"
--linux-shortcut
--linux-menu-group "Development"
--linux-app-category "Development"
--linux-rpm-license-type "MIT"
)
for opt in "${JAVA_OPTS_COMMON[@]}"; do
JPACKAGE_ARGS+=(--java-options "$opt")
done
for opt in "${JAVA_OPTS_LINUX[@]}"; do
if [ -n "$opt" ]; then
JPACKAGE_ARGS+=(--java-options "$opt")
fi
done
jpackage "${JPACKAGE_ARGS[@]}"
- name: Upload as Artifact(上传为构建产物)
uses: actions/upload-artifact@v4
with:
name: EasyPostman-RPM-amd64
path: dist/*.rpm
retention-days: 7
build-rpm-arm64:
name: Build RPM arm64(构建 RPM ARM64 安装包)
runs-on: ubuntu-22.04-arm
needs: [ get-version, build-jar-artifact ]
if: github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')
steps:
- name: Checkout(检出代码)
uses: actions/checkout@v4
- name: Setup Java(配置 Java)
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DISTRIBUTION }}
java-version: ${{ env.JAVA_VERSION }}
check-latest: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Download Fat JAR(下载跨平台 Fat JAR)
uses: actions/download-artifact@v4
with:
name: app-jar
path: target
- name: Install dependencies(安装系统依赖)
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev binutils rpm
- name: Create runtime with jlink(使用 jlink 创建 Linux 精简 JRE)
run: |
rm -rf target/runtime
jlink \
--add-modules ${{ env.JLINK_MODULES }} \
--strip-debug \
--no-header-files \
--no-man-pages \
--compress=2 \
--output target/runtime
- name: Prepare dist-input(准备打包输入目录)
run: |
VERSION="${{ needs.get-version.outputs.version }}"
rm -rf target/dist-input
mkdir -p target/dist-input
cp target/easy-postman-$VERSION.jar target/dist-input/easy-postman.jar
- name: Create RPM with jpackage(使用 jpackage 创建 RPM 安装包)
run: |
VERSION="${{ needs.get-version.outputs.version }}"
mkdir -p dist
IFS='|' read -ra JAVA_OPTS_COMMON <<< "${{ env.JAVA_OPTIONS_COMMON }}"
IFS='|' read -ra JAVA_OPTS_LINUX <<< "${{ env.JAVA_OPTIONS_LINUX }}"
JPACKAGE_ARGS=(
--input target/dist-input
--main-jar "easy-postman.jar"
--main-class com.laker.postman.App
--runtime-image target/runtime
--type rpm
--name "EasyPostman"
--app-version "$VERSION"
--dest dist
--vendor "Laker"
--copyright "© 2025 Laker"
--description "A modern API testing tool similar to Postman"
--linux-shortcut
--linux-menu-group "Development"
--linux-app-category "Development"
--linux-rpm-license-type "MIT"
)
for opt in "${JAVA_OPTS_COMMON[@]}"; do
JPACKAGE_ARGS+=(--java-options "$opt")
done
for opt in "${JAVA_OPTS_LINUX[@]}"; do
if [ -n "$opt" ]; then
JPACKAGE_ARGS+=(--java-options "$opt")
fi
done
jpackage "${JPACKAGE_ARGS[@]}"
- name: Upload as Artifact(上传为构建产物)
uses: actions/upload-artifact@v4
with:
name: EasyPostman-RPM-arm64
path: dist/*.rpm
retention-days: 7
# ============================================================
# 统一上传所有平台文件到 GitHub Release
# 使用 softprops/action-gh-release@v2,触发条件:release 事件
# always() 保证即使部分构建失败也能上传成功的文件
# ============================================================
upload-to-github-release:
name: Upload All to GitHub Release(统一上传到 GitHub Release)
if: always() && (github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')) && github.event_name == 'release'
needs: [ build-windows-portable, build-windows-exe, build-macos-intel, build-macos-arm, build-jar, build-ubuntu-amd64, build-ubuntu-arm64, build-rpm-amd64, build-rpm-arm64 ]
runs-on: ubuntu-latest
steps:
- name: Download all release artifacts(下载所有平台构建产物)
uses: actions/download-artifact@v4
with:
path: all-artifacts
pattern: EasyPostman-*
merge-multiple: true
- name: List downloaded files(列出所有下载文件)
run: |
echo "📦 Downloaded artifacts:"
find all-artifacts -type f | sort
- name: Upload all files to GitHub Release(上传所有文件到 Release)
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.event.release.tag_name }}
files: |
all-artifacts/*-portable.zip
all-artifacts/*.exe
all-artifacts/*-macos-x86_64.dmg
all-artifacts/*-macos-arm64.dmg
all-artifacts/*.jar
all-artifacts/*.deb
all-artifacts/*.rpm
fail_on_unmatched_files: false
overwrite_files: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ============================================================
# 检查是否至少有一个构建成功(用于 Gitee 同步前置判断)
# ============================================================
check-any-build-success:
name: Check Any Build Success(检查至少一个构建成功)
if: |
(github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')) &&
github.event_name == 'release' &&
always()
needs: [ build-windows-portable, build-windows-exe, build-macos-arm ]
runs-on: ubuntu-latest
outputs:
should_create_release: ${{ steps.check.outputs.should_create }}
steps:
- name: Check if any build succeeded(检查是否有任何构建成功)
id: check
run: |
echo "📊 检查构建状态..."
echo " Windows Portable: ${{ needs.build-windows-portable.result }}"
echo " Windows EXE: ${{ needs.build-windows-exe.result }}"
echo " macOS ARM: ${{ needs.build-macos-arm.result }}"
# 只要有一个成功就创建 Release
if [ "${{ needs.build-windows-portable.result }}" == "success" ] || \
[ "${{ needs.build-windows-exe.result }}" == "success" ] || \
[ "${{ needs.build-macos-arm.result }}" == "success" ]; then
echo "✅ 至少有一个构建成功,可以创建 Gitee Release"
echo "should_create=true" >> $GITHUB_OUTPUT
else
echo "❌ 所有构建都失败,跳过创建 Gitee Release"
echo "should_create=false" >> $GITHUB_OUTPUT
exit 1
fi
# ============================================================
# 校验 Gitee 附件大小(超过 100MB 直接失败)
# ============================================================
verify-gitee-assets:
name: Verify Gitee Assets(校验 Gitee 附件大小)
if: (github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')) && github.event_name == 'release' && needs.check-any-build-success.outputs.should_create_release == 'true'
needs: [ check-any-build-success, build-windows-portable, build-windows-exe, build-macos-arm ]
runs-on: ubuntu-latest
steps:
- name: Download Windows Portable artifact(下载 Windows 绿色版产物)
if: needs.build-windows-portable.result == 'success'
uses: actions/download-artifact@v4
with:
name: EasyPostman-Windows-Portable
path: verify/windows-portable
- name: Download Windows EXE artifact(下载 Windows EXE 产物)
if: needs.build-windows-exe.result == 'success'
uses: actions/download-artifact@v4
with:
name: EasyPostman-Windows-EXE
path: verify/windows-exe
- name: Download macOS ARM artifact(下载 macOS ARM 产物)
if: needs.build-macos-arm.result == 'success'
uses: actions/download-artifact@v4
with:
name: EasyPostman-macOS-ARM-DMG
path: verify/macos-arm
- name: Validate asset size(校验附件大小)
run: |
validate_file() {
FILE="$1"
LABEL="$2"
if [ ! -f "$FILE" ]; then
echo "❌ Missing expected artifact for $LABEL: $FILE"
exit 1
fi
FILE_SIZE=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE")
FILE_SIZE_MB=$(echo "scale=2; $FILE_SIZE/1048576" | bc)
echo "📏 $LABEL: ${FILE_SIZE_MB} MB"
if [ "$FILE_SIZE" -gt 104857600 ]; then
echo "❌ $LABEL exceeds Gitee 100MB limit: ${FILE_SIZE_MB} MB"
exit 1
fi
}
if [ "${{ needs.build-windows-portable.result }}" = "success" ]; then
validate_file "$(find verify/windows-portable -name '*-portable.zip' | head -n 1)" "Windows Portable"
fi
if [ "${{ needs.build-windows-exe.result }}" = "success" ]; then
validate_file "$(find verify/windows-exe -name '*.exe' | head -n 1)" "Windows EXE"
fi
if [ "${{ needs.build-macos-arm.result }}" = "success" ]; then
validate_file "$(find verify/macos-arm -name '*-macos-arm64.dmg' | head -n 1)" "macOS ARM"
fi
# ============================================================
# 创建 Gitee Release
# ============================================================
create-gitee-release:
name: Create Gitee Release(创建 Gitee Release)
if: (github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')) && github.event_name == 'release' && needs.check-any-build-success.outputs.should_create_release == 'true'
needs: [ get-version, check-any-build-success, verify-gitee-assets ]
runs-on: ubuntu-latest
outputs:
release_id: ${{ steps.gitee_release.outputs.release_id }}
tag_name: ${{ steps.get_version.outputs.tag }}
steps:
- name: Get version from tag(从标签获取版本号)
id: get_version
run: |
TAG_NAME="${{ github.event.release.tag_name }}"
VERSION="${TAG_NAME#v}"
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=$TAG_NAME" >> $GITHUB_OUTPUT
- name: Create Gitee Release(创建 Gitee Release)
id: gitee_release
run: |
VERSION="${{ steps.get_version.outputs.version }}"
TAG_NAME="${{ steps.get_version.outputs.tag }}"
RELEASE_BODY="${{ github.event.release.body }}"
if [ -z "$RELEASE_BODY" ]; then
RELEASE_BODY="EasyPostman ${VERSION} 发布版本,支持 Windows、macOS 和 Linux。"
fi
# 把 body 写入临时文件,方便处理特殊字符
BODY_FILE="/tmp/release_body.txt"
printf '%s\n' "${RELEASE_BODY}" > "$BODY_FILE"
echo "🚀 Creating Gitee Release for tag: $TAG_NAME"
# 重试机制
MAX_RETRIES=3
RETRY_COUNT=0
SUCCESS=false
while [ $RETRY_COUNT -lt $MAX_RETRIES ] && [ "$SUCCESS" = false ]; do
echo "⏳ Attempt $((RETRY_COUNT + 1))/$MAX_RETRIES..."
# 使用更健壮的 curl 选项
# --retry 3: curl 内部重试 3 次
# --retry-delay 2: 重试间隔 2 秒
# --connect-timeout 30: 连接超时 30 秒
# --max-time 60: 整体超时 60 秒
set +e # 临时禁用 exit on error
HTTP_CODE=$(curl -w "%{http_code}" \
--retry 3 \
--retry-delay 2 \
--connect-timeout 30 \
--max-time 60 \
-S -X POST \
-F "access_token=${{ secrets.GITEE_TOKEN }}" \
-F "tag_name=$TAG_NAME" \
-F "name=$TAG_NAME" \
-F "body=<${BODY_FILE}" \
-F "prerelease=false" \
-F "target_commitish=master" \
"https://gitee.com/api/v5/repos/lakernote/easy-postman/releases" \
-o /tmp/release.json 2>&1 | tail -n1)
CURL_EXIT_CODE=$?
set -e # 重新启用 exit on error
echo "curl exit code: $CURL_EXIT_CODE"
echo "HTTP Status Code: $HTTP_CODE"
if [ $CURL_EXIT_CODE -eq 0 ] && [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
SUCCESS=true
echo "✅ API call successful!"
else
RETRY_COUNT=$((RETRY_COUNT + 1))
if [ $RETRY_COUNT -lt $MAX_RETRIES ]; then
echo "⚠️ Failed (curl: $CURL_EXIT_CODE, HTTP: $HTTP_CODE), retrying in 5 seconds..."
sleep 5
fi
fi
done
if [ "$SUCCESS" = false ]; then
echo "❌ Failed to create Gitee Release after $MAX_RETRIES attempts"
echo "Last curl exit code: $CURL_EXIT_CODE"
echo "Last HTTP code: $HTTP_CODE"
cat /tmp/release.json 2>/dev/null || echo "No response file"
exit 1
fi
echo "API Response:"
cat /tmp/release.json
# 优先使用 jq(GitHub Actions Ubuntu runner 预装)
RELEASE_ID=$(jq -r '.id // empty' /tmp/release.json 2>/dev/null || echo "")
if [ -z "$RELEASE_ID" ]; then
echo "jq extraction failed, trying python3..."
RELEASE_ID=$(python3 -c "import sys, json; print(json.load(open('/tmp/release.json'))['id'])" 2>/dev/null || echo "")
fi
if [ -z "$RELEASE_ID" ]; then
echo "python3 failed, trying grep..."
RELEASE_ID=$(grep -o '"id":[0-9]*' /tmp/release.json | head -1 | grep -o '[0-9]*')
fi
if [ -z "$RELEASE_ID" ]; then
echo "❌ Error: Failed to extract release ID from response"
exit 1
fi
echo "release_id=$RELEASE_ID" >> $GITHUB_OUTPUT
echo "✅ Gitee Release created successfully with ID: $RELEASE_ID"
# Windows 绿色版上传到 Gitee
sync-windows-portable-to-gitee:
name: Upload Windows Portable to Gitee(上传 Windows 绿色版到 Gitee)
if: (github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')) && github.event_name == 'release' && needs.build-windows-portable.result == 'success'
needs: [ create-gitee-release, build-windows-portable ]
runs-on: ubuntu-latest
steps:
- name: Download Windows Portable artifact(下载 Windows 绿色版产物)
uses: actions/download-artifact@v4
with:
name: EasyPostman-Windows-Portable
path: artifacts
- name: Upload Windows Portable to Gitee(上传 Windows 绿色版到 Gitee)
run: |
RELEASE_ID="${{ needs.create-gitee-release.outputs.release_id }}"
FILE=$(find artifacts -name "*-portable.zip" | head -n 1)
if [ -z "$FILE" ]; then
echo "❌ Windows Portable ZIP file not found!"
exit 1
fi
FILE_SIZE=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE")
FILE_SIZE_MB=$(echo "scale=2; $FILE_SIZE/1048576" | bc)
echo "📏 File size: ${FILE_SIZE_MB} MB"
if [ "$FILE_SIZE" -gt 104857600 ]; then
echo "❌ File size ${FILE_SIZE_MB} MB exceeds Gitee 100MB limit."
exit 1
fi
echo "📦 Uploading $(basename $FILE) to Gitee..."
MAX_RETRIES=3
RETRY_COUNT=0
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
if curl -X POST "https://gitee.com/api/v5/repos/lakernote/easy-postman/releases/$RELEASE_ID/attach_files" \
-F "access_token=${{ secrets.GITEE_TOKEN }}" \
-F "file=@$FILE"; then
echo "✅ Windows Portable uploaded successfully!"
exit 0
else
RETRY_COUNT=$((RETRY_COUNT + 1))
[ $RETRY_COUNT -lt $MAX_RETRIES ] && echo "⚠️ Retrying ($RETRY_COUNT/$MAX_RETRIES)..." && sleep 5
fi
done
echo "❌ Failed to upload Windows Portable after $MAX_RETRIES attempts"
exit 1
# Windows EXE 上传到 Gitee
sync-windows-exe-to-gitee:
name: Upload Windows EXE to Gitee(上传 Windows EXE 到 Gitee)
if: (github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')) && github.event_name == 'release' && needs.build-windows-exe.result == 'success'
needs: [ create-gitee-release, build-windows-exe ]
runs-on: ubuntu-latest
steps:
- name: Download Windows EXE artifact(下载 Windows EXE 产物)
uses: actions/download-artifact@v4
with:
name: EasyPostman-Windows-EXE
path: artifacts
- name: Upload Windows EXE to Gitee(上传 Windows EXE 到 Gitee)
run: |
RELEASE_ID="${{ needs.create-gitee-release.outputs.release_id }}"
FILE=$(find artifacts -name "*.exe" | head -n 1)
if [ -z "$FILE" ]; then
echo "❌ Windows EXE file not found!"
exit 1
fi
FILE_SIZE=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE")
FILE_SIZE_MB=$(echo "scale=2; $FILE_SIZE/1048576" | bc)
echo "📏 File size: ${FILE_SIZE_MB} MB"
if [ "$FILE_SIZE" -gt 104857600 ]; then
echo "❌ File size ${FILE_SIZE_MB} MB exceeds Gitee 100MB limit."
exit 1
fi
echo "📦 Uploading $(basename $FILE) to Gitee..."
MAX_RETRIES=3
RETRY_COUNT=0
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
if curl -X POST "https://gitee.com/api/v5/repos/lakernote/easy-postman/releases/$RELEASE_ID/attach_files" \
-F "access_token=${{ secrets.GITEE_TOKEN }}" \
-F "file=@$FILE"; then
echo "✅ Windows EXE uploaded successfully!"
exit 0
else
RETRY_COUNT=$((RETRY_COUNT + 1))
[ $RETRY_COUNT -lt $MAX_RETRIES ] && echo "⚠️ Retrying ($RETRY_COUNT/$MAX_RETRIES)..." && sleep 5
fi
done
echo "❌ Failed to upload Windows EXE after $MAX_RETRIES attempts"
exit 1
# macOS ARM 上传到 Gitee
sync-macos-to-gitee:
name: Upload macOS ARM to Gitee(上传 macOS ARM 到 Gitee)
if: (github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')) && github.event_name == 'release' && needs.build-macos-arm.result == 'success'
needs: [ create-gitee-release, build-macos-arm ]
runs-on: ubuntu-latest
steps:
- name: Download macOS ARM artifact(下载 macOS ARM 产物)
uses: actions/download-artifact@v4
with:
name: EasyPostman-macOS-ARM-DMG
path: artifacts
- name: Upload macOS ARM to Gitee(上传 macOS ARM 到 Gitee)
run: |
RELEASE_ID="${{ needs.create-gitee-release.outputs.release_id }}"
FILE=$(find artifacts -name "*-macos-arm64.dmg" | head -n 1)
if [ -z "$FILE" ]; then
echo "❌ macOS ARM DMG file not found!"
exit 1
fi
FILE_SIZE=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE")
FILE_SIZE_MB=$(echo "scale=2; $FILE_SIZE/1048576" | bc)
echo "📏 File size: ${FILE_SIZE_MB} MB"
if [ "$FILE_SIZE" -gt 104857600 ]; then
echo "❌ File size ${FILE_SIZE_MB} MB exceeds Gitee 100MB limit."
exit 1
fi
echo "🍎 Uploading $(basename $FILE) to Gitee..."
MAX_RETRIES=3
RETRY_COUNT=0
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
if curl -X POST "https://gitee.com/api/v5/repos/lakernote/easy-postman/releases/$RELEASE_ID/attach_files" \
-F "access_token=${{ secrets.GITEE_TOKEN }}" \
-F "file=@$FILE"; then
echo "✅ macOS ARM uploaded successfully!"
exit 0
else
RETRY_COUNT=$((RETRY_COUNT + 1))
[ $RETRY_COUNT -lt $MAX_RETRIES ] && echo "⚠️ Retrying ($RETRY_COUNT/$MAX_RETRIES)..." && sleep 5
fi
done
echo "❌ Failed to upload macOS ARM after $MAX_RETRIES attempts"
exit 1
# 汇总结果
sync-summary:
name: Sync Summary(同步汇总)
if: |
(github.event_name != 'release' || startsWith(github.event.release.tag_name || '', 'v')) &&
github.event_name == 'release' &&
always()
needs: [ check-any-build-success, verify-gitee-assets, create-gitee-release, sync-windows-portable-to-gitee, sync-windows-exe-to-gitee, sync-macos-to-gitee ]
runs-on: ubuntu-latest
steps:
- name: Summary(汇总)
run: |
echo "📊 Gitee Release 同步完成!"
CHECK_STATUS="${{ needs.check-any-build-success.result }}"
VERIFY_STATUS="${{ needs.verify-gitee-assets.result }}"
RELEASE_STATUS="${{ needs.create-gitee-release.result }}"
PORTABLE_STATUS="${{ needs.sync-windows-portable-to-gitee.result }}"
EXE_STATUS="${{ needs.sync-windows-exe-to-gitee.result }}"
MACOS_STATUS="${{ needs.sync-macos-to-gitee.result }}"
echo ""
echo "🔍 构建检查结果: $CHECK_STATUS"
echo "📏 Gitee 附件校验: $VERIFY_STATUS"
echo "📝 Gitee Release 创建: $RELEASE_STATUS"
if [ "$RELEASE_STATUS" == "success" ]; then
echo "📍 Release URL: https://gitee.com/lakernote/easy-postman/releases/${{ needs.create-gitee-release.outputs.tag_name }}"
fi
echo ""
echo "已同步到 Gitee 的文件:"
echo " 📦 Windows Portable (绿色版) - $PORTABLE_STATUS"
echo " 🪟 Windows EXE (安装包) - $EXE_STATUS"
echo " 🍎 macOS Apple Silicon (ARM64) - $MACOS_STATUS"
echo ""
if [ "$CHECK_STATUS" == "failure" ]; then
echo "❌ 所有构建都失败,未创建 Gitee Release"
exit 1
fi
if [ "$VERIFY_STATUS" == "failure" ] || [ "$RELEASE_STATUS" == "failure" ] || \
[ "$PORTABLE_STATUS" == "failure" ] || [ "$EXE_STATUS" == "failure" ] || [ "$MACOS_STATUS" == "failure" ]; then
echo "❌ Gitee Release 流程存在失败步骤"
exit 1
fi
echo "✅ Gitee Release 创建成功,附件上传完成"