Skip to content

Refactor runtime setup extra-field merging into shared helpers#43135

Merged
pelikhan merged 8 commits into
mainfrom
copilot/duplicate-code-fix
Jul 4, 2026
Merged

Refactor runtime setup extra-field merging into shared helpers#43135
pelikhan merged 8 commits into
mainfrom
copilot/duplicate-code-fix

Conversation

Copilot AI commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

generateSetupStep was duplicating the same runtime/user extra-field merge and sorted with: rendering logic across the gh-aw, Go go-version-file, and generic runtime paths. That duplication made precedence, formatting, and ordering behavior easier to drift.

  • What changed

    • Extracted shared helpers in pkg/workflow/runtime_step_generator.go to:
      • merge Runtime.ExtraWithFields with RuntimeRequirement.ExtraFields
      • preserve existing precedence rules (req.ExtraFields override runtime defaults)
      • format user-provided values for YAML
      • emit with: entries in stable sorted order
  • Where the shared logic is now used

    • gh-aw setup step generation
    • generic runtime setup generation
    • Go setup generation when go-version-file is used
  • Behavior locked in with tests

    • added focused coverage for:
      • override behavior when runtime defaults and user fields share a key
      • deterministic ordering of emitted with: fields
      • parity across the gh-aw, generic runtime, and Go special-case paths
  • Example

    withFields := mergeRuntimeWithFields(req)
    step = appendSortedWithFieldEntries(step, withFields)

Generated by 👨‍🍳 PR Sous Chef · 7.05 AIC · ⌖ 5.18 AIC · ⊞ 6.6K ·
Comment /souschef to run again

Copilot AI and others added 3 commits July 3, 2026 06:56
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor duplicate code in generateSetupStep logic Refactor runtime setup extra-field merging into shared helpers Jul 3, 2026
Copilot AI requested a review from pelikhan July 3, 2026 07:04
@pelikhan pelikhan marked this pull request as ready for review July 3, 2026 07:13
Copilot AI review requested due to automatic review settings July 3, 2026 07:13

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 refactors runtime setup step generation by extracting shared helpers to consistently merge runtime default with: fields with user-provided overrides and to emit deterministic, sorted with: entries across the gh-aw, generic runtime, and Go go-version-file paths.

Changes:

  • Added shared helpers to merge runtime/user with: fields and append them in stable sorted order.
  • Updated gh-aw setup step generation to reuse the shared sorted with: rendering helper.
  • Added tests covering merged with: field output and ordering for generic runtimes, Go go-version-file, and gh-aw.
Show a summary per file
File Description
pkg/workflow/runtime_step_generator.go Introduces shared merge/sorted-append helpers and wires them into all runtime setup generation paths.
pkg/workflow/runtime_setup_test.go Adds tests for merged and deterministic ordering of runtime with: fields for generic runtimes and Go go-version-file.
pkg/workflow/runtime_gh_aw_test.go Adds gh-aw-specific test coverage for merge + deterministic ordering.
pkg/workflow/gh_aw_setup_steps.go Switches gh-aw setup step with: rendering to use the shared sorted-append helper.
.github/skills/agentic-workflow-designer/SKILL.md Removes documented fields/notes in the workflow designer skill (appears unrelated to the runtime refactor).

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: 6
  • Review effort level: Low

Comment on lines +60 to +70
func mergeRuntimeWithFields(req *RuntimeRequirement) map[string]string {
allExtraFields := make(map[string]string)

maps.Copy(allExtraFields, req.Runtime.ExtraWithFields)

for k, v := range req.ExtraFields {
allExtraFields[k] = formatYAMLValue(v)
}

return allExtraFields
}
Comment thread pkg/workflow/runtime_step_generator.go Outdated
func appendSortedWithFieldEntries(step GitHubActionStep, withFields map[string]string) GitHubActionStep {
for _, key := range sliceutil.SortedKeys(withFields) {
step = append(step, fmt.Sprintf(" %s: %s", key, withFields[key]))
workflowLog.Printf(" Added extra field to runtime setup: %s = %s", key, withFields[key])
Comment thread pkg/workflow/runtime_setup_test.go
Comment thread pkg/workflow/runtime_setup_test.go
Comment thread pkg/workflow/runtime_gh_aw_test.go
Comment on lines 309 to 317
After confirmation, generate one workflow file using the same skeleton style as `.github/aw/create-agentic-workflow.md`.

```markdown
---
emoji: <emoji>
description: <brief description>
strict: true
on:
<trigger config>
max-turns: <integer or omit>
max-ai-credits: <integer or omit for default 1000>
max-daily-ai-credits: <integer or omit to leave disabled>
user-rate-limit: <object or omit>
models: <object or omit>
permissions:
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

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

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate — ADR Required

This PR makes significant changes to core business logic (108 new lines in pkg/workflow/) but does not have a linked Architecture Decision Record (ADR).

Draft ADR committed: docs/adr/43135-extract-runtime-extra-field-helpers.md — review and complete it before merging.

This PR cannot merge until an ADR is linked in the PR body.

What to do next
  1. Review the draft ADR committed to your branch — it was generated from the PR diff
  2. Complete the missing sections — add context the AI could not infer, refine the decision rationale, and list real alternatives you considered
  3. Commit the finalized ADR to docs/adr/ on your branch
  4. Reference the ADR in this PR body by adding a line such as:

    ADR: ADR-43135: Extract Runtime Extra-Field Helpers into Shared Functions

Once an ADR is linked in the PR body, this gate will re-run and verify the implementation matches the decision.

Why ADRs Matter

ADRs create a searchable, permanent record of why the codebase looks the way it does. Future contributors (and your future self) will thank you.

Michael Nygard ADR Format Reference

An ADR must contain these four sections to be considered complete:

  • Context — What is the problem? What forces are at play?
  • Decision — What did you decide? Why?
  • Alternatives Considered — What else could have been done?
  • Consequences — What are the trade-offs (positive and negative)?

All ADRs are stored in docs/adr/ as Markdown files numbered by PR number (e.g., 43135-extract-runtime-extra-field-helpers.md for PR #43135).

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · 45.7 AIC · ⌖ 6.9 AIC · ⊞ 8.5K ·
Comment /review to run again

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

🤖 PR Triage

Field Value
Category refactor
Risk 🟡 Medium
Score 55 / 100
Action fast_track
Batch pr-batch:runtime-refactor (with #43134)

Score Breakdown: Impact 28 + Urgency 14 + Quality 13

Rationale: Extracts duplicated extra-field merging into shared helpers in runtime setup (108+/59−, 5 files). Good structure improvement but touches core runtime. Paired with #43134 for batch review.

Recommended Action: Review together with #43134 as a runtime-refactor batch.

Generated by 🔧 PR Triage Agent · 86.3 AIC · ⌖ 6.42 AIC · ⊞ 5.5K ·

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

⚠️ Test Quality Score: 68/100 — Acceptable

Analyzed 3 test(s): 3 design, 0 implementation, 0 violation(s).

📊 Metrics (3 tests)
Metric Value
Analyzed 3 (Go: 3, JS: 0)
✅ Design 3 (100%)
⚠️ Implementation 0 (0%)
Edge/error coverage 2 (67%)
Duplicate clusters 0
Inflation YES (78 test lines vs 30 prod lines, ~2.6:1)
🚨 Violations 0
Test File Classification Issues
TestGenerateRuntimeSetupSteps_GhAw_ReleaseMergesAndSortsExtraFields runtime_gh_aw_test.go:146 design_test / high_value None
TestGenerateRuntimeSetupSteps_MergesAndSortsRuntimeExtraFields runtime_setup_test.go:501 design_test / high_value Happy-path only; no error-path assertion
TestGenerateRuntimeSetupSteps_GoVersionFileMergesAndSortsRuntimeExtraFields runtime_setup_test.go:523 design_test / high_value Happy-path only; no error-path assertion
⚠️ Flagged Tests (1)

Test inflation — 78 new test lines vs 30 new production lines (~2.6:1 ratio, threshold 2:1). The refactored helpers are small (mergeRuntimeWithFields, appendSortedWithFieldEntries), but three separate tests duplicating the same merge+sort scenario inflate the count. Consider collapsing the two nearly-identical happy-path tests (_MergesAndSortsRuntimeExtraFields and _GoVersionFileMergesAndSortsRuntimeExtraFields) into a table-driven test to reduce duplication while keeping both runtime branches covered.

Verdict

Passed. 0% implementation tests (threshold: 30%). No coding-guideline violations. Score penalized 10 points for test:prod inflation ratio (2.6:1 > 2:1). All three tests enforce genuine behavioral contracts of the refactored helpers: field merge precedence and stable sort order in YAML output.

Warning

Firewall blocked 1 domain

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

  • awmgmcpg

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

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

🧪 Test quality analysis by Test Quality Sentinel · 37.3 AIC · ⌖ 16.3 AIC · ⊞ 6.8K ·
Comment /review to run again

@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: 68/100. 0% implementation tests (threshold: 30%). No coding-guideline violations. Minor test inflation flagged (2.6:1 ratio) but no hard violations.

@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.

Review: Refactor runtime setup extra-field merging into shared helpers

The refactoring is clean and well-executed. The three duplication sites are correctly unified, precedence semantics (runtime defaults < user overrides) are preserved, and the new tests provide solid coverage across all three paths (gh-aw, generic runtime, Go go-version-file).

Highlights:

  • mergeRuntimeWithFields cleanly centralizes the copy-then-override pattern
  • appendSortedWithFieldEntries eliminates the repeated sorted-keys loop
  • Test coverage now locks in override behavior and deterministic ordering across all paths

Pre-existing note (not introduced by this PR): the uv early-return guard checks len(req.ExtraFields) == 0 but ignores runtime.ExtraWithFields. Since uv has no ExtraWithFields today this is safe, but a follow-up hardening would be len(req.ExtraFields) == 0 && len(runtime.ExtraWithFields) == 0.

No blocking issues. ✅

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · 51.3 AIC · ⌖ 5.87 AIC · ⊞ 4.8K

@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.

REQUEST_CHANGES — 2 new blocking issues + confirms existing findings

The refactor direction is sound — shared helpers eliminate real duplication. But there are correctness issues in both existing and new comments that need to be addressed before merging.

Blocking (new findings):

  1. ** versionless path ignores ** (line 156): The early-return guard only checks , completely ignoring . The runtime currently has no defaults, so this is a latent bug — but adding defaults to later will silently drop them with no test failure. Fix: use as the guard.

  2. Dead unreachable branch (line 112): The block in the version-defaulting section is unreachable — returns at line 107. Future maintainers who add gh-aw version defaulting logic here will be surprised when it never runs.

Confirming existing critical finding

The existing review's top finding (duplicate key at line 146) is correct and should be treated as blocking. If contains , the generated YAML will have two conflicting entries — with the hardcoded value losing under last-value-wins semantics, inverting the advertised override precedence.

Test gaps (confirmed)

All three precedence tests (, , ) are missing assertions for the displaced runtime default values. A regression that emits duplicate keys would pass all three tests as written.

🔎 Code quality review by PR Code Quality Reviewer · 149.5 AIC · ⌖ 5.51 AIC · ⊞ 5.4K
Comment /review to run again

Comments that could not be inline-anchored

pkg/workflow/runtime_step_generator.go:156

uv early-return ignores Runtime.ExtraWithFields, silently dropping any runtime-defined defaults: The guard checks len(req.ExtraFields) == 0 but does not account for req.Runtime.ExtraWithFields; any default extra fields added to the uv runtime definition would be silently discarded on the versionless path.

<details>
<summary>💡 Suggested fix</summary>

Call mergeRuntimeWithFields first so the guard covers both field sources:

} else if runtime.ID == &quot;uv&quot; {
    withFields :…

</details>

<details><summary>pkg/workflow/runtime_step_generator.go:112</summary>

**Dead unreachable code: the `gh-aw` branch at line 112 can never execute**: The `gh-aw` path is fully handled and returned at lines 90107. The `if runtime.ID == &quot;gh-aw&quot;` check at line 112 is inside the fallthrough branch that is only reached for non-gh-aw runtimes, making it permanently dead. Any version-defaulting logic placed here silently has no effect, which will confuse future maintainers.

&lt;details&gt;
&lt;summary&gt;💡 Suggested fix&lt;/summary&gt;

Remove the dead inner branch:

```go
// Use default…

</details>

@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 /codebase-design, /improve-codebase-architecture, and /tdd — requesting changes on a few structural issues and test gaps worth addressing before merge.

📋 Key Themes & Highlights

Key Themes

  • Dead code not removed: The unreachable runtime.ID == "gh-aw" branch (line 112) survived the refactor and should be deleted.
  • Logging side-effect in pure helper: appendSortedWithFieldEntries logs internally; this was scoped to the generic path before but now fires across all three paths.
  • Helper signature over-couples to struct: mergeRuntimeWithFields accepts *RuntimeRequirement but only reads two fields — a narrower signature improves testability.
  • Override tests incomplete: Tests assert the user value is present but don't assert the runtime default is absent; that negative assertion is what actually proves override semantics.

Positive Highlights

  • ✅ Excellent motivation: three near-identical merge/sort blocks is exactly the right duplication to remove.
  • ✅ Good test strategy: all three paths (gh-aw, generic runtime, go version-file) are covered.
  • ✅ Clean helper naming: mergeRuntimeWithFields and appendSortedWithFieldEntries are immediately readable.
  • ✅ Net code reduction even including new tests — disciplined cleanup.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 85.7 AIC · ⌖ 5.87 AIC · ⊞ 6.6K
Comment /matt to run again

Comments that could not be inline-anchored

pkg/workflow/runtime_step_generator.go:63

[/codebase-design] mergeRuntimeWithFields dereferences req.Runtime without a nil guard — if a caller passes a RuntimeRequirement with a nil Runtime, this silently panics.

<details>
<summary>💡 Suggested nil guard</summary>

func mergeRuntimeWithFields(req *RuntimeRequirement) map[string]string {
    if req == nil || req.Runtime == nil {
        return map[string]string{}
    }
    allExtraFields := make(map[string]string)
    // ...
}

Callers today always populate `Runti…

pkg/workflow/runtime_step_generator.go:76

[/codebase-design] The log call inside appendSortedWithFieldEntries couples a rendering helper to a side-effectful logger, making it harder to test in isolation and noisier when called from the gh-aw path (which uses a different log prefix).

<details>
<summary>💡 Suggested approach</summary>

Move logging into the callers that have context about which runtime is being configured, or accept a logger/context as parameter. The helper's job is purely to append formatted lines — logging is …

pkg/workflow/runtime_step_generator.go:112

[/codebase-design] Dead branch: the runtime.ID == &quot;gh-aw&quot; check at line 112 is unreachable — execution always returns early from the outer if runtime.ID == &quot;gh-aw&quot; block at lines 90–108. This vestigial guard survived from before the refactor.

<details>
<summary>💡 Safe to remove</summary>

// Lines 110-117 — the inner gh-aw check can be deleted:
if version == &quot;&quot; {
    // runtime.ID == &quot;gh-aw&quot; branch is dead; only the else path is reachable here
    version = runtime.DefaultVersio</details>

<details><summary>pkg/workflow/runtime_setup_test.go:518</summary>

**[/tdd]** The ordering assertions check against a hardcoded assumption that `cache-dependency-path` sorts before `package-manager-cache` alphabeticallybut this is implicitly testing `sliceutil.SortedKeys` rather than the helper&#39;s contract. A test that directly calls `appendSortedWithFieldEntries` with a known map and asserts the resulting slice order would be a more precise unit test.

&lt;details&gt;
&lt;summary&gt;💡 Suggested unit test shape&lt;/summary&gt;

```go
func TestAppendSortedWithFieldEntries_Ord…

</details>

<details><summary>pkg/workflow/runtime_setup_test.go:543</summary>

**[/tdd]** The Go version-file test doesn&#39;t assert that the merged fields do *not* include `go-version` (the version field used by the non-mod-file path). A user who also sets `ExtraFields: {&quot;go-version&quot;: &quot;1.22&quot;}` might get unexpected double output. A negative assertion or a test for that boundary would tighten the spec.

&lt;details&gt;
&lt;summary&gt;💡 Additional assertion to consider&lt;/summary&gt;

```go
// Confirm the version-file path does not accidentally add go-version: from req.Version
assert.NotConta</details>

<details><summary>pkg/workflow/runtime_gh_aw_test.go:173</summary>

**[/tdd]** The test asserts `alpha: &#39;user&#39;` (with single quotes) because `formatYAMLValue` wraps string values in quotes, but the assertion for `beta: true` has no quotes (correct for booleans). It would strengthen the test to also assert that the *runtime* default `&#39;runtime&#39;` value for `alpha` is *not* presentconfirming override semantics, not just presence.

&lt;details&gt;
&lt;summary&gt;💡 Suggested additional assertion&lt;/summary&gt;

```go
assert.NotContains(t, content, &quot;alpha: &#39;runtime&#39;&quot;) // runtime d…

</details>

<details><summary>pkg/workflow/runtime_step_generator.go:60</summary>

**[/improve-codebase-architecture]** `mergeRuntimeWithFields` is tied to a struct (`*RuntimeRequirement`) but only uses two fields: `req.Runtime.ExtraWithFields` and `req.ExtraFields`. This tight coupling makes the function harder to reuse if a future caller has the fields but not the full struct.

&lt;details&gt;
&lt;summary&gt;💡 Consider a narrower signature&lt;/summary&gt;

```go
func mergeRuntimeWithFields(runtimeDefaults map[string]string, userFields map[string]any) map[string]string

Callers become:
`…

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill and address the unresolved blocking review feedback before rerunning checks. Open blocking review to resolve first: github-actions review from 2026-07-03T07:37:06Z (duplicate with key / precedence correctness, unreachable gh-aw branch, and uv versionless path dropping runtime extra fields).

Generated by 👨‍🍳 PR Sous Chef · 5.99 AIC · ⌖ 7.3 AIC · ⊞ 5.1K ·
Comment /souschef to run again

Copilot AI and others added 2 commits July 3, 2026 11:38
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please run the pr-finisher skill and address the unresolved blocking review feedback before rerunning checks. Open blocking review to resolve first: github-actions review from 2026-07-03T07...

Addressed in commits 14b15a4 and 8e9f437. I fixed the blocking runtime setup issues (duplicate go-version-file key prevention with explicit go-mod-file, removed unreachable gh-aw fallback branch, and preserved runtime with extras for versionless uv), added/strengthened regression tests for precedence and duplicate-key behavior, and reran local checks (make fmt, make lint, make test-unit, make test, make recompile) plus parallel validation.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, address these unresolved review items, and rerun checks once the branch is up to date:

  • github-actions:

Generated by 👨‍🍳 PR Sous Chef · 7.05 AIC · ⌖ 5.18 AIC · ⊞ 6.6K ·
Comment /souschef to run again

Copilot AI commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please run the pr-finisher skill, address these unresolved review items, and rerun checks once the branch is up to date:

  • github-actions:
    ...

Checked the latest state on the updated branch (8f062f5) and there are no remaining unresolved github-actions review items tied to the runtime setup findings; those were already addressed in 14b15a4 and 8e9f437. I reran local checks on the up-to-date branch (make fmt, make lint, make test-unit, make test, make recompile), all passed. I also investigated the current impacted-go-tests CI failure from run 28667070131; it does not reproduce locally (make test-impacted-go BASE_REF=origin/main passes).

@pelikhan pelikhan merged commit 9c16114 into main Jul 4, 2026
29 of 30 checks passed
@pelikhan pelikhan deleted the copilot/duplicate-code-fix branch July 4, 2026 02:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[duplicate-code] Duplicate Code: Extra-Field Merge Logic in generateSetupStep

4 participants