Skip to content

Conversation

gmondello
Copy link
Collaborator

Teams Integration and Assignment Logic

  • Implemented a new teams integration module (src/teams_cost_center_manager.py) supporting both auto and manual modes for assigning users to cost centers based on GitHub team membership. Multi-organization support and customizable cost center naming are included.
  • Enforced the GitHub API constraint that each user can only belong to one cost center at a time. For users in multiple teams, the last team processed determines their final cost center assignment, with clear warnings logged for conflicts.

Orphaned User Detection and Removal

  • Added orphaned user detection and optional removal: users no longer in a team but still assigned to its cost center are identified and, if configured, automatically removed. This keeps cost center assignments accurate as teams change.
  • Introduced new API methods (get_cost_center_members, remove_users_from_cost_center) and updated configuration options (remove_orphaned_users) to support this feature.

Documentation and Configuration Updates

  • Updated all relevant documentation files (README.md, TEAMS_INTEGRATION.md, TEAMS_QUICKSTART.md, IMPLEMENTATION_SUMMARY.md, config/config.yaml, config/config.example.yaml) to reflect the new teams mode, assignment logic, orphaned user handling, and best practices. [1] [2] [3]

Testing and Logging Improvements

  • Enhanced logging for multi-team user conflicts, orphaned user detection/removal, and configuration status. All Python files compile successfully and configuration loading/validation logic has been improved. [1] [2] [3]

Migration and Best Practices

  • Provided a migration guide and best practices for users transitioning to the new teams mode and orphaned user handling, including recommendations for plan mode testing, reviewing warning logs, and scheduling regular syncs. [1] [2]

…upport

- Add teams-based cost center assignment mode (alternative to PRU-based mode)
- Support both organization-level and enterprise-level teams
- Implement auto mode (one cost center per team) and manual mode (explicit mappings)
- Add required scope parameter: 'organization' or 'enterprise'
- Implement single cost center constraint per user (last team wins for multi-team users)
- Add comprehensive documentation (README, TEAMS_INTEGRATION, TEAMS_QUICKSTART)
- Add new GitHub API methods for teams and memberships
- Fix enterprise teams API to handle direct user objects (not wrapped in membership objects)
- Document that incremental mode is NOT supported for teams mode
- Add get_cost_center_members() API to fetch current cost center membership
- Add remove_users_from_cost_center() API to remove users from cost centers
- Add teams.remove_orphaned_users config option (default: false)
- Implement orphaned user detection in sync_team_assignments()
- Show orphaned users in plan mode
- Remove orphaned users in apply mode when configured
- Works with both organization and enterprise team scopes
- Add configuration display in main.py output
- Remove attempt to fetch cost center members in plan mode (IDs don't exist yet)
- Show clear message that orphaned detection is enabled and will run in apply mode
- Remove unused _show_orphaned_users_plan method
- Simplify plan mode messaging
- Parse improved API 409 response to extract existing cost center UUID
- Avoid unnecessary GET request to list all cost centers when name conflict occurs
- Fall back to name search only if UUID extraction fails
- Add regex pattern to match 'existing cost center UUID: <uuid>' format
- Improves performance by reducing API calls
- Add count of cost centers being checked
- Add debug logging showing current vs expected members per cost center
- Helps troubleshoot orphaned user detection issues
- Always detect orphaned users regardless of remove_orphaned_users setting
- Only remove orphaned users when remove_orphaned_users is true
- When removal is disabled, log warning that users will remain in cost centers
- Add 'remove' parameter to _remove_orphaned_users method
- Improve summary messages to indicate whether removal was performed or skipped
- Check current cost center members before adding users
- Only POST users who are not already in the cost center
- Avoids unnecessary API calls and potential issues with re-adding existing users
- Return success for users already assigned (no action needed)
- Improves efficiency and reduces API rate limit usage
- Change enterprise from 'avocado-corp' to empty string (use env var)
- Change organizations from 'cost-center-automation' to placeholder 'your-org-name'
- Ensures config.yaml doesn't contain specific test values
This was an internal development/explanation document and not needed in the final PR
This was an internal implementation summary and not needed in the final PR
- Make teams mode a first-class experience (not a bolt-on)
  * Update main.py help text and docstring to equally highlight both modes
  * Add comprehensive examples in argparse showing both PRU and Teams modes
  * Improve flag descriptions to be mode-agnostic or clearly specify mode

- Implement standardized bracket notation naming
  * Remove configurable template system from teams mode
  * Use fixed naming: [enterprise team] {team-name} and [org team] {org-name}/{team-name}
  * Update config examples to document naming conventions

- Simplify and streamline documentation
  * Reduce README from 650 to 346 lines (47% reduction)
  * Add collapsible Quick Start sections for both modes
  * Move detailed Teams docs to dedicated files
  * Focus on getting users started quickly
  * Make both modes equally prominent

- Clean up configuration files
  * Set teams.enabled default to false
  * Update config.example.yaml with bracket notation docs
  * Set remove_orphaned_users default to true
  * Remove obsolete template configuration
@gmondello gmondello marked this pull request as ready for review October 8, 2025 21:53
@gmondello gmondello requested a review from a team as a code owner October 8, 2025 21:53
@Copilot Copilot AI review requested due to automatic review settings October 8, 2025 21:53
Copy link

@Copilot Copilot AI left a comment

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 implements comprehensive GitHub Teams Integration for cost center automation, adding an alternative "Teams-based mode" alongside the existing PRU-based assignments. The integration supports both organization and enterprise team scopes with automatic/manual assignment modes and includes orphaned user detection.

Key changes:

  • Added teams-based cost center assignment with organization/enterprise scope support
  • Implemented orphaned user detection and optional removal functionality
  • Enhanced API with new team management and cost center membership methods

Reviewed Changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/teams_cost_center_manager.py New teams integration manager with auto/manual modes and multi-org support
src/github_api.py Enhanced with team listing, member fetching, and cost center management APIs
src/config_manager.py Added teams configuration properties loading
main.py Integrated teams mode with validation and execution flow
config/config.yaml Added comprehensive teams configuration section
config/config.example.yaml Added teams configuration examples and documentation
TEAMS_QUICKSTART.md Complete quickstart guide for teams integration setup
TEAMS_INTEGRATION.md Comprehensive teams mode reference documentation
README.md Updated with teams mode overview and usage examples
ORPHANED_USERS_FEATURE.md Detailed documentation for orphaned user detection feature

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +33 to +34
self.members_cache: Dict[str, List[str]] = {} # "org/team_slug" or "team_slug" -> list of usernames
self.cost_center_cache: Dict[str, str] = {} # "org/team_slug" or "team_slug" -> cost_center_id
Copy link

Copilot AI Oct 8, 2025

Choose a reason for hiding this comment

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

The cache key format comments are inconsistent with the actual implementation. For enterprise scope, the cache keys are just team_slug (no org prefix), but the comments suggest org/team_slug format for all caches.

Suggested change
self.members_cache: Dict[str, List[str]] = {} # "org/team_slug" or "team_slug" -> list of usernames
self.cost_center_cache: Dict[str, str] = {} # "org/team_slug" or "team_slug" -> cost_center_id
self.members_cache: Dict[str, List[str]] = {} # org scope: "org/team_slug", enterprise scope: "team_slug" -> list of usernames
self.cost_center_cache: Dict[str, str] = {} # org scope: "org/team_slug", enterprise scope: "team_slug" -> cost_center_id

Copilot uses AI. Check for mistakes.

# Enterprise name is required. Prefer setting via environment var GITHUB_ENTERPRISE.
# Leave as placeholder or blank if supplying via environment.
enterprise: "REPLACE_WITH_ENTERPRISE_SLUG"
enterprise: ""
Copy link

Copilot AI Oct 8, 2025

Choose a reason for hiding this comment

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

Setting enterprise to an empty string could cause issues if not properly validated. Consider using null/~ or adding validation to ensure it's set via environment variable.

Suggested change
enterprise: ""
enterprise: null

Copilot uses AI. Check for mistakes.

Comment on lines +16 to 18
prus_exception_users: []
# - "example.user1"
# - "example.user2"
Copy link

Copilot AI Oct 8, 2025

Choose a reason for hiding this comment

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

The prus_exception_users field has been changed from commented examples to an empty list, which removes helpful inline documentation for users setting up the configuration.

Suggested change
prus_exception_users: []
# - "example.user1"
# - "example.user2"
# Example:
# - "example.user1"
# - "example.user2"
prus_exception_users: []

Copilot uses AI. Check for mistakes.

@gmondello gmondello merged commit ec1edef into main Oct 9, 2025
3 checks passed
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.

2 participants