diff --git a/.github/workflows/firebaseai.yml b/.github/workflows/firebaseai.yml index eab6b595610..f04ca06e169 100644 --- a/.github/workflows/firebaseai.yml +++ b/.github/workflows/firebaseai.yml @@ -48,7 +48,7 @@ jobs: target: iOS xcode: Xcode_26.0 runs-on: ${{ matrix.os }} - needs: spm + # needs: spm env: TEST_RUNNER_FIRAAppCheckDebugToken: ${{ secrets.VERTEXAI_INTEGRATION_FAC_DEBUG_TOKEN }} TEST_RUNNER_VTXIntegrationImagen: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} @@ -56,10 +56,10 @@ jobs: secrets_passphrase: ${{ secrets.GHASecretsGPGPassphrase1 }} steps: - uses: actions/checkout@v4 - - uses: actions/cache/restore@v4 - with: - path: .build - key: ${{ needs.spm.outputs.cache_key }} + # - uses: actions/cache/restore@v4 + # with: + # path: .build + # key: ${{ needs.spm.outputs.cache_key }} - name: Run integration tests run: scripts/repo.sh tests run --secrets ./scripts/secrets/AI.json --platforms ${{ matrix.target }} --xcode ${{ matrix.xcode }} AI - name: Upload xcodebuild logs diff --git a/FirebaseAI/Tests/TestApp/Sources/Constants.swift b/FirebaseAI/Tests/TestApp/Sources/Constants.swift index 9bfc47a0e5a..4f88a39448b 100644 --- a/FirebaseAI/Tests/TestApp/Sources/Constants.swift +++ b/FirebaseAI/Tests/TestApp/Sources/Constants.swift @@ -23,10 +23,9 @@ public enum FirebaseAppNames { public enum ModelNames { public static let gemini2Flash = "gemini-2.0-flash-001" public static let gemini2FlashLite = "gemini-2.0-flash-lite-001" - public static let gemini2FlashPreviewImageGeneration = "gemini-2.0-flash-preview-image-generation" public static let gemini2FlashLive = "gemini-2.0-flash-live-001" public static let gemini2FlashLivePreview = "gemini-2.0-flash-live-preview-04-09" - public static let gemini2_5_FlashImagePreview = "gemini-2.5-flash-image-preview" + public static let gemini2_5_FlashImage = "gemini-2.5-flash-image" public static let gemini2_5_Flash = "gemini-2.5-flash" public static let gemini2_5_FlashLite = "gemini-2.5-flash-lite" public static let gemini2_5_FlashLivePreview = "gemini-live-2.5-flash-preview" diff --git a/FirebaseAI/Tests/TestApp/Tests/Integration/GenerateContentIntegrationTests.swift b/FirebaseAI/Tests/TestApp/Tests/Integration/GenerateContentIntegrationTests.swift index d83a6b4a18d..046d49ff4c0 100644 --- a/FirebaseAI/Tests/TestApp/Tests/Integration/GenerateContentIntegrationTests.swift +++ b/FirebaseAI/Tests/TestApp/Tests/Integration/GenerateContentIntegrationTests.swift @@ -322,18 +322,11 @@ struct GenerateContentIntegrationTests { } @Test(arguments: [ - (InstanceConfig.vertexAI_v1beta, ModelNames.gemini2FlashPreviewImageGeneration), - (InstanceConfig.vertexAI_v1beta_global, ModelNames.gemini2FlashPreviewImageGeneration), - (InstanceConfig.vertexAI_v1beta_global, ModelNames.gemini2_5_FlashImagePreview), - (InstanceConfig.googleAI_v1beta, ModelNames.gemini2FlashPreviewImageGeneration), - (InstanceConfig.googleAI_v1beta, ModelNames.gemini2_5_FlashImagePreview), + (InstanceConfig.vertexAI_v1beta, ModelNames.gemini2_5_FlashImage), + (InstanceConfig.vertexAI_v1beta_global, ModelNames.gemini2_5_FlashImage), + (InstanceConfig.googleAI_v1beta, ModelNames.gemini2_5_FlashImage), // Note: The following configs are commented out for easy one-off manual testing. - // (InstanceConfig.googleAI_v1beta_staging, ModelNames.gemini2FlashPreviewImageGeneration) - // (InstanceConfig.googleAI_v1beta_freeTier, ModelNames.gemini2FlashPreviewImageGeneration), - // ( - // InstanceConfig.googleAI_v1beta_freeTier_bypassProxy, - // ModelNames.gemini2FlashPreviewImageGeneration - // ), + // (InstanceConfig.googleAI_v1beta_staging, ModelNames.gemini2_5_FlashImage) ]) func generateImage(_ config: InstanceConfig, modelName: String) async throws { let generationConfig = GenerationConfig( @@ -354,17 +347,8 @@ struct GenerateContentIntegrationTests { ) let prompt = "Generate an image of a cute cartoon kitten playing with a ball of yarn." - var response: GenerateContentResponse? - try await withKnownIssue( - "Backend may fail with a 503 - Service Unavailable error when overloaded", - isIntermittent: true - ) { - response = try await model.generateContent(prompt) - } matching: { issue in - (issue.error as? BackendError).map { $0.httpResponseCode == 503 } ?? false - } + let response = try await model.generateContent(prompt) - guard let response else { return } let candidate = try #require(response.candidates.first) let inlineDataPart = try #require(candidate.content.parts .first { $0 is InlineDataPart } as? InlineDataPart) @@ -372,16 +356,12 @@ struct GenerateContentIntegrationTests { #expect(inlineDataPartsViaAccessor.count == 1) let inlineDataPartViaAccessor = try #require(inlineDataPartsViaAccessor.first) #expect(inlineDataPart == inlineDataPartViaAccessor) - #expect(inlineDataPart.mimeType == "image/png") + #expect(inlineDataPart.mimeType.starts(with: "image/")) #expect(inlineDataPart.data.count > 0) #if canImport(UIKit) let uiImage = try #require(UIImage(data: inlineDataPart.data)) - // Gemini 2.0 Flash Experimental returns images sized to fit within a 1024x1024 pixel box but - // dimensions may vary depending on the aspect ratio. - #expect(uiImage.size.width <= 1024) - #expect(uiImage.size.width >= 500) - #expect(uiImage.size.height <= 1024) - #expect(uiImage.size.height >= 500) + #expect(uiImage.size.width > 0) + #expect(uiImage.size.height > 0) #endif // canImport(UIKit) } @@ -552,18 +532,11 @@ struct GenerateContentIntegrationTests { } @Test(arguments: [ - (InstanceConfig.vertexAI_v1beta, ModelNames.gemini2FlashPreviewImageGeneration), - (InstanceConfig.vertexAI_v1beta_global, ModelNames.gemini2FlashPreviewImageGeneration), - (InstanceConfig.vertexAI_v1beta_global, ModelNames.gemini2_5_FlashImagePreview), - (InstanceConfig.googleAI_v1beta, ModelNames.gemini2FlashPreviewImageGeneration), - (InstanceConfig.googleAI_v1beta, ModelNames.gemini2_5_FlashImagePreview), + (InstanceConfig.vertexAI_v1beta, ModelNames.gemini2_5_FlashImage), + (InstanceConfig.vertexAI_v1beta_global, ModelNames.gemini2_5_FlashImage), + (InstanceConfig.googleAI_v1beta, ModelNames.gemini2_5_FlashImage), // Note: The following configs are commented out for easy one-off manual testing. - // (InstanceConfig.googleAI_v1beta_staging, ModelNames.gemini2FlashPreviewImageGeneration) - // (InstanceConfig.googleAI_v1beta_freeTier, ModelNames.gemini2FlashPreviewImageGeneration), - // ( - // InstanceConfig.googleAI_v1beta_freeTier_bypassProxy, - // ModelNames.gemini2FlashPreviewImageGeneration - // ), + // (InstanceConfig.googleAI_v1beta_staging, ModelNames.gemini2_5_FlashImage) ]) func generateImageStreaming(_ config: InstanceConfig, modelName: String) async throws { let generationConfig = GenerationConfig( @@ -572,11 +545,6 @@ struct GenerateContentIntegrationTests { topK: 1, responseModalities: [.text, .image] ) - let safetySettings = safetySettings.filter { - // HARM_CATEGORY_CIVIC_INTEGRITY is deprecated in Vertex AI but only rejected when using the - // 'gemini-2.0-flash-preview-image-generation' model. - $0.harmCategory != .civicIntegrity - } let model = FirebaseAI.componentInstance(config).generativeModel( modelName: modelName, generationConfig: generationConfig, @@ -605,16 +573,12 @@ struct GenerateContentIntegrationTests { #expect(inlineDataParts.count == 1) let inlineDataPart = try #require(inlineDataParts.first) - #expect(inlineDataPart.mimeType == "image/png") + #expect(inlineDataPart.mimeType.starts(with: "image/")) #expect(inlineDataPart.data.count > 0) #if canImport(UIKit) let uiImage = try #require(UIImage(data: inlineDataPart.data)) - // Gemini 2.0 Flash Experimental returns images sized to fit within a 1024x1024 pixel box but - // dimensions may vary depending on the aspect ratio. - #expect(uiImage.size.width <= 1024) - #expect(uiImage.size.width >= 500) - #expect(uiImage.size.height <= 1024) - #expect(uiImage.size.height >= 500) + #expect(uiImage.size.width > 0) + #expect(uiImage.size.height > 0) #endif // canImport(UIKit) } diff --git a/scripts/build.sh b/scripts/build.sh index f9a79ef0960..68f61b94019 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -113,7 +113,7 @@ function RunXcodebuild() { local buildaction="${xcodebuild_args[$# - 1]}" # buildaction is the last arg local log_filename="xcodebuild-${buildaction}.log" - local xcbeautify_cmd=(xcbeautify --renderer github-actions --disable-logging) + local xcbeautify_cmd=(xcbeautify --renderer github-actions --disable-logging --is-ci --preserve-unbeautified) local result=0 NSUnbufferedIO=YES xcodebuild "$@" 2>&1 | tee "$log_filename" | \