build_trio.yml 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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. # avoid starting an action at times when GitHub resources are more likely to be impacted
  9. - cron: "43 8 * * 0" # Checks for updates at 08:43 UTC every Sunday
  10. - cron: "43 6 8-14 * 6" # Builds the app on the second Saturday of each month at 06:43 UTC
  11. env:
  12. UPSTREAM_REPO: nightscout/Trio
  13. UPSTREAM_BRANCH: ${{ github.ref_name }} # branch on upstream repository to sync from (replace with specific branch name if needed)
  14. 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)
  15. ALIVE_BRANCH_MAIN: alive-main
  16. ALIVE_BRANCH_DEV: alive-dev
  17. jobs:
  18. # Checks if Distribution certificate is present and valid, optionally nukes and
  19. # creates new certs if the repository variable ENABLE_NUKE_CERTS == 'true'
  20. check_certs:
  21. name: Check certificates
  22. uses: ./.github/workflows/create_certs.yml
  23. secrets: inherit
  24. # Checks if GH_PAT holds workflow permissions
  25. # Checks for existence of alive branch; if non-existent creates it
  26. check_alive_and_permissions:
  27. needs: check_certs
  28. runs-on: ubuntu-latest
  29. name: Check alive branch and permissions
  30. permissions:
  31. contents: write
  32. outputs:
  33. WORKFLOW_PERMISSION: ${{ steps.workflow-permission.outputs.has_permission }}
  34. steps:
  35. - name: Check for workflow permissions
  36. id: workflow-permission
  37. env:
  38. TOKEN_TO_CHECK: ${{ secrets.GH_PAT }}
  39. run: |
  40. PERMISSIONS=$(curl -sS -f -I -H "Authorization: token ${{ env.TOKEN_TO_CHECK }}" https://api.github.com | grep ^x-oauth-scopes: | cut -d' ' -f2-);
  41. if [[ $PERMISSIONS =~ "workflow" || $PERMISSIONS == "" ]]; then
  42. echo "GH_PAT holds workflow permissions or is fine-grained PAT."
  43. echo "has_permission=true" >> $GITHUB_OUTPUT # Set WORKFLOW_PERMISSION to false.
  44. else
  45. echo "GH_PAT lacks workflow permissions."
  46. echo "Automated build features will be skipped!"
  47. echo "has_permission=false" >> $GITHUB_OUTPUT # Set WORKFLOW_PERMISSION to false.
  48. fi
  49. - name: Check for alive branches
  50. if: steps.workflow-permission.outputs.has_permission == 'true'
  51. id: check-alive
  52. env:
  53. GITHUB_TOKEN: ${{ secrets.GH_PAT }}
  54. run: |
  55. branch_list=$(gh api -H "Accept: application/vnd.github+json" /repos/${{ github.repository_owner }}/Trio/branches | jq -r '.[].name')
  56. if echo "$branch_list" | grep -q '^alive-main$'; then
  57. echo "alive-main exists"
  58. echo "ALIVE_MAIN_EXISTS=true" >> $GITHUB_ENV
  59. else
  60. echo "alive-main missing"
  61. echo "ALIVE_MAIN_EXISTS=false" >> $GITHUB_ENV
  62. fi
  63. if echo "$branch_list" | grep -q '^alive-dev$'; then
  64. echo "alive-dev exists"
  65. echo "ALIVE_DEV_EXISTS=true" >> $GITHUB_ENV
  66. else
  67. echo "alive-dev missing"
  68. echo "ALIVE_DEV_EXISTS=false" >> $GITHUB_ENV
  69. fi
  70. - name: Create alive-main branch if missing
  71. if: env.ALIVE_MAIN_EXISTS == 'false'
  72. env:
  73. GITHUB_TOKEN: ${{ secrets.GH_PAT }}
  74. run: |
  75. 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')
  76. echo "Creating alive-main from upstream main"
  77. gh api \
  78. --method POST \
  79. -H "Authorization: token $GITHUB_TOKEN" \
  80. -H "Accept: application/vnd.github.v3+json" \
  81. /repos/${{ github.repository_owner }}/Trio/git/refs \
  82. -f ref='refs/heads/alive-main' \
  83. -f sha=$SHA_MAIN
  84. - name: Create alive-dev branch if missing
  85. if: env.ALIVE_DEV_EXISTS == 'false'
  86. env:
  87. GITHUB_TOKEN: ${{ secrets.GH_PAT }}
  88. run: |
  89. 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')
  90. echo "Creating alive-dev from upstream dev"
  91. gh api \
  92. --method POST \
  93. -H "Authorization: token $GITHUB_TOKEN" \
  94. -H "Accept: application/vnd.github.v3+json" \
  95. /repos/${{ github.repository_owner }}/Trio/git/refs \
  96. -f ref='refs/heads/alive-dev' \
  97. -f sha=$SHA_DEV
  98. # Checks for changes in upstream repository; if changes exist prompts sync for build
  99. # Performs keepalive to avoid stale fork
  100. check_latest_from_upstream:
  101. needs: [check_certs, check_alive_and_permissions]
  102. runs-on: ubuntu-latest
  103. name: Check upstream and keep alive
  104. outputs:
  105. NEW_COMMITS: ${{ steps.sync.outputs.has_new_commits }}
  106. ABORT_SYNC: ${{ steps.check_branch.outputs.ABORT_SYNC }}
  107. steps:
  108. - name: Check if running on main or dev branch
  109. if: |
  110. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  111. (vars.SCHEDULED_BUILD != 'false' || vars.SCHEDULED_SYNC != 'false')
  112. id: check_branch
  113. run: |
  114. if [ "${GITHUB_REF##*/}" = "main" ]; then
  115. echo "Running on main branch"
  116. echo "ALIVE_BRANCH=${ALIVE_BRANCH_MAIN}" >> $GITHUB_OUTPUT
  117. echo "ABORT_SYNC=false" >> $GITHUB_OUTPUT
  118. elif [ "${GITHUB_REF##*/}" = "dev" ]; then
  119. echo "Running on dev branch"
  120. echo "ALIVE_BRANCH=${ALIVE_BRANCH_DEV}" >> $GITHUB_OUTPUT
  121. echo "ABORT_SYNC=false" >> $GITHUB_OUTPUT
  122. else
  123. echo "Not running on main or dev branch"
  124. echo "ABORT_SYNC=true" >> $GITHUB_OUTPUT
  125. fi
  126. - name: Checkout target repo
  127. if: |
  128. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  129. (vars.SCHEDULED_BUILD != 'false' || vars.SCHEDULED_SYNC != 'false')
  130. uses: actions/checkout@v4
  131. with:
  132. token: ${{ secrets.GH_PAT }}
  133. ref: ${{ steps.check_branch.outputs.ALIVE_BRANCH }}
  134. - name: Sync upstream changes
  135. if: | # do not run the upstream sync action on the upstream repository
  136. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  137. vars.SCHEDULED_SYNC != 'false' && github.repository_owner != 'nightscout' && steps.check_branch.outputs.ABORT_SYNC == 'false'
  138. id: sync
  139. uses: aormsby/Fork-Sync-With-Upstream-action@v3.4.1
  140. with:
  141. target_sync_branch: ${{ steps.check_branch.outputs.ALIVE_BRANCH }}
  142. shallow_since: 6 months ago
  143. target_repo_token: ${{ secrets.GH_PAT }}
  144. upstream_sync_branch: ${{ env.UPSTREAM_BRANCH }}
  145. upstream_sync_repo: ${{ env.UPSTREAM_REPO }}
  146. # Display a sample message based on the sync output var 'has_new_commits'
  147. - name: New commits found
  148. if: |
  149. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  150. vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'true'
  151. run: echo "New commits were found to sync."
  152. - name: No new commits
  153. if: |
  154. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  155. vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'false'
  156. run: echo "There were no new commits."
  157. - name: Show value of 'has_new_commits'
  158. if: needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' && vars.SCHEDULED_SYNC != 'false' && steps.check_branch.outputs.ABORT_SYNC == 'false'
  159. run: |
  160. echo ${{ steps.sync.outputs.has_new_commits }}
  161. echo "NEW_COMMITS=${{ steps.sync.outputs.has_new_commits }}" >> $GITHUB_OUTPUT
  162. # Keep repository "alive": add empty commits to ALIVE_BRANCH after "time_elapsed" days of inactivity to avoid inactivation of scheduled workflows
  163. - name: Keep alive
  164. run: |
  165. echo "Keep Alive temporarily removed while gautamkrishnar/keepalive-workflow is not available"
  166. # if: |
  167. # needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  168. # (vars.SCHEDULED_BUILD != 'false' || vars.SCHEDULED_SYNC != 'false')
  169. # uses: gautamkrishnar/keepalive-workflow@v1 # using the workflow with default settings
  170. # with:
  171. # time_elapsed: 20 # Time elapsed from the previous commit to trigger a new automated commit (in days)
  172. - name: Show scheduled build configuration message
  173. if: needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION != 'true'
  174. run: |
  175. echo "### :calendar: Scheduled Sync and Build Disabled :mobile_phone_off:" >> $GITHUB_STEP_SUMMARY
  176. echo "You have not yet configured the scheduled sync and build for Trio's browser build." >> $GITHUB_STEP_SUMMARY
  177. echo "Synchronizing your fork of <code>Trio</code> with the upstream repository <code>nightscout/Trio</code> will be skipped." >> $GITHUB_STEP_SUMMARY
  178. echo "If you want to enable automatic builds and updates for your Trio, please follow the instructions \
  179. under the following path <code>Trio/fastlane/testflight.md</code>." >> $GITHUB_STEP_SUMMARY
  180. # Builds Trio
  181. build:
  182. name: Build
  183. needs: [check_certs, check_alive_and_permissions, check_latest_from_upstream]
  184. runs-on: macos-15
  185. permissions:
  186. contents: write
  187. if:
  188. | # 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
  189. github.event_name == 'workflow_dispatch' ||
  190. (needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  191. (vars.SCHEDULED_BUILD != 'false' && github.event.schedule == '43 6 8-14 * 6') ||
  192. (vars.SCHEDULED_SYNC != 'false' && needs.check_latest_from_upstream.outputs.NEW_COMMITS == 'true' )
  193. )
  194. steps:
  195. - name: Select Xcode version
  196. run: "sudo xcode-select --switch /Applications/Xcode_16.3.app/Contents/Developer"
  197. - name: Checkout Repo for syncing
  198. if: |
  199. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  200. vars.SCHEDULED_SYNC != 'false'
  201. uses: actions/checkout@v4
  202. with:
  203. token: ${{ secrets.GH_PAT }}
  204. ref: ${{ env.TARGET_BRANCH }}
  205. - name: Sync upstream changes
  206. if: | # do not run the upstream sync action on the upstream repository
  207. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  208. vars.SCHEDULED_SYNC != 'false' && github.repository_owner != 'nightscout' && needs.check_latest_from_upstream.outputs.ABORT_SYNC == 'false'
  209. id: sync
  210. uses: aormsby/Fork-Sync-With-Upstream-action@v3.4.1
  211. with:
  212. target_sync_branch: ${{ env.TARGET_BRANCH }}
  213. shallow_since: 6 months ago
  214. target_repo_token: ${{ secrets.GH_PAT }}
  215. upstream_sync_branch: ${{ env.UPSTREAM_BRANCH }}
  216. upstream_sync_repo: ${{ env.UPSTREAM_REPO }}
  217. # Display a sample message based on the sync output var 'has_new_commits'
  218. - name: New commits found
  219. if: |
  220. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  221. vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'true' && needs.check_latest_from_upstream.outputs.ABORT_SYNC == 'false'
  222. run: echo "New commits were found to sync."
  223. - name: No new commits
  224. if: |
  225. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
  226. vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'false' && needs.check_latest_from_upstream.outputs.ABORT_SYNC == 'false'
  227. run: echo "There were no new commits."
  228. - name: Show value of 'has_new_commits'
  229. if: |
  230. needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true'
  231. && vars.SCHEDULED_SYNC != 'false' && needs.check_latest_from_upstream.outputs.ABORT_SYNC == 'false'
  232. run: |
  233. echo ${{ steps.sync.outputs.has_new_commits }}
  234. echo "NEW_COMMITS=${{ steps.sync.outputs.has_new_commits }}" >> $GITHUB_OUTPUT
  235. - name: Checkout Repo for building
  236. uses: actions/checkout@v4
  237. with:
  238. token: ${{ secrets.GH_PAT }}
  239. submodules: recursive
  240. ref: ${{ env.TARGET_BRANCH }}
  241. # Customize Trio: Use patches or download and apply patches from GitHub
  242. - name: Customize Trio
  243. run: |
  244. # Trio workspace patches
  245. # -applies any patches located in the Trio/patches/ directory
  246. if $(ls ./patches/* &> /dev/null); then
  247. git apply ./patches/* --allow-empty -v --whitespace=fix
  248. fi
  249. # Download and apply Trio patches from GitHub:
  250. # Template for customizing Trio code (as opposed to submodule code)
  251. # Remove the "#" sign from the beginning of the line below to activate
  252. # and then replace the alphanumeric string with your SHA, this SHA is NOT valid
  253. #curl https://github.com/nightscout/Trio/commit/d206432b024279ef710df462b20bd464cd9682d4.patch | git apply -v --whitespace=fix
  254. # Download and apply Submodule patches from GitHub:
  255. # Template for customizing submodules (you must edit the submodule name)
  256. # This example is for G7SensorKit showing you can apply multiple commits, in the proper order
  257. # Remove the "#" sign from the beginning of the lines below to activate
  258. # This example applies 3 commits from the scan-fix folder; valid only when these are not already in Trio
  259. #curl https://github.com/loopandlearn/G7SensorKit/commit/ba44beb3d1491c453f4f438443c3f8ba29146ab3.patch | git apply --directory=G7SensorKit -v --whitespace=fix
  260. #curl https://github.com/loopandlearn/G7SensorKit/commit/d86ac8e9cd523d1267587dd70c96597125eef7ab.patch | git apply --directory=G7SensorKit -v --whitespace=fix
  261. #curl https://github.com/loopandlearn/G7SensorKit/commit/205054e7537723c2aec58d807634b4853f687244.patch | git apply --directory=G7SensorKit -v --whitespace=fix
  262. # Add patches for additional customization by following the templates above,
  263. # and make sure to specify the submodule by setting "--directory=(submodule_name)".
  264. # Several patches may be added per submodule.
  265. # Adding comments (#) is strongly recommended to easily tell the individual patches apart.
  266. # Patch Fastlane Match to not print tables
  267. - name: Patch Match Tables
  268. run: |
  269. TABLE_PRINTER_PATH=$(ruby -e 'puts Gem::Specification.find_by_name("fastlane").gem_dir')/match/lib/match/table_printer.rb
  270. if [ -f "$TABLE_PRINTER_PATH" ]; then
  271. sed -i "" "/puts(Terminal::Table.new(params))/d" "$TABLE_PRINTER_PATH"
  272. else
  273. echo "table_printer.rb not found"
  274. exit 1
  275. fi
  276. # Install project dependencies
  277. - name: Install Project Dependencies
  278. run: bundle install
  279. # Sync the GitHub runner clock with the Windows time server (workaround as suggested in https://github.com/actions/runner/issues/2996)
  280. - name: Sync clock
  281. run: sudo sntp -sS time.windows.com
  282. # Build signed Trio IPA file
  283. - name: Fastlane Build & Archive
  284. run: bundle exec fastlane build_trio
  285. env:
  286. TEAMID: ${{ secrets.TEAMID }}
  287. GH_PAT: ${{ secrets.GH_PAT }}
  288. FASTLANE_KEY_ID: ${{ secrets.FASTLANE_KEY_ID }}
  289. FASTLANE_ISSUER_ID: ${{ secrets.FASTLANE_ISSUER_ID }}
  290. FASTLANE_KEY: ${{ secrets.FASTLANE_KEY }}
  291. MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
  292. # Upload to TestFlight
  293. - name: Fastlane upload to TestFlight
  294. run: bundle exec fastlane release
  295. env:
  296. TEAMID: ${{ secrets.TEAMID }}
  297. GH_PAT: ${{ secrets.GH_PAT }}
  298. FASTLANE_KEY_ID: ${{ secrets.FASTLANE_KEY_ID }}
  299. FASTLANE_ISSUER_ID: ${{ secrets.FASTLANE_ISSUER_ID }}
  300. FASTLANE_KEY: ${{ secrets.FASTLANE_KEY }}
  301. MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
  302. # Upload Build artifacts
  303. - name: Upload build log, IPA and Symbol artifacts
  304. if: always()
  305. uses: actions/upload-artifact@v4
  306. with:
  307. name: build-artifacts
  308. path: |
  309. artifacts
  310. buildlog