Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions .github/workflows/repo-size-audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: Repo Size Audit

# Advisory size check: surfaces packfile growth before it accumulates into
# another 600 MB-of-binary-churn situation (see the Phase 1 / Phase 2 plan
# in commit history for context). Does NOT block PRs today — but the warning
# threshold should drop after the Phase 2 history rewrite, and the failure
# threshold should drop with it.

on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
size-audit:
name: Repo Size Audit
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
# Full history so size-pack reflects the actual cost a fresh clone pays.
fetch-depth: 0

- name: Measure pack and working-tree size
id: measure
run: |
set -euo pipefail
# size-pack is the on-disk size of the packed git objects (KiB).
size_pack_kib=$(git count-objects -v | awk '/^size-pack:/ {print $2}')
size_pack_mib=$(( size_pack_kib / 1024 ))
tracked_bytes=$(git ls-files -z | xargs -0 stat -c '%s' 2>/dev/null | awk '{s+=$1} END {print s+0}')
tracked_mib=$(( tracked_bytes / 1024 / 1024 ))
echo "size_pack_mib=${size_pack_mib}" >> "$GITHUB_OUTPUT"
echo "tracked_mib=${tracked_mib}" >> "$GITHUB_OUTPUT"
echo "Pack size: ${size_pack_mib} MiB"
echo "Tracked working tree: ${tracked_mib} MiB"

- name: List largest tracked files
run: |
set -euo pipefail
echo "Top 20 largest tracked files:"
git ls-files -z \
| xargs -0 -I {} stat -c '%s %n' {} 2>/dev/null \
| sort -rn \
| head -20 \
| awk '{ printf " %8.2f MiB %s\n", $1/1024/1024, substr($0, index($0,$2)) }'

- name: List largest blobs across all history
run: |
set -euo pipefail
echo "Top 20 largest blob versions in git history:"
git rev-list --objects --all \
| git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
| awk '$1=="blob" && $3 > 100000 {print $3, $4}' \
| sort -rn \
| head -20 \
| awk '{ printf " %8.2f MiB %s\n", $1/1024/1024, substr($0, index($0,$2)) }'

- name: Enforce thresholds
env:
# Current pack size is ~205 MiB (Phase 1 state). Warn at 250 MiB,
# fail at 450 MiB so we still have headroom before AWS's 512 MiB
# clone limit kicks in. Lower both after Phase 2 history rewrite.
WARN_MIB: 250
FAIL_MIB: 450
SIZE_PACK_MIB: ${{ steps.measure.outputs.size_pack_mib }}
run: |
set -euo pipefail
if [ "$SIZE_PACK_MIB" -ge "$FAIL_MIB" ]; then
echo "::error::Pack size ${SIZE_PACK_MIB} MiB >= fail threshold ${FAIL_MIB} MiB. AWS Security Agent's 512 MiB clone limit is in danger. Stop committing binaries; see docs on the canonical fetch-from-release pattern."
exit 1
fi
if [ "$SIZE_PACK_MIB" -ge "$WARN_MIB" ]; then
echo "::warning::Pack size ${SIZE_PACK_MIB} MiB >= warn threshold ${WARN_MIB} MiB. Investigate the largest-blobs list above before this becomes a hard failure."
fi
echo "OK: pack size ${SIZE_PACK_MIB} MiB (warn=${WARN_MIB}, fail=${FAIL_MIB})."
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ data_archive/

# Coverage and CI reports
coverage.xml
coverage.json
htmlcov/
.coverage
bandit-report.json
Expand Down
26 changes: 25 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,32 @@ repos:
# Critical checks that should block
- id: check-merge-conflict
- id: detect-private-key
# Block files >250 KB. Build artifacts and pre-built binaries do NOT
# belong in git; distribute them via GitHub Releases or fetch on
# install (see tools/update_ciris_verify.py for the canonical pattern).
# Intentionally tracked larger files (allowlisted because there is no
# better distribution channel today):
# - ciris_engine/data/geo/cities.db (~6 MB) — geo typeahead, shipped in pip wheel
# - client/androidApp/wheels/*.whl (~2 MB each) — Android-specific pydantic_core
# builds, not available from PyPI
# If you genuinely need to commit a file larger than 250 KB, justify it
# in the PR description first; do NOT bypass this hook with --no-verify.
- id: check-added-large-files
args: ['--maxkb=500']
args: ['--maxkb=250']
Comment on lines 60 to +61

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Honor allowlisted binaries in large-file pre-commit hook

The new check-added-large-files setting enforces --maxkb=250 but does not configure any exclude for the files this same block describes as intentionally allowlisted (cities.db and Android wheel artifacts). Because this hook checks newly added files, routine wheel version bumps (new client/androidApp/wheels/pydantic_core-...whl filenames) will be rejected and force developers to bypass hooks, which directly contradicts the stated policy and can block normal Android packaging updates.

Useful? React with 👍 / 👎.

# Honor the allowlist documented in the comment above. Without this
# exclude, the wheel-version-bump path (e.g.,
# pydantic_core-2.23.4-...whl → 2.24.0-...whl) is a "new file" to
# the hook and gets rejected — forcing developers to bypass with
# --no-verify, which directly contradicts the policy stated above.
# Adding new entries to this list requires the same justification
# standard as bypassing the hook would: name the specific file,
# explain why there is no better distribution channel today, and
# link to the discussion in the PR description.
exclude: |
(?x)^(
ciris_engine/data/geo/cities\.db
| client/androidApp/wheels/.*\.whl
)$

# Quality checks - Run but don't block (Grace will report)
- repo: https://github.com/astral-sh/ruff-pre-commit
Expand Down
6 changes: 6 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,12 @@ Long-running commands may need timeout parameters for CI operations and comprehe
- **Response Time**: <1s API responses
- **Memory**: 4GB RAM maximum
- **Security**: Ed25519 signatures throughout
- **Repo Size**: Pre-commit blocks files >250 KB (`check-added-large-files`).
Do NOT bypass with `--no-verify`. Build artifacts and pre-built binaries do
not belong in git — distribute via GitHub Releases and fetch on install
(canonical pattern: `tools/update_ciris_verify.py`). AWS Security Agent and
several SAST products refuse to clone repos >512 MB. CI's
`repo-size-audit.yml` warns at 250 MiB pack size, fails at 450 MiB.

## Getting Help

Expand Down
1 change: 0 additions & 1 deletion coverage.json

This file was deleted.

Loading