Skip to content

Conversation

@ceorourke
Copy link
Member

@ceorourke ceorourke commented Nov 20, 2025

Fixes adding and updating sentry app actions on a workflow and requires settings to be passed for a sentry app action if it has a UI component. If it has no component, settings does not need to be passed.

Adds support for a target_type of either sentry_app_id or sentry_app_installation_uuid until we can migrate the data to only have sentry_app_id.

Add tests for adding and updating sentry app actions.

Fixes https://sentry.sentry.io/issues/6980690322

@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Nov 20, 2025
@codecov
Copy link

codecov bot commented Nov 20, 2025

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
30050 1 30049 241
View the top 1 failed test(s) by shortest run time
tests.sentry.core.endpoints.test_organization_index.OrganizationsCreateTest::test_valid_slugs
Stack Traces | 1.62s run time
#x1B[1m#x1B[.../core/endpoints/test_organization_index.py#x1B[0m:190: in test_valid_slugs
    response = self.get_success_response(name=input_slug, slug=input_slug)
#x1B[1m#x1B[.../sentry/testutils/cases.py#x1B[0m:628: in get_success_response
    assert_status_code(response, 200, 300)
#x1B[1m#x1B[.../sentry/testutils/asserts.py#x1B[0m:47: in assert_status_code
    assert minimum <= response.status_code < maximum, (
#x1B[1m#x1B[31mE   AssertionError: (500, b'{"detail":"Internal Error","errorId":null}')#x1B[0m
#x1B[1m#x1B[31mE   assert 500 < 300#x1B[0m
#x1B[1m#x1B[31mE    +  where 500 = <Response status_code=500, "application/json">.status_code#x1B[0m

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

Comment on lines +160 to +184
"sentryAppIdentifier": SentryAppIdentifier.SENTRY_APP_INSTALLATION_UUID,
"targetIdentifier": self.sentry_app_installation.uuid,
"targetType": ActionType.SENTRY_APP,
Copy link
Member Author

Choose a reason for hiding this comment

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

@ameliahsu I was only able to get this test to pass if I used this data which differs from what was passed in https://sentry.sentry.io/issues/6980690322 which was

{
    "sentry_app_identifier":"'sentry_app_id'",
    "target_identifier":"'72013'",
    "target_type":"'sentry_app'"
}

Do you know if the data in the Sentry issue is what's expected to be passed all the time or only sometimes? I'm not sure when we pass one versus the other, but if we set sentryAppIdentifier to "sentry_app" instead of "sentry_app_installation" (SentryAppIdentifier.SENTRY_APP_INSTALLATION_UUID) we go down a slightly different code path and set sentryAppInstallationUuid to None (code here) which leads to a SentryAppInstallation.DoesNotExist error (here).

I truly don't know if this is a bug or how it's intended to work, but it doesn't currently work if you do not pass the installation data. I did verify that even an internal unpublished sentry app has an installation object, so maybe it's intended for us to always pass that data?

Copy link
Member

Choose a reason for hiding this comment

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

@GabeVillalobos might be able to help here, i believe some existing app actions use the sentry app UUID instead of the sentry app ID, which is why we have to specify sentry_app_identifier? but we would like for all newly created actions going forward to use sentry app ID. not sure if that's why we throw an error tho 😅

Copy link
Member Author

Choose a reason for hiding this comment

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

Short answer here is that sentry_app_installation is some legacy data we need to migrate away from and the front end will be passing sentry_app_id for new actions. I updated the code to support both until we can run the migration so that old action with the uuid can be updated.

Comment on lines 246 to 249
if settings:
try:
# Only call creator for Sentry Apps with UI Components (settings) for actions
Copy link
Member Author

Choose a reason for hiding this comment

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

I copied this logic from how we do it today - in project_rule_details.py and project_rules.py we call trigger_sentry_app_action_creators_for_issues (here) which skips over the validation if there is no UI component

except SentryAppInstallation.DoesNotExist:
return None

def get_installation_by_uuid(
Copy link
Member Author

Choose a reason for hiding this comment

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

We only need this temporarily until we can migrate the action data to not have the installation uuid

@ceorourke ceorourke requested review from a team as code owners November 25, 2025 19:29
Copy link
Member

@cathteng cathteng left a comment

Choose a reason for hiding this comment

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

Generally looks good

Comment on lines 223 to 224
installation = app_service.get_installation_by_sentry_app_id(
sentry_app_id=int(target_identifier), organization_id=self.organization.id
Copy link
Member

@cathteng cathteng Nov 25, 2025

Choose a reason for hiding this comment

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

Adding a new RPC function will need to be deployed in a separate PR from the PR where you use it

return self.validated_data
except SentryAppBaseError as e:
raise ValidationError(e.message) from e
return self.validated_data
Copy link
Member

Choose a reason for hiding this comment

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

Should we be updating the validated data here to only save sentry app actions with sentry_app_identifier = "sentry_app_id"?

Copy link
Member Author

Choose a reason for hiding this comment

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

We have actions with the uuid saved in the db today so we don't want to block being able to update those. After we run the migration maybe part of the cleanup can be enforcing only that identifier.

Copy link
Member

Choose a reason for hiding this comment

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

If somebody is trying to update an action with a uuid we could update that action to save it with the sentry app id so we don't have any more actions being saved with uuid

Copy link
Member Author

Choose a reason for hiding this comment

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

updated 👍

Comment on lines +216 to +217
installations = None
installation = None
Copy link
Member

Choose a reason for hiding this comment

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

Is typing gonna complain this needs to be RpcSentryAppInstallation | None = None?

)
else:
installations = app_service.get_many(
filter=dict(app_ids=[int(target_identifier)], organization_id=self.organization.id)

This comment was marked as outdated.

Copy link
Member Author

Choose a reason for hiding this comment

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

good thing it is a number

)
else:
installations = app_service.get_many(
filter=dict(app_ids=[int(target_identifier)], organization_id=self.organization.id)
Copy link
Contributor

Choose a reason for hiding this comment

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

Bug: Unhandled ValueError when converting target identifier to int

When sentry_app_identifier is SENTRY_APP_ID, the code converts target_identifier to an integer without error handling. If a user passes a non-numeric string (like a UUID) as the target_identifier, this will raise an unhandled ValueError instead of returning a proper validation error, causing a 500 error rather than a user-friendly 400 validation error.

Fix in Cursor Fix in Web

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.

4 participants