src-auth-perms-sync 0.3.1__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/.gitignore +3 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/AGENTS.md +35 -11
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/PKG-INFO +1 -1
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/dev/TODO.md +28 -9
- src_auth_perms_sync-0.3.1/dev/memory-efficiency.md → src_auth_perms_sync-0.4.0/dev/engineering-requests.md +70 -180
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/dev/hooks/pre-commit +1 -5
- src_auth_perms_sync-0.4.0/dev/memory-efficiency.md +177 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/cli.py +63 -25
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/permissions/apply.py +18 -16
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/permissions/command.py +9 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/permissions/snapshot.py +72 -19
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/permissions/sourcegraph.py +20 -4
- src_auth_perms_sync-0.4.0/tests/README.md +146 -0
- src_auth_perms_sync-0.4.0/tests/__init__.py +12 -0
- src_auth_perms_sync-0.4.0/tests/e2e/__init__.py +11 -0
- src_auth_perms_sync-0.4.0/tests/e2e/case_runner.py +796 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/add-users-by-email-and-list/after.json +85 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/add-users-by-email-and-list/before.json +80 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/add-users-by-email-and-list/maps.yaml +11 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/add-users-preserves-existing/after.json +84 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/add-users-preserves-existing/before.json +82 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/add-users-preserves-existing/maps.yaml +10 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/and-filters-intersect/after.json +103 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/and-filters-intersect/before.json +101 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/and-filters-intersect/maps.yaml +11 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/empty-maps-noop/before.json +48 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/empty-maps-noop/maps.yaml +1 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/full-overwrite-dry-run/before.json +90 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/full-overwrite-dry-run/maps.yaml +16 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/full-overwrite-removes-stale-grant/after.json +75 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/full-overwrite-removes-stale-grant/before.json +75 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/full-overwrite-removes-stale-grant/maps.yaml +9 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/full-overwrite-unions/after.json +91 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/full-overwrite-unions/before.json +90 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/full-overwrite-unions/maps.yaml +16 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/full-overwrite-with-backup/after.json +75 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/full-overwrite-with-backup/before.json +75 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/full-overwrite-with-backup/maps.yaml +9 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/get-full-snapshot/before.json +48 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/get-repos-without-explicit-perms/before.json +54 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/get-user-grants/before.json +48 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/invalid-bad-regex/before.json +48 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/invalid-bad-regex/maps.yaml +8 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/invalid-missing-repos-section/before.json +48 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/invalid-missing-repos-section/maps.yaml +5 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/invalid-restore-wrong-schema-version/before.json +48 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/invalid-restore-wrong-schema-version/snapshot.json +21 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/invalid-set-created-after-date/before.json +46 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/invalid-set-created-after-date/maps.yaml +8 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/invalid-set-repos-created-after-date/before.json +46 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/invalid-set-repos-created-after-date/maps.yaml +8 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/invalid-set-unknown-repo/before.json +46 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/invalid-set-unknown-repo/maps.yaml +8 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/invalid-set-unknown-user/before.json +46 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/invalid-set-unknown-user/maps.yaml +8 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/invalid-unknown-selector-field/before.json +48 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/invalid-unknown-selector-field/maps.yaml +8 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/match-provider-and-host-fields/after.json +142 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/match-provider-and-host-fields/before.json +136 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/match-provider-and-host-fields/maps.yaml +13 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/no-match-noop/before.json +48 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/no-match-noop/maps.yaml +8 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/regex-filters-scope/after.json +97 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/regex-filters-scope/before.json +91 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/regex-filters-scope/maps.yaml +8 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/restore-applies-snapshot/after.json +70 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/restore-applies-snapshot/before.json +70 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/restore-applies-snapshot/snapshot.json +30 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/restore-dry-run-noop/before.json +70 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/restore-dry-run-noop/snapshot.json +30 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/restore-missing-file/before.json +49 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/saml-group-filter/after.json +140 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/saml-group-filter/before.json +136 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/saml-group-filter/maps.yaml +9 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/saml-group-live/after.json +181 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/saml-group-live/before.json +175 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/saml-group-live/maps.yaml +10 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-created-after-sync-saml-orgs-dry-run/maps.yaml +8 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-created-after-temp-user/after.json +42 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-created-after-temp-user/before.json +40 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-created-after-temp-user/maps.yaml +8 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-full-sync-saml-orgs-dry-run/maps.yaml +8 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-repos-created-after/after.json +70 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-repos-created-after/before.json +67 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-repos-created-after/maps.yaml +10 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-repos-created-after-noop/before.json +49 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-repos-created-after-noop/maps.yaml +8 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-repos-created-after-sync-saml-orgs-dry-run/maps.yaml +8 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-repos-filter/after.json +72 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-repos-filter/before.json +71 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-repos-filter/maps.yaml +10 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-repos-sync-saml-orgs-dry-run/maps.yaml +8 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-repos-without-explicit-perms/after.json +72 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-repos-without-explicit-perms/before.json +69 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-repos-without-explicit-perms/maps.yaml +10 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-repos-without-perms-sync-saml-orgs-dry-run/maps.yaml +8 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-users-created-after/after.json +85 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-users-created-after/before.json +80 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-users-created-after/maps.yaml +9 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-users-created-after-noop/before.json +49 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-users-created-after-noop/maps.yaml +8 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-users-sync-saml-orgs-dry-run/maps.yaml +8 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-users-without-explicit-perms/after.json +98 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-users-without-explicit-perms/before.json +95 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-users-without-explicit-perms/maps.yaml +10 -0
- src_auth_perms_sync-0.4.0/tests/e2e/fixtures/set-users-without-perms-sync-saml-orgs-dry-run/maps.yaml +8 -0
- src_auth_perms_sync-0.4.0/tests/e2e/test_local_cases.py +94 -0
- src_auth_perms_sync-0.4.0/tests/integration/__init__.py +11 -0
- src_auth_perms_sync-0.4.0/tests/run.py +3084 -0
- src_auth_perms_sync-0.4.0/tests/setup.py +419 -0
- src_auth_perms_sync-0.4.0/tests/tests.yaml +922 -0
- src_auth_perms_sync-0.4.0/tests/unit/__init__.py +11 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/tests/unit/test_cli_config.py +55 -8
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/tests/unit/test_permissions_sourcegraph.py +36 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/tests/unit/test_snapshot.py +127 -0
- src_auth_perms_sync-0.3.1/dev/test-end-to-end.py +0 -3047
- src_auth_perms_sync-0.3.1/tests/__init__.py +0 -1
- src_auth_perms_sync-0.3.1/tests/integration/__init__.py +0 -1
- src_auth_perms_sync-0.3.1/tests/unit/__init__.py +0 -1
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/.env.example +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/.github/CODEOWNERS +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/.github/workflows/ci.yml +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/.github/workflows/release.yml +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/.github/workflows/validate.yml +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/.markdownlint-cli2.yaml +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/.python-version +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/LICENSE +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/README.md +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/SECURITY.md +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/dev/audit-dead-code.md +0 -0
- {src_auth_perms_sync-0.3.1/dev → src_auth_perms_sync-0.4.0/dev/memory-analysis}/mapping-efficiency.md +0 -0
- {src_auth_perms_sync-0.3.1/dev → src_auth_perms_sync-0.4.0/dev/memory-analysis}/memory-efficiency-analyze.py +0 -0
- {src_auth_perms_sync-0.3.1/dev → src_auth_perms_sync-0.4.0/dev/memory-analysis}/memory-efficiency-generate.py +0 -0
- {src_auth_perms_sync-0.3.1/dev → src_auth_perms_sync-0.4.0/dev/memory-analysis}/memory-efficiency-monitor-sourcegraph.sh +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/dev/update-python-versions.md +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/maps-example.yaml +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/pyproject.toml +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/renovate.json +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/__init__.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/__main__.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/orgs/__init__.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/orgs/command.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/orgs/queries.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/orgs/sync.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/orgs/types.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/permissions/__init__.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/permissions/full_set.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/permissions/mapping.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/permissions/maps.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/permissions/queries.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/permissions/restore.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/permissions/types.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/permissions/workflow.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/shared/__init__.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/shared/backups.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/shared/queries.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/shared/run_context.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/shared/saml_groups.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/shared/site_config.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/shared/sourcegraph.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/src/src_auth_perms_sync/shared/types.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/tests/integration/test_cli_entrypoint.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/tests/unit/test_apply.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/tests/unit/test_backups.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/tests/unit/test_command_additive.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/tests/unit/test_maps.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/tests/unit/test_restore.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/tests/unit/test_saml_groups.py +0 -0
- {src_auth_perms_sync-0.3.1 → src_auth_perms_sync-0.4.0}/uv.lock +0 -0
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# AGENTS.md
|
|
2
2
|
|
|
3
|
+
## Reference materials
|
|
4
|
+
|
|
5
|
+
- GraphQL schema and database migrations (changes to SQL schema) are available in
|
|
6
|
+
<https://github.com/sourcegraph/artifacts>
|
|
7
|
+
|
|
3
8
|
## Linting
|
|
4
9
|
|
|
5
10
|
```bash
|
|
@@ -26,21 +31,40 @@ uv run src-auth-perms-sync --help
|
|
|
26
31
|
|
|
27
32
|
## Testing
|
|
28
33
|
|
|
29
|
-
|
|
34
|
+
All testing runs through one entrypoint: `tests/run.py`. Output goes to the
|
|
35
|
+
console and to a per-run log file under `logs/`. Each level runs only its
|
|
36
|
+
own checks.
|
|
30
37
|
|
|
31
38
|
```bash
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
39
|
+
# Fast, no network (also what the pre-commit hook runs):
|
|
40
|
+
# lint, format, pyright, unit + fixture tests, CLI rejection matrix,
|
|
41
|
+
# randomized permission invariants
|
|
42
|
+
uv run tests/run.py
|
|
43
|
+
|
|
44
|
+
# End-to-end runs against the .env test instance with independent GraphQL
|
|
45
|
+
# read-back verification, and a wheel install smoke test
|
|
46
|
+
uv run tests/run.py --live
|
|
47
|
+
|
|
48
|
+
# Run a subset: comma-delimited test names, substring match
|
|
49
|
+
uv run tests/run.py --live full-overwrite-unions
|
|
50
|
+
uv run tests/run.py --live wheel,baseline
|
|
51
|
+
|
|
52
|
+
# Repeated timed runs with Jaeger trace retention, RSS sampling,
|
|
53
|
+
# optional kubectl load monitoring, and baseline comparison
|
|
54
|
+
uv run tests/run.py --performance --repeat 3
|
|
55
|
+
uv run tests/run.py --performance --baseline-command "uvx src-auth-perms-sync@latest" \
|
|
56
|
+
--fail-on-memory-regression-percent 10
|
|
57
|
+
|
|
58
|
+
# Regenerate fixture goldens after editing tests/e2e/fixtures/ cases
|
|
59
|
+
uv run tests/run.py --update-golden
|
|
35
60
|
```
|
|
36
61
|
|
|
37
|
-
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
-
|
|
43
|
-
`src-auth-perms-sync-runs/<endpoint>/backups/` afterward to confirm the diff matches what you expected
|
|
62
|
+
- Fixture cases live in `tests/e2e/fixtures/<case>/` — see the README there
|
|
63
|
+
for the format. Add cases there to cover new mapping behaviors.
|
|
64
|
+
- For manual verification against a real instance, dry-run first (no
|
|
65
|
+
`--apply`), read the planned changes, then `--apply` on a scratch instance
|
|
66
|
+
and inspect the before/after snapshots under
|
|
67
|
+
`src-auth-perms-sync-runs/<endpoint>/runs/`.
|
|
44
68
|
|
|
45
69
|
## Release process
|
|
46
70
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: src-auth-perms-sync
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Set Sourcegraph permissions from authentication provider data
|
|
5
5
|
Project-URL: Homepage, https://github.com/sourcegraph/src-auth-perms-sync
|
|
6
6
|
Project-URL: Issues, https://github.com/sourcegraph/src-auth-perms-sync/issues
|
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# TODO
|
|
2
2
|
|
|
3
|
+
## Medium priority: extend SAML-group live coverage to org sync
|
|
4
|
+
|
|
5
|
+
tests/setup.py now fabricates SAML accounts with synthetic groups
|
|
6
|
+
(`perms-sync-test-eng` / `perms-sync-test-sales`, see tests/setup.yaml).
|
|
7
|
+
saml-group-live covers permission mapping; add a seeded
|
|
8
|
+
`sync-saml-orgs --apply` live case that maps those groups to a throwaway
|
|
9
|
+
org and asserts membership is added AND removed (today's
|
|
10
|
+
sync-saml-orgs-apply only covers the single real Okta user, add-only).
|
|
11
|
+
|
|
12
|
+
## Decide: pendingBindIDs / usersWithPendingPermissions
|
|
13
|
+
|
|
14
|
+
The CLI cannot create pending permissions (it validates users exist), but
|
|
15
|
+
snapshots record `pending_bindIDs`, and setup.py / the live hygiene check
|
|
16
|
+
report (never delete) any that appear. Decide whether "grant before first
|
|
17
|
+
login" is a customer need; if not, consider dropping the snapshot field.
|
|
18
|
+
See the thread discussion 2026-06-11.
|
|
19
|
+
|
|
3
20
|
## High priority: Remote trigger on demand
|
|
4
21
|
|
|
5
22
|
- Sourcegraph webhook for new user coming in v7.4.0
|
|
@@ -13,14 +30,6 @@
|
|
|
13
30
|
- How do we avoid stampedes (e.g., bulk repo sync triggering thousands
|
|
14
31
|
of re-runs)?
|
|
15
32
|
|
|
16
|
-
## High priority: End to End test cases
|
|
17
|
-
|
|
18
|
-
- Create test cases. Each test case should contain:
|
|
19
|
-
- Before state
|
|
20
|
-
- maps.yaml file
|
|
21
|
-
- Expected after state
|
|
22
|
-
- Script to run the script, and verify the after state matches the expected after state
|
|
23
|
-
|
|
24
33
|
## High priority: Verify perms are updated when a user's SAML groups change
|
|
25
34
|
|
|
26
35
|
- If a user gets added to a new SAML group, which hits a mapping, ensure they
|
|
@@ -29,14 +38,24 @@
|
|
|
29
38
|
## High priority: Reduce worst-case full-permission sync load
|
|
30
39
|
|
|
31
40
|
- Use the stress-run evidence in
|
|
32
|
-
[
|
|
41
|
+
[engineering-requests.md](./engineering-requests.md)
|
|
33
42
|
to request Sourcegraph bulk explicit-permission read and write APIs.
|
|
43
|
+
New evidence 2026-06-10: the whole-instance apply (1,150 repo
|
|
44
|
+
overwrites x 10,002 bindIDs each at parallelism 16) crashed the test
|
|
45
|
+
instance's Postgres ("connection refused", "unexpected EOF"); the
|
|
46
|
+
client circuit breaker opened and the harness restored cleanly. That
|
|
47
|
+
stress cycle is now opt-in: `uv run tests/run.py --live "full cycle"`.
|
|
34
48
|
- Add an explicit destructive/performance-test mode to the e2e runner so giant
|
|
35
49
|
stress runs can skip or defer full restore cleanup when the goal is finding
|
|
36
50
|
the server-side breaking point.
|
|
37
51
|
- Revisit full snapshot capture once Sourcegraph exposes a bulk read path;
|
|
38
52
|
replace aliased `User.permissionsInfo.repositories(source: API)` calls before
|
|
39
53
|
raising concurrency further.
|
|
54
|
+
- `get --repos <name>` still scans every user's explicit grants to find one
|
|
55
|
+
repo's holders (~400 s at 10k users). A repo-centric read
|
|
56
|
+
(`repository.permissionsInfo.users` + site-admin disambiguation, as the
|
|
57
|
+
test harness already does) would make it seconds — see the repo-centric
|
|
58
|
+
section below.
|
|
40
59
|
|
|
41
60
|
## Low priority: Repo-centric path, when users > repos, or for cross-checking
|
|
42
61
|
|
|
@@ -1,173 +1,18 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
Use this when full snapshot capture or full-set apply is slow. The goal is to
|
|
4
|
-
correlate `src-auth-perms-sync` structured logs with Sourcegraph Jaeger spans
|
|
5
|
-
and pod/Postgres load, then use the evidence to ask Sourcegraph engineering for
|
|
6
|
-
bulk explicit-permissions APIs.
|
|
7
|
-
|
|
8
|
-
## Capture a focused trace
|
|
9
|
-
|
|
10
|
-
Run a small command with `--fetch-sg-traces`. This sends
|
|
11
|
-
`X-Sourcegraph-Request-Trace` and a W3C `traceparent` header on each GraphQL
|
|
12
|
-
request. Sourcegraph may also return `x-trace`, `x-trace-span`, and
|
|
13
|
-
`x-trace-url` response headers.
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
uv run src-auth-perms-sync get \
|
|
17
|
-
--fetch-sg-traces \
|
|
18
|
-
--sample-interval 0 \
|
|
19
|
-
--parallelism 2 \
|
|
20
|
-
--explicit-permissions-batch-size 25
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
Find the slow GraphQL HTTP requests in the run log:
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
LOG=src-auth-perms-sync-runs/<endpoint>/runs/<run>/log.json
|
|
27
|
-
|
|
28
|
-
jq -r '
|
|
29
|
-
select(.event == "http_request" and .phase == "end") |
|
|
30
|
-
select(.url | endswith("/.api/graphql")) |
|
|
31
|
-
[
|
|
32
|
-
.duration_ms,
|
|
33
|
-
(.response_headers["x-trace"] // ""),
|
|
34
|
-
(.response_headers["x-trace-url"] // ""),
|
|
35
|
-
(.request_headers.traceparent // "")
|
|
36
|
-
] | @tsv
|
|
37
|
-
' "$LOG" | sort -nr | head -20
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Prefer the `x-trace` value when present. If Sourcegraph did not return one,
|
|
41
|
-
extract the trace ID from `traceparent`:
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
TRACEPARENT=00-<trace-id>-<span-id>-01
|
|
45
|
-
TRACE_ID="$(printf '%s' "$TRACEPARENT" | cut -d- -f2)"
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
Fetch the trace JSON from Jaeger:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
curl -sS \
|
|
52
|
-
-H "Authorization: token $SRC_ACCESS_TOKEN" \
|
|
53
|
-
"$SRC_ENDPOINT/-/debug/jaeger/api/traces/$TRACE_ID" \
|
|
54
|
-
> /tmp/sourcegraph-trace.json
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
Jaeger ingestion can lag. If the API returns `trace not found`, wait briefly
|
|
58
|
-
and retry. For long runs, fetch traces as soon as the relevant command
|
|
59
|
-
finishes; older trace IDs can disappear before a full matrix ends.
|
|
60
|
-
|
|
61
|
-
Summarize the hottest spans:
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
uv run python - <<'PY'
|
|
65
|
-
import collections
|
|
66
|
-
import json
|
|
67
|
-
|
|
68
|
-
trace = json.load(open("/tmp/sourcegraph-trace.json"))["data"][0]
|
|
69
|
-
durations_by_operation = collections.defaultdict(list)
|
|
70
|
-
for span in trace["spans"]:
|
|
71
|
-
durations_by_operation[span["operationName"]].append(span["duration"] / 1000)
|
|
72
|
-
|
|
73
|
-
for operation, durations in sorted(
|
|
74
|
-
durations_by_operation.items(),
|
|
75
|
-
key=lambda item: sum(item[1]),
|
|
76
|
-
reverse=True,
|
|
77
|
-
)[:15]:
|
|
78
|
-
print(
|
|
79
|
-
f"{operation}: count={len(durations)} "
|
|
80
|
-
f"sum_ms={sum(durations):.1f} "
|
|
81
|
-
f"max_ms={max(durations):.1f}"
|
|
82
|
-
)
|
|
83
|
-
PY
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
Do not commit tokens, customer URLs, raw trace JSON, benchmark CSVs, or monitor
|
|
87
|
-
artifacts. Keep them in `/tmp` unless a human asks to preserve them.
|
|
88
|
-
|
|
89
|
-
## Trace the end-to-end matrix
|
|
90
|
-
|
|
91
|
-
Prefer the end-to-end runner as the single orchestrator. With
|
|
92
|
-
`--fetch-sg-traces`, it passes Sourcegraph debug trace collection to every child
|
|
93
|
-
CLI command, tails child JSON logs, and fetches Jaeger traces in the background
|
|
94
|
-
while each child command is still running.
|
|
95
|
-
|
|
96
|
-
```bash
|
|
97
|
-
uv run python dev/test-end-to-end.py \
|
|
98
|
-
--fetch-sg-traces \
|
|
99
|
-
--sample-interval 0 \
|
|
100
|
-
--external-sample-interval 0 \
|
|
101
|
-
--results-json /tmp/src-auth-perms-sync-end-to-end-trace.json \
|
|
102
|
-
--results-csv /tmp/src-auth-perms-sync-end-to-end-trace.csv
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
Useful trace options:
|
|
106
|
-
|
|
107
|
-
- `--jaeger-trace-limit N`: fetch only the `N` slowest GraphQL traces per case.
|
|
108
|
-
- `--jaeger-trace-limit 0`: send trace headers but skip Jaeger fetching.
|
|
109
|
-
- `--jaeger-trace-parallelism N`: tune concurrent Jaeger fetches.
|
|
110
|
-
- `--jaeger-trace-jsonl PATH`: stream compact trace summaries as JSON Lines.
|
|
111
|
-
- `--jaeger-trace-dir PATH`: store complete raw Jaeger payloads.
|
|
112
|
-
|
|
113
|
-
Raw trace files include:
|
|
114
|
-
|
|
115
|
-
- `trace_request`: CLI-side HTTP and `graphql_query` correlation metadata,
|
|
116
|
-
including query name, page number, page size, cursor presence, query byte
|
|
117
|
-
count, variable names, response fields, status, and timing.
|
|
118
|
-
- `jaeger_summary`: compact hot-operation and GraphQL-operation summary.
|
|
119
|
-
- `jaeger_trace`: the complete Jaeger trace JSON returned by Sourcegraph.
|
|
1
|
+
# Engineering requests
|
|
120
2
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
3
|
+
Use this when opening Sourcegraph Engineering issues from memory-efficiency
|
|
4
|
+
evidence. Capture steps stay in [memory-efficiency.md](./memory-efficiency.md);
|
|
5
|
+
this file keeps the request-ready problem statement, evidence, proposed API
|
|
6
|
+
shape, and copy/paste issue text.
|
|
124
7
|
|
|
125
|
-
|
|
8
|
+
## Requested Sourcegraph changes
|
|
126
9
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
## Monitor Sourcegraph load during e2e runs
|
|
135
|
-
|
|
136
|
-
The runner can start the Sourcegraph pod/Postgres monitor and write monitor
|
|
137
|
-
artifact paths into the result JSON:
|
|
138
|
-
|
|
139
|
-
```bash
|
|
140
|
-
uv run python dev/test-end-to-end.py \
|
|
141
|
-
--fetch-sg-traces \
|
|
142
|
-
--monitor-sourcegraph-load \
|
|
143
|
-
--sample-interval 0 \
|
|
144
|
-
--external-sample-interval 0 \
|
|
145
|
-
--results-json /tmp/src-auth-perms-sync-end-to-end-trace.json \
|
|
146
|
-
--results-csv /tmp/src-auth-perms-sync-end-to-end-trace.csv
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
By default, monitor output is written beside `--results-json` or
|
|
150
|
-
`--results-csv` as `*-sourcegraph-load`, and the monitor's stdout/stderr goes
|
|
151
|
-
to `*-sourcegraph-load.log`. Override the location with
|
|
152
|
-
`--monitor-output-dir PATH`. Tune Kubernetes targets and sample intervals with
|
|
153
|
-
the `--monitor-*` flags if the test namespace or pod names differ.
|
|
154
|
-
|
|
155
|
-
The lower-level helper remains available for focused profiling outside a full
|
|
156
|
-
e2e run:
|
|
157
|
-
|
|
158
|
-
```bash
|
|
159
|
-
dev/memory-efficiency-monitor-sourcegraph.sh \
|
|
160
|
-
--namespace m \
|
|
161
|
-
--output-dir /tmp/src-auth-perms-sync-sourcegraph-load-$(date -u +%Y%m%d-%H%M%S)
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
Stop the helper with Ctrl-C, or add `--duration-seconds N`. It samples
|
|
165
|
-
Kubernetes CPU/memory, frontend and Postgres processes, cgroup CPU/memory
|
|
166
|
-
pressure, Postgres active queries/waits/locks, `pg_stat_statements` when
|
|
167
|
-
enabled, and frontend logs. On startup it runs `CREATE EXTENSION IF NOT EXISTS
|
|
168
|
-
pg_stat_statements` and `pg_stat_statements_reset()` through `kubectl exec`
|
|
169
|
-
against `pod/pgsql-0`, so statement summaries start clean for the monitored
|
|
170
|
-
run.
|
|
10
|
+
1. Add a bulk GraphQL read path for explicit API repository permissions.
|
|
11
|
+
2. Add a cheaper presence/filter path for users without explicit API repo
|
|
12
|
+
permissions.
|
|
13
|
+
3. Add Jaeger spans / metrics around the new store methods and around current
|
|
14
|
+
`ListUserPermissions` / `CountUserPermissions` paths.
|
|
15
|
+
4. Follow up with a bulk overwrite API for large full-set applies.
|
|
171
16
|
|
|
172
17
|
## Current trace findings
|
|
173
18
|
|
|
@@ -226,11 +71,46 @@ slower under the large explicit-perms state. This reinforces that the CLI needs
|
|
|
226
71
|
better Sourcegraph bulk read and write APIs for very large explicit permission
|
|
227
72
|
sets.
|
|
228
73
|
|
|
229
|
-
##
|
|
230
|
-
|
|
231
|
-
`src-auth-perms-sync`
|
|
232
|
-
|
|
233
|
-
|
|
74
|
+
## Concurrent-operator evidence (2026-06-10)
|
|
75
|
+
|
|
76
|
+
Four `src-auth-perms-sync` processes ran full explicit-permissions captures
|
|
77
|
+
concurrently against the 10k-user / 50k-repo test instance (each at
|
|
78
|
+
`--parallelism 8`, `--explicit-permissions-batch-size 25`), while a fifth ran a
|
|
79
|
+
small `set` command. Instance: single `pgsql-0` on an 8-core node.
|
|
80
|
+
|
|
81
|
+
Observed during the concurrent captures:
|
|
82
|
+
|
|
83
|
+
- `pgsql-0` CPU (`kubectl top`): 7,636–7,683 millicores of 8,000 (saturated).
|
|
84
|
+
- `frontend` / `gitserver` CPU: 124–138m / 2–3m (idle bystanders).
|
|
85
|
+
- `pg_stat_activity`: 29 active statements, all
|
|
86
|
+
`permsStore.ListUserPermissions`, **zero wait events** — pure CPU, no lock
|
|
87
|
+
contention.
|
|
88
|
+
- `pg_stat_statements`: `permsStore.ListUserPermissions` at 24,026 calls,
|
|
89
|
+
27,635.6s total, 1,150ms mean.
|
|
90
|
+
- Per-client capture throughput: 23 users/sec solo → 2–4 users/sec at 4-way
|
|
91
|
+
concurrency.
|
|
92
|
+
- Aggregate throughput: 8–16 users/sec at 4-way — **below the 23 users/sec a
|
|
93
|
+
single client achieves alone** (negative scaling).
|
|
94
|
+
- ALB (CloudWatch): no 5xx, no rejected connections — the edge and frontend
|
|
95
|
+
are not the bottleneck.
|
|
96
|
+
- Collateral failure: the fifth client's queries exceeded the 60s read timeout
|
|
97
|
+
under this load; 5 retry attempts exhausted; its run failed with exit 1.
|
|
98
|
+
|
|
99
|
+
Implications for the engineering request:
|
|
100
|
+
|
|
101
|
+
- A single per-user `permissionsInfo.repositories(source: API)` read costs
|
|
102
|
+
roughly 0.3–0.4s of Postgres CPU at this state size (1,150ms mean execution
|
|
103
|
+
under contention), so one operator at modest parallelism can saturate the
|
|
104
|
+
database by itself, and two concurrent operators degrade each other below
|
|
105
|
+
single-operator throughput.
|
|
106
|
+
- Timeout/retry behavior amplifies the problem: once statements exceed the
|
|
107
|
+
client read timeout, retries re-run the same expensive queries, adding load
|
|
108
|
+
exactly when the database is saturated.
|
|
109
|
+
- A bulk read API (one query returning explicit grants for many users or for
|
|
110
|
+
whole repos) would replace ~10,000 × ~1s statements per capture with a
|
|
111
|
+
single scan, and would also make concurrent operators viable.
|
|
112
|
+
|
|
113
|
+
## Sourcegraph codepath findings
|
|
234
114
|
|
|
235
115
|
[Deep Search findings](https://sourcegraph.sourcegraph.com/deepsearch/52a24164-1eb3-4db1-a92d-e320ef1c7557)
|
|
236
116
|
from `github.com/sourcegraph/sourcegraph`:
|
|
@@ -254,8 +134,14 @@ from `github.com/sourcegraph/sourcegraph`:
|
|
|
254
134
|
permissions, but the read path uses per-user connection queries and repo
|
|
255
135
|
resolver fanout.
|
|
256
136
|
|
|
257
|
-
|
|
258
|
-
|
|
137
|
+
## Proposed bulk read API
|
|
138
|
+
|
|
139
|
+
`src-auth-perms-sync` needs to snapshot explicit API permissions for many
|
|
140
|
+
users. Today it calls `User.permissionsInfo.repositories(source: API)` with
|
|
141
|
+
GraphQL aliases. This is correct, but expensive at scale.
|
|
142
|
+
|
|
143
|
+
Request a bulk read API for explicit permissions. GraphQL semantics make this a
|
|
144
|
+
query, not a mutation:
|
|
259
145
|
|
|
260
146
|
```graphql
|
|
261
147
|
type ExplicitRepositoryPermission {
|
|
@@ -298,6 +184,8 @@ Important requirements:
|
|
|
298
184
|
Expected benefit: replace hundreds or thousands of per-repo resolver SQL spans
|
|
299
185
|
per request with one indexed `user_repo_permissions` join per user batch.
|
|
300
186
|
|
|
187
|
+
## Proposed presence/filter API
|
|
188
|
+
|
|
301
189
|
The `get --users-without-explicit-perms` path also needs a cheaper presence
|
|
302
190
|
check. Today it has to ask
|
|
303
191
|
`User.permissionsInfo.repositories(source: API, first: 1)` for every candidate
|
|
@@ -326,15 +214,17 @@ extend type Query {
|
|
|
326
214
|
}
|
|
327
215
|
```
|
|
328
216
|
|
|
329
|
-
Expected benefit: `src-auth-perms-sync get --users-without-explicit-perms`
|
|
330
|
-
|
|
217
|
+
Expected benefit: `src-auth-perms-sync get --users-without-explicit-perms` can
|
|
218
|
+
either check explicit-permission presence for candidate users in one indexed
|
|
331
219
|
batch query, or ask Sourcegraph for the filtered user set directly instead of
|
|
332
220
|
probing every user through the expensive permissions connection resolver.
|
|
333
221
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
222
|
+
## Bulk overwrite follow-up
|
|
223
|
+
|
|
224
|
+
The stress profile also needs attention on the write path. A purpose-built bulk
|
|
225
|
+
overwrite API that accepts many repo/user edges at once, streams or stages the
|
|
226
|
+
input server-side, and avoids repeated per-repo permission reconciliation would
|
|
227
|
+
make worst-case full syncs much safer.
|
|
338
228
|
|
|
339
229
|
## Copy/paste request
|
|
340
230
|
|
|
@@ -19,10 +19,6 @@ run git diff --cached --check
|
|
|
19
19
|
run git diff --cached --stat
|
|
20
20
|
run git diff --stat
|
|
21
21
|
|
|
22
|
-
run uv run
|
|
23
|
-
run uv run ruff format . --check
|
|
24
|
-
run uv run pyright
|
|
25
|
-
run uv run python -m unittest discover -s tests
|
|
26
|
-
run uv run src-auth-perms-sync --help
|
|
22
|
+
run uv run tests/run.py --local
|
|
27
23
|
|
|
28
24
|
printf '\nPre-commit quality checks passed.\n'
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Memory efficiency testing
|
|
2
|
+
|
|
3
|
+
Use this when full snapshot capture or full-set apply is slow. The goal is to
|
|
4
|
+
correlate `src-auth-perms-sync` structured logs with Sourcegraph Jaeger spans
|
|
5
|
+
and pod/Postgres load. Request-ready evidence and copy/paste text for
|
|
6
|
+
Sourcegraph Engineering live in
|
|
7
|
+
[engineering-requests.md](./engineering-requests.md).
|
|
8
|
+
|
|
9
|
+
## Capture a focused trace
|
|
10
|
+
|
|
11
|
+
Run a small command with `--fetch-sg-traces`. This sends
|
|
12
|
+
`X-Sourcegraph-Request-Trace` and a W3C `traceparent` header on each GraphQL
|
|
13
|
+
request. Sourcegraph may also return `x-trace`, `x-trace-span`, and
|
|
14
|
+
`x-trace-url` response headers.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
uv run src-auth-perms-sync get \
|
|
18
|
+
--fetch-sg-traces \
|
|
19
|
+
--sample-interval 0 \
|
|
20
|
+
--parallelism 2 \
|
|
21
|
+
--explicit-permissions-batch-size 25
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Find the slow GraphQL HTTP requests in the run log:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
LOG=src-auth-perms-sync-runs/<endpoint>/runs/<run>/log.json
|
|
28
|
+
|
|
29
|
+
jq -r '
|
|
30
|
+
select(.event == "http_request" and .phase == "end") |
|
|
31
|
+
select(.url | endswith("/.api/graphql")) |
|
|
32
|
+
[
|
|
33
|
+
.duration_ms,
|
|
34
|
+
(.response_headers["x-trace"] // ""),
|
|
35
|
+
(.response_headers["x-trace-url"] // ""),
|
|
36
|
+
(.request_headers.traceparent // "")
|
|
37
|
+
] | @tsv
|
|
38
|
+
' "$LOG" | sort -nr | head -20
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Prefer the `x-trace` value when present. If Sourcegraph did not return one,
|
|
42
|
+
extract the trace ID from `traceparent`:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
TRACEPARENT=00-<trace-id>-<span-id>-01
|
|
46
|
+
TRACE_ID="$(printf '%s' "$TRACEPARENT" | cut -d- -f2)"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Fetch the trace JSON from Jaeger:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
curl -sS \
|
|
53
|
+
-H "Authorization: token $SRC_ACCESS_TOKEN" \
|
|
54
|
+
"$SRC_ENDPOINT/-/debug/jaeger/api/traces/$TRACE_ID" \
|
|
55
|
+
> /tmp/sourcegraph-trace.json
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Jaeger ingestion can lag. If the API returns `trace not found`, wait briefly
|
|
59
|
+
and retry. For long runs, fetch traces as soon as the relevant command
|
|
60
|
+
finishes; older trace IDs can disappear before a full matrix ends.
|
|
61
|
+
|
|
62
|
+
Summarize the hottest spans:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
uv run python - <<'PY'
|
|
66
|
+
import collections
|
|
67
|
+
import json
|
|
68
|
+
|
|
69
|
+
trace = json.load(open("/tmp/sourcegraph-trace.json"))["data"][0]
|
|
70
|
+
durations_by_operation = collections.defaultdict(list)
|
|
71
|
+
for span in trace["spans"]:
|
|
72
|
+
durations_by_operation[span["operationName"]].append(span["duration"] / 1000)
|
|
73
|
+
|
|
74
|
+
for operation, durations in sorted(
|
|
75
|
+
durations_by_operation.items(),
|
|
76
|
+
key=lambda item: sum(item[1]),
|
|
77
|
+
reverse=True,
|
|
78
|
+
)[:15]:
|
|
79
|
+
print(
|
|
80
|
+
f"{operation}: count={len(durations)} "
|
|
81
|
+
f"sum_ms={sum(durations):.1f} "
|
|
82
|
+
f"max_ms={max(durations):.1f}"
|
|
83
|
+
)
|
|
84
|
+
PY
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Do not commit tokens, customer URLs, raw trace JSON, benchmark CSVs, or monitor
|
|
88
|
+
artifacts. Keep them in `/tmp` unless a human asks to preserve them.
|
|
89
|
+
|
|
90
|
+
## Trace the end-to-end matrix
|
|
91
|
+
|
|
92
|
+
Prefer the end-to-end runner as the single orchestrator. With
|
|
93
|
+
`--fetch-sg-traces`, it passes Sourcegraph debug trace collection to every child
|
|
94
|
+
CLI command, tails child JSON logs, and fetches Jaeger traces in the background
|
|
95
|
+
while each child command is still running.
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
uv run python dev/test-end-to-end.py \
|
|
99
|
+
--fetch-sg-traces \
|
|
100
|
+
--sample-interval 0 \
|
|
101
|
+
--external-sample-interval 0 \
|
|
102
|
+
--results-json /tmp/src-auth-perms-sync-end-to-end-trace.json \
|
|
103
|
+
--results-csv /tmp/src-auth-perms-sync-end-to-end-trace.csv
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Useful trace options:
|
|
107
|
+
|
|
108
|
+
- `--jaeger-trace-limit N`: fetch only the `N` slowest GraphQL traces per case.
|
|
109
|
+
- `--jaeger-trace-limit 0`: send trace headers but skip Jaeger fetching.
|
|
110
|
+
- `--jaeger-trace-parallelism N`: tune concurrent Jaeger fetches.
|
|
111
|
+
- `--jaeger-trace-jsonl PATH`: stream compact trace summaries as JSON Lines.
|
|
112
|
+
- `--jaeger-trace-dir PATH`: store complete raw Jaeger payloads.
|
|
113
|
+
|
|
114
|
+
Raw trace files include:
|
|
115
|
+
|
|
116
|
+
- `trace_request`: CLI-side HTTP and `graphql_query` correlation metadata,
|
|
117
|
+
including query name, page number, page size, cursor presence, query byte
|
|
118
|
+
count, variable names, response fields, status, and timing.
|
|
119
|
+
- `jaeger_summary`: compact hot-operation and GraphQL-operation summary.
|
|
120
|
+
- `jaeger_trace`: the complete Jaeger trace JSON returned by Sourcegraph.
|
|
121
|
+
|
|
122
|
+
All runner flags are Config-backed. You can set them in the shell or `.env`
|
|
123
|
+
with `SRC_AUTH_PERMS_SYNC_E2E_*` names, plus `SRC_ENDPOINT`,
|
|
124
|
+
`SRC_ACCESS_TOKEN`, and `SRC_AUTH_PERMS_SYNC_TEST_USER`.
|
|
125
|
+
|
|
126
|
+
For each tested batch size and parallelism, record:
|
|
127
|
+
|
|
128
|
+
- CLI `capture_explicit_grants` duration from the structured log
|
|
129
|
+
- slowest GraphQL `http_request` duration and its trace metadata
|
|
130
|
+
- Jaeger counts and summed duration for `GraphQL Request`, `repos.Get`,
|
|
131
|
+
`sql.conn.query`, and `database.PermsStore.LoadUserPermissions`
|
|
132
|
+
- run-end `http_retry_count`, `http_request_attempt_count`, and timeout/error
|
|
133
|
+
counts
|
|
134
|
+
|
|
135
|
+
## Monitor Sourcegraph load during e2e runs
|
|
136
|
+
|
|
137
|
+
The runner can start the Sourcegraph pod/Postgres monitor and write monitor
|
|
138
|
+
artifact paths into the result JSON:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
uv run python dev/test-end-to-end.py \
|
|
142
|
+
--fetch-sg-traces \
|
|
143
|
+
--monitor-sourcegraph-load \
|
|
144
|
+
--sample-interval 0 \
|
|
145
|
+
--external-sample-interval 0 \
|
|
146
|
+
--results-json /tmp/src-auth-perms-sync-end-to-end-trace.json \
|
|
147
|
+
--results-csv /tmp/src-auth-perms-sync-end-to-end-trace.csv
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
By default, monitor output is written beside `--results-json` or
|
|
151
|
+
`--results-csv` as `*-sourcegraph-load`, and the monitor's stdout/stderr goes
|
|
152
|
+
to `*-sourcegraph-load.log`. Override the location with
|
|
153
|
+
`--monitor-output-dir PATH`. Tune Kubernetes targets and sample intervals with
|
|
154
|
+
the `--monitor-*` flags if the test namespace or pod names differ.
|
|
155
|
+
|
|
156
|
+
The lower-level helper remains available for focused profiling outside a full
|
|
157
|
+
e2e run:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
dev/memory-efficiency-monitor-sourcegraph.sh \
|
|
161
|
+
--namespace m \
|
|
162
|
+
--output-dir /tmp/src-auth-perms-sync-sourcegraph-load-$(date -u +%Y%m%d-%H%M%S)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Stop the helper with Ctrl-C, or add `--duration-seconds N`. It samples
|
|
166
|
+
Kubernetes CPU/memory, frontend and Postgres processes, cgroup CPU/memory
|
|
167
|
+
pressure, Postgres active queries/waits/locks, `pg_stat_statements` when
|
|
168
|
+
enabled, and frontend logs. On startup it runs `CREATE EXTENSION IF NOT EXISTS
|
|
169
|
+
pg_stat_statements` and `pg_stat_statements_reset()` through `kubectl exec`
|
|
170
|
+
against `pod/pgsql-0`, so statement summaries start clean for the monitored
|
|
171
|
+
run.
|
|
172
|
+
|
|
173
|
+
## Engineering requests
|
|
174
|
+
|
|
175
|
+
Request-ready trace findings, stress evidence, Sourcegraph codepath notes,
|
|
176
|
+
proposed GraphQL APIs, and copy/paste issue text now live in
|
|
177
|
+
[engineering-requests.md](./engineering-requests.md).
|