Skip to content

Commit a18f810

Browse files
authored
feat(infra): Add support for modifying SPM Firebase dep in xcodeprojs (#15279)
1 parent be9d960 commit a18f810

File tree

4 files changed

+125
-62
lines changed

4 files changed

+125
-62
lines changed

.github/workflows/firebaseai.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88
- '.github/workflows/common.yml'
99
- '.github/workflows/common_cocoapods.yml'
1010
- 'scripts/quickstart_build_spm.sh'
11-
- 'scripts/quickstart_spm_xcodeproj.sh'
11+
- 'scripts/update_firebase_spm_dependency.sh'
1212
- 'Gemfile*'
1313
# Do not run for documentation-only PRs.
1414
- '!**.md'

scripts/quickstart_build_spm.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
set -xeuo pipefail
2222

2323
SAMPLE=$1
24+
SAMPLE_DIR=$(echo "$SAMPLE" | perl -ne 'print lc')
25+
SAMPLE_XCODEPROJ=${SAMPLE_DIR}/${SAMPLE}Example.xcodeproj
2426

2527
scripts_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
2628

@@ -32,7 +34,7 @@ git clone https://github.com/firebase/quickstart-ios.git
3234

3335
cd quickstart-ios
3436

35-
source "$scripts_dir/quickstart_spm_xcodeproj.sh" "$SAMPLE"
37+
source "$scripts_dir/update_firebase_spm_dependency.sh" "$SAMPLE_XCODEPROJ" --branch "$BRANCH_NAME"
3638

3739
# Placeholder GoogleService-Info.plist good enough for build only testing.
3840
cp ./mock-GoogleService-Info.plist ./firebaseai/GoogleService-Info.plist

scripts/quickstart_spm_xcodeproj.sh

Lines changed: 0 additions & 60 deletions
This file was deleted.
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#!/usr/bin/env bash
2+
3+
# Copyright 2025 Google LLC
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
# Modify a .xcodeproj to use a specific branch, version, or commit for the
18+
# firebase-ios-sdk SPM dependency.
19+
20+
set -euo pipefail
21+
22+
# Enable trace mode if DEBUG is set to 'true'
23+
if [[ "${DEBUG:-false}" == "true" ]]; then
24+
set -x
25+
fi
26+
27+
# --- Argument parsing ---
28+
if [[ $# -lt 2 ]]; then
29+
echo "Modify a .xcodeproj to use a specific branch, version, or commit for the"
30+
echo "firebase-ios-sdk SPM dependency."
31+
echo ""
32+
echo "Usage: $0 <path_to.xcodeproj> [--version <version> | --revision <revision> | --prerelease | --branch <branch>]"
33+
exit 1
34+
fi
35+
36+
XCODEPROJ_PATH="$1"
37+
shift
38+
MODE="$1"
39+
shift
40+
41+
PBXPROJ_PATH="${XCODEPROJ_PATH}/project.pbxproj"
42+
43+
# Regex matches SemVer `firebase-ios-sdk` dependency in project.pbxproj:
44+
# {
45+
# isa = XCRemoteSwiftPackageReference;
46+
# repositoryURL = "https://github.com/firebase/firebase-ios-sdk.git";
47+
# requirement = {
48+
# kind = upToNextMajorVersion;
49+
# minimumVersion = xx.yy.zz;
50+
# };
51+
# };
52+
REQUIREMENT_REGEX='({'\
53+
'\s*isa = XCRemoteSwiftPackageReference;'\
54+
'\s*repositoryURL = "https://github\.com/firebase/firebase-ios-sdk(?:\.git)?";'\
55+
'\s*requirement = {\s*)kind = upToNextMajorVersion;'\
56+
'\s*minimumVersion = \d+\.\d+\.\d+;'\
57+
'(\s*};'\
58+
'\s*};)'
59+
60+
# Define the replacement regex based on the selected mode.
61+
case "$MODE" in
62+
--version)
63+
if [[ $# -lt 1 ]]; then echo "Error: Missing version for --version"; exit 1; fi
64+
VERSION="$1"
65+
REPLACEMENT_REGEX="\1kind = branch;\n\t\t\t\tbranch = \"$VERSION\";\2"
66+
;;
67+
--prerelease)
68+
COMMIT_HASH=$(git ls-remote https://github.com/firebase/firebase-ios-sdk.git main | cut -f1)
69+
if [[ -z "$COMMIT_HASH" ]]; then
70+
echo "Error: Failed to get remote revision for main branch."
71+
exit 1
72+
fi
73+
REPLACEMENT_REGEX="\1kind = revision;\n\t\t\t\trevision = \"$COMMIT_HASH\";\2"
74+
;;
75+
--revision)
76+
if [[ $# -lt 1 ]]; then echo "Error: Missing revision for --revision"; exit 1; fi
77+
REVISION="$1"
78+
REPLACEMENT_REGEX="\1kind = revision;\n\t\t\t\trevision = \"$REVISION\";\2"
79+
;;
80+
--branch)
81+
if [[ $# -lt 1 ]]; then echo "Error: Missing branch name for --branch"; exit 1; fi
82+
BRANCH_NAME="$1"
83+
REPLACEMENT_REGEX="\1kind = branch;\n\t\t\t\tbranch = \"$BRANCH_NAME\";\2"
84+
;;
85+
*)
86+
echo "Invalid mode: $MODE"
87+
exit 1
88+
;;
89+
esac
90+
91+
# Make a temporary backup of the original file.
92+
# This will be used to check if any changes were made.
93+
TEMP_FILE=$(mktemp)
94+
cp "$PBXPROJ_PATH" "$TEMP_FILE"
95+
96+
# Performs the replacement using Perl.
97+
#
98+
# -0777 Enables reading all input in one go (slurp), rather than line-by-line.
99+
# -p Causes Perl to loop through the input line by line.
100+
# -i Edits the file in place.
101+
# -e Provides the expression to execute.
102+
perl -0777 -i -pe "s#$REQUIREMENT_REGEX#$REPLACEMENT_REGEX#g" "$PBXPROJ_PATH" || {
103+
echo "Failed to update the Xcode project's SPM dependency."
104+
exit 1
105+
}
106+
107+
# Silently compare the modified file with the temporary backup.
108+
# If they are the same, cmp will return 0 (success), and the 'if' block will run.
109+
if cmp -s "$PBXPROJ_PATH" "$TEMP_FILE"; then
110+
echo "Failed to find and replace the firebase-ios-sdk dependency. Check the regex pattern and project file structure."
111+
# Restore the original file from the backup
112+
mv "$TEMP_FILE" "$PBXPROJ_PATH"
113+
exit 1
114+
fi
115+
116+
echo "Successfully updated SPM dependency in $PBXPROJ_PATH"
117+
118+
# Point SPM CI to the tip of `main` of
119+
# https://github.com/google/GoogleAppMeasurement so that the release process
120+
# can defer publishing the `GoogleAppMeasurement` tag until after testing.
121+
export FIREBASECI_USE_LATEST_GOOGLEAPPMEASUREMENT=1

0 commit comments

Comments
 (0)