build_trio.yml 16 KB

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