From f4b623deb63db7e8828ff0a06a2d3bc2d034ffdb Mon Sep 17 00:00:00 2001 From: kuaifan Date: Fri, 17 Apr 2026 09:56:07 +0000 Subject: [PATCH] =?UTF-8?q?chore(mobile):=20=E7=A7=BB=E9=99=A4=20EEUI=20?= =?UTF-8?q?=E6=9E=84=E5=BB=BA=E9=93=BE=E8=B7=AF=EF=BC=88=E8=BF=81=E7=A7=BB?= =?UTF-8?q?=E8=87=B3=E7=8B=AC=E7=AB=8B=20dootask-app=20=E4=BB=93=E5=BA=93?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 配合 dootask-app 仓库接入 Expo + EAS Build(见 docs/migration 的 Phase 6), 主仓库不再承担 iOS/Android 打包,保留前端资源构建即可。 - cmd: - appbuild/buildapp:从 electron_operate app 改为直接 web_build prod, 构建完成后打印提示去 dootask-app 仓库跑 EAS Build / 同步 assets/web/ - 移除 eeui 命令(docker run kuaifan/eeui-cli) - electron/build.js: - 删除 data.id === 'app' 分支(Android local.properties / iOS Version.xcconfig 回写、eeui build 调用) - 删除 argv 'app' 和 'android-upload' 两个命令 - .github/workflows/publish.yml: - build-client 矩阵移除 android;同时删除所有 (Android) 条件 steps(Build Js/ Setup JDK/Build App/Upload File/Upload Release) - 保留 Electron 桌面端(mac / windows)分支 - .github/workflows/ios-publish.yml:整体删除(iOS 移动端构建搬去 dootask-app) 子模块 resources/mobile 的 .gitmodules 条目和目录引用留到 Phase 7 一起清理。 Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/ios-publish.yml | 193 ------------------------------ .github/workflows/publish.yml | 67 +---------- cmd | 19 ++- electron/build.js | 83 +------------ 4 files changed, 12 insertions(+), 350 deletions(-) delete mode 100644 .github/workflows/ios-publish.yml diff --git a/.github/workflows/ios-publish.yml b/.github/workflows/ios-publish.yml deleted file mode 100644 index a82db0ea8..000000000 --- a/.github/workflows/ios-publish.yml +++ /dev/null @@ -1,193 +0,0 @@ -name: "iOS Publish" - -# Required GitHub Secrets: -# -# IOS_CERTIFICATE_BASE64 - Apple distribution certificate (.p12) encoded in base64 -# IOS_CERTIFICATE_PASSWORD - Password for the .p12 certificate -# IOS_PROVISION_PROFILE_BASE64 - App Store provisioning profile (.mobileprovision) encoded in base64 -# ASC_API_KEY_P8_BASE64 - App Store Connect API key (.p8) encoded in base64 -# ASC_API_KEY_ID - App Store Connect API Key ID -# ASC_ISSUER_ID - App Store Connect Issuer ID - -on: - workflow_dispatch: - -jobs: - prepare-assets: - name: Prepare iOS Assets - runs-on: ubuntu-latest - outputs: - version: ${{ steps.get-version.outputs.version }} - - steps: - - uses: actions/checkout@v4 - - - name: Get version from package.json - id: get-version - run: | - VERSION=$(node -p "require('./package.json').version") - echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "Version: $VERSION" - - - uses: actions/setup-node@v4 - with: - node-version: 20 - - - name: Install dependencies - run: npm install - - - name: Install electron dependencies - run: | - pushd electron - npm install - popd - - - name: Init mobile submodule - run: | - git submodule init - git submodule update --remote "resources/mobile" - - - name: Build app assets - run: ./cmd appbuild publish - - - name: Upload iOS platform artifacts - uses: actions/upload-artifact@v4 - with: - name: ios-platform - path: resources/mobile/platforms/ios/ - retention-days: 1 - - build-ios: - name: Build & Submit iOS - needs: prepare-assets - runs-on: macos-15 - environment: build - - steps: - - uses: actions/checkout@v4 - - - name: Init mobile submodule - run: | - git submodule init - git submodule update --remote "resources/mobile" - - - name: Download prepared assets - uses: actions/download-artifact@v4 - with: - name: ios-platform - path: resources/mobile/platforms/ios/ - - - name: Select Xcode - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: latest-stable - - - name: Install CocoaPods - run: | - if [ -f "resources/mobile/platforms/ios/eeuiApp/Podfile" ]; then - cd resources/mobile/platforms/ios/eeuiApp - pod install - fi - - - name: Import signing certificate - env: - IOS_CERTIFICATE_BASE64: ${{ secrets.IOS_CERTIFICATE_BASE64 }} - IOS_CERTIFICATE_PASSWORD: ${{ secrets.IOS_CERTIFICATE_PASSWORD }} - run: | - # Create temporary keychain - KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db - KEYCHAIN_PASSWORD=$(openssl rand -hex 20) - - security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" - security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" - security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" - - # Import certificate - CERTIFICATE_PATH=$RUNNER_TEMP/certificate.p12 - echo "$IOS_CERTIFICATE_BASE64" | base64 --decode > "$CERTIFICATE_PATH" - security import "$CERTIFICATE_PATH" \ - -P "$IOS_CERTIFICATE_PASSWORD" \ - -A \ - -t cert \ - -f pkcs12 \ - -k "$KEYCHAIN_PATH" - - security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" - security list-keychain -d user -s "$KEYCHAIN_PATH" - - - name: Import provisioning profile - env: - IOS_PROVISION_PROFILE_BASE64: ${{ secrets.IOS_PROVISION_PROFILE_BASE64 }} - run: | - PROFILE_PATH=$RUNNER_TEMP/profile.mobileprovision - echo "$IOS_PROVISION_PROFILE_BASE64" | base64 --decode > "$PROFILE_PATH" - - mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles - cp "$PROFILE_PATH" ~/Library/MobileDevice/Provisioning\ Profiles/ - - - name: Build archive - run: | - cd resources/mobile/platforms/ios/eeuiApp - xcodebuild archive \ - -workspace eeuiApp.xcworkspace \ - -scheme eeuiApp \ - -configuration Release \ - -archivePath $RUNNER_TEMP/eeuiApp.xcarchive \ - -allowProvisioningUpdates \ - CODE_SIGN_STYLE=Manual \ - | xcpretty - - - name: Export IPA - run: | - cd resources/mobile/platforms/ios/eeuiApp - - # Generate ExportOptions.plist - cat > $RUNNER_TEMP/ExportOptions.plist << 'PLIST' - - - - - method - app-store - uploadBitcode - - uploadSymbols - - - - PLIST - - xcodebuild -exportArchive \ - -archivePath $RUNNER_TEMP/eeuiApp.xcarchive \ - -exportOptionsPlist $RUNNER_TEMP/ExportOptions.plist \ - -exportPath $RUNNER_TEMP/ipa-output \ - -allowProvisioningUpdates \ - | xcpretty - - - name: Submit to App Store Connect - env: - ASC_API_KEY_ID: ${{ secrets.ASC_API_KEY_ID }} - ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }} - ASC_API_KEY_P8_BASE64: ${{ secrets.ASC_API_KEY_P8_BASE64 }} - run: | - # Prepare API key - mkdir -p ~/private_keys - echo "$ASC_API_KEY_P8_BASE64" | base64 --decode > ~/private_keys/AuthKey_${ASC_API_KEY_ID}.p8 - - # Find and upload IPA - IPA_PATH=$(find $RUNNER_TEMP/ipa-output -name "*.ipa" | head -1) - echo "Uploading: $IPA_PATH" - - xcrun altool --upload-app \ - -f "$IPA_PATH" \ - --type ios \ - --apiKey "$ASC_API_KEY_ID" \ - --apiIssuer "$ASC_ISSUER_ID" - - - name: Clean up - if: always() - run: | - security delete-keychain $RUNNER_TEMP/app-signing.keychain-db 2>/dev/null || true - rm -f $RUNNER_TEMP/certificate.p12 - rm -f $RUNNER_TEMP/profile.mobileprovision - rm -rf ~/private_keys diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f62f72797..e628ced3d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -131,8 +131,6 @@ jobs: include: - platform: "macos-latest" build_type: "mac" - - platform: "ubuntu-latest" - build_type: "android" - platform: "windows-latest" build_type: "windows" @@ -147,69 +145,8 @@ jobs: with: node-version: 20.x - # Android 构建步骤 - - name: (Android) Build Js - if: matrix.build_type == 'android' - uses: nick-fields/retry@v2 - with: - timeout_minutes: 10 - max_attempts: 3 - command: | - git submodule init - git submodule update --remote "resources/mobile" - ./cmd appbuild publish - - - name: (Android) Setup JDK 11 - if: matrix.build_type == 'android' - uses: actions/setup-java@v3 - with: - distribution: "zulu" - java-version: "11" - - - name: (Android) Build App - if: matrix.build_type == 'android' - uses: nick-fields/retry@v2 - with: - timeout_minutes: 20 - max_attempts: 5 - command: | - cd resources/mobile/platforms/android/eeuiApp - chmod +x ./gradlew - ./gradlew assembleRelease --quiet - - - name: (Android) Upload File - if: matrix.build_type == 'android' - env: - UPLOAD_TOKEN: ${{ secrets.UPLOAD_TOKEN }} - UPLOAD_URL: ${{ secrets.UPLOAD_URL }} - run: | - node ./electron/build.js android-upload - - - name: (Android) Upload Release - if: matrix.build_type == 'android' - uses: actions/github-script@v7 - env: - RELEASE_ID: ${{ needs.create-release.outputs.release_id }} - with: - script: | - const fs = require('fs'); - const path = require('path'); - const globby = require('globby'); - - // 查找 APK 文件 - const files = await globby('resources/mobile/platforms/android/eeuiApp/app/build/outputs/apk/release/*.apk'); - - for (const file of files) { - const data = await fs.promises.readFile(file); - - await github.rest.repos.uploadReleaseAsset({ - owner: context.repo.owner, - repo: context.repo.repo, - release_id: process.env.RELEASE_ID, - name: path.basename(file), - data: data - }); - } + # 移动端构建已迁移到 dootask-app 仓库(EAS Build),见 + # dootask-app/.github/workflows/build.yml # Mac 构建步骤 - name: (Mac) Build Client diff --git a/cmd b/cmd index 7213b6e18..1a748e9e5 100755 --- a/cmd +++ b/cmd @@ -833,23 +833,18 @@ case "$1" in ;; "appbuild"|"buildapp") shift 1 - electron_operate app "$@" + # 移动端已迁移到独立仓库 dootask-app(Expo + EAS Build)。 + # 这里只负责把前端 Vue SPA 构建到 public/,实际打包在 dootask-app 仓库执行。 + web_build prod + echo "" + echo "前端资源已构建至 public/" + echo "移动端打包请在 dootask-app 仓库使用 EAS Build" + echo "本地同步:cp -r public/* ~/workspaces/dootask-app/assets/web/" ;; "electron") shift 1 electron_operate "$@" ;; - "eeui") - shift 1 - cli="$@" - por="" - if [[ "$cli" == "build" ]]; then - cli="build --simple" - elif [[ "$cli" == "dev" ]]; then - por="-p 8880:8880" - fi - docker run $TTY_FLAG --rm -v ${WORK_DIR}/resources/mobile:/work -w /work ${por} kuaifan/eeui-cli:0.0.1 eeui ${cli} - ;; "npm") shift 1 npm "$@" diff --git a/electron/build.js b/electron/build.js index ac63319ea..8ff2a6f11 100644 --- a/electron/build.js +++ b/electron/build.js @@ -566,42 +566,9 @@ async function startBuild(data) { indexString = indexString.replace("", ``); fs.writeFileSync(indexFile, indexString, 'utf8'); // - if (data.id === 'app') { - const eeuiDir = path.resolve(__dirname, "../resources/mobile"); - const eeuiRun = `docker run --rm -v ${eeuiDir}:/work -w /work kuaifan/eeui-cli:0.0.1` - const publicDir = path.resolve(__dirname, "../resources/mobile/src/public"); - fse.removeSync(publicDir) - fse.copySync(electronDir, publicDir) - if (argv[3] === "publish") { - // Android config - const gradleFile = path.resolve(eeuiDir, "platforms/android/eeuiApp/local.properties") - let gradleResult = fs.existsSync(gradleFile) ? fs.readFileSync(gradleFile, 'utf8') : ""; - gradleResult = gradleResult.replace(/(versionCode|versionName)\s*=\s*(.+?)(\n|$)/g, '') - gradleResult += `versionCode = ${config.codeVerson}\nversionName = ${config.version}\n` - fs.writeFileSync(gradleFile, gradleResult, 'utf8') - // iOS config - const xcconfigFile = path.resolve(eeuiDir, "platforms/ios/eeuiApp/Config/Version.xcconfig") - let xcconfigResult = fs.existsSync(xcconfigFile) ? fs.readFileSync(xcconfigFile, 'utf8') : ""; - xcconfigResult = xcconfigResult.replace(/(VERSION_CODE|VERSION_NAME)\s*=\s*(.+?)(\n|$)/g, '') - xcconfigResult += `VERSION_CODE = ${config.codeVerson}\nVERSION_NAME = ${config.version}\n` - fs.writeFileSync(xcconfigFile, xcconfigResult, 'utf8') - } - if (['build', 'publish'].includes(argv[3])) { - if (!fs.existsSync(path.resolve(eeuiDir, "node_modules"))) { - child_process.execSync(`${eeuiRun} npm install`, {stdio: "inherit", cwd: "resources/mobile"}); - } - child_process.execSync(`${eeuiRun} eeui build --simple`, {stdio: "inherit", cwd: "resources/mobile"}); - } else { - [ - path.resolve(publicDir, "../../platforms/ios/eeuiApp/bundlejs/eeui/public"), - path.resolve(publicDir, "../../platforms/android/eeuiApp/app/src/main/assets/eeui/public"), - ].some(dir => { - fse.removeSync(dir) - fse.copySync(electronDir, dir) - }) - } - return; - } + // 注:移动端(data.id === 'app')的 EEUI 打包逻辑已随着迁移到 dootask-app 仓库 + // 而移除。前端资源现在通过 ./cmd appbuild(= web_build prod)构建到 public/, + // 实际的 iOS/Android 打包在 dootask-app 仓库用 EAS Build 执行。 const output = `dist/${data.id.replace(/\./g, '-')}/${platform}` // package.json Backup fse.copySync(packageFile, packageBakFile) @@ -697,50 +664,6 @@ if (["dev"].includes(argv[2])) { fs.writeFileSync(devloadCachePath, utils.formatUrl("localhost:" + env.parsed.APP_PORT), 'utf8'); child_process.spawn("npx", ["vite", "--", "fromcmd", "electronDev"], {stdio: "inherit"}); child_process.spawn("npm", ["run", "start-quiet"], {stdio: "inherit", cwd: "electron"}); -} else if (["app"].includes(argv[2])) { - // 编译前端页面给 App - let mobileSrcDir = path.resolve(__dirname, "../resources/mobile"); - if (!fs.existsSync(mobileSrcDir)) { - console.error("resources/mobile 未找到"); - process.exit() - } - startBuild({ - name: 'App', - id: 'app', - platform: '', - url: 'http://public/', - configure: { - platform: '', - archs: [], - publish: false, - release: true, - notarize: false, - } - }) -} else if (["android-upload"].includes(argv[2])) { - // 上传安卓文件(GitHub Actions) - (async () => { - const publisher = createPublisher() - if (!publisher) { - console.error("缺少 UPLOAD_TOKEN 或 UPLOAD_URL 环境变量") - process.exit(1) - } - const releaseDir = path.resolve(__dirname, "../resources/mobile/platforms/android/eeuiApp/app/build/outputs/apk/release"); - if (!fs.existsSync(releaseDir)) { - console.error("发布文件未找到") - process.exit(1) - } - const files = fs.readdirSync(releaseDir) - for (const filename of files) { - const localFile = path.join(releaseDir, filename) - if (/\.apk$/.test(filename) && fs.existsSync(localFile) && fs.statSync(localFile).isFile()) { - await publisher.uploadPackage(localFile, { platform: 'android' }) - } - } - })().catch(err => { - console.error(err.message || err) - process.exit(1) - }) } else if (["release"].includes(argv[2])) { // 通知官网发布完成(GitHub Actions) (async () => {