Skip to content

Add per-tip identity, surface, and combine controls + tip_suggestion hook#1202

Merged
gregmagolan merged 1 commit into
mainfrom
custom-links-tip-example
Jun 4, 2026
Merged

Add per-tip identity, surface, and combine controls + tip_suggestion hook#1202
gregmagolan merged 1 commit into
mainfrom
custom-links-tip-example

Conversation

@gregmagolan
Copy link
Copy Markdown
Member

@gregmagolan gregmagolan commented Jun 3, 2026

Adds per-tip control over identity, which status screens a tip renders on, and how same-tips from different tasks combine in the PR summary, plus a hook to intercept tip creation.

Identity — (id, key)

A tip is identified by (id, key):

  • id — the tip kind + silence key. --tips:silence=<id> (and the silence feature arg) match on id, so silencing one id covers every key under it.
  • key — optional discriminator (default ""). Same id, different key ⇒ distinct tips that coexist on a task's surface and as separate PR-summary rows. Use it for "same tip kind, different subject" (e.g. one flaky-test tip per failing target, all silenceable with --tips:silence=flaky-test).

A re-emit of the same (id, key) within a task replaces the stored tip; accumulate fields union (deduped + sorted) onto the prior.

Inputs — vars vs accumulate

  • vars — fixed scalars: str.format-interpolated for TIP_TEMPLATE_FORMAT, exposed as scalars to TIP_TEMPLATE_JINJA2 templates.
  • accumulate — list-valued JINJA2 fields: a template sees {{ name }} as a deduped + sorted list; values union on re-emit and (when combine_across_tasks) across tasks.

A name set in both is an error.

Surfaces

A surfaces allowlist names the screens a tip may render on: SURFACE_CLI, SURFACE_GITHUB_STATUS_CHECKS, SURFACE_BUILDKITE_ANNOTATIONS, SURFACE_GITLAB_COMMIT_STATUSES, SURFACE_GITHUB_PR_SUMMARY (or the TASK_SCREENS / AGGREGATE_SCREENS / SURFACE_ALL shorthands; empty ⇒ all). collect_tips_sorted(ctx, surface=…) filters via the shared tip_shows_on predicate; the CLI print is gated on SURFACE_CLI. Omitting SURFACE_GITHUB_PR_SUMMARY keeps a tip off the cross-task rollup.

Cross-task combination — combine_across_tasks

For same-(id, key) tips from sibling tasks in the PR summary:

  • True — union the accumulate fields across every task into one row (e.g. every scope every task was missing).
  • False (default) — one row with the latest task's content (identical content across tasks is attributed to all of them).

The built-in add-github-token-scope tip sets combine_across_tasks to union scopes/endpoints across tasks.

tip_suggestion hook

A TipsTrait.tip_suggestion hook fires on every add_tip, receives a TipInfo, and returns TIP_ACCEPT / TIP_REJECT / tip_replace(...) — letting config.axl veto or rewrite any tip (suppress an id, downgrade a severity, re-scope surfaces). Same accept/reject/replace shape as the existing repro_fix_suggestion hook.


Changes are visible to end-users: yes

  • Searched for relevant documentation and updated as needed: yes
  • Breaking change (forces users to change their own code or config): no

Suggested release notes

  • Tips gain (id, key) identity (distinct keys coexist; silencing is by id), a surfaces allowlist controlling which status screens render a tip, a combine_across_tasks flag controlling cross-task PR-summary union, separate vars (fixed) / accumulate (list-valued) template inputs, and a tip_suggestion hook on TipsTrait to accept / reject / rewrite any tip from .aspect/config.axl.

Test plan

  • New / updated test cases:
    • tips_test.axl(id, key) identity (re-emit replaces; distinct key coexists; silence-by-id across keys); within-task accumulate union (seed / merge / dedup / partial-overlap); vars + accumulate mix and vars-only JINJA2 re-emit; surfaces / combine_across_tasks storage + defaults; emit_tip template-vs-arg precedence; tip_shows_on; per-surface collect filter; tip_to_payload; the tip_suggestion hook (accept / reject / reject-by-id / replace / chain short-circuit).
    • github_status_comments_test.axl — surface gate; (id, key) grouping; combine_across_tasks union; latest-wins (identical → all tasks, divergent → latest); distinct-key separate rows; combine-if-any-contributor-opts-in.
  • Covered by existing test cases: tips / PR-comment / Buildkite-annotation / bazel-results / lint / format / gazelle / delivery / GitLab suites pass.

@aspect-workflows
Copy link
Copy Markdown

aspect-workflows Bot commented Jun 3, 2026

✨ Aspect Workflows Tasks

📅 Thu Jun 4 19:57:50 UTC 2026

⚠️ 2 flagged tasks

  • ⚠️ delivery (delivery-gha-debug) · ⏱ 42.4s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Delivery complete (2 warn · 3 skipped)
  • ⚠️ delivery (delivery-gha) · ⏱ 38.1s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Delivery complete (2 warn · 3 skipped)

✅ 14 successful tasks

  • ✅ build (build-gha-debug) · ⏱ 1m 22s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel build complete (164 built)
  • ✅ build (build-gha) · ⏱ 1m 18s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel build complete (164 built)
  • ✅ buildifier (buildifier-gha-debug) · ⏱ 36.4s · 🐙 GitHub Actions · ☑️ Check
    💬 Format complete (clean)
  • ✅ buildifier (buildifier-gha) · ⏱ 49s · 🐙 GitHub Actions · ☑️ Check
    💬 Format complete (clean)
  • ✅ format (format-gha-debug) · ⏱ 1m 27s · 🐙 GitHub Actions · ☑️ Check
    💬 Format complete (clean)
  • ✅ format (format-gha) · ⏱ 1m 23s · 🐙 GitHub Actions · ☑️ Check
    💬 Format complete (clean)
  • ✅ gazelle (gazelle-gha-debug) · ⏱ 36.4s · 🐙 GitHub Actions · ☑️ Check
    💬 Gazelle complete (clean)
  • ✅ gazelle (gazelle-from-source-gha-debug) · ⏱ 1m 36s · 🐙 GitHub Actions · ☑️ Check
    💬 Gazelle complete (clean)
  • ✅ gazelle (gazelle-from-source-gha) · ⏱ 2m 12s · 🐙 GitHub Actions · ☑️ Check
    💬 Gazelle complete (clean)
  • ✅ gazelle (gazelle-gha) · ⏱ 35.6s · 🐙 GitHub Actions · ☑️ Check
    💬 Gazelle complete (clean)
  • ✅ lint (lint-gha-debug) · ⏱ 43.3s · 🐙 GitHub Actions · ☑️ Check
    💬 Lint complete (clean)
  • ✅ lint (lint-gha) · ⏱ 37.7s · 🐙 GitHub Actions · ☑️ Check
    💬 Lint complete (clean)
  • ✅ test (test-gha-debug) · ⏱ 1m 16s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (25/25 passed · 25 cached)
  • ✅ test (test-gha) · ⏱ 1m 31s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (25/25 passed · 25 cached)

🔁 Reproduce

⚠️ delivery (delivery-gha-debug · delivery-gha)

# --mode=always --track-state=false for off-runner with no state backend.
aspect delivery --mode=always --track-state=false --dry-run=true

Install aspect: docs.aspect.build/cli/install


⏱ Last updated Thu Jun 4 20:00:50 UTC 2026 · 📊 GitHub API quota 4,309/15,000 (29% used, resets in 13m)
🚀 Powered by Aspect CLI (v0.0.0-dev)  |  Aspect Build · X · LinkedIn · YouTube

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d24d4ed3f9

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread .aspect/config.axl Outdated
@gregmagolan gregmagolan changed the title Add example custom click-through-links tip via task_update Add example custom task_update tip registered in config.axl Jun 3, 2026
@gregmagolan gregmagolan changed the title Add example custom task_update tip registered in config.axl Add per-tip surface allowlist + PR-summary aggregation policy Jun 3, 2026
@gregmagolan gregmagolan force-pushed the custom-links-tip-example branch 4 times, most recently from 0066317 to f9a5506 Compare June 4, 2026 03:36
@gregmagolan gregmagolan force-pushed the custom-links-tip-example branch 2 times, most recently from ec1d98d to 91c1102 Compare June 4, 2026 04:16
@gregmagolan gregmagolan changed the title Add per-tip surface allowlist + PR-summary aggregation policy Add per-tip repeat / surface / aggregation policies for tips Jun 4, 2026
@gregmagolan gregmagolan force-pushed the custom-links-tip-example branch from 91c1102 to 2f08e20 Compare June 4, 2026 13:56
@gregmagolan gregmagolan changed the title Add per-tip repeat / surface / aggregation policies for tips Add tip repeat / surface / aggregation policies + tip_suggestion hook Jun 4, 2026
@gregmagolan gregmagolan force-pushed the custom-links-tip-example branch 2 times, most recently from 308fa88 to 4848631 Compare June 4, 2026 19:31
@gregmagolan gregmagolan changed the title Add tip repeat / surface / aggregation policies + tip_suggestion hook Add per-tip identity, surface, and combine controls + tip_suggestion hook Jun 4, 2026
…suggestion hook

