Skip to content

feat(workflows): file-size as native dryvist workflow (Step 2 of 9, pilot)#9

Closed
JacobPEvans-personal wants to merge 1 commit into
mainfrom
feat/migrate-file-size-from-jp-personal
Closed

feat(workflows): file-size as native dryvist workflow (Step 2 of 9, pilot)#9
JacobPEvans-personal wants to merge 1 commit into
mainfrom
feat/migrate-file-size-from-jp-personal

Conversation

@JacobPEvans-personal
Copy link
Copy Markdown
Member

Summary

Step 2 of the org-wide config plan — the pilot of "dryvist owns the shared workflow library; JacobPEvans-personal consumes." File-size is the first workflow to make the trip from JacobPEvans-personal/.github/.github/workflows/_file-size.yml into this repo.

What lands here:

  • .github/workflows/file-size.yml — minimal caller (on: pull_request, two checkouts, runs the script). Patterned after the existing markdownlint.yml.
  • .github/scripts/file-size-check.sh (mode 100755) — all logic extracted per the no-scripts rule. Reads org defaults from a trusted, org-controlled file (passed as \$1); the per-repo override file is attacker-controllable on PR runs, so every value pulled from it is validated against strict regexes (positive int / extension shape / basename shape) before use. Malformed override values emit ::warning:: and fall back to the org default.
  • .github/file-size-defaults.yml — thresholds (warn: 6144, error: 12288), scan extensions, exempt list. Workflow + script have zero magic numbers.
  • CLAUDE.md — rewrites the inheritance section to flip the direction. dryvist/.github is the source of truth for the workflow library going forward; JacobPEvans-personal/.github is the consumer. File-size + markdownlint sourced here today; release-please + renovate-presets + SECURITY.md still inherited pending future migrations.

Per-repo override

  • Preferred path: .github/file-size.yml in the consuming repo (consolidates workflow-consumed configs under .github/).
  • Legacy: .file-size.yml at root — still read, but emits a ::warning:: to move it. Cleanup happens in Step 4 of the plan (batched per-repo PRs).

Override fields are unchanged from the original _file-size.yml:

defaults: { warn: <bytes>, error: <bytes> }   # additive override
scan: [.md, .nix]                              # REPLACES default scan list
extended: { limit: <bytes>, files: [BASE] }    # additive higher-limit set
exempt: [BASE]                                 # additive to org exempt list

Sequence

This PR is PR A of a three-PR migration for file-size:

  1. This PR — workflow lives here, ready to be consumed.
  2. PR B (follow-up, this repo or per consumer repo) — flip every uses: JacobPEvans-personal/.github/.github/workflows/_file-size.yml@main reference to uses: dryvist/.github/.github/workflows/file-size.yml@main.
  3. PR C (in JacobPEvans-personal/.github) — once gh code-search 'uses: JacobPEvans-personal/.github/.github/workflows/_file-size.yml' returns zero hits, delete the source.

Step 3 of the parent plan (separate, in terraform-github) will then add github_organization_ruleset.org_file_size_check that injects this workflow into every dryvist repo's PRs without any per-repo caller — at which point Step 4 deletes the per-repo callers entirely.

Test plan

  • shellcheck .github/scripts/file-size-check.sh — silent (green)
  • markdownlint-cli2 CLAUDE.md — 0 errors
  • yq parses both .github/file-size-defaults.yml and .github/workflows/file-size.yml
  • Commit GPG-signed
  • Manual review of CLAUDE.md scope section + .github/scripts/ directory convention
  • Live PR run against a dryvist repo to confirm the cross-repo checkout pattern works — Step 3's ruleset binding will exercise this end-to-end; in the meantime, any consumer can opt in with a thin caller (uses: dryvist/.github/.github/workflows/file-size.yml@main)

…ilot)

