Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions .github/actions/dataconnect-send-notifications/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,19 @@ runs:
calculate_github_issue_for_commenting.py
--issue-output-file=github_issue_number.txt
--github-repository='${{ github.repository }}'
--github-ref='${{ github.ref }}'
--github-ref='${GITHUB_REF}'
--github-event-name='${{ github.event_name }}'
--pr-body-github-issue-key=trksmnkncd_notification_issue
--github-issue-for-scheduled-run='${{ inputs.github-issue-for-scheduled-runs }}'
--github-issue-for-scheduled-run='${INPUTS_GITHUB_ISSUE_FOR_SCHEDULED_RUNS}'
)
echo "${args[*]}"
"${args[@]}"
set -xv
issue="$(cat github_issue_number.txt)"
echo "issue=$issue" >> "$GITHUB_OUTPUT"
env:
INPUTS_GITHUB_ISSUE_FOR_SCHEDULED_RUNS: ${{ inputs.github-issue-for-scheduled-runs }}

- name: Post Comment on GitHub Issue
if: steps.issue-id.outputs.issue != ''
Expand All @@ -51,21 +53,25 @@ runs:
args=(
python
post_comment_for_job_results.py
--github-issue='${{ steps.issue-id.outputs.issue }}'
--github-workflow='${{ github.workflow }}'
--github-issue='${STEPS_ISSUE_ID_OUTPUTS_ISSUE}'
--github-workflow='${GITHUB_WORKFLOW}'
--github-repository='${{ github.repository }}'
--github-ref='${{ github.ref }}'
--github-ref='${GITHUB_REF}'
--github-event-name='${{ github.event_name }}'
--github-sha='${{ github.sha }}'
--github-repository-html-url='${{ github.event.repository.html_url }}'
--github-repository-html-url='${GITHUB_EVENT_REPOSITORY_HTML_URL}'
--github-run-id='${{ github.run_id }}'
--github-run-number='${{ github.run_number }}'
--github-run-attempt='${{ github.run_attempt }}'
)
while read -r line; do
args=("${args[@]}" "$line")
done <'${{ inputs.job-results-file }}'
done <'${INPUTS_JOB_RESULTS_FILE}'
echo "${args[*]}"
exec "${args[@]}"
env:
STEPS_ISSUE_ID_OUTPUTS_ISSUE: ${{ steps.issue-id.outputs.issue }}
GITHUB_EVENT_REPOSITORY_HTML_URL: ${{ github.event.repository.html_url }}
INPUTS_JOB_RESULTS_FILE: ${{ inputs.job-results-file }}
27 changes: 27 additions & 0 deletions .github/workflows/app-distribution-gradle-compatibility-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: App Distribution Gradle Compatibility Tests

on:
schedule:
- cron: '0 6 * * *' # Run daily at 6 AM
workflow_dispatch: # Allow manual triggering

permissions:
contents: read

jobs:
app-distribution-plugin:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up JDK 17
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0
with:
java-version: 17
distribution: temurin
cache: gradle
- name: Run tests
id: tests
run: |
./gradlew \
:firebase-appdistribution-gradle:integrationTest"
10 changes: 7 additions & 3 deletions .github/workflows/ci_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,16 @@ jobs:
- name: ${{ matrix.module }} Unit Tests
env:
FIREBASE_CI: 1
MATRIX_MODULE: ${{matrix.module}}
run: |
./gradlew ${{matrix.module}}:check withErrorProne
./gradlew ${MATRIX_MODULE}:check withErrorProne
- name: Compute upload file name
if: always()
run: |
MODULE=${{matrix.module}}
MODULE=${MATRIX_MODULE}
echo "ARTIFACT_NAME=${MODULE//:/_}" >> $GITHUB_ENV
env:
MATRIX_MODULE: ${{matrix.module}}
- name: Upload Test Results
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
if: always()
Expand Down Expand Up @@ -143,8 +146,9 @@ jobs:
FTL_RESULTS_BUCKET: android-ci
FTL_RESULTS_DIR: ${{ github.event_name == 'pull_request' && format('pr-logs/pull/{0}/{1}/{2}/{3}_{4}/artifacts/', github.repository, github.event.pull_request.number, github.job, github.run_id, github.run_attempt) || format('logs/{0}/{1}_{2}/artifacts/', github.workflow, github.run_id, github.run_attempt)}}
FIREBASE_APP_CHECK_DEBUG_SECRET: ${{ secrets.FIREBASE_APP_CHECK_DEBUG_SECRET }}
MATRIX_MODULE: ${{matrix.module}}
run: |
./gradlew ${{matrix.module}}:deviceCheck withErrorProne -PtargetBackend="prod"
./gradlew ${MATRIX_MODULE}:deviceCheck withErrorProne -PtargetBackend="prod"
publish-test-results:
name: "Publish Tests Results"
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/create_releases.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ jobs:
cache: gradle
- name: Create release configuration template
run: |
./gradlew generateReleaseConfig -PcurrentRelease=${{ inputs.name }} -PpastRelease=${{ inputs.past-name }} -PprintOutput=true
./gradlew generateReleaseConfig -PcurrentRelease=${INPUTS_NAME} -PpastRelease=${INPUTS_PAST_NAME} -PprintOutput=true
env:
INPUTS_NAME: ${{ inputs.name }}
INPUTS_PAST_NAME: ${{ inputs.past-name }}

- name: Create Pull Request
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/release-note-changes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ jobs:
id: generate-comment
if: ${{ steps.install-fireci.outcome == 'success' }}
run: |
fireci changelog_comment -c "${{ steps.changed-files.outputs.all_changed_files }}" -o ./changelog_comment.md
fireci changelog_comment -c "${STEPS_CHANGED_FILES_OUTPUTS_ALL_CHANGED_FILES}" -o ./changelog_comment.md
env:
STEPS_CHANGED_FILES_OUTPUTS_ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}

- name: Add PR Comment
uses: mshick/add-pr-comment@b8f338c590a895d50bcbfa6c5859251edc8952fc # v2.8.2
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/update-cpp-sdk-on-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,6 @@ jobs:
- name: Trigger firebase-cpp-sdk update
run: |
pip install -r scripts/gha/python_requirements.txt
python scripts/gha/trigger_workflow.py -t ${{ steps.generate-token.outputs.token }} -w update-dependencies.yml -p updateAndroid 1 -p updateiOS 0 -p comment "[Triggered]($GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID) by [firebase-android-sdk $(date '+%b %d') release]($GITHUB_SERVER_URL/$GITHUB_REPOSITORY/commit/${{ github.sha }})." -s 10 -A
python scripts/gha/trigger_workflow.py -t ${STEPS_GENERATE_TOKEN_OUTPUTS_TOKEN} -w update-dependencies.yml -p updateAndroid 1 -p updateiOS 0 -p comment "[Triggered]($GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID) by [firebase-android-sdk $(date '+%b %d') release]($GITHUB_SERVER_URL/$GITHUB_REPOSITORY/commit/${{ github.sha }})." -s 10 -A
env:
STEPS_GENERATE_TOKEN_OUTPUTS_TOKEN: ${{ steps.generate-token.outputs.token }}
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ task integrationTest(type: Test) {
classpath = sourceSets.integrationTest.runtimeClasspath

shouldRunAfter(test)

testLogging {
showStandardStreams = true
}
}

