Skip to content

[pull] master from getsentry:master#2008

Merged
pull[bot] merged 60 commits into
KingDEV95:masterfrom
getsentry:master
May 28, 2026
Merged

[pull] master from getsentry:master#2008
pull[bot] merged 60 commits into
KingDEV95:masterfrom
getsentry:master

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented May 28, 2026

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

cvxluo and others added 30 commits May 28, 2026 08:56
Fix a small misalignment between highlight and the bottom of the project
selector. Same fix as:

https://github.com/getsentry/sentry/blob/b68ea049d1ae2be4471a52fd42de580ab6b71223/static/app/components/core/compactSelect/listBox/index.tsx#L296

Before:
<img width="723" height="175" alt="Screenshot 2026-05-27 at 10 25 39 AM"
src="https://github.com/user-attachments/assets/f32301af-2baf-4aa9-a8b3-74661917c906"
/>
After:
<img width="835" height="220" alt="Screenshot 2026-05-27 at 11 24 50 AM"
src="https://github.com/user-attachments/assets/106c079a-0567-4ef3-9554-356321dcb401"
/>

Co-authored-by: Claude <noreply@anthropic.com>
…6333)

<!-- Describe your PR here. -->

`POST /organizations/{org}/experimental/projects/` has been stable since
Jan 2024 — it is what the onboarding UI calls when a member (no
`project:write`) creates a project. Two problems: the `/experimental/`
path is a one-off with no codebase pattern, and `EXPERIMENTAL` status
excludes it from the OpenAPI spec, so `@sentry/api` and the CLI have
never been able to use it.

`POST /organizations/{org}/projects/` was an empty slot (only GET
existed). This fills it.

**Before**

```
POST /organizations/{org}/experimental/projects/   EXPERIMENTAL  ← not in spec
POST /teams/{org}/{team}/projects/                 PUBLIC
```

**After**

```
POST /organizations/{org}/projects/                PUBLIC  ← same behavior, first-class
POST /organizations/{org}/experimental/projects/   EXPERIMENTAL  ← temporary alias (backward compat)
POST /teams/{org}/{team}/projects/                 PUBLIC
```

The behavior is identical — auto-creates `team-{username}` for the
caller, requires only `project:read`. The team-scoped endpoint is
untouched.

The `/experimental/` alias is kept alive as a backward-compat shim
(`OrganizationProjectsExperimentalCompatEndpoint`) so the frontend
doesn't break between this deploy and the frontend PR landing. It's
POST-only (`http_method_names = ["post", "options"]`), marked
`EXPERIMENTAL` so it stays out of the spec, and carries a TODO to remove
it once the frontend PR merges.

Also fixes a pre-existing data consistency bug in the moved code:
`project.add_team(team)` was called outside the `transaction.atomic()`
block, meaning a failure there would leave a team and project in the DB
without being linked. Moved it inside the transaction.

**Housekeeping:** `organization_projects_experiment.py` deleted,
constants/helpers folded into `organization_projects.py`, both apidocs
allowlists updated, CODEOWNERS updated, test file renamed
`test_organization_projects_create.py` + new test for the `role=member`
happy path.

Frontend follow-up (separate PR): drop `/experimental/` from
`useCreateProject.ts` and `useCreateProjectFromWizard.tsx`, then a
cleanup PR removes the alias.

### Legal Boilerplate

Look, I get it. The entity doing business as "Sentry" was incorporated
in the State of Delaware in 2015 as Functional Software, Inc. and is
gonna need some rights from me in order to utilize my contributions in
this here PR. So here's the deal: I retain all rights, title and
interest in and to my contributions, and by keeping this boilerplate
intact I confirm that Sentry can use, modify, copy, and redistribute my
contributions, under Sentry's choice of terms.
…ks (#116385)

Remove the
`features.has("organizations:github-enterprise-github-com-source", ...)`
guards from the two GHE setup pipelines (form-based
`InstallationConfigView` and API-driven `GHEInstallationConfigApiStep`),
along with the tests that exercised the rejection path.

The flag is at 100% rollout (segment `GA`, no conditions) in flagpole,
so every org already passes the check — removing it makes that explicit
and lets us proceed with the standard flagpole removal sequence.

This is step 1 of three. Follow-ups:
1. Remove the
`feature.organizations:github-enterprise-github-com-source` block from
`sentry-options-automator/options/default/flagpole.yaml`.
2. Remove the `manager.add(...)` registration from
`src/sentry/features/temporary.py`.

Each waits for the previous to deploy.
Currently the `has` filter does not support dynamic fetching of
attributes for it's value combobox. This means users may not be seeing
all of the potential keys.

This PR updates the query builder `has` filter to search dynamically for
those values based off of the `getTagKeys` prop.

Closes LOGS-819

---------

Co-authored-by: Claude Opus 4 <noreply@anthropic.com>
The canonical attribute name for current environment (`production`,
`staging`, etc) is `sentry.environment`. However, for users'
convenience, we instead expose this in search as `environment`:


https://github.com/getsentry/sentry/blob/a26a0bef04d21e6ee7b6a55d7324ce01f7e3c9d3/src/sentry/search/eap/spans/attributes.py#L431

We also have code that makes Sentry aware of deprecated attributes from
https://github.com/getsentry/sentry-conventions, in
`_update_attribute_definitions_with_deprecations`:


https://github.com/getsentry/sentry/blob/a26a0bef04d21e6ee7b6a55d7324ce01f7e3c9d3/src/sentry/search/eap/spans/attributes.py#L528-L590

When the sentry-conventions package was updated in #113515 it brought in
two new attributes that backfill into `sentry.environment`:

```json
{"key": "resource.deployment.environment", "_status": "backfill", "replacement": "sentry.environment"}
{"key": "resource.deployment.environment.name", "_status": "backfill", "replacement": "sentry.environment"}
```

With this, `_update_attribute_definitions_with_deprecations` started
adding a field definition for `sentry.environment`, shadowing our
explicit mapping to the public field name `environment`. Not only did
this start defining the wrong attribute name, it actually hid
environment entirely, due to separate handling that filters out
`sentry.`-prefixed attribute names.

This PR explicitly checks for existing field definitions _before_ adding
new ones from sentry-conventions' deprecations. Currently
`environment`/`sentry.environment` appears to be the only field affected
by this bug, but this pattern in general should work if new such
definitions/deprecations are ever added.

Fixes BROWSE-527.

---

🤖: Claude Code (Opus 4.6) used to generate the code, with human editing
+ careful review. All words my own.
- Add a new "Debug in Sentry Replay Debugger" dropdown menu item for
superusers/employees in the replay detail view that opens the [Sentry
Replay Debugger](https://github.com/getsentry/replay-debugger/releases)
macOS app
- Replace `(superuser)` text with `FeatureBadge` debug variant on
existing superuser-only menu items

<img width="338" height="192" alt="image"
src="https://github.com/user-attachments/assets/970af2e7-aa01-476b-a4e6-5f1a17071c1c"
/>

Co-authored-by: Claude Opus 4 <noreply@anthropic.com>
Enforces css template tags inside of styled css. Allows us to enforce
our css lint rules and formatting.

```tsx
// Bad
const Row = styled('div')<{isSelected: boolean}>`
  padding: ${p => p.theme.space.md};

  ${p =>
    p.isSelected &&
    `
      background: ${p.theme.tokens.background.secondary};
      border-color: ${p.theme.tokens.border.accent};
    `}
`;

// Good
const Row = styled('div')<{isSelected: boolean}>`
  padding: ${p => p.theme.space.md};

  ${p =>
    p.isSelected &&
    css`
      background: ${p.theme.tokens.background.secondary};
      border-color: ${p.theme.tokens.border.accent};
    `}
`;
```
Update the docs for the group details endpoint to use the modern
drf-spec system.

Co-authored-by: Claude <noreply@anthropic.com>
This PR refactors how the metric samples table renders based off of
different sources. For the metrics page nothing has changed, however:

* Issue Detail & Trace Waterfall:
  * Rename view similar spans, to "View connected traces".
* Add an "open in explore" button, which is just a shortcut to explore
with that metric series open.
* Issue Details:
  *  Remove the add filter behavior

Closes LOGS-826

---------

Co-authored-by: OpenAI Codex <noreply@openai.com>
Enforces project-level access on preprod artifact endpoints that
previously scoped artifact lookups to the organization.

In closed-membership organizations, org membership does not imply access
to every project. The public size-analysis and install-details endpoints
now require access to the artifact project before returning size data or
creating install URLs. Size comparison downloads now also verify that
both metric artifacts belong to the authorized URL project.

The raw size-analysis download path already enforced project access
through `PreprodArtifactEndpoint`; this adds regression coverage for
that behavior.

Verified with focused backend tests for the affected preprod endpoints
and `prek` on the changed files.

Refs LINEAR VULN-1681
Refs LINEAR EME-1174
Refs LINEAR EME-1175
Refs LINEAR EME-1176
Refs LINEAR EME-1177

Co-authored-by: Codex <noreply@openai.com>
Misc cleanup, this event reprocessing endpoint seems to have a copy
pasted name from event-attachments above it.

Co-authored-by: Claude <noreply@anthropic.com>
…re (#116397)

Adds examples + types in preparation for publishing the debug files
endpoint with the modern DRF system.
Remove the `@pytest.mark.skip` markers on
`test_empty_attribute_type_for_all_attribute_types` and
`test_multiple_attribute_types` in
`tests/snuba/api/endpoints/test_organization_trace_item_attributes.py`.

Snuba PR getsentry/snuba#7689 removed boolean attribute double-writing,
and #111421 (cd2fcde) already updated the assertions in these tests
for the post-double-write world but kept the skip markers in place. Both
tests now pass locally against current Snuba, so the markers can go.

The three other boolean attribute tests called out in #111421
(`test_boolean_attributes` for logs and spans, and
`test_trace_metrics_boolean_attributes`) also pass locally — no
additional changes needed.

Refs #111421
Refs getsentry/snuba#7689


Agent transcript:
https://claudescope.sentry.dev/share/93vAKRpZyG9v5qDWDpIGfdIhSi1T6ak7JYSJsC0-k54
…gnore list (#116229)

Resolves
[ENG-7754](https://linear.app/getsentry/issue/ENG-7754/remove-sentryserviceseventstoremodels-from-ignore-list).

Fixes `mypy` typing issues in
`src/sentry/services/eventstore/models.py`.

Summary of changes:
- `Event` --> `BaseEvent` in grouping code. These grouping functions are
called with both `Event`s and `GroupEvent`s, so the correct common type
is the base class `BaseEvent`.
- `BaseEvent.data` abstract setter, `Event.data` setter, & `Event.group`
setter signatures widened to accept `None`, since the data they accept
is nullable
- Adds a no-op `GroupEvent.group_id` setter to satisfy the base class
contract
- Updates the `GroupEvent.data` setter to accept raw dicts in addition
to structured `NodeData` (some callers do this)
- Added and updated return type annotations for various methods across
`BaseEvent`, `Event`, and `GroupEvent`
- Changed the `EventSubjectTemplateData` base class because it
previously did not satisfy the `Mapping` protocol
Pass the timestamp along for the given metrics trace item details.

Closes LOGS-828

---------

Co-authored-by: OpenAI Codex <noreply@openai.com>
…rence to monitors (#116313)

This setting affects Monitors & Alerts rather than just Alerts like it
did before, so this PR updates copy to reflect that.
…olders (#116334)

Each `pipelineIntegrationX.tsx` (and its spec) moves into a per-provider
folder under `static/app/components/pipeline/` as
`integrationX/index.tsx`. `pipelineDummyProvider.tsx` similarly moves to
`dummyProvider/index.tsx`. Internal imports in `registry.tsx` and the
two external imports of `InstallationInfo` are updated.

The motivation is to give each provider room to grow sibling modules —
custom hooks, helpers, sub-components — without polluting the shared
pipeline directory. The first such sibling
(`useDiscordAppDirectoryInstall`) lands in a follow-up PR; this one is a
pure rename with no behavior change.

`shared/`, `registry.tsx`, `modal`, `usePipeline`, `types`, `testUtils`,
and `index.stories` stay flat. Exported symbol names are unchanged.

Verified: `pnpm typecheck`, `pnpm run lint:js`, and `pnpm test-ci
components/pipeline` (140/140) all pass.
This PR wires up the logs query to pass the `timestamp` while fetching
the trace item details for a given log.

Closes LOGS-829
Requires: #116315

---------

Co-authored-by: OpenAI Codex <noreply@openai.com>
This PR updates the calls to trace item details when it comes to the
trace waterfall to ensure that timestamps are passed to the request.

Also introducing a helper function to convert precise timestamps to
seconds based timestamps.

Closes LOGS-830
Requires: #116315

---------

Co-authored-by: OpenAI Codex <noreply@openai.com>
… 1st page (#116072)

A quick fix for something I noticed: when linked to a generic settings
page from our documentation:

https://sentry.io/orgredirect/organizations/:orgslug/settings/projects/:projectId/security-and-privacy/

I was presented with a "Select a project to continue" modal that clearly
listed a limited set of Sentry projects: they're alphabetically sorted
and end at "I", so the main `sentry` project was missing.

Instead of accepting the default page size on
/organizations/{orgSlug}/projects/ we should pass `?allprojects=1` to
ensure we get all projects at once.

Tested with dev-ui locally.

Before:
<img width="964" height="845" alt="Screenshot 2026-05-21 at 4 24 48 PM"
src="https://github.com/user-attachments/assets/cdb5b43b-1571-4869-9548-f611a0279e46"
/>

After:
<img width="1033" height="904" alt="Screenshot 2026-05-21 at 4 24 59 PM"
src="https://github.com/user-attachments/assets/d8e057ed-7582-4fad-bdb8-2dd553ba08db"
/>
…view (#116379)

`IntegrationOrganizationLink` was carrying GitHub-only installation
lookup logic — the `/extensions/github/installation/:id/` fetch, the
"sender verification" info banner, the "couldn't verify" warning
fallback, and the corresponding error toast — wedged in alongside the
generic org-picker flow that other providers also use. This moves it
into a sibling `GitHubInstallationCallout` component so the org-link
view doesn't conflate two unrelated provider entry points, and the
GitHub-specific code isn't fetched (or even imported) for non-GitHub
installs.

While moving, the previous `useApiQuery` call — which had a `/../../...`
path hack to escape `/api/0/` — is replaced with a hand-rolled
`queryOptions` factory using an unprefixed `Client({baseUrl: ''})`. The
factory mirrors the shape `apiOptions` produces (returns
`ApiResponse<T>`, uses `selectJson` to unwrap), so cache semantics match
the rest of the codebase. A long-form comment in the file explains why
this endpoint lives outside `/api/0/` (it's mounted under
`extensions/github/` in the integration package's `urls.py` rather than
the API URL conf).
#116400)

Clean up the allowlists for API ownership and publish status.

Co-authored-by: Claude <noreply@anthropic.com>
Fixing issue with failing log tests introduced in:
#116374

Co-authored-by: Codex <codex@openai.com>
Co-Authored-By: untitaker <837573+untitaker@users.noreply.github.com>

Co-authored-by: getsentry-bot <10587625+getsentry-bot@users.noreply.github.com>
Co-authored-by: untitaker <837573+untitaker@users.noreply.github.com>
…6392)

This work was incomplete and unused (no users had the flag enabled, even
internally). Remove it for now. If it ever needs to come back we'll
rescue this implementation or reimplement it.

Removing the flag definition is safe because the reference in Flagpole
was [already
removed](getsentry/sentry-options-automator#7963).

---

🤖: Claude Code (Opus 4.6) used to generate the code, with human editing
+ careful review. All words my own.
…orer page (#116250)

+ Register the metrics and profiling explorer with the LLM context
system so Seer Explorer can read page state (active metric queries,
chart interval, date range). Follows the same pattern used for logs,
spans, and replays explorers.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Project.transfer_to can result in some cross-org links for legacy
models.
We will clean those up, but in the meantime we should qualify lookups
using these links with organization.
For correct data, this should be a no-op, but it protects us from data
being shared between orgs if data is malformed.
…116330)

Tag filtering previously operated at the group level — if any image in a
group matched a tag, the entire group (with all its images) was
included. This meant filtering by a tag showed unrelated images, counts
didn't update, and the sidebar table of contents was inconsistent with
search behavior.

Tag filtering now narrows individual images within groups (matching how
search already works), counts update dynamically, and tags in the main
content area are clickable.

**Image-level narrowing**

`narrowItemByTags` replaces the old boolean `itemMatchesTagFilters` and
returns a new `SidebarItem` with only matching images/pairs kept,
mirroring the existing `narrowItemBySearch` pattern. A new
`tagFilteredItems` memo sits between `searchFilteredItems` and
`filteredItems` in the derivation chain, so status pill counts and
sidebar group counts all reflect the narrowed set.

**Cross-key dynamic tag counts**

`availableTags` now recomputes with cross-key awareness: selecting
`theme=dark` updates counts for other tag keys (like `area`) to reflect
only images matching `theme=dark`, while the `theme` key's own values
retain full counts so users can toggle between them. Tags that reach
count 0 render as disabled chips.

**Sidebar overflow and clickable tags**

The tag filter section's content area is capped at 200px with scroll to
prevent it from pushing the table of contents off-screen. Tags rendered
on image cards in the main content area (`CollapsibleBadgeRow`) now
accept an `onTagClick` callback, rendering as styled buttons with hover
state that toggle the corresponding sidebar filter.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
armcknight and others added 25 commits May 28, 2026 10:40
Take sentry.ratelimits and its test off the typing error ignore list.

Fixes ENG-6448
In general, but especially during our span streaming rollout, it's
useful for debugging to be able to see the underlying data for a
particular span before it is transformed by the Sentry API and frontend.
This PR adds a **superuser-only** `debug` flag on
`ProjectTraceItemDetailsEndpoint` that adds the **raw** request and
result from EAP's `TraceItemDetails` RPC into the API response's `meta`
dictionary.

Follows the established pattern from `OrganizationEventsEndpointBase`:


https://github.com/getsentry/sentry/blob/49fb05049cf9179001e3a9779e15700cd6cc6b40/src/sentry/api/bases/organization_events.py#L208

https://github.com/getsentry/sentry/blob/49fb05049cf9179001e3a9779e15700cd6cc6b40/src/sentry/api/bases/organization_events.py#L446-L448

This will be hooked up to a superuser-only button on the span details
pane in the trace waterfall, similar to how we have the link to see raw
transaction JSON for transactions (except limited to superusers) - see
#116131.

_This PR replaces the approach in
#116127

---

🤖: Claude Code (Opus 4.6) used to generate the code, with human editing
+ review. All words my own.
As mentioned by tkdodo, we don't want to setup query observers when we
don't need to, it's better to just have prefetches only when a hover
happens.

Reverts the fetch change made in
#98120

---------

Co-authored-by: Claude Opus 4.6 <noreply@example.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…16308)

Reduce metric volume by adding sentry.client_sample_rate sampling

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
This isn't used by the front end and is causing timeouts on queries for
detectors with a very large number of groups.
…work (#115887)

Snapshot tests can now specify a viewport width to test responsive
breakpoints. CSS media queries fire at the requested width, and `#root`
switches to `display: block` so percentage-based layouts fill the
viewport realistically.

**New `it.snapshot` API**

The third argument now accepts a `SnapshotOptions` object with an
optional `viewport` field. Viewport can be a named theme breakpoint
(`'sm'`, `'lg'`), a pixel number, or `{width, height}`. Breakpoint
values are derived from the theme tokens so they stay in sync
automatically. The legacy `Record<string, string>` metadata form is
still supported — existing tests are unchanged.

```tsx
it.snapshot('stacked-buttons', () => <Controls {...props} />, { viewport: 'sm' });
it.snapshot.breakpoints(['xs', 'sm', 'lg'], 'controls', () => <Controls {...props} />);
```

**Viewport-aware rendering**

When a viewport is specified, Playwright's browser context is created
with that viewport size and `#root` uses `display: block` instead of
`inline-block`. Viewport dimensions are written into snapshot metadata
JSON (`viewport_width`, `viewport_height`) for downstream consumption —
no Python changes needed since the manifest uses `extra = "allow"`.

---------

Co-authored-by: Claude Opus 4 <noreply@anthropic.com>
Co-authored-by: getsantry[bot] <66042841+getsantry[bot]@users.noreply.github.com>
For seer explorer chats, as messages come in we want to add a prefix to
the tab title counting the number of unread messages. The number only
updates when the chat is closed.

<img width="222" height="39" alt="Screenshot 2026-04-27 at 10 40 15 AM"
src="https://github.com/user-attachments/assets/8013ff3b-0616-4bdc-a359-ab4d99fca370"
/>
<img width="139" height="34" alt="Screenshot 2026-04-27 at 10 40 21 AM"
src="https://github.com/user-attachments/assets/298b6076-9f36-4f49-951b-ca56ae7c7e34"
/>
<img width="666" height="501" alt="Screenshot 2026-04-27 at 10 40 38 AM"
src="https://github.com/user-attachments/assets/f6fe371f-c22e-4451-8128-c4af50f23ec9"
/>
Replace the bespoke timer context manager with metrics.timer for the
get_snuba_map call site only, as a canary to confirm metric values are
unchanged before migrating the remaining call sites in #115279.

There are monitors on some of the other call sites in #115279 and I'd
like to not page anyone.
Change POST /projects/{org}/{project}/repo/ from PRIVATE to PUBLIC
Modernizes `IntegrationOrganizationLink` (the page that finishes a
third-party install — picking which Sentry org to attach it to) in a
handful of small, mechanical ways.

- Both remaining `useApiQuery` calls (the orgs list and the provider
config) migrate to `apiOptions.as<>()` + `useQuery`. The
conditional-fetch pattern goes from `enabled: hasSelectedOrg` +
`selectedOrgSlug!` to `path: hasSelectedOrg ? {...} : skipToken`, so the
non-null assertion disappears.
- The `AddIntegrationButton` helper is inlined into the parent and
`useAddIntegration()` is lifted alongside it. The install-click handler
is now a single `handleInstallClick` `useCallback` with an explicit
dispatch — `provider.key === 'github' && installationId` → API pipeline
modal, everything else → legacy install path.
- `finishInstallation` is renamed to `finishLegacyInstallation` with a
comment noting it bounces through `/extensions/<slug>/configure/` into
the Django-rendered `IntegrationExtensionConfigurationView`.
- Local `ButtonWrapper` and `FeatureListItem` styled components replaced
with `Flex` + `Text` primitives.
- `InstallLink` (a `<pre>` with a pink background, inside a red Alert,
semantically wrong for a URL) is replaced with `TextCopyInput` so the
admin URL gets a proper read-only field with a one-click copy button.
- Drops the now-unused `styled` and `getApiUrl` imports.

No behavior change beyond the `InstallLink` → `TextCopyInput` swap.
…tion and throwing errors (#116421)

I was having an issue with the heat maps endpoint for certain metrics.
Seems like some of these metrics have very small numbers for their
bounds and python was converting them to engineering notation (ex.
1.24e-4) when string formatting the query. We want to keep the decimal
notation because that's what the queries will correctly take in and
parse out.
Example:
<img width="300" height="200" alt="image"
src="https://github.com/user-attachments/assets/52c7e36a-247c-4a09-a68a-44b2e67ed13d"
/>

anyways to fix it i've created a function to pre-format these strings so
that they don't convert to eng notation.
…16131)

In general, but especially during our span streaming rollout, it's
useful for debugging to be able to see the underlying data for a
particular span from EAP before it is transformed by the Sentry API and
frontend. This PR adds a **superuser-only** button to the span details
pane that, when clicked, opens the trace item details JSON for the span
with the raw result from EAP's TraceItemDetails RPC included.

The button is modelled after the existing transaction JSON button,
although the use case for this one is strictly internal. Since the JSON
icon is already taken, I'm using the terminal icon to try to express
"debugging". Suggestions welcome (but this is internal, so it doesn't
matter _too_ much.)

<img width="644" height="343" alt="Screenshot 2026-05-25 at 11 33 42"
src="https://github.com/user-attachments/assets/70362123-fd0f-4fd0-b3c1-7bcbc8ccbad1"
/>

---

🤖: Claude Code (Opus 4.6) used to generate the code, with human editing
+ review. All words my own.
Even out the top and bottom padding on the active tag filter chips
section below the Tags disclosure header in the snapshot sidebar.
Previously, the top padding was removed (`paddingTop="0"`) creating an
unbalanced look. This sets equal `sm` vertical padding with `lg`
horizontal padding.

Co-authored-by: Claude <noreply@anthropic.com>
This will trigger the `process_workflow_activity` for relevant Seer
activities, noop for unrelated activities or organizations missing the
necessary flag.

The rest of the workflow engine will consume the activity just fine, but
we're still lacking the data condition to set up alerts and the fixes on
actions to support firing properly, (M2 and M3 respectively)

In practice an organization would need two flags, one for this workflow
processor, one that permits creating seer activities in the first place.

---------

Co-authored-by: Claude Opus 4 <noreply@example.com>
…#116412)

When a user installs the Sentry GitHub App directly from github.com,
GitHub redirects to `/extensions/github/setup/?setup_action=install&...`
and `PipelineAdvancerView` was bouncing them onward to the legacy
`/extensions/external-install/<provider>/<id>/` URL, which existed only
to render the React org-picker. This skips the intermediate hop and
redirects straight to the picker's real URL,
`/extensions/<slug>/link/?installationId=<id>`. The trampoline page's
fallback URL (for the rare case where the OAuth popup has no opener)
gets the same treatment.

To make this `reverse()`-able rather than a hardcoded path string, the
`/extensions/<slug>/link/` route is registered as
`sentry-integration-installation-link` (it was previously served only by
the catch-all). The now-unused `integration-installation` URL is
removed, and the matching carve-out in the integration request
classifier middleware goes with it.

The companion frontend cleanup (deleting `GitHubInstallRedirect` and its
route entry) lands in a follow-up PR.
`IntegrationOrganizationLink` was wired at two different URL shapes —
`/extensions/external-install/:integrationSlug/:installationId` for
GitHub installs initiated from github.com, and
`/extensions/:integrationSlug/link/` for everything else — and used
`useParams` to pull the GitHub `installationId` out of the path on one
of those routes. This made the component aware of two URL shapes for the
same product flow.

The companion backend change in #116412 redirects GitHub-initiated
installs straight to the `link/` route with `installationId` in the
query string, so the external-install URL no longer needs to resolve at
all. This drops the React route entry and updates the link view to read
`installationId` from the query string. The link view now only handles
one URL shape.

Depends on #116412 landing in production first.
…odal (#116429)

When a user installs the Sentry Discord app from Discord's App
Directory, Discord redirects to `/extensions/discord/configure/` with
`code` and `guild_id`. The configure URL forwards to
`/extensions/discord/link/` (the org-picker), and from there the install
needs to drive the existing API pipeline modal — there's a
Discord-specific pipeline (added in #116375) that consumes those params
and completes the install.

This wires up the frontend side of that flow.

In the org-link view (`IntegrationOrganizationLink`):

- Add a `discordAppDirectoryParams` memo that returns `{code, guild_id,
use_configure: '1'}` when `code` and `guild_id` are present in the URL
query, else null.
- Refactor `handleInstallClick` to dispatch via `gitHubAppListingParams
?? discordAppDirectoryParams` — whichever is non-null routes through
`startFlow`, otherwise we fall back to the legacy install path.
- Rename `onInstallWithInstallationId` → `onInstall` since both flows
use it now.
- Refresh the top-of-component docstring to enumerate both
provider-initiated entry points.

In the Discord pipeline step (`integrationDiscord`):

- Make `stepData` a discriminated union of the existing OAuth shape
(`{oauthUrl}`) and the new App Directory shape (`{appDirectoryInstall:
true, code, guildId, state}`).
- When the backend signals `appDirectoryInstall`, auto-advance via a
`useEffect` (guarded by a ref so React strict mode doesn't double-POST)
and render `<Text>Finishing up Discord integration
installation...</Text>` instead of the OAuth button.

Backend support landed in #116375.
…ace (#116418)

#116327 used the paginated Jira project endpoint, but we were also using
the unpaginated version in `_filter_active_projects`. Instead of
grabbing the whole list, we can search just the project ids we have set
up, also using the paginated endpoint.
…ies (with option) (#116424)

https://linear.app/getsentry/project/add-seer-actions-to-issue-activityaction-log-0e641e1f5dac/overview

Replaces the per-org `seer-activity-timeline` feature flag check with a
global `issues.record-seer-actions-as-activities` option for gating the
recording of Seer actions as issue activities in the backend, using the
Seer webhook. This PR enables recording Seer activities (RCA, solution,
coding, PR creation) for all organizations by default, while retaining
an option-based killswitch.

The existing `seer-activity-timeline` feature flag is preserved and will
be repurposed in a follow-up frontend PR to gate only the *display* of
these activities in the issue details timeline.
Use a rollout-gated, thread-local `requests.Session` for synchronous API
gateway proxy requests so the gateway can reuse HTTP connections without
sharing a session object across request-handler threads. Same as
#115827 which we saw helped
quite a bit with RPC latency, but on our api gateway cross silo
requests.

Slack Context:
https://sentry.slack.com/archives/C0B40RRUCT0/p1779391427679709

**Rollout Control**

Pooling now uses `hybridcloud.apigateway.use_pooling.rate` as a sampled
rollout rate, matching the RPC pooling rollout behavior instead of
treating any non-zero value as full enablement.

**Cookie Handling**

The pooled session uses a stateless cookie jar so backend `Set-Cookie`
headers are still returned to the client, incoming request `Cookie`
headers are still forwarded to the cell, and response cookies are not
remembered for later requests on the same thread.

---------

Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Claude <noreply@anthropic.com>
…6430)

These modules already pass strict mypy checks (disallow_any_generics,
disallow_untyped_defs, strict_equality) with zero errors, so they no
longer need to be in the relaxed override list.

Removed: `sentry.app`, `sentry.asgi`, `sentry.locks`,
`sentry.services.base`, `sentry.shared_integrations.constants`,
`sentry.spans.debug_trace_logger`, `sentry.spans.segment_key`,
`sentry.unmerge`, `sentry.wsgi`
Now that the API-driven pipeline is in place, drop the legacy
`InstallationConfigView`, `InstallationForm`, and
`GitHubEnterpriseInstallationRedirect` classes (and the
`_make_identity_pipeline_view` helper), the associated Django template,
and the legacy-flow tests. `get_pipeline_views()` now returns an empty
list; `get_pipeline_api_steps()` is the only setup path.
`build_integration` now reads identity exclusively from
`state["oauth_data"]`.

Refs
[VDY-32](https://linear.app/getsentry/issue/VDY-32/migrate-integration-setup-pipelines-to-api-driven-flows)
@pull pull Bot locked and limited conversation to collaborators May 28, 2026
@pull pull Bot added the ⤵️ pull label May 28, 2026
@pull pull Bot merged commit a9f7880 into KingDEV95:master May 28, 2026
1 check failed
@github-actions github-actions Bot added Scope: Frontend Automatically applied to PRs that change frontend components Scope: Backend Automatically applied to PRs that change backend components labels May 28, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

⤵️ pull Scope: Backend Automatically applied to PRs that change backend components Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.