Skip to content

chore: release v0.0.91 #776

chore: release v0.0.91

chore: release v0.0.91 #776

Workflow file for this run

name: Binary Size
on:
push:
branches: [main]
pull_request:
branches: [main]
concurrency:
group: binary-size-${{ github.head_ref || github.ref }}
cancel-in-progress: true
env:
# Maximum allowed binary size in bytes (16MB = 16777216).
#
# Baseline: the CLI measured ~1.9MB until Aug 2026, when 8556d46 made
# craft's first-party zig-js runtime part of the default build. That is a
# deliberate subsystem, not bloat — see the js-runtime option in
# packages/zig/build.zig (~+6.5MB in ReleaseFast; the ReleaseSafe binary
# we ship and measure here lands at ~13.9MB, already stripped, with no
# unwind tables or error traces). The gate sits ~15% above that baseline
# so it still catches accidental growth; opt-out `-Djs-runtime=false`
# builds remain around 2MB.
MAX_BINARY_SIZE: 16777216
# Warning threshold (14.5MB = 15204352), just above the ~13.9MB baseline
# so creep surfaces as a warning well before the hard limit.
WARN_BINARY_SIZE: 15204352
defaults:
run:
shell: bash
jobs:
track:
runs-on: ubuntu-latest
# The last step posts the size report as a pull request comment, and the
# default token here is read-only, so it failed with "Resource not
# accessible by integration" — after the build and the measuring had all
# succeeded. Requested explicitly rather than left to the repository
# default, which is what made this invisible.
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Setup Zig
uses: pantry-pm/pantry/packages/action@235036fa0f48bae99b2293df5a3dc35c809b1777 # pinned: last SHA whose bundled typescript resolves on linux-x64
- name: Install Linux dependencies
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev
- name: Cache Zig artifacts
uses: actions/cache@v5
with:
path: |
~/.cache/zig
packages/zig/zig-cache
key: size-${{ runner.os }}-zig-master-${{ hashFiles('packages/zig/build.zig') }}
restore-keys: |
size-${{ runner.os }}-zig-master-
- name: First-party Zig dependencies
uses: ./.github/actions/first-party-zig-deps
- name: Build release binary
working-directory: packages/zig
run: |
zig build -Doptimize=ReleaseSafe
- name: Measure binary size
id: size
working-directory: packages/zig
run: |
BINARY_PATH="zig-out/bin/craft"
if [ -f "$BINARY_PATH" ]; then
SIZE=$(wc -c < "$BINARY_PATH" | tr -d ' ')
SIZE_KB=$((SIZE / 1024))
SIZE_MB=$(echo "scale=2; $SIZE / 1048576" | bc)
echo "size=$SIZE" >> $GITHUB_OUTPUT
echo "size_kb=$SIZE_KB" >> $GITHUB_OUTPUT
echo "size_mb=$SIZE_MB" >> $GITHUB_OUTPUT
echo "Binary size: ${SIZE_KB}KB (${SIZE_MB}MB)"
else
echo "Binary not found at $BINARY_PATH"
exit 1
fi
- name: Check size limits
run: |
SIZE=${{ steps.size.outputs.size }}
SIZE_MB=${{ steps.size.outputs.size_mb }}
if [ "$SIZE" -gt "$MAX_BINARY_SIZE" ]; then
echo "::error::Binary size (${SIZE_MB}MB) exceeds maximum allowed size ($(echo "scale=2; $MAX_BINARY_SIZE / 1048576" | bc)MB)"
exit 1
elif [ "$SIZE" -gt "$WARN_BINARY_SIZE" ]; then
echo "::warning::Binary size (${SIZE_MB}MB) is approaching the limit"
fi
- name: First-party Zig dependencies
uses: ./.github/actions/first-party-zig-deps
- name: Get baseline size (main branch)
if: github.event_name == 'pull_request'
id: baseline
run: |
git fetch origin main
# Anchored at the workspace and `|| true`-guarded on purpose: the trap
# fires at the end of the step, by which point `cd packages/zig` below
# has moved us, so a relative pathspec resolves against the wrong
# directory and fails. Under `set -e` that failing restore became the
# step's exit status, so every pull request got a red Binary Size
# check for a cleanup step rather than for its binary size.
trap 'git -C "$GITHUB_WORKSPACE" restore --staged --worktree --source=HEAD -- packages/zig || true' EXIT
git checkout origin/main -- packages/zig
cd packages/zig
zig build -Doptimize=ReleaseSafe
if [ -f "zig-out/bin/craft" ]; then
BASELINE=$(wc -c < "zig-out/bin/craft" | tr -d ' ')
echo "baseline=$BASELINE" >> $GITHUB_OUTPUT
else
echo "::error::Baseline binary was not generated"
exit 1
fi
- name: Calculate size difference
if: github.event_name == 'pull_request'
id: diff
run: |
CURRENT=${{ steps.size.outputs.size }}
BASELINE=${{ steps.baseline.outputs.baseline }}
if [ "$BASELINE" -gt 0 ]; then
DIFF=$((CURRENT - BASELINE))
DIFF_KB=$((DIFF / 1024))
PERCENT=$(echo "scale=2; ($DIFF * 100) / $BASELINE" | bc)
echo "diff=$DIFF" >> $GITHUB_OUTPUT
echo "diff_kb=$DIFF_KB" >> $GITHUB_OUTPUT
echo "percent=$PERCENT" >> $GITHUB_OUTPUT
if [ "$DIFF" -gt 0 ]; then
echo "direction=increased" >> $GITHUB_OUTPUT
elif [ "$DIFF" -lt 0 ]; then
echo "direction=decreased" >> $GITHUB_OUTPUT
else
echo "direction=unchanged" >> $GITHUB_OUTPUT
fi
fi
- name: Generate size report
run: |
echo "## Binary Size Report" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Metric | Value |" >> $GITHUB_STEP_SUMMARY
echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Current Size | ${{ steps.size.outputs.size_kb }}KB (${{ steps.size.outputs.size_mb }}MB) |" >> $GITHUB_STEP_SUMMARY
if [ "${{ github.event_name }}" == "pull_request" ] && [ "${{ steps.baseline.outputs.baseline }}" -gt 0 ]; then
BASELINE_KB=$(( ${{ steps.baseline.outputs.baseline }} / 1024 ))
echo "| Baseline (main) | ${BASELINE_KB}KB |" >> $GITHUB_STEP_SUMMARY
echo "| Difference | ${{ steps.diff.outputs.diff_kb }}KB (${{ steps.diff.outputs.percent }}%) |" >> $GITHUB_STEP_SUMMARY
echo "| Status | ${{ steps.diff.outputs.direction }} |" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Limits" >> $GITHUB_STEP_SUMMARY
echo "- Warning threshold: $(echo "scale=2; $WARN_BINARY_SIZE / 1048576" | bc)MB" >> $GITHUB_STEP_SUMMARY
echo "- Maximum allowed: $(echo "scale=2; $MAX_BINARY_SIZE / 1048576" | bc)MB" >> $GITHUB_STEP_SUMMARY
- name: Comment on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const size = '${{ steps.size.outputs.size_kb }}';
const sizeMB = '${{ steps.size.outputs.size_mb }}';
const diff = '${{ steps.diff.outputs.diff_kb }}';
const percent = '${{ steps.diff.outputs.percent }}';
const direction = '${{ steps.diff.outputs.direction }}';
const warnMB = (Number(process.env.WARN_BINARY_SIZE) / 1048576).toFixed(2);
const maxMB = (Number(process.env.MAX_BINARY_SIZE) / 1048576).toFixed(2);
let emoji = '✅';
if (direction === 'increased' && parseInt(diff) > 10) emoji = '⚠️';
if (direction === 'decreased') emoji = '📉';
const body = `## ${emoji} Binary Size Report
| Metric | Value |
|--------|-------|
| Current Size | ${size}KB (${sizeMB}MB) |
| Change | ${diff}KB (${percent}%) ${direction} |
<details>
<summary>Size limits</summary>
- Warning: ${warnMB}MB
- Maximum: ${maxMB}MB
</details>`;
// Find existing comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const existingComment = comments.find(c =>
c.user.login === 'github-actions[bot]' &&
c.body.includes('Binary Size Report')
);
if (existingComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existingComment.id,
body: body
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
}
- name: Restore size history
if: github.ref == 'refs/heads/main'
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
# The history file lives only in the uploaded artifact (never in the
# repo), so pull the previous run's copy before appending — without
# this each artifact holds a single entry and no history accumulates.
mkdir -p .github/metrics
PREV_RUN=$(gh run list --workflow "Binary Size" --branch main --status success --limit 1 --json databaseId --jq '.[0].databaseId // empty')
if [ -n "$PREV_RUN" ]; then
gh run download "$PREV_RUN" -n binary-size-metrics -D .github/metrics || true
fi
- name: Save size history
if: github.ref == 'refs/heads/main'
run: |
mkdir -p .github/metrics
DATE=$(date -u +%Y-%m-%d)
COMMIT=$(git rev-parse --short HEAD)
echo "{\"date\": \"$DATE\", \"commit\": \"$COMMIT\", \"size\": ${{ steps.size.outputs.size }}}" >> .github/metrics/binary-size.jsonl
- name: Upload metrics
if: github.ref == 'refs/heads/main'
uses: actions/upload-artifact@v4
with:
name: binary-size-metrics
path: .github/metrics/
retention-days: 90