check.dependsOn(integrationTest)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -723,9 +723,9 @@ class UploadDistributionTaskTest {
// out.
// Also remember to update the latest AGP/gradle versions in BeePlusGradleProject.java.
// firebase-appdistribution-gradle/src/prodTest/java/com/google/firebase/appdistribution/gradle/BeePlusGradleProject.java#L59-L60
private const val LATEST_GRADLE_VERSION = "9.3.1"
private const val LATEST_AGP_VERSION = "9.1.0-alpha07"
private const val LATEST_GOOGLE_SERVICES_VERSION = "4.4.4"
private val LATEST_GRADLE_VERSION = VersionUtils.fetchLatestGradleVersion()
private val LATEST_AGP_VERSION = VersionUtils.fetchLatestAgpVersion()
private val LATEST_GOOGLE_SERVICES_VERSION = VersionUtils.fetchLatestGoogleServicesVersion()
// For tests against Gradle 9, we get the error:
// "In order to compile Java 9+ source, please set compileSdkVersion to 30 or above"
// when we don't set this to at least 30.
Expand All @@ -739,5 +739,15 @@ class UploadDistributionTaskTest {

// google-services Gradle plugin 4.3.2 was released in September 2019.
private const val OLDER_GOOGLE_SERVICES_VERSION = "4.3.2"

private val LOGGER = java.util.logging.Logger.getLogger(UploadDistributionTaskTest::class.java.name)

@org.junit.BeforeClass
@JvmStatic
fun logVersions() {
LOGGER.info("Latest Gradle Version: $LATEST_GRADLE_VERSION")
LOGGER.info("Latest AGP Version: $LATEST_AGP_VERSION")
LOGGER.info("Latest Google Services Version: $LATEST_GOOGLE_SERVICES_VERSION")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.firebase.appdistribution.gradle

import com.google.gson.JsonParser
import java.net.HttpURLConnection
import java.net.URL
import java.util.logging.Logger
import javax.xml.parsers.DocumentBuilderFactory
import org.w3c.dom.Document

object VersionUtils {
private val LOGGER = Logger.getLogger(VersionUtils::class.java.name)
private const val AGP_METADATA_URL =
"https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/maven-metadata.xml"
private const val GRADLE_RELEASES_URL =
"https://api.github.com/repos/gradle/gradle/releases/latest"
private const val GOOGLE_SERVICES_METADATA_URL =
"https://dl.google.com/dl/android/maven2/com/google/gms/google-services/maven-metadata.xml"

// Latest verified versions. Update these as new versions are released and verified.
// These serve as fallbacks if fetching fails.
const val VERIFIED_AGP_VERSION = "9.1.0-alpha07"
const val VERIFIED_GRADLE_VERSION = "9.3.1"
const val VERIFIED_GOOGLE_SERVICES_VERSION = "4.4.4"

fun fetchLatestAgpVersion(): String {
try {
val url = URL(AGP_METADATA_URL)
val connection = url.openConnection() as HttpURLConnection
connection.requestMethod = "GET"
connection.connect()

if (connection.responseCode == 200) {
val dbFactory = DocumentBuilderFactory.newInstance()
val dBuilder = dbFactory.newDocumentBuilder()
val doc: Document = dBuilder.parse(connection.inputStream)
doc.documentElement.normalize()
val versioning = doc.getElementsByTagName("versioning").item(0)
val latest = versioning.childNodes
for (i in 0 until latest.length) {
if (latest.item(i).nodeName == "latest") {
return latest.item(i).textContent
}
}
}
} catch (e: Exception) {
LOGGER.warning("Failed to fetch latest AGP version: ${e.message}")
}
return VERIFIED_AGP_VERSION
}

fun fetchLatestGradleVersion(): String {
try {
val url = URL(GRADLE_RELEASES_URL)
val connection = url.openConnection() as HttpURLConnection
connection.requestMethod = "GET"
connection.setRequestProperty("User-Agent", "Mozilla/5.0")
connection.connect()

if (connection.responseCode == 200) {
val content = connection.inputStream.bufferedReader().use { it.readText() }
val jsonObject = JsonParser.parseString(content).asJsonObject
return jsonObject.get("tag_name").asString.removePrefix("v")
}
} catch (e: Exception) {
LOGGER.warning("Failed to fetch latest Gradle version: ${e.message}")
}
return VERIFIED_GRADLE_VERSION
}

fun fetchLatestGoogleServicesVersion(): String {
try {
val url = URL(GOOGLE_SERVICES_METADATA_URL)
val connection = url.openConnection() as HttpURLConnection
connection.requestMethod = "GET"
connection.connect()

if (connection.responseCode == 200) {
val dbFactory = DocumentBuilderFactory.newInstance()
val dBuilder = dbFactory.newDocumentBuilder()
val doc: Document = dBuilder.parse(connection.inputStream)
doc.documentElement.normalize()
val versioning = doc.getElementsByTagName("versioning").item(0)
val latest = versioning.childNodes
for (i in 0 until latest.length) {
if (latest.item(i).nodeName == "latest") {
return latest.item(i).textContent
}
}
}
} catch (e: Exception) {
LOGGER.warning("Failed to fetch latest Google Services version: ${e.message}")
}
return VERIFIED_GOOGLE_SERVICES_VERSION
}
}
Loading