Skip to content

Commit

Permalink
Scheduled build improvements (LoopKit#71)
Browse files Browse the repository at this point in the history
* Add conditional scheduled build and sync

* Update testflight.md with instructions for scheduling setup

* Fix typo

* Remove GITHUB_TOKEN; use GH_PAT instead

* Update testflight.md with instructions how to add workflow scope

* Fixed conditions for scheduled build

* Fix upstream repo owner

* Refactor build to use workflow permissions and auto-create alive branch

* Change GITHUB_TOKEN to GH_PAT

* Change token to GITHUB_TOKEN where appropriate; Make env variable names more descriptive

* Fix broken alive branch auto-creation

* Update testflight.md with opt-out and new config info

* Update cron for sync and schedule, update build condition

* Fix typo…

* Update testflight.md with suggestions and re-organized contents

* Fix typo from PR74
  • Loading branch information
dnzxy authored Aug 20, 2023
1 parent 024b37c commit 484d3b4
Show file tree
Hide file tree
Showing 2 changed files with 224 additions and 33 deletions.
139 changes: 125 additions & 14 deletions .github/workflows/build_loop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,105 @@ on:
#push:

schedule:
- cron: '0 04 * * *' # Checks for updates at 04:00 UTC every day
- cron: '0 04 1 * *' # Builds the app on the 1th every month
- cron: '0 8 * * 3' # Checks for updates at 08:00 am UTC every Wednesday
- cron: '0 8 1 * 6' # Builds the app on the 1st Saturday every month at 08:00 am UTC

env:
UPSTREAM_REPO: LoopKit/LoopWorkspace
UPSTREAM_BRANCH: ${{ github.ref_name }} # branch on upstream repository to sync from (relpace with specific branch name if needed)
TARGET_BRANCH: ${{ github.ref_name }} # target branch on fork to be kept in sync, and target branch on upstream to be kept alive (relpace with specific branch name if needed)
UPSTREAM_BRANCH: ${{ github.ref_name }} # branch on upstream repository to sync from (replace with specific branch name if needed)
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)
ALIVE_BRANCH: alive
SYNC_UPSTREAM: ${{ vars.SYNC_UPSTREAM }} # set an optional "SYNC_UPSTREAM" repository variable to 'false' to disable syncing of fork with the upstream repository
WORKFLOW_PERMISSIONS: false

jobs:
secrets:
uses: ./.github/workflows/validate_secrets.yml
secrets: inherit

# Checks if GH_PAT holds workflow permissions
# Checks for existence of alive branch; if non-existent creates it
check_alive_and_permissions:
needs: secrets
runs-on: ubuntu-latest
name: Check alive branch and permissions
permissions:
contents: write
outputs:
WORKFLOW_PERMISSION: ${{ steps.workflow-permission.outputs.has_permission }}

steps:
- name: Check for workflow permissions
id: workflow-permission
env:
TOKEN_TO_CHECK: ${{ secrets.GH_PAT }}
run: |
PERMISSIONS=$(curl -sS -f -I -H "Authorization: token ${{ env.TOKEN_TO_CHECK }}" https://api.github.com | grep ^x-oauth-scopes: | cut -d' ' -f2-);
if [[ $PERMISSIONS =~ "workflow" || $PERMISSIONS == "" ]]; then
echo "GH_PAT holds workflow permissions or is fine-grained PAT."
echo "has_permission=true" >> $GITHUB_OUTPUT # Set WORKFLOW_PERMISSION to false.
else
echo "GH_PAT lacks workflow permissions."
echo "Automated build features will be skipped!"
echo "has_permission=false" >> $GITHUB_OUTPUT # Set WORKFLOW_PERMISSION to false.
fi
- name: Check for alive branch
if: steps.workflow-permission.outputs.has_permission == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [[ "$(gh api -H "Accept: application/vnd.github+json" /repos/${{ github.repository_owner }}/LoopWorkspace/branches | jq --raw-output 'any(.name=="alive")')" == "true" ]]; then
echo "Branch 'alive' exists."
echo "ALIVE_BRANCH_EXISTS=true" >> $GITHUB_ENV # Set ALIVE_BRANCH_EXISTS to true
else
echo "Branch 'alive' does not exist."
echo "ALIVE_BRANCH_EXISTS=false" >> $GITHUB_ENV # Set ALIVE_BRANCH_EXISTS to false
fi
- name: Create alive branch
if: env.ALIVE_BRANCH_EXISTS != 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Get ref for LoopKit/LoopWorkspace:dev
SHA=$(curl -sS https://api.github.com/repos/${{ env.UPSTREAM_REPO }}/git/refs \
| jq '.[] | select(.ref == "refs/heads/dev" ) | .object.sha' \
| tr -d '"'
);
# Create alive branch based on LoopKit/LoopWorkspace:dev
gh api \
--method POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
/repos/${{ github.repository_owner }}/LoopWorkspace/git/refs \
-f ref='refs/heads/alive' \
-f sha=$SHA
# Checks for changes in upstream repository; if changes exist prompts sync for build
# Performs keepalive to avoid stale fork
check_latest_from_upstream:
needs: check_alive_and_permissions
runs-on: ubuntu-latest
name: Check upstream and keep alive
outputs:
NEW_COMMITS: ${{ steps.sync.outputs.has_new_commits }}

steps:
- name: Checkout target repo
if: |
needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
(vars.SCHEDULED_BUILD != 'false' || vars.SCHEDULED_SYNC != 'false')
uses: actions/checkout@v3
with:
token: ${{ secrets.GH_PAT }}
ref: alive

- name: Sync upstream changes
if: ${{ env.SYNC_UPSTREAM != 'false' && github.repository_owner != 'LoopKit' }} # do not run the upstream sync action on the upstream repository
if: | # do not run the upstream sync action on the upstream repository
needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
vars.SCHEDULED_SYNC != 'false' && github.repository_owner != 'LoopKit'
id: sync
uses: aormsby/[email protected]
with:
Expand All @@ -44,41 +117,72 @@ jobs:

# Display a sample message based on the sync output var 'has_new_commits'
- name: New commits found
if: steps.sync.outputs.has_new_commits == 'true'
if: |
needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'true'
run: echo "New commits were found to sync."

- name: No new commits
if: steps.sync.outputs.has_new_commits == 'false'
if: |
needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'false'
run: echo "There were no new commits."

- name: Show value of 'has_new_commits'
if: needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' && vars.SCHEDULED_SYNC != 'false'
run: |
echo ${{ steps.sync.outputs.has_new_commits }}
echo "NEW_COMMITS=${{ steps.sync.outputs.has_new_commits }}" >> $GITHUB_OUTPUT
# Keep repository "alive": add empty commits to ALIVE_BRANCH after "time_elapsed" days of inactivity to avoid inactivation of scheduled workflows
- name: Keep alive
if: |
needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
(vars.SCHEDULED_BUILD != 'false' || vars.SCHEDULED_SYNC != 'false')
uses: gautamkrishnar/keepalive-workflow@v1 # using the workflow with default settings
with:
time_elapsed: 20 # Time elapsed from the previous commit to trigger a new automated commit (in days)

- name: Show scheduled build configuration message
if: needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION != 'true'
run: |
echo "### :calendar: Scheduled Sync and Build Disabled :mobile_phone_off:" >> $GITHUB_STEP_SUMMARY
echo "You have not yet configured the scheduled sync and build for Loop's browser build." >> $GITHUB_STEP_SUMMARY
echo "Synchronizing your fork of <code>LoopWorkspace</code> with the upstream repository <code>LoopKit/LoopWorkspace</code> will be skipped." >> $GITHUB_STEP_SUMMARY
echo "If you want to enable automatic builds and updates for your Loop, please follow the instructions \
under the following path <code>LoopWorkspace/fastlane/testflight.md</code>." >> $GITHUB_STEP_SUMMARY

# Builds Loop
build:
name: Build
needs: check_latest_from_upstream
runs-on: macos-13
if: ${{ github.event_name == 'workflow_dispatch' || github.event.schedule == '0 04 1 * *' || needs.check_latest_from_upstream.outputs.NEW_COMMITS == 'true' }} # runs if started manually, or if scheduled on the first each month, or if new commits were found
permissions:
contents: write
if: | # 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
github.event_name == 'workflow_dispatch' ||
(needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
(vars.SCHEDULED_BUILD != 'false' && github.event.schedule == '0 8 1 * 6') ||
(vars.SCHEDULED_SYNC != 'false' && needs.check_latest_from_upstream.outputs.NEW_COMMITS == 'true' )
)
steps:
- name: Select Xcode version
run: "sudo xcode-select --switch /Applications/Xcode_14.3.1.app/Contents/Developer"

- name: Checkout Repo for syncing
if: |
needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
vars.SCHEDULED_SYNC != 'false'
uses: actions/checkout@v3
with:
token: ${{ secrets.GH_PAT }}
ref: ${{ env.TARGET_BRANCH }}

- name: Sync upstream changes
if: ${{ env.SYNC_UPSTREAM != 'false' && github.repository_owner != 'LoopKit' }} # do not run the upstream sync action on the upstream repository
if: | # do not run the upstream sync action on the upstream repository
needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
vars.SCHEDULED_SYNC != 'false' && github.repository_owner != 'LoopKit'
id: sync
uses: aormsby/[email protected]
with:
Expand All @@ -90,14 +194,21 @@ jobs:

# Display a sample message based on the sync output var 'has_new_commits'
- name: New commits found
if: steps.sync.outputs.has_new_commits == 'true'
if: |
needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'true'
run: echo "New commits were found to sync."

- name: No new commits
if: steps.sync.outputs.has_new_commits == 'false'
if: |
needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'false'
run: echo "There were no new commits."

- name: Show value of 'has_new_commits'
if: |
needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true'
&& vars.SCHEDULED_SYNC != 'false'
run: |
echo ${{ steps.sync.outputs.has_new_commits }}
echo "NEW_COMMITS=${{ steps.sync.outputs.has_new_commits }}" >> $GITHUB_OUTPUT
Expand Down
Loading

0 comments on commit 484d3b4

Please sign in to comment.