Skip to content

Add run-again footer hints for slash and label command triggers#41920

Merged
pelikhan merged 1 commit into
mainfrom
copilot/update-footer-slash-command
Jun 27, 2026
Merged

Add run-again footer hints for slash and label command triggers#41920
pelikhan merged 1 commit into
mainfrom
copilot/update-footer-slash-command

Conversation

Copilot AI commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Generated safe-output footers already hinted slash-command re-entry, but did not guide users for label-command flows. This change makes footer hints explicit for both trigger types so users can immediately re-run workflows with the correct action.

  • Footer behavior

    • Extend default footer rendering to append a label-command hint when a label trigger is configured.
    • Preserve existing slash-command hint behavior, including custom placeholder support.
    • Render both hints when a workflow supports both trigger types.
  • Runtime metadata plumbing

    • Add GH_AW_LABEL_COMMANDS to safe-outputs environment generation so footer rendering can resolve label-command names at runtime.
    • Reuse first-command selection semantics used by slash commands for consistent hint output.
  • Compiler output updates

    • Emit GH_AW_LABEL_COMMANDS in generated safe-output ingestion env blocks where command metadata is already passed.
  • Coverage updates

    • Add/extend JS footer tests for label-only and slash+label combined hint output.
    • Extend Go env-var generation tests to cover GH_AW_LABEL_COMMANDS.
// messages_footer.cjs (default footer behavior)
if (ctx.slashCommand) {
  defaultFooter += `\n> <sub>Comment <em>/{slash_command}</em> ${hintText}</sub>`;
}
if (ctx.labelCommand) {
  defaultFooter += `\n> <sub>Add label <em>{label_command}</em> to run again</sub>`;
}

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@pelikhan pelikhan marked this pull request as ready for review June 27, 2026 19:04
Copilot AI review requested due to automatic review settings June 27, 2026 19:04
@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR #41920 does not have the 'implementation' label and has only 13 new lines of code in business logic directories (threshold: 100).

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR improves the default safe-output footer “run again” guidance by adding explicit label-trigger hints alongside the existing slash-command hints, and wires label-command metadata through compiler-generated environment variables so footer rendering can resolve label names at runtime.

Changes:

  • Extend default footer rendering to include a label-based rerun hint (and render both label + slash hints when both are configured).
  • Plumb GH_AW_LABEL_COMMANDS through safe-output environment generation (Go compiler + generated YAML env blocks).
  • Add/extend JS and Go tests to cover label-only and combined hint behavior, plus env-var generation.
Show a summary per file
File Description
pkg/workflow/compiler_yaml.go Emits GH_AW_LABEL_COMMANDS in generated env blocks alongside existing command metadata.
pkg/workflow/compiler_safe_outputs_job.go Adds GH_AW_LABEL_COMMANDS to job-level safe-output env var generation.
pkg/workflow/compiler_safe_outputs_job_test.go Extends env-var generation coverage to validate GH_AW_LABEL_COMMANDS.
actions/setup/js/messages_footer.cjs Adds label rerun hint rendering and factors “first command” selection into a shared helper.
actions/setup/js/messages.test.cjs Adds footer tests for label-only and slash+label combined rerun hint output (and env-driven label hint rendering).

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 5/5 changed files
  • Comments generated: 0
  • Review effort level: Low

@github-actions github-actions Bot mentioned this pull request Jun 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 82/100 — Excellent

Analyzed 5 test(s) across 2 files: 5 design, 0 implementation, 0 guideline violation(s).

📊 Metrics & Test Classification (5 tests analyzed)
Metric Value
New/modified tests analyzed 5
✅ Design tests (behavioral contracts) 5 (100%)
⚠️ Implementation tests (low value) 0 (0%)
Tests with error/edge cases 2 (40%)
Duplicate test clusters 0
Test inflation detected No (51 test lines / 30 prod lines = 1.7×)
🚨 Coding-guideline violations 0
Test File Classification Issues Detected
should append label command hint when labelCommand is provided actions/setup/js/messages.test.cjs:634 ✅ Design
should include both slash and label command hints when both are provided actions/setup/js/messages.test.cjs:648 ✅ Design
should include label command hint when GH_AW_LABEL_COMMANDS is set actions/setup/js/messages.test.cjs:842 ✅ Design
should use first label command from GH_AW_LABEL_COMMANDS when multiple are configured actions/setup/js/messages.test.cjs:857 ✅ Design
TestBuildJobLevelSafeOutputEnvVars (LabelCommand row) pkg/workflow/compiler_safe_outputs_job_test.go:563 ✅ Design

