build_trio.yml 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. name: 4. Build Trio
  2. run-name: Build Trio (${{ github.ref_name }})
  3. on:
  4. workflow_dispatch:
  5. ## Remove the "#" sign from the beginning of the line below to get automated builds on push (code changes in your repository)
  6. #push:
  7. schedule:
  8. - cron: "0 8 * * 3" # Checks for updates at 08:00 UTC every Wednesday
  9. - cron: "0 6 1 * *" # Builds the app on the 1st of every month at 06:00 UTC
  10. env:
  11. UPSTREAM_REPO: nightscout/Trio
  12. UPSTREAM_BRANCH: ${{ github.ref_name }} # branch on upstream repository to sync from (replace with specific branch name if needed)
  13. TARGET_BRANCH: ${{ github.ref_name }} # target branch on fork to be kept in sync, and target branch on upstream to be kept alive (replace with specific branch name if needed)
  14. ALIVE_BRANCH_MAIN: alive-main
  15. ALIVE_BRANCH_DEV: alive-dev
  16. jobs:
  17. validate:
  18. name: Validate
  19. uses: ./.github/workflows/validate_secrets.yml
  20. secrets: inherit
  21. # Checks if GH_PAT holds workflow permissions
  22. # Checks for existence of alive branch; if non-existent creates it
  23. check_alive_and_permissions:
  24. needs: validate
  25. runs-on: ubuntu-latest
  26. name: Check alive branch and permissions
  27. permissions:
  28. contents: write
  29. outputs:
  30. WORKFLOW_PERMISSION: ${{ steps.workflow-permission.outputs.has_permission }}
  31. steps:
  32. - name: Check for workflow permissions
  33. id: workflow-permission
  34. env:
  35. TOKEN_TO_CHECK: ${{ secrets.GH_PAT }}
  36. run: |
  37. PERMISSIONS=$(curl -sS -f -I -H "Authorization: token ${{ env.TOKEN_TO_CHECK }}" https://api.github.com | grep ^x-oauth-scopes: | cut -d' ' -f2-);
  38. if [[ $PERMISSIONS =~ "workflow" || $PERMISSIONS == "" ]]; then
  39. echo "GH_PAT holds workflow permissions or is fine-grained PAT."
  40. echo "has_permission=true" >> $GITHUB_OUTPUT # Set WORKFLOW_PERMISSION to false.
  41. else
  42. echo "GH_PAT lacks workflow permissions."
  43. echo "Automated build features will be skipped!"
  44. echo "has_permission=false" >> $GITHUB_OUTPUT # Set WORKFLOW_PERMISSION to false.
  45. fi
  46. - name: Check for alive branches
  47. if: steps.workflow-permission.outputs.has_permission == 'true'
  48. env:
  49. GITHUB_TOKEN: ${{ secrets.GH_PAT }}
  50. run: |
  51. if [[ $(gh api -H "Accept: application/vnd.github+json" /repos/${{ github.repository_owner }}/Trio/branches | jq --raw-output '[.[] | select(.name == "alive-main" or .name == "alive-dev")] | length > 0') == "true" ]]; then
  52. echo "Branches 'alive-main' or 'alive-dev' exist."
  53. echo "ALIVE_BRANCH_EXISTS=true" >> $GITHUB_ENV
  54. else
  55. echo "Branches 'alive-main' and 'alive-dev' do not exist."
  56. echo "ALIVE_BRANCH_EXISTS=false" >> $GITHUB_ENV
  57. fi
  58. - name: Create alive branches
  59. if: env.ALIVE_BRANCH_EXISTS == 'false'
  60. env:
  61. GITHUB_TOKEN: ${{ secrets.GH_PAT }}
  62. run: |
  63. # Get ref for UPSTREAM_REPO:main
  64. SHA_MAIN=$(curl -sS -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/repos/${{ env.UPSTREAM_REPO }}/git/refs/heads/main | jq -r '.object.sha')
  65. # Get ref for UPSTREAM_REPO:dev
  66. SHA_DEV=$(curl -sS -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/repos/${{ env.UPSTREAM_REPO }}/git/refs/heads/dev | jq -r '.object.sha')
  67. # Create alive-main branch in Trio fork based on UPSTREAM_REPO:main
  68. gh api \
  69. --method POST \
  70. -H "Authorization: token $GITHUB_TOKEN" \
  71. -H "Accept: application/vnd.github.v3+json" \
  72. /repos/${{ github.repository_owner }}/Trio/git/refs \
  73. -f ref='refs/heads/alive-main' \
  74. -f sha=$SHA_MAIN
  75. # Create alive-dev branch in Trio fork based on UPSTREAM_REPO:dev
  76. gh api \
  77. --method POST \
  78. -H "Authorization: token $GITHUB_TOKEN" \
  79. -H "Accept: application/vnd.github.v3+json" \
  80. /repos/${{ github.repository_owner }}/Trio/git/refs \
  81. -f ref='refs/heads/alive-dev' \
  82. -f sha=$SHA_DEV
  83. # Checks for changes in upstream repository; if changes exist prompts sync for build
  84. # Performs keepalive to avoid stale fork
  85. check_latest_from_upstream:
  86. needs: [validate, check_alive_and_permissions]
  87. runs-on: ubuntu-latest
  88. name: Check upstream and keep alive
  89. outputs:
  90. NEW_COMMITS: ${{ steps.sync.outputs.has_new_commits }}
  91. ABORT_SYNC: ${{ steps.check_branch.outputs.ABORT_SYNC }}
  92. steps:
  93. - name: Check if running on main or dev branch
  94. if: |
  95. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  96. (vars.SCHEDULED_BUILD != 'false' || vars.SCHEDULED_SYNC != 'false')
  97. id: check_branch
  98. run: |
  99. if [ "${GITHUB_REF##*/}" = "main" ]; then
  100. echo "Running on main branch"
  101. echo "ALIVE_BRANCH=${ALIVE_BRANCH_MAIN}" >> $GITHUB_OUTPUT
  102. echo "ABORT_SYNC=false" >> $GITHUB_OUTPUT
  103. elif [ "${GITHUB_REF##*/}" = "dev" ]; then
  104. echo "Running on dev branch"
  105. echo "ALIVE_BRANCH=${ALIVE_BRANCH_DEV}" >> $GITHUB_OUTPUT
  106. echo "ABORT_SYNC=false" >> $GITHUB_OUTPUT
  107. else
  108. echo "Not running on main or dev branch"
  109. echo "ABORT_SYNC=true" >> $GITHUB_OUTPUT
  110. fi
  111. - name: Checkout target repo
  112. if: |
  113. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  114. (vars.SCHEDULED_BUILD != 'false' || vars.SCHEDULED_SYNC != 'false')
  115. uses: actions/checkout@v4
  116. with:
  117. token: ${{ secrets.GH_PAT }}
  118. ref: ${{ steps.check_branch.outputs.ALIVE_BRANCH }}
  119. - name: Sync upstream changes
  120. if: | # do not run the upstream sync action on the upstream repository
  121. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  122. vars.SCHEDULED_SYNC != 'false' && github.repository_owner != 'nightscout' && steps.check_branch.outputs.ABORT_SYNC == 'false'
  123. id: sync
  124. uses: aormsby/Fork-Sync-With-Upstream-action@v3.4.1
  125. with:
  126. target_sync_branch: ${{ steps.check_branch.outputs.ALIVE_BRANCH }}
  127. shallow_since: 6 months ago
  128. target_repo_token: ${{ secrets.GH_PAT }}
  129. upstream_sync_branch: ${{ env.UPSTREAM_BRANCH }}
  130. upstream_sync_repo: ${{ env.UPSTREAM_REPO }}
  131. # Display a sample message based on the sync output var 'has_new_commits'
  132. - name: New commits found
  133. if: |
  134. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  135. vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'true'
  136. run: echo "New commits were found to sync."
  137. - name: No new commits
  138. if: |
  139. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  140. vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'false'
  141. run: echo "There were no new commits."
  142. - name: Show value of 'has_new_commits'
  143. if: needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' && vars.SCHEDULED_SYNC != 'false' && steps.check_branch.outputs.ABORT_SYNC == 'false'
  144. run: |
  145. echo ${{ steps.sync.outputs.has_new_commits }}
  146. echo "NEW_COMMITS=${{ steps.sync.outputs.has_new_commits }}" >> $GITHUB_OUTPUT
  147. # Keep repository "alive": add empty commits to ALIVE_BRANCH after "time_elapsed" days of inactivity to avoid inactivation of scheduled workflows
  148. - name: Keep alive
  149. if: |
  150. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  151. (vars.SCHEDULED_BUILD != 'false' || vars.SCHEDULED_SYNC != 'false')
  152. uses: gautamkrishnar/keepalive-workflow@v1 # using the workflow with default settings
  153. with:
  154. time_elapsed: 20 # Time elapsed from the previous commit to trigger a new automated commit (in days)
  155. - name: Show scheduled build configuration message
  156. if: needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION != 'true'
  157. run: |
  158. echo "### :calendar: Scheduled Sync and Build Disabled :mobile_phone_off:" >> $GITHUB_STEP_SUMMARY
  159. echo "You have not yet configured the scheduled sync and build for Trio's browser build." >> $GITHUB_STEP_SUMMARY
  160. echo "Synchronizing your fork of <code>Trio</code> with the upstream repository <code>nightscout/Trio</code> will be skipped." >> $GITHUB_STEP_SUMMARY
  161. echo "If you want to enable automatic builds and updates for your Trio, please follow the instructions \
  162. under the following path <code>Trio/fastlane/testflight.md</code>." >> $GITHUB_STEP_SUMMARY
  163. # Builds Trio
  164. build:
  165. name: Build
  166. needs: [validate, check_alive_and_permissions, check_latest_from_upstream]
  167. runs-on: macos-15
  168. permissions:
  169. contents: write
  170. if:
  171. | # runs if started manually, or if sync schedule is set and enabled and scheduled on the first Saturday each month, or if sync schedule is set and enabled and new commits were found
  172. github.event_name == 'workflow_dispatch' ||
  173. (needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  174. (vars.SCHEDULED_BUILD != 'false' && github.event.schedule == '0 6 1 * *') ||
  175. (vars.SCHEDULED_SYNC != 'false' && needs.check_latest_from_upstream.outputs.NEW_COMMITS == 'true' )
  176. )
  177. steps:
  178. - name: Select Xcode version
  179. run: "sudo xcode-select --switch /Applications/Xcode_16.0.app/Contents/Developer"
  180. - name: Checkout Repo for syncing
  181. if: |
  182. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  183. vars.SCHEDULED_SYNC != 'false'
  184. uses: actions/checkout@v4
  185. with:
  186. token: ${{ secrets.GH_PAT }}
  187. ref: ${{ env.TARGET_BRANCH }}
  188. - name: Sync upstream changes
  189. if: | # do not run the upstream sync action on the upstream repository
  190. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  191. vars.SCHEDULED_SYNC != 'false' && github.repository_owner != 'nightscout' && needs.check_latest_from_upstream.outputs.ABORT_SYNC == 'false'
  192. id: sync
  193. uses: aormsby/Fork-Sync-With-Upstream-action@v3.4.1
  194. with:
  195. target_sync_branch: ${{ env.TARGET_BRANCH }}
  196. shallow_since: 6 months ago
  197. target_repo_token: ${{ secrets.GH_PAT }}
  198. upstream_sync_branch: ${{ env.UPSTREAM_BRANCH }}
  199. upstream_sync_repo: ${{ env.UPSTREAM_REPO }}
  200. # Display a sample message based on the sync output var 'has_new_commits'
  201. - name: New commits found
  202. if: |
  203. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  204. vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'true' && needs.check_latest_from_upstream.outputs.ABORT_SYNC == 'false'
  205. run: echo "New commits were found to sync."
  206. - name: No new commits
  207. if: |
  208. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  209. vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'false' && needs.check_latest_from_upstream.outputs.ABORT_SYNC == 'false'
  210. run: echo "There were no new commits."
  211. - name: Show value of 'has_new_commits'
  212. if: |
  213. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true'
  214. && vars.SCHEDULED_SYNC != 'false' && needs.check_latest_from_upstream.outputs.ABORT_SYNC == 'false'
  215. run: |
  216. echo ${{ steps.sync.outputs.has_new_commits }}
  217. echo "NEW_COMMITS=${{ steps.sync.outputs.has_new_commits }}" >> $GITHUB_OUTPUT
  218. - name: Checkout Repo for building
  219. uses: actions/checkout@v4
  220. with:
  221. token: ${{ secrets.GH_PAT }}
  222. submodules: recursive
  223. ref: ${{ env.TARGET_BRANCH }}
  224. # Patch Fastlane Match to not print tables
  225. - name: Patch Match Tables
  226. run: |
  227. TABLE_PRINTER_PATH=$(ruby -e 'puts Gem::Specification.find_by_name("fastlane").gem_dir')/match/lib/match/table_printer.rb
  228. if [ -f "$TABLE_PRINTER_PATH" ]; then
  229. sed -i "" "/puts(Terminal::Table.new(params))/d" "$TABLE_PRINTER_PATH"
  230. else
  231. echo "table_printer.rb not found"
  232. exit 1
  233. fi
  234. # Install project dependencies
  235. - name: Install Project Dependencies
  236. run: bundle install
  237. # Sync the GitHub runner clock with the Windows time server (workaround as suggested in https://github.com/actions/runner/issues/2996)
  238. - name: Sync clock
  239. run: sudo sntp -sS time.windows.com
  240. # Build signed Trio IPA file
  241. - name: Fastlane Build & Archive
  242. run: bundle exec fastlane build_trio
  243. env:
  244. TEAMID: ${{ secrets.TEAMID }}
  245. GH_PAT: ${{ secrets.GH_PAT }}
  246. FASTLANE_KEY_ID: ${{ secrets.FASTLANE_KEY_ID }}
  247. FASTLANE_ISSUER_ID: ${{ secrets.FASTLANE_ISSUER_ID }}
  248. FASTLANE_KEY: ${{ secrets.FASTLANE_KEY }}
  249. MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
  250. # Upload to TestFlight
  251. - name: Fastlane upload to TestFlight
  252. run: bundle exec fastlane release
  253. env:
  254. TEAMID: ${{ secrets.TEAMID }}
  255. GH_PAT: ${{ secrets.GH_PAT }}
  256. FASTLANE_KEY_ID: ${{ secrets.FASTLANE_KEY_ID }}
  257. FASTLANE_ISSUER_ID: ${{ secrets.FASTLANE_ISSUER_ID }}
  258. FASTLANE_KEY: ${{ secrets.FASTLANE_KEY }}
  259. MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
  260. # Upload Build artifacts
  261. - name: Upload build log, IPA and Symbol artifacts
  262. if: always()
  263. uses: actions/upload-artifact@v4
  264. with:
  265. name: build-artifacts
  266. path: |
  267. artifacts
  268. buildlog