snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Code scanning - action / CodeQL-Build (push) Failing after 2s
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s

This commit is contained in:
upstream-mirror
2026-09-16 01:21:02 +05:00
commit 30810eecd7
10161 changed files with 987110 additions and 0 deletions

View File

@@ -0,0 +1,581 @@
name: 'Docker Image Size Tracker'
description: 'Track and report Docker image sizes in Pull Requests'
author: 'Rocket.Chat'
inputs:
github-token:
description: 'GitHub token for commenting on PRs'
required: true
ci-pat:
description: 'GitHub token for committing to history branch'
required: true
registry:
description: 'Container registry (e.g., ghcr.io)'
required: false
default: 'ghcr.io'
repository:
description: 'Repository name (e.g., rocketchat)'
required: true
tag:
description: 'Image tag to measure'
required: true
baseline-tag:
description: 'Baseline tag to compare against'
required: false
default: 'develop'
platform:
description: 'Platform architecture to compare (amd64 or arm64)'
required: false
default: 'amd64'
size-thresholds:
description: 'Optional JSON: per-image trigger thresholds. Only comment when an image increase exceeds its threshold. Example: {"rocketchat":{"mb":50,"percent":5},"omnichannel":{"mb":10,"percent":2}}'
required: false
default: ''
fail-thresholds:
description: 'Optional JSON: per-image fail thresholds. Task fails when an image increase exceeds its threshold (mb and/or percent). Example: {"rocketchat":{"mb":100,"percent":15}}'
required: false
default: ''
outputs:
total-size:
description: 'Total size in bytes'
value: ${{ steps.measure.outputs.total-size }}
size-diff:
description: 'Size difference in bytes'
value: ${{ steps.compare.outputs.size-diff }}
size-diff-percent:
description: 'Size difference percentage'
value: ${{ steps.compare.outputs.size-diff-percent }}
comment-triggered:
description: 'Whether to post PR comment (only when size is bigger and thresholds met)'
value: ${{ steps.compare.outputs.comment-triggered }}
failed:
description: 'True if image size exceeded fail-thresholds'
value: ${{ steps.compare.outputs.failed }}
runs:
using: 'composite'
steps:
- name: Download manifests
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
pattern: manifests-*
path: /tmp/manifests
merge-multiple: true
- name: Measure image sizes from artifacts
id: measure
shell: bash
env:
PLATFORM: ${{ inputs.platform }}
TAG: ${{ inputs.tag }}
run: |
echo "Reading image sizes from build artifacts for platform: $PLATFORM"
declare -A sizes
declare -a services_list
total=0
# Loop through service directories (same as publish workflow)
shopt -s nullglob
for service_dir in /tmp/manifests/*; do
[[ -d "$service_dir" ]] || continue
service="$(basename "$service_dir")"
echo "Processing service: $service"
services_list+=("$service")
size=0
# Read only the specified platform architecture
manifest_file="$service_dir/$PLATFORM/manifest.json"
if [[ -f "$manifest_file" ]]; then
# docker manifest inspect -v puts the manifest under SchemaV2Manifest
# (Docker schema2 images) or OCIManifest (OCI images, which buildx
# produces by default). Coalesce so both formats are read.
config_size=$(jq -r '(.SchemaV2Manifest // .OCIManifest).config.size // 0' "$manifest_file")
layers_size=$(jq '[(.SchemaV2Manifest // .OCIManifest).layers[]?.size // 0] | add // 0' "$manifest_file")
size=$((config_size + layers_size))
echo " → Found $manifest_file: $size bytes (config: $config_size, layers: $layers_size)"
else
echo " ⚠ Manifest not found for platform $PLATFORM: $manifest_file"
fi
sizes[$service]=$size
total=$((total + size))
done
echo "Total size (all services, $PLATFORM only): $total bytes"
echo "total-size=$total" >> $GITHUB_OUTPUT
# Save to JSON
echo "{" > current-sizes.json
echo " \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"," >> current-sizes.json
echo " \"tag\": \"$TAG\"," >> current-sizes.json
echo " \"total\": $total," >> current-sizes.json
echo " \"services\": {" >> current-sizes.json
first=true
for service in "${services_list[@]}"; do
if [[ "$first" == "true" ]]; then
first=false
else
echo "," >> current-sizes.json
fi
echo " \"$service\": ${sizes[$service]}" >> current-sizes.json
done
echo " }" >> current-sizes.json
echo "}" >> current-sizes.json
echo "Current sizes saved:"
cat current-sizes.json
# Save services list for baseline measurement
printf '%s\n' "${services_list[@]}" > /tmp/services-list.txt
- name: Measure baseline
id: baseline
shell: bash
continue-on-error: true
env:
REGISTRY: ${{ inputs.registry }}
ORG: ${{ inputs.repository }}
TAG: ${{ inputs.baseline-tag }}
PLATFORM: ${{ inputs.platform }}
run: |
echo "Measuring baseline: $REGISTRY/$ORG/*:$TAG (platform: $PLATFORM)"
declare -A sizes
declare -a services_list
total=0
# Read services list from current measurement
while IFS= read -r service; do
services_list+=("$service")
# Map service name to image name (handle rocketchat -> rocket.chat)
if [[ "$service" == "rocketchat" ]] || [[ "$service" == "rocketchat-cov" ]]; then
image_name="rocket.chat"
[[ "$service" == "rocketchat-cov" ]] && image_name="rocket.chat-cov"
else
image_name="$service"
fi
image="$REGISTRY/$ORG/$image_name:$TAG"
echo " → Inspecting $image"
size=0
if manifest=$(docker manifest inspect "$image" 2>/dev/null); then
# Check if it's a manifest list (multi-arch)
if echo "$manifest" | jq -e '.manifests' > /dev/null 2>&1; then
# Manifest list - find the specified platform
echo " → Multi-arch manifest detected, filtering for $PLATFORM"
platform_digest=$(echo "$manifest" | jq -r --arg arch "$PLATFORM" '.manifests[] | select(.platform.architecture == $arch) | .digest' | head -1)
if [[ -n "$platform_digest" ]]; then
echo " → Inspecting $PLATFORM platform: $platform_digest"
if platform_manifest=$(docker manifest inspect "$REGISTRY/$ORG/$image_name@$platform_digest" 2>/dev/null); then
config_size=$(echo "$platform_manifest" | jq -r '.config.size // 0')
layers_size=$(echo "$platform_manifest" | jq '[.layers[]?.size // 0] | add // 0')
size=$((config_size + layers_size))
echo " → Size: $size bytes"
fi
else
echo " ⚠ Platform $PLATFORM not found in manifest"
fi
else
# Single arch manifest
config_size=$(echo "$manifest" | jq -r '.config.size // 0')
layers_size=$(echo "$manifest" | jq '[.layers[]?.size // 0] | add // 0')
size=$((config_size + layers_size))
fi
fi
sizes[$service]=$size
total=$((total + size))
done < /tmp/services-list.txt
echo "baseline-total=$total" >> $GITHUB_OUTPUT
echo "{" > baseline-sizes.json
echo " \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"," >> baseline-sizes.json
echo " \"tag\": \"$TAG\"," >> baseline-sizes.json
echo " \"total\": $total," >> baseline-sizes.json
echo " \"services\": {" >> baseline-sizes.json
first=true
for service in "${services_list[@]}"; do
if [[ "$first" == "true" ]]; then
first=false
else
echo "," >> baseline-sizes.json
fi
echo " \"$service\": ${sizes[$service]}" >> baseline-sizes.json
done
echo " }" >> baseline-sizes.json
echo "}" >> baseline-sizes.json
- name: Setup history storage
id: history
shell: bash
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
# Create a separate worktree for history branch
mkdir -p /tmp/history-worktree
# Try to fetch history branch
if git ls-remote --heads origin image-size-history | grep -q image-size-history; then
git fetch origin image-size-history
git worktree add /tmp/history-worktree image-size-history
else
# Create orphan branch for history in worktree
git worktree add --detach /tmp/history-worktree
cd /tmp/history-worktree
git checkout --orphan image-size-history
git rm -rf . 2>/dev/null || true
mkdir -p history
echo "# Image Size History" > README.md
echo "This branch stores historical image size data for tracking" >> README.md
git add README.md
git commit -m "Initialize image size history"
git push origin image-size-history
cd -
fi
mkdir -p /tmp/history-worktree/history
- name: Load historical data
shell: bash
run: |
# Load last 30 measurements and group by day (keep only last entry per day)
echo "[]" > history-data.json
if [[ -d /tmp/history-worktree/history ]]; then
jq -s '.' /tmp/history-worktree/history/*.json 2>/dev/null | jq '
sort_by(.timestamp) |
group_by(.timestamp[0:10]) |
map(.[-1]) |
.[-30:]
' > history-data.json || echo "[]" > history-data.json
fi
count=$(jq 'length' history-data.json)
echo "Loaded $count historical measurements (one per day)"
- name: Save current measurement to history
if: github.ref == 'refs/heads/develop'
shell: bash
env:
CI_PAT: ${{ inputs.ci-pat }}
run: |
timestamp=$(date -u +%Y%m%d-%H%M%S)
commit_sha="${{ github.sha }}"
# Add commit info to current measurement
jq --arg sha "$commit_sha" '. + {commit: $sha}' current-sizes.json > "/tmp/history-worktree/history/${timestamp}.json"
cd /tmp/history-worktree
git add "history/${timestamp}.json"
git commit -m "Add measurement for ${timestamp} (${commit_sha:0:7})"
git config --global user.email "ci@rocket.chat"
git config --global user.name "rocketchat-ci[bot]"
git config --global url.https://$CI_PAT@github.com/.insteadOf https://github.com/
git push origin image-size-history
cd -
echo "Saved measurement to history"
- name: Compare and generate report
id: compare
shell: bash
env:
SIZE_THRESHOLDS: ${{ inputs.size-thresholds }}
FAIL_THRESHOLDS: ${{ inputs.fail-thresholds }}
TAG: ${{ inputs.tag }}
BASELINE_TAG: ${{ inputs.baseline-tag }}
run: |
current_total=$(jq -r '.total' current-sizes.json)
if [[ ! -f baseline-sizes.json ]]; then
echo "No baseline available"
echo "size-diff=0" >> $GITHUB_OUTPUT
echo "size-diff-percent=0" >> $GITHUB_OUTPUT
echo "comment-triggered=false" >> $GITHUB_OUTPUT
cat > report.md << 'EOF'
# 📦 Docker Image Size Report
**Status:** First measurement - no baseline for comparison
**Total Size:** $(numfmt --to=iec-i --suffix=B $current_total)
EOF
exit 0
fi
baseline_total=$(jq -r '.total' baseline-sizes.json)
diff=$((current_total - baseline_total))
if [[ $baseline_total -gt 0 ]]; then
percent=$(awk "BEGIN {printf \"%.2f\", ($diff / $baseline_total) * 100}")
else
percent=0
fi
echo "size-diff=$diff" >> $GITHUB_OUTPUT
echo "size-diff-percent=$percent" >> $GITHUB_OUTPUT
# Only comment when size is bigger than baseline; optionally require per-image thresholds
THRESHOLDS="$SIZE_THRESHOLDS"
FAIL_THRESHOLDS="$FAIL_THRESHOLDS"
comment_triggered=false
fail_triggered=false
if [[ $diff -gt 0 ]]; then
if [[ -z "$THRESHOLDS" ]] || [[ "$THRESHOLDS" == "{}" ]]; then
comment_triggered=true
fi
fi
color="gray"
if (( $(awk "BEGIN {print ($percent > 0.01)}") )); then
color="red"
elif (( $(awk "BEGIN {print ($percent < -0.01)}") )); then
color="green"
fi
# Generate report
if [[ $diff -gt 0 ]]; then
emoji="📈"
badge="![](https://img.shields.io/badge/size-+${percent}%25-${color})"
sign="+"
elif [[ $diff -lt 0 ]]; then
emoji="📉"
badge="![](https://img.shields.io/badge/size--${percent}%25-${color})"
sign="-"
else
emoji="➡️"
badge="![](https://img.shields.io/badge/size-unchanged-${color})"
sign=""
fi
cat > report.md << EOF
# 📦 Docker Image Size Report
## $emoji Changes $badge
| Service | Current | Baseline | Change | Percent |
|---------|---------|----------|--------|---------|
| **sum of all images** | **$(numfmt --to=iec-i --suffix=B $current_total)** | **$(numfmt --to=iec-i --suffix=B $baseline_total)** | **${sign}$(numfmt --to=iec-i --suffix=B ${diff#-})** | $badge |
EOF
# Get services dynamically from current-sizes.json, sorted by size (largest first)
for service in $(jq -r '.services | to_entries | sort_by(-.value) | .[].key' current-sizes.json); do
current=$(jq -r ".services.\"$service\"" current-sizes.json)
baseline=$(jq -r ".services.\"$service\" // 0" baseline-sizes.json)
service_diff=$((current - baseline))
if [[ $baseline -gt 0 ]]; then
service_percent=$(awk "BEGIN {printf \"%.2f\", ($service_diff / $baseline) * 100}")
else
service_percent=0
fi
# Check per-image thresholds for comment trigger (only when size increased)
if [[ $diff -gt 0 ]] && [[ -n "$THRESHOLDS" ]] && [[ "$THRESHOLDS" != "{}" ]]; then
threshold_mb=$(echo "$THRESHOLDS" | jq -r ".\"$service\".mb // empty")
threshold_pct=$(echo "$THRESHOLDS" | jq -r ".\"$service\".percent // empty")
if [[ -n "$threshold_mb" ]] || [[ -n "$threshold_pct" ]]; then
exceeded=false
if [[ -n "$threshold_mb" ]] && [[ $service_diff -ge $(awk "BEGIN {printf \"%.0f\", $threshold_mb * 1048576}") ]]; then
exceeded=true
fi
if [[ -n "$threshold_pct" ]] && [[ $service_percent != "0.00" ]] && (( $(awk "BEGIN {print ($service_percent >= $threshold_pct)}") )); then
exceeded=true
fi
[[ "$exceeded" == "true" ]] && comment_triggered=true
fi
fi
# Check per-image fail thresholds (task fails when exceeded)
if [[ $diff -gt 0 ]] && [[ -n "$FAIL_THRESHOLDS" ]] && [[ "$FAIL_THRESHOLDS" != "{}" ]]; then
fail_mb=$(echo "$FAIL_THRESHOLDS" | jq -r ".\"$service\".mb // empty")
fail_pct=$(echo "$FAIL_THRESHOLDS" | jq -r ".\"$service\".percent // empty")
if [[ -n "$fail_mb" ]] || [[ -n "$fail_pct" ]]; then
exceeded=false
if [[ -n "$fail_mb" ]] && [[ $service_diff -ge $(awk "BEGIN {printf \"%.0f\", $fail_mb * 1048576}") ]]; then
exceeded=true
fi
if [[ -n "$fail_pct" ]] && [[ $service_percent != "0.00" ]] && (( $(awk "BEGIN {print ($service_percent >= $fail_pct)}") )); then
exceeded=true
fi
[[ "$exceeded" == "true" ]] && fail_triggered=true
fi
fi
color="gray"
if (( $(awk "BEGIN {print ($service_percent > 0.01)}") )); then
color="red"
elif (( $(awk "BEGIN {print ($service_percent < -0.01)}") )); then
color="green"
fi
if [[ $service_diff -gt 0 ]]; then
badge="![](https://img.shields.io/badge/size-+${service_percent}%25-${color})"
sign="+"
elif [[ $service_diff -lt 0 ]]; then
badge="![](https://img.shields.io/badge/size--${service_percent}%25-${color})"
sign="-"
else
badge="![](https://img.shields.io/badge/size-unchanged-${color})"
sign=""
fi
echo "| $service | $(numfmt --to=iec-i --suffix=B $current) | $(numfmt --to=iec-i --suffix=B $baseline) | ${sign}$(numfmt --to=iec-i --suffix=B ${service_diff#-}) | $badge |" >> report.md
done
# Generate historical trend chart
echo "" >> report.md
echo "## 📊 Historical Trend" >> report.md
echo "" >> report.md
# Load history and generate mermaid chart
history_count=$(jq 'length' history-data.json)
if [[ $history_count -gt 0 ]]; then
# Get all services from current build
all_services=$(jq -r '.services | keys | .[]' current-sizes.json | sort)
# Generate Mermaid chart data
x_labels=""
declare -A service_data
# Initialize service data arrays
for service in $all_services; do
service_data[$service]=""
done
# Process historical data
while IFS= read -r line; do
timestamp=$(echo "$line" | jq -r '.timestamp')
date_label=$(date -d "$timestamp" +"%m/%d %H:%M")
if [[ -z "$x_labels" ]]; then
x_labels="\"$date_label\""
else
x_labels="$x_labels, \"$date_label\""
fi
# Add data point for each service
for service in $all_services; do
size=$(echo "$line" | jq -r ".services.\"$service\" // 0")
size_gb=$(awk "BEGIN {printf \"%.2f\", $size / 1073741824}")
if [[ -z "${service_data[$service]}" ]]; then
service_data[$service]="$size_gb"
else
service_data[$service]="${service_data[$service]}, $size_gb"
fi
done
done < <(jq -c '.[]' history-data.json)
# Add current PR as last point
current_date=$(date -u +"%m/%d %H:%M")
x_labels="$x_labels, \"$current_date (PR)\""
for service in $all_services; do
size=$(jq -r ".services.\"$service\" // 0" current-sizes.json)
size_gb=$(awk "BEGIN {printf \"%.2f\", $size / 1073741824}")
service_data[$service]="${service_data[$service]}, $size_gb"
done
# Generate mermaid chart with multiple lines
cat >> report.md << EOF
\`\`\`mermaid
---
config:
theme: "dark"
xyChart:
width: 900
height: 400
---
xychart
title "Image Size Evolution by Service (Last 30 Days + This PR)"
x-axis [$x_labels]
y-axis "Size (GB)" 0 --> 0.5
EOF
# Add a line for each service
for service in $all_services; do
echo " line \"$service\" [${service_data[$service]}]" >> report.md
done
cat >> report.md << 'EOF'
```
EOF
# Add summary stats
min_size=$(jq '[.[].total] | min' history-data.json)
max_size=$(jq '[.[].total] | max' history-data.json)
avg_size=$(jq '[.[].total] | add / length' history-data.json)
cat >> report.md << EOF
**Statistics (last $history_count days):**
- 📊 Average: $(numfmt --to=iec-i --suffix=B ${avg_size%.*})
- ⬇️ Minimum: $(numfmt --to=iec-i --suffix=B $min_size)
- ⬆️ Maximum: $(numfmt --to=iec-i --suffix=B $max_size)
- 🎯 Current PR: $(numfmt --to=iec-i --suffix=B $current_total)
EOF
else
cat >> report.md << 'EOF'
*No historical data available yet. History tracking starts after merging to develop.*
EOF
fi
cat >> report.md << EOF
<details>
<summary>ℹ️ About this report</summary>
This report compares Docker image sizes from this build against the \`$BASELINE_TAG\` baseline.
- **Tag:** \`$TAG\`
- **Baseline:** \`$BASELINE_TAG\`
- **Timestamp:** $(date -u +"%Y-%m-%d %H:%M:%S UTC")
- **Historical data points:** $history_count
</details>
EOF
echo "comment-triggered=$comment_triggered" >> $GITHUB_OUTPUT
echo "failed=$fail_triggered" >> $GITHUB_OUTPUT
if [[ "$fail_triggered" == "true" ]]; then
echo "::error::Docker image size exceeded fail-thresholds (mb/percent). Check the report for details."
exit 1
fi
- name: Add report to Job Summary
if: always()
shell: bash
run: |
if [[ -f report.md ]]; then
cat report.md >> $GITHUB_STEP_SUMMARY
fi
- name: Cleanup worktree
if: always()
shell: bash
run: |
if [[ -d /tmp/history-worktree ]]; then
git worktree remove /tmp/history-worktree --force 2>/dev/null || true
fi
branding:
icon: 'package'
color: 'blue'