Update Android and iOS dependencies #239
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Update Android and iOS dependencies | |
on: | |
workflow_dispatch: | |
inputs: | |
updateAndroid: | |
description: 'update Android dependencies?' | |
default: 1 | |
updateiOS: | |
description: 'update iOS dependencies?' | |
default: 1 | |
includeGMA: | |
description: 'include GMA?' | |
default: 0 | |
triggerTests: | |
description: 'trigger tests on PR?' | |
default: 1 | |
baseBranch: | |
description: 'create the new branch from this base' | |
default: 'main' | |
comment: | |
description: 'optional comment to add to PR' | |
default: '' | |
env: | |
branchPrefix: "workflow/auto-update-deps-" | |
triggerTestsLabel: "tests-requested: quick" | |
jobs: | |
update_dependencies: | |
name: update-deps | |
runs-on: macos-13 | |
steps: | |
- name: Get token for firebase-workflow-trigger | |
uses: tibdex/github-app-token@v1 | |
id: generate-token | |
with: | |
app_id: ${{ secrets.WORKFLOW_TRIGGER_APP_ID }} | |
private_key: ${{ secrets.WORKFLOW_TRIGGER_APP_PRIVATE_KEY }} | |
- name: Setup python | |
uses: actions/setup-python@v4 | |
with: | |
python-version: 3.8 | |
- name: Check out base branch | |
uses: actions/checkout@v3 | |
with: | |
fetch-depth: 0 | |
ref: ${{ github.event.inputs.baseBranch }} | |
- name: Install prerequisites | |
run: | | |
python scripts/gha/install_prereqs_desktop.py | |
python -m pip install requests | |
- name: Name new branch | |
run: | | |
date_str=$(date "+%Y%m%d-%H%M%S") | |
echo "NEW_BRANCH=${{env.branchPrefix}}${{github.run_number}}-${date_str}" >> $GITHUB_ENV | |
- name: Create new branch | |
run: | | |
git remote update | |
git checkout -b "${NEW_BRANCH}" | |
echo "UPDATE_LOGFILE=update_log.txt" >> $GITHUB_ENV | |
- name: Run update script | |
run: | | |
gma_flag= | |
if [[ ${{ github.event.inputs.includeGMA }} -eq 1 ]]; then | |
gma_flag="--include_gma" | |
fi | |
if [[ ${{ github.event.inputs.updateiOS }} -eq 1 ]]; then | |
if [[ ${{ github.event.inputs.updateAndroid }} -eq 1 ]]; then | |
# Update both | |
echo "Updating all dependencies" | |
python scripts/update_android_ios_dependencies.py --logfile=${UPDATE_LOGFILE} ${gma_flag} | |
echo "CHOSEN_DEPS=mobile" >> $GITHUB_ENV | |
else | |
# Update iOS only | |
echo "Updating iOS dependencies only" | |
python scripts/update_android_ios_dependencies.py --skip_android --logfile=${UPDATE_LOGFILE} ${gma_flag} | |
echo "CHOSEN_DEPS=iOS" >> $GITHUB_ENV | |
fi | |
# iOS: Update Firestore external version to match Firestore Cocoapod version. | |
firestore_version=$(grep "pod 'Firebase/Firestore'" ios_pod/Podfile | sed "s/.*'\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)'.*/\1/") | |
echo "Setting Firestore external version to ${firestore_version}" | |
sed -i~ "s/^set(version [^)]*)/set(version CocoaPods-${firestore_version})/i" cmake/external/firestore.cmake | |
# iOS: Update Analytics header files, used for generating constants. | |
analytics_version=$(grep "pod 'Firebase/Analytics'" ios_pod/Podfile | sed "s/.*'\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)'.*/\1/") | |
if [[ "$(uname)" == "Darwin"* ]]; then | |
echo "Updating Analytics iOS headers from version ${analytics_version}" | |
# Unfortunately we can't just download these headers from GitHub, as | |
# Analytics is closed-source. If it becomes open-source, we could just | |
# download the header files from the iOS SDK's release branch. So instead, | |
# download the Firebase Analytics cocoapod (via a stub project) and get the | |
# header from there. This will only work on macOS. | |
podtmp="$(mktemp -d)" | |
cd "${podtmp}" | |
# Generate a Podfile for Firebase/Analytics. Use the Specs.git | |
# source to avoid any propagation delays due to CocoaPods mirror. | |
echo "source 'https://github.com/CocoaPods/Specs.git'" > Podfile | |
echo "platform :ios, '14.0'" >> Podfile | |
echo "pod 'Firebase/Analytics', '${analytics_version}'" >> Podfile | |
pod repo update | |
pod install || true # ignore error since there is no Xcode project | |
declare -a header_dirs | |
# Get all of the framework header directories from the xcframework. | |
header_dirs=(Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.xcframework/*/FirebaseAnalytics.framework/Headers) | |
# Just use the first directory found, the headers should be the same across | |
# all of the frameworks. | |
header_dir="${header_dirs[0]}" | |
cd - | |
cd analytics/ios_headers | |
for ios_header in *.h; do | |
# Each file in this directory matches a file in the Analytics iOS SDK. | |
cp -vf "${podtmp}/${header_dir}/${ios_header}" . | |
# If the file doesn't have a Google copyright, add one. | |
if ! grep -q "^// Copyright [0-9]* Google LLC" "${ios_header}"; then | |
copyright_line="// Copyright $(date +%Y) Google LLC\n" | |
else | |
copyright_line= | |
fi | |
# Add a note to each file about its source. | |
sed -i~ "s|^/// @file|${copyright_line}\n// Copied from Firebase Analytics iOS SDK ${analytics_version}.\n\n/// @file|" "${ios_header}" | |
rm -f "${ios_header}~" # remove backup file that sed generated | |
python ../../scripts/format_code.py --f "${ios_header}" | |
done | |
cd - | |
rm -rf "${podtmp}" | |
fi | |
# Download the zip distribution and get the Swift header files. | |
core_version=$(grep "pod 'Firebase/Core'" ios_pod/Podfile | sed "s/.*'\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)'.*/\1/") | |
echo "Getting Swift header files from Firebase iOS SDK ${core_version} zip distribution" | |
ziptmp="$(mktemp -d)" | |
# The version might be named vX.Y.Z or simply X.Y.Z, check which exists. | |
declare -a zip_urls | |
zip_urls=("https://github.com/firebase/firebase-ios-sdk/releases/download/v${core_version}/Firebase.zip" "https://github.com/firebase/firebase-ios-sdk/releases/download/${core_version}/Firebase.zip") | |
for try_url in ${zip_urls[@]} error; do | |
curl -H 'Authorization: token ${{ github.token }}' -L -f "${try_url}" -o "${ziptmp}/Firebase.zip" 2> /dev/null && break | |
done | |
if [[ "${try_url}" == "error" ]]; then | |
echo "::error ::Could not download Firebase iOS prebuilt zip file, skipping Swift headers." | |
else | |
cd "${ziptmp}" | |
echo "Unzipping..." | |
unzip -q Firebase.zip '*-Swift.h' | |
cd - | |
# Copy all *-Swift.h header files into ios_pod/swift_headers/ | |
echo "Copying headers..." | |
find "${ziptmp}" -name '*-Swift.h' -path '*ios*arm64*x86_64*simulator*' -print0 | xargs -0 -n 1 -J REPLACETEXT cp -f REPLACETEXT ios_pod/swift_headers/ | |
copyright_line="// Copyright $(date +%Y) Google LLC" | |
# Add a note to each file about its source. | |
for ios_header in ios_pod/swift_headers/*.h; do | |
if ! grep -q "^// Copied from Firebase iOS SDK" "${ios_header}"; then | |
sed -i~ "s|^// Generated by Apple Swift|${copyright_line}\n// Copied from Firebase iOS SDK ${core_version}.\n\n// Generated by Apple Swift|" "${ios_header}" | |
fi | |
python3 scripts/format_code.py --f "${ios_header}" | |
done | |
fi | |
rm -rf ${ziptmp} | |
elif [[ ${{ github.event.inputs.updateAndroid }} -eq 1 ]]; then | |
# Update Android only | |
echo "Updating Android dependencies only" | |
python scripts/update_android_ios_dependencies.py --skip_ios --logfile=${UPDATE_LOGFILE} ${gma_flag} | |
echo "CHOSEN_DEPS=Android" >> $GITHUB_ENV | |
else | |
echo "::error ::Neither Android nor iOS selected. Exiting." | |
exit 1 | |
fi | |
touch ${UPDATE_LOGFILE} # In case it wasn't generated before | |
cat ${UPDATE_LOGFILE} | |
- name: Push branch if there are changes | |
id: push-branch | |
run: | | |
if ! git update-index --refresh; then | |
# Do a bit of post-processing on the update log to split it by platform. | |
UPDATE_LOGFILE_PROCESSED=update_log_processed.txt | |
touch "${UPDATE_LOGFILE_PROCESSED}" | |
if grep -q ^Android: "${UPDATE_LOGFILE}"; then | |
echo "### Android" >> "${UPDATE_LOGFILE_PROCESSED}" | |
echo "" >> "${UPDATE_LOGFILE_PROCESSED}" | |
grep ^Android: "${UPDATE_LOGFILE}" | sed 's/^Android: /- /' >> ${UPDATE_LOGFILE_PROCESSED} | |
echo "" >> "${UPDATE_LOGFILE_PROCESSED}" | |
fi | |
if grep -q ^iOS: "${UPDATE_LOGFILE}"; then | |
echo "### iOS" >> "${UPDATE_LOGFILE_PROCESSED}" | |
echo "" >> "${UPDATE_LOGFILE_PROCESSED}" | |
grep ^iOS: "${UPDATE_LOGFILE}" | sed 's/^iOS: /- /' >> ${UPDATE_LOGFILE_PROCESSED} | |
echo "" >> "${UPDATE_LOGFILE_PROCESSED}" | |
fi | |
date_str=$(date "+%a %b %d %Y") | |
commit_title="Update ${CHOSEN_DEPS} dependencies - ${date_str}" | |
commit_body= | |
if [[ -n '${{ github.event.inputs.comment }}' ]]; then | |
# If a comment was provided, start with that instead of blank. | |
commit_body='${{ github.event.inputs.comment }} | |
' | |
fi | |
commit_body="${commit_body}$(cat ${UPDATE_LOGFILE_PROCESSED}) | |
> Created by [${{github.workflow}} workflow]($GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID)." | |
git config user.email "firebase-workflow-trigger-bot@google.com" | |
git config user.name "firebase-workflow-trigger-bot" | |
git config core.commentChar "%" # so we can use # in git commit messages | |
git commit -a -m "${commit_title} | |
${commit_body}" | |
echo "branch_pushed=1" >> $GITHUB_OUTPUT | |
# Show changes in git log | |
git diff | |
# Push branch | |
git push --set-upstream origin "${NEW_BRANCH}" | |
# Create pull request | |
pr_number=$(python scripts/gha/create_pull_request.py --token ${{ steps.generate-token.outputs.token }} --head "${NEW_BRANCH}" --base "${{ github.event.inputs.baseBranch }}" --title "${commit_title}" --body "${commit_body}") | |
echo "created_pr_number=${pr_number}" >> $GITHUB_OUTPUT | |
else | |
echo "::warning ::No changes detected, won't create pull request." | |
echo "branch_pushed=0" >> $GITHUB_OUTPUT | |
fi | |
- name: Set test trigger label. | |
uses: actions-ecosystem/action-add-labels@v1 | |
if: ${{ github.event.inputs.triggerTests == 1 && steps.push-branch.outputs.branch_pushed == 1 }} | |
with: | |
github_token: ${{ steps.generate-token.outputs.token }} | |
number: ${{ steps.push-branch.outputs.created_pr_number }} | |
labels: "${{ env.triggerTestsLabel }}" |