Go: 1 (*_test.go); JavaScript: 4 (*.test.cjs). No other languages detected.

Verdict

Check passed. 0% implementation tests (threshold: 30%). All new tests verify observable behavior (output strings, env var contents, selection logic) rather than internal implementation details.

🧪 Test quality analysis by Test Quality Sentinel · 45.6 AIC · ⌖ 17.7 AIC · ⊞ 8.4K ·

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Test Quality Sentinel: 82/100. Test quality is acceptable — 0% of new tests are implementation tests (threshold: 30%).

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Skills-Based Review 🧠

Applied /tdd and /grill-with-docs — no blocking correctness issues, but a few test-coverage gaps and a design-consistency point worth addressing.

📋 Key Themes & Highlights

Key Themes

  • Test coverage gaps (3 items): getFirstCommandHint has no isolated unit tests; generateOutputCollectionStep in compiler_yaml.go is untested; label-command-only scenario missing from Go tests.
  • Design asymmetry: label command hint text is hardcoded while slash commands support slashCommandPlaceholder — either document the intentional limit or extend the API to match.
  • Comment quality: extracting getFirstCommandHint dropped the "compiler-generated JSON" context that justified the silent error ignore.

Positive Highlights

  • ✅ Clean extraction of getFirstCommandHint — good refactor that eliminates the duplicated JSON-parse block.
  • ✅ The combined slash+label test uses toBe (exact match) — prevents silent ordering regressions.
  • GH_AW_LABEL_COMMANDS is correctly cleaned up in the global afterEach, making individual test cleanups safe even if assertions throw.
  • ✅ The two-site env var emission (compiler_safe_outputs_job.go + compiler_yaml.go) is consistent with the existing slash-command pattern.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 79.6 AIC · ⌖ 9.91 AIC · ⊞ 6.6K

} catch {
// Silently ignore malformed JSON; hints are non-critical enhancements.
}
return undefined;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/tdd] getFirstCommandHint is tested only indirectly through generateFooterWithMessages. Direct unit tests for its edge cases would make the contract explicit and catch regressions faster.

💡 Suggested test cases to add
describe("getFirstCommandHint", () => {
  it("returns undefined for undefined input", () =>
    expect(getFirstCommandHint(undefined)).toBeUndefined());
  it("returns undefined for empty array JSON", () =>
    expect(getFirstCommandHint(JSON.stringify([]))).toBeUndefined());
  it("returns undefined when first element is not a string", () =>
    expect(getFirstCommandHint(JSON.stringify([42]))).toBeUndefined());
  it("returns undefined for malformed JSON", () =>
    expect(getFirstCommandHint("not-json")).toBeUndefined());
  it("returns first command from valid array", () =>
    expect(getFirstCommandHint(JSON.stringify(["deploy", "release"]))).toBe("deploy"));
});

Without isolated tests, a future change to getFirstCommandHint that breaks the empty-array or non-string guards would only be caught if an existing integration-level test exercises that path.

@copilot please address this.

}
if len(data.LabelCommand) > 0 {
if labelCommandsJSON, err := json.Marshal(data.LabelCommand); err == nil {
fmt.Fprintf(yaml, " GH_AW_LABEL_COMMANDS: %q\n", string(labelCommandsJSON))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/tdd] The GH_AW_LABEL_COMMANDS emission in generateOutputCollectionStep has no test coverage. compiler_yaml_test.go has 21 test functions but none exercise this path — a label-command workflow fixture would add meaningful protection here.

💡 Suggested test sketch

Add a test case to TestGenerateOutputCollectionStep (or the nearest existing snapshot/fixture test) that sets data.LabelCommand = []string{"deploy"} and asserts the emitted YAML contains GH_AW_LABEL_COMMANDS: "[\"deploy\"]".

This mirrors the existing test coverage gap for GH_AW_COMMANDS in compiler_yaml_test.go — worth closing for both while the context is fresh.

@copilot please address this.

workflowData: &WorkflowData{
Name: "Test Workflow",
Command: []string{"review-bot"},
LabelCommand: []string{"deploy"},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/tdd] LabelCommand is added to the combined slash-command-plus-placeholder test case only. A dedicated label-command-only test case (no Command set) would verify isolation and serve as a clearer specification.

💡 Suggested additional test case
{
    name: "with label command only",
    workflowData: &WorkflowData{
        Name:         "Test Workflow",
        LabelCommand: []string{"deploy"},
        SafeOutputs:  &SafeOutputsConfig{},
    },
    workflowID: "test-workflow",
    expectedVars: map[string]string{
        "GH_AW_LABEL_COMMANDS": `"[\"deploy\"]"`,
    },
    notExpectedVars: []string{"GH_AW_COMMANDS"},
    checkContains: true,
},

This ensures the env var is emitted correctly even when there is no accompanying slash command, and confirms GH_AW_COMMANDS is not mistakenly injected.

@copilot please address this.

}
// Append label command hint when applicable (workflow has a label command trigger)
if (ctx.labelCommand) {
defaultFooter += `\n> <sub>Add label <em>{label_command}</em> to run again</sub>`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/grill-with-docs] The label command hint hard-codes "to run again" while the analogous slash command hint supports slashCommandPlaceholder for custom text (e.g. "to review this PR"). This asymmetry should be intentional — if so, please document it in the JSDoc; if not, a labelCommandPlaceholder field would make the two hints consistent.

💡 Documenting the intentional asymmetry

If customisation is intentionally out of scope for now, add a note to the FooterContext JSDoc:

 * `@property` {string} [labelCommand] - Label command name for the run-again hint.
 *   Note: unlike slash commands, the hint text is fixed to "to run again".
 *   Add labelCommandPlaceholder when custom text is needed.

This prevents future contributors from adding the placeholder in two inconsistent places.

@copilot please address this.

return commands[0];
}
} catch {
// Silently ignore malformed JSON; hints are non-critical enhancements.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/grill-with-docs] The catch comment lost a useful piece of context from the original inline slash-command block: "The value is compiler-generated JSON, so this path should not occur in practice." Preserving that reasoning helps future readers understand why the silent ignore is safe.

💡 Suggested updated comment
  } catch {
    // Silently ignore malformed JSON; hints are non-critical enhancements.
    // In practice this path should not occur — the value is compiler-generated JSON.
  }

@copilot please address this.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Functionally correct — one non-blocking gap

The template substitution is sound (verified via toSnakeCase({ ...ctx }) converting labelCommandlabel_command), getFirstCommandHint is a clean DRY refactor of the existing inline JSON parsing, the Go error-handling pattern is consistent with GH_AW_COMMANDS in the same files, and test teardown is safe (vi.resetModules() + beforeEach cleanup cover it).

One medium gap: the label hint hardcodes "to run again" with no labelCommandPlaceholder equivalent, unlike the slash command hint. Commented inline — non-blocking but worth addressing before the next feature that needs custom text.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • patchdiff.githubusercontent.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "patchdiff.githubusercontent.com"

See Network Configuration for more information.

🔎 Code quality review by PR Code Quality Reviewer · 102.5 AIC · ⌖ 7.03 AIC · ⊞ 5.2K

}
// Append label command hint when applicable (workflow has a label command trigger)
if (ctx.labelCommand) {
defaultFooter += `\n> <sub>Add label <em>{label_command}</em> to run again</sub>`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Label hint text is hardcoded with no customization path, unlike slashCommandPlaceholder which allows workflows to say "to review this PR" etc.

💡 Suggested improvement

slashCommand supports custom hint text via slashCommandPlaceholder (read from GH_AW_COMMAND_PLACEHOLDER). The label hint hardcodes "to run again" with no equivalent escape hatch:

// Current
defaultFooter += `\n> <sub>Add label <em>{label_command}</em> to run again</sub>`;

// With parity
const labelHintText = ctx.labelCommandPlaceholder || "to run again";
defaultFooter += `\n> <sub>Add label <em>{label_command}</em> ${labelHintText}</sub>`;

This would also require:

  • labelCommandPlaceholder in the FooterContext typedef
  • GH_AW_LABEL_COMMAND_PLACEHOLDER env var in generateFooterWithMessages
  • Corresponding compiler emission in compiler_safe_outputs_job.go and compiler_yaml.go

A deploy workflow will never be able to say "to trigger deployment" instead of the generic "to run again" without this. Since slashCommandPlaceholder already exists and the two hint types are rendered in the same block, the omission will be noticed.

@pelikhan pelikhan merged commit 4459088 into main Jun 27, 2026
86 of 105 checks passed
@pelikhan pelikhan deleted the copilot/update-footer-slash-command branch June 27, 2026 20:44
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.

3 participants