build(gradle): 优化版本代码和名称的环境变量读取逻辑 #34
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 工作流名称 | |
| name: 创建 Release 并上传 APK | |
| # 工作流触发条件 | |
| on: | |
| push: | |
| tags: | |
| - 'v*' # 当一个以 'v' 开头的标签被推送到仓库时触发 (例如 v1.0, v2.1.0) | |
| workflow_dispatch: # 支持手动触发工作流 | |
| inputs: | |
| version_code: | |
| description: '版本号 (versionCode,如:1),留空则使用 version.properties 中的值' | |
| required: false | |
| type: string | |
| default: '' | |
| version_name: | |
| description: '版本名称 (versionName,如:1.0.0),留空则使用 version.properties 中的值' | |
| required: false | |
| type: string | |
| default: '' | |
| # 定义一个或多个作业 | |
| jobs: | |
| # 作业ID | |
| build-and-release: | |
| # 指定运行此作业的虚拟机环境 | |
| runs-on: ubuntu-latest | |
| # 定义作业中的各个步骤 | |
| steps: | |
| # 第1步:检出代码 | |
| # actions/checkout 是一个官方的 action,用于检出你的仓库代码,以便工作流可以访问它。 | |
| - name: 检出代码 | |
| uses: actions/checkout@v4 | |
| # 第2步:设置 Java 环境 | |
| # actions/setup-java 用于配置 Java 环境。 | |
| - name: 设置 JDK 21 | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: 'temurin' | |
| java-version: '21' | |
| cache: 'gradle' # 缓存 Gradle 依赖,加快构建速度 | |
| # 第3步:解码签名文件 | |
| # 从 GitHub Secrets 中获取 Base64 编码的签名文件内容,并解码还原成 .jks 文件。 | |
| - name: 解码签名文件 (Keystore) | |
| id: decode_keystore | |
| run: | | |
| echo "从 Secrets 中解码签名文件..." | |
| echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > app/release.jks | |
| echo "签名文件已成功解码到 app/release.jks" | |
| # 第4步:创建签名配置 | |
| # 创建一个临时的 gradle.properties 文件,并写入从 Secrets 获取的签名信息。 | |
| - name: 为签名创建 gradle.properties | |
| run: | | |
| echo "为签名创建 app/gradle.properties 文件..." | |
| echo "StoreFile=release.jks" > app/gradle.properties | |
| echo "StorePassword=${{ secrets.STORE_PASSWORD }}" >> app/gradle.properties | |
| echo "KeyAlias=${{ secrets.KEY_ALIAS }}" >> app/gradle.properties | |
| echo "KeyPassword=${{ secrets.KEY_PASSWORD }}" >> app/gradle.properties | |
| echo "gradle.properties 文件创建成功。" | |
| # 第5步:为 gradlew 添加执行权限 | |
| # 在 Linux/macOS 系统中,需要给 gradlew 脚本添加执行权限。 | |
| - name: 授予 gradlew 执行权限 | |
| run: chmod +x gradlew | |
| # 第6步:构建 Release 版本的 APK | |
| # 运行 Gradle 命令来编译和打包带签名的 APK。 | |
| - name: 构建 Release APK | |
| run: ./gradlew :app:assembleRelease --stacktrace | |
| env: | |
| GRADLE_OPTS: -Xmx8g -Dfile.encoding=UTF-8 | |
| # 手动触发时传递版本参数,留空则使用 version.properties 中的值 | |
| APP_VERSION_CODE: ${{ github.event.inputs.version_code }} | |
| APP_VERSION_NAME: ${{ github.event.inputs.version_name }} | |
| # 调试步骤(暂时保留,用于确认构建是否生成目录) | |
| - name: 调试:列出构建输出 | |
| run: ls -R build/app/outputs | |
| # 第6.5步:生成 appConfig.json | |
| # 运行自定义任务生成 appConfig.json 文件 | |
| - name: 生成 appConfig.json | |
| run: ./gradlew :app:printReleaseAppConfig | |
| # 第7步:获取版本信息 | |
| # 从 version.properties 文件中读取版本信息,如果有手动输入则优先使用手动输入的值。 | |
| - name: 获取版本名称 | |
| id: get_version | |
| run: | | |
| # 读取 version.properties 中的值作为默认值 | |
| VERSION_NAME=$(grep 'versionName=' version.properties | cut -d'=' -f2) | |
| VERSION_CODE=$(grep 'versionCode=' version.properties | cut -d'=' -f2) | |
| # 如果提供了手动输入的版本名称,则使用手动输入的值 | |
| if [ -n "${{ github.event.inputs.version_name }}" ]; then | |
| VERSION_NAME="${{ github.event.inputs.version_name }}" | |
| fi | |
| # 如果提供了手动输入的版本号,则使用手动输入的值 | |
| if [ -n "${{ github.event.inputs.version_code }}" ]; then | |
| VERSION_CODE="${{ github.event.inputs.version_code }}" | |
| fi | |
| echo "version=$VERSION_NAME" >> $GITHUB_OUTPUT | |
| echo "version_code=$VERSION_CODE" >> $GITHUB_OUTPUT | |
| echo "::notice::Building with versionName=$VERSION_NAME, versionCode=$VERSION_CODE" | |
| # 第8步:获取 APK 路径 | |
| # 从输出目录中找到构建生成的 APK 文件。 | |
| - name: 获取 APK 路径 | |
| id: get_apk_path | |
| run: | | |
| APK_PATH=$(find build/app/outputs/apk/release -type f -name "*.apk" | head -n 1) | |
| if [ -z "$APK_PATH" ]; then | |
| echo "错误:在 build/app/outputs/apk/release 目录中找不到 APK 文件。" >&2 | |
| exit 1 | |
| fi | |
| # 获取文件名(不带扩展名),用于 Artifact 命名 | |
| APK_NAME=$(basename "$APK_PATH" .apk) | |
| echo "apk_path=$APK_PATH" >> $GITHUB_OUTPUT | |
| echo "apk_name=$APK_NAME" >> $GITHUB_OUTPUT | |
| APP_CONFIG_PATH=$(find build/app/outputs/apk/release -type f -name "appConfig.json" | head -n 1) | |
| if [ -z "$APP_CONFIG_PATH" ]; then | |
| echo "错误:在 build/app/outputs/apk/release 目录中找不到 appConfig.json 文件。" >&2 | |
| else | |
| echo "app_config_path=$APP_CONFIG_PATH" >> $GITHUB_OUTPUT | |
| fi | |
| # 第9步:上传 APK 为 Artifact(仅手动触发时) | |
| # 手动触发工作流时,将 APK 上传为 artifact,方便下载测试 | |
| - name: 上传 APK 为 Artifact | |
| if: github.event_name == 'workflow_dispatch' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ steps.get_apk_path.outputs.apk_name }} | |
| path: | | |
| ${{ steps.get_apk_path.outputs.apk_path }} | |
| ${{ steps.get_apk_path.outputs.app_config_path }} | |
| retention-days: 30 | |
| # 第10步:创建 GitHub Release(仅 tag 触发时) | |
| # 使用 softprops/action-gh-release 这个 action 来创建 Release 并上传 APK。 | |
| - name: 创建 GitHub Release | |
| if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| # 上传的文件路径 | |
| files: | | |
| ${{ steps.get_apk_path.outputs.apk_path }} | |
| ${{ steps.get_apk_path.outputs.app_config_path }} | |
| # Release 的标题 | |
| name: "Release ${{ github.ref_name }}" | |
| # Release 的描述内容 | |
| body: | | |
| **版本:** ${{ steps.get_version.outputs.version }} | |
| 此版本由 GitHub Actions 自动构建和发布。 | |
| # 是否为预发布版本 | |
| prerelease: false | |
| env: | |
| # 需要 GITHUB_TOKEN 才能有权限创建 Release | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # 第11步:清理工作区 | |
| # 删除生成的签名文件和配置文件,确保它们不会被意外泄露。 | |
| - name: 清理签名文件和配置 | |
| if: always() # 保证无论之前的步骤成功或失败,此步骤都会执行 | |
| run: | | |
| echo "清理工作区..." | |
| rm -f app/release.jks | |
| rm -f app/gradle.properties | |
| echo "清理完成。" |