build_trio.yml 16 KB

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