name: Deploy Client on: push: tags: - 'client-v[0-9]*.[0-9]*.[0-9]*' # 手动运行(在 tag 上 Run workflow)时可指定 Windows 构建来源,无需改仓库变量。 # 走 github 模式:选该版本的 tag 作为 ref 运行 + windows_source=github。 workflow_dispatch: inputs: windows_source: description: 'Windows 构建来源:home=家里 runner(默认) / github=从 NAS 拉 GitHub 云构建' required: false default: home type: choice options: [home, github] concurrency: group: deploy-client cancel-in-progress: false jobs: build-client-web: runs-on: mac env: GOPROXY: https://goproxy.cn,direct PUB_HOSTED_URL: https://pub.flutter-io.cn FLUTTER_STORAGE_BASE_URL: https://storage.flutter-io.cn steps: - uses: actions/checkout@v4 - name: Provision (idempotent — auto-runs if host not initialized) run: sh scripts/ci/provision-mac.sh - name: Compile (Flutter Web) run: sh scripts/ci/compile-client-web.sh "${{ gitea.ref_name }}" - name: Upload web artifacts uses: actions/upload-artifact@v3 with: name: client-web path: dist/ build-macos: needs: build-client-web runs-on: mac env: PUB_HOSTED_URL: https://pub.flutter-io.cn FLUTTER_STORAGE_BASE_URL: https://storage.flutter-io.cn steps: - uses: actions/checkout@v4 - name: Provision (idempotent — auto-runs if host not initialized) run: sh scripts/ci/provision-mac.sh - name: Compile (Flutter macOS) env: MACOS_DEVELOPER_ID_CERT_P12_BASE64: ${{ secrets.MACOS_DEVELOPER_ID_CERT_P12_BASE64 }} MACOS_DEVELOPER_ID_CERT_PASSWORD: ${{ secrets.MACOS_DEVELOPER_ID_CERT_PASSWORD }} APPSTORE_API_KEY_ID: ${{ secrets.APPSTORE_API_KEY_ID }} APPSTORE_API_ISSUER_ID: ${{ secrets.APPSTORE_API_ISSUER_ID }} APPSTORE_API_KEY_P8_BASE64: ${{ secrets.APPSTORE_API_KEY_P8_BASE64 }} run: sh scripts/ci/compile-macos.sh "${{ gitea.ref_name }}" - name: Upload macos artifacts uses: actions/upload-artifact@v3 with: name: macos path: dist/ build-android: needs: build-macos runs-on: mac env: PUB_HOSTED_URL: https://pub.flutter-io.cn FLUTTER_STORAGE_BASE_URL: https://storage.flutter-io.cn steps: - uses: actions/checkout@v4 - name: Provision (idempotent — auto-runs if host not initialized) run: sh scripts/ci/provision-mac.sh - name: Compile (Flutter Android APK) env: ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} run: sh scripts/ci/compile-android.sh "${{ gitea.ref_name }}" - name: Upload android artifacts uses: actions/upload-artifact@v3 with: name: android path: dist/ build-ios: needs: build-android runs-on: mac env: PUB_HOSTED_URL: https://pub.flutter-io.cn FLUTTER_STORAGE_BASE_URL: https://storage.flutter-io.cn steps: - uses: actions/checkout@v4 - name: Provision (idempotent — auto-runs if host not initialized) run: sh scripts/ci/provision-mac.sh - name: Compile & upload to TestFlight (Flutter iOS) env: IOS_DIST_CERT_P12_BASE64: ${{ secrets.IOS_DIST_CERT_P12_BASE64 }} IOS_DIST_CERT_PASSWORD: ${{ secrets.IOS_DIST_CERT_PASSWORD }} IOS_PROVISIONING_PROFILE_BASE64: ${{ secrets.IOS_PROVISIONING_PROFILE_BASE64 }} IOS_TEAM_ID: ${{ secrets.IOS_TEAM_ID }} APPSTORE_API_KEY_ID: ${{ secrets.APPSTORE_API_KEY_ID }} APPSTORE_API_ISSUER_ID: ${{ secrets.APPSTORE_API_ISSUER_ID }} APPSTORE_API_KEY_P8_BASE64: ${{ secrets.APPSTORE_API_KEY_P8_BASE64 }} run: sh scripts/ci/compile-ios.sh "${{ gitea.ref_name }}" # 默认:家里那台 Windows runner 构建(回家后照常用)。 # 仅当 gitea 仓库变量 WINDOWS_SOURCE=github 时跳过,改由 build-windows-ci 从 NAS 拉云构建。 build-windows: # 来源判定:运行参数 windows_source 优先,其次仓库变量 WINDOWS_SOURCE,默认 home。 if: ${{ (github.event.inputs.windows_source || vars.WINDOWS_SOURCE || 'home') != 'github' }} runs-on: windows env: GOPROXY: https://goproxy.cn,direct PUB_HOSTED_URL: https://pub.flutter-io.cn FLUTTER_STORAGE_BASE_URL: https://storage.flutter-io.cn steps: - uses: actions/checkout@v4 - name: Provision (idempotent — auto-runs if host not initialized) shell: bash run: sh scripts/ci/provision-windows.sh - name: Compile (Flutter Windows) shell: bash run: sh scripts/ci/compile-windows.sh "${{ gitea.ref_name }}" - name: Upload windows artifacts uses: actions/upload-artifact@v3 with: name: windows path: dist/ # 特殊:家里 Windows 关机/连不上时,从 NAS 暂存拉 GitHub 云构建的安装器(版本强匹配)。 # 启用:gitea 仓库设变量 WINDOWS_SOURCE=github,并先在 GitHub 跑 windows.yml 构建该版本。 # 产出同名 windows artifact,下游 release-deploy-client 无需改动。 build-windows-ci: if: ${{ (github.event.inputs.windows_source || vars.WINDOWS_SOURCE || 'home') == 'github' }} runs-on: mac steps: - uses: actions/checkout@v4 - name: Fetch staged Windows installer from NAS env: FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }} FORGEJO_URL: ${{ secrets.FORGEJO_URL }} GITEA_REPOSITORY: ${{ gitea.repository }} run: sh scripts/ci/fetch-windows-staged.sh "${{ gitea.ref_name }}" - name: Upload windows artifacts uses: actions/upload-artifact@v3 with: name: windows path: dist/ release-deploy-client: needs: [build-client-web, build-macos, build-android, build-ios, build-windows, build-windows-ci] # 家里/云 两条 Windows 腿只会跑一条(另一条 skipped)。用 always() + 显式成功判定, # 只要其中一条 windows 成功、且其余端全绿就继续发版。 if: | always() && needs.build-client-web.result == 'success' && needs.build-macos.result == 'success' && needs.build-android.result == 'success' && needs.build-ios.result == 'success' && (needs.build-windows.result == 'success' || needs.build-windows-ci.result == 'success') runs-on: mac env: GOPROXY: https://goproxy.cn,direct PUB_HOSTED_URL: https://pub.flutter-io.cn FLUTTER_STORAGE_BASE_URL: https://storage.flutter-io.cn steps: - uses: actions/checkout@v4 - name: Download web artifacts uses: actions/download-artifact@v3 with: name: client-web path: dist/ - name: Download macos artifacts uses: actions/download-artifact@v3 with: name: macos path: dist/ - name: Download android artifacts uses: actions/download-artifact@v3 with: name: android path: dist/ - name: Download windows artifacts uses: actions/download-artifact@v3 with: name: windows path: dist/ - name: Test (flutter analyze) run: sh scripts/ci/test.sh client - name: Release env: FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }} FORGEJO_URL: ${{ secrets.FORGEJO_URL }} GITEA_REPOSITORY: ${{ gitea.repository }} run: sh scripts/ci/release-client.sh "${{ gitea.ref_name }}" # 2026-07-03 割接后阿里机即唯一发布目标(EC2 轨移除;EC2 仅保留 # jiu.51yanmei.com 反代桥接到 ali,见 baize 台账)。 - name: Deploy → Ali env: FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }} FORGEJO_URL: ${{ secrets.FORGEJO_URL }} GITEA_REPOSITORY: ${{ gitea.repository }} DEPLOY_SSH_KEY: ${{ secrets.ALI_SSH_KEY }} DEPLOY_HOST: ${{ secrets.ALI_HOST }} DEPLOY_USER: ${{ secrets.ALI_USER }} run: sh scripts/ci/deploy-client.sh "${{ gitea.ref_name }}" - name: Notify if: always() env: TELEGRAM_TOKEN: ${{ secrets.TELEGRAM_TOKEN }} TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} run: sh scripts/ci/notify.sh "${{ gitea.ref_name }}" "${{ job.status }}"