diff --git a/.github/workflows/glossary-maintainer.lock.yml b/.github/workflows/glossary-maintainer.lock.yml index aaef1a1e33d..926cea7dcf6 100644 --- a/.github/workflows/glossary-maintainer.lock.yml +++ b/.github/workflows/glossary-maintainer.lock.yml @@ -1697,7 +1697,7 @@ jobs: ref: ${{ github.event.repository.default_branch }} token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} persist-credentials: false - fetch-depth: 1 + fetch-depth: 0 - name: Checkout repository if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') && github.event_name != 'issue_comment' && github.event_name != 'pull_request_review_comment' uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -1705,7 +1705,7 @@ jobs: ref: ${{ steps.extract-base-branch.outputs.base-branch || github.base_ref || github.event.pull_request.base.ref || github.ref_name || github.event.repository.default_branch }} token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} persist-credentials: false - fetch-depth: 1 + fetch-depth: 0 - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/pr-sous-chef.lock.yml b/.github/workflows/pr-sous-chef.lock.yml index c118169a288..b096a366b5a 100644 --- a/.github/workflows/pr-sous-chef.lock.yml +++ b/.github/workflows/pr-sous-chef.lock.yml @@ -1609,7 +1609,7 @@ jobs: ref: ${{ github.event.repository.default_branch }} token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} persist-credentials: false - fetch-depth: 1 + fetch-depth: 0 - name: Checkout repository if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch') && github.event_name != 'issue_comment' && github.event_name != 'pull_request_review_comment' uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -1617,7 +1617,7 @@ jobs: ref: ${{ steps.extract-base-branch.outputs.base-branch || github.base_ref || github.event.pull_request.base.ref || github.ref_name || github.event.repository.default_branch }} token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} persist-credentials: false - fetch-depth: 1 + fetch-depth: 0 - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch') env: diff --git a/pkg/workflow/checkout_config_parser.go b/pkg/workflow/checkout_config_parser.go index 54416a2350b..aaf70904cd5 100644 --- a/pkg/workflow/checkout_config_parser.go +++ b/pkg/workflow/checkout_config_parser.go @@ -162,6 +162,9 @@ func checkoutConfigFromMap(m map[string]any) (*CheckoutConfig, error) { default: return nil, errors.New("checkout.fetch-depth must be an integer") } + if cfg.FetchDepth != nil && *cfg.FetchDepth < 0 { + return nil, errors.New("checkout.fetch-depth must be >= 0") + } } if v, ok := m["sparse-checkout"]; ok { diff --git a/pkg/workflow/checkout_manager_test.go b/pkg/workflow/checkout_manager_test.go index d0c3b6a84d0..59f13be160c 100644 --- a/pkg/workflow/checkout_manager_test.go +++ b/pkg/workflow/checkout_manager_test.go @@ -281,6 +281,17 @@ func TestParseCheckoutConfigs(t *testing.T) { assert.Equal(t, 0, *configs[0].FetchDepth, "fetch-depth should be 0") }) + t.Run("negative fetch-depth returns error", func(t *testing.T) { + for _, depth := range []float64{-1, -999999} { + raw := map[string]any{ + "fetch-depth": depth, + } + _, err := ParseCheckoutConfigs(raw) + require.Error(t, err) + assert.Contains(t, err.Error(), "checkout.fetch-depth must be >= 0") + } + }) + t.Run("backward compat: token key still works", func(t *testing.T) { raw := map[string]any{ "token": "${{ secrets.MY_TOKEN }}", diff --git a/pkg/workflow/compiler_safe_outputs_steps.go b/pkg/workflow/compiler_safe_outputs_steps.go index 464c87f71a8..ff929049267 100644 --- a/pkg/workflow/compiler_safe_outputs_steps.go +++ b/pkg/workflow/compiler_safe_outputs_steps.go @@ -53,6 +53,12 @@ func buildExtractBaseBranchStep() []string { func (c *Compiler) buildSharedPRCheckoutSteps(data *WorkflowData) []string { consolidatedSafeOutputsStepsLog.Print("Building shared PR checkout steps") var steps []string + fetchDepth := 1 + + if defaultCheckout := NewCheckoutManager(data.CheckoutConfigs).GetDefaultCheckoutOverride(); defaultCheckout != nil && defaultCheckout.fetchDepth != nil { + fetchDepth = *defaultCheckout.fetchDepth + consolidatedSafeOutputsStepsLog.Printf("Using custom checkout fetch-depth for safe_outputs: %d", fetchDepth) + } // Determine which token to use for checkout // Uses resolvePRCheckoutToken for consistent token resolution (GitHub App or PAT chain) @@ -149,7 +155,7 @@ func (c *Compiler) buildSharedPRCheckoutSteps(data *WorkflowData) []string { steps = append(steps, " ref: ${{ github.event.repository.default_branch }}\n") steps = append(steps, fmt.Sprintf(" token: %s\n", checkoutToken)) steps = append(steps, " persist-credentials: false\n") - steps = append(steps, " fetch-depth: 1\n") + steps = append(steps, fmt.Sprintf(" fetch-depth: %d\n", fetchDepth)) } // Step 1b: Checkout repository with conditional execution @@ -172,7 +178,7 @@ func (c *Compiler) buildSharedPRCheckoutSteps(data *WorkflowData) []string { steps = append(steps, fmt.Sprintf(" ref: %s\n", checkoutRef)) steps = append(steps, fmt.Sprintf(" token: %s\n", checkoutToken)) steps = append(steps, " persist-credentials: false\n") - steps = append(steps, " fetch-depth: 1\n") + steps = append(steps, fmt.Sprintf(" fetch-depth: %d\n", fetchDepth)) // Step 2: Configure Git credentials with conditional execution // Security: Pass GitHub token through environment variable to prevent template injection diff --git a/pkg/workflow/compiler_safe_outputs_steps_test.go b/pkg/workflow/compiler_safe_outputs_steps_test.go index a0ebe251cbe..7352c06ca34 100644 --- a/pkg/workflow/compiler_safe_outputs_steps_test.go +++ b/pkg/workflow/compiler_safe_outputs_steps_test.go @@ -12,9 +12,12 @@ import ( // TestBuildSharedPRCheckoutSteps tests shared PR checkout step generation func TestBuildSharedPRCheckoutSteps(t *testing.T) { + fetchDepthZero := 0 + tests := []struct { name string safeOutputs *SafeOutputsConfig + checkoutConfigs []*CheckoutConfig trialMode bool trialRepo string checkContains []string @@ -39,6 +42,21 @@ func TestBuildSharedPRCheckoutSteps(t *testing.T) { "github-actions[bot]@users.noreply.github.com", }, }, + { + name: "uses custom checkout fetch-depth", + safeOutputs: &SafeOutputsConfig{ + CreatePullRequests: &CreatePullRequestsConfig{}, + }, + checkoutConfigs: []*CheckoutConfig{ + {FetchDepth: &fetchDepthZero}, + }, + checkContains: []string{ + "fetch-depth: 0", + }, + checkNotContains: []string{ + "fetch-depth: 1", + }, + }, { name: "push to PR branch only", safeOutputs: &SafeOutputsConfig{ @@ -317,8 +335,9 @@ func TestBuildSharedPRCheckoutSteps(t *testing.T) { } workflowData := &WorkflowData{ - Name: "Test Workflow", - SafeOutputs: tt.safeOutputs, + Name: "Test Workflow", + SafeOutputs: tt.safeOutputs, + CheckoutConfigs: tt.checkoutConfigs, } steps := compiler.buildSharedPRCheckoutSteps(workflowData)