6756cea413
Deploy Client / build-android (push) Successful in 1m37s
Deploy Client / build-macos (push) Failing after 3s
Deploy Client / build-ios (push) Successful in 3s
Deploy Client / release-deploy (push) Successful in 1m1s
Deploy Client / build-windows (push) Successful in 1m57s
209 lines
8.8 KiB
YAML
209 lines
8.8 KiB
YAML
name: Deploy Client
|
|
|
|
# Mirrors ~/code/jiu/.gitea/workflows/deploy-client.yml's tag→build→release→
|
|
# deploy shape. Android + Windows are required (release-deploy `needs` them);
|
|
# macOS + iOS (Phase 3, see docs/superpowers/plans/2026-07-05-cicd.md) are
|
|
# intentionally DECOUPLED — see the "why build-macos/build-ios don't block"
|
|
# note above the build-macos job below for the mechanism and rationale.
|
|
#
|
|
# TODO(controller) — RUNNER AVAILABILITY: per docs/ci-runner.md, pangolin
|
|
# currently has exactly ONE registered Gitea Actions runner
|
|
# ("mac-pangolin-2", label `nas:host`). Neither `runs-on: mac` nor
|
|
# `runs-on: windows` below has any runner registered to pick it up yet — this
|
|
# workflow will queue forever until that's fixed. Options: (a) register
|
|
# mac-pangolin-2 with an additional `mac` label (it's already a mac host —
|
|
# cheapest fix for build-android/release-deploy) and separately stand up +
|
|
# register an actual Windows host runner labeled `windows` for build-windows
|
|
# (no such machine exists per docs/ci-runner.md), or (b) repoint both at
|
|
# `nas` and accept that Android/Windows builds then compete with the
|
|
# docker-in-domain nas jobs on the same single mac host. This mirrors the
|
|
# `runs-on: mac` / `runs-on: windows` split already planned in
|
|
# docs/superpowers/plans/2026-07-05-cicd.md Task 7/10 — written that way here
|
|
# for fidelity to that plan, NOT because the runners are confirmed to exist.
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'client-v[0-9]*.[0-9]*.[0-9]*'
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
group: deploy-client
|
|
# true:新 client-v* 取消仍在跑的旧发版(如 windows 机离线导致 build-windows 无限排队
|
|
# 卡住的旧 run),让最新版顺利发布,避免并发组被僵尸 run 占死。
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
build-android:
|
|
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:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Compile (Android APK)
|
|
env:
|
|
RELEASE_KEYSTORE: ${{ secrets.RELEASE_KEYSTORE }}
|
|
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
|
|
REF_NAME: ${{ gitea.ref_name }}
|
|
run: bash scripts/ci/compile-android.sh "$REF_NAME"
|
|
|
|
- name: Upload android artifact
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: android
|
|
path: dist/
|
|
|
|
build-windows:
|
|
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:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Compile (Windows installer)
|
|
shell: bash
|
|
env:
|
|
REF_NAME: ${{ gitea.ref_name }}
|
|
run: bash scripts/ci/compile-windows.sh "$REF_NAME"
|
|
|
|
- name: Upload windows artifact
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: windows
|
|
path: dist/
|
|
|
|
# Why build-macos/build-ios don't block the working android+windows pipeline
|
|
# when Apple secrets aren't configured yet (they aren't, as of this writing):
|
|
# 1. release-deploy's `needs:` below is [build-android, build-windows]
|
|
# ONLY — macOS/iOS are NOT dependencies, so release-deploy never waits
|
|
# on them and never fails because of them.
|
|
# 2. `continue-on-error: true` on both jobs keeps the overall workflow-run
|
|
# status green even while compile-macos.sh hard-fails (Apple Developer
|
|
# ID / notary secrets absent — see its fail-fast checks) — that failure
|
|
# is real signal ("go configure the secrets"), but it shouldn't read as
|
|
# "the release pipeline is broken" when android+windows shipped fine.
|
|
# 3. compile-macos.sh's own default behavior is to hard-fail (not skip)
|
|
# when its secrets are missing (macOS distribution must never ship
|
|
# unsigned/unnotarized — see its header comment); compile-ios.sh's
|
|
# default is to skip gracefully (exit 0) since an unconfigured iOS
|
|
# account is a normal "not set up yet" state, not a defect. Either way
|
|
# the job produces no dist/pangolin-macos-x64.zip, and
|
|
# release-deploy's "Download all artifacts" step (no `name:` filter)
|
|
# simply picks up whatever artifacts DO exist — an absent "macos"
|
|
# artifact is not an error there.
|
|
build-macos:
|
|
runs-on: mac
|
|
continue-on-error: true
|
|
env:
|
|
PUB_HOSTED_URL: https://pub.flutter-io.cn
|
|
FLUTTER_STORAGE_BASE_URL: https://storage.flutter-io.cn
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Compile (macOS System Extension app)
|
|
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 }}
|
|
MACOS_APP_PROVISION_PROFILE_BASE64: ${{ secrets.MACOS_APP_PROVISION_PROFILE_BASE64 }}
|
|
MACOS_SYSEXT_PROVISION_PROFILE_BASE64: ${{ secrets.MACOS_SYSEXT_PROVISION_PROFILE_BASE64 }}
|
|
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 }}
|
|
REF_NAME: ${{ gitea.ref_name }}
|
|
run: bash scripts/ci/compile-macos.sh "$REF_NAME"
|
|
|
|
- name: Upload macos artifact
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: macos
|
|
path: dist/
|
|
|
|
build-ios:
|
|
runs-on: mac
|
|
continue-on-error: true
|
|
env:
|
|
PUB_HOSTED_URL: https://pub.flutter-io.cn
|
|
FLUTTER_STORAGE_BASE_URL: https://storage.flutter-io.cn
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Compile & upload to TestFlight (iOS)
|
|
env:
|
|
IOS_DIST_CERT_P12_BASE64: ${{ secrets.IOS_DIST_CERT_P12_BASE64 }}
|
|
IOS_DIST_CERT_PASSWORD: ${{ secrets.IOS_DIST_CERT_PASSWORD }}
|
|
IOS_APP_PROVISIONING_PROFILE_BASE64: ${{ secrets.IOS_APP_PROVISIONING_PROFILE_BASE64 }}
|
|
IOS_PACKETTUNNEL_PROVISIONING_PROFILE_BASE64: ${{ secrets.IOS_PACKETTUNNEL_PROVISIONING_PROFILE_BASE64 }}
|
|
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 }}
|
|
REF_NAME: ${{ gitea.ref_name }}
|
|
run: bash scripts/ci/compile-ios.sh "$REF_NAME"
|
|
# No artifact upload — compile-ios.sh uploads straight to TestFlight via
|
|
# altool (matches jiu); nothing is produced under dist/ for this job.
|
|
|
|
# release-deploy 只 needs build-android(唯一稳定可用的平台 floor)。windows/macos/ios
|
|
# best-effort:各自 runner+secret 就绪则上传 artifact,release-deploy flatten 收
|
|
# dist-raw/ 里"当时存在"的产物。windows 机离线 / Apple secret 未配 都不阻塞发版
|
|
# (对应平台下载保留 pangolin1 上一版,待可用时下个 client-v* 追上)。
|
|
release-deploy:
|
|
needs: [build-android]
|
|
runs-on: mac
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
# 一次性下所有 artifact(不带 name),避免同 job 内两次复用 download-artifact
|
|
# action → act 对其只读缓存 git 仓库做二次操作时 EACCES(pack idx 444)。
|
|
- name: Download all artifacts
|
|
uses: actions/download-artifact@v3
|
|
with:
|
|
path: dist-raw/
|
|
|
|
- name: Flatten artifacts into dist/
|
|
shell: bash
|
|
run: |
|
|
mkdir -p dist
|
|
find dist-raw -type f -exec cp {} dist/ \;
|
|
echo "dist/ 内容:"; ls -la dist/
|
|
|
|
- name: Release → Forgejo
|
|
env:
|
|
FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }}
|
|
FORGEJO_URL: ${{ secrets.FORGEJO_URL }}
|
|
# Needed here (not just in the "Deploy" step below) because
|
|
# release-client.sh now also SSH-pushes the auto-update manifest
|
|
# (version.yaml) straight to pangolin1's /etc/pangolin/ — see the
|
|
# header comment in scripts/ci/release-client.sh.
|
|
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
REF_NAME: ${{ gitea.ref_name }}
|
|
run: bash scripts/ci/release-client.sh "$REF_NAME"
|
|
|
|
- name: Deploy → pangolin1 (downloads/)
|
|
env:
|
|
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
REF_NAME: ${{ gitea.ref_name }}
|
|
run: bash scripts/ci/deploy-client.sh "$REF_NAME"
|
|
|
|
- name: Notify
|
|
if: always()
|
|
env:
|
|
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
|
TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
|
|
REF_NAME: ${{ gitea.ref_name }}
|
|
JOB_STATUS: ${{ job.status }}
|
|
run: |
|
|
. scripts/ci/notify.sh
|
|
if [ "$JOB_STATUS" = "success" ]; then
|
|
notify_ok "client $REF_NAME released + deployed"
|
|
else
|
|
notify_fail "client $REF_NAME pipeline failed"
|
|
fi
|