Reworks the tips framework around a small, orthogonal set of controls.

Identity: a tip is `(id, key)`. `id` is the kind + silence key
(`--tips:silence=<id>` covers every key); an optional `key` makes
same-`id` tips distinct so "same tip, different subject" coexists as
separate rows. A re-emit of the same `(id, key)` replaces the stored tip,
with `accumulate` fields unioned (deduped + sorted) onto the prior.

Inputs: `vars` are fixed scalars (FORMAT interpolation / JINJA2
constants); `accumulate` are list-valued JINJA2 fields that union on
re-emit and, when `combine_across_tasks`, across tasks. A name in both is
an error.

Surfaces: a `surfaces` allowlist (SURFACE_CLI / _GHSC / _BK / _GITLAB /
_PR_SUMMARY, plus TASK_SCREENS / AGGREGATE_SCREENS / SURFACE_ALL
shorthands; empty = all) gates which screens render a tip, via the shared
`tip_shows_on` predicate; the CLI print is gated on SURFACE_CLI. Omitting
SURFACE_PR_SUMMARY keeps a tip off the rollup.

PR summary: same-`(id, key)` tips combine by `combine_across_tasks` —
True unions `accumulate` across tasks into one row; False shows the
latest task's content (identical content across tasks is attributed to
all). The built-in add-github-token-scope tip sets combine_across_tasks.

tip_suggestion hook: a `TipsTrait.tip_suggestion` hook fires on every
add_tip with a TipInfo and returns TIP_ACCEPT / TIP_REJECT /
tip_replace(...), letting config.axl veto or rewrite any tip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gregmagolan gregmagolan force-pushed the custom-links-tip-example branch from 4848631 to cfd81b2 Compare June 4, 2026 19:55
@gregmagolan gregmagolan merged commit 8a34329 into main Jun 4, 2026
36 checks passed
@gregmagolan gregmagolan deleted the custom-links-tip-example branch June 4, 2026 20:17
gregmagolan added a commit that referenced this pull request Jun 4, 2026
A worked example of the per-tip `surfaces` controls added in #1202: a
custom `suggestion` tip that surfaces click-through links on every
build/test task.

Registered inline in `config(ctx)` by subscribing to the `task_update`
lifecycle event — no new framework hook. The handler reads three links
off each `TaskUpdate` the way the built-in surfaces do and shows
whichever it knows, one per line in the built-in metadata-row style:

```
✨ Aspect Web UI — invocation details, test logs, build logs, and timing
🔗 BES results
🐙 GitHub Actions — raw CI logs for this job
```

- **Aspect Web UI** — `aspect_web_ui_url(env, data)`
(`sink_invocation_id` joined onto `ASPECT_WORKFLOWS_BES_RESULTS_URL`).
- **BES results** — `render_bes_url` (Bazel's `invocation_id` +
`bes_results_url`).
- **CI build** — `detect_build_url` + the per-host icon/label from
`detect_ci_host` (🐙 GitHub Actions, ⭕ CircleCI, 🏗 Buildkite, 🦊 GitLab
CI).

Each emit rebuilds the full body from whatever links have resolved and
re-adds the tip under a stable id; the default last-emit-wins replace
overwrites the prior tip in place, so it grows as links appear across
separate `task_update` emits. `surfaces = TASK_SCREENS` keeps these
per-invocation links off the cross-task PR summary.

It calls the single `add_tip(ctx, id=…, severity=…, type=…, surfaces=…,
title=…, body=…)` producer API (from #1209) — the example was updated
alongside the API collapse from `emit_tip(ctx, {…})` to a single
named-arg `add_tip`.

Stacked on #1209 (`tips-public-facades`); the diff is
`.aspect/config.axl` only once that lands.

---

### Changes are visible to end-users: no

<!-- example config in this repo's own .aspect/, not a shipped @aspect
builtin -->

- Searched for relevant documentation and updated as needed: yes
- Breaking change (forces users to change their own code or config): no

### Test plan

- Manual: `ASPECT_CLI_TESTING=github_status_checks aspect build
//examples/lint/...` surfaces the tip with the GitHub Actions link bar,
deduped across the build's `task_update` emits; `buildifier` clean.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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