diff --git a/.github/workflows/sdk-size-checks.yml b/.github/workflows/sdk-size-checks.yml new file mode 100644 index 00000000000..85c67f01e59 --- /dev/null +++ b/.github/workflows/sdk-size-checks.yml @@ -0,0 +1,121 @@ +name: SDK size checks + +on: + pull_request: + +env: + METRICS_PROJECT: "stream-chat-android-metrics" + MODULES: "stream-chat-android-client stream-chat-android-offline stream-chat-android-ui-components stream-chat-android-compose" + METRICS_FILE: "metrics/size.json" + MAX_TOLERANCE: 500 + FINE_TOLERANCE: 250 + +jobs: + compare-sdk-sizes: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + - uses: ./.github/actions/setup-java + - uses: ./.github/actions/gradle-cache + with: + key-prefix: gradle-build + + - name: Assemble release for metrics + run: ./gradlew :metrics:$METRICS_PROJECT:assembleRelease + + - name: Get current SDK sizes + run: | + # Reads current SDK sizes from the metrics file + # and define to a variable using a compact JSON format + # so it can be exported for the next job step + CURRENT_SDK_SIZES=$(jq -c .release $METRICS_FILE) + echo "CURRENT_SDK_SIZES=$CURRENT_SDK_SIZES" >> $GITHUB_ENV + + - name: Calculate PR branch SDK sizes + run: | + echo '{}' > pr_sdk_sizes.json + + # Calculate sizes from the .apk files and save them into a temporary JSON file + # so it can be exported for the next job step + for module in $MODULES; do + baselineFile="metrics/$METRICS_PROJECT/build/outputs/apk/$module-baseline/release/$METRICS_PROJECT-$module-baseline-release.apk" + streamFile="metrics/$METRICS_PROJECT/build/outputs/apk/$module-stream/release/$METRICS_PROJECT-$module-stream-release.apk" + + baselineSize=$(du -k "$baselineFile" | awk '{print $1}') + streamSize=$(du -k "$streamFile" | awk '{print $1}') + size=$((streamSize - baselineSize)) + + jq -c --arg sdk "$module" --arg size "$size" '. + {($sdk): ($size | tonumber)}' pr_sdk_sizes.json > temp.json && mv temp.json pr_sdk_sizes.json + done + + echo "PR_SDK_SIZES=$(cat pr_sdk_sizes.json)" >> $GITHUB_ENV + + - name: Post comment on PR + uses: actions/github-script@v6 + with: + script: | + const maxTolerance = process.env.MAX_TOLERANCE + const fineTolerance = process.env.FINE_TOLERANCE + const currentSdkSizes = process.env.CURRENT_SDK_SIZES ? JSON.parse(process.env.CURRENT_SDK_SIZES) : {}; + const prSdkSizes = JSON.parse(process.env.PR_SDK_SIZES); + const commentHeader = '## SDK Size Comparison 📏'; + + // Prepare the comparison table + + let commentBody = ` + ${commentHeader} + + | SDK | Before | After | Difference | Status | + |-|-|-|-|-| + `; + + Object.keys(prSdkSizes).forEach(sdk => { + const currentSize = currentSdkSizes[sdk] || 0; + const prSize = prSdkSizes[sdk]; + const diff = prSize - currentSize; + const currentSizeInMb = (currentSize / 1024).toFixed(2); + const prSizeInMb = (prSize / 1024).toFixed(2); + const diffInMb = (diff / 1024).toFixed(2); + + let status = "🟢"; + if (diff < 0) { + status = "🚀"; + } else if (diff >= maxTolerance) { + status = "🔴"; + } else if (diff >= fineTolerance) { + status = "🟡"; + } + + commentBody += `| ${sdk} | ${currentSizeInMb} MB | ${prSizeInMb} MB | ${diffInMb} MB | ${status} |\n`; + }); + + // Post or update the PR comment + + // Find existing comment + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + }); + + const comment = comments.find(c => c.body.includes(commentHeader)); + + if (comment) { + // Update the existing comment + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: comment.id, + body: commentBody, + }); + } else { + // Create a new comment + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + body: commentBody, + }); + } diff --git a/.github/workflows/sdk-size-updates.yml b/.github/workflows/sdk-size-updates.yml new file mode 100644 index 00000000000..aa6914d1dd2 --- /dev/null +++ b/.github/workflows/sdk-size-updates.yml @@ -0,0 +1,95 @@ +name: SDK size updates + +on: + push: + branches: + - develop + + workflow_dispatch: + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + +env: + METRICS_PROJECT: "stream-chat-android-metrics" + MODULES: "stream-chat-android-client stream-chat-android-offline stream-chat-android-ui-components stream-chat-android-compose" + VARIANTS: "debug release" + METRICS_FILE: "metrics/size.json" + BRANCH_NAME: ${{ github.head_ref || github.ref_name }} + +jobs: + update-sdk-sizes: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + persist-credentials: false + - uses: ./.github/actions/setup-java + - uses: ./.github/actions/gradle-cache + with: + key-prefix: gradle-build + + - name: Assemble release and debug for metrics + run: ./gradlew :metrics:$METRICS_PROJECT:assemble + + - name: Update size metrics + run: | + # Create temporary JSON file + echo '{}' > metrics.json + + # Calculate sizes + for module in $MODULES; do + for variant in $VARIANTS; do + baselineFile="metrics/$METRICS_PROJECT/build/outputs/apk/$module-baseline/$variant/$METRICS_PROJECT-$module-baseline-$variant.apk" + streamFile="metrics/$METRICS_PROJECT/build/outputs/apk/$module-stream/$variant/$METRICS_PROJECT-$module-stream-$variant.apk" + + # Ensure files exist + if [[ -f "$baselineFile" && -f "$streamFile" ]]; then + baselineSize=$(du -k "$baselineFile" | awk '{print $1}') + streamSize=$(du -k "$streamFile" | awk '{print $1}') + size=$((streamSize - baselineSize)) + else + echo "Warning: $baselineFile or $streamFile not found. Setting size to 0." + size=0 + fi + + # Update JSON + jq --arg module "$module" --arg variant "$variant" --argjson size "$size" \ + ".\"$variant\".\"$module\" = $size" metrics.json > temp.json && mv temp.json metrics.json + done + done + + # Validate Generated JSON + jq . metrics.json + + # Move temporary JSON file to the final file + mv metrics.json $METRICS_FILE + + - name: Update size badges + run: | + for module in $MODULES; do + size=$(jq --arg module "$module" ".release.\"$module\"" $METRICS_FILE) + sizeInMb=$(echo "scale=2; $size / 1024" | bc) + badgeUrl="https://img.shields.io/badge/${module//-/--}-$sizeInMb%20MB-lightgreen" + sed -i "s|!\[$module\](.*)|![$module](${badgeUrl})|" README.md + done + + - name: Commit changes + run: | + git fetch origin $BRANCH_NAME + git checkout $BRANCH_NAME + + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + + git add $METRICS_FILE README.md + git commit -m "Update SDK sizes" || echo "No changes to commit" + + - name: Push changes + uses: ad-m/github-push-action@master + with: + github_token: ${{ secrets.STREAM_PUBLIC_BOT_TOKEN }} + branch: ${{ env.BRANCH_NAME }} diff --git a/README.md b/README.md index 88ee120d48e..5b39546c876 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,17 @@
+