diff --git a/.github/workflows/ci-coach.lock.yml b/.github/workflows/ci-coach.lock.yml index 0b0683a5ac6..30f547fa8f0 100644 --- a/.github/workflows/ci-coach.lock.yml +++ b/.github/workflows/ci-coach.lock.yml @@ -120,7 +120,7 @@ jobs: name: Download CI workflow runs from last 7 days run: "# Download workflow runs for the ci workflow\ngh run list --repo ${{ github.repository }} --workflow=ci.yml --limit 100 --json databaseId,status,conclusion,createdAt,updatedAt,displayTitle,headBranch,event,url,workflowDatabaseId,number > /tmp/ci-runs.json\n\n# Create directory for artifacts\nmkdir -p /tmp/ci-artifacts\n\n# Download artifacts from recent runs (last 5 successful runs)\necho \"Downloading artifacts from recent CI runs...\"\ngh run list --repo ${{ github.repository }} --workflow=ci.yml --status success --limit 5 --json databaseId | jq -r '.[].databaseId' | while read -r run_id; do\n echo \"Processing run $run_id\"\n gh run download \"$run_id\" --repo ${{ github.repository }} --dir \"/tmp/ci-artifacts/$run_id\" 2>/dev/null || echo \"No artifacts for run $run_id\"\ndone\n\necho \"CI runs data saved to /tmp/ci-runs.json\"\necho \"Artifacts saved to /tmp/ci-artifacts/\"\n" - name: Set up Go - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: cache: true go-version-file: go.mod diff --git a/.github/workflows/go-logger.lock.yml b/.github/workflows/go-logger.lock.yml index b098eb4d0b5..0cfeb035d56 100644 --- a/.github/workflows/go-logger.lock.yml +++ b/.github/workflows/go-logger.lock.yml @@ -109,7 +109,7 @@ jobs: - name: Create gh-aw temp directory run: bash /tmp/gh-aw/actions/create_gh_aw_tmp_dir.sh - name: Set up Go - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: cache: true go-version-file: go.mod diff --git a/.github/workflows/hourly-ci-cleaner.lock.yml b/.github/workflows/hourly-ci-cleaner.lock.yml index ddcde40a0a4..ddc00b21e75 100644 --- a/.github/workflows/hourly-ci-cleaner.lock.yml +++ b/.github/workflows/hourly-ci-cleaner.lock.yml @@ -120,7 +120,7 @@ jobs: sudo apt-get update sudo apt-get install -y make - name: Setup Go - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: cache: true go-version-file: go.mod diff --git a/.github/workflows/unbloat-docs.lock.yml b/.github/workflows/unbloat-docs.lock.yml index fc24514d3ab..605cf4c4697 100644 --- a/.github/workflows/unbloat-docs.lock.yml +++ b/.github/workflows/unbloat-docs.lock.yml @@ -131,7 +131,7 @@ jobs: - name: Create gh-aw temp directory run: bash /tmp/gh-aw/actions/create_gh_aw_tmp_dir.sh - name: Checkout repository - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: persist-credentials: false - name: Setup Node.js diff --git a/pkg/workflow/runtime_setup.go b/pkg/workflow/runtime_setup.go index ac0c61ac42a..8de9aec09d3 100644 --- a/pkg/workflow/runtime_setup.go +++ b/pkg/workflow/runtime_setup.go @@ -801,6 +801,24 @@ func DeduplicateRuntimeSetupStepsFromCustomSteps(customSteps string, runtimeRequ log.Printf("Deduplicating runtime setup steps from custom steps (%d runtimes)", len(runtimeRequirements)) + // Extract version comments from uses lines before unmarshaling + // This is necessary because YAML treats "# comment" as a comment, not part of the value + // Format: "uses: action@sha # v1.0.0" -> after unmarshal, only "action@sha" remains + versionComments := make(map[string]string) // key: action@sha, value: # v1.0.0 + lines := strings.Split(customSteps, "\n") + for _, line := range lines { + trimmed := strings.TrimSpace(line) + if strings.HasPrefix(trimmed, "uses:") && strings.Contains(trimmed, " # ") { + // Extract the uses value and version comment + parts := strings.SplitN(trimmed, " # ", 2) + if len(parts) == 2 { + usesValue := strings.TrimSpace(strings.TrimPrefix(parts[0], "uses:")) + versionComment := " # " + parts[1] + versionComments[usesValue] = versionComment + } + } + } + // Parse custom steps YAML var stepsWrapper map[string]any if err := yaml.Unmarshal([]byte(customSteps), &stepsWrapper); err != nil { @@ -965,10 +983,32 @@ func DeduplicateRuntimeSetupStepsFromCustomSteps(customSteps string, runtimeRequ // Convert back to YAML stepsWrapper["steps"] = filteredSteps + + // Restore version comments to steps that have them + // This must be done before marshaling + for i, step := range filteredSteps { + if stepMap, ok := step.(map[string]any); ok { + if usesVal, hasUses := stepMap["uses"]; hasUses { + if usesStr, ok := usesVal.(string); ok { + if versionComment, hasComment := versionComments[usesStr]; hasComment { + // Add the version comment back + stepMap["uses"] = usesStr + versionComment + filteredSteps[i] = stepMap + } + } + } + } + } + deduplicatedYAML, err := yaml.Marshal(stepsWrapper) if err != nil { 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) } - return string(deduplicatedYAML), filteredRequirements, nil + // Remove quotes from uses values with version comments + // The YAML marshaller quotes strings containing # (for inline version comments) + // but GitHub Actions expects unquoted uses values + deduplicatedStr := unquoteUsesWithComments(string(deduplicatedYAML)) + + return deduplicatedStr, filteredRequirements, nil }