diff --git a/.github/workflows/ci-doctor.lock.yml b/.github/workflows/ci-doctor.lock.yml index 63e34dc3a3..0f132ed126 100644 --- a/.github/workflows/ci-doctor.lock.yml +++ b/.github/workflows/ci-doctor.lock.yml @@ -1287,7 +1287,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"create_issue\":{\"close_older_issues\":true,\"expires\":24,\"labels\":[\"cookie\"],\"max\":1,\"title_prefix\":\"[CI Failure Doctor] \"},\"missing_data\":{},\"missing_tool\":{},\"update_issue\":{\"max\":1}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"create_issue\":{\"close_older_issues\":true,\"expires\":24,\"labels\":[\"cookie\"],\"max\":1,\"title_prefix\":\"[CI Failure Doctor] \"},\"missing_data\":{},\"missing_tool\":{},\"update_issue\":{\"allow_body\":true,\"max\":1}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/sub-issue-closer.lock.yml b/.github/workflows/sub-issue-closer.lock.yml index d35999091d..44497760c6 100644 --- a/.github/workflows/sub-issue-closer.lock.yml +++ b/.github/workflows/sub-issue-closer.lock.yml @@ -1097,7 +1097,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":20,\"target\":\"*\"},\"missing_data\":{},\"missing_tool\":{},\"update_issue\":{\"allow_status\":true,\"max\":20,\"target\":\"*\"}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":20,\"target\":\"*\"},\"missing_data\":{},\"missing_tool\":{},\"update_issue\":{\"allow_body\":true,\"allow_status\":true,\"max\":20,\"target\":\"*\"}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/workflow-health-manager.lock.yml b/.github/workflows/workflow-health-manager.lock.yml index 5474196e77..c1cbbf41b6 100644 --- a/.github/workflows/workflow-health-manager.lock.yml +++ b/.github/workflows/workflow-health-manager.lock.yml @@ -1312,7 +1312,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":15},\"create_issue\":{\"expires\":24,\"group\":true,\"labels\":[\"cookie\"],\"max\":10},\"missing_data\":{},\"missing_tool\":{},\"update_issue\":{\"max\":5}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":15},\"create_issue\":{\"expires\":24,\"group\":true,\"labels\":[\"cookie\"],\"max\":10},\"missing_data\":{},\"missing_tool\":{},\"update_issue\":{\"allow_body\":true,\"max\":5}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/pkg/workflow/data/action_pins.json b/pkg/workflow/data/action_pins.json index 3688f8f2b9..15f27afb75 100644 --- a/pkg/workflow/data/action_pins.json +++ b/pkg/workflow/data/action_pins.json @@ -65,6 +65,11 @@ "version": "v4.3.1", "sha": "67a3573c9a986a3f9c594539f4ab511d57bb3ce9" }, + "actions/setup-go@v5": { + "repo": "actions/setup-go", + "version": "v5", + "sha": "40f1582b2485089dde7abd97c1529aa768e1baff" + }, "actions/setup-go@v6.2.0": { "repo": "actions/setup-go", "version": "v6.2.0", diff --git a/pkg/workflow/update_entity_helpers.go b/pkg/workflow/update_entity_helpers.go index 15cc22ca1d..b0cc765164 100644 --- a/pkg/workflow/update_entity_helpers.go +++ b/pkg/workflow/update_entity_helpers.go @@ -40,12 +40,18 @@ // body: null # Can update body (key exists) // ``` // -// 2. **Bool Value Mode** (for pull requests): -// Fields are enabled based on explicit boolean values: +// 2. **Bool Value Mode** (for body/footer fields in all entities): +// Fields are enabled based on explicit boolean values. +// Special case: null values are treated as true for backward compatibility: // ```yaml +// update-issue: +// body: true # Explicitly enable body updates +// body: false # Explicitly disable body updates +// body: null # Treated as true (backward compatibility) +// body: # Same as null, treated as true // update-pull-request: -// title: true # Can update title -// body: false # Cannot update body +// title: true # Can update title +// body: false # Cannot update body // ``` // // # When to Use vs Alternatives @@ -194,8 +200,9 @@ const ( // FieldParsingKeyExistence mode: Field presence (even if nil) indicates it can be updated // Used by update-issue and update-discussion FieldParsingKeyExistence FieldParsingMode = iota - // FieldParsingBoolValue mode: Field's boolean value determines if it can be updated - // Used by update-pull-request (defaults to true if nil) + // FieldParsingBoolValue mode: Field's boolean value determines if it can be updated. + // Special case: nil values are treated as true for backward compatibility. + // Used by body/footer fields in all update entities. FieldParsingBoolValue ) @@ -212,7 +219,9 @@ const ( // // Behavior by mode: // - FieldParsingKeyExistence: Returns new(bool) if key exists, nil otherwise -// - FieldParsingBoolValue: Returns &boolValue if key exists and is bool, nil otherwise +// - FieldParsingBoolValue: Returns &boolValue if key exists and is bool. +// Special case: if key exists with nil value (e.g., body: null), returns &true +// for backward compatibility. Returns nil for other non-bool values (invalid config). func parseUpdateEntityBoolField(configMap map[string]any, fieldName string, mode FieldParsingMode) *bool { if configMap == nil { return nil @@ -233,7 +242,13 @@ func parseUpdateEntityBoolField(configMap map[string]any, fieldName string, mode if boolVal, ok := val.(bool); ok { return &boolVal } - // If present but not a bool (e.g., null), return nil (no explicit setting) + // If value is explicitly nil (not a bool), treat as true (explicit enablement) + // This maintains backward compatibility where body: null enables the field + if val == nil { + trueVal := true + return &trueVal + } + // For other non-bool values (like strings), return nil (invalid config) return nil default: diff --git a/pkg/workflow/update_entity_helpers_test.go b/pkg/workflow/update_entity_helpers_test.go index 33ef47283b..9f793f7216 100644 --- a/pkg/workflow/update_entity_helpers_test.go +++ b/pkg/workflow/update_entity_helpers_test.go @@ -78,7 +78,8 @@ func TestParseUpdateEntityBoolField(t *testing.T) { configMap: map[string]any{"title": nil}, fieldName: "title", mode: FieldParsingBoolValue, - wantNil: true, // Non-bool values return nil + wantNil: false, // Nil values are treated as true (explicit enablement) + wantValue: true, // Defaults to true for backward compatibility }, { name: "bool value mode: string value (not a bool)", diff --git a/pkg/workflow/update_issue_test.go b/pkg/workflow/update_issue_test.go index ff2e9984f6..a5c893acdc 100644 --- a/pkg/workflow/update_issue_test.go +++ b/pkg/workflow/update_issue_test.go @@ -360,10 +360,13 @@ This workflow tests body: (null) for backward compatibility. t.Fatal("Expected update-issue configuration to be parsed") } - // With FieldParsingBoolValue mode, null values result in nil pointer - // The handler will default to true via AddBoolPtrOrDefault + // With FieldParsingBoolValue mode, null values are treated as true (explicit enablement) // This maintains backward compatibility where body: enables body updates - if workflowData.SafeOutputs.UpdateIssues.Body != nil { - t.Fatal("Expected body to be nil when set to null (will default to true in handler)") + if workflowData.SafeOutputs.UpdateIssues.Body == nil { + t.Fatal("Expected body to be non-nil when set to null") + } + + if !*workflowData.SafeOutputs.UpdateIssues.Body { + t.Fatal("Expected body to be true when set to null (backward compatibility)") } }