test.yml 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. name: Test Build
  2. on:
  3. push:
  4. branches:
  5. - main
  6. paths:
  7. - '**'
  8. # - '!**/assets/**'
  9. # - '!**.md'
  10. - '!**/ISSUE_TEMPLATE/**'
  11. - '!**/modules/web/**'
  12. pull_request:
  13. paths-ignore:
  14. - '**/modules/web/**'
  15. workflow_run:
  16. workflows: [Build Web]
  17. branches: [master]
  18. types:
  19. - completed
  20. workflow_dispatch:
  21. permissions:
  22. contents: write
  23. concurrency:
  24. group: ${{ github.workflow }}-${{ github.ref }}
  25. cancel-in-progress: true
  26. jobs:
  27. prepare:
  28. runs-on: ubuntu-latest
  29. if: ${{ !startsWith(github.event.head_commit.message, 'Merge pull request') }}
  30. outputs:
  31. # versionL: 完整版本号,例如 3.26.3-beta.1
  32. versionL: ${{ steps.set-ver.outputs.full_version_name }}
  33. # version: 基础版本号,例如 3.26.3
  34. version: ${{ steps.set-ver.outputs.current_version }}
  35. # build_number: 增量构建号,例如 1
  36. build_number: ${{ steps.set-ver.outputs.build_number }}
  37. # latest_tag: 最近一个用于版本递增的 tag,例如 3.26.2-beta.5 (不带v前缀)
  38. latest_tag: ${{ steps.set-ver.outputs.last_tag }}
  39. steps:
  40. - uses: actions/checkout@v4
  41. with:
  42. # 确保拉取所有标签,用于版本号计算
  43. fetch-depth: 0
  44. - name: 计算版本号和构建号
  45. id: set-ver
  46. run: |
  47. PROPERTIES_FILE="./app/version.properties"
  48. if [[ ! -f "$PROPERTIES_FILE" ]]; then
  49. echo "错误:version.properties 文件不存在于 $PROPERTIES_FILE"
  50. exit 1
  51. fi
  52. # 确保获取到的版本号没有空格
  53. MAJOR=$(cat "$PROPERTIES_FILE" | grep 'VERSION_MAJOR' | cut -d'=' -f2 | tr -d '[:space:]')
  54. MINOR=$(cat "$PROPERTIES_FILE" | grep 'VERSION_MINOR' | cut -d'=' -f2 | tr -d '[:space:]')
  55. PATCH=$(cat "$PROPERTIES_FILE" | grep 'VERSION_PATCH' | cut -d'=' -f2 | tr -d '[:space:]')
  56. CURRENT_VERSION="$MAJOR.$MINOR.$PATCH"
  57. # 1. 找到仓库中最近创建的任意 TAG (无论是正式版还是测试版),作为日志起点
  58. LAST_ANY_TAG=$(git tag --sort=-committerdate | head -n 1)
  59. # 2. 尝试获取匹配当前 CURRENT_VERSION 的上一个 TAG (用于版本号递增)
  60. if [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" == "refs/heads/main" ]]; then
  61. # 查找匹配当前 CURRENT_VERSION 的上一个 TAG (e.g., 3.26.3-beta.X)
  62. # 注意:这里查找的是不带 'v' 的标签
  63. LAST_MATCHING_TAG=$(git tag --list "$CURRENT_VERSION-beta.*" --sort=-committerdate | head -n 1)
  64. if [[ $LAST_MATCHING_TAG =~ [0-9]+\.[0-9]+\.[0-9]+-beta\.([0-9]+) ]]; then
  65. # 如果找到匹配当前 PATCH 版本的 beta 标签,则递增
  66. LAST_BUILD_NUM="${BASH_REMATCH[1]}"
  67. NEW_BUILD_NUM=$((LAST_BUILD_NUM + 1))
  68. LAST_TAG_FOR_LOG="$LAST_MATCHING_TAG"
  69. echo "版本 $CURRENT_VERSION 未变更,构建号自增:$LAST_BUILD_NUM -> $NEW_BUILD_NUM"
  70. else
  71. # 如果找不到匹配的标签 (PATCH 刚修改,或首次构建),则重置为 1
  72. NEW_BUILD_NUM=1
  73. # 此时,日志应该从最近的 '非本次构建' 的 TAG 开始
  74. LAST_TAG_FOR_LOG="${LAST_ANY_TAG#v}" # 尽管没有 v,但保留这一行以防未来格式变化
  75. echo "版本 $CURRENT_VERSION 为新版本或首次构建,构建号重置为 $NEW_BUILD_NUM。日志将从 $LAST_TAG_FOR_LOG 开始。"
  76. fi
  77. else
  78. # 对于 PR 或其他分支,使用一个固定的构建号 0
  79. NEW_BUILD_NUM=0
  80. LAST_TAG_FOR_LOG="${LAST_ANY_TAG#v}"
  81. echo "非 main 分支推送,构建号设置为 $NEW_BUILD_NUM"
  82. fi
  83. # 3. 构造最终版本信息
  84. VERSION_SUFFIX_NAME="-beta.$NEW_BUILD_NUM"
  85. FULL_VERSION_NAME="${CURRENT_VERSION}${VERSION_SUFFIX_NAME}"
  86. # 4. 设置输出供后续作业使用
  87. echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
  88. echo "full_version_name=$FULL_VERSION_NAME" >> $GITHUB_OUTPUT
  89. echo "build_number=$NEW_BUILD_NUM" >> $GITHUB_OUTPUT
  90. echo "last_tag=$LAST_TAG_FOR_LOG" >> $GITHUB_OUTPUT
  91. build:
  92. needs: prepare
  93. strategy:
  94. matrix:
  95. product: [ app ]
  96. type: [ release ]
  97. fail-fast: false
  98. runs-on: ubuntu-latest
  99. env:
  100. product: ${{ matrix.product }}
  101. type: ${{ matrix.type }}
  102. # 使用 prepare job 的输出
  103. VERSION: ${{ needs.prepare.outputs.version }}
  104. VERSIONL: ${{ needs.prepare.outputs.versionL }}
  105. BUILD_NUMBER: ${{ needs.prepare.outputs.build_number }}
  106. steps:
  107. - uses: actions/checkout@v5
  108. with:
  109. fetch-depth: 0
  110. - name: Set up JDK 17
  111. uses: actions/setup-java@v5
  112. with:
  113. distribution: 'temurin'
  114. java-version: 17
  115. - name: Clear 18PlusList.txt
  116. run: |
  117. echo "清空18PlusList.txt"
  118. echo "">$GITHUB_WORKSPACE/app/src/main/assets/18PlusList.txt
  119. - name: Release Apk Sign
  120. run: |
  121. echo "${{ secrets.SIGNING_KEY }}" | base64 -d > $GITHUB_WORKSPACE/app/my-release-key.jks
  122. echo "RELEASE_STORE_FILE=my-release-key.jks" >> $GITHUB_WORKSPACE/gradle.properties
  123. echo "RELEASE_STORE_PASSWORD=${{ secrets.KEYSTORE_PASSWORD }}" >> $GITHUB_WORKSPACE/gradle.properties
  124. echo "RELEASE_KEY_ALIAS=${{ secrets.KEY_ALIAS }}" >> $GITHUB_WORKSPACE/gradle.properties
  125. echo "RELEASE_KEY_PASSWORD=${{ secrets.KEY_PASSWORD }}" >> $GITHUB_WORKSPACE/gradle.properties
  126. - name: Set up Gradle
  127. uses: gradle/actions/setup-gradle@v4
  128. - name: 统一版本号
  129. run: |
  130. # 1. 临时修改 version.properties 中的 VERSION_SUFFIX
  131. echo "VERSION_SUFFIX=-beta.${{ env.BUILD_NUMBER }}" >> ./app/version.properties
  132. # 2. 覆盖 build.gradle 中复杂的 versionCode 计算逻辑
  133. sed -i "s/versionCode 10000 + gitCommits/versionCode 10000 + ${{ env.BUILD_NUMBER }}/" $GITHUB_WORKSPACE/app/build.gradle
  134. echo "versionName 已设置为 ${{ env.VERSIONL }}"
  135. echo "versionCode 已设置为 10000 + ${{ env.BUILD_NUMBER }}"
  136. - name: Build With Gradle
  137. run: |
  138. echo "开始${{ env.product }}${{ env.type }}构建"
  139. chmod +x gradlew
  140. ./gradlew assemble${{ env.product }}Release
  141. - name: Move Missing Rules Files
  142. run: |
  143. echo "移动missing_rules.txt文件"
  144. MAPPING_DIR="${{ github.workspace }}/mapping"
  145. mkdir -p "$MAPPING_DIR"
  146. # 使用 find 代替 ls,避免参数列表过长
  147. find ${{ github.workspace }}/app/build/outputs/mapping/ -name "missing_rules.txt" -exec mv {} "$MAPPING_DIR/missing_rules.txt" \;
  148. - name: Upload Missing Rules File To Artifact
  149. uses: actions/upload-artifact@v4
  150. with:
  151. name: legado.${{ env.product }}.${{ env.type }}.mapping.missing_rules
  152. if-no-files-found: ignore
  153. path: ${{ github.workspace }}/mapping/missing_rules.txt
  154. - name: Check Build production
  155. run: |
  156. echo "检查 APK 输出目录"
  157. APK_PATH="$GITHUB_WORKSPACE/app/build/outputs/apk"
  158. # 检查是否有任何 APK 文件生成
  159. if [ -z "$(find "$APK_PATH" -name "*.apk" -print -quit)" ]; then
  160. echo "Build production not found! Check gradle logs."
  161. exit 1
  162. fi
  163. - name: Upload universal APK
  164. uses: actions/upload-artifact@v4
  165. with:
  166. name: universal-apk
  167. path: app/build/outputs/apk/app/release/legado_app_*[0-9].apk
  168. - name: Upload arm64-v8a APK
  169. uses: actions/upload-artifact@v4
  170. with:
  171. name: arm64-v8a-apk
  172. path: app/build/outputs/apk/app/release/*arm64-v8a.apk
  173. - name: Upload armeabi-v7a APK
  174. uses: actions/upload-artifact@v4
  175. with:
  176. name: armeabi-v7a-apk
  177. path: app/build/outputs/apk/app/release/*armeabi-v7a.apk
  178. - name: Upload Mapping File To Artifact
  179. uses: actions/upload-artifact@v4
  180. with:
  181. name: legado.${{ env.product }}.${{ env.type }}.mapping
  182. if-no-files-found: ignore
  183. path: ${{ github.workspace }}/mapping/mapping.txt
  184. test_Branch:
  185. needs: [ prepare, build ]
  186. runs-on: ubuntu-latest
  187. if: ${{ github.event_name != 'pull_request' && github.actor == 'gedoor' }}
  188. steps:
  189. - uses: actions/checkout@v5
  190. - uses: actions/download-artifact@v5
  191. with:
  192. path: apk/
  193. - working-directory: apk/
  194. run: |
  195. # 使用 find 安全地移动文件
  196. find . -type f -name "*.apk" -exec mv {} . \;
  197. # 清理子目录
  198. find . -type d -mindepth 1 -exec rm -rf {} +
  199. - name: Push To "test" Branch
  200. run: |
  201. cd $GITHUB_WORKSPACE/apk/
  202. git init
  203. git checkout -b test
  204. git config --global user.name "github-actions[bot]"
  205. git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
  206. git remote add origin "https://${{ github.actor }}:${{ secrets.ACTIONS_TOKEN }}@github.com/${{ github.actor }}/release"
  207. git add *.apk
  208. git commit -m "${{ needs.prepare.outputs.versionL }}"
  209. git push -f -u origin test
  210. create_pre_release:
  211. needs: [ prepare, build ]
  212. if: |
  213. github.event_name == 'push' &&
  214. github.ref == 'refs/heads/main' &&
  215. needs.prepare.outputs.build_number > 0 &&
  216. success()
  217. runs-on: ubuntu-latest
  218. steps:
  219. - uses: actions/checkout@v4
  220. with:
  221. fetch-depth: 0
  222. - name: 获取所有 Commit 消息作为 Release Body
  223. id: get_commits
  224. run: |
  225. LATEST_TAG="${{ needs.prepare.outputs.latest_tag }}"
  226. if [ -z "$LATEST_TAG" ]; then
  227. # 如果没有找到任何 tag,则从第一个 commit 开始获取所有日志
  228. COMMIT_LOG=$(git log --pretty=format:'* %s (%an)' --reverse)
  229. else
  230. COMMIT_LOG=$(git log $LATEST_TAG..HEAD --pretty=format:'* %s (%an)')
  231. fi
  232. if [ -z "$COMMIT_LOG" ]; then
  233. RELEASE_BODY="本次发布无新增 Commit。"
  234. else
  235. RELEASE_BODY="# 本次更新内容\n\n$COMMIT_LOG"
  236. fi
  237. echo "release_body<<EOF" >> $GITHUB_OUTPUT
  238. echo "$RELEASE_BODY" >> $GITHUB_OUTPUT
  239. echo "EOF" >> $GITHUB_OUTPUT
  240. - name: 创建 Pre-Release Tag
  241. run: |
  242. git tag ${{ needs.prepare.outputs.versionL }}
  243. git push origin ${{ needs.prepare.outputs.versionL }}
  244. env:
  245. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  246. - name: 创建 Pre-Release
  247. id: create_release
  248. uses: actions/create-release@v1
  249. env:
  250. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  251. with:
  252. tag_name: ${{ needs.prepare.outputs.versionL }}
  253. # Release 标题:例如 Pre-release 3.26.3-beta.1
  254. release_name: Pre-release ${{ needs.prepare.outputs.versionL }}
  255. # Release 内容为所有 Commit 消息
  256. body: ${{ steps.get_commits.outputs.release_body }}
  257. draft: false
  258. # 标记为预发布版本
  259. prerelease: true
  260. - name: 下载所有 APK Artifacts
  261. uses: actions/download-artifact@v4
  262. with:
  263. pattern: '*-apk'
  264. path: artifacts
  265. merge-multiple: true
  266. - name: 上传 Release Assets
  267. uses: actions/upload-release-asset@v1
  268. env:
  269. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  270. with:
  271. upload_url: ${{ steps.create_release.outputs.upload_url }}
  272. asset_path: artifacts/*.apk
  273. asset_name: legado-${{ needs.prepare.outputs.versionL }}.apk
  274. asset_content_type: application/zip