diff --git a/.github/workflows/acceptance.yml b/.github/workflows/acceptance.yml deleted file mode 100644 index 6cca80505b4bdf..00000000000000 --- a/.github/workflows/acceptance.yml +++ /dev/null @@ -1,152 +0,0 @@ -# Also note that this name *MUST* match the filename because GHA -# only provides the workflow name (https://docs.github.com/en/free-pro-team@latest/actions/reference/environment-variables#default-environment-variables) -# and GH APIs only support querying by workflow *FILENAME* (https://developer.github.com/v3/actions/workflows/#get-a-workflow) -name: acceptance -on: - push: - branches: - - master - - releases/** - pull_request: - -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -# hack for https://github.com/actions/cache/issues/810#issuecomment-1222550359 -env: - SEGMENT_DOWNLOAD_TIMEOUT_MINS: 3 - NODE_OPTIONS: '--max-old-space-size=4096' - CHARTCUTERIE_CONFIG_PATH: ${{ github.workspace }}/config/chartcuterie - SNUBA_NO_WORKERS: 1 - -jobs: - files-changed: - name: detect what files changed - runs-on: ubuntu-24.04 - timeout-minutes: 3 - # Map a step output to a job output - outputs: - acceptance: ${{ steps.changes.outputs.acceptance }} - backend_all: ${{ steps.changes.outputs.backend_all }} - frontend_all: ${{ steps.changes.outputs.frontend_all }} - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Check for backend file changes - uses: dorny/paths-filter@0bc4621a3135347011ad047f9ecf449bf72ce2bd # v3.0.0 - id: changes - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - acceptance: - if: needs.files-changed.outputs.acceptance == 'true' - needs: files-changed - name: acceptance - runs-on: ubuntu-24.04 - timeout-minutes: 30 - permissions: - contents: read - id-token: write - actions: read # used for DIM metadata - strategy: - # This helps not having to run multiple jobs because one fails, thus, reducing resource usage - # and reducing the risk that one of many runs would turn red again (read: intermittent tests) - fail-fast: false - matrix: - # XXX: Use 5 runners when backend changes are present, 10 runners for frontend-only changes - instance: ${{ needs.files-changed.outputs.backend_all == 'true' && fromJSON('[0, 1, 2, 3, 4]') || fromJSON('[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]') }} - env: - # XXX: MATRIX_INSTANCE_TOTAL must match the matrix size (5 for backend changes, 10 for frontend-only) - MATRIX_INSTANCE_TOTAL: ${{ needs.files-changed.outputs.backend_all == 'true' && '5' || '10' }} - TEST_GROUP_STRATEGY: roundrobin - - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Checkout sentry - - - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4 - id: setup-node - with: - node-version-file: '.node-version' - - - uses: pnpm/action-setup@36de12bed180fa130ed56a35e7344f2fa7a820ab # v4 - - - name: Step configurations - id: config - run: | - echo "webpack-path=.webpack_cache" >> "$GITHUB_OUTPUT" - echo "WEBPACK_CACHE_PATH=.webpack_cache" >> "$GITHUB_ENV" - - - name: webpack cache - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 - with: - path: ${{ steps.config.outputs.webpack-path }} - key: ${{ runner.os }}-v2-webpack-cache-${{ hashFiles('rspack.config.ts', 'pnpm-lock.yaml', 'package.json') }} - - - name: node_modules cache - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 - id: nodemodulescache - with: - path: node_modules - key: ${{ runner.os }}-node-modules-${{ hashFiles('pnpm-lock.yaml', 'api-docs/pnpm-lock.yaml', '.node-version') }} - - - name: Install Javascript Dependencies - if: steps.nodemodulescache.outputs.cache-hit != 'true' - run: pnpm install --frozen-lockfile - - - name: webpack - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - # should set value either as `true` or `false` - CODECOV_ENABLE_BA: ${{ needs.files-changed.outputs.frontend_all == 'true'}} - GH_COMMIT_SHA: ${{ github.event.pull_request.head.sha }} - run: | - pnpm run build-acceptance - - - name: Build chartcuterie configuration module - run: | - make build-chartcuterie-config - - - name: Setup sentry env - uses: ./.github/actions/setup-sentry - id: setup - with: - mode: acceptance-ci - - - name: Run acceptance tests (#${{ steps.setup.outputs.matrix-instance-number }} of ${{ steps.setup.outputs.matrix-instance-total }}) - run: make run-acceptance - - - name: Inspect failure - if: failure() - run: | - if command -v devservices; then - devservices logs - fi - - - name: Collect test data - uses: ./.github/actions/collect-test-data - if: ${{ !cancelled() }} - with: - artifact_path: .artifacts/pytest.acceptance.json - gcs_bucket: ${{ secrets.COLLECT_TEST_DATA_GCS_BUCKET }} - gcp_project_id: ${{ secrets.COLLECT_TEST_DATA_GCP_PROJECT_ID }} - workload_identity_provider: ${{ secrets.SENTRY_GCP_DEV_WORKLOAD_IDENTITY_POOL }} - service_account_email: ${{ secrets.COLLECT_TEST_DATA_SERVICE_ACCOUNT_EMAIL }} - matrix_instance_number: ${{ steps.setup.outputs.matrix-instance-number }} - - acceptance-required-checks: - # this is a required check so we need this job to always run and report a status. - if: always() - name: Acceptance - needs: [acceptance, files-changed] - runs-on: ubuntu-24.04 - timeout-minutes: 3 - steps: - - name: Check for failures - if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') - run: | - echo "One of the dependent jobs have failed. You may need to re-run it." && exit 1 diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml deleted file mode 100644 index 06d484a897d800..00000000000000 --- a/.github/workflows/backend.yml +++ /dev/null @@ -1,450 +0,0 @@ -name: backend - -on: - push: - branches: - - master - pull_request: - workflow_dispatch: - -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -# hack for https://github.com/actions/cache/issues/810#issuecomment-1222550359 -env: - SEGMENT_DOWNLOAD_TIMEOUT_MINS: 3 - SNUBA_NO_WORKERS: 1 - -jobs: - files-changed: - name: detect what files changed - runs-on: ubuntu-24.04 - timeout-minutes: 3 - # Map a step output to a job output - outputs: - api_docs: ${{ steps.changes.outputs.api_docs }} - backend: ${{ steps.changes.outputs.backend_all }} - backend_dependencies: ${{ steps.changes.outputs.backend_dependencies }} - backend_api_urls: ${{ steps.changes.outputs.backend_api_urls }} - backend_any_type: ${{ steps.changes.outputs.backend_any_type }} - migration_lockfile: ${{ steps.changes.outputs.migration_lockfile }} - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Check for backend file changes - uses: dorny/paths-filter@0bc4621a3135347011ad047f9ecf449bf72ce2bd # v3.0.0 - id: changes - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - api-docs: - if: needs.files-changed.outputs.api_docs == 'true' - needs: files-changed - name: api docs test - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4 - id: setup-node - with: - node-version-file: '.node-version' - - - uses: pnpm/action-setup@36de12bed180fa130ed56a35e7344f2fa7a820ab # v4 - - - name: Setup sentry python env - uses: ./.github/actions/setup-sentry - id: setup - with: - mode: default - - - name: Run API docs tests - run: | - make test-api-docs - - - name: Inspect failure - if: failure() - run: | - if command -v devservices; then - devservices logs - fi - - calculate-shards: - if: needs.files-changed.outputs.backend == 'true' - needs: files-changed - name: calculate test shards - runs-on: ubuntu-24.04 - timeout-minutes: 5 - outputs: - shard-count: ${{ steps.calculate-shards.outputs.shard-count }} - shard-indices: ${{ steps.calculate-shards.outputs.shard-indices }} - - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Setup sentry env - uses: ./.github/actions/setup-sentry - id: setup - with: - mode: backend-ci - skip-devservices: true - - - name: Calculate test shards - id: calculate-shards - run: | - python3 .github/workflows/scripts/calculate-backend-test-shards.py - - backend-test: - if: needs.files-changed.outputs.backend == 'true' - needs: [files-changed, calculate-shards] - name: backend test - runs-on: ubuntu-24.04 - timeout-minutes: 60 - permissions: - contents: read - id-token: write - actions: read # used for DIM metadata - strategy: - # This helps not having to run multiple jobs because one fails, thus, reducing resource usage - # and reducing the risk that one of many runs would turn red again (read: intermittent tests) - fail-fast: false - matrix: - # Dynamic matrix from calculate-shards - instance: ${{ fromJSON(needs.calculate-shards.outputs.shard-indices) }} - - env: - # Dynamic total from calculate-shards - MATRIX_INSTANCE_TOTAL: ${{ needs.calculate-shards.outputs.shard-count }} - TEST_GROUP_STRATEGY: roundrobin - - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Setup sentry env - uses: ./.github/actions/setup-sentry - id: setup - with: - mode: backend-ci - - - name: Run backend test (${{ steps.setup.outputs.matrix-instance-number }} of ${{ steps.setup.outputs.matrix-instance-total }}) - run: | - make test-python-ci - - - name: Inspect failure - if: failure() - run: | - if command -v devservices; then - devservices logs - fi - - - name: Collect test data - uses: ./.github/actions/collect-test-data - if: ${{ !cancelled() }} - with: - artifact_path: .artifacts/pytest.json - gcs_bucket: ${{ secrets.COLLECT_TEST_DATA_GCS_BUCKET }} - gcp_project_id: ${{ secrets.COLLECT_TEST_DATA_GCP_PROJECT_ID }} - workload_identity_provider: ${{ secrets.SENTRY_GCP_DEV_WORKLOAD_IDENTITY_POOL }} - service_account_email: ${{ secrets.COLLECT_TEST_DATA_SERVICE_ACCOUNT_EMAIL }} - matrix_instance_number: ${{ steps.setup.outputs.matrix-instance-number }} - - backend-migration-tests: - if: needs.files-changed.outputs.backend == 'true' - needs: files-changed - name: backend migration tests - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Setup sentry env - uses: ./.github/actions/setup-sentry - id: setup - with: - mode: default - - - name: run tests - run: | - PYTEST_ADDOPTS="$PYTEST_ADDOPTS -m migrations --migrations --reruns 0 --fail-slow=120s" make test-python-ci - - - name: Inspect failure - if: failure() - run: | - if command -v devservices; then - devservices logs - fi - - cli: - if: needs.files-changed.outputs.backend == 'true' - needs: files-changed - name: cli test - runs-on: ubuntu-24.04 - timeout-minutes: 10 - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Setup sentry env - uses: ./.github/actions/setup-sentry - id: setup - with: - mode: migrations - - - name: Run test - env: - # This short circuits the create_default_projects post_upgrade hook - # which spawns taskworkers which will spin for 5 minutes on kafka - # not being up. We don't need the default project here as this is not local dev. - SENTRY_NO_CREATE_DEFAULT_PROJECT: 1 - run: make test-cli - - - name: Inspect failure - if: failure() - run: | - if command -v devservices; then - devservices logs - fi - - requirements: - if: needs.files-changed.outputs.backend_dependencies == 'true' - needs: files-changed - name: requirements check - runs-on: ubuntu-24.04 - timeout-minutes: 3 - steps: - - uses: getsentry/action-github-app-token@d4b5da6c5e37703f8c3b3e43abb5705b46e159cc # v3.0.0 - id: token - continue-on-error: true - with: - app_id: ${{ vars.SENTRY_INTERNAL_APP_ID }} - private_key: ${{ secrets.SENTRY_INTERNAL_APP_PRIVATE_KEY }} - - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - uses: astral-sh/setup-uv@884ad927a57e558e7a70b92f2bccf9198a4be546 # v6 - with: - version: '0.8.2' - - - uses: getsentry/action-setup-venv@5a80476d175edf56cb205b08bc58986fa99d1725 # v3.2.0 - with: - cache-dependency-path: uv.lock - install-cmd: echo - - - name: check requirements - run: | - make freeze-requirements - if ! git diff --exit-code; then - echo $'\n\nrun `make freeze-requirements` locally to update requirements' - exit 1 - fi - - - name: apply any requirements changes - if: steps.token.outcome == 'success' && github.ref != 'refs/heads/master' && always() - uses: getsentry/action-github-commit@31f6706ca1a7b9ad6d22c1b07bf3a92eabb05632 # v2.0.0 - with: - github-token: ${{ steps.token.outputs.token }} - message: ':snowflake: re-freeze requirements' - - api-url-typescript: - if: needs.files-changed.outputs.backend_api_urls == 'true' - needs: files-changed - name: api url typescript generation - runs-on: ubuntu-24.04 - timeout-minutes: 10 - steps: - - uses: getsentry/action-github-app-token@d4b5da6c5e37703f8c3b3e43abb5705b46e159cc # v3.0.0 - id: token - with: - app_id: ${{ vars.SENTRY_INTERNAL_APP_ID }} - private_key: ${{ secrets.SENTRY_INTERNAL_APP_PRIVATE_KEY }} - - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Setup sentry env - uses: ./.github/actions/setup-sentry - with: - mode: backend-ci - - - name: Sync API Urls to TypeScirpt - run: | - python3 -m tools.api_urls_to_typescript - - - name: Apply any file changes - if: github.ref != 'refs/heads/master' && always() - uses: getsentry/action-github-commit@31f6706ca1a7b9ad6d22c1b07bf3a92eabb05632 # v2.0.0 - with: - github-token: ${{ steps.token.outputs.token }} - message: ':hammer_and_wrench: Sync API Urls to TypeScirpt' - - migration: - if: needs.files-changed.outputs.migration_lockfile == 'true' - needs: files-changed - name: check migration - runs-on: ubuntu-24.04 - - steps: - - name: Checkout sentry - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Setup sentry env - uses: ./.github/actions/setup-sentry - id: setup - with: - mode: migrations - - - name: Migration & lockfile checks - env: - SENTRY_LOG_LEVEL: ERROR - PGPASSWORD: postgres - run: | - ./.github/workflows/scripts/migration-check.sh - - - name: Inspect failure - if: failure() - run: | - if command -v devservices; then - devservices logs - fi - - monolith-dbs: - if: needs.files-changed.outputs.backend == 'true' - needs: files-changed - name: monolith-dbs test - runs-on: ubuntu-24.04 - timeout-minutes: 20 - permissions: - contents: read - id-token: write - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Setup sentry env - uses: ./.github/actions/setup-sentry - id: setup - with: - mode: migrations - - - name: Run test - run: | - make test-monolith-dbs - - - name: Inspect failure - if: failure() - run: | - if command -v devservices; then - devservices logs - fi - - - name: Collect test data - uses: ./.github/actions/collect-test-data - if: ${{ !cancelled() }} - with: - artifact_path: .artifacts/pytest.monolith-dbs.json - gcs_bucket: ${{ secrets.COLLECT_TEST_DATA_GCS_BUCKET }} - gcp_project_id: ${{ secrets.COLLECT_TEST_DATA_GCP_PROJECT_ID }} - workload_identity_provider: ${{ secrets.SENTRY_GCP_DEV_WORKLOAD_IDENTITY_POOL }} - service_account_email: ${{ secrets.COLLECT_TEST_DATA_SERVICE_ACCOUNT_EMAIL }} - - typing: - if: needs.files-changed.outputs.backend == 'true' - needs: files-changed - name: backend typing - runs-on: ubuntu-24.04 - timeout-minutes: 20 - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - uses: astral-sh/setup-uv@884ad927a57e558e7a70b92f2bccf9198a4be546 # v6 - with: - version: '0.8.2' - # we just cache the venv-dir directly in action-setup-venv - enable-cache: false - - - uses: getsentry/action-setup-venv@5a80476d175edf56cb205b08bc58986fa99d1725 # v3.2.0 - with: - cache-dependency-path: uv.lock - install-cmd: uv sync --frozen --active - - - name: setup sentry (lite) - run: | - python3 -m tools.fast_editable --path . - sentry init - - - run: PYTHONWARNINGS=error::RuntimeWarning mypy - id: run - - - uses: getsentry/action-github-app-token@d4b5da6c5e37703f8c3b3e43abb5705b46e159cc # v3.0.0 - id: token - continue-on-error: true - with: - app_id: ${{ vars.SENTRY_INTERNAL_APP_ID }} - private_key: ${{ secrets.SENTRY_INTERNAL_APP_PRIVATE_KEY }} - - # only if `mypy` succeeds should we try and trim the blocklist - - run: python3 -m tools.mypy_helpers.make_module_ignores - id: regen-blocklist - - - run: git diff --exit-code - - - run: | - # mypy does not have granular codes so don't allow specific messages to regress - set -euo pipefail - ! grep "'Settings' object has no attribute" .artifacts/mypy-all - ! grep 'Argument .* of "dispatch" is incompatible with' .artifacts/mypy-all - ! grep 'Cannot override class variable' .artifacts/mypy-all - ! grep 'Exception type must be derived from BaseException' .artifacts/mypy-all - ! grep 'Incompatible default for argument' .artifacts/mypy-all - ! grep 'Incompatible return value type (got "HttpResponseBase"' .artifacts/mypy-all - ! grep 'Incompatible types in "yield"' .artifacts/mypy-all - ! grep 'Module "sentry.*has no attribute' .artifacts/mypy-all - ! grep 'No return value expected' .artifacts/mypy-all - ! grep 'Return value expected' .artifacts/mypy-all - ! grep 'Unpacking a string is disallowed' .artifacts/mypy-all - ! grep 'base class .* defined the type as.*Permission' .artifacts/mypy-all - ! grep 'does not explicitly export attribute' .artifacts/mypy-all - ! grep 'gets multiple values for' .artifacts/mypy-all - - - name: apply blocklist changes - if: | - steps.token.outcome == 'success' && - steps.run.outcome == 'success' && - steps.regen-blocklist.outcome == 'success' && - github.ref != 'refs/heads/master' && - always() - uses: getsentry/action-github-commit@31f6706ca1a7b9ad6d22c1b07bf3a92eabb05632 # v2.0.0 - with: - github-token: ${{ steps.token.outputs.token }} - message: ':knife: regenerate mypy module blocklist' - - # This check runs once all dependent jobs have passed - # It symbolizes that all required Backend checks have succesfully passed (Or skipped) - # This step is the only required backend check - backend-required-check: - needs: - [ - api-docs, - backend-test, - backend-migration-tests, - calculate-shards, - cli, - files-changed, - requirements, - migration, - monolith-dbs, - typing, - ] - name: Backend - # This is necessary since a failed/skipped dependent job would cause this job to be skipped - if: always() - runs-on: ubuntu-24.04 - steps: - # If any jobs we depend on fail, we will fail since this is a required check - # NOTE: A timeout is considered a failure - - name: Check for failures - if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') - run: | - echo "One of the dependent jobs have failed. You may need to re-run it." && exit 1 diff --git a/.github/workflows/backend_selective_testing.yml b/.github/workflows/backend_selective_testing.yml new file mode 100644 index 00000000000000..e0c4aea5162772 --- /dev/null +++ b/.github/workflows/backend_selective_testing.yml @@ -0,0 +1,133 @@ +name: backend (selective) + +on: + pull_request: + +# Cancel in progress workflows on pull_requests. +# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + # files-changed: + # name: detect what files changed + # runs-on: ubuntu-24.04 + # timeout-minutes: 3 + # # Map a step output to a job output + # outputs: + # api_docs: ${{ steps.changes.outputs.api_docs }} + # backend: ${{ steps.changes.outputs.backend_all }} + # backend_dependencies: ${{ steps.changes.outputs.backend_dependencies }} + # backend_api_urls: ${{ steps.changes.outputs.backend_api_urls }} + # backend_any_type: ${{ steps.changes.outputs.backend_any_type }} + # migration_lockfile: ${{ steps.changes.outputs.migration_lockfile }} + # steps: + # - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + # + # - name: Check for backend file changes + # uses: dorny/paths-filter@0bc4621a3135347011ad047f9ecf449bf72ce2bd # v3.0.0 + # id: changes + # with: + # token: ${{ github.token }} + # filters: .github/file-filters.yml + + select-tests: + #if: needs.files-changed.outputs.backend == 'true' + #needs: files-changed + name: select tests + runs-on: ubuntu-24.04 + timeout-minutes: 5 + outputs: + shard-count: ${{ steps.select-tests.outputs.shard-count }} + shard-indices: ${{ steps.select-tests.outputs.shard-indices }} + + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + # full checkout is required for symmetric diff with the merge base to get changed files + # maybe we can just use the github api to get a PR's changed files? + fetch-depth: 0 + + # TODO: Replace with Gcloud download + # Download coverage artifact from a previous workflow run + # actions/download-artifact doesn't support cross-run downloads, so we use alternatives + - name: Download coverage database from run 20529759656 + uses: dawidd6/action-download-artifact@v6 + continue-on-error: true + id: download-coverage + with: + run_id: 20529759656 + name: pycoverage-sqlite-combined-20529759656 + path: .coverage + github_token: ${{ github.token }} + + - name: Select Tests + id: select-tests + env: + GITHUB_PR_BASE_REF: ${{ github.event.pull_request.base.sha }} + COVERAGE_DB_PATH: .coverage/.coverage.combined + run: | + python3 .github/workflows/scripts/select-tests.py + + - name: Upload selected tests + uses: actions/upload-artifact@v4 + with: + name: selected-tests + path: selected-tests + + backend-test-selective: + #if: needs.files-changed.outputs.backend == 'true' + #needs: files-changed + needs: select-tests + name: backend test + runs-on: ubuntu-24.04 + timeout-minutes: 60 + permissions: + contents: read + id-token: write + actions: read # used for DIM metadata + strategy: + fail-fast: false + matrix: + instance: ${{ fromJSON(needs.select-tests.outputs.shard-indices) }} + + env: + MATRIX_INSTANCE_TOTAL: ${{ needs.select-tests.outputs.shard-count }} + + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + - name: Setup sentry env + uses: ./.github/actions/setup-sentry + id: setup + with: + mode: backend-ci + + - name: Download selected tests + uses: actions/download-artifact@v4 + with: + name: selected-tests + + - name: Run backend tests (${{ steps.setup.outputs.matrix-instance-number }} of ${{ steps.setup.outputs.matrix-instance-total }}) + id: run_backend_tests + run: | + python .github/workflows/scripts/pytest-args-wrapper.py selected-tests + + - name: Inspect failure + if: failure() + run: | + if command -v devservices; then + devservices logs + fi + + # - name: Collect test data + # uses: ./.github/actions/collect-test-data + # if: ${{ !cancelled() }} + # with: + # artifact_path: .artifacts/pytest.json # TODO + # gcs_bucket: ${{ secrets.COLLECT_TEST_DATA_GCS_BUCKET }} + # gcp_project_id: ${{ secrets.COLLECT_TEST_DATA_GCP_PROJECT_ID }} + # workload_identity_provider: ${{ secrets.SENTRY_GCP_DEV_WORKLOAD_IDENTITY_POOL }} + # service_account_email: ${{ secrets.COLLECT_TEST_DATA_SERVICE_ACCOUNT_EMAIL }} + # matrix_instance_number: ${{ steps.setup.outputs.matrix-instance-number }} diff --git a/.github/workflows/bump-sentry-in-getsentry.yml b/.github/workflows/bump-sentry-in-getsentry.yml deleted file mode 100644 index d955d1d12cc492..00000000000000 --- a/.github/workflows/bump-sentry-in-getsentry.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: bump sentry in getsentry - -# Serializes the execution of this workflow. -concurrency: - group: ${{ github.workflow }} - -on: - push: - branches: - - master - -defaults: - run: - # the default default is: - # bash --noprofile --norc -eo pipefail {0} - shell: bash --noprofile --norc -eo pipefail -ux {0} - -jobs: - bump-sentry: - runs-on: ubuntu-24.04 - steps: - - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - with: - # For getsentry/bin/bump-sentry, sentry needs to be at ../sentry relative to getsentry. - path: sentry - - - name: checkout getsentry - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - with: - repository: 'getsentry/getsentry' - path: getsentry - # This PAT (Personal Access Token) belongs to getsentry-bot, - # who can write to getsentry and is SAML+SSO ready. - token: ${{ secrets.BUMP_SENTRY_TOKEN }} - - - name: bump-sentry ${{ github.sha }} - run: | - cd getsentry - - python -S -m bin.bump_sentry ${{ github.sha }} - - # If getsentry is pushed to by any other means while we were here, - # we won't be able to push. - for i in 1 2 3 4 5; do - git push origin master && exit 0 - # There's a little bit of network delay here that suffices - # as a small sleep. - git \ - -c user.name=getsentry-bot \ - -c user.email=bot@sentry.io \ - pull --rebase origin master - done - - # 5th and final attempt. - git push origin master diff --git a/.github/workflows/bump-version.yml b/.github/workflows/bump-version.yml deleted file mode 100644 index 70c044beb67098..00000000000000 --- a/.github/workflows/bump-version.yml +++ /dev/null @@ -1,75 +0,0 @@ -on: - workflow_dispatch: - inputs: - package: - required: true - type: string - description: package name such as `sentry-arroyo` - version: - required: true - type: string - description: desired version such as `1.2.3`, or `latest` to pull the latest version from PyPI - pr_options: - type: string - default: '' - description: additional options for gh pr create, such as for asking for specific reviewers - - # for use in other (cron/scheduled) workflows to bump specific - # company-internal dependencies on a more aggressive schedule - workflow_call: - inputs: - package: - required: true - type: string - version: - required: true - type: string - pr_options: - type: string - default: '' - -# disable all permissions -- we use the PAT's permissions instead -permissions: {} - -jobs: - bump-version: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - with: - token: ${{ secrets.BUMP_SENTRY_TOKEN }} - - uses: astral-sh/setup-uv@884ad927a57e558e7a70b92f2bccf9198a4be546 # v6 - with: - version: '0.8.2' - - run: | - set -euxo pipefail - - if [ "$VERSION" = latest ]; then - VERSION="$(curl -sL https://pypi.org/pypi/$PACKAGE/json | jq -r .info.version)" - fi - - git checkout -b "bot/bump-version/$PACKAGE/$VERSION" - - python3 -S -m tools.bump_version "$PACKAGE" "$VERSION" - - if git diff --exit-code; then - exit 0 - fi - - git \ - -c user.name=getsentry-bot \ - -c user.email='10587625+getsentry-bot@users.noreply.github.com' \ - commit \ - --all \ - --message "ref: bump $PACKAGE to $VERSION" \ - --message "Co-Authored-By: $SENDER <$SENDER_ID+$SENDER@users.noreply.github.com>" - - git push origin HEAD --quiet - - gh pr create --fill ${{ inputs.pr_options }} - env: - GH_TOKEN: ${{ secrets.BUMP_SENTRY_TOKEN }} - PACKAGE: ${{ inputs.package }} - VERSION: ${{ inputs.version }} - SENDER: ${{ github.event.sender.login }} - SENDER_ID: ${{ github.event.sender.id }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index 2ab3a274259355..00000000000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,68 +0,0 @@ -name: 'CodeQL' - -on: - pull_request: - # The branches below must be a subset of the branches above - branches: ['master'] - paths: - - '**.js' - - '**.ejs' - - '**.tsx' - - '**.ts' - - '**.py' - - '!tests/**' - schedule: - - cron: '44 12 * * 1' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: ['javascript', 'python'] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] - # Learn more about CodeQL language support at https://git.io/codeql-language-support - - steps: - - name: Checkout repository - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 # v2.22.3 - with: - trap-caching: false - config-file: ./.github/codeql/codeql-config.yml - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: security-extended - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - # - name: Autobuild - # uses: github/codeql-action/autobuild@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 # v2.22.3 - - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - # âœī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 # v2.22.3 - with: - category: '/language:${{matrix.language}}' diff --git a/.github/workflows/development-environment.yml b/.github/workflows/development-environment.yml deleted file mode 100644 index 42804f51630dda..00000000000000 --- a/.github/workflows/development-environment.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: dev env -on: - pull_request: - paths: - - '.pre-commit-config.yaml' - - 'Makefile' - - '.github/workflows/development-environment.yml' - - 'requirements-*.txt' - - 'pyproject.toml' - - 'uv.lock' - - '.python-version' - - '.envrc' - - 'Brewfile' - - 'scripts/**' - - 'tools/**' - - 'src/sentry/runner/commands/devserver.py' - - 'src/sentry/runner/commands/devservices.py' - - 'bin/load-mocks' - -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -# hack for https://github.com/actions/cache/issues/810#issuecomment-1222550359 -env: - SEGMENT_DOWNLOAD_TIMEOUT_MINS: 3 - -jobs: - test: - runs-on: ubuntu-24.04 - timeout-minutes: 5 - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - uses: astral-sh/setup-uv@884ad927a57e558e7a70b92f2bccf9198a4be546 # v6 - with: - version: '0.8.2' - # we just cache the venv-dir directly in action-setup-venv - enable-cache: false - - - uses: getsentry/action-setup-venv@5a80476d175edf56cb205b08bc58986fa99d1725 # v3.2.0 - with: - cache-dependency-path: uv.lock - install-cmd: uv sync --only-dev --frozen --active - - - name: test-tools - run: make test-tools - - devenv: - runs-on: ubuntu-24.04 - timeout-minutes: 10 - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - uses: astral-sh/setup-uv@884ad927a57e558e7a70b92f2bccf9198a4be546 # v6 - with: - version: '0.8.2' - # we just cache the venv-dir directly in action-setup-venv - enable-cache: false - - - uses: getsentry/action-setup-venv@5a80476d175edf56cb205b08bc58986fa99d1725 # v3.2.0 - with: - cache-dependency-path: uv.lock - # technically we can just use --only-dev but more cache is nice - install-cmd: uv sync --frozen --active - - - name: devenv sync - run: | - devenv --nocoderoot sync diff --git a/.github/workflows/enforce-license-compliance.yml b/.github/workflows/enforce-license-compliance.yml deleted file mode 100644 index 5cb36295bc5eb4..00000000000000 --- a/.github/workflows/enforce-license-compliance.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: Enforce License Compliance - -on: - pull_request: - -jobs: - enforce-license-compliance: - runs-on: ubuntu-latest - steps: - - name: 'Enforce License Compliance' - uses: getsentry/action-enforce-license-compliance@48236a773346cb6552a7bda1ee370d2797365d87 # main - with: - fossa_api_key: ${{ secrets.FOSSA_API_KEY }} diff --git a/.github/workflows/fast-revert.yml b/.github/workflows/fast-revert.yml deleted file mode 100644 index 32469edf2a49cc..00000000000000 --- a/.github/workflows/fast-revert.yml +++ /dev/null @@ -1,40 +0,0 @@ -on: - pull_request_target: - types: [labeled] - workflow_dispatch: - inputs: - pr: - required: true - description: pr number - co_authored_by: - required: true - description: '`name ` for triggering user' - -# disable all permissions -- we use the PAT's permissions instead -permissions: {} - -jobs: - revert: - runs-on: ubuntu-latest - if: | - github.event_name == 'workflow_dispatch' || github.event.label.name == 'Trigger: Revert' - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - with: - token: ${{ secrets.BUMP_SENTRY_TOKEN }} - - uses: getsentry/action-fast-revert@35b4b6c1f8f91b5911159568b3b15e531b5b8174 # v2.0.1 - with: - pr: ${{ github.event.number || github.event.inputs.pr }} - co_authored_by: ${{ github.event.inputs.co_authored_by || format('{0} <{1}+{0}@users.noreply.github.com>', github.event.sender.login, github.event.sender.id) }} - committer_name: getsentry-bot - committer_email: bot@sentry.io - token: ${{ secrets.BUMP_SENTRY_TOKEN }} - - name: comment on failure - run: | - curl \ - --silent \ - -X POST \ - -H 'Authorization: token ${{ secrets.BUMP_SENTRY_TOKEN }}' \ - -d'{"body": "revert failed (conflict? already reverted?) -- [check the logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})"}' \ - https://api.github.com/repositories/${{ github.event.repository.id }}/issues/${{ github.event.number || github.event.inputs.pr }}/comments - if: failure() diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml deleted file mode 100644 index 2d74fa6e21a8bd..00000000000000 --- a/.github/workflows/frontend.yml +++ /dev/null @@ -1,238 +0,0 @@ -name: frontend - -on: - push: - branches: - - master - pull_request: - -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -# hack for https://github.com/actions/cache/issues/810#issuecomment-1222550359 -env: - SEGMENT_DOWNLOAD_TIMEOUT_MINS: 3 - NODE_OPTIONS: '--max-old-space-size=4096' - -jobs: - files-changed: - name: detect what files changed - runs-on: ubuntu-24.04 - timeout-minutes: 3 - # Map a step output to a job output - outputs: - testable_modified: ${{ steps.changes.outputs.testable_modified }} - testable_rules_changed: ${{ steps.changes.outputs.testable_rules_changed }} - typecheckable_rules_changed: ${{ steps.changes.outputs.typecheckable_rules_changed }} - frontend_all: ${{ steps.changes.outputs.frontend_all }} - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Check for frontend file changes - uses: dorny/paths-filter@0bc4621a3135347011ad047f9ecf449bf72ce2bd # v3.0.0 - id: changes - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - list-files: shell - - typescript: - if: needs.files-changed.outputs.frontend_all == 'true' - needs: files-changed - name: typescript - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4 - id: setup-node - with: - node-version-file: '.node-version' - - - uses: pnpm/action-setup@36de12bed180fa130ed56a35e7344f2fa7a820ab # v4 - - - name: node_modules cache - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 - id: nodemodulescache - with: - path: node_modules - key: ${{ runner.os }}-node-modules-${{ hashFiles('pnpm-lock.yaml', 'api-docs/pnpm-lock.yaml', '.node-version') }} - - - name: Install Javascript Dependencies - if: steps.nodemodulescache.outputs.cache-hit != 'true' - run: pnpm install --frozen-lockfile - - # Setup custom tsc matcher, see https://github.com/actions/setup-node/issues/97 - - name: setup matchers - run: | - echo "::remove-matcher owner=masters::" - echo "::add-matcher::.github/tsc.json" - - - name: tsc - id: tsc - run: pnpm exec tsc -p tsconfig.json - - eslint: - if: needs.files-changed.outputs.frontend_all == 'true' - needs: files-changed - name: eslint - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4 - id: setup-node - with: - node-version-file: '.node-version' - - - uses: pnpm/action-setup@36de12bed180fa130ed56a35e7344f2fa7a820ab # v4 - - - name: node_modules cache - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 - id: nodemodulescache - with: - path: node_modules - key: ${{ runner.os }}-node-modules-${{ hashFiles('pnpm-lock.yaml', 'api-docs/pnpm-lock.yaml', '.node-version') }} - - - name: Install Javascript Dependencies - if: steps.nodemodulescache.outputs.cache-hit != 'true' - run: pnpm install --frozen-lockfile - - # Setup custom eslint matcher, see https://github.com/actions/setup-node/issues/97 - - name: setup matchers - run: | - echo "::remove-matcher owner=masters::" - echo "::add-matcher::.github/eslint-stylish.json" - - - name: eslint - id: eslint - run: pnpm run lint:js - - knip: - if: needs.files-changed.outputs.frontend_all == 'true' - needs: files-changed - name: knip - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4 - id: setup-node - with: - node-version-file: '.node-version' - - - uses: pnpm/action-setup@36de12bed180fa130ed56a35e7344f2fa7a820ab # v4 - - - name: node_modules cache - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 - id: nodemodulescache - with: - path: node_modules - key: ${{ runner.os }}-node-modules-${{ hashFiles('pnpm-lock.yaml', 'api-docs/pnpm-lock.yaml', '.node-version') }} - - - name: Install Javascript Dependencies - if: steps.nodemodulescache.outputs.cache-hit != 'true' - run: pnpm install --frozen-lockfile - - # Setup custom eslint matcher, see https://github.com/actions/setup-node/issues/97 - - name: setup matchers - run: | - echo "::remove-matcher owner=masters::" - echo "::add-matcher::.github/eslint-stylish.json" - - - name: knip - id: knip - run: pnpm run knip - - - name: knip-prod - id: knip-prod - run: pnpm run knip:prod - - frontend-jest-tests: - if: needs.files-changed.outputs.testable_rules_changed == 'true' || needs.files-changed.outputs.testable_modified == 'true' - needs: [files-changed] - name: Jest - # If you change the runs-on image, you must also change the runner in jest-balance.yml - # so that the balancer runs in the same environment as the tests. - runs-on: ubuntu-24.04 - timeout-minutes: 30 - strategy: - # This helps not having to run multiple jobs because one fails, thus, reducing resource usage - # and reducing the risk that one of many runs would turn red again (read: intermittent tests) - fail-fast: false - matrix: - # XXX: When updating this, make sure you also update CI_NODE_TOTAL. - - instance: [0, 1, 2, 3] - - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Checkout sentry - - - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4 - id: setup-node - with: - node-version-file: '.node-version' - - - uses: pnpm/action-setup@36de12bed180fa130ed56a35e7344f2fa7a820ab # v4 - - - name: node_modules cache - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 - id: nodemodulescache - with: - path: node_modules - key: ${{ runner.os }}-node-modules-${{ hashFiles('pnpm-lock.yaml', 'api-docs/pnpm-lock.yaml', '.node-version') }} - - - name: Install Javascript Dependencies - if: steps.nodemodulescache.outputs.cache-hit != 'true' - run: pnpm install --frozen-lockfile - - - name: Download jest-balance.json - id: download-artifact - uses: dawidd6/action-download-artifact@ac66b43f0e6a346234dd65d4d0c8fbb31cb316e5 # v11 - with: - workflow: 38531594 # jest-balancer.yml - workflow_conclusion: success # The conclusion of the workflow we're looking for - branch: master # The branch we're looking for - name: jest-balance.json # Artifact name - name_is_regexp: false - path: tests/js/test-balancer/ # Directory where to extract artifact(s), defaults to the current directory - search_artifacts: true # Search for the last workflow run whose stored the artifact we're looking for - if_no_artifact_found: warn # Can be one of: "fail", "warn", "ignore" - - - name: jest - env: - GITHUB_PR_SHA: ${{ github.event.pull_request.head.sha || github.sha }} - GITHUB_PR_REF: ${{ github.event.pull_request.head.ref || github.ref }} - # XXX: CI_NODE_TOTAL must be hardcoded to the length of strategy.matrix.instance. - # Otherwise, if there are other things in the matrix, using strategy.job-total - # wouldn't be correct. - CI_NODE_TOTAL: 4 - CI_NODE_INDEX: ${{ matrix.instance }} - # Disable testing-library from printing out any of of the DOM to - # stdout. No one actually looks through this in CI, they're just - # going to run it locally. - # - # This quiets up the logs quite a bit. - DEBUG_PRINT_LIMIT: 0 - run: pnpm run test-ci --forceExit - - # This check runs once all dependant jobs have passed - # It symbolizes that all required Frontend checks have succesfully passed (Or skipped) - # This check is the only required Github check - frontend-required-check: - needs: [files-changed, frontend-jest-tests, typescript, eslint, knip] - name: Frontend - # This is necessary since a failed/skipped dependent job would cause this job to be skipped - if: always() - runs-on: ubuntu-24.04 - steps: - # If any jobs we depend on fail, we will fail since this is a required check - # NOTE: A timeout is considered a failure - - name: Check for failures - if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') - run: | - echo "One of the dependent jobs have failed. You may need to re-run it." && exit 1 diff --git a/.github/workflows/getsentry-dispatch.yml b/.github/workflows/getsentry-dispatch.yml deleted file mode 100644 index ec4a3dd36ab45b..00000000000000 --- a/.github/workflows/getsentry-dispatch.yml +++ /dev/null @@ -1,81 +0,0 @@ -# Dispatch a request to getsentry to run getsentry test suites -name: getsentry dispatcher - -on: - # XXX: We are using `pull_request_target` instead of `pull_request` because we want - # this to run on forks. It allows forks to access secrets safely by - # only running workflows from the main branch. Prefer to use `pull_request` when possible. - # - # See https://github.com/getsentry/sentry/pull/21600 for more details - pull_request_target: - types: [labeled, opened, reopened, synchronize] - -# disable all other special privileges -permissions: - # needed for `actions/checkout` to clone the code - contents: read - # needed to remove the pull-request label - pull-requests: write - -jobs: - dispatch: - if: "github.event.action != 'labeled' || github.event.label.name == 'Trigger: getsentry tests'" - name: getsentry dispatch - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - with: - persist-credentials: false - - - name: permissions - run: | - python3 -uS .github/workflows/scripts/getsentry-dispatch-setup \ - --repo-id ${{ github.event.repository.id }} \ - --pr ${{ github.event.number }} \ - --event ${{ github.event.action }} \ - --username "$ARG_USERNAME" \ - --label-names "$ARG_LABEL_NAMES" - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # these can contain special characters - ARG_USERNAME: ${{ github.event.pull_request.user.login }} - ARG_LABEL_NAMES: ${{ toJSON(github.event.pull_request.labels.*.name) }} - - - name: Check for file changes - uses: dorny/paths-filter@0bc4621a3135347011ad047f9ecf449bf72ce2bd # v3.0.0 - id: changes - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - - name: getsentry token - uses: getsentry/action-github-app-token@d4b5da6c5e37703f8c3b3e43abb5705b46e159cc # v3.0.0 - id: getsentry - with: - app_id: ${{ vars.SENTRY_INTERNAL_APP_ID }} - private_key: ${{ secrets.SENTRY_INTERNAL_APP_PRIVATE_KEY }} - - - name: Wait for PR merge commit - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 - id: mergecommit - with: - github-token: ${{ steps.getsentry.outputs.token }} - script: | - require(`${process.env.GITHUB_WORKSPACE}/.github/workflows/scripts/wait-for-merge-commit`).waitForMergeCommit({ - github, - context, - core, - }); - - - name: Dispatch getsentry tests - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 - with: - github-token: ${{ steps.getsentry.outputs.token }} - script: | - require(`${process.env.GITHUB_WORKSPACE}/.github/workflows/scripts/getsentry-dispatch`).dispatch({ - github, - context, - core, - mergeCommitSha: '${{ steps.mergecommit.outputs.mergeCommitSha }}', - fileChanges: ${{ toJson(steps.changes.outputs) }}, - }); diff --git a/.github/workflows/jest-balance.yml b/.github/workflows/jest-balance.yml deleted file mode 100644 index de55de4c4de710..00000000000000 --- a/.github/workflows/jest-balance.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: jest balancer -on: - workflow_dispatch: - schedule: - - cron: '0 0 1,15 * *' -jobs: - jest-balance: - # Buckle up, this may take a while - timeout-minutes: 60 - # Make sure this matches the runner that runs frontend tests - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Checkout sentry - - - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4 - id: setup-node - with: - node-version-file: '.node-version' - - - uses: pnpm/action-setup@36de12bed180fa130ed56a35e7344f2fa7a820ab # v4 - - - name: node_modules cache - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 - id: nodemodulescache - with: - path: node_modules - key: ${{ runner.os }}-node-modules-${{ hashFiles('pnpm-lock.yaml', 'api-docs/pnpm-lock.yaml', '.node-version') }} - - - name: Install Javascript Dependencies - if: steps.nodemodulescache.outputs.cache-hit != 'true' - run: pnpm install --frozen-lockfile - - - name: jest balancer - env: - GITHUB_PR_SHA: ${{ github.event.pull_request.head.sha || github.sha }} - GITHUB_PR_REF: ${{ github.event.pull_request.head.ref || github.ref }} - run: JEST_TEST_BALANCER=1 pnpm run test-ci - - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 - with: - name: jest-balance.json - path: tests/js/test-balancer/jest-balance.json diff --git a/.github/workflows/label-pullrequest.yml b/.github/workflows/label-pullrequest.yml deleted file mode 100644 index 48cfe4f909e607..00000000000000 --- a/.github/workflows/label-pullrequest.yml +++ /dev/null @@ -1,69 +0,0 @@ -# Adds labels to pull requests for the type of change the PR makes -name: meta(labels) - -on: - pull_request_target: - -jobs: - label-pullrequest: - permissions: - contents: read - pull-requests: write - name: labels pull requests (frontend / backend) - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - with: - persist-credentials: false - - - name: Check for file changes - uses: dorny/paths-filter@0bc4621a3135347011ad047f9ecf449bf72ce2bd # v3.0.0 - id: changes - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - - name: Add frontend label - uses: getsentry/action-add-labels@54d0cba498c1eaf8bd34985d715504d1b6e2935f - if: steps.changes.outputs.frontend_all == 'true' - with: - labels: 'Scope: Frontend' - - - name: Add backend label - uses: getsentry/action-add-labels@54d0cba498c1eaf8bd34985d715504d1b6e2935f - if: steps.changes.outputs.backend_src == 'true' - with: - labels: 'Scope: Backend' - - - name: Find previous frontend/backend warning comment - uses: peter-evans/find-comment@a54c31d7fa095754bfef525c0c8e5e5674c4b4b1 # v2.4.0 - id: fc - with: - issue-number: ${{ github.event.pull_request.number }} - comment-author: 'github-actions[bot]' - body-includes: '' - - - name: Add frontend/backend warning comment - uses: peter-evans/create-or-update-comment@b95e16d2859ad843a14218d1028da5b2c4cbc4b4 - if: > - steps.changes.outputs.frontend_all == 'true' && - steps.changes.outputs.backend_src == 'true' && - steps.fc.outputs.comment-id == 0 - with: - issue-number: ${{ github.event.pull_request.number }} - body: > - - - 🚨 **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](https://app.slack.com/client/T024ZCV9U/CTJL7358X). diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml deleted file mode 100644 index bd0df9cd60adb0..00000000000000 --- a/.github/workflows/lock.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: 'lock closed issues/PRs' -on: - schedule: - - cron: '* */12 * * *' - workflow_dispatch: -jobs: - lock: - runs-on: ubuntu-latest - steps: - - uses: dessant/lock-threads@be8aa5be94131386884a6da4189effda9b14aa21 # v4.0.1 - with: - github-token: ${{ github.token }} - issue-inactive-days: 15 - issue-lock-reason: '' - pr-inactive-days: 15 - pr-lock-reason: '' diff --git a/.github/workflows/meta-deploys-detect-change-type.yml b/.github/workflows/meta-deploys-detect-change-type.yml deleted file mode 100644 index 4cc98d2375c34f..00000000000000 --- a/.github/workflows/meta-deploys-detect-change-type.yml +++ /dev/null @@ -1,33 +0,0 @@ -# Add a GitHub Check to commits in "master" that specifies the "type" of files that were changed -# ex: "only frontend", "only backed", or "fullstack" -name: meta(deploy) - -on: - push: - branches: - - master - -jobs: - files-changed: - name: detect what files changed - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Check for file changes - uses: dorny/paths-filter@0bc4621a3135347011ad047f9ecf449bf72ce2bd # v3.0.0 - id: changes - with: - list-files: shell - token: ${{ github.token }} - filters: .github/file-filters.yml - - - name: Create GitHub job - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 - with: - script: | - require(`${process.env.GITHUB_WORKSPACE}/.github/workflows/scripts/deploy`).updateChangeType({ - github, - context, - fileChanges: ${{ toJson(steps.changes.outputs) }} - }); diff --git a/.github/workflows/migrations-drift.yml b/.github/workflows/migrations-drift.yml deleted file mode 100644 index 901da1af353ca9..00000000000000 --- a/.github/workflows/migrations-drift.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: migrations-drift -on: - pull_request: - paths: ['src/sentry/**/migrations/**.py', '.github/workflows/migrations-drift.yml'] - -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -defaults: - run: - # the default default is: - # bash --noprofile --norc -eo pipefail {0} - shell: bash --noprofile --norc -eo pipefail -ux {0} - -jobs: - drift: - name: migration drift - runs-on: ubuntu-24.04 - timeout-minutes: 15 - - steps: - # Checkout master to run all merged migrations. - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - with: - ref: master - - - name: Setup sentry env - uses: ./.github/actions/setup-sentry - with: - mode: migrations - - - name: Apply migrations - env: - # This short circuits the create_default_projects post_upgrade hook - # which spawns taskworkers which will spin for 5 minutes on kafka - # not being up. We don't need the default project here as this is not local dev. - SENTRY_NO_CREATE_DEFAULT_PROJECT: 1 - run: make apply-migrations - - # Checkout the current ref - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - with: - clean: false - - - name: Apply migrations (again) - env: - SENTRY_NO_CREATE_DEFAULT_PROJECT: 1 - run: make apply-migrations - - - name: capture database schema before - run: docker exec sentry-postgres-1 bash -c 'pg_dumpall -U postgres -s' > schema-before - - - name: clear db - run: make drop-db create-db - - - name: squash migrations - run: python3 -um tools.migrations.squash - - - name: apply squashed migrations - env: - SENTRY_NO_CREATE_DEFAULT_PROJECT: 1 - run: make drop-db apply-migrations - - - name: capture database schema after - run: docker exec sentry-postgres-1 bash -c 'pg_dumpall -U postgres -s' > schema-after - - - name: compare schema - run: python3 -um tools.migrations.compare --color schema-before schema-after diff --git a/.github/workflows/migrations.yml b/.github/workflows/migrations.yml deleted file mode 100644 index 359057e28a2fde..00000000000000 --- a/.github/workflows/migrations.yml +++ /dev/null @@ -1,77 +0,0 @@ -name: migrations -on: pull_request - -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -defaults: - run: - # the default default is: - # bash --noprofile --norc -eo pipefail {0} - shell: bash --noprofile --norc -eo pipefail -ux {0} - -jobs: - did-migration-change: - name: check if any migration changes - runs-on: ubuntu-24.04 - timeout-minutes: 3 - # Map a step output to a job output - outputs: - added: ${{ steps.changes.outputs.migrations_added }} - modified: ${{ steps.changes.outputs.migrations_modified }} - steps: - - name: Checkout sentry - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Match migration files - uses: dorny/paths-filter@0bc4621a3135347011ad047f9ecf449bf72ce2bd # v3.0.0 - id: changes - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - sql: - name: Generate SQL - runs-on: ubuntu-24.04 - timeout-minutes: 8 - - needs: did-migration-change - if: needs.did-migration-change.outputs.added == 'true' - - steps: - # Checkout master to run all merged migrations. - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - with: - ref: master - - - name: Setup sentry env - uses: ./.github/actions/setup-sentry - with: - mode: migrations - - - name: Apply migrations - run: | - sentry upgrade --noinput - - # Checkout the current ref - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - with: - clean: false - - - name: Get changed migration files - id: file - run: | - echo 'added<> "$GITHUB_OUTPUT" - git diff --diff-filter=A --name-only origin/master HEAD -- 'src/sentry/*/migrations/*' 'src/sentry/migrations/*' ':!*/__init__.py' >> "$GITHUB_OUTPUT" - echo 'EOF' >> "$GITHUB_OUTPUT" - - - name: Generate SQL for migration - uses: getsentry/action-migrations@9f4400077fa0d5216d2f251d3228380e5a774d7d # v1.3.0 - env: - SENTRY_LOG_LEVEL: ERROR - with: - githubToken: ${{ secrets.GITHUB_TOKEN }} - migration: ${{ steps.file.outputs.added }} diff --git a/.github/workflows/openapi-diff.yml b/.github/workflows/openapi-diff.yml deleted file mode 100644 index 4eb4c5da25eb56..00000000000000 --- a/.github/workflows/openapi-diff.yml +++ /dev/null @@ -1,74 +0,0 @@ -name: openapi-diff -on: - pull_request: - -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -# hack for https://github.com/actions/cache/issues/810#issuecomment-1222550359 -env: - SEGMENT_DOWNLOAD_TIMEOUT_MINS: 3 - -jobs: - check-diff: - name: (Optional) Shows the difference between the prod and dev schema - runs-on: ubuntu-24.04 - timeout-minutes: 90 - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Check for python file changes - uses: dorny/paths-filter@0bc4621a3135347011ad047f9ecf449bf72ce2bd # v3.0.0 - id: changes - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - - name: Setup sentry env - uses: ./.github/actions/setup-sentry - with: - mode: migrations - if: steps.changes.outputs.api_docs == 'true' - - - name: Checkout getsentry/sentry-api-schema - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - if: steps.changes.outputs.api_docs == 'true' - with: - ref: 'main' - repository: getsentry/sentry-api-schema - path: sentry-api-schema - - - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4 - id: setup-node - with: - node-version-file: '.node-version' - - - uses: pnpm/action-setup@36de12bed180fa130ed56a35e7344f2fa7a820ab # v4 - - - name: Build OpenAPI Derefed JSON - if: steps.changes.outputs.api_docs == 'true' - run: | - make build-api-docs - - - name: Compare OpenAPI Derefed JSON - if: steps.changes.outputs.api_docs == 'true' - run: | - npx json-diff@0.5.4 --color sentry-api-schema/openapi-derefed.json tests/apidocs/openapi-derefed.json - - - name: Dump RPC schema for new version - id: newschema - if: steps.changes.outputs.api_docs == 'true' - run: | - mkdir schemas - sentry rpcschema > rpc_method_schema.json - - - name: Output RPC schema comparison - uses: oasdiff/oasdiff-action/breaking@a2ff6682b27d175162a74c09ace8771bd3d512f8 # A few commits after v0.0.19 to get fixes - if: steps.changes.outputs.api_docs == 'true' - with: - base: sentry-api-schema/rpc_method_schema.json - revision: ./rpc_method_schema.json - fail-on: WARN diff --git a/.github/workflows/openapi.yml b/.github/workflows/openapi.yml deleted file mode 100644 index 4e673f899e191f..00000000000000 --- a/.github/workflows/openapi.yml +++ /dev/null @@ -1,80 +0,0 @@ -name: openapi -on: - push: - branches: - - master - -# hack for https://github.com/actions/cache/issues/810#issuecomment-1222550359 -env: - SEGMENT_DOWNLOAD_TIMEOUT_MINS: 3 - -jobs: - build_and_deref_json: - runs-on: ubuntu-24.04 - timeout-minutes: 90 - steps: - - name: Getsentry Token - id: getsentry - uses: getsentry/action-github-app-token@d4b5da6c5e37703f8c3b3e43abb5705b46e159cc # v3.0.0 - with: - app_id: ${{ vars.SENTRY_INTERNAL_APP_ID }} - private_key: ${{ secrets.SENTRY_INTERNAL_APP_PRIVATE_KEY }} - - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Check for python file changes - uses: dorny/paths-filter@0bc4621a3135347011ad047f9ecf449bf72ce2bd # v3.0.0 - id: changes - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - - name: Setup sentry env - uses: ./.github/actions/setup-sentry - with: - mode: migrations - if: steps.changes.outputs.api_docs == 'true' - - - name: Checkout getsentry/sentry-api-schema - if: steps.changes.outputs.api_docs == 'true' - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - with: - ref: 'main' - repository: getsentry/sentry-api-schema - path: sentry-api-schema - token: ${{ steps.getsentry.outputs.token }} - - - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4 - if: steps.changes.outputs.api_docs == 'true' - id: setup-node - with: - node-version-file: '.node-version' - - - uses: pnpm/action-setup@36de12bed180fa130ed56a35e7344f2fa7a820ab # v4 - - - name: Build OpenAPI Derefed JSON - if: steps.changes.outputs.api_docs == 'true' - run: | - make build-api-docs - - - name: Build RPC method schema - if: steps.changes.outputs.api_docs == 'true' - run: | - sentry rpcschema > rpc_method_schema.json - - - name: Copy artifacts into getsentry/sentry-api-schema - if: steps.changes.outputs.api_docs == 'true' - run: | - cp tests/apidocs/openapi-derefed.json sentry-api-schema - cp src/sentry/apidocs/api_ownership_stats_dont_modify.json sentry-api-schema - cp rpc_method_schema.json sentry-api-schema - - - name: Git Commit & Push - uses: stefanzweifel/git-auto-commit-action@0049e3fa4059ca715255fbbcb7dea4516f02ce0a # v4.15.3 - if: steps.changes.outputs.api_docs == 'true' - with: - repository: sentry-api-schema - branch: main - commit_message: Generated - commit_user_email: bot@getsentry.com - commit_user_name: openapi-getsentry-bot diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml deleted file mode 100644 index 9f2cc202a60667..00000000000000 --- a/.github/workflows/pre-commit.yml +++ /dev/null @@ -1,106 +0,0 @@ -name: pre-commit - -on: - push: - branches: - - master - pull_request: - -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -defaults: - run: - # the default default is: - # bash --noprofile --norc -eo pipefail {0} - shell: bash --noprofile --norc -eo pipefail -ux {0} - -# hack for https://github.com/actions/cache/issues/810#issuecomment-1222550359 -env: - SEGMENT_DOWNLOAD_TIMEOUT_MINS: 3 - # workaround: secrets cannot be directly referenced in `if` - # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-using-secrets - SECRET_ACCESS: ${{toJSON(secrets.SENTRY_INTERNAL_APP_PRIVATE_KEY != null)}} - -jobs: - lint: - name: pre-commit lint - runs-on: ubuntu-24.04 - timeout-minutes: 10 - steps: - - # get a non-default github token so that any changes are verified by CI - if: env.SECRET_ACCESS == 'true' - uses: getsentry/action-github-app-token@d4b5da6c5e37703f8c3b3e43abb5705b46e159cc # v3.0.0 - id: token - with: - app_id: ${{ vars.SENTRY_INTERNAL_APP_ID }} - private_key: ${{ secrets.SENTRY_INTERNAL_APP_PRIVATE_KEY }} - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - name: Get changed files - id: changes - uses: dorny/paths-filter@0bc4621a3135347011ad047f9ecf449bf72ce2bd # v3.0.0 - with: - # Enable listing of files matching each filter. - # Paths to files will be available in `${FILTER_NAME}_files` output variable. - list-files: json - - # It doesn't make sense to lint deleted files. - # Therefore we specify we are only interested in added or modified files. - filters: | - all: - - added|modified: '**/*' - - - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4 - id: setup-node - with: - node-version-file: '.node-version' - - - uses: pnpm/action-setup@36de12bed180fa130ed56a35e7344f2fa7a820ab # v4 - - - name: node_modules cache - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 - id: nodemodulescache - with: - path: node_modules - key: ${{ runner.os }}-node-modules-${{ hashFiles('pnpm-lock.yaml', 'api-docs/pnpm-lock.yaml', '.node-version') }} - - - name: Install Javascript Dependencies - if: steps.nodemodulescache.outputs.cache-hit != 'true' - run: pnpm install --frozen-lockfile - - - uses: astral-sh/setup-uv@884ad927a57e558e7a70b92f2bccf9198a4be546 # v6 - with: - version: '0.8.2' - # we just cache the venv-dir directly in action-setup-venv - enable-cache: false - - - uses: getsentry/action-setup-venv@5a80476d175edf56cb205b08bc58986fa99d1725 # v3.2.0 - with: - cache-dependency-path: uv.lock - install-cmd: uv sync --only-dev --frozen --active - - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 - with: - path: ~/.cache/pre-commit - key: cache-epoch-1|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml') }} - - name: Setup pre-commit - # We don't need pre-commit install --install-hooks since we're just interested - # in running the hooks. - run: | - pre-commit install-hooks - - - name: Run pre-commit on PR commits - run: | - jq '.[]' --raw-output <<< '${{steps.changes.outputs.all_files}}' | - # Run pre-commit to lint and format check files that were changed (but not deleted) compared to master. - xargs pre-commit run --files - - - name: Apply any pre-commit fixed files - # note: this runs "always" or else it's skipped when pre-commit fails - if: env.SECRET_ACCESS == 'true' && startsWith(github.ref, 'refs/pull') && always() - uses: getsentry/action-github-commit@31f6706ca1a7b9ad6d22c1b07bf3a92eabb05632 # v2.0.0 - with: - github-token: ${{ steps.token.outputs.token }} - message: ':hammer_and_wrench: apply pre-commit fixes' diff --git a/.github/workflows/react-to-product-owners-yml-changes.yml b/.github/workflows/react-to-product-owners-yml-changes.yml deleted file mode 100644 index 7fe3a5dcce70a4..00000000000000 --- a/.github/workflows/react-to-product-owners-yml-changes.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: React to product-owners.yml changes -on: - # This could be run manually, but the general expectation is that this fires - # from GHA in getsentry/security-as-code on changes there. - - workflow_dispatch: -jobs: - release: - runs-on: ubuntu-latest - name: React to product-owners.yml changes - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - uses: astral-sh/setup-uv@884ad927a57e558e7a70b92f2bccf9198a4be546 # v6 - with: - version: '0.8.2' - # we just cache the venv-dir directly in action-setup-venv - enable-cache: false - - - uses: getsentry/action-setup-venv@5a80476d175edf56cb205b08bc58986fa99d1725 # v3.2.0 - with: - cache-dependency-path: uv.lock - install-cmd: echo - - - name: React to product-owners.yml changes - shell: bash - env: - GITHUB_TOKEN: ${{ secrets.BUMP_SENTRY_TOKEN }} - COMMITTER_NAME: getsentry-bot - COMMITTER_EMAIL: bot@sentry.io - run: | - uv export --only-dev --no-hashes --no-annotate --no-header \ - | grep '^pyyaml' | sed -E 's/ ;.*//' \ - | xargs uv pip install --index-url 'https://pypi.devinfra.sentry.io/simple' - - ./bin/react-to-product-owners-yml-changes.sh diff --git a/.github/workflows/release-ghcr-version-tag.yml b/.github/workflows/release-ghcr-version-tag.yml deleted file mode 100644 index 3988c8dfa8df9e..00000000000000 --- a/.github/workflows/release-ghcr-version-tag.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Release GHCR Versioned Image - -on: - release: - types: [prereleased, released] - -jobs: - release-ghcr-version-tag: - runs-on: ubuntu-latest - steps: - - name: Log in to GitHub Container Registry - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Tag release version - run: | - docker buildx imagetools create --tag \ - ghcr.io/getsentry/sentry:${{ github.ref_name }} \ - ghcr.io/getsentry/sentry:${{ github.sha }} - - - name: Tag latest version - run: | - docker buildx imagetools create --tag \ - ghcr.io/getsentry/sentry:latest \ - ghcr.io/getsentry/sentry:${{ github.sha }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 406fed5714067e..00000000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Release -on: - workflow_dispatch: - inputs: - version: - description: Version to release (optional) - required: false - force: - description: Force a release even when there are release-blockers (optional) - required: false - schedule: - # We want the release to be at 9-10am Pacific Time - # We also want it to be 1 hour before the self-hosted release - - cron: '0 17 15 * *' -jobs: - release: - runs-on: ubuntu-latest - name: 'Release a new version' - steps: - - name: Get auth token - id: token - uses: actions/create-github-app-token@5d869da34e18e7287c1daad50e0b8ea0f506ce69 # v1.11.0 - with: - app-id: ${{ vars.SENTRY_RELEASE_BOT_CLIENT_ID }} - private-key: ${{ secrets.SENTRY_RELEASE_BOT_PRIVATE_KEY }} - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - with: - token: ${{ steps.token.outputs.token }} - fetch-depth: 0 - - name: Prepare release - uses: getsentry/action-prepare-release@d2cc2db3db92bc5b79a90c316f588f2b13626a2b # v1.5.6 - env: - GITHUB_TOKEN: ${{ steps.token.outputs.token }} - with: - version: ${{ github.event.inputs.version }} - force: ${{ github.event.inputs.force }} - calver: true diff --git a/.github/workflows/scripts/calculate-backend-test-shards.py b/.github/workflows/scripts/calculate-backend-test-shards.py deleted file mode 100755 index fca159736127d4..00000000000000 --- a/.github/workflows/scripts/calculate-backend-test-shards.py +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env python3 -import json -import math -import os -import re -import subprocess -import sys - -TESTS_PER_SHARD = 1200 -MIN_SHARDS = 1 -MAX_SHARDS = 22 -DEFAULT_SHARDS = 22 - -PYTEST_ARGS = [ - "pytest", - "--collect-only", - "--quiet", - "tests", - "--ignore=tests/acceptance", - "--ignore=tests/apidocs", - "--ignore=tests/js", - "--ignore=tests/tools", -] - - -def collect_test_count(): - try: - result = subprocess.run( - PYTEST_ARGS, - capture_output=True, - text=True, - check=False, - ) - - # Parse output for "N tests collected" - # Format: "27000 tests collected in 18.53s" - match = re.search(r"(\d+) tests? collected", result.stdout + result.stderr) - if match: - count = int(match.group(1)) - print(f"Collected {count} tests", file=sys.stderr) - return count - - # If no match, check if pytest failed - if result.returncode != 0: - print( - f"Pytest collection failed (exit {result.returncode})", - file=sys.stderr, - ) - print(result.stderr, file=sys.stderr) - return None - - print("No tests collected", file=sys.stderr) - return 0 - except Exception as e: - print(f"Error collecting tests: {e}", file=sys.stderr) - return None - - -def calculate_shards(test_count): - if test_count is None: - print(f"Using default shard count: {DEFAULT_SHARDS}", file=sys.stderr) - return DEFAULT_SHARDS - - if test_count == 0: - print(f"No tests to run, using minimum: {MIN_SHARDS}", file=sys.stderr) - return MIN_SHARDS - - calculated = math.ceil(test_count / TESTS_PER_SHARD) - bounded = max(MIN_SHARDS, min(calculated, MAX_SHARDS)) - - if bounded != calculated: - print( - f"Calculated {calculated} shards, bounded to {bounded}", - file=sys.stderr, - ) - else: - print( - f"Calculated {bounded} shards ({test_count} tests Ãˇ {TESTS_PER_SHARD})", - file=sys.stderr, - ) - - return bounded - - -def main(): - test_count = collect_test_count() - shard_count = calculate_shards(test_count) - # Generate a JSON array of shard indices [0, 1, 2, ..., shard_count-1] - shard_indices = json.dumps(list(range(shard_count))) - - github_output = os.getenv("GITHUB_OUTPUT") - if github_output: - with open(github_output, "a") as f: - f.write("\n") - f.write(f"shard-count={shard_count}\n") - f.write(f"shard-indices={shard_indices}\n") - - print(f"shard-count={shard_count}") - print(f"shard-indices={shard_indices}") - - return 0 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/.github/workflows/scripts/pytest-args-wrapper.py b/.github/workflows/scripts/pytest-args-wrapper.py new file mode 100644 index 00000000000000..ab30544997d22a --- /dev/null +++ b/.github/workflows/scripts/pytest-args-wrapper.py @@ -0,0 +1,17 @@ +# we need this so we don't exceed ARGS_MAX on linux/macos +# trying to pass large strings directly to pytest cli + +import sys + +import pytest + +if len(sys.argv) < 2: + print("Usage: pytest-args-wrapper.py [pytest args...]") + sys.exit(1) + +testnodeids_file = sys.argv[1] +with open(testnodeids_file) as f: + nodeids = [line.strip() for line in f.readlines() if line.strip()] + +pytest_args = sys.argv[2:] +sys.exit(pytest.main(pytest_args + nodeids)) diff --git a/.github/workflows/scripts/select-tests.py b/.github/workflows/scripts/select-tests.py new file mode 100644 index 00000000000000..bdd328e3a25345 --- /dev/null +++ b/.github/workflows/scripts/select-tests.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 +import json +import math +import os +import sqlite3 +import subprocess +import sys + +TESTS_PER_SHARD = 1200 +MIN_SHARDS = 1 +MAX_SHARDS = 22 +DEFAULT_SHARDS = 22 + +IGNORED_FILES = { + # the pytest code itself is not part of the test suite but will be referenced by most tests + "sentry/testutils/pytest/sentry.py", +} + +IGNORED_NODEIDS = ("tests/sentry/test_wsgi.py::test_wsgi_init",) + + +def executed_lines(bitblob: bytes) -> set[int]: + """ + Returns a set of executed line numbers for a coverage bitblob. + Line numbers are 1-based. + """ + lines = set() + for byte_index, byte in enumerate(bitblob): + for bit_index in range(8): + if byte & (1 << bit_index): + lines.add(byte_index * 8 + bit_index) + return lines + + +def select_tests(coverage_db_path: str, changed_files: set[str]): + test_nodeids = set() + + with sqlite3.connect(coverage_db_path) as conn: + cursor = conn.cursor() + + file_paths = [ + f"/home/runner/work/sentry/sentry/{file_path}" + for file_path in changed_files - IGNORED_FILES + ] + + placeholders = ",".join("?" for _ in file_paths) + + cursor.execute( + f""" + SELECT c.context, lb.numbits + FROM line_bits lb + JOIN file f ON lb.file_id = f.id + JOIN context c ON lb.context_id = c.id + WHERE f.path IN ({placeholders}) + AND c.context != '' + """, + file_paths, + ) + + for test_context, bitblob in cursor.fetchall(): + if not test_context.endswith("|run"): + # for now we're ignoring |setup and |teardown + continue + + lines = executed_lines(bitblob) + if not lines: + # test wasn't executed + continue + + test_nodeid = test_context.partition("|")[0] + if test_nodeid in IGNORED_NODEIDS: + continue + + test_nodeids.add(test_nodeid) + + return test_nodeids + + +def calculate_shards(test_count): + if test_count is None: + print(f"Using default shard count: {DEFAULT_SHARDS}", file=sys.stderr) + return DEFAULT_SHARDS + + if test_count == 0: + print(f"No tests to run, using minimum: {MIN_SHARDS}", file=sys.stderr) + return MIN_SHARDS + + calculated = math.ceil(test_count / TESTS_PER_SHARD) + bounded = max(MIN_SHARDS, min(calculated, MAX_SHARDS)) + + if bounded != calculated: + print( + f"Calculated {calculated} shards, bounded to {bounded}", + ) + else: + print( + f"Calculated {bounded} shards ({test_count} tests Ãˇ {TESTS_PER_SHARD})", + ) + + return bounded + + +def main(): + COVERAGE_DB_PATH = os.environ["COVERAGE_DB_PATH"] + GITHUB_PR_BASE_REF = os.environ["GITHUB_PR_BASE_REF"] + + changed_files = ( + subprocess.check_output( + ( + "git", + "diff", + "--name-only", + f"{GITHUB_PR_BASE_REF}...HEAD", + ), + text=True, + ) + .strip() + .splitlines() + ) + + print(f"changed files:\n{'\n'.join(changed_files)}\n") + + selected_tests = select_tests(COVERAGE_DB_PATH, set(changed_files)) + selected_tests_str = "\n".join(selected_tests) + + with open("selected-tests", "w") as f: + f.write(selected_tests_str) + + print(f"selected {len(selected_tests)} tests:\n{selected_tests_str}\n\n") + + shard_count = calculate_shards(len(selected_tests)) + shard_indices = json.dumps(list(range(shard_count))) + + github_output = os.getenv("GITHUB_OUTPUT") + if github_output: + with open(github_output, "a") as f: + f.write("\n") + f.write(f"shard-count={shard_count}\n") + f.write(f"shard-indices={shard_indices}\n") + + print(f"shard-count={shard_count}") + print(f"shard-indices={shard_indices}") + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/.github/workflows/self-hosted.yml b/.github/workflows/self-hosted.yml deleted file mode 100644 index 4ebffd78cd84f4..00000000000000 --- a/.github/workflows/self-hosted.yml +++ /dev/null @@ -1,118 +0,0 @@ -name: self-hosted -on: - push: - branches: - - master - - releases/** - pull_request: - -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -# hack for https://github.com/actions/cache/issues/810#issuecomment-1222550359 -env: - SEGMENT_DOWNLOAD_TIMEOUT_MINS: 3 - NODE_OPTIONS: '--max-old-space-size=4096' - -jobs: - self-hosted: - runs-on: ${{ matrix.os }} - strategy: - matrix: - include: - - os: ubuntu-24.04 - platform: amd64 - - os: ubuntu-24.04-arm - platform: arm64 - name: self-hosted-${{ matrix.os }}-${{ matrix.platform }} - permissions: - contents: read - packages: write - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4 - id: setup-node - with: - node-version-file: '.node-version' - - - uses: pnpm/action-setup@36de12bed180fa130ed56a35e7344f2fa7a820ab # v4 - - - uses: astral-sh/setup-uv@884ad927a57e558e7a70b92f2bccf9198a4be546 # v6 - with: - version: '0.8.2' - - - uses: getsentry/action-setup-venv@5a80476d175edf56cb205b08bc58986fa99d1725 # v3.2.0 - with: - cache-dependency-path: uv.lock - # sentry.build.main has no external dependencies; - # this is only to set up the venv with the correct - # python version - install-cmd: echo - - - name: Step configurations - id: config - run: | - echo "webpack-path=.webpack_cache" >> "$GITHUB_OUTPUT" - echo "WEBPACK_CACHE_PATH=.webpack_cache" >> "$GITHUB_ENV" - - - name: webpack cache - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 - with: - path: ${{ steps.config.outputs.webpack-path }} - key: ${{ runner.os }}-self-hosted-webpack-cache-${{ hashFiles('webpack.config.ts') }} - - - name: node_modules cache - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 - id: nodemodulescache - with: - path: node_modules - key: ${{ runner.os }}-self-hosted-node-modules-${{ hashFiles('pnpm-lock.yaml', '.node-version') }} - - - name: Install Javascript Dependencies - if: steps.nodemodulescache.outputs.cache-hit != 'true' - run: pnpm install --frozen-lockfile --production - - - run: | - python3 -m tools.fast_editable --path . - python3 -m sentry.build.main - - - uses: getsentry/action-build-and-push-images@07a1c835f7a78e0f438fc766cc6024ed0ca1bf03 - with: - image_name: 'sentry' - platforms: linux/${{ matrix.platform }} - dockerfile_path: 'self-hosted/Dockerfile' - tag_suffix: -${{ matrix.platform }} - build_args: | - SOURCE_COMMIT=${{ github.sha }} - TARGETARCH=${{ matrix.platform }} - ghcr: true - tag_nightly: false - tag_latest: false - - assemble: - needs: [self-hosted] - if: ${{ (github.ref_name == 'master' || startsWith(github.ref_name, 'releases/')) && github.event_name != 'pull_request' }} - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - steps: - - name: Docker Login - run: docker login --username '${{ github.actor }}' --password-stdin ghcr.io <<< "$GHCR_TOKEN" - env: - GHCR_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 - - - name: Create multiplatform manifests - run: | - docker buildx imagetools create \ - --tag ghcr.io/getsentry/sentry:${{ github.sha }} \ - --tag ghcr.io/getsentry/sentry:nightly \ - ghcr.io/getsentry/sentry:${{ github.sha }}-amd64 \ - ghcr.io/getsentry/sentry:${{ github.sha }}-arm64 diff --git a/.github/workflows/sentry-pull-request-bot.yml b/.github/workflows/sentry-pull-request-bot.yml deleted file mode 100644 index 4da9362d566a11..00000000000000 --- a/.github/workflows/sentry-pull-request-bot.yml +++ /dev/null @@ -1,74 +0,0 @@ -name: sentry pull request bot - -# Note this event happens on Issue comments AND PR comments, -# we make sure that we only respond to PR comments. -on: - issue_comment: - types: [created, edited] - pull_request: - types: [opened, edited] - -jobs: - # TODO(billy): Move this into an external action as we add more functionality - test-getsentry: - name: test getsentry - runs-on: ubuntu-24.04 - - # Ensure this bot only responds for pull requests and only for the main repository - if: >- - (github.event.issue.pull_request.url != '' || github.event.pull_request.id != '') && - (contains(github.event.comment.body, '#test-getsentry') || contains(github.event.pull_request.body, '#test-getsentry')) && - github.repository == 'getsentry/sentry' - - steps: - - name: Check getsentry membership - id: org - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 - with: - script: | - try { - const result = await github.rest.orgs.checkMembershipForUser({ - org: 'getsentry', - username: context.payload.sender.login, - }) - return result.status == 204; - } catch { - return false; - } - - - name: Fetch getsentry token - if: steps.org.outputs.result == 'true' - id: getsentry - uses: getsentry/action-github-app-token@d4b5da6c5e37703f8c3b3e43abb5705b46e159cc # v3.0.0 - with: - app_id: ${{ vars.SENTRY_INTERNAL_APP_ID }} - private_key: ${{ secrets.SENTRY_INTERNAL_APP_PRIVATE_KEY }} - - - name: Wait for PR merge commit - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 - id: mergecommit - with: - github-token: ${{ steps.getsentry.outputs.token }} - script: | - require(`${process.env.GITHUB_WORKSPACE}/.github/workflows/scripts/wait-for-merge-commit`).waitForMergeCommit({ - github, - context, - core, - }); - - - name: Dispatch getsentry tests - if: steps.org.outputs.result == 'true' - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 - with: - github-token: ${{ steps.getsentry.outputs.token }} - script: | - github.rest.actions.createWorkflowDispatch({ - owner: 'getsentry', - repo: 'getsentry', - workflow_id: 'acceptance.yml', - ref: 'master', - inputs: { - 'sentry-sha': '${{ steps.mergecommit.outputs.mergeCommitSha }}', - 'sentry-pr-sha': '${{ github.event.pull_request.head.sha }}', - } - }) diff --git a/.github/workflows/shuffle-tests.yml b/.github/workflows/shuffle-tests.yml deleted file mode 100644 index 9858c4ebed8ad3..00000000000000 --- a/.github/workflows/shuffle-tests.yml +++ /dev/null @@ -1,78 +0,0 @@ -name: shuffle-tests - -on: - # Allow manually running - workflow_dispatch: - inputs: - per-test-coverage: - description: Whether to get per-test coverage (uses ./github/workflows/codecov_per_test_coverage.yml) - required: true - default: 'true' - seed: - description: The seed for the test ordering - required: false - - # Run once a day - schedule: - - cron: '0 1 * * *' - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -env: - SENTRY_SHUFFLE_TESTS: true -jobs: - backend-test: - name: run backend tests - runs-on: ubuntu-24.04 - timeout-minutes: 90 - permissions: - contents: read - id-token: write - strategy: - # This helps not having to run multiple jobs because one fails, thus, reducing resource usage - # and reducing the risk that one of many runs would turn red again (read: intermittent tests) - fail-fast: false - matrix: - # XXX: When updating this, make sure you also update MATRIX_INSTANCE_TOTAL. - instance: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - - env: - # XXX: `MATRIX_INSTANCE_TOTAL` must be hardcoded to the length of `strategy.matrix.instance`. - MATRIX_INSTANCE_TOTAL: 11 - - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Setup sentry env - uses: ./.github/actions/setup-sentry - id: setup - with: - mode: backend-ci - env: - SENTRY_SHUFFLE_TESTS_SEED: ${{ inputs.seed }} - - - name: Run backend test (${{ steps.setup.outputs.matrix-instance-number }} of ${{ steps.setup.outputs.matrix-instance-total }}) - run: | - make test-python-ci - env: - SENTRY_SHUFFLE_TESTS_SEED: ${{ inputs.seed }} - - - name: Inspect failure - if: failure() - run: | - if command -v devservices; then - devservices logs - fi - - - name: Collect test data - uses: ./.github/actions/collect-test-data - if: ${{ !cancelled() }} - with: - artifact_path: .artifacts/pytest.json - gcs_bucket: ${{ secrets.COLLECT_TEST_DATA_GCS_BUCKET }} - gcp_project_id: ${{ secrets.COLLECT_TEST_DATA_GCP_PROJECT_ID }} - workload_identity_provider: ${{ secrets.SENTRY_GCP_DEV_WORKLOAD_IDENTITY_POOL }} - service_account_email: ${{ secrets.COLLECT_TEST_DATA_SERVICE_ACCOUNT_EMAIL }} - matrix_instance_number: ${{ steps.setup.outputs.matrix-instance-number }} diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml deleted file mode 100644 index 77c947a1faff49..00000000000000 --- a/.github/workflows/sync-labels.yml +++ /dev/null @@ -1,78 +0,0 @@ -name: meta(labels) -on: - pull_request: - paths: - - .github/labels.yml - push: - branches: - - master - paths: - - .github/labels.yml - -# hack for https://github.com/actions/cache/issues/810#issuecomment-1222550359 -env: - SEGMENT_DOWNLOAD_TIMEOUT_MINS: 3 - -jobs: - sync: - name: syncs repository labels - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4 - id: setup-node - with: - node-version-file: '.node-version' - - - uses: pnpm/action-setup@36de12bed180fa130ed56a35e7344f2fa7a820ab # v4 - - - name: Install github-label-sync - run: pnpm add github-label-sync@2.2.0 - - - name: Run github-label-sync - run: | - pnpm exec github-label-sync \ - --access-token ${{ secrets.GITHUB_TOKEN }} \ - --labels .github/labels.yml \ - ${{ github.event_name == 'pull_request' && '--dry-run' || '' }} \ - ${{ github.repository }} \ - 2>&1 | tee sync-report.txt - - - name: Read sync output into variable - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 - if: github.event_name == 'pull_request' - id: github-label-sync - with: - script: | - const fs = require('fs'); - return fs.readFileSync('sync-report.txt','utf8').toString(); - result-encoding: string - - - name: Find previous dry-run comment - uses: peter-evans/find-comment@a54c31d7fa095754bfef525c0c8e5e5674c4b4b1 # v2.4.0 - if: github.event_name == 'pull_request' - id: fc - with: - issue-number: ${{ github.event.pull_request.number }} - comment-author: 'github-actions[bot]' - body-includes: '' - - - name: Add or update dry-run comment - uses: peter-evans/create-or-update-comment@b95e16d2859ad843a14218d1028da5b2c4cbc4b4 - if: github.event_name == 'pull_request' - with: - issue-number: ${{ github.event.pull_request.number }} - comment-id: ${{ steps.fc.outputs.comment-id }} - edit-mode: replace - body: > - - - 🏷 The following changes will be made to the repository labels - - ``` - ${{ steps.github-label-sync.outputs.result }} - ``` diff --git a/src/sentry/preprod/size_analysis/compare.py b/src/sentry/preprod/size_analysis/compare.py index 42d9b309236bdd..42960bb916283d 100644 --- a/src/sentry/preprod/size_analysis/compare.py +++ b/src/sentry/preprod/size_analysis/compare.py @@ -28,6 +28,8 @@ logger = logging.getLogger(__name__) +# hello + def compare_size_analysis( head_size_analysis: PreprodArtifactSizeMetrics,