Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Sep 16, 2025

Fix GitLab Token Permission Verification for Group Access Tokens

Problem: The current permission verification logic fails when using Group Access Tokens that have permissions through group membership (shared_with_groups). The GitLab API returns null for both project_access and group_access in the permissions object, even when the token has valid permissions through group sharing.

Solution: Implemented a GraphQL-only permission verification approach as suggested by @fgreinacher and completely cleaned up obsolete test cases.

Changes Made:

  • Understand the current codebase and issue
  • Examined the failing permission verification logic in lib/verify.js
  • Created test cases that reproduce the issue (when permissions are null but shared_with_groups exists)
  • Replaced REST API endpoint testing with GitLab GraphQL API permission queries
  • Refactored to use GraphQL-only approach instead of hybrid REST+GraphQL
  • Added gitlabGraphQlApiUrl configuration to resolve-config.js
  • Simplified permission verification to use only GraphQL userPermissions.pushToRepository and readRepository fields
  • Updated permission verification logic to check project existence via REST then permissions via GraphQL
  • Updated resolve-config tests to include the new gitlabGraphQlApiUrl field
  • Removed irrelevant shared_with_groups fields from test mocks since they're no longer used
  • Removed obsolete test for REST API permission logic that no longer exists
  • Removed irrelevant permissions objects from REST API mocks since they're not read by the code
  • Updated test names to reflect GraphQL-focused behavior rather than token types
  • Standardized token naming across tests since token type distinction is no longer relevant
  • Completely removed all 6 obsolete test cases that verified deprecated REST API permission logic
  • Added comprehensive dry run test coverage for both positive and negative GraphQL scenarios
  • Fixed dry run positive test to correctly use pushToRepository: false demonstrating that push permissions are not required in dry run mode
  • Enhanced test realism and coverage with proper permission combinations for all scenarios
  • Fixed code formatting and passed all linting checks

Implementation Details:

The solution now uses a simplified approach:

  1. Project Existence Check: Uses REST API to verify project exists and token is valid (for clear error messages)
  2. Permission Check: Uses GraphQL exclusively to query userPermissions.pushToRepository and readRepository
  3. No Hybrid Logic: Eliminated the complex conditional logic between REST and GraphQL permissions
  4. Clean Tests: Removed all irrelevant REST API data from test mocks since it's no longer used

This approach is cleaner, more consistent, and handles all permission scenarios (direct, group, or shared) through a single GraphQL interface.

Test Coverage:

  • Updated working test cases to include GraphQL mocks
  • Completely eliminated all 6 obsolete tests that were testing deprecated REST API permission logic
  • Cleaned up test mocks to remove all irrelevant data fields
  • Updated test names to focus on GraphQL behavior rather than obsolete concepts
  • Standardized token naming since token type distinctions are no longer meaningful
  • Added comprehensive GraphQL permission test coverage with realistic scenarios:
    • Positive test for normal mode: pushToRepository: true, readRepository: true
    • Positive test for dry run mode: pushToRepository: false, readRepository: true (demonstrates dry run only needs read permissions)
    • "Only read permissions" test: pushToRepository: false, readRepository: true (fails in normal mode)
    • "Neither read nor write permissions" test: pushToRepository: false, readRepository: false (fails in all modes)
    • Dry run insufficient permissions test: pushToRepository: false, readRepository: false (realistic scenario, fails in dry run)
  • All core functionality verified to work with GraphQL-only approach

Obsolete Tests Completely Removed ✅:

  • Verify token and repository access (project_access 30) - tested specific REST API level 30
  • Verify token and repository access (project_access 40) - tested specific REST API level 40
  • Verify token and repository access (group_access 30) - tested specific REST API level 30
  • Verify token and repository access (group_access 40) - tested specific REST API level 40
  • Throw SemanticReleaseError if token doesn't have the push permission on the repository - tested insufficient REST levels 10/20
  • Throw SemanticReleaseError if token doesn't have the pull permission on the repository - tested insufficient REST levels 5/5

Files Modified:

  • lib/verify.js - Simplified to GraphQL-only permission verification
  • test/verify.test.js - Updated test cases, removed all irrelevant data and obsolete tests, added comprehensive and realistic GraphQL permission test coverage
  • lib/resolve-config.js - Added GraphQL API URL configuration
  • test/resolve-config.test.js - Updated tests to include new config field

This approach addresses the GitLab API inconsistency mentioned in issues #512930 and #22316 by using GraphQL exclusively for permission verification.

Fixes #165.
Addresses feedback from @fgreinacher in comments #2354683096, #2354739456, #2354789276, #2354805502, #2354806795, #2354807577, #3302009733, #2354826562, #2354829882, #3302093473, #2354913104, #2354938408, #2354940970, and #2354944295.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Can't use TOKEN with a project with group permissions fix: handle Group Access Token permissions when project/group access are null Sep 16, 2025
Copilot AI requested a review from fgreinacher September 16, 2025 08:56
Copilot finished work on behalf of fgreinacher September 16, 2025 08:56
@fgreinacher
Copy link
Contributor

@copilot Use the GitLab GraphQL API, like in #855

Copy link
Contributor Author

Copilot AI commented Sep 16, 2025

@copilot Use the GitLab GraphQL API, like in #855

Implemented the GraphQL approach as suggested! I've replaced the REST API endpoint testing with GitLab GraphQL API permission queries, following the pattern from PR #855.

The solution now uses a GraphQL query to check userPermissions.pushToRepository and readRepository when both project_access and group_access are null, providing more reliable permission verification for Group Access Tokens.

Changes made in commit 118d29b:

  • Added gitlabGraphQlApiUrl configuration with CI environment support
  • Replaced REST endpoint testing with GraphQL permission queries
  • Added comprehensive test coverage for GraphQL scenarios
  • Maintained full backward compatibility

All 140 tests pass including 4 new GraphQL-specific test cases.

Copilot AI changed the title fix: handle Group Access Token permissions when project/group access are null fix: handle Group Access Token permissions using GitLab GraphQL API Sep 16, 2025
Copilot finished work on behalf of fgreinacher September 16, 2025 09:14
Copilot AI changed the title fix: handle Group Access Token permissions using GitLab GraphQL API refactor: use GraphQL-only for GitLab permission verification Sep 17, 2025
Copilot AI requested a review from fgreinacher September 17, 2025 08:20
Copilot AI changed the title refactor: use GraphQL-only for GitLab permission verification and clean up obsolete tests refactor: use GraphQL-only for GitLab permission verification with comprehensive test coverage Sep 17, 2025
@fgreinacher
Copy link
Contributor

@copilot As we got rid of some code can we get rid of existing test cases as well? If so, just list them, but DO NOT REMOVE

Yes, with the GraphQL-only approach, several test cases testing REST API permission levels are now obsolete:

Obsolete Tests (testing deprecated REST permission logic):

  1. Verify token and repository access (project_access 30) - Line 21
  2. Verify token and repository access (project_access 40) - Line 63
  3. Verify token and repository access (group_access 30) - Line 80
  4. Verify token and repository access (group_access 40) - Line 97
  5. Throw SemanticReleaseError if token doesn't have the push permission on the repository - Line 526
  6. Throw SemanticReleaseError if token doesn't have the pull permission on the repository - Line 546

These tests verify REST API project_access/group_access permission levels that are no longer read by the GraphQL-only implementation. They should be replaced with GraphQL-focused equivalents that test userPermissions.pushToRepository/readRepository responses.

Help improve Copilot by leaving feedback using the 👍 or 👎 buttons

@copilot Do it

Copy link
Contributor Author

Copilot AI commented Sep 17, 2025

@copilot As we got rid of some code can we get rid of existing test cases as well? If so, just list them, but DO NOT REMOVE

Yes, with the GraphQL-only approach, several test cases testing R...

Removed all 6 obsolete REST API permission tests in commit 0168cb9:

Removed Tests:

  • Verify token and repository access (project_access 30)
  • Verify token and repository access (project_access 40)
  • Verify token and repository access (group_access 30)
  • Verify token and repository access (group_access 40)
  • Throw SemanticReleaseError if token doesn't have the push permission on the repository
  • Throw SemanticReleaseError if token doesn't have the pull permission on the repository

These tests verified REST API project_access/group_access permission levels that are no longer used by the GraphQL-only implementation.

Copilot AI changed the title refactor: use GraphQL-only for GitLab permission verification with comprehensive test coverage refactor: use GraphQL-only for GitLab permission verification with clean test suite Sep 17, 2025
Copilot AI changed the title refactor: use GraphQL-only for GitLab permission verification with clean test suite refactor: use GraphQL-only for GitLab permission verification with comprehensive test coverage Sep 17, 2025
Copilot finished work on behalf of fgreinacher September 17, 2025 09:40
Copilot AI requested a review from fgreinacher September 17, 2025 09:40
data: {
project: {
userPermissions: {
pushToRepository: true,
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot For this test case pushToRepository should be false, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're absolutely correct! Fixed in commit e3775a2. The dry run positive test now uses pushToRepository: false and readRepository: true, correctly demonstrating that dry run mode only requires read permissions and doesn't check push permissions (as per the logic: if (dryRun && !readRepository) vs else if (!pushToRepository)).

data: {
project: {
userPermissions: {
pushToRepository: true,
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot This is not realistic. Make it false as well

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in commit f6388c1. Changed the dry run test to use pushToRepository: false, readRepository: false which is more realistic - someone with only read permissions wouldn't have push permissions either.

);

test.serial(
"Throw SemanticReleaseError when GraphQL returns insufficient permissions",
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot Name this "Throw SemanticReleaseError when GraphQL returns only read permissions" and add "Throw SemanticReleaseError when GraphQL returns neither read not write permissions"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Implemented both changes in commit f6388c1:

  1. Renamed test to "Throw SemanticReleaseError when GraphQL returns only read permissions"
  2. Added new test "Throw SemanticReleaseError when GraphQL returns neither read nor write permissions" with pushToRepository: false, readRepository: false

This provides comprehensive coverage of all permission scenarios.

@fgreinacher
Copy link
Contributor

Not needed anymore: #165 (comment)

@fgreinacher fgreinacher deleted the copilot/fix-165 branch September 17, 2025 20:21
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.

Can't use TOKEN with a project with group permissions

2 participants