Skip to content

[duplicate-code] Safe Output update jobs share repeated buildersΒ #5130

@github-actions

Description

@github-actions

πŸ” Duplicate Code Detected: Safe Output Update Jobs

Analysis of commit faacd5c

Assignee: @copilot

Summary

All of the newly added safe-output update jobs (issues, pull requests, releases) repeat the same job-builder scaffolding: guard clauses, environment construction, identical SafeOutputJobConfig wiring, and per-type output wiring. The three structs (UpdateIssuesConfig, UpdatePullRequestsConfig, UpdateReleaseConfig) also share the same parsing approach. This is 100+ lines of near-identical Go that will have to be updated in lock-step for every new update target.

Duplication Details

Pattern: Copy/pasted safe-output job builders

  • Severity: Medium
  • Occurrences: 3 (issues, pull requests, releases)
  • Locations:
    • pkg/workflow/update_issue.go:17-64
    • pkg/workflow/update_pull_request.go:16-66
    • pkg/workflow/update_release.go:13-45
  • Code Sample:
    return c.buildSafeOutputJob(data, SafeOutputJobConfig{
        JobName:        "update_issue",
        StepName:       "Update Issue",
        StepID:         "update_issue",
        MainJobName:    mainJobName,
        CustomEnvVars:  customEnvVars,
        Script:         getUpdateIssueScript(),
        Permissions:    NewPermissionsContentsReadIssuesWrite(),
        Outputs:        outputs,
        Condition:      jobCondition,
        Token:          data.SafeOutputs.UpdateIssues.GitHubToken,
        TargetRepoSlug: data.SafeOutputs.UpdateIssues.TargetRepoSlug,
    })
    The same block appears in update_pull_request.go and update_release.go with only string/permission swaps.

Impact Analysis

  • Maintainability: Any change to how safe-output jobs are configured (new env vars, telemetry, permissions) requires three manual edits today and will grow with every new update type.
  • Bug Risk: Easy to forget a tweak (e.g., staged-mode env vars or condition fixes) in one copy, leading to inconsistent behavior between issue vs PR updates.
  • Code Bloat: Adds ~120 LoC of boilerplate and makes it harder to understand what is unique to each update job.

Refactoring Recommendations

  1. Introduce a data-driven helper
    • Add a helper like buildUpdateJob(job SafeOutputJobConfig, opts UpdateJobOptions) that receives the varying pieces (permissions factory, number output keys, allowed fields) and shares condition/env wiring.
    • Estimated effort: 4-6 hours to extract and update the three call sites.
    • Benefits: one implementation point for staged-mode handling, token/target repo wiring, and outputs.
  2. Unify config parsing
    • Move the shared parseBaseSafeOutputConfig pattern plus target/field parsing into reusable helpers (e.g., parseUpdateTargetConfig(map[string]any, defaults)), so future update types just supply metadata.
    • Estimated effort: 2-3 hours.

Implementation Checklist

  • Review duplication findings
  • Prioritize refactoring tasks
  • Create refactoring plan
  • Implement changes
  • Update tests
  • Verify no functionality broken

Analysis Metadata

  • Analyzed Files: 335 changed .go/.cjs files (focus on new update job scaffolding)
  • Detection Method: Serena semantic code analysis + git diff inspection
  • Commit: faacd5c
  • Analysis Date: 2025-11-30

AI generated by Duplicate Code Detector

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions