Skip to content

Commit 9914773

Browse files
authored
fix: correct stale with: version: when uses: comment and version drifted before upgrade (#20895)
1 parent 5dc8091 commit 9914773

2 files changed

Lines changed: 84 additions & 7 deletions

File tree

pkg/cli/copilot_setup.go

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,32 @@ func renderCopilotSetupUpdateInstructions(filePath string, actionMode workflow.A
299299
var setupCliUsesPattern = regexp.MustCompile(
300300
`(?m)^(\s+uses:[ \t]*)"?(github/gh-aw(?:-actions)?/(?:actions/)?setup-cli@[^"\n]*)"?([ \t]*)$`)
301301

302+
// versionInWithPattern matches the version: parameter in the with: block that immediately
303+
// follows any setup-cli uses: line (any ref format: version tag, SHA-pinned, or quoted).
304+
// It is anchored to the same action repos as setupCliUsesPattern so that it only updates
305+
// the version belonging to the setup-cli step, but is independent of the exact ref value.
306+
// This allows it to correct pre-existing drift where the uses: comment and with: version:
307+
// were already out of sync before the upgrade was run.
308+
//
309+
// Pattern breakdown:
310+
//
311+
// [ \t]+uses:[ \t]* — indented uses: key with optional surrounding spaces
312+
// "?github/gh-aw(?:-actions)?/(?:actions/)?setup-cli@[^"\n]*"?
313+
// — any setup-cli ref (version tag, SHA+comment, or quoted)
314+
// [^\n]*\n — rest of the uses: line (e.g. trailing spaces)
315+
// (?:[^\n]*\n)*? — zero or more lines between uses: and with: (non-greedy)
316+
// [ \t]+with:[ \t]*\n — indented with: key
317+
// (?:[^\n]*\n)*? — zero or more lines between with: and version: (non-greedy)
318+
// [ \t]+version:[ \t]* — indented version: key (final part of the prefix captured as group 1)
319+
// (\S+) — the version value (captured as group 2)
320+
// ([ \t]*(?:\n|$)) — trailing whitespace and line terminator (captured as group 3)
321+
//
322+
// Note: In the full pattern, group 1 wraps the entire prefix from the setup-cli `uses:` line
323+
// through the `version:` key (and following spaces), group 2 is just the version value, and
324+
// group 3 is the trailing whitespace plus the line terminator.
325+
var versionInWithPattern = regexp.MustCompile(
326+
`(?s)([ \t]+uses:[ \t]*"?github/gh-aw(?:-actions)?/(?:actions/)?setup-cli@[^"\n]*"?[^\n]*\n(?:[^\n]*\n)*?[ \t]+with:[ \t]*\n(?:[^\n]*\n)*?[ \t]+version:[ \t]*)(\S+)([ \t]*(?:\n|$))`)
327+
302328
// upgradeSetupCliVersionInContent replaces the setup-cli action reference and the
303329
// associated version: parameter in the raw YAML content using targeted regex
304330
// substitutions, preserving all other formatting in the file.
@@ -325,13 +351,9 @@ func upgradeSetupCliVersionInContent(content []byte, actionMode workflow.ActionM
325351
updated := setupCliUsesPattern.ReplaceAll(content, []byte("${1}"+newUses+"${3}"))
326352

327353
// Replace the version: value in the with: block immediately following the
328-
// setup-cli uses: line. A combined multiline match is used so that only the
329-
// version: parameter belonging to this specific step is updated.
330-
// This pattern cannot be pre-compiled at package level because it embeds
331-
// the runtime value newUses (which varies with version and resolver output).
332-
escapedNewUses := regexp.QuoteMeta(newUses)
333-
versionInWithPattern := regexp.MustCompile(
334-
`(?s)(uses:[ \t]*` + escapedNewUses + `[^\n]*\n(?:[^\n]*\n)*?[ \t]+with:[ \t]*\n(?:[^\n]*\n)*?[ \t]+version:[ \t]*)(\S+)([ \t]*(?:\n|$))`)
354+
// setup-cli uses: line. versionInWithPattern matches any valid setup-cli
355+
// reference so it succeeds even when there was pre-existing drift between
356+
// the uses: comment and the version: parameter before the upgrade was run.
335357
updated = versionInWithPattern.ReplaceAll(updated, []byte("${1}"+version+"${3}"))
336358

337359
if bytes.Equal(content, updated) {

pkg/cli/copilot_setup_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,61 @@ jobs:
11411141
resolver: nil,
11421142
expectUpgrade: false,
11431143
},
1144+
{
1145+
name: "corrects drift: SHA-pinned uses comment ahead of with: version:",
1146+
content: `jobs:
1147+
copilot-setup-steps:
1148+
steps:
1149+
- name: Install gh-aw extension
1150+
uses: github/gh-aw/actions/setup-cli@cb7966564184443e601bd6135d5fbb534300070e # v0.58.0
1151+
with:
1152+
version: v0.53.6
1153+
`,
1154+
actionMode: workflow.ActionModeRelease,
1155+
version: "v0.60.0",
1156+
resolver: &mockSHAResolver{sha: "newsha123"},
1157+
expectUpgrade: true,
1158+
validate: func(t *testing.T, got string) {
1159+
if !strings.Contains(got, "uses: github/gh-aw/actions/setup-cli@newsha123 # v0.60.0") {
1160+
t.Errorf("Expected updated SHA-pinned uses: line, got:\n%s", got)
1161+
}
1162+
if !strings.Contains(got, "version: v0.60.0") {
1163+
t.Errorf("Expected with: version: updated to v0.60.0, got:\n%s", got)
1164+
}
1165+
if strings.Contains(got, "v0.53.6") {
1166+
t.Errorf("Stale version v0.53.6 should be gone, got:\n%s", got)
1167+
}
1168+
if strings.Contains(got, "v0.58.0") {
1169+
t.Errorf("Old comment version v0.58.0 should be gone, got:\n%s", got)
1170+
}
1171+
},
1172+
},
1173+
{
1174+
name: "corrects drift: version-tag uses ahead of with: version:",
1175+
content: `jobs:
1176+
copilot-setup-steps:
1177+
steps:
1178+
- name: Install gh-aw extension
1179+
uses: github/gh-aw/actions/[email protected]
1180+
with:
1181+
version: v0.53.6
1182+
`,
1183+
actionMode: workflow.ActionModeRelease,
1184+
version: "v0.60.0",
1185+
resolver: nil,
1186+
expectUpgrade: true,
1187+
validate: func(t *testing.T, got string) {
1188+
if !strings.Contains(got, "uses: github/gh-aw/actions/[email protected]") {
1189+
t.Errorf("Expected updated uses: line, got:\n%s", got)
1190+
}
1191+
if !strings.Contains(got, "version: v0.60.0") {
1192+
t.Errorf("Expected with: version: updated to v0.60.0, got:\n%s", got)
1193+
}
1194+
if strings.Contains(got, "v0.53.6") {
1195+
t.Errorf("Stale version v0.53.6 should be gone, got:\n%s", got)
1196+
}
1197+
},
1198+
},
11441199
}
11451200

11461201
for _, tt := range tests {

0 commit comments

Comments
 (0)