Skip to content

feat(codemods): rename allow-team-membersallowed-collaborators in safe-outputs.mentions#40394

Merged
pelikhan merged 7 commits into
mainfrom
copilot/add-codemod-rename-allowed-team-members
Jun 20, 2026
Merged

feat(codemods): rename allow-team-membersallowed-collaborators in safe-outputs.mentions#40394
pelikhan merged 7 commits into
mainfrom
copilot/add-codemod-rename-allowed-team-members

Conversation

Copilot AI commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

allow-team-members is being replaced by the more consistent allowed-collaborators name in safe-outputs.mentions. This adds a gh aw fix codemod for automatic migration and renames the field throughout the codebase.

Codemod (mentions-allow-team-members-to-allowed-collaborators)

  • Detects safe-outputs.mentions.allow-team-members and rewrites it to allowed-collaborators
  • No-ops when: key is absent, mentions is a bare boolean, or field is already migrated
  • Preserves indentation, inline comments, and markdown body

Field rename

  • MentionsConfig.AllowTeamMembersAllowedCollaborators with YAML tag allowed-collaborators
  • Runtime JSON key: allowTeamMembersallowedCollaborators
  • parseMentionsConfig falls back to allow-team-members for backward compatibility during migration

Schema

  • allow-team-members replaced by allowed-collaborators as the canonical entry
  • Old name retained as a deprecated alias with x-deprecation-message pointing users to gh aw fix

Before / after:

# Before
safe-outputs:
  mentions:
    allow-team-members: false

# After
safe-outputs:
  mentions:
    allowed-collaborators: false

Copilot AI and others added 2 commits June 19, 2026 21:58
… safe-outputs.mentions

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title feat(codemods): rename allow-team-members to allowed-collaborators in safe-outputs.mentions feat(codemods): rename allow-team-membersallowed-collaborators in safe-outputs.mentions Jun 19, 2026
Copilot AI requested a review from pelikhan June 19, 2026 22:01
@pelikhan pelikhan marked this pull request as ready for review June 19, 2026 22:56
Copilot AI review requested due to automatic review settings June 19, 2026 22:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates safe-outputs.mentions from the legacy allow-team-members key to the new canonical allowed-collaborators, adding an automatic gh aw fix codemod and updating the Go config types, parsing, and schema accordingly.

Changes:

  • Renames the mentions field in Go (MentionsConfig) and updates parsing/generation to prefer allowed-collaborators with fallback to allow-team-members.
  • Updates the workflow schema to make allowed-collaborators canonical and retain allow-team-members as a deprecated alias with a deprecation message.
  • Adds a new gh aw fix codemod to rewrite frontmatter keys under safe-outputs.mentions.
Show a summary per file
File Description
pkg/workflow/safe_outputs_messages_config.go Prefer allowed-collaborators when parsing mentions, with fallback to deprecated key.
pkg/workflow/safe_outputs_mentions_test.go Updates mentions parsing/generation tests for the new key (but currently contains issues noted in review comments).
pkg/workflow/safe_outputs_config.go Emits mentions config JSON using allowedCollaborators.
pkg/workflow/safe_outputs_config_generation_test.go Updates generation test expectations to the new JSON key.
pkg/workflow/safe_output_validation_config_test.go Updates validation-config JSON tests to the new mentions JSON key.
pkg/workflow/compiler_types.go Renames the MentionsConfig field/tag to AllowedCollaborators.
pkg/parser/schemas/main_workflow_schema.json Makes allowed-collaborators canonical and keeps allow-team-members as a deprecated alias.
pkg/cli/fix_codemods.go Registers the new mentions migration codemod.
pkg/cli/fix_codemods_test.go Updates codemod registry tests to include the new codemod ID and order.
pkg/cli/codemod_mentions_allow_team_members.go Implements frontmatter rewrite from allow-team-membersallowed-collaborators under safe-outputs.mentions.
pkg/cli/codemod_mentions_allow_team_members_test.go Adds unit tests for the new codemod behavior.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 11/11 changed files
  • Comments generated: 11

Comment on lines +1003 to 1005
if m.AllowedCollaborators != nil {
cfg["allowedCollaborators"] = *m.AllowedCollaborators
}
AllowContext: boolPtr(false),
Allowed: []string{"bot1"},
AllowedTeams: []string{"myorg/eng"},
Max: new(10),
AllowedCollaborators: boolPtr(false),
AllowContext: boolPtr(true),
Allowed: []string{"bot1", "bot2"},
Max: new(20),
AllowedCollaborators: boolPtr(false),
AllowedTeams: []string{"myorg/eng"},
Allowed: []string{"bot1"},
Max: new(30),
AllowedCollaborators: boolPtr(false),
AllowContext: boolPtr(true),
Allowed: []string{"bot1"},
Max: new(15),
Comment on lines +168 to +169
AllowedCollaborators: &allowTeamMembers,
Max: &max,
Comment thread pkg/workflow/compiler_types.go Outdated
Comment on lines +780 to +781
// AllowedCollaborators determines if repository collaborators (team members) can be mentioned (default: true)
AllowedCollaborators *bool `yaml:"allowed-collaborators,omitempty" json:"allowedCollaborators,omitempty"`
"allowed-collaborators": {
"type": "boolean",
"description": "Allow mentions of repository team members (collaborators with any permission level, excluding bots). Default: true",
"description": "Allow mentions of repository collaborators (team members with any permission level, excluding bots). Default: true",
Comment on lines +97 to +115
if inSafeOutputs && isDescendant(indent, safeOutputsIndent) && strings.HasSuffix(trimmed, ":") && !strings.HasPrefix(trimmed, "#") {
if safeOutputsChildIndent == "" {
safeOutputsChildIndent = indent
}
if indent == safeOutputsChildIndent {
key := strings.TrimSuffix(trimmed, ":")
if key == "mentions" {
inMentions = true
mentionsIndent = indent
mentionsChildIndent = ""
} else {
inMentions = false
mentionsIndent = ""
mentionsChildIndent = ""
}
}
result = append(result, line)
continue
}
require.NoError(t, err)
assert.False(t, applied)
assert.Equal(t, content, result)
}
@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

⚠️ PR Code Quality Reviewer failed during code quality review.

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions

Copy link
Copy Markdown
Contributor

🏗️ Design Decision Gate — ADR Required

This PR makes significant changes to core business logic (>100 new lines in pkg/) but does not have a linked Architecture Decision Record (ADR).

📄 Draft ADR committed: docs/adr/40394-rename-allow-team-members-to-allowed-collaborators.md — review and complete it before merging.

🔒 This PR cannot merge until an ADR is linked in the PR body.

📋 What to do next
  1. Review the draft ADR committed to your branch — it was generated from the PR diff (a backward-compatible config field rename with a deprecated alias and a gh aw fix codemod).
  2. Complete the missing sections — confirm the context, refine the decision rationale, and verify the alternatives reflect what you actually considered.
  3. Commit the finalized ADR to docs/adr/ on your branch.
  4. Reference the ADR in this PR body by adding a line such as:

    ADR: ADR-40394: Rename allow-team-members to allowed-collaborators

Once an ADR is linked in the PR body, this gate will re-run and verify the implementation matches the decision.

❓ Why ADRs Matter

ADRs create a searchable, permanent record of why the codebase looks the way it does — including how a public configuration field was evolved without a breaking change. Future contributors (and your future self) will thank you.

📋 Michael Nygard ADR Format Reference

An ADR must contain these four sections to be considered complete:

  • Context — What is the problem? What forces are at play?
  • Decision — What did you decide? Why?
  • Alternatives Considered — What else could have been done?
  • Consequences — What are the trade-offs (positive and negative)?

All ADRs are stored in docs/adr/ as Markdown files numbered by PR number (e.g., 40394-...md for PR #40394).

🔒 Blocking: link the completed ADR in the PR body to clear this gate.

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · 95.3 AIC · ⌖ 10.2 AIC · ⊞ 13.6K ·

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

⚠️ Test Quality Score: 78/100 — Acceptable

Analyzed 11 new test function(s): 10 design, 1 implementation, 0 guideline violations (build tag ✅, no mocks ✅); soft flag for missing assertion messages on all 11 new tests.

📊 Metrics & Test Classification (11 tests analyzed)
Metric Value
New/modified tests analyzed 11
✅ Design tests (behavioral contracts) 10 (91%)
⚠️ Implementation tests (low value) 1 (9%)
Tests with error/edge cases 8 (73%)
Duplicate test clusters 0
Test inflation detected ⚠️ Yes — codemod_mentions_allow_team_members_test.go (+288) vs production (+135) = 2.13:1
🚨 Coding-guideline violations 0 (no mock libraries, build tag present)
Test File Classification Issues Detected
TestGetMentionsAllowTeamMembersCodemod pkg/cli/codemod_mentions_allow_team_members_test.go:13 ⚠️ Implementation Verifies metadata fields only (ID, Name, Description, version); doesn't assert on transformation behavior. Missing assertion messages.
TestMentionsAllowTeamMembersCodemod_HappyPath pkg/cli/codemod_mentions_allow_team_members_test.go:20 ✅ Design Missing assertion messages.
TestMentionsAllowTeamMembersCodemod_NoOp_NoSafeOutputs pkg/cli/codemod_mentions_allow_team_members_test.go:51 ✅ Design + edge case Missing assertion messages.
TestMentionsAllowTeamMembersCodemod_NoOp_NoMentions pkg/cli/codemod_mentions_allow_team_members_test.go:74 ✅ Design + edge case Missing assertion messages.
TestMentionsAllowTeamMembersCodemod_NoOp_MentionsBoolean pkg/cli/codemod_mentions_allow_team_members_test.go:97 ✅ Design + edge case Missing assertion messages.
TestMentionsAllowTeamMembersCodemod_NoOp_AlreadyMigrated pkg/cli/codemod_mentions_allow_team_members_test.go:120 ✅ Design + edge case Missing assertion messages.
TestMentionsAllowTeamMembersCodemod_Idempotent pkg/cli/codemod_mentions_allow_team_members_test.go:145 ✅ Design + edge case Missing assertion messages.
TestMentionsAllowTeamMembersCodemod_PreservesInlineComment pkg/cli/codemod_mentions_allow_team_members_test.go:175 ✅ Design + edge case Missing assertion messages.
TestMentionsAllowTeamMembersCodemod_PreservesIndentation pkg/cli/codemod_mentions_allow_team_members_test.go:203 ✅ Design + edge case Missing assertion messages.
TestMentionsAllowTeamMembersCodemod_PreservesMarkdownBody pkg/cli/codemod_mentions_allow_team_members_test.go:234 ✅ Design Missing assertion messages.
TestMentionsAllowTeamMembersCodemod_NoOp_OldKeyAbsent pkg/cli/codemod_mentions_allow_team_members_test.go:265 ✅ Design + edge case Missing assertion messages.

Go: 11 (*_test.go); JavaScript: 0. The remaining 4 modified test files (fix_codemods_test.go, safe_output_validation_config_test.go, safe_outputs_config_generation_test.go, safe_outputs_mentions_test.go) contain only mechanical field renames (AllowTeamMembersAllowedCollaborators) with no new behavioral coverage to score.

⚠️ Flagged Tests — Soft Concerns (2 issue type(s))

TestGetMentionsAllowTeamMembersCodemod (pkg/cli/codemod_mentions_allow_team_members_test.go:13) — ⚠️ Implementation detail: only asserts on codemod metadata fields (ID, Name, Description, IntroducedIn) without verifying any transformation behavior. The require.NotNil(t, codemod.Apply) check is useful as a nil-guard but the remaining assertions are pure metadata. Suggested improvement: fold this into a table-driven test that also validates Apply transforms at least one input, or accept the low-value registration check as a thin smoke test.

Missing assertion messages (all 11 new tests)⚠️ Guideline: all testify assertions in codemod_mentions_allow_team_members_test.go use bare calls without a descriptive msg argument (e.g. assert.True(t, applied) instead of assert.True(t, applied, "codemod should report applied=true after renaming old key")). This makes failure output harder to triage. Not a hard failure condition, but the guideline requires descriptive message arguments on every assertion call.

Test inflation (codemod_mentions_allow_team_members_test.go) — +288 test lines vs +135 production lines = ratio 2.13:1 (threshold 2:1). The coverage is substantive and the extra lines reflect legitimate scenario breadth (11 distinct scenarios), so this is a borderline flag rather than a quality concern — but the ratio triggers the scoring penalty.

Verdict

Check passed. 9% implementation tests (threshold: 30%); no coding-guideline violations (build tag present, no mock libraries). The new codemod tests cover the transformation contract comprehensively: happy-path rename, four no-op precondition checks, idempotency, YAML comment and indentation preservation, and markdown-body integrity. Consider adding assertion messages to all bare testify calls in future test additions.

🧪 Test quality analysis by Test Quality Sentinel · 66.4 AIC · ⌖ 9.48 AIC · ⊞ 8.3K ·

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Test Quality Sentinel: 78/100. Test quality is acceptable — 9% of new tests are implementation tests (threshold: 30%).

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skills-Based Review 🧠

Applied /tdd — requesting changes on two test coverage gaps in the backward-compatibility path.

📋 Key Themes & Highlights

Key Themes

  • Untested backward-compat fallback: parseMentionsConfig now prefers allowed-collaborators with a fallback to allow-team-members, but the test cases in safe_outputs_mentions_test.go were updated to use only the new key as input. The fallback branch (else if allowTeamMembers) is never exercised by a test.
  • Undocumented no-op edge case: When both keys exist simultaneously, the codemod skips without a test asserting that expectation. This should be documented as intentional behavior.

Positive Highlights

  • ✅ Excellent codemod test coverage: happy path, four distinct no-op conditions, idempotency, and preservation of indentation / inline comments
  • ✅ Clean two-key fallback structure in parseMentionsConfig — reads intuitively
  • ✅ Schema correctly retains allow-team-members as a deprecated alias with x-deprecation-message pointing users to gh aw fix
  • hasExitedBlock correctly returns false for blank lines, so YAML with internal blank lines is handled safely

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 102.1 AIC · ⌖ 7.43 AIC · ⊞ 6.9K

if val, ok := allowedCollaborators.(bool); ok {
config.AllowedCollaborators = &val
}
} else if allowTeamMembers, exists := mentionsMap["allow-team-members"]; exists {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] The else if allowTeamMembers backward-compat fallback path is untested — this is the most critical part of the migration story.

All TestParseMentionsConfig_Object test cases were updated to use allowed-collaborators as the input key, so no test now exercises the scenario where a user's un-migrated workflow still uses allow-team-members. If this fallback is silently broken, existing workflows would lose their collaborator-mention filtering without any visible error.

💡 Suggested test case to add to `safe_outputs_mentions_test.go`
{
    name: "allow-team-members key (backward-compat fallback)",
    input: map[string]any{
        "allow-team-members": false,
        "allow-context":      true,
    },
    expected: &MentionsConfig{
        AllowedCollaborators: boolPtr(false),
        AllowContext:         boolPtr(true),
    },
},

This directly exercises the else if allowTeamMembers branch added in parseMentionsConfig.


_, hasOld := mentionsMap["allow-team-members"]
_, hasNew := mentionsMap["allowed-collaborators"]
return hasOld && !hasNew

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] When both allow-team-members and allowed-collaborators are present simultaneously, mentionsAllowTeamMembersNeedsMigration returns false and the codemod silently skips. The old deprecated key stays in the file even after the user runs gh aw fix.

The TestMentionsAllowTeamMembersCodemod_NoOp_AlreadyMigrated test only covers the case where allow-team-members is absent — not the "both keys present" case. A user who hand-edited their YAML to add allowed-collaborators but forgot to remove the old key would be surprised that gh aw fix does nothing.