Migrates the file-size check from JacobPEvans-personal/.github (where it
lived as the reusable workflow _file-size.yml) into dryvist/.github as a
standalone, org-Required-Workflow-shaped check. First migration of the
"dryvist owns the workflow library; JacobPEvans-personal consumes" pattern
established in CLAUDE.md.

What lands
----------
- .github/workflows/file-size.yml: new. on: pull_request, two checkouts
  (target + .org-github), runs the script. No inline logic.
- .github/scripts/file-size-check.sh: new (mode 100755). All control flow
  extracted per the no-scripts rule. Reads org defaults from a trusted
  file (passed by argument); validates per-repo override values with
  strict regexes before use (positive int / extension shape / basename
  shape) since the override file is attacker-controllable on PR runs.
  Emits ::warning:: for malformed override values rather than silently
  ignoring them.
- .github/file-size-defaults.yml: new. Carries thresholds (warn: 6144,
  error: 12288), scan extensions, exempt list. No magic numbers in the
  workflow or the script - everything threshold-shaped is here.
- CLAUDE.md: rewrites the "Inheritance from JacobPEvans/.github" section
  to reflect the reversed direction. dryvist/.github is now the source
  of truth for the shared workflow library; JacobPEvans-personal is a
  consumer. File-size + markdownlint are sourced here; release-please
  + renovate-presets + SECURITY.md still inherited pending migration.
  Scope section updated to enumerate the new .github/scripts/ and
  .github/<name>-defaults.yml directories.

Per-repo override path
----------------------
Workflow prefers .github/file-size.yml (consolidated location); falls back
to legacy .file-size.yml at root with a deprecation warning. Per-repo
cleanup (Step 4 of the plan) renames every repo's .file-size.yml to
.github/file-size.yml in batched PRs.

What this does NOT do
---------------------
- No deletion of _file-size.yml in JacobPEvans-personal/.github yet -
  that's atomic-after consumer flips. Sequence: (1) this PR lands here;
  (2) follow-up PRs flip every `uses: JacobPEvans-personal/.github/...
  /_file-size.yml@main` reference to `uses: dryvist/.github/.../
  file-size.yml@main`; (3) once `gh code-search` confirms zero remaining
  references, delete the old workflow in JacobPEvans-personal/.github.
- No ruleset binding yet - Step 3 of the plan adds
  github_organization_ruleset.org_file_size_check in terraform-github,
  which will inject this workflow into every dryvist repo's PRs without
  any per-repo caller.

Verification
------------
- shellcheck .github/scripts/file-size-check.sh -> green
- markdownlint-cli2 CLAUDE.md -> 0 errors
- yq parses .github/file-size-defaults.yml and the workflow file -> green

Assisted-by: Claude <noreply@anthropic.com>
@JacobPEvans-personal
Copy link
Copy Markdown
Member Author

Closing per direction: file-size enforcement is a native GitHub feature (max_file_size and file_extension_restriction push rules in github_organization_ruleset). A custom workflow + script for this is the wrong answer — the right answer is to add the push rule in terraform-github, which deploys to GitHub. The migrated _file-size.yml should not have been ported at all; it should be deleted from JacobPEvans-personal/.github and not recreated here.

Follow-up moves:

  • terraform-github gets a new org_push_protection ruleset with max_file_size + file_extension_restriction (Step 1 of the parent plan), source-of-truth in config/rulesets-defaults.yml.
  • JacobPEvans-personal/.github/.github/workflows/_file-size.yml gets deleted once consumers stop calling it.
  • dryvist/.github/CLAUDE.md cleanup (extract content to a new AGENTS.md, leave CLAUDE.md as @AGENTS.md) belongs in its own PR, not this one.

Sorry for the rework — three lessons saved as agent memories for future sessions: file-size is native, no magic numbers / org names in code, CLAUDE.md is always a pointer to AGENTS.md.

@JacobPEvans-personal JacobPEvans-personal deleted the feat/migrate-file-size-from-jp-personal branch May 30, 2026 23:24
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.

1 participant