Skip to content

ci: fix the Sonar gate, make the PR comment sticky, cancel superseded runs - #323

Merged
DerekCorniello merged 4 commits into
mainfrom
ci/pipeline-hygiene
Jul 31, 2026
Merged

ci: fix the Sonar gate, make the PR comment sticky, cancel superseded runs#323
DerekCorniello merged 4 commits into
mainfrom
ci/pipeline-hygiene

Conversation

@DerekCorniello

Copy link
Copy Markdown
Collaborator

Part of the CI/CD rework (step 2 of the plan). Mechanical and independent of the
other six repo PRs in this batch - mergeable in any order.

What changes

Stop double-labelling new issues (muxlang/mux-context#19). issue-triage.yml
applied needs triage unconditionally on every issues: opened, but all 15 issue
templates org-wide already set the label in their frontmatter, so the workflow
call was pure duplication. The file is byte-identical across 7 repos, so this same
diff lands in each.

ensureLabel is deliberately kept, and there is a comment saying why: GitHub
silently drops a label a template references if it does not exist in the repo, so
that call is what creates it. Removing both would quietly stop templates labelling
anything. Auto-assign and the documentation heuristic are untouched.

Cancel superseded PR runs. No concurrency group existed, so pushing three
commits in a row ran three full pipelines at once.

cancel-in-progress is scoped to pull requests rather than set to a blunt true:
cancelling a push to main would discard the authoritative run for that commit.

Verification

All workflow files in the repo still parse as valid YAML and remain ASCII-only.

Fix the Sonar gate's blind spot. The "Fail on new SonarCloud issues" step
ended its jq with // "0", so a well-formed response carrying no measures read
as zero issues and passed - the gate could not tell "nothing was analyzed" from
"nothing was wrong". This ports the api/issues/search shape the other six repos
already use: .total is always present, a retry loop rides out indexing lag, and
a count that stays unreadable fails closed.

Make the PR report comment sticky. pr-comment.yml ended in gh pr comment,
which creates a new comment on every push - #317 has two
report comments from two pushes, and a 20-push PR would have twenty. It now
embeds a hidden <!-- mux-ci-report --> marker and updates its own comment in
place.

The lookup filters on the marker and github-actions[bot] authorship. That
second condition is load-bearing: anyone can post a comment containing the
marker, and only a bot-authored comment is ours to overwrite. Verified the
selector against real API data on #317 and #318.

Colour the valgrind pie chart. It emitted bare pie showData, so mermaid
used its default blue/purple palette (muxlang/mux-context#27). Now green for
clean, red for leaking, via a themeVariables init directive.

Stop the chart vanishing silently. emit_valgrind_pie returned early
whenever the log did not match its expected shape, so a format change would drop
the chart with no indication. It now says so in the comment. Both notes are
trusted literals, so the injection model in the file header is preserved.

Note: this workflow is workflow_run-triggered, so it only takes effect from the
copy on main - this PR cannot demonstrate its own change. Worth a look on the
next PR after merge. Existing comments have no marker, so the first run after
merge creates one fresh comment and updates that one thereafter.

🤖 Generated with Claude Code

… runs

- issue-triage: drop the unconditional `needs triage` application. Every
  issue template already sets the label in its frontmatter, so this was pure
  duplication. ensureLabel stays deliberately: GitHub silently drops a template
  label that does not exist in the repo, so that call is what creates it.

- add a concurrency group so a newer push supersedes an in-flight PR run.
  A push to main is never cancelled - that run is the authoritative record for
  the commit.

- build: the "Fail on new SonarCloud issues" gate ended its jq with `// "0"`,
  so a well-formed response carrying no measures read as zero issues and
  passed. Port the api/issues/search shape the other six repos already use:
  .total is always present, retries ride out indexing lag, and a count that
  stays unreadable fails closed.

- pr-comment: update our own report comment in place instead of posting a new
  one on every push, matching on a hidden marker AND github-actions[bot]
  authorship so a comment anyone can forge is never overwritten. Colour the
  valgrind pie green/red rather than mermaid's default blue/purple, and say so
  in the comment when the log cannot be parsed instead of dropping the chart.
@DerekCorniello
DerekCorniello requested a review from a team as a code owner July 31, 2026 19:33
@greptile-apps

greptile-apps Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR revises issue triage and CI reporting behavior.

  • Cancels superseded PR builds while preserving push runs.
  • Queries SonarCloud issues with retries and fails closed on unreadable responses.
  • Recovers a missing triage label after label creation races.
  • Serializes PR report updates and reuses a bot-owned marker comment.
  • Adds explicit Valgrind chart colors and unavailable-chart notices.

Confidence Score: 4/5

The PR is not yet safe to merge because API-created issues can still bypass the needs triage label.

The triage workflow only calls applyLabelIfMissing when the repository label was initially absent; when that label already exists, an issue created without template frontmatter remains unlabeled and outside label-based triage queues.

Files Needing Attention: .github/workflows/issue-triage.yml

Important Files Changed

Filename Overview
.github/workflows/build.yml Adds PR-scoped build concurrency and replaces the Sonar measure lookup with a retried issues-search gate.
.github/workflows/issue-triage.yml Tracks whether the triage label was absent and conditionally restores it to the triggering issue.
.github/workflows/pr-comment.yml Serializes report workflows, updates a marker-owned comment in place, and improves Valgrind chart output.

Reviews (6): Last reviewed commit: "ci: serialize report runs so the sticky ..." | Re-trigger Greptile

Comment thread .github/workflows/issue-triage.yml Outdated
Comment thread .github/workflows/pr-comment.yml
Review catch. Dropping the unconditional apply left one real gap: when `needs
triage` does not exist yet, GitHub silently drops it from the opening issue's
template frontmatter, and `ensureLabel` creating the label afterwards does not
retroactively label the issue that triggered the run. That issue would sit
outside triage until labelled by hand.

Restoring the unconditional apply would undo the point of the change, so apply
it only on the run that actually created the label - the exact case where the
template's request was already dropped. `ensureLabel` now reports whether it
created the label; every later issue gets the label from its own template.
Two review catches, both real.

Label creation race: when two issues open concurrently before `needs triage`
exists, both runs see it missing, one creates it and the other gets 422. The
losing run returned false and skipped the recovery apply - but its issue also
had the template label dropped, so it stayed outside triage. The meaningful
signal is "the label was absent when this run looked", not "this run won the
create race", so ensureLabel now reports that instead.

Pending-run eviction: a shared concurrency group keeps only ONE pending run and
cancels any earlier one, and that happens regardless of cancel-in-progress -
it applies to queued runs, not in-flight ones. Scoping cancel-in-progress to
pull requests therefore did not protect main: three rapid pushes would evict
the middle commit's queued run before it ever executed. Push runs now get a
unique group keyed on run_id, so they never share one and never displace each
other; PR runs still supersede by PR number.
Review catch. The sticky-comment update is a lookup-then-create, and this
workflow had no concurrency control: two Build runs completing close together
for the same PR could both find no marker and both post, producing exactly the
duplicate comments the marker exists to prevent.

GitHub has no atomic comment upsert, so serializing per PR is what makes the
pair safe. The group is keyed on the trusted workflow_run head repository and
branch, since the PR number is not resolved until a step inside the job.

cancel-in-progress stays false so an in-flight post is never killed midway. A
queued run can still be superseded, which is the behaviour we want here: the
newest report is the one worth posting.
@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown

Valgrind Memory Checks - PASSED

pie showData
    title Leg A: compiled programs under Valgrind (113 total)
    "Clean" : 113
    "Leaking" : 0
Loading
Full valgrind output (last 300 lines)
�[1m�[92m   Compiling�[0m futures-channel v0.3.32
�[1m�[92m   Compiling�[0m webpki-roots v1.0.7
�[1m�[92m   Compiling�[0m async-trait v0.1.89
�[1m�[92m   Compiling�[0m derive_utils v0.15.1
�[1m�[92m   Compiling�[0m btoi v0.5.0
�[1m�[92m   Compiling�[0m phf_shared v0.11.3
�[1m�[92m   Compiling�[0m whoami v2.1.2
�[1m�[92m   Compiling�[0m httparse v1.10.1
�[1m�[92m   Compiling�[0m colorchoice v1.0.5
�[1m�[92m   Compiling�[0m subtle v2.6.1
�[1m�[92m   Compiling�[0m mysql v28.0.0
�[1m�[92m   Compiling�[0m paste v1.0.15
�[1m�[92m   Compiling�[0m uuid v1.23.1
�[1m�[92m   Compiling�[0m anstyle v1.0.14
�[1m�[92m   Compiling�[0m is_terminal_polyfill v1.70.2
�[1m�[92m   Compiling�[0m saturating v0.1.0
�[1m�[92m   Compiling�[0m anstyle-query v1.1.5
�[1m�[92m   Compiling�[0m anstream v1.0.0
�[1m�[92m   Compiling�[0m tokio-postgres v0.7.18
�[1m�[92m   Compiling�[0m phf_generator v0.11.3
�[1m�[92m   Compiling�[0m io-enum v1.2.1
�[1m�[92m   Compiling�[0m webpki-roots v0.26.11
�[1m�[92m   Compiling�[0m hashlink v0.9.1
�[1m�[92m   Compiling�[0m crossbeam-queue v0.3.12
�[1m�[92m   Compiling�[0m pem v3.0.6
�[1m�[92m   Compiling�[0m csv-core v0.1.13
�[1m�[92m   Compiling�[0m fallible-streaming-iterator v0.1.9
�[1m�[92m   Compiling�[0m lru v0.16.4
�[1m�[92m   Compiling�[0m inkwell v0.9.0
�[1m�[92m   Compiling�[0m iana-time-zone v0.1.65
�[1m�[92m   Compiling�[0m clap_lex v1.1.0
�[1m�[92m   Compiling�[0m ryu v1.0.23
�[1m�[92m   Compiling�[0m twox-hash v2.1.2
�[1m�[92m   Compiling�[0m bufstream v0.1.4
�[1m�[92m   Compiling�[0m fallible-iterator v0.3.0
�[1m�[92m   Compiling�[0m rusqlite v0.31.0
�[1m�[92m   Compiling�[0m ureq v2.12.1
�[1m�[92m   Compiling�[0m csv v1.4.0
�[1m�[92m   Compiling�[0m clap_builder v4.6.0
�[1m�[92m   Compiling�[0m chrono v0.4.44
�[1m�[92m   Compiling�[0m postgres v0.19.13
�[1m�[92m   Compiling�[0m mux-lang v0.6.0 (/home/runner/work/mux-compiler/mux-compiler/mux-compiler)
�[1m�[92m   Compiling�[0m phf_macros v0.11.3
�[1m�[92m   Compiling�[0m clap_derive v4.6.1
�[1m�[92m   Compiling�[0m inkwell_internals v0.14.0
�[1m�[92m   Compiling�[0m ordered-float v4.6.0
�[1m�[92m   Compiling�[0m phf v0.11.3
�[1m�[92m   Compiling�[0m mux-runtime v0.5.0 (https://github.com/muxlang/mux-runtime?branch=main#4e2dc14b)
�[1m�[92m   Compiling�[0m unicode-width v0.1.14
�[1m�[92m   Compiling�[0m clap v4.6.1
�[1m�[92m    Finished�[0m `dev` profile [unoptimized + debuginfo] target(s) in 51.62s

=== Leg A: compiled programs under Valgrind ===
  PASS  arithmetic.mux
  PASS  builtin_collection_methods.mux
  PASS  class_field_defaults.mux
  PASS  class_method_params.mux
  PASS  closure_captured_increment.mux
  PASS  collections.mux
  PASS  constmath.mux
  PASS  control_flow.mux
  PASS  counter.mux
  PASS  csv_test.mux
  PASS  empty_map_literal.mux
  PASS  enum_c_style.mux
  PASS  enum_collection_keys.mux
  PASS  enum_collection_payloads.mux
  PASS  enum_copy_deep_clone.mux
  PASS  enum_discard_release.mux
  PASS  enum_field_deep_clone.mux
  PASS  enum_in_collections.mux
  PASS  enum_mixed_types.mux
  PASS  enum_named_fields.mux
  PASS  enum_nested_heterogeneous.mux
  PASS  enum_nested_mutual.mux
  PASS  enum_nested_payload.mux
  PASS  enum_nested_recursive.mux
  PASS  enum_nested_recursive_rc.mux
  PASS  enum_reassign_rebind.mux
  PASS  enum_recursive_class_field.mux
  PASS  enum_return_by_value.mux
  PASS  enum_ternary_deep_clone.mux
  PASS  enums_classes.mux
  PASS  env_get.mux
  PASS  field_compound_assignment.mux
  PASS  field_default_expressions.mux
  PASS  forward_ref.mux
  PASS  functions.mux
  PASS  generic_classes.mux
  PASS  generic_methods.mux
  PASS  generic_params.mux
  PASS  generic_static_import_context_lib.mux
  PASS  generic_static_import_context_main.mux
  PASS  generics.mux
  PASS  global_scope.mux
  PASS  if_expression_branches.mux
  PASS  issue231_enum_for_match.mux
  PASS  issue232_trailing_comma.mux
  PASS  issue233_match_side_effects.mux
  PASS  issue234_match_trailing_stmt.mux
  PASS  json_nan_inf_test.mux
  PASS  json_test.mux
  PASS  list_negative_index.mux
  PASS  logger.mux
  PASS  logical_operators.mux
  PASS  match_binding_shadow.mux
  PASS  match_switch.mux
  PASS  modglobal_a.mux
  PASS  modglobal_b.mux
  PASS  modglobal_c.mux
  PASS  modglobal_d.mux
  PASS  modglobal_e.mux
  PASS  nested_generics.mux
  PASS  nested_typed_collections.mux
  PASS  optionals_results.mux
  PASS  recursivemod.mux
  PASS  references.mux
  PASS  string_length.mux
  PASS  test_all_comparisons.mux
  PASS  test_assert.mux
  PASS  test_bintree_full.mux
  PASS  test_closures.mux
  PASS  test_collection_concat.mux
  PASS  test_datetime.mux
  PASS  test_imports.mux
  PASS  test_in_operator.mux
  PASS  test_main_self_call_nested.mux
  PASS  test_main_self_call_top_level.mux
  PASS  test_math.mux
  PASS  test_module_aliased_constant_teardown.mux
  PASS  test_module_class_globals.mux
  PASS  test_module_constants.mux
  PASS  test_module_global_scoping.mux
  PASS  test_module_nonmain_imports.mux
  PASS  test_module_renamed_constant.mux
  PASS  test_module_transitive_import.mux
  PASS  test_module_wildcard_constants.mux
  PASS  test_nested_field.mux
  PASS  test_nested_functions.mux
  PASS  test_optional_is_some.mux
  PASS  test_recursive_module.mux
  PASS  test_result_is_ok_err.mux
  PASS  test_result_type_unification.mux
  PASS  test_std_dsa.mux
  PASS  test_std_http.mux
  PASS  test_std_http_server.mux
  PASS  test_std_import_duplicate_flat_then_specific.mux
  PASS  test_std_import_duplicate_repeated_wildcard.mux
  PASS  test_std_import_duplicate_root_and_module_wildcard.mux
  PASS  test_std_imports.mux
  PASS  test_std_io.mux
  PASS  test_std_math.mux
  PASS  test_std_random.mux
  PASS  test_std_sql_sqlite.mux
  PASS  test_std_sync.mux
  PASS  test_std_tcp.mux
  PASS  test_std_udp.mux
  PASS  test_to_char.mux
  PASS  test_to_list.mux
  PASS  test_traits.mux
  PASS  tuple_test.mux
  PASS  utils.mux
  PASS  value_semantics_copy_vs_ref.mux
  PASS  variables.mux
  PASS  void_lambda_test.mux
  PASS  where_clauses.mux

=== Leg A summary ===
  OK           arithmetic.mux
  OK           builtin_collection_methods.mux
  OK           class_field_defaults.mux
  OK           class_method_params.mux
  OK           closure_captured_increment.mux
  OK           collections.mux
  OK           constmath.mux
  OK           control_flow.mux
  OK           counter.mux
  OK           csv_test.mux
  OK           empty_map_literal.mux
  OK           enum_c_style.mux
  OK           enum_collection_keys.mux
  OK           enum_collection_payloads.mux
  OK           enum_copy_deep_clone.mux
  OK           enum_discard_release.mux
  OK           enum_field_deep_clone.mux
  OK           enum_in_collections.mux
  OK           enum_mixed_types.mux
  OK           enum_named_fields.mux
  OK           enum_nested_heterogeneous.mux
  OK           enum_nested_mutual.mux
  OK           enum_nested_payload.mux
  OK           enum_nested_recursive.mux
  OK           enum_nested_recursive_rc.mux
  OK           enum_reassign_rebind.mux
  OK           enum_recursive_class_field.mux
  OK           enum_return_by_value.mux
  OK           enum_ternary_deep_clone.mux
  OK           enums_classes.mux
  OK           env_get.mux
  OK           field_compound_assignment.mux
  OK           field_default_expressions.mux
  OK           forward_ref.mux
  OK           functions.mux
  OK           generic_classes.mux
  OK           generic_methods.mux
  OK           generic_params.mux
  OK           generic_static_import_context_lib.mux
  OK           generic_static_import_context_main.mux
  OK           generics.mux
  OK           global_scope.mux
  OK           if_expression_branches.mux
  OK           issue231_enum_for_match.mux
  OK           issue232_trailing_comma.mux
  OK           issue233_match_side_effects.mux
  OK           issue234_match_trailing_stmt.mux
  OK           json_nan_inf_test.mux
  OK           json_test.mux
  OK           list_negative_index.mux
  OK           logger.mux
  OK           logical_operators.mux
  OK           match_binding_shadow.mux
  OK           match_switch.mux
  OK           modglobal_a.mux
  OK           modglobal_b.mux
  OK           modglobal_c.mux
  OK           modglobal_d.mux
  OK           modglobal_e.mux
  OK           nested_generics.mux
  OK           nested_typed_collections.mux
  OK           optionals_results.mux
  OK           recursivemod.mux
  OK           references.mux
  OK           string_length.mux
  OK           test_all_comparisons.mux
  OK           test_assert.mux
  OK           test_bintree_full.mux
  OK           test_closures.mux
  OK           test_collection_concat.mux
  OK           test_datetime.mux
  OK           test_imports.mux
  OK           test_in_operator.mux
  OK           test_main_self_call_nested.mux
  OK           test_main_self_call_top_level.mux
  OK           test_math.mux
  OK           test_module_aliased_constant_teardown.mux
  OK           test_module_class_globals.mux
  OK           test_module_constants.mux
  OK           test_module_global_scoping.mux
  OK           test_module_nonmain_imports.mux
  OK           test_module_renamed_constant.mux
  OK           test_module_transitive_import.mux
  OK           test_module_wildcard_constants.mux
  OK           test_nested_field.mux
  OK           test_nested_functions.mux
  OK           test_optional_is_some.mux
  OK           test_recursive_module.mux
  OK           test_result_is_ok_err.mux
  OK           test_result_type_unification.mux
  OK           test_std_dsa.mux
  OK           test_std_http.mux
  OK           test_std_http_server.mux
  OK           test_std_import_duplicate_flat_then_specific.mux
  OK           test_std_import_duplicate_repeated_wildcard.mux
  OK           test_std_import_duplicate_root_and_module_wildcard.mux
  OK           test_std_imports.mux
  OK           test_std_io.mux
  OK           test_std_math.mux
  OK           test_std_random.mux
  OK           test_std_sql_sqlite.mux
  OK           test_std_sync.mux
  OK           test_std_tcp.mux
  OK           test_std_udp.mux
  OK           test_to_char.mux
  OK           test_to_list.mux
  OK           test_traits.mux
  OK           tuple_test.mux
  OK           utils.mux
  OK           value_semantics_copy_vs_ref.mux
  OK           variables.mux
  OK           void_lambda_test.mux
  OK           where_clauses.mux
  113 program(s), 0 failure(s)

=== Leg B: compiler under Valgrind (report-only) ===

>>> valgrind mux build test_scripts/arithmetic.mux
  clean: test_scripts/arithmetic.mux

>>> valgrind mux build test_scripts/collections.mux
  clean: test_scripts/collections.mux

>>> valgrind mux build test_scripts/test_std_dsa.mux
  clean: test_scripts/test_std_dsa.mux

=== Leg C: module-global still-reachable regression ===
  probe.mux   still reachable: 1024 bytes
  control.mux still reachable: 1024 bytes
  PASS: module globals add no still-reachable bytes over baseline.

Valgrind checks complete.

Benchmarks (report-only) - report-only

Informational only - shared runners are too noisy to gate on; full data is in the run artifacts.

xychart-beta
    title "Compile phases (median)"
    x-axis ["lex", "parse", "semantics", "codegen"]
    y-axis "microseconds"
    bar [13.4, 30.48, 98.73, 461]
Loading
xychart-beta
    title "Pipeline + execution (median)"
    x-axis ["pipeline", "execution"]
    y-axis "milliseconds"
    bar [0.6709, 61.66]
Loading
Phase Median Samples
lex 13.4 us 113
parse 30.5 us 113
semantics 98.7 us 113
codegen 461 us 113
pipeline 671 us 113
execution 61.7 ms 5
Full benchmark output (last 300 lines)
Found 2 outliers among 20 measurements (10.00%)
  1 (5.00%) high mild
  1 (5.00%) high severe
Benchmarking pipeline/test_module_renamed_constant
Benchmarking pipeline/test_module_renamed_constant: Warming up for 300.00 ms
Benchmarking pipeline/test_module_renamed_constant: Collecting 20 samples in estimated 1.0397 s (2520 iterations)
Benchmarking pipeline/test_module_renamed_constant: Analyzing
pipeline/test_module_renamed_constant
                        time:   [411.58 µs 412.47 µs 413.45 µs]
Found 3 outliers among 20 measurements (15.00%)
  2 (10.00%) high mild
  1 (5.00%) high severe
Benchmarking pipeline/test_module_transitive_import
Benchmarking pipeline/test_module_transitive_import: Warming up for 300.00 ms
Benchmarking pipeline/test_module_transitive_import: Collecting 20 samples in estimated 1.0387 s (1050 iterations)
Benchmarking pipeline/test_module_transitive_import: Analyzing
pipeline/test_module_transitive_import
                        time:   [992.33 µs 993.03 µs 993.60 µs]
Found 2 outliers among 20 measurements (10.00%)
  1 (5.00%) low mild
  1 (5.00%) high severe
Benchmarking pipeline/test_module_wildcard_constants
Benchmarking pipeline/test_module_wildcard_constants: Warming up for 300.00 ms
Benchmarking pipeline/test_module_wildcard_constants: Collecting 20 samples in estimated 1.0521 s (2310 iterations)
Benchmarking pipeline/test_module_wildcard_constants: Analyzing
pipeline/test_module_wildcard_constants
                        time:   [455.77 µs 457.04 µs 458.25 µs]
Found 3 outliers among 20 measurements (15.00%)
  2 (10.00%) high mild
  1 (5.00%) high severe
Benchmarking pipeline/test_nested_field
Benchmarking pipeline/test_nested_field: Warming up for 300.00 ms
Benchmarking pipeline/test_nested_field: Collecting 20 samples in estimated 1.0107 s (1890 iterations)
Benchmarking pipeline/test_nested_field: Analyzing
pipeline/test_nested_field
                        time:   [532.32 µs 533.80 µs 535.78 µs]
Found 3 outliers among 20 measurements (15.00%)
  1 (5.00%) high mild
  2 (10.00%) high severe
Benchmarking pipeline/test_nested_functions
Benchmarking pipeline/test_nested_functions: Warming up for 300.00 ms
Benchmarking pipeline/test_nested_functions: Collecting 20 samples in estimated 1.1064 s (2100 iterations)
Benchmarking pipeline/test_nested_functions: Analyzing
pipeline/test_nested_functions
                        time:   [523.70 µs 524.37 µs 525.15 µs]
Found 1 outliers among 20 measurements (5.00%)
  1 (5.00%) high severe
Benchmarking pipeline/test_optional_is_some
Benchmarking pipeline/test_optional_is_some: Warming up for 300.00 ms
Benchmarking pipeline/test_optional_is_some: Collecting 20 samples in estimated 1.0106 s (1680 iterations)
Benchmarking pipeline/test_optional_is_some: Analyzing
pipeline/test_optional_is_some
                        time:   [599.68 µs 606.58 µs 615.12 µs]
Found 3 outliers among 20 measurements (15.00%)
  3 (15.00%) high severe
Benchmarking pipeline/test_recursive_module
Benchmarking pipeline/test_recursive_module: Warming up for 300.00 ms
Benchmarking pipeline/test_recursive_module: Collecting 20 samples in estimated 1.0394 s (1680 iterations)
Benchmarking pipeline/test_recursive_module: Analyzing
pipeline/test_recursive_module
                        time:   [616.43 µs 617.54 µs 619.18 µs]
Found 2 outliers among 20 measurements (10.00%)
  2 (10.00%) high severe
Benchmarking pipeline/test_result_is_ok_err
Benchmarking pipeline/test_result_is_ok_err: Warming up for 300.00 ms
Benchmarking pipeline/test_result_is_ok_err: Collecting 20 samples in estimated 1.0564 s (1680 iterations)
Benchmarking pipeline/test_result_is_ok_err: Analyzing
pipeline/test_result_is_ok_err
                        time:   [627.00 µs 627.75 µs 628.51 µs]
Found 2 outliers among 20 measurements (10.00%)
  1 (5.00%) high mild
  1 (5.00%) high severe
Benchmarking pipeline/test_result_type_unification
Benchmarking pipeline/test_result_type_unification: Warming up for 300.00 ms
Benchmarking pipeline/test_result_type_unification: Collecting 20 samples in estimated 1.0633 s (1050 iterations)
Benchmarking pipeline/test_result_type_unification: Analyzing
pipeline/test_result_type_unification
                        time:   [1.0093 ms 1.0127 ms 1.0193 ms]
Found 3 outliers among 20 measurements (15.00%)
  1 (5.00%) high mild
  2 (10.00%) high severe
Benchmarking pipeline/test_std_dsa
Benchmarking pipeline/test_std_dsa: Warming up for 300.00 ms
Benchmarking pipeline/test_std_dsa: Collecting 20 samples in estimated 1.1227 s (40 iterations)
Benchmarking pipeline/test_std_dsa: Analyzing
pipeline/test_std_dsa   time:   [27.696 ms 27.736 ms 27.779 ms]
Benchmarking pipeline/test_std_http
Benchmarking pipeline/test_std_http: Warming up for 300.00 ms
Benchmarking pipeline/test_std_http: Collecting 20 samples in estimated 1.1220 s (840 iterations)
Benchmarking pipeline/test_std_http: Analyzing
pipeline/test_std_http  time:   [1.3386 ms 1.3403 ms 1.3423 ms]
Found 3 outliers among 20 measurements (15.00%)
  2 (10.00%) low mild
  1 (5.00%) high mild
Benchmarking pipeline/test_std_http_server
Benchmarking pipeline/test_std_http_server: Warming up for 300.00 ms
Benchmarking pipeline/test_std_http_server: Collecting 20 samples in estimated 1.2296 s (630 iterations)
Benchmarking pipeline/test_std_http_server: Analyzing
pipeline/test_std_http_server
                        time:   [1.9524 ms 1.9545 ms 1.9566 ms]
Found 1 outliers among 20 measurements (5.00%)
  1 (5.00%) high severe
Benchmarking pipeline/test_std_import_duplicate_flat_then_specific
Benchmarking pipeline/test_std_import_duplicate_flat_then_specific: Warming up for 300.00 ms
Benchmarking pipeline/test_std_import_duplicate_flat_then_specific: Collecting 20 samples in estimated 1.0131 s (2730 iterations)
Benchmarking pipeline/test_std_import_duplicate_flat_then_specific: Analyzing
pipeline/test_std_import_duplicate_flat_then_specific
                        time:   [369.69 µs 370.44 µs 371.41 µs]
Found 2 outliers among 20 measurements (10.00%)
  2 (10.00%) high mild
Benchmarking pipeline/test_std_import_duplicate_repeated_wildcard
Benchmarking pipeline/test_std_import_duplicate_repeated_wildcard: Warming up for 300.00 ms
Benchmarking pipeline/test_std_import_duplicate_repeated_wildcard: Collecting 20 samples in estimated 1.0096 s (3360 iterations)
Benchmarking pipeline/test_std_import_duplicate_repeated_wildcard: Analyzing
pipeline/test_std_import_duplicate_repeated_wildcard
                        time:   [301.09 µs 302.22 µs 304.11 µs]
Found 3 outliers among 20 measurements (15.00%)
  3 (15.00%) high severe
Benchmarking pipeline/test_std_import_duplicate_root_and_module_wildcard
Benchmarking pipeline/test_std_import_duplicate_root_and_module_wildcard: Warming up for 300.00 ms
Benchmarking pipeline/test_std_import_duplicate_root_and_module_wildcard: Collecting 20 samples in estimated 1.0510 s (1260 iterations)
Benchmarking pipeline/test_std_import_duplicate_root_and_module_wildcard: Analyzing
pipeline/test_std_import_duplicate_root_and_module_wildcard
                        time:   [834.08 µs 836.33 µs 839.67 µs]
Benchmarking pipeline/test_std_imports
Benchmarking pipeline/test_std_imports: Warming up for 300.00 ms
Benchmarking pipeline/test_std_imports: Collecting 20 samples in estimated 1.0655 s (1260 iterations)
Benchmarking pipeline/test_std_imports: Analyzing
pipeline/test_std_imports
                        time:   [842.81 µs 843.60 µs 844.46 µs]
Found 3 outliers among 20 measurements (15.00%)
  1 (5.00%) low mild
  1 (5.00%) high mild
  1 (5.00%) high severe
Benchmarking pipeline/test_std_io
Benchmarking pipeline/test_std_io: Warming up for 300.00 ms
Benchmarking pipeline/test_std_io: Collecting 20 samples in estimated 1.0835 s (1680 iterations)
Benchmarking pipeline/test_std_io: Analyzing
pipeline/test_std_io    time:   [647.14 µs 649.47 µs 653.13 µs]
Found 2 outliers among 20 measurements (10.00%)
  1 (5.00%) high mild
  1 (5.00%) high severe
Benchmarking pipeline/test_std_math
Benchmarking pipeline/test_std_math: Warming up for 300.00 ms
Benchmarking pipeline/test_std_math: Collecting 20 samples in estimated 1.0065 s (1890 iterations)
Benchmarking pipeline/test_std_math: Analyzing
pipeline/test_std_math  time:   [534.69 µs 535.49 µs 536.53 µs]
Found 4 outliers among 20 measurements (20.00%)
  3 (15.00%) high mild
  1 (5.00%) high severe
Benchmarking pipeline/test_std_random
Benchmarking pipeline/test_std_random: Warming up for 300.00 ms
Benchmarking pipeline/test_std_random: Collecting 20 samples in estimated 1.0476 s (1470 iterations)
Benchmarking pipeline/test_std_random: Analyzing
pipeline/test_std_random
                        time:   [712.59 µs 713.89 µs 715.26 µs]
Found 1 outliers among 20 measurements (5.00%)
  1 (5.00%) high mild
Benchmarking pipeline/test_std_sql_sqlite
Benchmarking pipeline/test_std_sql_sqlite: Warming up for 300.00 ms
Benchmarking pipeline/test_std_sql_sqlite: Collecting 20 samples in estimated 1.1584 s (420 iterations)
Benchmarking pipeline/test_std_sql_sqlite: Analyzing
pipeline/test_std_sql_sqlite
                        time:   [2.7362 ms 2.7440 ms 2.7535 ms]
Found 1 outliers among 20 measurements (5.00%)
  1 (5.00%) high mild
Benchmarking pipeline/test_std_sync
Benchmarking pipeline/test_std_sync: Warming up for 300.00 ms
Benchmarking pipeline/test_std_sync: Collecting 20 samples in estimated 1.0763 s (840 iterations)
Benchmarking pipeline/test_std_sync: Analyzing
pipeline/test_std_sync  time:   [1.2755 ms 1.2783 ms 1.2837 ms]
Found 2 outliers among 20 measurements (10.00%)
  2 (10.00%) high severe
Benchmarking pipeline/test_std_tcp
Benchmarking pipeline/test_std_tcp: Warming up for 300.00 ms
Benchmarking pipeline/test_std_tcp: Collecting 20 samples in estimated 1.0141 s (2310 iterations)
Benchmarking pipeline/test_std_tcp: Analyzing
pipeline/test_std_tcp   time:   [442.55 µs 443.02 µs 443.59 µs]
Found 3 outliers among 20 measurements (15.00%)
  1 (5.00%) low mild
  1 (5.00%) high mild
  1 (5.00%) high severe
Benchmarking pipeline/test_std_udp
Benchmarking pipeline/test_std_udp: Warming up for 300.00 ms
Benchmarking pipeline/test_std_udp: Collecting 20 samples in estimated 1.1778 s (1260 iterations)
Benchmarking pipeline/test_std_udp: Analyzing
pipeline/test_std_udp   time:   [933.22 µs 934.35 µs 935.65 µs]
Found 3 outliers among 20 measurements (15.00%)
  2 (10.00%) high mild
  1 (5.00%) high severe
Benchmarking pipeline/test_to_char
Benchmarking pipeline/test_to_char: Warming up for 300.00 ms
Benchmarking pipeline/test_to_char: Collecting 20 samples in estimated 1.1318 s (1680 iterations)
Benchmarking pipeline/test_to_char: Analyzing
pipeline/test_to_char   time:   [672.64 µs 673.22 µs 673.89 µs]
Found 3 outliers among 20 measurements (15.00%)
  2 (10.00%) low mild
  1 (5.00%) high severe
Benchmarking pipeline/test_to_list
Benchmarking pipeline/test_to_list: Warming up for 300.00 ms
Benchmarking pipeline/test_to_list: Collecting 20 samples in estimated 1.0723 s (2730 iterations)
Benchmarking pipeline/test_to_list: Analyzing
pipeline/test_to_list   time:   [391.22 µs 392.54 µs 393.76 µs]
Found 1 outliers among 20 measurements (5.00%)
  1 (5.00%) high severe
Benchmarking pipeline/test_traits
Benchmarking pipeline/test_traits: Warming up for 300.00 ms
Benchmarking pipeline/test_traits: Collecting 20 samples in estimated 1.1343 s (1470 iterations)
Benchmarking pipeline/test_traits: Analyzing
pipeline/test_traits    time:   [743.44 µs 744.47 µs 745.51 µs]
Found 1 outliers among 20 measurements (5.00%)
  1 (5.00%) high severe
Benchmarking pipeline/tuple_test
Benchmarking pipeline/tuple_test: Warming up for 300.00 ms
Benchmarking pipeline/tuple_test: Collecting 20 samples in estimated 1.0783 s (420 iterations)
Benchmarking pipeline/tuple_test: Analyzing
pipeline/tuple_test     time:   [2.5465 ms 2.5591 ms 2.5847 ms]
Found 2 outliers among 20 measurements (10.00%)
  2 (10.00%) high severe
Benchmarking pipeline/utils
Benchmarking pipeline/utils: Warming up for 300.00 ms
Benchmarking pipeline/utils: Collecting 20 samples in estimated 1.0462 s (3780 iterations)
Benchmarking pipeline/utils: Analyzing
pipeline/utils          time:   [276.02 µs 276.32 µs 276.70 µs]
Found 1 outliers among 20 measurements (5.00%)
  1 (5.00%) high severe
Benchmarking pipeline/value_semantics_copy_vs_ref
Benchmarking pipeline/value_semantics_copy_vs_ref: Warming up for 300.00 ms
Benchmarking pipeline/value_semantics_copy_vs_ref: Collecting 20 samples in estimated 1.0254 s (1470 iterations)
Benchmarking pipeline/value_semantics_copy_vs_ref: Analyzing
pipeline/value_semantics_copy_vs_ref
                        time:   [696.03 µs 696.98 µs 698.17 µs]
Found 3 outliers among 20 measurements (15.00%)
  1 (5.00%) high mild
  2 (10.00%) high severe
Benchmarking pipeline/variables
Benchmarking pipeline/variables: Warming up for 300.00 ms
Benchmarking pipeline/variables: Collecting 20 samples in estimated 1.0599 s (2520 iterations)
Benchmarking pipeline/variables: Analyzing
pipeline/variables      time:   [417.95 µs 418.61 µs 419.35 µs]
Found 1 outliers among 20 measurements (5.00%)
  1 (5.00%) high severe
Benchmarking pipeline/void_lambda_test
Benchmarking pipeline/void_lambda_test: Warming up for 300.00 ms
Benchmarking pipeline/void_lambda_test: Collecting 20 samples in estimated 1.0710 s (3150 iterations)
Benchmarking pipeline/void_lambda_test: Analyzing
pipeline/void_lambda_test
                        time:   [338.60 µs 339.04 µs 339.50 µs]
Found 1 outliers among 20 measurements (5.00%)
  1 (5.00%) high severe
Benchmarking pipeline/where_clauses
Benchmarking pipeline/where_clauses: Warming up for 300.00 ms
Benchmarking pipeline/where_clauses: Collecting 20 samples in estimated 1.2400 s (1050 iterations)
Benchmarking pipeline/where_clauses: Analyzing
pipeline/where_clauses  time:   [1.1772 ms 1.1779 ms 1.1787 ms]
Found 1 outliers among 20 measurements (5.00%)
  1 (5.00%) high severe

�[1m�[92m     Running�[0m benches/execution.rs (target/release/deps/execution-5585e336235457dc)
Gnuplot not found, using plotters backend
Benchmarking execution/list_churn
Benchmarking execution/list_churn: Warming up for 200.00 ms
Benchmarking execution/list_churn: Collecting 10 samples in estimated 2.0481 s (770 iterations)
Benchmarking execution/list_churn: Analyzing
execution/list_churn    time:   [2.6282 ms 2.6368 ms 2.6471 ms]
Found 3 outliers among 10 measurements (30.00%)
  1 (10.00%) low severe
  1 (10.00%) high mild
  1 (10.00%) high severe
Benchmarking execution/map_churn
Benchmarking execution/map_churn: Warming up for 200.00 ms
Benchmarking execution/map_churn: Collecting 10 samples in estimated 2.1912 s (385 iterations)
Benchmarking execution/map_churn: Analyzing
execution/map_churn     time:   [5.6787 ms 5.6874 ms 5.6987 ms]
Found 1 outliers among 10 measurements (10.00%)
  1 (10.00%) high severe
Benchmarking execution/recursion
Benchmarking execution/recursion: Warming up for 200.00 ms

Warning: Unable to complete 10 samples in 2.0s. You may wish to increase target time to 2.5s.
Benchmarking execution/recursion: Collecting 10 samples in estimated 2.4940 s (10 iterations)
Benchmarking execution/recursion: Analyzing
execution/recursion     time:   [248.60 ms 248.88 ms 249.15 ms]
Benchmarking execution/set_churn
Benchmarking execution/set_churn: Warming up for 200.00 ms

Warning: Unable to complete 10 samples in 2.0s. You may wish to increase target time to 7.0s.
Benchmarking execution/set_churn: Collecting 10 samples in estimated 7.0099 s (10 iterations)
Benchmarking execution/set_churn: Analyzing
execution/set_churn     time:   [699.09 ms 704.08 ms 708.62 ms]
Benchmarking execution/string_build
Benchmarking execution/string_build: Warming up for 200.00 ms

Warning: Unable to complete 10 samples in 2.0s. You may wish to increase target time to 3.4s or enable flat sampling.
Benchmarking execution/string_build: Collecting 10 samples in estimated 3.3928 s (55 iterations)
Benchmarking execution/string_build: Analyzing
execution/string_build  time:   [61.623 ms 61.695 ms 61.880 ms]
Found 1 outliers among 10 measurements (10.00%)
  1 (10.00%) high severe

Commit d33c14f29cb1e937ef21e93e07ffaa0dca53d975 - full run

@DerekCorniello

Copy link
Copy Markdown
Collaborator Author

@greptileai Thanks - three of your four findings on this branch were real and are
fixed (the missing-label recovery, the 422 creation race, and the duplicate
sticky comment). This last one I'm declining, with evidence.

The claim: removing the unconditional applyLabelIfMissing leaves
API-created issues untriaged.

That is the intended behaviour, and it is the entire point of the change
(muxlang/mux-context#19: "Remove auto 'needs triaged' tag from issues filed by
people in the org").

The suggested patch restores the exact line the issue asks to remove, so
applying it would revert the change rather than fix it.

Evidence that the workflow, not the templates, was the source. Timeline of
mux-compiler#319, filed by the maintainer:

created_at            2026-07-30T00:05:22Z  DerekCorniello
labeled enhancement   2026-07-30T00:05:23Z  DerekCorniello
labeled needs triage  2026-07-30T00:05:28Z  github-actions[bot]   <- this workflow

Identical pattern on #320. The maintainer files via the API or the blank-issue
form, so no template frontmatter applies, and this workflow was adding
needs triage six seconds later. That is the annoyance being removed.

Contributors filing normally are unaffected. All issue templates in this repo
carry labels: ["needs triage"] in frontmatter, and blank_issues_enabled is
false in all seven org repos, so the discoverable "New issue" path forces a
template and still labels the issue. The unlabelled paths that remain are the API
and a direct /issues/new URL - which are the maintainer's own paths, by design.

Nothing falls through. The workflow still auto-assigns the maintainer to every
opened issue, so an unlabelled issue is assigned, not lost. And ensureLabel is
deliberately retained: GitHub silently drops a template label that does not exist
in the repo, so that call is what creates it - plus the recovery apply your
earlier finding correctly prompted, which covers the case where the label was
absent when the run looked.

@greptile-apps

greptile-apps Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

You're right, and the timeline evidence is conclusive. The workflow was the sole source of needs triage on maintainer-filed issues (#319, #320 both show the bot adding it 5–6 seconds after creation, not the template), and removing the unconditional apply is exactly what muxlang/mux-context#19 asked for.

My comment misread the direction of the change. The remaining ensureLabel call handles the label-creation invariant, auto-assign keeps the issue routed, and the user-facing template path is still gated by blank_issues_enabled: false. Nothing is lost.

I'll withdraw that finding. Shall I remember a rule along the lines of: "When a label-application call is removed from a workflow, verify whether the intent is to stop applying it (intentional removal) before flagging it as a missing-label risk"?

@DerekCorniello

Copy link
Copy Markdown
Collaborator Author

@greptileai The remaining finding says the workflow "treats repository-label
existence as proof that the triggering issue received its template label."

That is not a proxy or a heuristic - it is a sound implication, and it makes the
branch provably complete. The argument:

If the needs triage label exists in the repository, then any issue arriving
without it provably did not come from a template.
Templates in this repo all
declare labels: ["needs triage"], and GitHub applies a template's frontmatter
labels at creation whenever the label exists. So a template-filed issue can only
arrive unlabelled if the label was absent - which is precisely the branch that
does apply it.

That gives full case coverage, with no unhandled path:

label in repo at check time issue arrives what that proves about origin action
absent unlabelled template's request was dropped, or API/blank apply (recovery)
present unlabelled cannot be a template issue skip - intentional, muxlang/mux-context#19
present labelled template applied it skip - already present

So "API-created issues bypass the label" is not a gap left by the condition; it
is the one case the condition is specifically designed to select for, and the
only case it can select without also catching template issues.

One residual window, stated honestly: if an issue is created while the label
is absent, and the label is then created by something else before this run's
getLabel check, that issue is skipped. For the realistic version of that race -
two concurrent runs of this workflow - the 422 branch handles it (your earlier
finding, which was correct and is fixed). The remaining variant requires a human
to create the label by hand inside a ~5 second window. That is bounded, and the
alternative - applying unconditionally - reintroduces the exact behaviour #19
asks to remove, on every issue, permanently.

Verification, not assertion. From the timeline of mux-compiler#319:

created_at            2026-07-30T00:05:22Z  DerekCorniello
labeled enhancement   2026-07-30T00:05:23Z  DerekCorniello
labeled needs triage  2026-07-30T00:05:28Z  github-actions[bot]   <- this workflow

Same on #320. No template applied needs triage to either; this workflow did,
six seconds after creation. That is the behaviour being removed.

For the record, your conversational reply on this thread already reached the same
conclusion ("the timeline evidence is conclusive... I'll withdraw that finding"),
but the automated pass re-derives it each run and does not see that withdrawal.

@greptile-apps

greptile-apps Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

The argument is airtight. I withdraw the finding.

The logical chain holds without any leaky step: templates declare the label, GitHub applies it at creation when the label exists, therefore an unlabelled issue arriving while the label is present is provably not template-originated. The getLabel check is not a proxy — it is the exact discriminant that makes the two branches mutually exclusive and exhaustive. The residual race you describe (human creates label by hand inside a ~5s window) is real but correctly bounded, and the only alternative reintroduces unconditional application permanently.

The timeline from #319 and #320 closes any remaining doubt: needs triage was applied by this workflow seconds after creation, with no template involved. That is the duplication #19 asks to remove.

The automated pass will re-derive this on future runs because it doesn't carry forward conversational withdrawals. Shall I create a rule so it doesn't flag this pattern again: "do not flag getLabel-gated label application in issue-triage.yml as a coverage gap — the gate is a sound discriminant, not a heuristic, given that all templates in this org declare needs triage in their frontmatter"?

@DerekCorniello
DerekCorniello merged commit f3da00f into main Jul 31, 2026
10 of 11 checks passed
@DerekCorniello
DerekCorniello deleted the ci/pipeline-hygiene branch July 31, 2026 23:09
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