Skip to content

refactor(workflow): break up largefunc violations in maintenance/compiler YAML builders#46335

Closed
pelikhan with Copilot wants to merge 6 commits into
mainfrom
copilot/lint-monster-reduce-largefunc-findings-again
Closed

refactor(workflow): break up largefunc violations in maintenance/compiler YAML builders#46335
pelikhan with Copilot wants to merge 6 commits into
mainfrom
copilot/lint-monster-reduce-largefunc-findings-again

Conversation

Copilot AI commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Five functions in pkg/workflow exceeded the 60-line largefunc lint limit, with buildMaintenanceWorkflowYAML at 961 lines being the primary offender. Pure behavioral-preserving refactor — emitted YAML and all external interfaces are unchanged.

Changes

maintenance_workflow_yaml.go + new maintenance_workflow_yaml_sections.go

Extracted ~13 per-job helpers from the monolithic 961-line buildMaintenanceWorkflowYAML. The main function is now a thin orchestrator:

func buildMaintenanceWorkflowYAML(ctx context.Context, opts buildMaintenanceWorkflowYAMLOptions) string {
    var yaml strings.Builder
    writeMaintenanceWorkflowHeaderAndTriggers(&yaml, opts, ...)
    writeCloseExpiredJobs(&yaml, opts, ...)
    writeCleanupCacheJob(&yaml, opts, ...)
    writeRunOperationJob(ctx, &yaml, opts, ...)
    // ... one call per job section
    return yaml.String()
}

compiler_yaml_prompt.go

Split generatePrompt (284 lines) by extracting import-processing and expression-merging phases into focused helpers.

compiler_yaml_header.go

Split generateWorkflowHeader (172 lines) into separate metadata-line writer and comment-block writer.

compiler_yaml_step_lifecycle.go

Split generateCreateAwInfo (180 lines) into param-resolution + YAML env-var writing helpers; split generateOutputCollectionStep (82 lines) into step and domain-resolution helpers.

Copilot AI and others added 2 commits July 18, 2026 03:52
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor workflow YAML generation to reduce long function lengths refactor(workflow): break up largefunc violations in maintenance/compiler YAML builders Jul 18, 2026
Copilot AI requested a review from pelikhan July 18, 2026 04:24
@github-actions

Copy link
Copy Markdown
Contributor

Hi @app/copilot-swe-agent 👋 — thanks for the detailed refactor summary. The work appears on-topic and reasonably focused, but this repository's contribution policy requires non-core contributors to open issues with agentic plans rather than direct PRs.

Also, for a structural refactor of this size (2970 lines), there are no test file changes in the diff — a follow-up plan should explicitly cover validation.

Please replace this PR with a GitHub issue in github/gh-aw.
In the issue, include:
- the largefunc findings being addressed
- the intended refactor boundaries
- why behavior should remain unchanged
- the exact validation plan (tests/build/lint/recompile if needed)
- links to this PR and the related issue numbers

A core team member can then implement or sponsor the change through the project's normal agentic workflow.

Generated by ✅ Contribution Check · 77.3 AIC · ⌖ 8.93 AIC · ⊞ 6.2K ·

@pelikhan
pelikhan marked this pull request as ready for review July 18, 2026 05:48
Copilot AI review requested due to automatic review settings July 18, 2026 05:48

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

Refactors oversized workflow YAML generators into focused helpers while preserving public interfaces.

Changes:

  • Splits maintenance workflow generation into section builders.
  • Extracts prompt, header, lifecycle, and output helpers.
  • Refreshes action-version annotations in four generated lock files.
Show a summary per file
File Description
pkg/workflow/maintenance_workflow_yaml.go Converts maintenance generation into orchestration.
pkg/workflow/maintenance_workflow_yaml_sections.go Adds maintenance section templates and builders.
pkg/workflow/compiler_yaml_step_lifecycle.go Extracts lifecycle parameter and output helpers.
pkg/workflow/compiler_yaml_prompt.go Splits prompt import and expression processing.
pkg/workflow/compiler_yaml_header.go Extracts workflow header writers.
.github/workflows/skillet.lock.yml Refreshes generated action annotations.
.github/workflows/release.lock.yml Refreshes generated setup-go annotation.
.github/workflows/hourly-ci-cleaner.lock.yml Refreshes generated checkout annotations.
.github/workflows/avenger.lock.yml Refreshes generated checkout annotations.

Review details

Tip

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

  • Files reviewed: 9/9 changed files
  • Comments generated: 5
  • Review effort level: Medium

