Skip to content

[duplicate-code] Duplicate Code: Divergent runs-on normalization across config parsers #52973

Description

@github-actions

🔍 Duplicate Code Detected: Divergent runs-on Normalization Across Config Parsers

Analysis of commit 5e03fe022755ab7af5fcc3cf36899b4003a5544a

Assignee: @copilot

Summary

The head commit introduced another dedicated runs-on parsing path in pkg/workflow/repo_config.go and pkg/workflow/safe_jobs.go, but the codebase already has multiple independent implementations that normalize or render runs-on values.

This now spans repo config JSON, safe-jobs YAML, safe-outputs JSON, threat-detection config, evals config, and custom jobs. The duplication is no longer just cosmetic: each path supports a slightly different shape set and rendering strategy, which raises the risk of inconsistent behavior when runner syntax evolves.

Duplication Details

Pattern: repeated runs-on shape parsing and rendering logic

  • Severity: Medium
  • Occurrences: 6
  • Locations:
    • pkg/workflow/repo_config.go (lines 73-125, 473-489)
    • pkg/workflow/safe_jobs.go (lines 71-76, 241-250)
    • pkg/workflow/runs_on_unmarshal.go (lines 13-29, 35-50)
    • pkg/workflow/evals_config.go (lines 98-100)
    • pkg/workflow/threat_detection_config.go (lines 141-143)
    • pkg/workflow/compiler_custom_jobs.go (lines 245-260)
  • Code Sample:
func (r *RunsOnValue) UnmarshalJSON(data []byte) error {
	var s string
	if err := json.Unmarshal(data, &s); err == nil {
		*r = RunsOnValue{s}
		return nil
	}

	var ss []string
	if err := json.Unmarshal(data, &ss); err != nil {
		return fmt.Errorf("runs_on value is not recognized: %w", err)
	}
	*r = RunsOnValue(ss)
	return nil
}

if runsOn, exists := jobConfig["runs-on"]; exists {
	safeJob.RunsOn = toRunsOnValue(runsOn)
	safeJob.runsOnArray = isRunsOnArrayValue(runsOn)
}

if runsOnRaw, ok := v["runs-on"]; ok {
	cfg.RunsOn = renderRunsOnSnippet(runsOnRaw)
}

The same concern shows up in multiple forms:

  • some call sites preserve list-vs-string shape (safe_jobs.go)
  • some normalize directly to a YAML snippet (runs_on_unmarshal.go, evals_config.go, threat_detection_config.go)
  • some special-case strings and marshal everything else (compiler_custom_jobs.go)
  • the new repo-config path only supports string and string-array forms (repo_config.go)

Impact Analysis

  • Maintainability: adding support for new runner forms or changing normalization rules now requires touching several unrelated parsers.
  • Bug Risk: fixes can land in one parser and miss the others, leaving runs-on behavior inconsistent across config surfaces.
  • Code Bloat: the new commit increased the number of specialized helpers instead of consolidating the existing runner-shape handling.

Refactoring Recommendations

  1. Introduce a shared runs-on normalization package-level helper
    Extract common parsing/rendering into one API that can accept the supported raw shapes and return both normalized labels and rendered YAML when needed.
    Estimated effort: medium.
    Benefits: one behavior definition, one validation surface, lower regression risk.

  2. Separate parsing from rendering
    Keep a single normalized internal representation for runs-on, then render YAML only at emission sites.
    Estimated effort: medium.
    Benefits: avoids mixing config decoding rules with workflow serialization details.

  3. Add one compatibility matrix for all supported runs-on surfaces
    Cover repo config, safe-jobs, safe-outputs, threat detection, evals, and custom jobs with the same fixture set.
    Estimated effort: low to medium.
    Benefits: makes behavior drift visible before more parsers diverge.

Implementation Checklist

  • Review duplication findings
  • Prioritize refactoring tasks
  • Create refactoring plan
  • Implement changes
  • Update tests
  • Verify no functionality broken
Analysis Metadata
  • Analyzed Files: 2 changed production files (pkg/workflow/repo_config.go, pkg/workflow/safe_jobs.go)
  • Detection Method: Serena activation attempted; fallback to targeted code/pattern analysis because the runner lacks a working Go language server (go not installed)
  • Commit: 5e03fe022755ab7af5fcc3cf36899b4003a5544a
  • Analysis Date: 2026-08-15T21:55:35Z

Generated by 🔍 Duplicate Code Detector · gpt54 · 55.3 AIC · ⊞ 13K ·

  • expires on Aug 17, 2026, 1:57 PM UTC-08:00

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions