From ff2bcc82b1747b63f93aed1aef5e5c880dbea827 Mon Sep 17 00:00:00 2001 From: Ammar Ahmed Date: Mon, 30 Mar 2026 16:07:51 +0500 Subject: [PATCH] ci: add ios workflow --- .github/workflows/ios.preview.firebase.yml | 145 ++++++++++++++++++ apps/mobile/ios/ExportOptionsStaging.plist | 15 ++ .../ios/Notesnook.xcodeproj/project.pbxproj | 46 +++--- apps/mobile/ios/Notesnook/Info.plist | 2 +- apps/mobile/ios/Podfile | 16 ++ apps/mobile/ios/Podfile.lock | 30 ++-- apps/mobile/ios/build-configs/README.md | 41 +++++ .../build-configs/ios-build.active.xcconfig | 10 ++ .../ios-build.production.xcconfig | 10 ++ .../build-configs/ios-build.staging.xcconfig | 10 ++ .../ios/build-configs/use-ios-build-config.sh | 99 ++++++++++++ 11 files changed, 387 insertions(+), 37 deletions(-) create mode 100644 .github/workflows/ios.preview.firebase.yml create mode 100644 apps/mobile/ios/ExportOptionsStaging.plist create mode 100644 apps/mobile/ios/build-configs/README.md create mode 100644 apps/mobile/ios/build-configs/ios-build.active.xcconfig create mode 100644 apps/mobile/ios/build-configs/ios-build.production.xcconfig create mode 100644 apps/mobile/ios/build-configs/ios-build.staging.xcconfig create mode 100755 apps/mobile/ios/build-configs/use-ios-build-config.sh diff --git a/.github/workflows/ios.preview.firebase.yml b/.github/workflows/ios.preview.firebase.yml new file mode 100644 index 000000000..1ea962c69 --- /dev/null +++ b/.github/workflows/ios.preview.firebase.yml @@ -0,0 +1,145 @@ +name: Notesnook iOS Preview + +on: + pull_request: + types: [opened, reopened, synchronize] + branches: [master, beta] + paths: + - "apps/mobile/**" + - "packages/**" + # re-run workflow if workflow file changes + - ".github/workflows/mobile.publish.firebase.yml" + +jobs: + build: + runs-on: macos-26 + timeout-minutes: 60 + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup Node + uses: ./.github/actions/setup-node-with-cache + + - name: Setup Xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: "26.1.1" + + - name: Install node modules + run: | + npm ci --ignore-scripts --prefer-offline --no-audit + npm run bootstrap -- --scope=mobile + + - name: Build packages + run: npm run tx @notesnook/mobile:build + + - name: Cache Pods + uses: actions/cache@v3 + id: pods-cache + with: + path: apps/mobile/ios/Pods + key: ${{ runner.os }}-pods-${{ hashFiles('apps/mobile/ios/Podfile.lock') }} + + - name: Install Pods + run: | + cd apps/mobile/ios + pod install + + - name: Check for typescript errors + run: | + npm run tx mobile:build + cd apps/mobile + npx tsc --noEmit + + - name: Get marketing version + id: marketing-version + run: echo "version=$(grep "IOS_MARKETING_VERSION" apps/mobile/ios/build-configs/ios-build.staging.xcconfig | awk -F'=' '{print $2}' | xargs)" >> $GITHUB_OUTPUT + + - name: Get build number + id: build-number + run: echo "timestamp=$(($(date +%s) - 1774851180 ))" >> $GITHUB_OUTPUT + + - name: Make staging xcconfig active + run: | + cd apps/mobile/ios/build-configs + ./use-ios-build-config.sh staging --marketing-version ${{steps.marketing-version.outputs.version}} --build-number ${{steps.build-number.outputs.timestamp}} + + - name: Build iOS App + uses: ammarahm-ed/ios-build-action@master + with: + bundle-identifier: org.streetwriters.notesnook + scheme: Notesnook + configuration: "Release" + export-options: apps/mobile/ios/ExportOptionsStaging.plist + export-method: "ad-hoc" + project-path: apps/mobile/ios/Notesnook.xcodeproj + workspace-path: apps/mobile/ios/Notesnook.xcworkspace + update-targets: | + Notesnook + Make Note + NotesWidgetExtension + disable-targets: Notesnook-tvOS,Notesnook-tvOSTests,NotesnookTests + code-signing-identity: Apple Distribution + team-id: ${{ secrets.APPLE_TEAM_ID }} + p12-base64: ${{ secrets.APPLE_CERTIFICATE_P12 }} + certificate-password: ${{ secrets.APPLE_CERTIFICATE_P12_PASSWORD }} + app-store-connect-api-key-issuer-id: ${{ secrets.API_KEY_ISSUER_ID }} + app-store-connect-api-key-id: ${{ secrets.APPSTORE_KEY_ID }} + app-store-connect-api-key-base64: ${{ secrets.APPSTORE_CONNECT_API_KEY_BASE64 }} + output-path: Notesnook.ipa + mobileprovision-base64: | + ${{ secrets.APPLE_MOBILE_PROVISION_ADHOC_APP }} + ${{ secrets.APPLE_MOBILE_PROVISION_ADHOC_SHARE }} + ${{ secrets.APPLE_MOBILE_PROVISION_ADHOC_WIDGET }} + + - name: Publish to firebase CLI + id: firebase-output + uses: wzieba/Firebase-Distribution-Github-Action@v1 + with: + appId: ${{secrets.FIREBASE_IOS_APP_ID}} + serviceCredentialsFileContent: ${{ secrets.QA_SERVICE_ACCOUNT }} + groups: testers + file: Notesnook.ipa + + - name: Post or update PR comment + uses: actions/github-script@v6 + env: + preview_url: ${{ steps.firebase-output.outputs.TESTING_URI }} + with: + script: | + const marker = ''; + const prNumber = context.issue.number; + const previewUrl = process.env.preview_url || ''; + const body = `${marker}\n**iOS App Preview**\n\n${previewUrl || 'Preview URL unavailable — check workflow logs.'}\n\nCommit: ${process.env.GITHUB_SHA}\n`; + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + }); + const existing = comments.find(c => c.body && c.body.includes(marker)); + if (existing) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existing.id, + body, + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body, + }); + } + + # - name: Upload Notesnook.ipa to Github + # uses: actions/upload-artifact@v4 + # with: + # name: Notesnook.zip + # path: | + # Notesnook.ipa + # apps/mobile/ios/**/*.map + # packages/editor-mobile/sourcemaps/*.map diff --git a/apps/mobile/ios/ExportOptionsStaging.plist b/apps/mobile/ios/ExportOptionsStaging.plist new file mode 100644 index 000000000..7aca51e30 --- /dev/null +++ b/apps/mobile/ios/ExportOptionsStaging.plist @@ -0,0 +1,15 @@ + + + + + provisioningProfiles + + org.streetwriters.notesnook + Notesnook Adhoc 2026 + org.streetwriters.notesnook.notewidget + Notesnook Note Widget Adhoc 2026 + org.streetwriters.notesnook.share + Notesnook Share Adhoc 2026 + + + \ No newline at end of file diff --git a/apps/mobile/ios/Notesnook.xcodeproj/project.pbxproj b/apps/mobile/ios/Notesnook.xcodeproj/project.pbxproj index 7d26398c7..45261c8ae 100644 --- a/apps/mobile/ios/Notesnook.xcodeproj/project.pbxproj +++ b/apps/mobile/ios/Notesnook.xcodeproj/project.pbxproj @@ -144,6 +144,7 @@ 65E03409257B9FF100793428 /* Notesnook-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Notesnook-Bridging-Header.h"; sourceTree = ""; }; 65E0340A257B9FF100793428 /* File.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = File.swift; sourceTree = ""; }; 65EC5B71272A7EE200FB3748 /* NotesWidgetExtensionDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NotesWidgetExtensionDebug.entitlements; sourceTree = ""; }; + 684AA0A1B1BE6091A02D42FF /* ios-build.active.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "ios-build.active.xcconfig"; path = "build-configs/ios-build.active.xcconfig"; sourceTree = SOURCE_ROOT; }; 77124A1C1FB538ED63FDEF82 /* Pods-Notesnook.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Notesnook.release.xcconfig"; path = "Target Support Files/Pods-Notesnook/Pods-Notesnook.release.xcconfig"; sourceTree = ""; }; 7D3F6A50D104CE391243515F /* Pods-Notesnook-Add to Notes.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Notesnook-Add to Notes.release.xcconfig"; path = "Target Support Files/Pods-Notesnook-Add to Notes/Pods-Notesnook-Add to Notes.release.xcconfig"; sourceTree = ""; }; 88211800FA8BF60638327ADE /* Pods-Make Note.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Make Note.debug.xcconfig"; path = "Target Support Files/Pods-Make Note/Pods-Make Note.debug.xcconfig"; sourceTree = ""; }; @@ -312,6 +313,7 @@ 2D16E6871FA4F8E400B85C8A /* Frameworks */, DA84645424CFBF19A44D64B3 /* Pods */, B5216B66C0B4A91C0A69128B /* PrivacyInfo.xcprivacy */, + 684AA0A1B1BE6091A02D42FF /* ios-build.active.xcconfig */, ); indentWidth = 2; sourceTree = ""; @@ -1035,7 +1037,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2178; + CURRENT_PROJECT_VERSION = "$(IOS_CURRENT_PROJECT_VERSION)"; DEVELOPMENT_TEAM = 53CWBG3QUC; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; @@ -1110,13 +1112,13 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 3.3.18; + MARKETING_VERSION = "$(IOS_MARKETING_VERSION)"; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook; + PRODUCT_BUNDLE_IDENTIFIER = "$(IOS_MAIN_BUNDLE_ID)"; PRODUCT_NAME = Notesnook; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Notesnook-Bridging-Header.h"; @@ -1141,7 +1143,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2178; + CURRENT_PROJECT_VERSION = "$(IOS_CURRENT_PROJECT_VERSION)"; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; @@ -1216,17 +1218,17 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 3.3.18; + MARKETING_VERSION = "$(IOS_MARKETING_VERSION)"; ONLY_ACTIVE_ARCH = NO; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook; + PRODUCT_BUNDLE_IDENTIFIER = "$(IOS_MAIN_BUNDLE_ID)"; PRODUCT_NAME = Notesnook; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Notesnook 2026"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "$(IOS_MAIN_PROFILE)"; SWIFT_OBJC_BRIDGING_HEADER = "Notesnook-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1373,7 +1375,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2178; + CURRENT_PROJECT_VERSION = "$(IOS_CURRENT_PROJECT_VERSION)"; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 53CWBG3QUC; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; @@ -1385,10 +1387,10 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 3.3.18; + MARKETING_VERSION = "$(IOS_MARKETING_VERSION)"; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget; + PRODUCT_BUNDLE_IDENTIFIER = "$(IOS_WIDGET_BUNDLE_ID)"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; @@ -1416,7 +1418,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 2178; + CURRENT_PROJECT_VERSION = "$(IOS_CURRENT_PROJECT_VERSION)"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC; @@ -1429,12 +1431,12 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 3.3.18; + MARKETING_VERSION = "$(IOS_MARKETING_VERSION)"; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget; + PRODUCT_BUNDLE_IDENTIFIER = "$(IOS_WIDGET_BUNDLE_ID)"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Notesnook Note Widget 2026"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "$(IOS_WIDGET_PROFILE)"; SKIP_INSTALL = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; @@ -1459,7 +1461,7 @@ CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2178; + CURRENT_PROJECT_VERSION = "$(IOS_CURRENT_PROJECT_VERSION)"; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 53CWBG3QUC; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; @@ -1540,10 +1542,10 @@ "@executable_path/../../Frameworks", ); LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)"; - MARKETING_VERSION = 3.3.18; + MARKETING_VERSION = "$(IOS_MARKETING_VERSION)"; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share; + PRODUCT_BUNDLE_IDENTIFIER = "$(IOS_SHARE_BUNDLE_ID)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OBJC_BRIDGING_HEADER = "Make Note/Make Note-Bridging-Header.h"; @@ -1571,7 +1573,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 2178; + CURRENT_PROJECT_VERSION = "$(IOS_CURRENT_PROJECT_VERSION)"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC; @@ -1653,12 +1655,12 @@ "@executable_path/../../Frameworks", ); LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)"; - MARKETING_VERSION = 3.3.18; + MARKETING_VERSION = "$(IOS_MARKETING_VERSION)"; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share; + PRODUCT_BUNDLE_IDENTIFIER = "$(IOS_SHARE_BUNDLE_ID)"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Notesnook Share 2026"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "$(IOS_SHARE_PROFILE)"; SKIP_INSTALL = YES; SWIFT_OBJC_BRIDGING_HEADER = "Make Note/Make Note-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -1668,6 +1670,7 @@ }; 83CBBA201A601CBA00E9B192 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 684AA0A1B1BE6091A02D42FF /* ios-build.active.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; APPLICATION_EXTENSION_API_ONLY = YES; @@ -1740,6 +1743,7 @@ }; 83CBBA211A601CBA00E9B192 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 684AA0A1B1BE6091A02D42FF /* ios-build.active.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; APPLICATION_EXTENSION_API_ONLY = YES; diff --git a/apps/mobile/ios/Notesnook/Info.plist b/apps/mobile/ios/Notesnook/Info.plist index 8ec6fb96e..38ddf54cf 100644 --- a/apps/mobile/ios/Notesnook/Info.plist +++ b/apps/mobile/ios/Notesnook/Info.plist @@ -12,7 +12,7 @@ CFBundleDevelopmentRegion en CFBundleDisplayName - Notesnook + $(APP_DISPLAY_NAME) CFBundleDocumentTypes diff --git a/apps/mobile/ios/Podfile b/apps/mobile/ios/Podfile index 69e14fe1c..5e28ff61a 100644 --- a/apps/mobile/ios/Podfile +++ b/apps/mobile/ios/Podfile @@ -86,4 +86,20 @@ post_install do |installer| end end end + + # Embed the active iOS build config xcconfig as the project-level base configuration. + # CocoaPods only manages target-level base configurations, so the project-level one + # is safe to set here and will survive future pod installs. + # To switch environments: update ios-build.active.xcconfig, then re-run pod install. + # active_xcconfig_rel_path = 'build-configs/ios-build.active.xcconfig' + # user_project = installer.aggregate_targets.first.user_project + # xcconfig_ref = user_project.files.find { |f| f.path&.end_with?('ios-build.active.xcconfig') } + # if xcconfig_ref.nil? + # xcconfig_ref = user_project.main_group.new_file(active_xcconfig_rel_path, :project) + # xcconfig_ref.last_known_file_type = 'text.xcconfig' + # end + # user_project.build_configurations.each do |config| + # config.base_configuration_reference = xcconfig_ref + # end + # user_project.save end diff --git a/apps/mobile/ios/Podfile.lock b/apps/mobile/ios/Podfile.lock index 0fa6a3544..ad32c4ecf 100644 --- a/apps/mobile/ios/Podfile.lock +++ b/apps/mobile/ios/Podfile.lock @@ -2275,7 +2275,7 @@ PODS: - ReactCommon/turbomodule/core - SocketRocket - Yoga - - react-native-upload (6.31.0): + - react-native-upload (6.33.0): - React - react-native-view-shot (4.0.3): - boost @@ -2872,7 +2872,7 @@ PODS: - React-perflogger (= 0.82.1) - React-utils (= 0.82.1) - SocketRocket - - RNBackgroundFetch (4.2.2): + - RNBackgroundFetch (4.2.3): - React-Core - RNBootSplash (6.3.11): - boost @@ -3092,10 +3092,10 @@ PODS: - Yoga - RNKeychain (4.0.5): - React - - RNNotifee (7.4.11): + - RNNotifee (7.4.12): - React-Core - - RNNotifee/NotifeeCore (= 7.4.11) - - RNNotifee/NotifeeCore (7.4.11): + - RNNotifee/NotifeeCore (= 7.4.12) + - RNNotifee/NotifeeCore (7.4.12): - React-Core - RNPrivacySnapshot (1.0.0): - React-Core @@ -3875,19 +3875,19 @@ SPEC CHECKSUMS: boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 callstack-repack: 3991230773c74ea49e7db6932d20e72d175faa41 DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb - fast_float: b32c788ed9c6a8c584d114d0047beda9664e7cc6 + fast_float: 914e00b8b67cb8ba184a778c7bbc2e9fe98d37b3 FBLazyVector: 0aa6183b9afe3c31fc65b5d1eeef1f3c19b63bfa - fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd - glog: 5683914934d5b6e4240e497e0f4a3b42d1854183 + fmt: b85d977e8fe789fd71c77123f9f4920d88c4d170 + glog: 682871fb30f4a65f657bf357581110656ea90b08 GZIP: 3c0abf794bfce8c7cb34ea05a1837752416c8868 - hermes-engine: 273e30e7fb618279934b0b95ffab60ecedb7acf5 + hermes-engine: 1c85d2d2a4722541e6faffceb7bcc2249b5398b2 JWTDecode: 2eed97c2fa46ccaf3049a787004eedf0be474a87 MMKV: 7b5df6a8bf785c6705cc490c541b9d8a957c4a64 MMKVCore: 3f40b896e9ab522452df9df3ce983471aa2449ba NitroCloudUploader: 62489381ed6b472d87c8c6b62629136ebd2342d1 NitroModules: f964d2f3f5b392d0c0303737085cc30e375dc43f pop: d582054913807fd11fd50bfe6a539d91c7e1a55a - RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669 + RCT-Folly: fb64616e25cfac1c3d10bfd784d68926325ae67f RCTDeprecation: f17e2ebc07876ca9ab8eb6e4b0a4e4647497ae3a RCTRequired: e2c574c1b45231f7efb0834936bd609d75072b63 RCTTypeSafety: c693294e3993056955c3010eb1ebc574f1fcded6 @@ -3946,7 +3946,7 @@ SPEC CHECKSUMS: react-native-share-extension: fdc6aaab51591a2d445df239c446aaa3a99658ec react-native-sodium: 066f76e46c9be13e9260521e3fa994937c4cdab4 react-native-theme-switch-animation: 449d6db7a760f55740505e7403ae8061debc9a7e - react-native-upload: 6285965d20879bcfcf7953f05eb785ba03a60e40 + react-native-upload: 7b7ad336c3db703b68a8c07cf38e9319ae90d695 react-native-view-shot: 6c008e58f4720de58370848201c5d4a082c6d4ca react-native-webview: 654f794a7686b47491cf43aa67f7f428bea00eed React-NativeModulesApple: 46690a0fe94ec28fc6fc686ec797b911d251ded0 @@ -3981,7 +3981,7 @@ SPEC CHECKSUMS: ReactAppDependencyProvider: a45ef34bb22dc1c9b2ac1f74167d9a28af961176 ReactCodegen: 878add6c7d8ff8cea87697c44d29c03b79b6f2d9 ReactCommon: 804dc80944fa90b86800b43c871742ec005ca424 - RNBackgroundFetch: 0c49d5892a0e2f9c139e24ba498985cf0bf070c6 + RNBackgroundFetch: 7b9281af0b21100c3c5ef07d1df9ab1adf2dc686 RNBootSplash: 98a34471966945e8dacd1da8f0c2f87cbc2e2df7 RNCCheckbox: 33b44487ca8008394ce658cc32b26eab04f426ef RNCClipboard: 4b58c780f63676367640f23c8e114e9bd0cf86ac @@ -3994,7 +3994,7 @@ SPEC CHECKSUMS: RNIap: 61f183ac917792fae42b0326b1bef33598c1adf6 RNImageCropPicker: 5fd4ceaead64d8c53c787e4e559004f97bc76df7 RNKeychain: ffd0513e676445c637410b47249460cbf56bc9cb - RNNotifee: c4827fa2cec60ab634d62bafdb5cf57cd2999d54 + RNNotifee: dea82c9ec44684eeeac9da85deb5eeb8ebe5937f RNPrivacySnapshot: ccad3a548338c2f526bb7b1789af3fb0618b7d1d RNReanimated: f1868b36f4b2b52a0ed00062cfda69506f75eaee RNScreens: ffbb0296608eb3560de641a711bbdb663ed1f6b4 @@ -4005,7 +4005,7 @@ SPEC CHECKSUMS: RNWorklets: d9c050940f140af5d8b611d937eab1cbfce5e9a5 RNZipArchive: 71befbdc20e7fbd4b64552a0b324ad0e8d0efefb SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d - SexyTooltip: 5c9b4dec52bfb317938cb0488efd9da3717bb6fd + SexyTooltip: 605cfd16ae28fd8c3afac9c29236518e156dbbd8 SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef SwiftyRSA: 8c6dd1ea7db1b8dc4fb517a202f88bb1354bc2c6 @@ -4013,6 +4013,6 @@ SPEC CHECKSUMS: toolbar-android: c426ed5bd3dcccfed20fd79533efc0d1ae0ef018 Yoga: 689c8e04277f3ad631e60fe2a08e41d411daf8eb -PODFILE CHECKSUM: 3021ad3db20df40d4106c9be82d0100d9d447239 +PODFILE CHECKSUM: 3fe13efa8356dcc061862bfa9f453dcd12ede70a COCOAPODS: 1.16.2 diff --git a/apps/mobile/ios/build-configs/README.md b/apps/mobile/ios/build-configs/README.md new file mode 100644 index 000000000..fa074bd8b --- /dev/null +++ b/apps/mobile/ios/build-configs/README.md @@ -0,0 +1,41 @@ +# iOS Build Config Switching + +This folder controls iOS bundle identifiers and app display name per environment. + +## Files + +- `ios-build.production.xcconfig`: production identifiers and name +- `ios-build.staging.xcconfig`: staging identifiers and name +- `ios-build.active.xcconfig`: active config consumed during build +- `use-ios-build-config.sh`: helper to switch active config + +## Switch Active Config + +From `apps/mobile`: + +```bash +bash ios/build-configs/use-ios-build-config.sh production +bash ios/build-configs/use-ios-build-config.sh staging +``` + +## Build With Active Config + +Use `xcodebuild` with the active file: + +```bash +xcodebuild \ + -workspace ios/Notesnook.xcworkspace \ + -scheme Notesnook \ + -configuration Release \ + -xcconfig ios/build-configs/ios-build.active.xcconfig +``` + +You can also use a specific config file directly: + +```bash +xcodebuild \ + -workspace ios/Notesnook.xcworkspace \ + -scheme Notesnook \ + -configuration Release \ + -xcconfig ios/build-configs/ios-build.staging.xcconfig +``` diff --git a/apps/mobile/ios/build-configs/ios-build.active.xcconfig b/apps/mobile/ios/build-configs/ios-build.active.xcconfig new file mode 100644 index 000000000..7fa30b5bb --- /dev/null +++ b/apps/mobile/ios/build-configs/ios-build.active.xcconfig @@ -0,0 +1,10 @@ +// Staging iOS build identifiers +IOS_CURRENT_PROJECT_VERSION = 2178 +IOS_MARKETING_VERSION = 3.3.18 +IOS_MAIN_BUNDLE_ID = org.streetwriters.notesnook +IOS_WIDGET_BUNDLE_ID = org.streetwriters.notesnook.notewidget +IOS_SHARE_BUNDLE_ID = org.streetwriters.notesnook.share +APP_DISPLAY_NAME = Notesnook +IOS_MAIN_PROFILE = Notesnook Adhoc 2026 +IOS_WIDGET_PROFILE = Notesnook Note Widget Adhoc 2026 +IOS_SHARE_PROFILE = Notesnook Share Adhoc 2026 diff --git a/apps/mobile/ios/build-configs/ios-build.production.xcconfig b/apps/mobile/ios/build-configs/ios-build.production.xcconfig new file mode 100644 index 000000000..9c57d3bde --- /dev/null +++ b/apps/mobile/ios/build-configs/ios-build.production.xcconfig @@ -0,0 +1,10 @@ +// Production iOS build identifiers +IOS_CURRENT_PROJECT_VERSION = 2178 +IOS_MARKETING_VERSION = 3.3.18 +IOS_MAIN_BUNDLE_ID = org.streetwriters.notesnook +IOS_WIDGET_BUNDLE_ID = org.streetwriters.notesnook.notewidget +IOS_SHARE_BUNDLE_ID = org.streetwriters.notesnook.share +APP_DISPLAY_NAME = Notesnook +IOS_MAIN_PROFILE = Notesnook 2026 +IOS_WIDGET_PROFILE = Notesnook Note Widget 2026 +IOS_SHARE_PROFILE = Notesnook Share 2026 diff --git a/apps/mobile/ios/build-configs/ios-build.staging.xcconfig b/apps/mobile/ios/build-configs/ios-build.staging.xcconfig new file mode 100644 index 000000000..7fa30b5bb --- /dev/null +++ b/apps/mobile/ios/build-configs/ios-build.staging.xcconfig @@ -0,0 +1,10 @@ +// Staging iOS build identifiers +IOS_CURRENT_PROJECT_VERSION = 2178 +IOS_MARKETING_VERSION = 3.3.18 +IOS_MAIN_BUNDLE_ID = org.streetwriters.notesnook +IOS_WIDGET_BUNDLE_ID = org.streetwriters.notesnook.notewidget +IOS_SHARE_BUNDLE_ID = org.streetwriters.notesnook.share +APP_DISPLAY_NAME = Notesnook +IOS_MAIN_PROFILE = Notesnook Adhoc 2026 +IOS_WIDGET_PROFILE = Notesnook Note Widget Adhoc 2026 +IOS_SHARE_PROFILE = Notesnook Share Adhoc 2026 diff --git a/apps/mobile/ios/build-configs/use-ios-build-config.sh b/apps/mobile/ios/build-configs/use-ios-build-config.sh new file mode 100755 index 000000000..feeed7701 --- /dev/null +++ b/apps/mobile/ios/build-configs/use-ios-build-config.sh @@ -0,0 +1,99 @@ +#!/usr/bin/env bash +set -euo pipefail + +usage() { + cat < [--marketing-version ] [--build-number ] + +Examples: + $0 production + $0 staging --marketing-version 3.3.19 --build-number 2179 +EOF +} + +if [[ $# -lt 1 ]]; then + usage + exit 1 +fi + +ENV_NAME="$1" +shift + +MARKETING_VERSION="" +BUILD_NUMBER="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --marketing-version) + if [[ $# -lt 2 ]]; then + echo "Missing value for --marketing-version" + exit 1 + fi + MARKETING_VERSION="$2" + shift 2 + ;; + --build-number) + if [[ $# -lt 2 ]]; then + echo "Missing value for --build-number" + exit 1 + fi + BUILD_NUMBER="$2" + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" + usage + exit 1 + ;; + esac +done + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +ACTIVE_FILE="$SCRIPT_DIR/ios-build.active.xcconfig" +SOURCE_FILE="$SCRIPT_DIR/ios-build.${ENV_NAME}.xcconfig" + +if [[ ! -f "$SOURCE_FILE" ]]; then + echo "Unknown config '$ENV_NAME'. Expected 'production' or 'staging'." + exit 1 +fi + +set_or_append_key() { + local file="$1" + local key="$2" + local value="$3" + local escaped_value="${value//&/\\&}" + + if grep -Eq "^[[:space:]]*${key}[[:space:]]*=" "$file"; then + sed -E -i.bak "s|^[[:space:]]*${key}[[:space:]]*=.*$|${key} = ${escaped_value}|g" "$file" + rm -f "$file.bak" + else + printf "\n%s = %s\n" "$key" "$value" >> "$file" + fi +} + +if [[ -n "$MARKETING_VERSION" || -n "$BUILD_NUMBER" ]]; then + for xcconfig in "$SCRIPT_DIR"/*.xcconfig; do + if [[ -n "$MARKETING_VERSION" ]]; then + set_or_append_key "$xcconfig" "IOS_MARKETING_VERSION" "$MARKETING_VERSION" + fi + + if [[ -n "$BUILD_NUMBER" ]]; then + set_or_append_key "$xcconfig" "IOS_CURRENT_PROJECT_VERSION" "$BUILD_NUMBER" + fi + done +fi + +cp "$SOURCE_FILE" "$ACTIVE_FILE" +echo "Active iOS build config set to: $ENV_NAME" + +if [[ -n "$MARKETING_VERSION" ]]; then + echo "Updated marketing version in all xcconfigs: $MARKETING_VERSION" +fi + +if [[ -n "$BUILD_NUMBER" ]]; then + echo "Updated build number in all xcconfigs: $BUILD_NUMBER" +fi