Comment thread pkg/workflow/compiler_yaml_prompt.go Outdated
Comment on lines +70 to +71
if len(data.PromptImports) > 0 {
return buildOrderedPromptImportChunks(c, data)
GH_AW_INFO_ENGINE_ID: "copilot"
- name: Checkout skills directory
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # 9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
RELEASE_TAG: ${{ needs.config.outputs.release_tag }}
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # b7ad1dad31e06c5925ef5d2fc7ad053ef454303e
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV"
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # 9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV"
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # 9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
@github-actions

github-actions Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

⚠️ PR Code Quality Reviewer failed during code quality review.

@github-actions

github-actions Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

No test files were added or modified in this PR. PR #46335 contains only production code refactoring of workflow YAML builders (compiler_yaml_header.go, compiler_yaml_prompt.go, compiler_yaml_step_lifecycle.go, maintenance_workflow_yaml.go, and new maintenance_workflow_yaml_sections.go). Test Quality Sentinel analysis skipped.

@github-actions github-actions Bot mentioned this pull request Jul 18, 2026
…w YAML builders

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

Copy link
Copy Markdown
Contributor

🏗️ Design Decision Gate — ADR Required

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

📄 Draft ADR committed: docs/adr/46335-decompose-largefunc-violations-in-workflow-yaml-builders.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 at docs/adr/46335-decompose-largefunc-violations-in-workflow-yaml-builders.md — 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-46335: Decompose Largefunc Violations in Workflow YAML Builders

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., 46335-decompose-largefunc-violations-in-workflow-yaml-builders.md for PR #46335).

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · 76.5 AIC · ⌖ 10.5 AIC · ⊞ 8.5K ·
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.

Review: largefunc refactor

The refactor is well-structured and extracted helpers are clean. One correctness regression was found.

Findings:

Severity File Issue
🔴 Correctness compiler_yaml_prompt.go:71 Expression extraction from MainWorkflowMarkdown dropped for the PromptImports path
🟡 Noise *.lock.yml Action-version metadata regenerated, contradicting the "emitted YAML unchanged" claim
Correctness regression detail

In the original code, Step 1.5 (extracting needs.* expressions from MainWorkflowMarkdown) ran unconditionally — it applied to both the ordered-imports path and the legacy path.

In the refactor, that extraction only executes in buildUserPromptChunks inside the legacy branch (after buildOrderedPromptImportChunks returns early). Workflows that use PromptImports and reference needs.* expressions in their main markdown will silently produce incomplete substitution steps, causing actionlint errors or runtime failures.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · 57.5 AIC · ⌖ 4.36 AIC · ⊞ 5K

@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 — requesting changes on one correctness issue and two maintainability patterns.

📋 Key Themes & Highlights

Key Themes

  • Correctness gap (line 71, compiler_yaml_prompt.go): the buildUserPromptChunks refactor accidentally conditionalized the MainWorkflowMarkdown expression-extraction step — it now runs only in the legacy path, not when PromptImports is present. This was a single sequential block before the split.
  • Template call readability (maintenance_workflow_yaml_sections.go): several fmt.Fprintf calls pass 6–8 positional arguments in a single line against long templates; a misaligned argument silently corrupts generated YAML.
  • Intentionality of conditionals: resolveAwInfoMCPGatewayVersion dropped the Version != "" guard — behaviorally equivalent today but loses the explicit intent.

Positive Highlights

  • ✅ The builder-struct pattern for maintenanceWorkflowYAMLBuilder is clean and navigable — a marked improvement over the 961-line monolith.
  • writeHeaderCommentBlock and its helpers decompose the header into single-responsibility writers that are easy to test independently.
  • ✅ The awInfoParams struct is a good deep-module move: all resolution logic is co-located and the write step becomes trivially thin.
  • ✅ Lock file changes are all trivial metadata-only diffs — consistent with the PR's behavioral-equivalence claim.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 126.6 AIC · ⌖ 4.91 AIC · ⊞ 6.7K
Comment /matt to run again

Comment thread pkg/workflow/compiler_yaml_prompt.go Outdated
compilerYamlPromptLog.Printf("Inlined main workflow markdown in %d chunks", len(inlinedChunks))
func buildUserPromptChunks(c *Compiler, data *WorkflowData) ([]string, []*ExpressionMapping) {
if len(data.PromptImports) > 0 {
return buildOrderedPromptImportChunks(c, data)

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.

[/codebase-design] buildUserPromptChunks early-returns on line 71 for the ordered-import path, so the MainWorkflowMarkdown expression-extraction guard (lines 74–82) is only reachable in the legacy path. In the original monolith, that extraction ran after both import paths; the split accidentally conditionalized it.

💡 Impact & suggested fix

When a workflow uses PromptImports (the non-legacy path), needs.* expressions in the main markdown body will not be extracted, which means the substitute-placeholders step will later emit unresolved __EXPR_*__ placeholders at runtime.

Consider moving the MainWorkflowMarkdown extraction into buildOrderedPromptImportChunks, or lifting it into generatePrompt after both helpers return.

@copilot please address this.

if data.SandboxConfig != nil && data.SandboxConfig.MCP != nil && data.SandboxConfig.MCP.Version != "" {
mcpGatewayVersion = data.SandboxConfig.MCP.Version
func resolveAwInfoMCPGatewayVersion(data *WorkflowData) string {
if data.SandboxConfig != nil && data.SandboxConfig.MCP != nil {

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.

[/codebase-design] resolveAwInfoMCPGatewayVersion returns data.SandboxConfig.MCP.Version unconditionally when MCP != nil, but the original code only set mcpGatewayVersion when Version != "". If Version is an empty string, the old path left mcpGatewayVersion as "", which is the same result here — so this is behaviorally safe. However the comment (Version != "") was load-bearing documentation that is now silently gone.

💡 Suggested improvement

The original conditional was there to make the intent explicit. Consider re-adding the guard:

func resolveAwInfoMCPGatewayVersion(data *WorkflowData) string {
	if data.SandboxConfig != nil && data.SandboxConfig.MCP != nil && data.SandboxConfig.MCP.Version != "" {
		return data.SandboxConfig.MCP.Version
	}
	return ""
}

This makes the "only set when non-empty" intent visible at the extractor level rather than relying on the zero-value coincidence.

@copilot please address this.

if b.opts.maintenanceConfig.IsJobDisabled("close-expired-entities") {
return
}
jobs := []maintenanceCloseExpiredJob{{"close-expired-discussions", "discussions: write", "Close expired discussions", "close_expired_discussions"}, {"close-expired-issues", "issues: write", "Close expired issues", "close_expired_issues"}, {"close-expired-pull-requests", "pull-requests: write", "Close expired pull requests", "close_expired_pull_requests"}}

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.

[/codebase-design] The three maintenanceCloseExpiredJob literals are packed into a single long slice literal on one line (line 624), which is hard to scan and would fail a longline linter if one is ever added.

💡 Suggested formatting
jobs := []maintenanceCloseExpiredJob{
    {"close-expired-discussions",   "discussions: write",    "Close expired discussions",   "close_expired_discussions"},
    {"close-expired-issues",        "issues: write",         "Close expired issues",        "close_expired_issues"},
    {"close-expired-pull-requests", "pull-requests: write",  "Close expired pull requests", "close_expired_pull_requests"},
}

Minor, but the extracted helper is otherwise a clean pattern — do not undercut it with an opaque one-liner.

@copilot please address this.

}

func (b *maintenanceWorkflowYAMLBuilder) writeRunOperationJob() {
fmt.Fprintf(b.yaml, maintenanceRunOperationJobTemplate, RenderCondition(buildRunOperationCondition("safe_outputs", "create_labels", "activity_report", "close_agentic_workflows_issues", "clean_cache_memories", "update_pull_request_branches", "validate", "forecast")), b.opts.runsOnValue, b.repositoryCheckoutBlock(), b.setupScriptsBlock(), b.adminPermissionsBlock(""), generateInstallCLISteps(b.ctx, b.opts.actionMode, b.opts.version, b.opts.actionTag, b.opts.resolver), b.githubScriptPin(), getCLICmdPrefix(b.opts.actionMode))

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.

[/codebase-design] writeRunOperationJob calls fmt.Fprintf with 8 positional arguments on a single line. This is harder to maintain than the original inline construction because a new argument requires counting format verbs.

💡 Suggested improvement

Extract the template arguments to named locals before the Fprintf call, so each argument is self-documenting:

func (b *maintenanceWorkflowYAMLBuilder) writeRunOperationJob() {
    condition := RenderCondition(buildRunOperationCondition(...))
    repoCheckout := b.repositoryCheckoutBlock()
    scripts := b.setupScriptsBlock()
    adminCheck := b.adminPermissionsBlock("")
    cliSteps := generateInstallCLISteps(b.ctx, b.opts.actionMode, b.opts.version, b.opts.actionTag, b.opts.resolver)
    ghScript := b.githubScriptPin()
    cmdPrefix := getCLICmdPrefix(b.opts.actionMode)
    fmt.Fprintf(b.yaml, maintenanceRunOperationJobTemplate,
        condition, b.opts.runsOnValue,
        repoCheckout, scripts, adminCheck, cliSteps,
        ghScript, cmdPrefix)
}

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

Review: behavioral-preserving refactor with two correctness concerns

Two issues warrant attention before merging:

1. Expression extraction skipped for ordered imports (high, existing comment at line 71)
When PromptImports is non-empty, buildUserPromptChunks returns via buildOrderedPromptImportChunks without running the Step 1.5 expression extraction from MainWorkflowMarkdown. The original code always ran that step after the import branching. This drops needs.* and other compile-time expressions from the substitution step for any workflow that uses ordered imports.

2. Firewall version silently dropped when firewall disabled (medium, new comment)
resolveAwInfoFirewallVersion returns "" whenever !firewallConfig.Enabled, but the original set firewallVersion = firewallConfig.Version unconditionally and only applied the default fallback under Enabled && Version == "". The refactor silently drops a non-empty version for a disabled-but-explicitly-versioned firewall config.

Other observations (non-blocking)
  • Lock file changes (comment annotations 9c091bb...v7.0.0) are unrelated to the refactor and contradict the PR's claim that emitted YAML is unchanged (already flagged in existing comments).
  • The resolveWorkflowHeaderSource helper introduced for internal use returns a fallback string but is never called externally, keeping its scope clean.
  • mergeKnownNeedsExpressions correctly preserves the original merge-with-higher-priority semantics.

🔎 Code quality review by PR Code Quality Reviewer · 490.9 AIC · ⌖ 4.53 AIC · ⊞ 5.6K
Comment /review to run again

Comments that could not be inline-anchored

pkg/workflow/compiler_yaml_step_lifecycle.go:1079

Behavioral change in resolveAwInfoFirewallVersion: the original code set firewallVersion = firewallConfig.Version unconditionally, so a disabled-but-explicitly-versioned firewall config still emitted its version string; the refactored helper returns &quot;&quot; whenever !firewallConfig.Enabled, silently dropping a non-empty version.

<details>
<summary>💡 Detail</summary>

Original semantics:

firewallVersion = firewallConfig.Version          // set regardless of Enabled
if firewallEnab</details>

@github-actions

Copy link
Copy Markdown
Contributor

🤖 PR Triage

Field Value
Category refactor
Risk 🟡 Medium
Score 52/100 (impact:20, urgency:10, quality:22)
Action batch_review
Batch pr-batch:largefunc-refactor (with #46332)

Rationale: Mechanical largefunc lint fix across workflow YAML builders. Large diff (1441+/1575−, 10 files) but purely structural. Review together with #46332.

Generated by 🔧 PR Triage Agent · 32.1 AIC · ⌖ 7.02 AIC · ⊞ 5.6K ·

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill and address the unresolved review feedback before handing this back to maintainers.

Open review feedback to address:

Please fix the reported correctness issues, update the branch if needed, rerun relevant validation/checks, and summarize what changed plus any remaining blockers for maintainers.

Generated by PR Sous Chef: https://github.com/github/gh-aw/actions/runs/29636316820

Generated by 👨‍🍳 PR Sous Chef · 37.1 AIC · ⌖ 7.15 AIC · ⊞ 6K ·
Comment /souschef to run again

Copilot AI and others added 2 commits July 18, 2026 08:03
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 18, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please run the pr-finisher skill and address the unresolved review feedback before handing this back to maintainers.

Open review feedback to address:...

Addressed in f727227. I restored main-workflow expression extraction for the PromptImports path, preserved the explicit disabled-firewall aw_info version behavior, reinstated the MCP gateway non-empty guard, applied the requested readability cleanups in the maintenance helper, and reverted the affected generated lockfile drift. Local make fmt, make lint, make test-unit, and make test passed. CI on this head is still unverified and needs a maintainer re-trigger.

Copilot AI requested a review from gh-aw-bot July 18, 2026 08:27
@pelikhan pelikhan closed this Jul 18, 2026
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.

[lint-monster] [Code Quality] Reduce largefunc findings in pkg/workflow maintenance/compiler YAML slice

4 participants