Skip to content

feat(issues): Add GroupActionLog instrumentation for issue mutations#116347

Merged
yuvmen merged 19 commits into
masterfrom
yuvmen/group-action-log-instrumentation
Jun 3, 2026
Merged

feat(issues): Add GroupActionLog instrumentation for issue mutations#116347
yuvmen merged 19 commits into
masterfrom
yuvmen/group-action-log-instrumentation

Conversation

@yuvmen

@yuvmen yuvmen commented May 27, 2026

Copy link
Copy Markdown
Member

Summary

Instruments issue-facing API endpoints to emit structured log entries for the Issue Action Log, with full source attribution (web, API, MCP client, Seer, sentry-cli).

  • Adds action_log.py module with resolve_action_source(), publish_action(), and a ContextVar-based ActionContext that's set at the API boundary and read at lower-level mutation sites
  • Places publish_action calls next to existing Activity.objects.create() calls, piggybacking on their existing change detection rather than reimplementing it
  • Currently a no-op structured logger — will be wired to GroupActionLogEntry once that model lands

Instrumented actions

Resolve, unresolve, archive, assign, unassign, set priority, merge, mark reviewed, view, trigger autofix, comment (create/edit/delete)

Edit: Ended up adding instrumentation for some system tasks like auto_update_priority and integrations, as I wanted to be able to track missing instrumentation but without those it would get pretty noisy, and it wasn't a big thing to add here.

@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label May 27, 2026
Comment thread src/sentry/api/helpers/group_index/update.py
from typing import Any

from sentry.api import client
from sentry.api.client import ApiClient

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

was getting typing errors on all these tool files, have no idea why when main has them go through fine. Eventually gave up and fixed the typing issue here, seems like import was too ambiguous

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Feel free to spin this off, should get an instant stamp.

@yuvmen yuvmen marked this pull request as ready for review May 28, 2026 03:53
@yuvmen yuvmen requested review from a team as code owners May 28, 2026 03:54
Comment thread src/sentry/issues/action_log.py Outdated
Comment thread src/sentry/issues/status_change.py
Comment thread src/sentry/issues/action_log.py Outdated
Comment thread src/sentry/issues/action_log.py
@yuvmen yuvmen changed the title feat(issues): Add Issue Action Log instrumentation for issue mutations feat(issues): Add GroupActionLog instrumentation for issue mutations May 28, 2026
Comment thread src/sentry/issues/priority.py
Comment thread src/sentry/integrations/utils/sync.py
@linear-code

linear-code Bot commented May 28, 2026

Copy link
Copy Markdown

ID-1570

ID-1571

@kcons kcons left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't have many useful things to say about the logic for determining Source or the granularity of it, as ultimately I think those things are very tied to what actually works combined with what we need, and I'm not on firm footing in either case.

I'm also not sure how strictly to consider this PR; my sense is that while it is a big footprint and the start of some critical stuff, we're mostly considering it placeholder for now. If the intend is to land it (which i hope it is; starting to actually log stuff and consider the practicalities of collecting the relevant data in context is fairly urgent), I do think we need to go a bit harder on docs and interface, though that may mean being explicitly non-committal more than being very careful.

In principle, I think "a short identifying string with some structure, not large in cardinality, carefully controlled in generation but tolerant in consumption (when we start consuming)" is the right model here for source, and I do think we want source.

So, with that and my interest in getting preliminary stuff with plausible interfaces in play, I conceptually approve.

Comment thread src/sentry/issues/action_log.py
def publish_action(
*,
action: ActionType,
source: str,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Seems like this should be ActionSource.
I understand why it isn't; we want to be able to qualify things with prefixes to show it is a specific variant of a category of source.. but I don't think we want that to mean we accept a string.
I think it'd be nice to limit the set of legal ActionSources to those that we believe are valid, and know that by virtue of it being able to be constructed an ActionSource is valid; potentially be able to parse str to an ActionSource and know it is then valid. From the API perspective, this makes things simpler and harder to break. From a data management perspective, it means if it is published we think it is valid. The only real burden here is having an ActionSource representation that knows the rules. It could be a wrapped str with a regex, but I'm assuming it'd be some sort of SourceKind(StrEnum) akin to current ActionSource, along with an optional addition str with values restricted by SourceKind. I assume it'd have a __str__ method that sorta does ":".join[self.kind, self.variant] if self.variant else self.kind.

Maybe it's overkill, but interface-wise, easy, and implementation presumably one-shottable by an agent.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

yea I agree this should actually be ActionSource, and with your analysis here of the possible second type that includes variant. I think right now we cna go with this.
I think another possibility to what you suggested is we can keep it simpler and have the source variant be a part of the metadata. Like ActionSource has concrete categories that are well defined and low cardinality, if someone wants to add a more loose optional variant on top it can be in the data field and higher cardinality.

Comment thread src/sentry/issues/action_log.py Outdated
PAGERDUTY = "pagerduty"
OPSGENIE = "opsgenie"
PERFORCE = "perforce"
UNKNOWN = "unknown"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do you think there's value in distinguishing between 'UNKNOWN' and 'Something bad happened and we were unable to execute the appropriate logic'? Or is 'UNKNOWN' better understood as 'ERROR'?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Not sure if you think we shouldn't save the action log in when we cant determine source? I mean UNKNOWN is an error state in a way for sure, like we have logic to determine source, if our rules for source fail I dont want to fail the whole flow and prevent the log from getting created, so saving it with UNKNOWN I think is a good representation of this case, would be odd to save with source=ERROR no? though not sure if thats what youre suggesting

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I was trying to clarify for myself what UNKNOWN means. One natural interpretation is "not one of these other ones that we recognize" but sounds like it's an in-band None. That seems reasonable to me; I'm hoping we can move toward an interface where nobody is really hand-picking ActionSource (generated by helpers write-side, opt-in predicates read-side) so it shouldn't matter much. No change needed (as a special value, a one-line doc wouldn't hurt, but I think we'll end up doing a clarification pass on most of these, so it can wait).

Comment thread src/sentry/issues/action_log.py Outdated


def resolve_action_source(request: Request | None) -> str:
if request is None:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This fallback seems surprising. Are contexts where you might have a request common?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

yea this actually doesnt make much sense when I think about it, had in mind like SYSTEM cases will still call this with None, but as you say we are never unsure if we have request or not, will remove this

Comment thread src/sentry/issues/action_log.py Outdated


@contextmanager
def action_context_scope(source: str, actor_id: int | None = None) -> Generator[None]:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

With actor_id == None meaning SYSTEM, it seems safe to not have a default here. I'd read only setting source to mean only overriding source, not actor, if I saw it in code.

)


def publish_action_from_context(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm very interested in the context bits here.
It seems like a really helpful way for us to get coverage without having to thread through lots of extra data (with user it was maybe reasonable to expect we'd have it, but source is a different beast). I could imagine that we'd set up a context by default in most endpoints, and probably have a convention for threading it through task arguments so under normal circumstances a context could be assumed.
However, we don't get proof of availability, and refactors will break context and lead to errors we have to hope will be triaged.
It is possible to use static analysis to find cases of context use that don't have a provable source, but I don't know how hard that'd be to set up.

I think in general "_from_context" existing suggests that it's what most people should use outside of some narrow and shallow reporting cases; we should probably specify this if that's the case. Not necessarily in this change, but certainly in a v0 of what we expect anyone to use.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

yea agreed, this is the part that I was the most conflicted about. It does indeed come with this tradeoff you describe, but I think it is probably worth for the amount of clutter it saves. I am open to considering more sophisticated ways to make sure context exists where it needs to, this was my attempt to not get too fancy right away.
I wonder if we can even instruct agents to help with this, like an instruction in some AGENTS.md about "if publish_action_from_context is called, make sure context is populated earlier`, wont be airtight but might reduce times people break it. I say this becase I am not sure how viable static analysis would be in detecting something like, but agentic would probably be able to.

Right now breaking context would cause Sentry issues with the log.error there, and with the addition of throwing in tests you suggested it might help prevent breaking.

regarding from_context I think for sure this is a convention we want to push and yes we should it should be the preferable way outside of narrow cases like you said

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

yea agreed, this is the part that I was the most conflicted about. It does indeed come with this tradeoff you describe, but I think it is probably worth for the amount of clutter it saves. I am open to considering more sophisticated ways to make sure context exists where it needs to, this was my attempt to not get too fancy right away.
I wonder if we can even instruct agents to help with this, like an instruction in some AGENTS.md about "if publish_action_from_context is called, make sure context is populated earlier`, wont be airtight but might reduce times people break it. I say this becase I am not sure how viable static analysis would be in detecting something like, but agentic would probably be able to.

Right now breaking context would cause Sentry issues with the log.error there, and with the addition of throwing in tests you suggested it might help prevent breaking.

regarding from_context I think for sure this is a convention we want to push and yes we should it should be the preferable way outside of narrow cases like you said



@dataclass(frozen=True)
class ActionContext:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This strikes me as pretty central, conceptually and practically.
My pr has GroupActionActor because that's the core attribution information I was dealing with, and once determined it's best treated as one thing, but I think that needs to be extended with source, since in any given context they are really grouped.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

yea agreed as I said above this Context is the main thing here and we need to align on it. Regarding Actor, I see it as - Actor is mostly a "who" and ActionContext is about both who and how, so yea I think it should be extended to this, I dont mind how exactly so whatever works for you

idempotency_key: str | None = None,
) -> None:
actor_type = ActorType.USER if actor_id is not None else ActorType.SYSTEM
logger.info(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

might also be fun to have a counter tagged by action and source, just for now.

Comment thread src/sentry/issues/ingest.py Outdated
Comment thread src/sentry/issues/ingest.py Outdated
Comment thread src/sentry/issues/action_log.py
@yuvmen

yuvmen commented May 29, 2026

Copy link
Copy Markdown
Member Author

@kcons thanks for all the comments - I think this work for sure is a bit exploratory but I do intend on actually landing this PR, acknowledging much of this is still subject to change.

I fully agree with:

In principle, I think "a short identifying string with some structure, not large in cardinality, carefully controlled in generation but tolerant in consumption (when we start consuming)" is the right model here for source, and I do think we want source.

regarding this

I do think we need to go a bit harder on docs and interface, though that may mean being explicitly non-committal more than being very careful.

I also agree but I am not sure how to address it at this point, do you think like add some more comments / context in code or detail these decisions in our docs better?

I made corrections and responded to your comments, I do want to get this PR in shape and land it, there are some instrumentation assumptions it will help me prove and I think setting this in place will move us forward, even if its all subject to change.

@kcons

kcons commented May 30, 2026

Copy link
Copy Markdown
Member

@kcons thanks for all the comments - I think this work for sure is a bit exploratory but I do intend on actually landing this PR, acknowledging much of this is still subject to change.

I fully agree with:

In principle, I think "a short identifying string with some structure, not large in cardinality, carefully controlled in generation but tolerant in consumption (when we start consuming)" is the right model here for source, and I do think we want source.

regarding this

I do think we need to go a bit harder on docs and interface, though that may mean being explicitly non-committal more than being very careful.

I also agree but I am not sure how to address it at this point, do you think like add some more comments / context in code or detail these decisions in our docs better?

I made corrections and responded to your comments, I do want to get this PR in shape and land it, there are some instrumentation assumptions it will help me prove and I think setting this in place will move us forward, even if its all subject to change.

Regardling landability, I think we just want someone seeing a use of this module to be able to answer "what is this doing? is this important? should I be using it?" fairly quickly (ie basic doc coverage on the public interface, perhaps with a standard one-line disclaimer about it being experimental or whatever). If someone is refactoring involved code, they should be able to do it correctly. Also, a module level doc given the basic context and status so someone wondering what action_log is has a reasonable answer ("what is this module? should I be using it?" probably core questions to answer).
I feel like it's perfectly fine for us to set a low threshold for acceptability if we aren't breaking interfacing code and are clear enough about the state of things; that may be a mostly theoretical concern (not like most new code is final in form or deeply considered) but the due diligence should only take a few minutes, so seems worth it to me.

I hope to get back to my table PR soon (almost done with replies) and once that happens, I'll have some fun merging this in.

Comment thread src/sentry/api/helpers/group_index/update.py
@yuvmen

yuvmen commented Jun 1, 2026

Copy link
Copy Markdown
Member Author

@kcons agreed sounds good, added some comments, I think it makes sense when adding something experimental like this, we can always revise later

yuvmen added 7 commits June 1, 2026 09:55
Adds `publish_action` calls alongside existing Activity creation sites
to log issue mutations with source attribution (web, API, MCP, Seer).

Uses a contextvar (`ActionContext`) set at the API boundary in
`update_groups()` and read at lower-level mutation sites, so functions
like `GroupAssignee.assign()` and `update_priority()` can log actions
without signature changes.

Instrumented actions: resolve, unresolve, archive, assign, unassign,
set_priority, merge, mark_reviewed, view, trigger_autofix, comment
(create/edit/delete).

Currently a no-op structured logger — will be wired to the real
GroupActionLogEntry model once that lands.
The `from sentry.api import client` resolves to the module, not the
ApiClient instance, causing mypy attr-defined errors on `.get()` calls.
…rom unresolve

- Replace module-level global MCP_APPLICATION_ID with django.core.cache
  (5min TTL), so a missing app record on first lookup doesn't permanently
  poison the cache for the worker lifetime
- Add ActionType.UNARCHIVE to distinguish un-ignoring (IGNORED->UNRESOLVED)
  from un-resolving (RESOLVED->UNRESOLVED), matching the existing signal
  distinction (issue_unignored vs issue_unresolved)
…plication_id

- Remove UNARCHIVE — "unresolve" is the destination state regardless of
  whether the issue was previously resolved or archived
- Skip _get_mcp_application_id() cache/DB call when request has no
  application_id (the common case for non-token-auth requests)
- Use ActionSource.MCP constant in f-string for MCP client slug
…ontext

When publish_action_from_context is called without an ActionContext,
log an error (creates a Sentry issue with stack trace) and record the
action with source="unknown" instead of silently dropping it.
yuvmen added 6 commits June 1, 2026 09:55
…revert UNARCHIVE

- Wrap system-initiated mutations (auto_update_priority, ingest assign,
  ownership auto-assign, release-based assign) with
  action_context_scope(source=SYSTEM)
- Wrap integration sync assign/deassign with
  action_context_scope(source=integration.provider)
- Revert UNARCHIVE action type — UNRESOLVE covers both transitions since
  "unresolved" is a real state, "unarchived" is not
- Keep logger.error for missing context so unexpected callers surface as
  Sentry issues
- Make actor_id required in action_context_scope (no silent default)
- Raise RuntimeError in test environment when context is missing
- Remove dead request=None branch from resolve_action_source
- Add metrics.incr counter tagged by action and source
The RuntimeError in test environment broke every existing test that
calls instrumented functions without action context. Keep logger.error
as the safety net instead — it creates Sentry issues for triage without
coupling unrelated tests to the action log system.
@yuvmen yuvmen force-pushed the yuvmen/group-action-log-instrumentation branch from 0934633 to ab0f6b4 Compare June 1, 2026 16:57
Comment thread src/sentry/issues/action_log.py Outdated


def _get_mcp_application_id() -> int | None:
from django.core.cache import cache

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: move to top of file?


@dataclass(frozen=True)
class ActionContext:
source: str

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should we enforce that this is an ActionSource?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ah just saw Kyle's comment below

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

yea it would just take solving some of the variant stuff and how we do it, will leave it as a follow up

data.update({"participants": participants})

publish_action(
action=ActionType.VIEW,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

seems like we'll end up recording a ton of these. probably not worth adjusting at this point, but i wonder if eventually we may want to sample view events

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

yea I wondered about that, I am trying to not log a VIEW on bulk fetches, only specific get for a specific issue, so I am not sure how much is this going to explode or not on a single issue. We will have a lot of these in general that is for sure, I think once we merge and have some numbers we can consider our steps

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

When we log these permanently, I think we'll want to throttle them.
I don't think data will necessarily show it to be unimportant, but I think the difference between "they fetched this" and "they fetched this N times over 10 minutes" isn't huge for us, and this carries much less strength of intent than the place where we update GroupSeen (I assume), so if we can do something simple to reduce log load and what we'd count as noise, that's good.

The mechanism is an interesting question. Maybe it doesn't much matter, and a ttl'd cache key for simple throttling is good enough.
It's also not too hard to support time-bounded deduplication with action-specific criteria, but if that's not stepping on idempotency key stuff, that is lossy, so a VIEW-specific thing seems a better starting point.

I'd be interested to add the cache-ttl based checking just as a way to track how often it matters, but not an issue for this PR.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I see, I guess time-bounded dedup in case its the same actor requesting make sense. I had in mind like - I dont care if they "fetched it N times over 10 minutes" but I do care if they fetched it now or a week ago, like as an indication of when did X person last notice this issue. I think its indeed something to think about in the future, gonna leave it raw for now to let us just log stats as it is

request = _make_request(meta={"HTTP_X_SEER_REFERRER": "seer-explorer"})
assert resolve_action_source(request) == "seer:explorer"

def test_seer_rpc_authenticator(self) -> None:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

a test for the priority logic might be good, e.g. when seer referrer header and SeerRpcSignatureAuthentication are both present

@kcons kcons left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The auto_spec and the api app part are the only "please do" here.
I want to rework the way we type ActionSource, but we don't need to block on that. At this point, we only need to block on wrong things and things that make future iteration harder.

Caveat: I'm reviewing this from the perspective of it enabling GAL iteration; my approval shouldn't be treated as "I think the group lifecycle integration is definitely correct" or "i think we're doing source determination accurately".

data.update({"participants": participants})

publish_action(
action=ActionType.VIEW,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

When we log these permanently, I think we'll want to throttle them.
I don't think data will necessarily show it to be unimportant, but I think the difference between "they fetched this" and "they fetched this N times over 10 minutes" isn't huge for us, and this carries much less strength of intent than the place where we update GroupSeen (I assume), so if we can do something simple to reduce log load and what we'd count as noise, that's good.

The mechanism is an interesting question. Maybe it doesn't much matter, and a ttl'd cache key for simple throttling is good enough.
It's also not too hard to support time-bounded deduplication with action-specific criteria, but if that's not stepping on idempotency key stuff, that is lossy, so a VIEW-specific thing seems a better starting point.

I'd be interested to add the cache-ttl based checking just as a way to track how often it matters, but not an issue for this PR.

Comment thread tests/sentry/issues/test_action_log.py Outdated
assert len(resolve_calls) == 1
assert resolve_calls[0].kwargs["group_id"] == self.group.id

@patch(PUBLISH_UPDATE_CTX)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we presumably want to auto_spec=True on these to validate use.

Comment thread tests/sentry/issues/test_action_log.py Outdated
assert info_record.__dict__["source"] == "unknown"


PUBLISH_UPDATE = "sentry.api.helpers.group_index.update.publish_action"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

marginal preference for patch.object(actual_module_maybe_imported_as_alias, 'method_name'). The validation benefit isn't huge, but you get click-through and some tools do better, and it should fail at import time rather than execution.

Not as valuable as auto_spec, so up to you.

Comment thread src/sentry/issues/action_log.py Outdated
PAGERDUTY = "pagerduty"
OPSGENIE = "opsgenie"
PERFORCE = "perforce"
UNKNOWN = "unknown"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I was trying to clarify for myself what UNKNOWN means. One natural interpretation is "not one of these other ones that we recognize" but sounds like it's an in-band None. That seems reasonable to me; I'm hoping we can move toward an interface where nobody is really hand-picking ActionSource (generated by helpers write-side, opt-in predicates read-side) so it shouldn't matter much. No change needed (as a special value, a one-line doc wouldn't hurt, but I think we'll end up doing a clarification pass on most of these, so it can wait).

Comment thread src/sentry/issues/action_log.py Outdated

logger = logging.getLogger(__name__)

# Issue Action Log — experimental module for tracking who did what to an issue and how.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it is Group Action Log.

Comment thread src/sentry/issues/action_log.py Outdated
from sentry.models.apiapplication import ApiApplication

try:
app = ApiApplication.objects.filter(name__icontains="sentry-mcp").first()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This non-deterministically picks from like 5 api apps, and I think only 1 is ours.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

hmm oh I now realize this doesnt work the way I thought it did, ApiApplication is actually just an integration and anyone can add them and name them, this check is not good enough at all.
We also have more than one as you say that belongs to us, gonna read this off of a secret with specific values

Comment thread src/sentry/issues/action_log.py Outdated
yuvmen added 2 commits June 2, 2026 13:23
Replace the ApiApplication name lookup (non-deterministic and spoofable)
with a check on the User-Agent the MCP sends (sentry-mcp/...), mirroring
how sentry-cli is detected. The X-Sentry-MCP-Client-Name header still
provides the sub-type (mcp:claude-code, etc.). Source attribution is
self-reported and spoofable by design — best-effort, not for audit.
Use the standardized X-Sentry-MCP-Client-Family header (claude-code,
cursor, etc.) instead of the free-form client-name, so sub-type values
are predictable. Unrecognized families are logged so new ones can be
added; the MCP's own "other"/"unknown" catch-alls fall back to plain mcp.
Comment thread src/sentry/receivers/releases.py
@yuvmen

yuvmen commented Jun 2, 2026

Copy link
Copy Markdown
Member Author

MCP started sending client-family in this PR, and it was my actual original preference as it basically uses the MCP to standardize the client-name values, so I switched to go off that.

The question remains from previous discussions here of how/if we limit the values we can get here, same considerations as taking variants from client-name, even if its more standardized now. We still only accept some mainstream specific values as variants (e.g. source=mcp:claude-code) and leave the rest as just mcp. We can decide on client-familyvalues I think when we decide on how strict we wantsource` values to be in general.

resolved_in_commit and resolved_in_pull_request wrapped the self-assign
in action_context_scope with actor_id=None while passing acting_user into
assign(), so the action log recorded ASSIGN as a system action with no
actor. Attribute it to acting_user, matching the activity and group
history records.

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit e1aecec. Configure here.

Comment thread src/sentry/seer/endpoints/group_ai_autofix.py Outdated
Comment on lines +121 to +126
with action_context_scope(source=integration.provider, actor_id=None):
GroupAssignee.objects.assign(
group,
user,
assignment_source=AssignmentSource.from_integration(integration),
)

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.

Bug: The action_context_scope in _handle_assign is incorrectly called with actor_id=None, causing user assignment actions from integrations to be misattributed to the system.
Severity: LOW

Suggested Fix

In _handle_assign, update the action_context_scope to use the available user's ID. Change with action_context_scope(source=integration.provider, actor_id=None): to with action_context_scope(source=integration.provider, actor_id=user.id):.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: src/sentry/integrations/utils/sync.py#L121-L126

Potential issue: In the `_handle_assign` function, the `action_context_scope` is invoked
with `actor_id=None` during integration syncs. A `user` object is available at this
point, but its ID is not used. This causes the action log to incorrectly attribute the
assignment to a system action with no actor, instead of the user being assigned. This
pattern was identified as a bug and fixed in other parts of the codebase
(`resolved_in_commit` and `resolved_in_pull_request`), but this instance was missed.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

deferring to follow up

The POST handler logged TRIGGER_AUTOFIX on any 202, but _post_inner
returns 202 for coding_agent_handoff and open_pr too, not only a built-in
autofix run — so non-autofix steps were recorded as autofix triggers.
Remove the instrumentation (and fold _post_inner back into post) until it
can target the actual autofix run. Tracked in ID-1591.

@kcons kcons left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I favor paring down bits not needed to flex source determination (more prototype and api demo than necessarily useful for now) and sentrybot seems to have a point, but I think we can go forward with this.
Thanks!

@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Backend Test Failures

Failures on ac8de43 in this run:

tests/sentry/issues/test_action_log.py::TestActionLogIntegration::test_merge_emits_actionslog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5091"
tests/sentry/issues/test_action_log.py::TestActionLogIntegration::test_resolve_emits_actionlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5097"
tests/sentry/issues/test_occurrence_consumer.py::ParseEventPayloadTest::test_handles_missing_receivedlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
.venv/lib/python3.13/site-packages/django/db/models/query.py:948: in get_or_create
    return self.get(**kwargs), False
           ^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/models/query.py:635: in get
    raise self.model.DoesNotExist(
E   sentry.users.models.identity.Identity.DoesNotExist: Identity matching query does not exist.

During handling of the above exception, another exception occurred:
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:105: in _execute
    return self.cursor.execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/decorators.py:16: in inner
    return func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:95: in execute
    return self.cursor.execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E   psycopg2.errors.UniqueViolation: duplicate key value violates unique constraint "sentry_identity_idp_id_external_id_a24ac9c1_uniq"
E   DETAIL:  Key (idp_id, external_id)=(16, AccountId) already exists.

The above exception was the direct cause of the following exception:
src/sentry/integrations/pipeline.py:282: in _install_integration
    identity_model = Identity.objects.link_identity(
src/sentry/users/models/identity.py:104: in link_identity
    identity, created = self.get_or_create(
src/sentry/silo/base.py:157: in override
    return original_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/models/manager.py:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/silo/base.py:157: in override
    return original_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/models/query.py:955: in get_or_create
    return self.create(**params), True
           ^^^^^^^^^^^^^^^^^^^^^
src/sentry/silo/base.py:157: in override
    return original_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/models/query.py:665: in create
    obj.save(force_insert=True, using=self.db)
src/sentry/silo/base.py:157: in override
    return original_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/models/base.py:902: in save
    self.save_base(
src/sentry/silo/base.py:157: in override
    return original_method(*args, **kwargs)
... (135 more lines)
tests/sentry/issues/test_occurrence_consumer.py::ParseEventPayloadTest::test_occurrence_title_on_eventlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
.venv/lib/python3.13/site-packages/django/db/models/query.py:948: in get_or_create
    return self.get(**kwargs), False
           ^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/models/query.py:635: in get
    raise self.model.DoesNotExist(
E   sentry.users.models.identity.Identity.DoesNotExist: Identity matching query does not exist.

During handling of the above exception, another exception occurred:
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:105: in _execute
    return self.cursor.execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/decorators.py:16: in inner
    return func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:95: in execute
    return self.cursor.execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E   psycopg2.errors.UniqueViolation: duplicate key value violates unique constraint "sentry_identity_idp_id_external_id_a24ac9c1_uniq"
E   DETAIL:  Key (idp_id, external_id)=(16, AccountId) already exists.

The above exception was the direct cause of the following exception:
src/sentry/integrations/pipeline.py:282: in _install_integration
    identity_model = Identity.objects.link_identity(
src/sentry/users/models/identity.py:104: in link_identity
    identity, created = self.get_or_create(
src/sentry/silo/base.py:157: in override
    return original_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/models/manager.py:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/silo/base.py:157: in override
    return original_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/models/query.py:955: in get_or_create
    return self.create(**params), True
           ^^^^^^^^^^^^^^^^^^^^^
src/sentry/silo/base.py:157: in override
    return original_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/models/query.py:665: in create
    obj.save(force_insert=True, using=self.db)
src/sentry/silo/base.py:157: in override
    return original_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/models/base.py:902: in save
    self.save_base(
src/sentry/silo/base.py:157: in override
    return original_method(*args, **kwargs)
... (135 more lines)
tests/sentry/models/test_file.py::FileTest::test_seeklog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/models/test_file.py:155: in test_seek
    file1 = File.objects.create(name="baz.js", type="default", size=26)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/silo/base.py:157: in override
    return original_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/models/manager.py:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/silo/base.py:157: in override
    return original_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/models/query.py:665: in create
    obj.save(force_insert=True, using=self.db)
src/sentry/silo/base.py:157: in override
    return original_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/models/base.py:902: in save
    self.save_base(
src/sentry/silo/base.py:157: in override
    return original_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/models/base.py:1008: in save_base
    updated = self._save_table(
.venv/lib/python3.13/site-packages/django/db/models/base.py:1169: in _save_table
    results = self._do_insert(
.venv/lib/python3.13/site-packages/django/db/models/base.py:1210: in _do_insert
    return manager._insert(
.venv/lib/python3.13/site-packages/django/db/models/manager.py:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/models/query.py:1873: in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/models/sql/compiler.py:1882: in execute_sql
    cursor.execute(sql, params)
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
... (8 more lines)
tests/sentry/models/test_release.py::ReleaseFilterBySemverTest::testlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5119"
tests/sentry/models/test_release.py::ReleaseFilterBySemverTest::test_wildcardlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5125"
tests/sentry/monitors/test_models.py::MonitorTestCase::test_save_defaults_slug_to_namelog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5137"
tests/sentry/monitors/test_models.py::MonitorEnvironmentTestCase::test_monitor_environment_limitslog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5143"
tests/sentry/monitors/test_models.py::CronMonitorDataSourceHandlerTest::test_get_current_instance_countlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5149"
tests/sentry/monitors/test_models.py::MonitorIsMutedPropertyTestCase::test_is_muted_single_environmentlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5155"
tests/sentry/notifications/notifications/test_suspect_commits_activity.py::SuspectCommitsInActivityNotificationsTest::test_resolved_notification_includes_suspect_commitslog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5161"
tests/sentry/notifications/platform/msteams/test_provider.py::MSTeamsNotificationProviderSendTest::test_send_to_direct_messagelog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5167"
tests/sentry/notifications/platform/test_service.py::NotificationServiceTest::test_killswitch_only_blocks_listed_sourceslog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5173"
tests/sentry/notifications/platform/test_service.py::NotificationServiceTest::test_notify_integration_target_async_with_failurelog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5179"
tests/sentry/options/test_manager.py::OptionsManagerTest__InCellMode::test_flag_immutablelog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5185"
tests/sentry/options/test_manager.py::OptionsManagerTest__InCellMode::test_unregisterlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5191"
tests/sentry/options/test_manager.py::OptionsManagerTest::test_driftedlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5197"
tests/sentry/plugins/bases/test_issue2.py::IssuePlugin2GroupActionTest::test_get_unlink_validlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5203"
tests/sentry/preprod/api/endpoints/public/test_organization_preprod_artifact_install_details.py::OrganizationPreprodArtifactPublicInstallDetailsEndpointTest::test_installable_android_artifactlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5209"
tests/sentry/preprod/api/endpoints/public/test_project_preprod_build_distribution_latest.py::CheckForUpdatesTest::test_combined_filter_inheritancelog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5215"
tests/sentry/preprod/api/endpoints/test_builds.py::BuildsEndpointTest::test_query_git_pr_numberlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5221"
tests/sentry/preprod/api/endpoints/test_preprod_artifact_snapshot.py::ProjectPreprodSnapshotTest::test_snapshot_negative_dimensionslog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5227"
tests/sentry/preprod/api/endpoints/test_project_preprod_upload_options.py::ProjectPreprodUploadOptionsTest::test_without_feature_flaglog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5233"
tests/sentry/preprod/size_analysis/test_comparison_utils.py::CanCompareSizeMetricsTest::test_failed_takes_priority_over_pendinglog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5239"
tests/sentry/preprod/size_analysis/test_grouptype.py::PreprodSizeAnalysisDetectorQueryFilterTest::test_matching_query_evaluates_normallylog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140034801617792_x5245"
tests/sentry/preprod/test_models.py::PreprodArtifactBaseArtifactTest::test_get_head_artifacts_for_commit_multiple_artifacts_same_commitlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError

... (truncated due to GitHub comment size limit)

@yuvmen yuvmen merged commit 9718806 into master Jun 3, 2026
115 of 118 checks passed
@yuvmen yuvmen deleted the yuvmen/group-action-log-instrumentation branch June 3, 2026 16:36
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