build_trio.yml 17 KB

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