name: Build All UI APP on: push: branches: - 'android-app' workflow_dispatch: jobs: prepare: name: Prepare Version runs-on: ubuntu-latest outputs: version: ${{ steps.version.outputs.VERSION }} app_version: ${{ steps.version.outputs.APP_VERSION }} is_release: ${{ steps.version.outputs.IS_RELEASE }} steps: - name: Checkout code uses: actions/checkout@v4 - name: Get version info id: version run: | BASE_VERSION=$(cat VERSION) if [[ "${{ github.ref }}" == refs/tags/* ]]; then VERSION=${GITHUB_REF#refs/tags/} APP_VERSION=${VERSION#v} IS_RELEASE="true" else APP_VERSION="$BASE_VERSION" VERSION=v${BASE_VERSION} IS_RELEASE="false" fi echo "VERSION=$VERSION" >> $GITHUB_OUTPUT echo "APP_VERSION=$APP_VERSION" >> $GITHUB_OUTPUT echo "IS_RELEASE=$IS_RELEASE" >> $GITHUB_OUTPUT echo "Building version: $VERSION" echo "App version: $APP_VERSION" build-android: name: Build Android APK needs: prepare runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v5 with: go-version: '1.25.3' cache: true - name: Install Fyne CLI run: | go install fyne.io/tools/cmd/fyne@latest - name: Set up JDK 17 uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '17' - name: Install Android SDK uses: android-actions/setup-android@v3 with: packages: 'platform-tools' - name: Install Android NDK run: | sdkmanager --install "ndk;25.2.9519653" echo "ANDROID_NDK_HOME=$ANDROID_SDK_ROOT/ndk/25.2.9519653" >> $GITHUB_ENV - name: Install Android Build Tools run: | sdkmanager --install "build-tools;33.0.2" sdkmanager --install "platforms;android-33" - name: Configure Git for Private Modules run: | git config --global url."https://${{ secrets.GHT }}@github.com/".insteadOf "https://github.com/" git config --global url."git@github.com:".insteadOf "https://github.com/" env: GITHUB_TOKEN: ${{ secrets.GHT }} - name: Download dependencies run: go mod download env: GOPRIVATE: github.com/oneclickvirt/security - name: Verify dependencies run: go mod verify - name: Download ECS binaries for embed run: | REPO="oneclickvirt/ecs" BINARIES_DIR="embedding/binaries" mkdir -p "$BINARIES_DIR" # 使用 gh CLI 获取最新版本 echo "获取最新版本信息..." ECS_VERSION=$(gh release view --repo "$REPO" --json tagName --jq '.tagName') if [ -z "$ECS_VERSION" ]; then echo "错误: 无法获取最新版本" exit 1 fi echo "ECS 版本: $ECS_VERSION" # 下载 Linux ARM64(用于 Android ARM64) echo "下载 Linux ARM64..." gh release download "$ECS_VERSION" --repo "$REPO" --pattern "goecs_linux_arm64.zip" --output "/tmp/goecs_linux_arm64.zip" unzip -q -o "/tmp/goecs_linux_arm64.zip" -d /tmp/ mv /tmp/goecs "${BINARIES_DIR}/goecs-linux-arm64" chmod +x "${BINARIES_DIR}/goecs-linux-arm64" # 下载 Linux AMD64(用于 Android x86_64) echo "下载 Linux AMD64..." gh release download "$ECS_VERSION" --repo "$REPO" --pattern "goecs_linux_amd64.zip" --output "/tmp/goecs_linux_amd64.zip" unzip -q -o "/tmp/goecs_linux_amd64.zip" -d /tmp/ mv /tmp/goecs "${BINARIES_DIR}/goecs-linux-amd64" chmod +x "${BINARIES_DIR}/goecs-linux-amd64" echo "" echo "二进制文件列表:" ls -lh "${BINARIES_DIR}/" echo "" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Update FyneApp.toml version run: | sed -i "s/Version = .*/Version = \"${{ needs.prepare.outputs.version }}\"/" FyneApp.toml cat FyneApp.toml - name: Build Android APK (arm64) env: ANDROID_NDK_HOME: ${{ env.ANDROID_NDK_HOME }} GOPRIVATE: github.com/oneclickvirt/security run: | fyne package --os android --app-id com.oneclickvirt.goecs --app-version "${{ needs.prepare.outputs.app_version }}" if [ -f *.apk ]; then mkdir -p .build mv *.apk .build/goecs-gui-android-arm64-${{ needs.prepare.outputs.version }}.apk echo "ARM64 APK 构建成功" else echo "ARM64 APK 构建失败" exit 1 fi - name: Build Android APK (x86_64) env: ANDROID_NDK_HOME: ${{ env.ANDROID_NDK_HOME }} GOPRIVATE: github.com/oneclickvirt/security run: | fyne package --os android/amd64 --app-id com.oneclickvirt.goecs --app-version "${{ needs.prepare.outputs.app_version }}" if [ -f *.apk ]; then mv *.apk .build/goecs-gui-android-x86_64-${{ needs.prepare.outputs.version }}.apk echo "x86_64 APK 构建成功" else echo "x86_64 APK 构建失败" exit 1 fi - name: List build artifacts run: | ls -lh .build/ du -sh .build/*.apk - name: Get release id: get_release shell: bash run: | LATEST_RELEASE=$(gh release list --limit 1 --json tagName --jq '.[0].tagName') if [ -z "$LATEST_RELEASE" ] || [ "$LATEST_RELEASE" == "null" ]; then exit 1 else RELEASE_TAG="$LATEST_RELEASE" echo "Found existing release: $RELEASE_TAG" fi echo "RELEASE_TAG=$RELEASE_TAG" >> $GITHUB_OUTPUT env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Upload to release shell: bash run: | cd .build for file in *; do if [ -f "$file" ]; then echo "Uploading $file to release ${{ steps.get_release.outputs.RELEASE_TAG }}" gh release upload "${{ steps.get_release.outputs.RELEASE_TAG }}" "$file" --clobber fi done env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Upload ARM64 APK uses: actions/upload-artifact@v4 with: name: goecs-gui-android-arm64-${{ needs.prepare.outputs.version }} path: .build/goecs-gui-android-arm64-${{ needs.prepare.outputs.version }}.apk retention-days: 90 - name: Upload x86_64 APK uses: actions/upload-artifact@v4 with: name: goecs-gui-android-x86_64-${{ needs.prepare.outputs.version }} path: .build/goecs-gui-android-x86_64-${{ needs.prepare.outputs.version }}.apk retention-days: 90 build-desktop: name: Build Desktop Apps needs: prepare runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: include: # macOS builds - os: macos-latest platform: darwin arch: arm64 name: macos-arm64 - os: macos-13 # Intel Mac runner platform: darwin arch: amd64 name: macos-amd64 # Windows builds - os: windows-latest platform: windows arch: amd64 name: windows-amd64 steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v5 with: go-version: '1.25.3' cache: true - name: Install Fyne CLI run: go install fyne.io/tools/cmd/fyne@latest - name: Configure Git for Private Modules run: | git config --global url."https://${{ secrets.GHT }}@github.com/".insteadOf "https://github.com/" env: GITHUB_TOKEN: ${{ secrets.GHT }} - name: Download dependencies run: go mod download env: GOPRIVATE: github.com/oneclickvirt/security - name: Verify dependencies run: go mod verify - name: Download ECS binaries for embed shell: bash run: | REPO="oneclickvirt/ecs" BINARIES_DIR="embedding/binaries" TARGET_OS="${{ matrix.platform }}" TARGET_ARCH="${{ matrix.arch }}" mkdir -p "$BINARIES_DIR" # 使用 gh CLI 获取最新版本(更简单可靠) echo "获取最新版本信息..." ECS_VERSION=$(gh release view --repo "$REPO" --json tagName --jq '.tagName') if [ -z "$ECS_VERSION" ]; then echo "错误: 无法获取最新版本" exit 1 fi echo "ECS 版本: $ECS_VERSION" echo "目标平台: $TARGET_OS/$TARGET_ARCH" # Windows 需要 .exe 后缀 if [ "$TARGET_OS" == "windows" ]; then OUTPUT_FILE="${BINARIES_DIR}/goecs-${TARGET_OS}-${TARGET_ARCH}.exe" else OUTPUT_FILE="${BINARIES_DIR}/goecs-${TARGET_OS}-${TARGET_ARCH}" fi PATTERN="goecs_${TARGET_OS}_${TARGET_ARCH}.zip" echo "下载 ${TARGET_OS}/${TARGET_ARCH}..." echo "Pattern: $PATTERN" echo "Output: $OUTPUT_FILE" # 下载到临时文件 gh release download "$ECS_VERSION" --repo "$REPO" --pattern "$PATTERN" --output "/tmp/goecs.zip" unzip -q -o "/tmp/goecs.zip" -d /tmp/ if [ -f "/tmp/goecs.exe" ]; then mv /tmp/goecs.exe "$OUTPUT_FILE" elif [ -f "/tmp/goecs" ]; then mv /tmp/goecs "$OUTPUT_FILE" chmod +x "$OUTPUT_FILE" else echo "错误: 找不到解压后的二进制文件" exit 1 fi echo "" echo "二进制文件列表:" ls -lh "${BINARIES_DIR}/" echo "" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Update FyneApp.toml version shell: bash run: | if [ "${{ runner.os }}" == "macOS" ]; then sed -i '' "s/Version = .*/Version = \"${{ needs.prepare.outputs.version }}\"/" FyneApp.toml else sed -i "s/Version = .*/Version = \"${{ needs.prepare.outputs.version }}\"/" FyneApp.toml fi cat FyneApp.toml - name: Build for ${{ matrix.name }} env: GOPRIVATE: github.com/oneclickvirt/security shell: bash run: | # macOS 需要特殊处理:先编译再打包 if [ "${{ matrix.platform }}" == "darwin" ]; then echo "Building macOS binary with ldflags..." go build -ldflags "-checklinkname=0 -s -w" -o goecs-bin . echo "Packaging macOS app with fyne..." fyne package -os darwin -name goecs --exe goecs-bin --app-version "${{ needs.prepare.outputs.app_version }}" if [ -d goecs.app ]; then mkdir -p .build TARFILE="goecs-gui-${{ matrix.name }}-${{ needs.prepare.outputs.version }}.tar.gz" echo "Creating tar file: $TARFILE" tar -czf "$TARFILE" goecs.app mv "$TARFILE" .build/ echo "✓ macOS app 构建成功" else echo "✗ macOS app 构建失败" exit 1 fi else # Windows 直接使用 fyne package echo "Building ${{ matrix.platform }} with fyne package..." fyne package -os ${{ matrix.platform }} -name goecs --app-version "${{ needs.prepare.outputs.app_version }}" if [ "${{ matrix.platform }}" == "windows" ]; then if [ -f goecs.exe ]; then mkdir -p .build mv goecs.exe .build/goecs-gui-${{ matrix.name }}-${{ needs.prepare.outputs.version }}.exe echo "✓ Windows exe 构建成功" else echo "✗ Windows exe 构建失败" exit 1 fi fi fi - name: List build artifacts shell: bash run: | ls -lh .build/ du -sh .build/* - name: Get release id: get_release shell: bash run: | LATEST_RELEASE=$(gh release list --limit 1 --json tagName --jq '.[0].tagName') if [ -z "$LATEST_RELEASE" ] || [ "$LATEST_RELEASE" == "null" ]; then exit 1 else RELEASE_TAG="$LATEST_RELEASE" echo "Found existing release: $RELEASE_TAG" fi echo "RELEASE_TAG=$RELEASE_TAG" >> $GITHUB_OUTPUT env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Upload to release shell: bash run: | cd .build for file in *; do if [ -f "$file" ]; then echo "Uploading $file to release ${{ steps.get_release.outputs.RELEASE_TAG }}" gh release upload "${{ steps.get_release.outputs.RELEASE_TAG }}" "$file" --clobber fi done env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}