Skip to content
Draft
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
35 changes: 16 additions & 19 deletions crates/aspect-cli/src/builtins/aspect/lib/format_results.axl
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,17 @@ load(
)
load("./repro_commands.axl", "patch_download_cmd")
load("./result_text.axl", "emoji_for_status")
load("./text.axl", "pluralize")

# ─── Constants ────────────────────────────────────────────────────────────────

_DETAILS_LIMIT = 65000 # GitHub check-run `output.text` hard limit
_FILES_LIMIT = 200 # max files listed in the details body before truncating

# Default --scope arg value (mirrors format.axl). The Configuration row
# suppresses `Scope: <default>` because it adds no signal — only a
# user-chosen non-default scope is worth surfacing.
_DEFAULT_SCOPE = "changed"

# ─── Public API ───────────────────────────────────────────────────────────────

def init_data():
Expand Down Expand Up @@ -232,31 +236,24 @@ def _config_items(data):
"""Build the Configuration row for the format summary.

Surfaces the run-shape knobs directly above "Last update":
- Scope: always shown (`changed` is the default; `all` is the
whole-tree variant — the choice meaningfully changes what the
formatter touches and the changed-files preamble in the body
only signals the changed-scope path, so make the actual scope
explicit at-a-glance). When `scope == "changed"` and the task
recorded the post-ignore-pattern file count, append it as
" — filtered to N changed files" — analogous to lint's
"Strategy: hold-the-line — filtered to N changed files".
("changed files" is OK here because the "filtered to" prefix
makes it clear these are files in the change set, not files
we modified.)
- Scope: only shown when the user picked a non-default value
(default is `_DEFAULT_SCOPE`); `all` is the whole-tree variant
and is worth calling out at-a-glance. The default-scope file
count is already surfaced in the body's "All N files in scope
are properly formatted" line, so suppressing the default here
avoids duplicating that signal.
- Soft-fail: only shown when True. The default is False and
showing `Soft-fail: false` on every clean run would be noise;
the flag's whole purpose is to flag CI-bypass mode, so it
should stand out when set.
"""
items = []
scope = data["format"].get("scope", "") or ""
if scope:
value = scope
if scope == "changed":
count = data.get("changed_files_count", 0) or 0
if count > 0:
value = "%s — filtered to %s" % (scope, pluralize(count, "changed file"))
items.append({"key": "Scope", "value": value})
if scope and scope != _DEFAULT_SCOPE:
# The default-scope ("changed") count-suffix path is unreachable
# here — only `--scope=all` ever reaches this branch — so the
# value is the raw scope name.
items.append({"key": "Scope", "value": scope})
if data["format"].get("on_change_resolved") == "warn":
items.append({"key": "On-change", "value": "warn"})
return items
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@ Run with:

Scenarios:
1. clean-passed — no files need formatting
2. files-need-format — 3 files need formatting (scope=changed)
3. scope-all-many — 15 files need formatting (scope=all)
2. files-need-format — 3 files need formatting (default scope=changed)
3. scope-all-many — 15 files need formatting (non-default scope=all)
4. on-change-warn — files need formatting, --on-change=warn; exits 0
5. formatter-error — formatter binary crashed
6. no-git — no initial commit / not in git repo
7. no-files-to-format — scope=changed, no changed files found
8. with-patch-url — patch artifact uploaded; check run shows download link
9. non-default-target — custom formatter target label in repro command
10. large — 250 files to exercise the trim cascade

The Scope Configuration row only renders for non-default scope —
scenario 3 (scope=all) and 10 (scope=all). All other scenarios use
the default scope=changed and omit the row.
"""

load("./format_results.axl", "init_data", "render_check_output")
Expand Down Expand Up @@ -68,7 +72,9 @@ def _make_files_need_format():

# changed_files_count is the input set the formatter saw (post-ignore-pattern);
# affected_files is the post-format diff (what the formatter rewrote).
# Both populated to exercise the Scope-with-count Configuration row.
# Default scope (`changed`) — the Scope Configuration row is
# suppressed; changed_files_count surfaces in the body's
# "All N files in scope are properly formatted" line.
r["changed_files_count"] = 42
r["format"]["affected_files"] = [
"apps/web/src/auth/login.ts",
Expand Down
16 changes: 11 additions & 5 deletions crates/aspect-cli/src/builtins/aspect/lib/gazelle_results.axl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ load("./text.axl", "pluralize")
_DETAILS_LIMIT = 65000
_FILES_LIMIT = 200

# Default --scope arg value (mirrors gazelle.axl). The Configuration row
# suppresses `Scope: <default>` because it adds no signal — only a
# user-chosen non-default scope is worth surfacing.
_DEFAULT_SCOPE = "all"

# ─── Public API ───────────────────────────────────────────────────────────────

def init_data():
Expand Down Expand Up @@ -290,10 +295,11 @@ def _config_items(data):
"""Build the Configuration row for the gazelle summary.

Surfaces the run-shape knobs directly above "Last update":
- Scope: always shown. When `scope == "changed"` and the task
recorded a non-zero post-intersection effective-dir count,
append it as ` — N changed dirs` so reviewers can tell at a
glance how many subtrees gazelle was asked to update.
- Scope: only shown when the user picked a non-default value
(default is `_DEFAULT_SCOPE`). When `scope == "changed"` and
the task recorded a non-zero post-intersection effective-dir
count, append it as ` — N changed dirs` so reviewers can tell
at a glance how many subtrees gazelle was asked to update.
- Soft-fail: only shown when True. Default is False; rendering
`Soft-fail: false` on every clean run would be noise.
- Scope-all-on-change: only when `scope == "changed"` and the
Expand All @@ -308,7 +314,7 @@ def _config_items(data):
items = []
g = data["gazelle"]
scope = g.get("scope", "") or ""
if scope:
if scope and scope != _DEFAULT_SCOPE:
value = scope
if scope == "changed":
dirs_count = len(g.get("dirs", []) or [])
Expand Down
16 changes: 11 additions & 5 deletions crates/aspect-cli/src/builtins/aspect/lib/gazelle_results_test.axl
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@ Scenarios:
10. in-progress — task still running (initial state)
11. metadata-all — GitHubStatusChecksTrait.metadata_keys = ["*"]
12. early-fail — early-bail before gazelle ran
13. scope=changed — Configuration row with Scope + default escalation list
14. scope=changed full — all four Config rows fire (Scope, On-change, escalate, pattern)
15. scope=changed empty — no-op short-circuit, dirs=[]
13. scope=changed — non-default scope: Scope row + default escalation list
14. scope=changed full — non-default scope: all four Config rows fire
15. scope=changed empty — non-default scope, no-op short-circuit, dirs=[]

(Scenarios 1-12 use the default scope=all and therefore omit the
Scope Configuration row entirely — that's the default-suppression
path. 13-15 exercise the non-default rendered path.)
"""

load("./gazelle_results.axl", "init_data", "render_check_output")
Expand Down Expand Up @@ -231,8 +235,10 @@ def _test_impl(ctx):
# entrypoint resolution failed). Title and body must say "Failed",
# NOT "Passed" / "All BUILD files are up to date."
("12. early-fail · GH", _make_early_fail(), "failed", "github", None),
# Scope=changed configs: surface Scope row + Scope-all-on-change
# + (when set) Changed-file-pattern + Soft-fail.
# Non-default --scope=changed: surfaces the Scope Configuration
# row + Scope-all-on-change + (when set) Changed-file-pattern.
# (All earlier scenarios use the default scope=all and therefore
# omit the Scope row — that's the default-suppression path.)
("13. scope=changed default · GH", _make_scope_changed(), "failed", "github", None),
("14. scope=changed full config · GH", _make_scope_changed_with_filter(), "failed", "github", None),
("15. scope=changed empty no-op · GH", _make_scope_changed_empty(), "passed", "github", None),
Expand Down