Skip to content

Commit 0c52650

Browse files
authored
Fix compiler to preserve action version comments during deduplication (#8011)
1 parent 7e03749 commit 0c52650

5 files changed

Lines changed: 45 additions & 5 deletions

File tree

.github/workflows/ci-coach.lock.yml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/workflows/go-logger.lock.yml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/workflows/hourly-ci-cleaner.lock.yml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/workflows/unbloat-docs.lock.yml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/workflow/runtime_setup.go

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,24 @@ func DeduplicateRuntimeSetupStepsFromCustomSteps(customSteps string, runtimeRequ
801801

802802
log.Printf("Deduplicating runtime setup steps from custom steps (%d runtimes)", len(runtimeRequirements))
803803

804+
// Extract version comments from uses lines before unmarshaling
805+
// This is necessary because YAML treats "# comment" as a comment, not part of the value
806+
// Format: "uses: action@sha # v1.0.0" -> after unmarshal, only "action@sha" remains
807+
versionComments := make(map[string]string) // key: action@sha, value: # v1.0.0
808+
lines := strings.Split(customSteps, "\n")
809+
for _, line := range lines {
810+
trimmed := strings.TrimSpace(line)
811+
if strings.HasPrefix(trimmed, "uses:") && strings.Contains(trimmed, " # ") {
812+
// Extract the uses value and version comment
813+
parts := strings.SplitN(trimmed, " # ", 2)
814+
if len(parts) == 2 {
815+
usesValue := strings.TrimSpace(strings.TrimPrefix(parts[0], "uses:"))
816+
versionComment := " # " + parts[1]
817+
versionComments[usesValue] = versionComment
818+
}
819+
}
820+
}
821+
804822
// Parse custom steps YAML
805823
var stepsWrapper map[string]any
806824
if err := yaml.Unmarshal([]byte(customSteps), &stepsWrapper); err != nil {
@@ -965,10 +983,32 @@ func DeduplicateRuntimeSetupStepsFromCustomSteps(customSteps string, runtimeRequ
965983

966984
// Convert back to YAML
967985
stepsWrapper["steps"] = filteredSteps
986+
987+
// Restore version comments to steps that have them
988+
// This must be done before marshaling
989+
for i, step := range filteredSteps {
990+
if stepMap, ok := step.(map[string]any); ok {
991+
if usesVal, hasUses := stepMap["uses"]; hasUses {
992+
if usesStr, ok := usesVal.(string); ok {
993+
if versionComment, hasComment := versionComments[usesStr]; hasComment {
994+
// Add the version comment back
995+
stepMap["uses"] = usesStr + versionComment
996+
filteredSteps[i] = stepMap
997+
}
998+
}
999+
}
1000+
}
1001+
}
1002+
9681003
deduplicatedYAML, err := yaml.Marshal(stepsWrapper)
9691004
if err != nil {
9701005
return customSteps, runtimeRequirements, fmt.Errorf("failed to marshal deduplicated workflow steps to YAML. Step deduplication removes duplicate runtime setup actions (like actions/setup-node) from custom steps to avoid conflicts when automatic runtime detection adds them. This optimization ensures runtime setup steps appear before custom steps. Error: %w", err)
9711006
}
9721007

973-
return string(deduplicatedYAML), filteredRequirements, nil
1008+
// Remove quotes from uses values with version comments
1009+
// The YAML marshaller quotes strings containing # (for inline version comments)
1010+
// but GitHub Actions expects unquoted uses values
1011+
deduplicatedStr := unquoteUsesWithComments(string(deduplicatedYAML))
1012+
1013+
return deduplicatedStr, filteredRequirements, nil
9741014
}

0 commit comments

Comments
 (0)