Skip to content

chore(samples): build apk and upload to aws #2266

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 30, 2025

Conversation

renefloor
Copy link
Contributor

@renefloor renefloor commented May 27, 2025

Submit a pull request

Linear: fixes FLU-150

Github Issue: #

CLA

  • I have signed the Stream CLA (required).
  • The code changes follow best practices
  • Code changes are tested (add some information if not applicable)

Description of the pull request

This copies the publishing code from flutter-samples so we publish the apk to aws again and have it downloadable from the website.

Summary by CodeRabbit

  • New Features
    • Android app builds are now distributed via AWS S3 instead of Firebase.
  • Chores
    • Updated workflow to use AWS S3 for Android app distribution.
    • Standardized APK output filename to "flutter-sample-app.apk".
    • Added AWS S3 integration for Fastlane.
  • Refactor
    • Adjusted Fastlane configuration to support S3 uploads and removed Firebase-specific steps.

@renefloor renefloor changed the title chore: build apk and upload to aws chore(samples): build apk and upload to aws May 27, 2025
@xsahil03x
Copy link
Member

@coderabbitai full review

Copy link
Contributor

coderabbitai bot commented May 29, 2025

✅ Actions performed

Full review triggered.

Copy link
Contributor

coderabbitai bot commented May 29, 2025

"""

Walkthrough

The Android GitHub Actions workflow was updated to replace Firebase distribution with an AWS S3 upload using a new Fastlane lane. The APK output filename was standardized, and the Fastlane configuration was extended with an AWS S3 plugin and a new lane to build and upload the APK to S3.

Changes

File(s) Change Summary
.github/workflows/distribute_external.yml Removed Firebase distribution steps; added Fastlane lane call to distribute APK to AWS S3
sample_app/android/fastlane/Fastfile Added distribute_to_s3 lane; updated APK artifact path in distribute_to_firebase lane; removed App Store Connect lane
sample_app/android/fastlane/Pluginfile Added fastlane-plugin-aws_s3 gem dependency
sample_app/android/app/build.gradle Set fixed APK output filename "flutter-sample-app.apk" for all build variants

Sequence Diagram(s)

sequenceDiagram
    participant GitHubActions as GitHub Actions Workflow
    participant Fastlane as Fastlane
    participant AWS as AWS S3

    GitHubActions->>Fastlane: Run `distribute_to_s3` lane with AWS creds
    Fastlane->>Fastlane: Build APK (fixed name)
    Fastlane->>AWS: Upload APK to S3 bucket with encryption
    AWS-->>Fastlane: Upload confirmation
    Fastlane-->>GitHubActions: Lane completion
Loading

Assessment against linked issues

Objective Addressed Explanation
Publish APK to AWS (FLU-150)

Poem

A bunny with code on its mind,
Hopped past Firebase, left it behind.
With Flutter it built,
To S3 it did tilt—
Now APKs in the cloud you will find!
☁️🐇✨
"""


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e612ab1 and fb8822b.

📒 Files selected for processing (4)
  • .github/workflows/distribute_external.yml (1 hunks)
  • sample_app/android/app/build.gradle (1 hunks)
  • sample_app/android/fastlane/Fastfile (1 hunks)
  • sample_app/android/fastlane/Pluginfile (1 hunks)

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
.github/workflows/distribute_external.yml (3)

77-79: Explicitly specify --release and cache pub dependencies for faster builds

By default, flutter build apk produces a release build, but adding --release makes it explicit. Also, caching pub dependencies can significantly speed up CI runs.

Example diffs:

-      - name: Build
-        run: flutter build apk
+      - name: Build
+        run: flutter build apk --release
         working-directory: sample_app
+      - name: Cache Flutter Pub dependencies
+        uses: actions/cache@v3
+        with:
+          path: ~/.pub-cache
+          key: ${{ runner.os }}-pub-${{ hashFiles('**/pubspec.lock') }}

81-85: Make the artifact name dynamic and set retention

The static artifact name (android-stream-chat-v1) can become confusing over time. Incorporate the release tag or build number, and add retention-days to automatically prune old artifacts.

Example diff:

-      - name: Upload Artifact
-        uses: actions/upload-artifact@v4
-        with:
-          name: android-stream-chat-v1
-          path: sample_app/build/app/outputs/apk/release/app-release.apk
+      - name: Upload Artifact
+        uses: actions/upload-artifact@v4
+        with:
+          name: android-stream-chat-${{ github.ref_name }}
+          path: sample_app/build/app/outputs/apk/release/app-release.apk
+          retention-days: 30

94-98: Simplify the S3 upload step by removing the intermediate copy

The cp command and intermediate file are unnecessary. Upload directly from the build output to S3 in one go.

Suggested diff:

-      - name: Upload to S3
-        run: |
-          cp sample_app/build/app/outputs/apk/release/app-release.apk flutter-sample-app.apk
-          aws s3 cp flutter-sample-app.apk s3://${{ secrets.AWS_S3_BUCKET }} --sse AES256
+      - name: Upload to S3
+        run: aws s3 cp sample_app/build/app/outputs/apk/release/app-release.apk s3://${{ secrets.AWS_S3_BUCKET }}/flutter-sample-app.apk --sse AES256
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 366635b and f13065b.

📒 Files selected for processing (1)
  • .github/workflows/distribute_external.yml (1 hunks)
🧰 Additional context used
🪛 actionlint (1.7.7)
.github/workflows/distribute_external.yml

88-88: the runner of "aws-actions/configure-aws-credentials@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
sample_app/android/app/build.gradle (1)

84-88: APK naming standardization looks good, consider variant-specific naming for robustness.

The fixed APK naming facilitates consistent artifact handling for the AWS S3 upload process. However, consider the following potential improvements:

  1. Variant conflicts: The current implementation applies the same filename to all variants (debug, release, etc.), which could cause file conflicts if multiple variants are built simultaneously.

  2. Build type awareness: Consider incorporating build type in the filename for better traceability.

If you want to maintain variant-specific naming while keeping consistency for release builds, consider this approach:

 applicationVariants.all { variant ->
     variant.outputs.all {
-        outputFileName = "flutter-sample-app.apk"
+        if (variant.buildType.name == "release") {
+            outputFileName = "flutter-sample-app.apk"
+        } else {
+            outputFileName = "flutter-sample-app-${variant.buildType.name}.apk"
+        }
     }
 }
sample_app/android/fastlane/Fastfile (1)

55-76: Well-implemented S3 distribution lane with room for minor improvements.

The new distribute_to_s3 lane is well-structured with proper validation and security considerations. The implementation correctly:

  • Reuses the existing build_apk lane for modularity
  • Validates bucket and path configuration
  • Uses secure environment variable handling
  • Applies server-side encryption

Consider these enhancements for robustness:

  1. More flexible bucket parsing: The current split logic assumes a simple bucket/path structure.
-    bucket_name, path = bucket_with_path.split('/', 2)
+    parts = bucket_with_path.split('/', 2)
+    bucket_name = parts[0]
+    path = parts[1..-1].join('/') if parts.length > 1
  1. Build versioning consistency: Unlike the Firebase lane, this doesn't handle build numbering. Consider if versioning is needed for S3 uploads.

  2. Upload verification: Consider adding a verification step to confirm successful upload.

+    # Verify upload success
+    UI.success("Successfully uploaded APK to s3://#{bucket_name}/#{path}/flutter-sample-app.apk")
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f13065b and 6932c85.

📒 Files selected for processing (4)
  • .github/workflows/distribute_external.yml (1 hunks)
  • sample_app/android/app/build.gradle (1 hunks)
  • sample_app/android/fastlane/Fastfile (1 hunks)
  • sample_app/android/fastlane/Pluginfile (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • sample_app/android/fastlane/Pluginfile
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/distribute_external.yml
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: android
  • GitHub Check: stream_chat_flutter
  • GitHub Check: stream_chat_localizations
🔇 Additional comments (1)
sample_app/android/fastlane/Fastfile (1)

48-48: APK path update aligns correctly with build.gradle changes.

The updated artifact path correctly reflects the new standardized APK naming convention configured in sample_app/android/app/build.gradle.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
sample_app/android/fastlane/Fastfile (3)

65-65: Enhance path validation for better robustness.

The current validation only checks for nil or empty strings. Consider trimming whitespace and validating the path format more thoroughly.

-    UI.user_error!("AWS_S3_BUCKET must include path (e.g., 'bucket-name/downloads')") if path.nil? || path.empty?
+    path = path&.strip
+    UI.user_error!("AWS_S3_BUCKET must include path (e.g., 'bucket-name/downloads')") if path.nil? || path.empty?

58-58: Extract APK path to avoid code duplication.

The APK file path is hardcoded in both the Firebase and S3 lanes. Consider extracting this to a method or constant to improve maintainability.

Add a helper method at the top of the platform block:

platform :android do
  app_id = "1:674907137625:android:f4033353c54985b0d7f348" # The Firebase app ID
+  
+  def apk_output_path
+    "#{root_path}/build/app/outputs/apk/release/flutter-sample-app.apk"
+  end

Then update both lanes to use this method:

-      android_artifact_path: "#{root_path}/build/app/outputs/apk/release/flutter-sample-app.apk",
+      android_artifact_path: apk_output_path,
-      files: ["#{root_path}/build/app/outputs/apk/release/flutter-sample-app.apk"]
+      files: [apk_output_path]

Also applies to: 74-74


67-75: Consider adding error handling for AWS operations.

The S3 upload operation could fail due to network issues, invalid credentials, or insufficient permissions. Consider wrapping the aws_s3 call in error handling to provide clearer feedback.

-    aws_s3(
-      access_key: ENV.fetch("AWS_ACCESS_KEY_ID"),
-      secret_access_key: ENV.fetch("AWS_SECRET_ACCESS_KEY"),
-      region: ENV.fetch("AWS_REGION", "us-east-1"),
-      bucket: bucket_name,
-      path: path,
-      server_side_encryption: "AES256",
-      files: ["#{root_path}/build/app/outputs/apk/release/flutter-sample-app.apk"]
-    )
+    begin
+      aws_s3(
+        access_key: ENV.fetch("AWS_ACCESS_KEY_ID"),
+        secret_access_key: ENV.fetch("AWS_SECRET_ACCESS_KEY"),
+        region: ENV.fetch("AWS_REGION", "us-east-1"),
+        bucket: bucket_name,
+        path: path,
+        server_side_encryption: "AES256",
+        files: ["#{root_path}/build/app/outputs/apk/release/flutter-sample-app.apk"]
+      )
+      UI.success("APK successfully uploaded to S3: s3://#{bucket_name}/#{path}")
+    rescue => e
+      UI.user_error!("Failed to upload APK to S3: #{e.message}")
+    end
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6932c85 and 1c53d2e.

📒 Files selected for processing (1)
  • sample_app/android/fastlane/Fastfile (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: android
  • GitHub Check: stream_chat_localizations
  • GitHub Check: stream_chat_flutter_core
  • GitHub Check: stream_chat_flutter
  • GitHub Check: stream_chat_persistence
🔇 Additional comments (2)
sample_app/android/fastlane/Fastfile (2)

48-48: LGTM! APK path update aligns with new naming convention.

The updated path correctly reflects the new standardized APK filename and output location.


55-76: Well-implemented S3 distribution lane with good security practices.

The new distribute_to_s3 lane is well-structured and includes:

  • Proper environment variable usage with ENV.fetch
  • Bucket/path parsing and validation
  • AES256 server-side encryption for security
  • Clear documentation and usage examples

The implementation follows Fastlane best practices and provides a clean replacement for Firebase distribution.

@xsahil03x xsahil03x force-pushed the chore/publish-sample-to-aws branch from 210833b to 331bf82 Compare May 30, 2025 16:28
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
sample_app/android/fastlane/Fastfile (1)

55-108: Consider reducing verbose logging and improving error handling.

The new S3 distribution lane includes comprehensive logging for debugging APK file locations, which is helpful for troubleshooting but may be excessive for production use.

Consider the following improvements:

  desc "Build and distribute app to S3"
  # Usage: bundle exec fastlane android distribute_to_s3
  lane :distribute_to_s3 do |options|
    build_apk
    
-    # Add logging to verify APK file availability
-    UI.message("🔍 Checking APK build outputs...")
-    
-    # List contents of the build directory
-    build_dir = "#{root_path}/build/app/outputs"
-    if Dir.exist?(build_dir)
-      UI.message("📁 Contents of #{build_dir}:")
-      Dir.glob("#{build_dir}/**/*").each do |file|
-        UI.message("  - #{file}")
-      end
-    else
-      UI.error("❌ Build directory does not exist: #{build_dir}")
-    end
-    
-    # Check specific APK locations
-    expected_apk = "#{root_path}/build/app/outputs/apk/release/flutter-sample-app.apk"
-    actual_apk = "#{root_path}/build/app/outputs/flutter-apk/app-release.apk"
-    
-    UI.message("🎯 Checking expected APK location: #{expected_apk}")
-    if File.exist?(expected_apk)
-      UI.success("✅ Expected APK found!")
-      file_size = File.size(expected_apk) / (1024 * 1024) # Size in MB
-      UI.message("📦 APK size: #{file_size.round(1)} MB")
-    else
-      UI.error("❌ Expected APK not found")
-    end
-    
-    UI.message("🎯 Checking actual APK location: #{actual_apk}")
-    if File.exist?(actual_apk)
-      UI.success("✅ Actual APK found!")
-      file_size = File.size(actual_apk) / (1024 * 1024) # Size in MB
-      UI.message("📦 APK size: #{file_size.round(1)} MB")
-    else
-      UI.error("❌ Actual APK not found")
-    end
-    
-    # Find all APK files
-    UI.message("🔎 Searching for all APK files in build directory...")
-    apk_files = Dir.glob("#{build_dir}/**/*.apk")
-    if apk_files.any?
-      UI.message("📱 Found APK files:")
-      apk_files.each do |apk|
-        file_size = File.size(apk) / (1024 * 1024) # Size in MB
-        UI.message("  - #{apk} (#{file_size.round(1)} MB)")
-      end
-    else
-      UI.error("❌ No APK files found in build directory!")
-    end
+    # Verify APK exists before upload
+    apk_path = "#{root_path}/build/app/outputs/apk/release/flutter-sample-app.apk"
+    unless File.exist?(apk_path)
+      UI.user_error!("APK file not found at: #{apk_path}")
+    end
+    
+    file_size = File.size(apk_path) / (1024 * 1024)
+    UI.message("📦 Uploading APK (#{file_size.round(1)} MB) to S3...")
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 331bf82 and c142375.

📒 Files selected for processing (1)
  • sample_app/android/fastlane/Fastfile (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: android
  • GitHub Check: stream_chat_localizations
  • GitHub Check: stream_chat_flutter_core
  • GitHub Check: stream_chat_flutter
🔇 Additional comments (1)
sample_app/android/fastlane/Fastfile (1)

48-48: LGTM! APK path standardization looks good.

The APK path has been updated to align with the new naming convention. This change maintains consistency across the Firebase distribution workflow.

@xsahil03x xsahil03x force-pushed the chore/publish-sample-to-aws branch from eecb5cd to fb8822b Compare May 30, 2025 17:43
@xsahil03x
Copy link
Member

@coderabbitai summary

Copy link
Contributor

coderabbitai bot commented May 30, 2025

✅ Actions performed

Summary regeneration triggered.

@xsahil03x xsahil03x merged commit 3b3241a into master May 30, 2025
15 checks passed
@xsahil03x xsahil03x deleted the chore/publish-sample-to-aws branch May 30, 2025 18:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants