Skip to content

Conversation

@szokeasaurusrex
Copy link
Member

@szokeasaurusrex szokeasaurusrex commented Dec 17, 2025

Changes

  • Add authorization logic to allow users with project:releases or org:ci scopes to create releases via the organization releases endpoint, even if they're not direct team members of the project
  • Ensures consistency with the project releases endpoint behavior
  • Add test case to verify users with project:releases token can create releases for projects they're not team members of
  • Fix test to use proper silo mode context (assume_test_silo_mode(SiloMode.CONTROL)) for ApiToken creation

Context

Previously, the organization releases endpoint only allowed release creation if the user was either a member of the project or was using an org Auth Token with org:ci scope. This change extends that check to also include users with project:releases scope, matching the behavior of the project releases endpoint and providing consistency across the API.

Issues

@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Dec 17, 2025
@szokeasaurusrex szokeasaurusrex marked this pull request as draft December 17, 2025 10:14
Comment on lines 676 to 678
if not has_valid_api_key and request.user and request.user.is_authenticated:
if request.access.has_scope("project:releases") or request.access.has_scope("org:ci"):
has_valid_api_key = True

This comment was marked as outdated.

@codecov
Copy link

codecov bot commented Dec 17, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff            @@
##           master   #105130   +/-   ##
========================================
  Coverage   80.58%    80.58%           
========================================
  Files        9438      9438           
  Lines      404429    404433    +4     
  Branches    25694     25694           
========================================
+ Hits       325912    325917    +5     
+ Misses      78048     78047    -1     
  Partials      469       469           

@linear
Copy link

linear bot commented Dec 17, 2025

@szokeasaurusrex szokeasaurusrex marked this pull request as ready for review December 17, 2025 17:06
@szokeasaurusrex szokeasaurusrex changed the title ref(releases): Allow project:releases scope for org releases endpoint fix(releases): Allow project:releases scope for org releases endpoint Dec 17, 2025
@szokeasaurusrex szokeasaurusrex requested review from loewenheim and removed request for mikejihbe December 17, 2025 17:07
from sentry.hybridcloud.models.apitokenreplica import ApiTokenReplica

if isinstance(auth, AuthenticatedToken):
return auth.kind == "api_token"
Copy link
Contributor

Choose a reason for hiding this comment

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

How does this line work with the new return type?

Copy link
Member Author

Choose a reason for hiding this comment

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

TypeGuard, as I understand it from reading the docs, just means that the function returns a bool, but if the bool is True, then the type checker should narrow the type of the first parameter to the type parameter to TypeGuard, which is AuthenticatedToken | ApiToken | ApiTokenReplica here.

This part of the docs is the most relevant for our purposes:

When a conditional statement includes a call to a user-defined type guard function, and that function returns true, the expression passed as the first positional argument to the type guard function should be assumed by a static type checker to take on the type specified in the TypeGuard return type, unless and until it is further narrowed within the conditional code block.

Some built-in type guards provide narrowing for both positive and negative tests (in both the if and else clauses). For example, consider the type guard for an expression of the form x is None. If x has a type that is a union of None and some other type, it will be narrowed to None in the positive case and the other type in the negative case. User-defined type guards apply narrowing only in the positive case (the if clause). The type is not narrowed in the negative case.

Very importantly, the second paragraph means that we are not required to return True when the type matches the type guard, as no inference is made as to the type of the first parameter when we return False. Since we can only return True when the parameter has one of the types specified in the TypeGuard, this is safe.

szokeasaurusrex and others added 4 commits January 5, 2026 10:18
- Add logic to check for project:releases and org:ci scopes when determining release permissions
- Ensures consistency with project releases endpoint behavior
- Add test to verify users with project:releases token can create releases for non-member projects
- Fix test to use proper silo mode context for ApiToken creation
Co-authored-by: Sebastian Zivota <loewenheim@users.noreply.github.com>
request.access checks organization membership, and only returns scopes if the token should be able to acccess the given organization.
@szokeasaurusrex szokeasaurusrex force-pushed the fix-org-releases-auth-token-silo-mode branch from 6daf8f1 to 149b842 Compare January 5, 2026 09:18
@szokeasaurusrex szokeasaurusrex marked this pull request as ready for review January 5, 2026 09:23
@szokeasaurusrex
Copy link
Member Author

@loewenheim would appreciate a re-review. Seer found a potential bug that I fixed with these changes.

Does this look good now?

@szokeasaurusrex szokeasaurusrex merged commit 2ba052d into master Jan 12, 2026
65 checks passed
@szokeasaurusrex szokeasaurusrex deleted the fix-org-releases-auth-token-silo-mode branch January 12, 2026 13:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants