Skip to content

ref(scm): Implement sentry-scm dependency#112969

Merged
cmanallen merged 22 commits intomasterfrom
cmanallen/implement-scm-platform
Apr 15, 2026
Merged

ref(scm): Implement sentry-scm dependency#112969
cmanallen merged 22 commits intomasterfrom
cmanallen/implement-scm-platform

Conversation

@cmanallen
Copy link
Copy Markdown
Member

@cmanallen cmanallen commented Apr 14, 2026

Replaces sentry/scm implementation with a new sentry-scm dependency. sentry-scm replicates the behavior of sentry/scm but moves it to a third-party package so that it may be distributed to multiple services.

There is a minor refactor contained in here. It was a simplification of some overly complex behaviors and a reduction in the SourceCodeManager class's instantiation capabilities. Previously we allowed initialization from an integration instance. However, this goes against one of the goals of the SCM which is to enforce access-controls. For now its been removed. This optimization can be added later if necessary.

@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Apr 14, 2026
@github-actions github-actions bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Apr 14, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🚨 Warning: This pull request contains Frontend and Backend changes!

It's discouraged to make changes to Sentry's Frontend and Backend in a single pull request. The Frontend and Backend are not atomically deployed. If the changes are interdependent of each other, they must be separated into two pull requests and be made forward or backwards compatible, such that the Backend or Frontend can be safely deployed independently.

Have questions? Please ask in the #discuss-dev-infra channel.

@sentry
Copy link
Copy Markdown
Contributor

sentry bot commented Apr 14, 2026

Sentry Snapshot Testing

Name Added Removed Modified Renamed Unchanged Status
sentry-frontend
sentry-frontend
0 0 0 0 204 ✅ Unchanged

⚙️ sentry-frontend Snapshot Settings

Comment thread src/sentry/scm/private/helpers.py Outdated
Comment thread src/sentry/scm/private/helpers.py Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 14, 2026

Backend Test Failures

Failures on b0c0f35 in this run:

tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_end_to_endlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
.venv/lib/python3.13/site-packages/scm/rpc/client.py:79: in fetch_repository
    resp = msgspec.json.decode(response.content, type=ErrorResponse)
E   msgspec.ValidationError: Object missing required field `errors`

The above exception was the direct cause of the following exception:
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:81: in fetch_repository
    raise SCMCodedError(code="rpc_errors_could_not_be_deserialized") from e
E   scm.errors.SCMCodedError: ('rpc_errors_could_not_be_deserialized', 'The error response could not be deserialized.')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_get_missing_authlog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
.venv/lib/python3.13/site-packages/scm/rpc/client.py:79: in fetch_repository
    resp = msgspec.json.decode(response.content, type=ErrorResponse)
E   msgspec.ValidationError: Object missing required field `errors`

The above exception was the direct cause of the following exception:
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:81: in fetch_repository
    raise SCMCodedError(code="rpc_errors_could_not_be_deserialized") from e
E   scm.errors.SCMCodedError: ('rpc_errors_could_not_be_deserialized', 'The error response could not be deserialized.')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_getlog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
.venv/lib/python3.13/site-packages/scm/rpc/client.py:79: in fetch_repository
    resp = msgspec.json.decode(response.content, type=ErrorResponse)
E   msgspec.ValidationError: Object missing required field `errors`

The above exception was the direct cause of the following exception:
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:81: in fetch_repository
    raise SCMCodedError(code="rpc_errors_could_not_be_deserialized") from e
E   scm.errors.SCMCodedError: ('rpc_errors_could_not_be_deserialized', 'The error response could not be deserialized.')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_get_invalid_headerslog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
.venv/lib/python3.13/site-packages/scm/rpc/client.py:79: in fetch_repository
    resp = msgspec.json.decode(response.content, type=ErrorResponse)
E   msgspec.ValidationError: Object missing required field `errors`

The above exception was the direct cause of the following exception:
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:81: in fetch_repository
    raise SCMCodedError(code="rpc_errors_could_not_be_deserialized") from e
E   scm.errors.SCMCodedError: ('rpc_errors_could_not_be_deserialized', 'The error response could not be deserialized.')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_post_invalid_secretlog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
.venv/lib/python3.13/site-packages/scm/rpc/client.py:79: in fetch_repository
    resp = msgspec.json.decode(response.content, type=ErrorResponse)
E   msgspec.ValidationError: Object missing required field `errors`

The above exception was the direct cause of the following exception:
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:81: in fetch_repository
    raise SCMCodedError(code="rpc_errors_could_not_be_deserialized") from e
E   scm.errors.SCMCodedError: ('rpc_errors_could_not_be_deserialized', 'The error response could not be deserialized.')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_post_invalid_headerslog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
.venv/lib/python3.13/site-packages/scm/rpc/client.py:79: in fetch_repository
    resp = msgspec.json.decode(response.content, type=ErrorResponse)
E   msgspec.ValidationError: Object missing required field `errors`

The above exception was the direct cause of the following exception:
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:81: in fetch_repository
    raise SCMCodedError(code="rpc_errors_could_not_be_deserialized") from e
E   scm.errors.SCMCodedError: ('rpc_errors_could_not_be_deserialized', 'The error response could not be deserialized.')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_get_invalid_secretlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
.venv/lib/python3.13/site-packages/scm/rpc/client.py:79: in fetch_repository
    resp = msgspec.json.decode(response.content, type=ErrorResponse)
E   msgspec.ValidationError: Object missing required field `errors`

The above exception was the direct cause of the following exception:
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:81: in fetch_repository
    raise SCMCodedError(code="rpc_errors_could_not_be_deserialized") from e
E   scm.errors.SCMCodedError: ('rpc_errors_could_not_be_deserialized', 'The error response could not be deserialized.')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_post_missing_authlog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
.venv/lib/python3.13/site-packages/scm/rpc/client.py:79: in fetch_repository
    resp = msgspec.json.decode(response.content, type=ErrorResponse)
E   msgspec.ValidationError: Object missing required field `errors`

The above exception was the direct cause of the following exception:
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:81: in fetch_repository
    raise SCMCodedError(code="rpc_errors_could_not_be_deserialized") from e
E   scm.errors.SCMCodedError: ('rpc_errors_could_not_be_deserialized', 'The error response could not be deserialized.')

Comment thread src/sentry/scm/endpoints/scm_rpc.py Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 14, 2026

Backend Test Failures

Failures on 1e2ede9 in this run:

tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_get_invalid_secretlog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:86: in fetch_repository
    raise exceptions[0]
E   scm.errors.SCMCodedError: ('rpc_invalid_grant', 'Invalid grant')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_get_missing_authlog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:86: in fetch_repository
    raise exceptions[0]
E   scm.errors.SCMCodedError: ('rpc_invalid_grant', 'Invalid grant')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_get_invalid_headerslog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:86: in fetch_repository
    raise exceptions[0]
E   scm.errors.SCMCodedError: ('rpc_invalid_grant', 'Invalid grant')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_post_invalid_headerslog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:86: in fetch_repository
    raise exceptions[0]
E   scm.errors.SCMCodedError: ('rpc_invalid_grant', 'Invalid grant')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_post_invalid_secretlog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:86: in fetch_repository
    raise exceptions[0]
E   scm.errors.SCMCodedError: ('rpc_invalid_grant', 'Invalid grant')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_end_to_endlog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:86: in fetch_repository
    raise exceptions[0]
E   scm.errors.SCMCodedError: ('rpc_invalid_grant', 'Invalid grant')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_getlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:86: in fetch_repository
    raise exceptions[0]
E   scm.errors.SCMCodedError: ('rpc_invalid_grant', 'Invalid grant')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_post_missing_authlog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:86: in fetch_repository
    raise exceptions[0]
E   scm.errors.SCMCodedError: ('rpc_invalid_grant', 'Invalid grant')

Comment thread src/sentry/scm/private/helpers.py
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 15, 2026

Backend Test Failures

Failures on 6d2ac0e in this run:

tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_getlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:86: in fetch_repository
    raise exceptions[0]
E   scm.errors.SCMCodedError: ('rpc_invalid_grant', 'Invalid grant')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_post_invalid_secretlog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:86: in fetch_repository
    raise exceptions[0]
E   scm.errors.SCMCodedError: ('rpc_invalid_grant', 'Invalid grant')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_get_missing_authlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:86: in fetch_repository
    raise exceptions[0]
E   scm.errors.SCMCodedError: ('rpc_invalid_grant', 'Invalid grant')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_get_invalid_secretlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:86: in fetch_repository
    raise exceptions[0]
E   scm.errors.SCMCodedError: ('rpc_invalid_grant', 'Invalid grant')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_end_to_endlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:86: in fetch_repository
    raise exceptions[0]
E   scm.errors.SCMCodedError: ('rpc_invalid_grant', 'Invalid grant')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_get_invalid_headerslog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:86: in fetch_repository
    raise exceptions[0]
E   scm.errors.SCMCodedError: ('rpc_invalid_grant', 'Invalid grant')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_post_invalid_headerslog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:86: in fetch_repository
    raise exceptions[0]
E   scm.errors.SCMCodedError: ('rpc_invalid_grant', 'Invalid grant')
tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_post_missing_authlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/endpoints/test_scm_rpc.py:82: in setUp
    self.rpc_client = SourceCodeManager.make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/rpc/client.py:137: in make_from_repository_id
    return super().make_from_repository_id(
.venv/lib/python3.13/site-packages/scm/manager.py:20: in make_from_repository_id
    provider = initialize_provider(
.venv/lib/python3.13/site-packages/scm/helpers.py:14: in initialize_provider
    repository = fetch_repository(organization_id, repository_id)
.venv/lib/python3.13/site-packages/scm/rpc/client.py:141: in <lambda>
    fetch_repository=lambda oid, rid: fetch_repository(full_url, signing_secret, oid, rid, session),
.venv/lib/python3.13/site-packages/scm/rpc/client.py:86: in fetch_repository
    raise exceptions[0]
E   scm.errors.SCMCodedError: ('rpc_invalid_grant', 'Invalid grant')

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 15, 2026

Backend Test Failures

Failures on b7cee83 in this run:

tests/sentry/scm/endpoints/test_scm_rpc.py::TestScmRpc::test_get_no_secrets_setlog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/endpoints/test_scm_rpc.py:120: in test_get_no_secrets_set
    assert response_json == {
E   AssertionError: assert {'errors': [{... '401', ...}]} == {'data': {'at...'repository'}}
E     
E     Left contains 1 more item:
E     {'errors': [{'code': 'rpc_invalid_grant',
E                  'detail': None,
E                  'meta': None,
E                  'status': '401',
E                  'title': 'Invalid grant'}]}
E     Right contains 1 more item:
E     {'data': {'attributes': {'external_id': '12345',
E                              'integration_id': 89,
E                              'is_active': True,
E                              'name': 'test-org/test-repo',
E                              'organization_id': 4557972519714832,
E                              'provider_name': 'github'},
E               'id': '36',
E               'type': 'repository'}}
E     
E     Full diff:
E       {
E     +     'errors': [
E     +         {
E     +             'code': 'rpc_invalid_grant',
E     +             'detail': None,
E     +             'meta': None,
E     +             'status': '401',
E     +             'title': 'Invalid grant',
E     -     'data': {
E     -         'attributes': {
E     -             'external_id': '12345',
E     -             'integration_id': 89,
E     -             'is_active': True,
E     -             'name': 'test-org/test-repo',
E     -             'organization_id': 4557972519714832,
E     -             'provider_name': 'github',
E               },
E     -         'id': '36',
E     -         'type': 'repository',
E     -     },
E     ?     ^
E     +     ],
E     ?     ^
E       }
tests/sentry/scm/integration/test_helpers_integration.py::TestFetchRepository::test_fetch_by_id_returns_repositorylog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/integration/test_helpers_integration.py:22: in test_fetch_by_id_returns_repository
    assert result is not None
E   assert None is not None
tests/sentry/scm/integration/test_helpers_integration.py::TestFetchRepository::test_fetch_by_provider_and_external_id_returns_repositorylog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/integration/test_helpers_integration.py:52: in test_fetch_by_provider_and_external_id_returns_repository
    assert result is not None
E   assert None is not None

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 15, 2026

Backend Test Failures

Failures on 11a59ab in this run:

tests/sentry/scm/integration/test_helpers_integration.py::TestFetchRepository::test_fetch_by_id_returns_repositorylog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/integration/test_helpers_integration.py:22: in test_fetch_by_id_returns_repository
    assert result is not None
E   assert None is not None
tests/sentry/scm/integration/test_helpers_integration.py::TestFetchRepository::test_fetch_by_provider_and_external_id_returns_repositorylog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/scm/integration/test_helpers_integration.py:52: in test_fetch_by_provider_and_external_id_returns_repository
    assert result is not None
E   assert None is not None

@cmanallen cmanallen marked this pull request as ready for review April 15, 2026 15:29
@cmanallen cmanallen requested review from a team as code owners April 15, 2026 15:29
Comment thread src/sentry/scm/private/helpers.py
Comment thread src/sentry/scm/factory.py
Comment thread src/sentry/scm/endpoints/scm_rpc.py Outdated
publish_status = {
"POST": ApiPublishStatus.EXPERIMENTAL,
}
publish_status = {"GET": ApiPublishStatus.EXPERIMENTAL, "POST": ApiPublishStatus.EXPERIMENTAL}
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.

tbh dont remember what this does, (is it for openapi?) but shouldn't it be private?

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.

Good point!

Comment thread src/sentry/api/urls.py
),
re_path(
r"^scm-rpc/(?P<method_name>\w+)/$",
r"^scm-rpc/$",
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.

where does the method routing get handled now?

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.

The equivalent of method is handled in the POST body.

Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

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 0e43521. Configure here.

Comment thread src/sentry/scm/endpoints/scm_rpc.py
Comment thread src/sentry/scm/private/helpers.py
@cmanallen cmanallen merged commit a7d6f84 into master Apr 15, 2026
112 of 114 checks passed
@cmanallen cmanallen deleted the cmanallen/implement-scm-platform branch April 15, 2026 18:26
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 Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants