Add codemod to migrate tools.serena to shared Serena import#27403
Add codemod to migrate tools.serena to shared Serena import#27403
Conversation
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/4b18acd2-1622-4e97-8f1b-4960fd6ce6a9 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/4b18acd2-1622-4e97-8f1b-4960fd6ce6a9 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
🧪 Test Quality Sentinel ReportTest Quality Score: 95/100✅ Excellent test quality
Test Classification DetailsView All Test Classifications
Compliance Checks
Minor Observation (not a flag)The four sub-tests all assert Language Support
Verdict
📖 Understanding Test ClassificationsDesign Tests (High Value) verify what the system does:
Implementation Tests (Low Value) verify how the system does it:
Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators. References: §24680939253
|
There was a problem hiding this comment.
✅ Test Quality Sentinel: 95/100. Test quality is excellent — 0% of new tests are implementation tests (threshold: 30%). All 4 sub-tests in the new codemod test file verify observable behavioral contracts with proper error checking, edge cases (duplicate prevention, no-op path), and descriptive assertion messages. No coding-guideline violations detected.
There was a problem hiding this comment.
Pull request overview
Adds a new CLI codemod to migrate removed tools.serena configuration to the shared Serena workflow import (shared/mcp/serena.md), and wires it into the global codemod registry with accompanying tests.
Changes:
- Introduce
serena-tools-to-shared-importcodemod to removetools.serenaand add an equivalentimports: - uses: shared/mcp/serena.mdentry (preserving languages). - Register the new codemod in
GetAllCodemods()and update registry tests for count/ordering. - Add dedicated unit tests covering short/long Serena language syntax and duplicate-import avoidance.
Show a summary per file
| File | Description |
|---|---|
| pkg/cli/fix_codemods.go | Registers the new Serena migration codemod in the global registry. |
| pkg/cli/fix_codemods_test.go | Updates registry tests for new codemod count, presence, and ordering. |
| pkg/cli/codemod_serena_import.go | Implements the tools.serena → imports migration logic. |
| pkg/cli/codemod_serena_import_test.go | Adds unit tests for the new Serena migration codemod behavior. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (3)
pkg/cli/codemod_serena_import.go:77
extractSerenaLanguagestreats[]stringvalues differently from the[]anycase: it doesn’t trim whitespace or filter out empty strings, and it returnsokbased on the original slice length rather than the cleaned result. This can migrate invalid language entries like""or" go"into the generatedimports.with.languageslist. Consider normalizing[]stringby trimming/filtering empties (and basingokon the normalized slice length) to match the behavior of the[]anypath.
func extractSerenaLanguages(serenaAny any) ([]string, bool) {
switch serena := serenaAny.(type) {
case []string:
return sliceutil.Deduplicate(serena), len(serena) > 0
case []any:
pkg/cli/codemod_serena_import.go:208
addSerenaImportinserts a new top-levelimports:block immediately after the firstengine:line (insertAt = i + 1). Ifengine:is a mapping block (e.g.engine:\n id: ...), insertingimports:before the indented engine children will break the YAML structure. The insertion point should be after the end of the entireengineblock (or another stable top-level boundary), not just after theengine:header line.
insertAt := 0
for i, line := range lines {
if isTopLevelKey(line) && strings.HasPrefix(strings.TrimSpace(line), "engine:") {
insertAt = i + 1
break
pkg/cli/codemod_serena_import.go:201
- When an
imports:key already exists, the codemod appends an indented list entry without checking whetherimports:is declared in flow/scalar form on the same line (e.g.imports: [],imports: ["..."], orimports: shared/mcp/serena.md). In those cases, appending block-sequence lines (- uses: ...) will produce invalid YAML. Consider detecting an inline value afterimports:and rewriting it into a multi-line block sequence before appending, or falling back to a structured frontmatter rewrite forimports.
trimmed := strings.TrimSpace(line)
if isTopLevelKey(line) && strings.HasPrefix(trimmed, "imports:") {
importsIdx = i
for j := i + 1; j < len(lines); j++ {
if isTopLevelKey(lines[j]) {
importsEnd = j
break
}
}
break
}
}
if importsIdx >= 0 {
result := make([]string, 0, len(lines)+len(entry))
result = append(result, lines[:importsEnd]...)
result = append(result, entry...)
result = append(result, lines[importsEnd:]...)
return result
- Files reviewed: 4/4 changed files
- Comments generated: 2
| t.Run("migrates tools.serena short syntax to imports", func(t *testing.T) { | ||
| content := `--- | ||
| engine: copilot | ||
| tools: | ||
| serena: ["go", "typescript"] | ||
| strict: false | ||
| --- | ||
|
|
||
| # Test Workflow | ||
| ` | ||
| frontmatter := map[string]any{ |
There was a problem hiding this comment.
The new codemod tests cover the common block-style YAML cases, but they don’t exercise the edge cases that the implementation is currently sensitive to (e.g. engine: as a mapping block and imports: declared in flow/scalar form like imports: []). Adding focused cases for these formats would help prevent regressions and would have caught the YAML-invalid insertion paths.
| languages, ok := extractSerenaLanguages(serenaAny) | ||
| if !ok || len(languages) == 0 { | ||
| serenaImportCodemodLog.Print("Found tools.serena but languages configuration is invalid or empty - skipping migration; verify tools.serena languages are set") | ||
| return content, false, nil | ||
| } |
There was a problem hiding this comment.
If tools.serena is present but the languages value is invalid/empty, the codemod currently returns (content, false, nil) and leaves tools.serena in place (lines 39-43). Since tools.serena is no longer a recognized built-in tool (and workflows using it fail to compile per the docs), it’s safer for the codemod to still remove tools.serena even when it cannot confidently construct the replacement import (optionally logging a warning that the user must add imports: - uses: shared/mcp/serena.md manually).
This issue also appears in the following locations of the same file:
- line 73
- line 183
- line 204
Summary
tools.serenatoimportswithshared/mcp/serena.mdwith.languages(short and long syntax supported)tools.serenaValidation
go test -v -run "TestSerenaToSharedImportCodemod|TestGetAllCodemods" ./pkg/cli/✅make agent-finishsecurity-gosecdue to pre-existing repository findings unrelated to this change