💡 Suggested additional test
func TestMentionsAllowTeamMembersCodemod_NoOp_BothKeysPresent(t *testing.T) {
    codemod := getMentionsAllowTeamMembersCodemod()
    content := `---
safe-outputs:
  mentions:
    allow-team-members: false
    allowed-collaborators: false
---`
    frontmatter := map[string]any{
        "safe-outputs": map[string]any{
            "mentions": map[string]any{
                "allow-team-members":    false,
                "allowed-collaborators": false,
            },
        },
    }
    result, applied, err := codemod.Apply(content, frontmatter)
    require.NoError(t, err)
    assert.False(t, applied)
    assert.Equal(t, content, result)
}

This documents the intended no-op and prevents a future refactor from accidentally "fixing" both-key documents in unexpected ways.

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot run pr-reviewer skill

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

REQUEST_CHANGES — one critical blocker (flagged by prior review) plus one new medium finding.

Critical blocker (pre-existing comment, still unresolved)

The change in buildMentionsHandlerConfig (line 1005) now emits allowedCollaborators as the JSON key, but the safe-outputs runtime handler still reads allowTeamMembers. This means any workflow that has already migrated to allowed-collaborators: false will have that setting silently ignored at runtime — collaborators remain mentionable by default. This is a correctness regression that must be resolved before merging (see existing inline comment at L1005).

Additional finding (new)

Backward-compat fallback in parseMentionsConfig is untested

The else if allow-team-members branch (lines 71-74 of safe_outputs_messages_config.go) has no test coverage. All test cases that previously exercised allow-team-members as input were migrated to allowed-collaborators, leaving the fallback as dead code from a testing perspective. A regression here silently breaks filtering for workflows still on the old key — see inline comment for a suggested fix.

🔎 Code quality review by PR Code Quality Reviewer · 202.5 AIC · ⌖ 9.78 AIC · ⊞ 5.1K

if val, ok := allowedCollaborators.(bool); ok {
config.AllowedCollaborators = &val
}
} else if allowTeamMembers, exists := mentionsMap["allow-team-members"]; exists {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Backward-compat fallback untested: the allow-team-members fallback path has zero test coverage — every prior test case that used allow-team-members input was migrated to allowed-collaborators, leaving lines 71-74 as a dead branch from a test perspective.

💡 Impact and suggested fix

During the migration window, workflows that have not yet run gh aw fix still carry allow-team-members in their YAML. If this fallback regresses, AllowedCollaborators silently stays nil. Because the runtime defaults the field to true when nil, a workflow that explicitly set allow-team-members: false would silently stop filtering collaborators — with no failing test to catch it.

Add a test case to TestParseMentionsConfig_Object that exercises the deprecated key:

{
    name: "backward compat — allow-team-members maps to AllowedCollaborators",
    input: map[string]any{
        "allow-team-members": false,
    },
    expected: &MentionsConfig{
        AllowedCollaborators: boolPtr(false),
    },
},

Same gap exists in TestExtractSafeOutputsConfig_WithMentions.

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot run pr-finisher skill

Copilot AI and others added 4 commits June 20, 2026 00:00
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Jun 20, 2026

Copy link
Copy Markdown
Contributor Author

@copilot run pr-reviewer skill

Done. I ran the PR review workflow and addressed the actionable feedback in commits up to 74e14df (runtime key compatibility, flow-style codemod migration + regression test, deprecated alias parsing coverage, and collaborator wording updates).

@pelikhan pelikhan merged commit e6d9ce6 into main Jun 20, 2026
37 of 38 checks passed
@pelikhan pelikhan deleted the copilot/add-codemod-rename-allowed-team-members branch June 20, 2026 00:16
Copilot stopped work on behalf of pelikhan due to an error June 20, 2026 00:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants