Skip to content

Comments

refactor: extract applyFrontmatterLineTransform to eliminate duplicate codemod boilerplate#18050

Merged
pelikhan merged 2 commits intomainfrom
copilot/refactor-codemod-frontmatter-pattern
Feb 24, 2026
Merged

refactor: extract applyFrontmatterLineTransform to eliminate duplicate codemod boilerplate#18050
pelikhan merged 2 commits intomainfrom
copilot/refactor-codemod-frontmatter-pattern

Conversation

Copy link
Contributor

Copilot AI commented Feb 24, 2026

Every codemod Apply function repeated the same parse→transform→reconstruct skeleton across 20+ files, making consistent fixes and behavior changes difficult to propagate.

Changes

  • New helper applyFrontmatterLineTransform in codemod_yaml_utils.go wraps the shared boilerplate — parseFrontmatterLines, early-return on no-op, and reconstructContent — accepting a func([]string) ([]string, bool) transform callback
  • Refactored all 20 codemods to use the helper, eliminating ~150 net lines
  • Removed dead stdlib wrappers (trimLine/startsWith in codemod_bash_anonymous.go; getTrimmedLine/startsWithKey/isComment/startsWithPrefix/trimSpace in codemod_slash_command.go) that duplicated strings.TrimSpace and strings.HasPrefix

Before / After

// Before — repeated in every codemod
frontmatterLines, markdown, err := parseFrontmatterLines(content)
if err != nil {
    return content, false, err
}
result := make([]string, len(frontmatterLines))
var modified bool
for i, line := range frontmatterLines {
    // transform logic...
}
if !modified {
    return content, false, nil
}
return reconstructContent(result, markdown), true, nil

// After
return applyFrontmatterLineTransform(content, func(lines []string) ([]string, bool) {
    // transform logic only
})

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw GO111MODULE /opt/hostedtoolcache/go/1.25.0/x--show-toplevel git t-85�� k/gh-aw/gh-aw/.github/workflows/ai-moderator.md go /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet -json GO111MODULE e/git /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw git /usr/bin/git git init�� /usr/bin/git git /usr/bin/docker --show-toplevel git /usr/bin/git docker (http block)
  • https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha --show-toplevel go /usr/lib/sysstat/sadc t2908156110/.gitgit GO111MODULE ache/go/1.25.0/x--show-toplevel /usr/lib/sysstat/sadc -F -L l /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/compile 1 1 /var/log/sysstat--show-toplevel /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha --show-toplevel ache/go/1.25.0/x64/pkg/tool/linux_amd64/vet /usr/bin/git --show-toplevel 64/pkg/tool/linurev-parse /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git --show-toplevel git 5225647/b430/vet--show-toplevel git (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v3
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha --get-regexp ^remote\..*\.gh-resolved$ /usr/bin/git -json GO111MODULE 64/bin/go git -C 3052-39007/test-895938487/.github/workflows rev-parse .cfg -json GO111MODULE 64/bin/go git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha --show-toplevel /usr/bin/git 64/bin/go --get-regexp ^remote\..*\.gh-config 0/x64/bin/node git-upload-pack orig�� ache/go/1.25.0/x--show-toplevel bash /usr/bin/git ithub/workflows/git 5101531/b381/imprev-parse ache/go/1.25.0/x--show-toplevel git (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v4 --jq .object.sha blog-auditor.md .github/workflows/test.md 889464/b001/importcfg.link ck '**/*.cjs' '*git GO111MODULE 64/bin/go vPBDs1ZUP6CSK/A-DRCM7Vqhhwhhr6k1-dwarf=false rev-�� runs/20260224-043052-39007/test-go1.25.0 go 0/x64/bin/node l GO111MODULE ache/go/1.25.0/x--show-toplevel /usr/bin/git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v4 --jq .object.sha --show-toplevel go Name,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle GoFiles,Export,Dgit GO111MODULE ache/go/1.25.0/x--show-toplevel git rev-�� --show-toplevel go /usr/bin/gh b/workflows GO111MODULE ache/go/1.25.0/x--show-toplevel gh (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v4 --jq .object.sha /tmp/gh-aw-test-runs/20260224-043052-39007/test-1240132269 status /usr/bin/git .github/workflowgit (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v5
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha runs/20260224-042816-37683/test-4145145633 test@example.com x_amd64/link -json GO111MODULE 64/bin/go x_amd64/link rev-�� :latest go 64/pkg/tool/linux_amd64/vet -json GO111MODULE de/node/bin/sh Na/UQQ8CcwpYVTOJe-jYmC-/BghG0r2UaJqs0lL-qm2s (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --noprofile node ache/node/24.13.0/x64/bin/node --check **/*.cjs tnet/tools/bash git t-34�� bility_SameInputSameOutput3125363097/001/stability-test.md rev-parse /usr/bin/git 4072122690/.githgit GO111MODULE /opt/hostedtoolc--show-toplevel git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --git-dir git /usr/bin/git --show-toplevel GOPROXY /usr/bin/infocmp--show-toplevel git init�� herFiles,CFiles,user.name infocmp /opt/hostedtoolcache/node/24.13.0/x64/bin/node xterm-color go x_amd64/cgo /opt/hostedtoolcache/node/24.13.0/x64/bin/node (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v8
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha GOSUMDB GOWORK 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env json' --ignore-pGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha vaScript814853199/001/test-simpl-test.timeout=10m0s go 0/x64/bin/node ck '**/*.cjs' '*git GO111MODULE ache/go/1.25.0/x--show-toplevel git t-ha�� SameOutput3125363097/001/stability-test.md test@example.com /usr/bin/git ub/workflows GO111MODULE ache/go/1.25.0/x--show-toplevel /usr/bin/git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha --show-toplevel git /usr/bin/git user.email test@example.comrev-parse /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git test.txt go /usr/bin/git git (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha --git-dir go Name,createdAt,startedAt,updated-buildmode=exe ck '**/*.cjs' '*git GO111MODULE tartedAt,updated--show-toplevel 64/pkg/tool/linux_amd64/link remo�� eutil.test origin ortcfg.link -json GO111MODULE ache/go/1.25.0/x--show-toplevel FpiJ9ENbZatjTay5oJ/BhqTCoRMGewfss9ZXZGY/X4XoDkfiiEtxJ64HjgrP (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha --show-toplevel git /usr/bin/git -pack /tmp/go-build405rev-parse (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/1/artifacts
    • Triggering command: /usr/bin/gh gh run download 1 --dir test-logs/run-1 GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env .js' --ignore-path .prettierignoGOSUMDB GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run download 1 --dir test-logs/run-1 GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE sh -c "prettier" --check '**/*.cjs' '**/*.ts' '**/*.json' --ignore-patGOINSECURE GOPROXY ache/go/1.25.0/x64/bin/go GOSUMDB GOWORK 64/bin/go go (http block)
    • Triggering command: /usr/bin/gh gh run download 1 --dir test-logs/run-1 /tmp/go-build3295911744/b001/_te-ifaceassert /usr/bin/git json' --ignore-p/tmp/go-build4055225647/b422/testutil.test GO111MODULE ules/.bin/node fp/NMwnngRe6Bnkr-test.v=true rev-�� --git-dir go d5c3131b8141e162-test.short=true -json GO111MODULE 64/bin/go git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12345/artifacts
    • Triggering command: /usr/bin/gh gh run download 12345 --dir test-logs/run-12345 GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env .js' --ignore-pa.github/workflows/test.md GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run download 12345 --dir test-logs/run-12345 GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE sh -c "prettier" --che@{u} GOPROXY ache/go/1.25.0/x64/bin/go GOSUMDB GOWORK 64/bin/go go (http block)
    • Triggering command: /usr/bin/gh gh run download 12345 --dir test-logs/run-12345 origin x_amd64/vet json' --ignore-pgit GO111MODULE 64/bin/go x_amd64/vet rev-�� runs/20260224-042816-37683/test-remote.origin.url go /usr/bin/git l GO111MODULE 64/bin/go git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12346/artifacts
    • Triggering command: /usr/bin/gh gh run download 12346 --dir test-logs/run-12346 GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env .js' --ignore-pa@{u} GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run download 12346 --dir test-logs/run-12346 GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE sh -c "prettier" --check '**/*.cjs' '**/*.ts' '**/*.json' --ignore-patGOINSECURE GOPROXY ache/go/1.25.0/x64/bin/go GOSUMDB GOWORK 64/bin/go go (http block)
    • Triggering command: /usr/bin/gh gh run download 12346 --dir test-logs/run-12346 test@example.com x_amd64/link json' --ignore-pnode GO111MODULE 64/bin/go x_amd64/link rev-�� runs/20260224-042816-37683/test-4072122690/.github/workflows go /usr/bin/git th .prettierignogit GO111MODULE 64/bin/go G7/NMwnngRe6Bnkrtest@example.com (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/2/artifacts
    • Triggering command: /usr/bin/gh gh run download 2 --dir test-logs/run-2 GO111MODULE ndor/bin/sh GOINSECURE GOMOD GOMODCACHE go env .js' --ignore-path .prettierignoGOSUMDB GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run download 2 --dir test-logs/run-2 GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE sh -c "prettier" --che.github/workflows/test.md GOPROXY ache/go/1.25.0/x64/bin/go GOSUMDB GOWORK 64/bin/go go (http block)
    • Triggering command: /usr/bin/gh gh run download 2 --dir test-logs/run-2 go /usr/bin/git json' --ignore-pgit GO111MODULE 64/bin/go git -C /tmp/gh-aw-test-runs/20260224-042609-36663/test-1270580111 rev-parse /usr/bin/git @{u} GO111MODULE 64/bin/go git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/3/artifacts
    • Triggering command: /usr/bin/gh gh run download 3 --dir test-logs/run-3 GO111MODULE tartedAt,updatedAt,event,headBranch,headSha,displayTitle GOINSECURE GOMOD GOMODCACHE go env .js' --ignore-path .prettierignoGOSUMDB GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run download 3 --dir test-logs/run-3 GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE sh -c "prettier" --che@{u} GOPROXY ache/go/1.25.0/x64/bin/go GOSUMDB GOWORK 64/bin/go go (http block)
    • Triggering command: /usr/bin/gh gh run download 3 --dir test-logs/run-3 go /usr/bin/git json' --ignore-pgit GO111MODULE 64/bin/go git -C runs/20260224-042816-37683/test-2732982896/.github/workflows status /usr/bin/git l GO111MODULE 64/bin/go git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/4/artifacts
    • Triggering command: /usr/bin/gh gh run download 4 --dir test-logs/run-4 GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env .js' --ignore-path .prettierignoGOSUMDB GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run download 4 --dir test-logs/run-4 GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE sh -c "prettier" --check '**/*.cjs' '**/*.ts' '**/*.json' --ignore-patGOINSECURE GOPROXY Name,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle GOSUMDB GOWORK 64/bin/go go (http block)
    • Triggering command: /usr/bin/gh gh run download 4 --dir test-logs/run-4 rev-parse /usr/bin/git json' --ignore-pgit GO111MODULE 64/bin/go git rese�� HEAD .github/workflows/test.md /usr/bin/git th .prettierignogit GO111MODULE 64/bin/go git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/5/artifacts
    • Triggering command: /usr/bin/gh gh run download 5 --dir test-logs/run-5 GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env .js' --ignore-path .prettierignoGOSUMDB GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run download 5 --dir test-logs/run-5 GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE sh -c "prettier" --check '**/*.cjs' '**/*.ts' '**/*.json' --ignore-patGOINSECURE GOPROXY ache/go/1.25.0/x64/bin/go GOSUMDB GOWORK 64/bin/go go (http block)
    • Triggering command: /usr/bin/gh gh run download 5 --dir test-logs/run-5 config /usr/bin/git remote.origin.urnode GO111MODULE ules/.bin/pretti/tmp/TestHashStability_SameInputSameOutput3125363097/001/stability-test.md git chec�� .github/workflows/test.md go /usr/bin/git -json GO111MODULE 64/bin/go git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path GOSUMDB GOWORK 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE _modules/.bin/shGOMODCACHE GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 100 GOMOD GOMODCACHE go env 4b62a6f5921b98e3GOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 6 GOMOD GOMODCACHE go tion�� -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha master go /usr/bin/git -json GO111MODULE 64/bin/go git rev-�� ty-test.md go ps -json GO111MODULE 64/bin/go ps (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha --show-toplevel x_amd64/link /usr/bin/git matter-with-arragit test@example.comrev-parse /usr/bin/git git rev-�� v1.0.0 uV/nLUya0DMdbzlh8afRszc/J-5ptimqu69dtnPwupbS /usr/bin/git --show-toplevel go 64/pkg/tool/linu--show-toplevel git (http block)
  • https://api.github.com/repos/nonexistent/action/git/ref/tags/v999.999.999
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq .object.sha r/test-repo/actions/secrets go /usr/bin/git -json GO111MODULE 64/bin/go git rev-�� k/gh-aw/gh-aw/.github/workflows go /usr/bin/git -json GO111MODULE 64/bin/go git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq .object.sha --show-toplevel x_amd64/vet /usr/bin/git tructions-test-4git go /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git --show-toplevel (http block)
  • https://api.github.com/repos/nonexistent/repo/actions/runs/12345
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion GOINSECURE GOMOD GOMODCACHE node /hom�� --check **/*.cjs ache/go/1.25.0/x64/bin/go **/*.json --ignore-path ../../../.pretti--show-toplevel go (http block)
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion on' --ignore-patgit GO111MODULE 64/bin/go x_amd64/link rev-�� --show-toplevel go /usr/bin/git -json GO111MODULE 64/bin/go HC/wPHmRHH07drGotDxh6_4/9rUbv3kNremote.origin.url (http block)
  • https://api.github.com/repos/owner/repo/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 64/bin/go GOINSECURE GOMOD (http block)
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo /opt/hostedtoolcache/go/1.25.0/x64/bin/go -p main -lang=go1.25 go env 2804548131/custom/workflows GO111MODULE /opt/hostedtoolcache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/owner/repo/contents/file.md
    • Triggering command: /tmp/go-build3295911744/b001/cli.test /tmp/go-build3295911744/b001/cli.test -test.testlogfile=/tmp/go-build3295911744/b001/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.run=Test GOSUMDB GOWORK 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /tmp/go-build1979182845/b001/cli.test /tmp/go-build1979182845/b001/cli.test -test.testlogfile=/tmp/go-build1979182845/b001/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.run=Test */*.ts' '**/*.json' --ignore-patGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /tmp/go-build4055225647/b381/cli.test /tmp/go-build4055225647/b381/cli.test -test.testlogfile=/tmp/go-build4055225647/b381/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true tierignore GO111MODULE 64/bin/go go env -json GO111MODULE /opt/hostedtoolcache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/test-owner/test-repo/actions/secrets
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name GOSUMDB GOWORK 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE ode_modules/.binGOMODCACHE GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name -json GO111MODULE x_amd64/link GOINSECURE GOMOD GOMODCACHE x_amd64/link env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name -json GOCACHE /opt/hostedtoolcache/go/1.25.0/x64/bin/go tierignore GO111MODULE 64/bin/go go env 2502136522/.gith--workflow GO111MODULE /opt/hostedtoolc--limit GOINSECURE GOMOD GOMODCACHE go (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Duplicate Code: Codemod frontmatter line-walk/replace pattern</issue_title>
<issue_description># 🔍 Duplicate Code Detected: Codemod frontmatter line-walk/replace pattern

Analysis of commit e750213

Assignee: @copilot

Summary

Multiple codemod implementations repeat the same frontmatter line-walk, block-tracking, replace, and reconstruction pattern. This is duplicated across many pkg/cli/codemod_*.go files and exceeds the duplication threshold.

Duplication Details

Pattern: Frontmatter line walk with block tracking and replacement

  • Severity: Medium
  • Occurrences: 3+ (seen across many codemods)
  • Locations:
    • pkg/cli/codemod_slash_command.go (lines 9-89)
    • pkg/cli/codemod_assign_to_agent.go (lines 12-125)
    • pkg/cli/codemod_permissions.go (lines 12-85)
  • Code Sample:
frontmatterLines, markdown, err := parseFrontmatterLines(content)
if err != nil {
	return content, false, err
}

var modified bool
result := make([]string, len(frontmatterLines))

for i, line := range frontmatterLines {
	trimmedLine := strings.TrimSpace(line)
	// block tracking and replacement logic...
	result[i] = line
}

if !modified {
	return content, false, nil
}

newContent := reconstructContent(result, markdown)
return newContent, true, nil

Impact Analysis

  • Maintainability: Changes to block-walk behavior (indent handling, comment skipping, etc.) must be made in many files.
  • Bug Risk: Inconsistent fixes across codemods can create subtle YAML parsing differences.
  • Code Bloat: Repeated 50–100 line loops across codemods increases file size and review overhead.

Refactoring Recommendations

  1. Extract a shared helper in pkg/cli/codemod_yaml_utils.go

    • Provide a utility that takes frontmatter lines, a block key, and a line transform callback.
    • Estimated effort: medium (2–4 hours)
    • Benefits: single source of truth for block-walk behavior and indentation handling.
  2. Standardize codemod apply flow

    • Build a small scaffold helper like applyFrontmatterLineTransform(content, fn) to handle parse/reconstruct boilerplate.
    • Estimated effort: low to medium (1–2 hours)
    • Benefits: removes repeated parse/reconstruct code and ensures consistent error handling.

Implementation Checklist

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

Analysis Metadata

  • Analyzed Files: 3 core codemod files (pattern appears in many more)
  • Detection Method: Serena semantic code analysis
  • Commit: e750213
  • Analysis Date: February 24, 2026

Generated by Duplicate Code Detector

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

…uplicate codemod pattern

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor duplicate frontmatter line-walk patterns in codemods refactor: extract applyFrontmatterLineTransform to eliminate duplicate codemod boilerplate Feb 24, 2026
@pelikhan pelikhan marked this pull request as ready for review February 24, 2026 04:52
Copilot AI review requested due to automatic review settings February 24, 2026 04:52
Copy link
Contributor

Copilot AI left a comment

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 successfully extracts a common applyFrontmatterLineTransform helper function to eliminate duplicate boilerplate code across 20+ codemod files, improving maintainability and reducing code by approximately 150 net lines.

Changes:

  • Introduced applyFrontmatterLineTransform helper function that encapsulates the parse→transform→reconstruct pattern
  • Refactored all 20 applicable codemods to use the new helper, each passing a custom transform callback
  • Removed dead stdlib wrapper functions (trimLine, startsWith, getTrimmedLine, startsWithKey, isComment, startsWithPrefix, trimSpace) in favor of standard strings.TrimSpace and strings.HasPrefix

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
pkg/cli/codemod_yaml_utils.go Added new applyFrontmatterLineTransform helper that wraps parse/reconstruct boilerplate
pkg/cli/codemod_yaml_utils_test.go Comprehensive tests for the new helper covering transforms, no-ops, and edge cases
pkg/cli/codemod_timeout_minutes.go Simplified to use helper, reducing from ~40 to ~20 lines
pkg/cli/codemod_upload_assets.go Refactored block-tracking logic to use helper
pkg/cli/codemod_slash_command.go Removed 5 stdlib wrapper functions; uses helper with inline transform
pkg/cli/codemod_schedule.go Complex multi-pattern transform refactored to use helper
pkg/cli/codemod_sandbox_agent.go Simplified line manipulation logic
pkg/cli/codemod_safe_inputs.go Now delegates to existing removeFieldFromBlock via helper
pkg/cli/codemod_roles.go Complex multi-pass transform refactored to use helper
pkg/cli/codemod_playwright_domains.go Domain collection and network update logic refactored
pkg/cli/codemod_permissions.go Both functions refactored (read-all/write-all and write-to-read migrations)
pkg/cli/codemod_network_firewall.go Firewall removal and sandbox.agent addition refactored
pkg/cli/codemod_mcp_network.go MCP server network migration refactored
pkg/cli/codemod_mcp_mode_to_type.go Simplified to delegate existing transform via helper
pkg/cli/codemod_install_script_url.go URL replacement logic refactored
pkg/cli/codemod_grep_tool.go Tool removal delegated via helper
pkg/cli/codemod_expires_integer.go Integer-to-string conversion delegated via helper
pkg/cli/codemod_engine_steps.go Highly complex engine.steps migration refactored (200+ lines)
pkg/cli/codemod_discussion_flag.go Discussion flag removal refactored
pkg/cli/codemod_bots.go Bot migration logic refactored
pkg/cli/codemod_bash_anonymous.go Removed 2 stdlib wrapper functions; refactored to use helper
pkg/cli/codemod_assign_to_agent.go Assign-to-agent field renaming refactored
pkg/cli/codemod_agent_session.go Agent task-to-session migration refactored

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

Comment on lines +125 to +127
if modified {
scheduleCodemodLog.Print("Applied schedule 'at' to 'around' migration")
}
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

The logging placement is inconsistent across the refactored codemods. Some files (like codemod_timeout_minutes.go, codemod_upload_assets.go) place the success log outside the transform function in an if applied block, while others (like this file and codemod_install_script_url.go) place it inside the transform function with an if modified check.

For consistency and to match the original behavior where logging happened after all processing was complete, all codemods should follow the same pattern of logging outside the transform in the if applied block.

Copilot uses AI. Check for mistakes.
Comment on lines +46 to +48
if modified {
installScriptURLCodemodLog.Print("Applied install script URL migration")
}
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

The logging placement is inconsistent with other refactored codemods. Some files place the success log outside the transform function in an if applied block (like codemod_timeout_minutes.go, codemod_upload_assets.go), while this file places it inside the transform function.

For consistency and to match the original behavior where logging happened after all processing was complete, all codemods should follow the same pattern of logging outside the transform in the if applied block.

Copilot uses AI. Check for mistakes.
},
wantApplied: false,
},
{
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

The test case "content with no frontmatter is handled gracefully" expects the transform to return false for the modified flag. However, there's no test verifying what happens when parseFrontmatterLines returns an error.

Consider adding a test case that verifies error handling from parseFrontmatterLines, such as:

  • Malformed frontmatter (e.g., missing closing ---)
  • Empty content
  • Content that starts with --- but has no closing delimiter

This would ensure the error propagation path works correctly.

Suggested change
{
{
name: "malformed frontmatter returns error",
content: `---
on: workflow_dispatch
# missing closing '---' delimiter`,
transform: func(lines []string) ([]string, bool) {
// In error cases, the transform should not be applied.
return lines, false
},
wantApplied: false,
wantErr: true,
},
{

Copilot uses AI. Check for mistakes.
@pelikhan pelikhan merged commit 8cbe287 into main Feb 24, 2026
120 checks passed
@pelikhan pelikhan deleted the copilot/refactor-codemod-frontmatter-pattern branch February 24, 2026 04:58
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.

Duplicate Code: Codemod frontmatter line-walk/replace pattern

2 participants