[pull] master from getsentry:master#2012
Merged
Merged
Conversation
Add synonyms and alternative search terms to command palette actions based on analysis of top no-result queries from Amplitude data. Many users search for features using terms that don't match any existing action label, details, or keyword — resulting in zero results. Since the command palette uses fzf subsequence matching, the query must appear as a subsequence within a single candidate string (label, details, or keyword). Longer queries can't match shorter candidates, and space-separated terms won't match their concatenated forms. Each addition was verified against the fzf matching algorithm to confirm it's not already reachable via existing candidates: | Action | Keywords Added | Top Queries Covered | |--------|---------------|---------------------| | Create Alert | `alert rules`, `issue alert` | "alert rules", "issue alert" (~15) | | Monitors > Alerts | `alert rules`, `issue alert` | same, for workflow-engine-ui users | | DSN | `sentry dsn` | "Sentry DSN", "sentry d" (~8) | | Traces | `spans`, `trace explorer` | "spans", "Trace Explorer" (~5) | | Replays | `rum`, `session replay` | "RUM", "Session Replay" (~6) | | Releases | `release health` | "Release Health" (2) | | Profiles | `profiling` | "Profiling" (3) | | Organization Tokens | `user auth tokens` | "user auth", "User Auth Tokens" (~26) | | Personal Tokens | `user auth tokens` | same | | Close Account | `delete account` | "delete account", "delete" (~5) | | Integrations | `linear` | "linear", "Linear" (~5) | | Issue Grouping | `fingerprinting`, `fingerprint rules` | "fingerprint" (~14) | | Client Keys (DSN) | `allowed domains` | "allow", "allowed dom" (~14) | | Ownership Rules | `code owners` | "code owner" (~5) | Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…ithm (#116453) No change in behavior, just doing some minor cleanup in the logic here.
…tions as issue details activities (#116425) https://linear.app/getsentry/project/add-seer-actions-to-issue-activityaction-log-0e641e1f5dac/overview Follow-up to #116424. Renames the `seer-activity-timeline` feature flag to `display-seer-actions-as-issue-activities` to clarify that this flag only gates the *display* of Seer activities in the issue details timeline. The *recording* of these activities is controlled by the `issues.record-seer-actions-as-activities` option added in the above PR.
When `AutoSaveForm` gets back an error response that doesn't contain
field-level errors (e.g. `{detail: "Cannot override environment variable
EXAMPLE"}` instead of `{project_mappings: ["error"]}`), it currently
falls back to a generic "Failed to save" message. This PR attempts to
extract any `detail` errors before falling back.
`unsign` deserializes an arbitrary signed JSON payload, so narrowing its return to `dict[str, Any]` forced callers that know the concrete shape to cast the result. This types the return as `Any` (like `json.loads`) so callers can annotate the deserialized shape directly — e.g. a DRF serializer's `validate()` returning a `TypedDict` — without a cast.
…#116474) The `OrganizationSupergroupsByGroupEndpoint` was using inline `Group.objects.filter` calls to validate and filter group IDs. This refactors it to use the existing `get_group_list` helper from `sentry.api.helpers.group_index`, which is the canonical pattern for this kind of scoped group lookup (see `api/helpers/group_index/update.py` line 275 for the existing usage). `get_group_list` previously lived in `group_index/update.py` — a large mutation-focused module with heavy dependencies. Since the function is a pure read with minimal dependencies (`Group`, `Project`, `Sequence`), it has been extracted into a new `group_index/lookup.py`. This avoids a circular-import risk (`update.py` ← `index.py` ← `__init__.py` ← `update.py`) and gives the function a proper home as a first-class export of the package via `__init__.__all__`. `update.py` now imports `get_group_list` from `.lookup`; no behaviour change for existing callers. Test coverage for the endpoint has been expanded and `@cell_silo_test` has been added to the test class to match the endpoint's `@cell_silo_endpoint` decorator. Refs AIML-2879
…6469) Night-shift was the only autofix invoker that forwarded an explicit `intelligence_level` and `reasoning_effort` (both `"high"`) to `trigger_autofix_agent`. Every other invoker — the group autofix endpoint, the issue-summary auto-trigger, the on-completion pipeline, and Slack — relies on the defaults: `intelligence_level="medium"` and the per-step `reasoning_effort` from the step config. This drops the explicit arguments from the night-shift autofix call so its runs use the same model as all other invokers. The night-shift triage step still honors the configured `intelligence_level` and `reasoning_effort` options; only the autofix invocation changes. Agent transcript: https://claudescope.sentry.dev/share/p8XAfGYOrDo-lObjRdup6LquAGyi4CNn3M0hGLD_HDo
…projects/ (#116388) <!-- Describe your PR here. --> Backend PR #116333 promoted `POST /organizations/{org}/experimental/projects/` to `POST /organizations/{org}/projects/` (PUBLIC). That PR keeps the old `/experimental/` path alive as a backward-compat alias so the frontend doesn't break between deploys. This PR drops the `/experimental/` path from the two hooks that call it and updates the test mocks and generated URL registry to match. **Changed hooks:** - `useCreateProject` — used by the main onboarding flow and the create-project settings page - `useCreateProjectFromWizard` — used by the setup wizard **Also adds** a unit test for `useCreateProject` that explicitly asserts the URL routing logic (no team slug → org endpoint, team slug present → teams endpoint). That coverage didn't exist before. Depends on #116333. ### 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.
…6490) [VDY-101: Microsoft Teams: API-driven integration setup](https://linear.app/getsentry/issue/VDY-101/microsoft-teams-api-driven-integration-setup) Adds the API-mode pipeline machinery for Microsoft Teams alongside the existing server-rendered configure flow, without changing the entry point yet. This is the first of three deploy-safe steps: the legacy `MsTeamsExtensionConfigurationView` and the `/extensions/msteams/configure/` URL are left untouched, so nothing changes for users until the frontend can drive the modal and the configure URL is later swapped to a redirect. - `MsTeamsInitialDataSerializer` unsigns the bot's `signed_params` blob and binds each field to top-level pipeline state. - `MsTeamsApiStep` has no interactive UI; it signals the frontend to auto-advance, which runs `build_integration` on the bound state. - `build_integration` now reads top-level state, falling back to the nested `state["msteams"]` the legacy view binds, so both flows work during the transition. Also adds a `can_add_externally` marker to `IntegrationProvider` for integrations whose install is initiated from the third party's app directory or marketplace and completed through the pipeline modal. MS Teams sets `can_add = False` to hide the in-app install button, so the pipeline endpoint needs this opt-in to allow the externally-initiated install. The other already-external providers (Discord, GitHub, and GitHub Enterprise via subclassing) are marked for consistency; it's a no-op for them since they're `can_add = True`. Note: mypy will be red until #116486 (typing `utils.signing.unsign` as `Any`) merges, since the serializer's `validate()` returns a `TypedDict` from `unsign()`. The frontend follow-up is #116488.
Seems to be an issue with nuqs on the initial tab change doing a fairly hefty page reload. To resolve this issue, we need to make the change "shallow". Closes JAVASCRIPT-3A1R --------- Co-authored-by: Codex <noreply@openai.com>
…nd auto_create_pr fields (#116352) Consolidate `update_seer_project_settings` and `bulk_update_seer_project_settings` into a single function that bulk deletes/creates project options across 1+ project ids. Also, strip seat-based business logic (stopping point → auto_create_pr syncing, tuning validation) out of the update helper and add tuning and auto_create_pr as update fields, so it becomes a pure write layer and can be used by other callsites. Followups: #116356, #115962 #### Why: By moving business logic out, other callsites can do updates without hidden side effects. - Independent auto_create_pr and tuning updates are needed by legacy seer and will be used when we add legacy seer to the project settings endpoints: #115962 - #116356 reroutes existing callsites that modify seer project settings (`_write_preferences_to_sentry_db`, `configure_seer_for_existing_org`, `set_default_project_seer_preferences`) to the update helper to ensure that handoff options are either cleared or added atomically AND to skip unnecessary connected repo operations. It also removes `Project` row locks and simplifies `clear_preference_automation_handoff`. #### Other cleanups: - `SeerProjectSettingsUpdate` uses snake_case keys via `CamelSnakeSerializer`. - Add tuning to the project settings endpoints serializers (as opposed to consolidating tuning="off" into stopping_point="off"), again to make it easier to support legacy seer. - Endpoint returns `autoCreatePr` and `automationTuning` in response. - Stopping point syncs `auto_create_pr` automatically.
#116342) ## Summary Move the loading indicator from dropdown trigger to the dropdown list. This is exactly how the other search bars handle it (for example searching in the explore search bar). This resolves two issues: 1. Having the spinner in the trigger causes the trigger to change widths when it goes from not-loading -> loading, this results in some annoying shifting (See [DAIN-1636](https://linear.app/getsentry/issue/DAIN-1636) for video) 2. Having the trigger on the dropdown list more accurately reflects the state, the list of options are loading. Before it looked like the selected item is being changed. ### Before <img width="442" height="185" alt="image" src="https://github.com/user-attachments/assets/e9fbe4c6-cdcc-405e-b114-47d03f24c6cf" /> ### After <img width="449" height="591" alt="image" src="https://github.com/user-attachments/assets/0533bdb9-7239-4fb1-9a64-4eee0b497219" /> Refs DAIN-1636 --------- Co-authored-by: Claude <noreply@anthropic.com>
…xed (#116476) Make Night Shift more conservative about which issues it autofixes. The triage agent assigns each candidate issue one of three verdicts: - **`autofix`** → runs a full Seer autofix to the project's stopping point (can open a code-change PR, with no human consulted before the fix is written) - **`root_cause_only`** → root-cause analysis only; a human decides what to do - **`skip`** → nothing This PR tightens the `autofix` decision so we only ship code changes for issues we're convinced can be fixed correctly without human involvement. Anything less now falls back to `root_cause_only` — investigation is still valuable, but a human stays in the loop. ## Changes **Stricter triage prompt** (`agentic_triage.py`) - Frames the verdicts as a "ladder of increasing caution" — default to the least aggressive verdict; when torn, pick the more conservative one. - Gates `autofix` behind a hard ALL-of checklist: exact root cause confirmed by reading code, exactly one clearly-correct fix, small/localized change, can't change intended behavior or need human judgment, not in a high-blast-radius area (auth, billing, security, concurrency, migrations…), and shippable without a human reviewing the approach. - Makes `root_cause_only` the explicit default for anything fixable that doesn't clear the bar. - Notes that a high fixability score alone is **not** a reason to autofix. Agent transcript: https://claudescope.sentry.dev/share/yiuFYRbvXKCU5YRlGYCutt_oRvbpmMBZoVfko81-1Xo
Now that the API-driven pipeline is in place, drop the legacy `InstallationConfigView`, `OAuthLoginView`, and `OAuthCallbackView` classes (and the `InstallationForm` they used), 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. Fixes [VDY-103](https://linear.app/getsentry/issue/VDY-103/remove-legacy-bitbucket-server-integration-setup-views)
## Summary - Skip 3 tests in `test_project_trace_item_details.py` that are broken as of 05-29-2026 - `test_convert_rpc_attribute_to_json_serializes_known_string_array_without_array_flag` - `test_convert_rpc_attribute_to_json_exposes_array_with_array_flag` - `TestReplacementAttributeFiltering::test_replacement_array_shown_when_no_deprecated_source` ## Test plan - CI should pass with these tests skipped Will continue root causing and follow up with the relevant parties to ensure the real cause is addressed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nter (#116496) Extend the structural linter at `src/sentry/apidocs/_check_response_annotation_matches_schema.py` to support union return annotations and compare against decorator response entries at every status code (not just 2xx). This unblocks endpoints that want to type both their success and error response bodies — `-> Response[FooResponse] | Response[ErrorBody]` with corresponding decorator entries — and removes the artificial 2xx restriction from before. ## What changed | Aspect | Before | After | |---|---|---| | Annotation forms | `Response[T]` only | `Response[T]` and `Response[T_a] \| Response[T_b] \| ...` | | Decorator status range | 2xx entries only | All status codes | | Decorator shape recognized | `inline_sentry_response_serializer("Name", T)` | unchanged | | Comparison | T-name equality (single) | Set equality on raw T names | | Name handling | Verbatim | Verbatim (no normalization, no convention pairing) | ## What is intentionally still skipped (no diagnostic, no false positive) - Plain `-> Response` annotations (the unmigrated state). - Methods with no `@extend_schema` decorator. - Decorator entries that aren't `inline_sentry_response_serializer(...)`. This includes: - Direct serializer-class references like `MonitorSerializer` — these carry a typed output by sentry convention but no statically-resolvable link to a `TypedDict`. The right path for these is either migrating the entry to `inline_sentry_response_serializer(...)`, or waiting for a generic-`Serializer[T]` refactor where the linter can read the parameter directly from the class. - `OpenApiResponse(...)` wrappers. - `RESPONSE_*` canned constants (error documentation, no body type). - `None`, raw `dict`, etc. - Union arms that aren't `Response[T]` (e.g. `Response[T] | HttpResponse`). In all those cases the linter exits clean — it neither false-positives nor gives a misleading guess. ## Status-code-to-T linkage is intentionally not enforced mypy can't model the link (the status code is runtime data), and broad `except APIException` patterns would lose it anyway. Endpoints needing strict status↔T guarantees should `raise <APIException>(...)` for error paths so the success-path return is uniquely typed. ## Worked examples **Single T (unchanged from prior behavior):** ```python @extend_schema(responses={200: inline_sentry_response_serializer("Foo", FooResponse)}) def get(...) -> Response[FooResponse]: ... # pass: decorator set {FooResponse} == annotation set {FooResponse} ``` **Union with success + typed error:** ```python @extend_schema( responses={ 200: inline_sentry_response_serializer("Foo", FooResponse), 400: inline_sentry_response_serializer("Err", ErrorBody), }, ) def get(...) -> Response[FooResponse] | Response[ErrorBody]: ... # pass: sets {FooResponse, ErrorBody} match ``` **Drift — annotation missing a decorator-declared T:** ```python @extend_schema( responses={ 200: inline_sentry_response_serializer("Foo", FooResponse), 400: inline_sentry_response_serializer("Err", ErrorBody), }, ) def get(...) -> Response[FooResponse]: ... # fail: decorator {FooResponse, ErrorBody} != annotation {FooResponse} ``` ## Tests 16 cases in `tests/sentry/apidocs/test_check_response_annotation_matches_schema.py`: - Single-T match / mismatch - Union annotation matching multi-status decorator (both arms typed) - Annotation missing a decorator-declared T (set inequality) - Annotation containing extra T not in decorator (set inequality) - Multiple 2xx schemas (200 + 201) matched by union - Unmigrated `-> Response` skipped - Method without `@extend_schema` skipped - `RESPONSE_*` canned constant skipped - Direct serializer-class reference skipped (waiting on generic Serializer[T]) - `OpenApiResponse(...)` wrapper skipped - Union arm that isn't `Response[T]` skipped - Async methods - Dotted annotation form (`rest_framework.response.Response[T]`) - `main()` exit codes (zero on clean, nonzero on mismatch) Full src/sentry run: clean. The 43 endpoints already opted into `Response[T]` (#116335, #116433) continue to pass. ## Follow-up paths (out of scope for this PR) A survey of all 862 `responses={N: ...}` entries in `src/sentry` showed that ~97 use direct serializer-class references (about as common as `inline_sentry_response_serializer`). The linter doesn't help these endpoints today. Two ways to bring them into coverage later: - **Migrate** each to `inline_sentry_response_serializer("Name", FooResponse)` with an explicit paired TypedDict. - **Make sentry's `Serializer` generic** in its output type (`Serializer[T]`), so the linter can extract T directly from the class's bases. This eliminates the need for any naming convention. Either path gives the linter a real handle. This PR doesn't attempt to bridge it with name heuristics — those were considered and rejected as brittle. Co-authored-by: Claude <noreply@anthropic.com>
Remove codecov-integration feature from the Settings page
…rd-migration` (#116450) Remove `organizations:insights-ai-and-mcp-dashboard-migration`. This flag has 0 usages across code, frontend, and tests (dead for 78 days, first seen dead 2026-03-12). Not present in sentry-options-automator. --- _Generated by [Claude Code](https://claude.ai/code/session_01RNki2RgdHF3ZuroLVpupeQ)_ Co-authored-by: Claude <noreply@anthropic.com>
) Currently v1 (transaction-based) spans send user attributes in `sentry.user.*` attributes, while v2 (streaming) spans send user attributes in conventions-defined `user.*` attributes. Only the v1 attributes are currently propagated, meaning that child spans from span streaming SDKs are missing user info. We can use our conventions' deprecation mechanism (getsentry/sentry-conventions#406) to make queries backwards compatible, but that doesn't affect segment enrichment which reads data directly from spans. For now, propagate both the old v1 user attributes and the new v2 user attributes to children. Once that's done, EAP's attribute coalescing (via above deprecation PR) will take care of the rest. Next steps will be to clean up our use of the v1 `sentry.user.*` attributes in Relay and Sentry, at which point we can stop propagating them. (That work is tracked in BROWSE-535). Fixes BROWSE-532. --- 🤖: Claude Code (Opus 4.6) used to generate the tests. I made the code changes and reviewed the tests. Words my own.
…ndpoint (#115962) Depends on #116352 and #116356. Add legacy usage-based Seer support to the project settings endpoints by branching on `is_seer_seat_based_tier_enabled`. **Serializer split:** - Extract `_BaseProjectSettingsUpdateSerializer` with shared validation (agent, integration_id, cross-field checks) - `ProjectSettingsUpdateSerializer` (seat-based): restricted tuning choices (off/medium), stopping_point validation via `get_valid_automated_run_stopping_points`, auto_create_pr synced from stopping_point - `LegacyProjectSettingsUpdateSerializer` (usage-based): accepts all tuning values, direct `auto_create_pr` field, no stopping_point restrictions ### Example payloads **Set tuning to a granular value:** ```json PUT /api/0/projects/{org}/{project}/seer/settings/ {"automationTuning": "high"} ``` **Set stopping point (frontend sends agent=seer to clear any external handoff):** ```json PUT /api/0/projects/{org}/{project}/seer/settings/ {"stoppingPoint": "code_changes", "agent": "seer"} ``` This clears handoff keys (target, point, integration_id) but preserves `auto_create_pr` so switching back to an external agent restores the previous toggle value. **Switch to external agent with auto_create_pr:** ```json PUT /api/0/projects/{org}/{project}/seer/settings/ {"agent": "cursor_background_agent", "integrationId": 1, "autoCreatePr": true} ``` **Toggle auto_create_pr on an existing external agent:** ```json PUT /api/0/projects/{org}/{project}/seer/settings/ {"autoCreatePr": false} ``` **Turn off automation:** ```json PUT /api/0/projects/{org}/{project}/seer/settings/ {"automationTuning": "off"} ``` GET response will show `stoppingPoint: "off"`, but the stored stopping point is unchanged — re-enabling restores it.
this removes 93 unused options identified via tracking read options via logging in #115610 (which this PR also reverts as I'm done collecting data) cross referenced with static analysis in getsentry/sentry-options#123 the details are in getsentry/sentry-options#123 - `scripts/migration/safe.txt` is essentially the set intersection of statically unreferenced options and unseen/unread options over 120 hours of GCP production logs. the unseen list was determined by subtracting options.seen unique events from all known options (options.all()) and I observed no newly seen options beyond the ~100 hour mark (`scripts/migration/collect-seen-options-out.txt`). getsentry options that were unused are removed here too: getsentry/getsentry#20449
Discover was still routing issue event id clicks through the project-event redirect, even when the row already had `issue.id`. That made some issue-event urls messy and left the redirect to clean things up later. This requests `issue.id` with the hidden link context and builds the issue event url directly. Keeps the old project redirect fallback for rows that do not have issue context.
…116427) Adds an optional `all_image_file_names_as_regex` field to the snapshot upload endpoint. It works like the existing `all_image_file_names`, except each entry is a regex pattern (matched with `fullmatch`) rather than a literal file name. This lets callers declare the head build's complete image set with a handful of patterns instead of an exhaustive list — useful for selective uploads, where only changed images are sent but the full set is needed downstream to tell `removed` images apart from `skipped` ones. The two fields are mutually exclusive and both require `selective`. Every uploaded image name must be covered by the declared set (appear in the list, or match at least one pattern), preserving the existing invariant. `fullmatch` (not `search`) is used because the literal field uses exact full-string equality, and full-match is its faithful regex analog. Renames still work: rename detection runs after the removed/skipped partitioning by matching content hashes across `added`/`removed`/`skipped`, and that shared logic is unchanged. ### New dependency: `google-re2` Patterns are **client-supplied**, so they cannot be matched with a backtracking engine (stdlib `re` or the `regex` lib) without exposing a ReDoS vector — a pathological pattern can hang a worker. This PR matches them with **RE2** ([`google-re2`](https://github.com/google/re2)), a linear-time, finite-automaton engine: - **Catastrophic backtracking is impossible by construction** — no time budget or timeout needed. - **Unsupported constructs (backreferences, lookaround) are rejected at compile time** (`re2.error`), so the engine enforces the safe subset. These make no sense for filename patterns anyway. Compiling a pattern *is* the validation (invalid/unsupported → 400), and the same compiled object does the matching. Pattern length (500 chars) and count (100) caps remain as sanity bounds. Reviewed with security; RE2's linear-time guarantee is the agreed approach over a wall-clock-timeout mitigation. `google-re2` was added to the internal PyPI mirror in getsentry/pypi#2192 (merged). It ships prebuilt wheels for all our targets and has no new transitive dependencies. ### Refactor included To avoid a third parallel code path, the literal and regex modes are unified behind a single `SnapshotManifest.head_image_name_matcher()` consumed by `categorize_image_diff`, and the endpoint's coverage checks are consolidated into one helper (`make_image_name_matcher`). Behavior-preserving. A `root_validator` on `SnapshotManifest` enforces the mutual-exclusion invariant at the model level. Co-authored-by: Claude <noreply@anthropic.com>
Wire GitLab merge requests into Seer code review. This uses the old web
hook handler format rather than the new event listeners format. I
struggled too much with the listeners. I'd rather ship the old system
than deal with it. It can be ported later if/when the new system is at
parity.
# Slop
What changed:
- Processor architecture on GitlabWebhook — adds a
`WEBHOOK_EVENT_PROCESSORS` tuple + shared `_handle` loop (with
`EVENT_TYPE` enforcement) so multiple handlers can run per event. PR
persistence stays inline in `MergeEventWebhook.__call__`; only the
code-review handler runs in the (error-isolated) processor loop.
- New handle_merge_request_event handler
(seer/code_review/webhooks/merge_request.py) — runs preflight checks,
maps GitLab actions to triggers, and enqueues the review:
- open / un-drafted update → ON_READY_FOR_REVIEW; update with new
commits → ON_NEW_COMMIT; close / merge → PR-closed. Everything else
(metadata-only edits, drafts unsupported actions) is filtered.
- GitLab has no ready_for_review action, so un-drafting is detected from
the changes payload.
- De-dupes redeliveries (and the per-org dispatch fan-out) via a short
Redis TTL key.
- Routes to the provider-agnostic
/v1/scm_code_review/{review-request,pr-closed} Seer endpoints (GitLab
isn't supported by the PyGithub-based /v1/code_review/* routes).
- Provider-aware repo definitions (seer/code_review/utils.py) — split
GitHub/GitLab builders. GitLab derives owner/name from config["path"]
(not the display name) and is_private from project.visibility_level.
- Metrics generalized to accept string event names so the funnel metrics
work for merge_request.
Known limitation
Code review won't fire in production until GitLab
OrganizationContributors are seeded — the billing preflight currently
filters every MR with ORG_CONTRIBUTOR_NOT_FOUND (GitHub seeds these via
track_contributor_seat; GitLab doesn't yet). Documented in the module
docstring.
Update the dsyms endpoint to use the modern DRF-spec system.
for components that are not specifically owned by a team further down in the codeowners, fallback to the issue-workflow team.
…ne modal (#116488) [VDY-101: Microsoft Teams: API-driven integration setup](https://linear.app/getsentry/issue/VDY-101/microsoft-teams-api-driven-integration-setup) When a user installs the Sentry app from the Microsoft Teams Marketplace, the Sentry bot posts a card linking to `/extensions/msteams/configure/` with a signed `signed_params` blob. That forwards to `/extensions/msteams/link/` (the org picker), and from there the install needs to drive the API pipeline modal. This wires up the frontend side: - Adds `msTeamsParams` in the org-link view, returning `{signedParams}` when `signed_params` is present in the URL query, and routes `handleInstallClick` through it via the existing `gitHubAppListingParams ?? discordAppDirectoryParams ?? msTeamsParams` chain. - Adds the `integrationMsTeams` pipeline definition. Its single step has no interactive UI; all install data arrives already bound to pipeline state, so it auto-advances when the backend returns `appDirectoryInstall`, rendering a brief "Finishing up..." message (guarded by a ref against React strict-mode double-fire). - Registers the pipeline and adds `msteams` to `UNCONDITIONAL_API_PIPELINE_PROVIDERS`. Depends on the backend support (separate PR) and must not deploy before it: the modal calls the API pipeline `initialize` endpoint for `msteams`, which only works once the backend serializer / step / `can_add_externally` changes are live. The `/extensions/msteams/configure/` URL still routes through the legacy server-rendered view until a follow-up swaps it to a redirect.
…#116511) Guard against `None` entries in `exception.values` when extracting exception data for the eventstream/EAP pipeline. Some events have `None` entries in their `exception.values` list. When `_extract_exception` iterates over this list, it calls `.get("type")` on `None`, causing `AttributeError: 'NoneType' object has no attribute 'get'`. The fix filters `None` entries out of the exceptions list before iteration rather than skipping inside the loop. This keeps `exception_count`, `stack_level` indices, and the parallel `stack_*` arrays consistent. Also adds `or []` to handle the case where `"values"` is explicitly `None`. Fixes SENTRY-FOR-SENTRY-2T8
When creating autofix PRs, make sure to link the linear ticket so it'll be closed too.
Co-Authored-By: george-sentry <249834052+george-sentry@users.noreply.github.com> Co-authored-by: getsentry-bot <10587625+getsentry-bot@users.noreply.github.com> Co-authored-by: george-sentry <249834052+george-sentry@users.noreply.github.com>
…t need to update the full Seer project preference (#116356) Followup to #116352. Reroute existing callsites that modify seer project settings (`_write_preferences_to_sentry_db`, `configure_seer_for_existing_org`, `set_default_project_seer_preferences`) to the unified `update_seer_project_settings` helper. This ensures handoff options are cleared/added atomically and skips unnecessary connected repo operations. Also remove `Project` row locks from `_write_preferences_to_sentry_db` and `clear_preference_automation_handoff` — no longer needed since handoff options are all either cleared or added atomically, and the other update fields may be updated independently of each other.
We had duplicate definitions of 'Author' across releases. Consolidate them to the type `UserSerializerResponse | NonMappableUser`. Co-authored-by: Claude <noreply@anthropic.com>
Remove `organizations:seer-issue-view`. This flag has zero usage and is not registered in sentry-options-automator. --- _Generated by [Claude Code](https://claude.ai/code/session_01KC1dc6Scf5gtgkusF5v6Ui)_
We're planning to add search filters which will allow users to query issues by the activity types contained within them (e.g. an upcoming `issue.agent:pr_created` filter which filters to issues with the activity `SEER_PR_CREATED`). Those queries filter `sentry_activity` on `project_id` plus `type`, which results in a very slow and inefficient query without this index. This is a huge table (>1B rows), so it is a post deployment migration. In addition to the new index, this also removes an unused one (`sentry_activity_weekly_report_jtcunning`) to clear some room.
…le (#116515) Add types and example for the event attachments endpoint, in preparation for publishing it. Co-authored-by: Claude <noreply@anthropic.com>
The old issue details guide was still wired into anchors that no longer exist, while the current tour had no launcher when the backend marked it unseen. Removes the stale guide and anchor wrappers, keeps the existing tour, and lazy-loads the start tour modal when we should show it. Brings back the tour, can be manually triggered `#issue-details-tour` on the issue details page <img width="507" height="459" alt="image" src="https://github.com/user-attachments/assets/12a41ac3-98c8-42a0-bcf5-6349b5c22d41" />
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 : )