diff --git a/.github/workflows/build_LoopFollow.yml b/.github/workflows/build_LoopFollow.yml index 443f7bf0c..abf779d15 100644 --- a/.github/workflows/build_LoopFollow.yml +++ b/.github/workflows/build_LoopFollow.yml @@ -131,10 +131,10 @@ jobs: if: steps.workflow-permission.outputs.has_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 LoopFollow's browser build." >> $GITHUB_STEP_SUMMARY - echo "Synchronizing your fork of LoopFollow with the upstream repository loopandlearn/LoopFollow will be skipped." >> $GITHUB_STEP_SUMMARY - echo "If you want to enable automatic builds and updates for your LoopFollow, please follow the instructions \ - under the following path LoopFollow/fastlane/testflight.md." >> $GITHUB_STEP_SUMMARY + echo "You have not yet configured the scheduled sync and build for ${{ github.event.repository.name }}'s browser build." >> $GITHUB_STEP_SUMMARY + echo "Synchronizing your fork of ${{ github.event.repository.name }} with the upstream repository ${{ env.UPSTREAM_REPO }} will be skipped." >> $GITHUB_STEP_SUMMARY + echo "If you want to enable automatic builds and updates for your ${{ github.event.repository.name }}, please follow the instructions \ + under the following path ${{ github.event.repository.name }}/fastlane/testflight.md." >> $GITHUB_STEP_SUMMARY # Set a logic flag if this is the second instance of this day-of-week in this month - name: Check if this is the second time this day-of-week happens this month @@ -161,7 +161,7 @@ jobs: (vars.SCHEDULED_BUILD != 'false' && needs.check_status.outputs.IS_SECOND_IN_MONTH == 'true') || (vars.SCHEDULED_SYNC != 'false' && needs.check_status.outputs.NEW_COMMITS == 'true' ) - # Builds LoopFollow + # Builds the app build: name: Build needs: [check_certs, check_status] @@ -203,7 +203,7 @@ jobs: - name: Sync clock run: sudo sntp -sS time.windows.com - # Build signed LoopFollow IPA file + # Build signed IPA file - name: Fastlane Build & Archive run: bundle exec fastlane build_LoopFollow env: diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 120b9f061..8f46645c5 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -23,6 +23,27 @@ DEVICE_NAME = ENV["DEVICE_NAME"] DEVICE_ID = ENV["DEVICE_ID"] ENV["FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT"] = "120" +# Reads the per-app suffix from LoopFollowDisplayNameConfig.xcconfig so the same +# Fastfile produces the correct bundle identifiers in every sister repository +# (LoopFollow, LoopFollow_Second, LoopFollow_Third) without per-repo edits. +def loopfollow_app_suffix + root = GITHUB_WORKSPACE || File.expand_path("..", __dir__) + path = File.join(root, "LoopFollowDisplayNameConfig.xcconfig") + return "" unless File.exist?(path) + + File.foreach(path) do |line| + next if line.strip.start_with?("//") + if (match = line.match(/^\s*app_suffix\s*=\s*(.*)$/)) + return match[1].strip + end + end + "" +end + +APP_SUFFIX = loopfollow_app_suffix +APP_IDENTIFIER = "com.#{TEAMID}.LoopFollow#{APP_SUFFIX}" +LA_IDENTIFIER = "#{APP_IDENTIFIER}.LoopFollowLAExtension" + platform :ios do desc "Build Loop Follow" lane :build_LoopFollow do @@ -40,7 +61,7 @@ platform :ios do ) previous_build_number = latest_testflight_build_number( - app_identifier: "com.#{TEAMID}.LoopFollow", + app_identifier: APP_IDENTIFIER, api_key: api_key, ) @@ -55,8 +76,8 @@ platform :ios do type: "appstore", git_basic_authorization: Base64.strict_encode64("#{GITHUB_REPOSITORY_OWNER}:#{GH_PAT}"), app_identifier: [ - "com.#{TEAMID}.LoopFollow", - "com.#{TEAMID}.LoopFollow.LoopFollowLAExtension" + APP_IDENTIFIER, + LA_IDENTIFIER ] ) @@ -66,14 +87,14 @@ platform :ios do update_code_signing_settings( path: "#{GITHUB_WORKSPACE}/LoopFollow.xcodeproj", - profile_name: mapping["com.#{TEAMID}.LoopFollow"], + profile_name: mapping[APP_IDENTIFIER], code_sign_identity: "iPhone Distribution", targets: ["LoopFollow"] ) update_code_signing_settings( - path: "#{GITHUB_WORKSPACE}/LoopFollow.xcodeproj", - profile_name: mapping["com.#{TEAMID}.LoopFollow.LoopFollowLAExtension"], + path: "#{GITHUB_WORKSPACE}/LoopFollow.xcodeproj", + profile_name: mapping[LA_IDENTIFIER], code_sign_identity: "iPhone Distribution", targets: ["LoopFollowLAExtensionExtension"] ) @@ -87,10 +108,10 @@ platform :ios do buildlog_path: 'buildlog', export_options: { provisioningProfiles: { - "com.#{TEAMID}.LoopFollow" => mapping["com.#{TEAMID}.LoopFollow"], - "com.#{TEAMID}.LoopFollow.LoopFollowLAExtension" => mapping["com.#{TEAMID}.LoopFollow.LoopFollowLAExtension"] + APP_IDENTIFIER => mapping[APP_IDENTIFIER], + LA_IDENTIFIER => mapping[LA_IDENTIFIER] } - } + } ) copy_artifacts( @@ -138,12 +159,12 @@ platform :ios do end end - configure_bundle_id("LoopFollow", "com.#{TEAMID}.LoopFollow", [ + configure_bundle_id("LoopFollow", APP_IDENTIFIER, [ Spaceship::ConnectAPI::BundleIdCapability::Type::APP_GROUPS, Spaceship::ConnectAPI::BundleIdCapability::Type::PUSH_NOTIFICATIONS ]) - - configure_bundle_id("LoopFollow Live Activity Extension", "com.#{TEAMID}.LoopFollow.LoopFollowLAExtension", [ + + configure_bundle_id("LoopFollow Live Activity Extension", LA_IDENTIFIER, [ Spaceship::ConnectAPI::BundleIdCapability::Type::APP_GROUPS ]) @@ -166,8 +187,8 @@ platform :ios do verbose: true, git_basic_authorization: Base64.strict_encode64("#{GITHUB_REPOSITORY_OWNER}:#{GH_PAT}"), app_identifier: [ - "com.#{TEAMID}.LoopFollow", - "com.#{TEAMID}.LoopFollow.LoopFollowLAExtension" + APP_IDENTIFIER, + LA_IDENTIFIER ] ) end diff --git a/release.sh b/release.sh index 3ba67c2fb..fa97f02bf 100755 --- a/release.sh +++ b/release.sh @@ -14,7 +14,6 @@ VERSION_FILE="Config.xcconfig" MARKETING_KEY="LOOP_FOLLOW_MARKETING_VERSION" DEV_BRANCH="dev" MAIN_BRANCH="main" -PATCH_DIR="../${APP_NAME}_update_patches" # --------------------------------------- # --- functions here --- @@ -26,38 +25,49 @@ queue_push() { push_cmds+=("git -C \"$(pwd)\" $*"); echo "+ [queued] (in $(pwd)) update_follower () { local DIR="$1" + local build_minute="$2" # staggered Sunday-build minute (see calls below) + local suffix=".${DIR#${APP_NAME}_}" # LoopFollow_Second -> .Second + local display="$DIR" # LoopFollow_Second + local upstream="loopandlearn/${DIR}" # loopandlearn/LoopFollow_Second + echo; echo "🔄 Updating $DIR …" cd "$DIR" - echo; echo "If there are custom changes needed to the patch, make the change before continuing" - pause - # 1 · Make sure we’re on a clean, up-to-date main echo_run git switch "$MAIN_BRANCH" echo_run git fetch echo_run git pull - # 2 · Apply the patch - if ! git apply --whitespace=nowarn "$PATCH_FILE"; then - echo "‼️ Some changes could not be applied, so no changes were made." - echo "The command used was: git apply --whitespace=nowarn $PATCH_FILE" - echo; echo "Use a different terminal to fix and apply the patch before continuing" - pause + # 2 · Full mirror of the release tree from the primary repo. + # Every tracked file (including the overlay files) is synced; only git + # metadata and local/build dirs are protected. --delete makes the tree an + # exact mirror, auto-correcting any drift. + echo_run rsync -a --delete \ + --exclude='.git/' \ + --exclude='.claude/' \ + --exclude='build/' \ + "$PRIMARY_ABS_PATH"/ ./ + + # 3 · Re-apply this instance's overlay on top of the mirror + perl -i -pe "s|^app_suffix\s*=.*|app_suffix = ${suffix}|" LoopFollowDisplayNameConfig.xcconfig + perl -i -pe "s|^display_name\s*=.*|display_name = ${display}|" LoopFollowDisplayNameConfig.xcconfig + perl -i -pe "s|^(\s*)UPSTREAM_REPO:.*|\${1}UPSTREAM_REPO: ${upstream}|" .github/workflows/build_LoopFollow.yml + perl -i -pe "s|^(\s*)- cron:.*|\${1}- cron: \"${build_minute} 10 * * 0\" # Sunday at UTC 10:${build_minute}|" .github/workflows/build_LoopFollow.yml + + # 4 · Rename the synced workspace to this instance's name + rm -rf "${DIR}.xcworkspace" + if [ -d "${APP_NAME}.xcworkspace" ]; then + mv "${APP_NAME}.xcworkspace" "${DIR}.xcworkspace" fi - # 3 · Pause if any conflict markers remain - if git ls-files -u | grep -q .; then - echo "⚠️ Conflicts detected." - echo " If Fastfile or build_LoopFollow.yml were modified, these are expected." - echo " Open your merge tool, resolve, then press Enter." - pause + # 5 · Single commit capturing the mirror + overlay + git add -A + if git diff --cached --quiet; then + echo "✓ $DIR already up to date — nothing to commit." + else + echo_run git commit -m "transfer v${new_ver} updates from LF to ${DIR}" fi - # 4 · Single commit capturing all staged changes - git add -u - git add $(git ls-files --others --exclude-standard) 2>/dev/null || true - git commit -m "transfer v${new_ver} updates from LF to ${DIR}" - echo_run git status echo "💻 Build & test $DIR now."; pause # build & test checkpoint queue_push push origin "$MAIN_BRANCH" @@ -109,16 +119,13 @@ echo_run git commit -m "update version to ${new_ver} [skip ci]" "$VERSION_FILE" echo "💻 Build & test release branch now."; pause queue_push push origin "$RELEASE_BRANCH" -# --- create a patch from main..release branch (includes the bump) ----- -mkdir -p "$PATCH_DIR" -PATCH_FILE="${PATCH_DIR}/LF_diff_${old_ver}_to_${new_ver}.patch" - -git diff -M --binary "$MAIN_BRANCH" "$RELEASE_BRANCH" \ - > "$PATCH_FILE" - +# --- mirror the release tree into the sister repos ---- +# Second arg = each app's scheduled browser-build minute (Sundays at 10:xx UTC), +# staggered from the main app (:17) so a user who forked all three apps doesn't +# trigger three simultaneous builds. cd .. -update_follower "$SECOND_DIR" -update_follower "$THIRD_DIR" +update_follower "$SECOND_DIR" "27" +update_follower "$THIRD_DIR" "40" # ---------- GitHub Actions Test --------- echo;