src-py-lib 0.1.1__tar.gz → 0.1.2__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_py_lib-0.1.2/.github/workflows/ci.yml +16 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/.github/workflows/release.yml +59 -28
- src_py_lib-0.1.1/.github/workflows/ci.yml → src_py_lib-0.1.2/.github/workflows/validate.yml +47 -16
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/AGENTS.md +11 -6
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/PKG-INFO +8 -1
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/README.md +7 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/pyproject.toml +2 -2
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/src/src_py_lib/__init__.py +32 -1
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/src/src_py_lib/clients/graphql.py +20 -3
- src_py_lib-0.1.2/src/src_py_lib/clients/sourcegraph.py +472 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/src/src_py_lib/utils/http.py +69 -3
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/src/src_py_lib/utils/logging.py +121 -12
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/tests/test_logging_http_clients.py +127 -4
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/uv.lock +1 -1
- src_py_lib-0.1.1/src/src_py_lib/clients/sourcegraph.py +0 -127
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/.gitignore +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/.markdownlint-cli2.yaml +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/.python-version +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/LICENSE +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/SECURITY.md +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/renovate.json +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/src/src_py_lib/clients/__init__.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/src/src_py_lib/clients/github.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/src/src_py_lib/clients/google_sheets.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/src/src_py_lib/clients/linear.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/src/src_py_lib/clients/one_password.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/src/src_py_lib/clients/slack.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/src/src_py_lib/py.typed +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/src/src_py_lib/utils/__init__.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/src/src_py_lib/utils/config.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/src/src_py_lib/utils/json_cache.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/src/src_py_lib/utils/json_types.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/src/src_py_lib/utils/tsv.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/tests/test_import.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.2}/tests/test_tsv.py +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
contents: read
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
validate:
|
|
15
|
+
name: Validate
|
|
16
|
+
uses: ./.github/workflows/validate.yml
|
|
@@ -23,8 +23,15 @@ defaults:
|
|
|
23
23
|
shell: bash
|
|
24
24
|
|
|
25
25
|
jobs:
|
|
26
|
+
validate:
|
|
27
|
+
name: Validate
|
|
28
|
+
uses: ./.github/workflows/validate.yml
|
|
29
|
+
with:
|
|
30
|
+
ref: ${{ github.event.inputs.tag || github.ref }}
|
|
31
|
+
|
|
26
32
|
wheel:
|
|
27
33
|
name: Build wheel
|
|
34
|
+
needs: validate
|
|
28
35
|
runs-on: ubuntu-24.04
|
|
29
36
|
env:
|
|
30
37
|
IMPORT_NAME: src_py_lib
|
|
@@ -45,6 +52,14 @@ jobs:
|
|
|
45
52
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
46
53
|
cache: pip
|
|
47
54
|
|
|
55
|
+
- name: Cache uv
|
|
56
|
+
uses: actions/cache@v4
|
|
57
|
+
with:
|
|
58
|
+
path: ~/.cache/uv
|
|
59
|
+
key: uv-${{ runner.os }}-py${{ env.PYTHON_VERSION }}-${{ hashFiles('uv.lock') }}
|
|
60
|
+
restore-keys: |
|
|
61
|
+
uv-${{ runner.os }}-py${{ env.PYTHON_VERSION }}-
|
|
62
|
+
|
|
48
63
|
- name: Install build tools
|
|
49
64
|
run: |
|
|
50
65
|
python -m pip install --upgrade pip
|
|
@@ -62,6 +77,14 @@ jobs:
|
|
|
62
77
|
echo "::error title=Missing tag::Tag '${release_tag}' was not fetched. Create and push it before running this workflow."
|
|
63
78
|
exit 1
|
|
64
79
|
fi
|
|
80
|
+
tag_revision="$(git rev-list -n 1 "${release_tag}")"
|
|
81
|
+
git fetch --no-tags origin main
|
|
82
|
+
main_revision="$(git rev-parse origin/main)"
|
|
83
|
+
if ! git merge-base --is-ancestor "${tag_revision}" "${main_revision}"; then
|
|
84
|
+
echo "::error title=Tag is not on main::Tag '${release_tag}' points at ${tag_revision}, which is not reachable from origin/main."
|
|
85
|
+
echo "::error::Merge the release PR first, then tag the main commit."
|
|
86
|
+
exit 1
|
|
87
|
+
fi
|
|
65
88
|
|
|
66
89
|
project_version=$(uv run --frozen python - <<'PY'
|
|
67
90
|
import tomllib
|
|
@@ -77,22 +100,6 @@ jobs:
|
|
|
77
100
|
|
|
78
101
|
echo "tag=${release_tag}" >> "${GITHUB_OUTPUT}"
|
|
79
102
|
|
|
80
|
-
- name: Validate package
|
|
81
|
-
run: |
|
|
82
|
-
uv lock --check
|
|
83
|
-
uv run --frozen ruff check .
|
|
84
|
-
uv run --frozen ruff format --check .
|
|
85
|
-
uv run --frozen pyright
|
|
86
|
-
uv run --frozen python -m unittest discover -s tests
|
|
87
|
-
uv run --frozen python - <<'PY'
|
|
88
|
-
import os
|
|
89
|
-
|
|
90
|
-
import src_py_lib
|
|
91
|
-
|
|
92
|
-
if src_py_lib.__name__ != os.environ["IMPORT_NAME"]:
|
|
93
|
-
raise SystemExit(f"unexpected import name: {src_py_lib.__name__}")
|
|
94
|
-
PY
|
|
95
|
-
|
|
96
103
|
- name: Build distributions
|
|
97
104
|
id: build
|
|
98
105
|
run: |
|
|
@@ -115,17 +122,24 @@ jobs:
|
|
|
115
122
|
wheel_path="${project_wheels[0]}"
|
|
116
123
|
wheel_name="$(basename "${wheel_path}")"
|
|
117
124
|
source_distribution_path="${source_distributions[0]}"
|
|
118
|
-
|
|
125
|
+
source_distribution_name="$(basename "${source_distribution_path}")"
|
|
126
|
+
wheel_checksum_path="${wheel_path}.sha256"
|
|
127
|
+
source_distribution_checksum_path="${source_distribution_path}.sha256"
|
|
119
128
|
|
|
120
129
|
(
|
|
121
130
|
cd "$(dirname "${wheel_path}")"
|
|
122
|
-
shasum -a 256 "${wheel_name}" > "$(basename "${
|
|
131
|
+
shasum -a 256 "${wheel_name}" > "$(basename "${wheel_checksum_path}")"
|
|
132
|
+
shasum -a 256 "${source_distribution_name}" > "$(basename "${source_distribution_checksum_path}")"
|
|
123
133
|
)
|
|
124
134
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
135
|
+
{
|
|
136
|
+
echo "wheel_path=${wheel_path}"
|
|
137
|
+
echo "wheel_name=${wheel_name}"
|
|
138
|
+
echo "source_distribution_path=${source_distribution_path}"
|
|
139
|
+
echo "source_distribution_name=${source_distribution_name}"
|
|
140
|
+
echo "wheel_checksum_path=${wheel_checksum_path}"
|
|
141
|
+
echo "source_distribution_checksum_path=${source_distribution_checksum_path}"
|
|
142
|
+
} >> "${GITHUB_OUTPUT}"
|
|
129
143
|
|
|
130
144
|
- name: Smoke test installed wheel
|
|
131
145
|
run: |
|
|
@@ -147,6 +161,7 @@ jobs:
|
|
|
147
161
|
run: |
|
|
148
162
|
release_tag="${{ steps.release.outputs.tag }}"
|
|
149
163
|
wheel_name="${{ steps.build.outputs.wheel_name }}"
|
|
164
|
+
source_distribution_name="${{ steps.build.outputs.source_distribution_name }}"
|
|
150
165
|
notes_path="build/release/release-notes.md"
|
|
151
166
|
cat > "${notes_path}" <<EOF
|
|
152
167
|
## Install
|
|
@@ -163,13 +178,19 @@ jobs:
|
|
|
163
178
|
pip install "https://github.com/sourcegraph/src-py-lib/releases/download/${release_tag}/${wheel_name}"
|
|
164
179
|
\`\`\`
|
|
165
180
|
|
|
181
|
+
Source distribution:
|
|
182
|
+
|
|
183
|
+
\`\`\`sh
|
|
184
|
+
curl -LO "https://github.com/sourcegraph/src-py-lib/releases/download/${release_tag}/${source_distribution_name}"
|
|
185
|
+
\`\`\`
|
|
186
|
+
|
|
166
187
|
Or install this tag with uv:
|
|
167
188
|
|
|
168
189
|
\`\`\`sh
|
|
169
190
|
uv add "git+https://github.com/sourcegraph/src-py-lib.git@${release_tag}"
|
|
170
191
|
\`\`\`
|
|
171
192
|
|
|
172
|
-
Verify downloaded
|
|
193
|
+
Verify downloaded assets with the matching \`.sha256\` files.
|
|
173
194
|
EOF
|
|
174
195
|
echo "path=${notes_path}" >> "${GITHUB_OUTPUT}"
|
|
175
196
|
|
|
@@ -179,7 +200,9 @@ jobs:
|
|
|
179
200
|
name: src-py-lib-release
|
|
180
201
|
path: |
|
|
181
202
|
${{ steps.build.outputs.wheel_path }}
|
|
182
|
-
${{ steps.build.outputs.
|
|
203
|
+
${{ steps.build.outputs.source_distribution_path }}
|
|
204
|
+
${{ steps.build.outputs.wheel_checksum_path }}
|
|
205
|
+
${{ steps.build.outputs.source_distribution_checksum_path }}
|
|
183
206
|
${{ steps.notes.outputs.path }}
|
|
184
207
|
|
|
185
208
|
- name: Upload PyPI artifact
|
|
@@ -196,16 +219,23 @@ jobs:
|
|
|
196
219
|
run: |
|
|
197
220
|
release_tag="${{ steps.release.outputs.tag }}"
|
|
198
221
|
wheel_path="${{ steps.build.outputs.wheel_path }}"
|
|
199
|
-
|
|
222
|
+
source_distribution_path="${{ steps.build.outputs.source_distribution_path }}"
|
|
223
|
+
wheel_checksum_path="${{ steps.build.outputs.wheel_checksum_path }}"
|
|
224
|
+
source_distribution_checksum_path="${{ steps.build.outputs.source_distribution_checksum_path }}"
|
|
200
225
|
notes_path="${{ steps.notes.outputs.path }}"
|
|
226
|
+
release_assets=(
|
|
227
|
+
"${wheel_path}"
|
|
228
|
+
"${source_distribution_path}"
|
|
229
|
+
"${wheel_checksum_path}"
|
|
230
|
+
"${source_distribution_checksum_path}"
|
|
231
|
+
)
|
|
201
232
|
|
|
202
233
|
if gh release view "${release_tag}" >/dev/null 2>&1; then
|
|
203
234
|
gh release edit "${release_tag}" --title "${release_tag}" --notes-file "${notes_path}"
|
|
204
|
-
gh release upload "${release_tag}" "${
|
|
235
|
+
gh release upload "${release_tag}" "${release_assets[@]}" --clobber
|
|
205
236
|
else
|
|
206
237
|
gh release create "${release_tag}" \
|
|
207
|
-
"${
|
|
208
|
-
"${checksum_path}" \
|
|
238
|
+
"${release_assets[@]}" \
|
|
209
239
|
--title "${release_tag}" \
|
|
210
240
|
--notes-file "${notes_path}" \
|
|
211
241
|
--verify-tag
|
|
@@ -233,3 +263,4 @@ jobs:
|
|
|
233
263
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
234
264
|
with:
|
|
235
265
|
packages-dir: dist
|
|
266
|
+
skip-existing: true
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
name:
|
|
1
|
+
name: Validate
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
workflow_call:
|
|
5
|
+
inputs:
|
|
6
|
+
ref:
|
|
7
|
+
description: "Git ref to validate. Defaults to the caller's ref."
|
|
8
|
+
required: false
|
|
9
|
+
type: string
|
|
8
10
|
|
|
9
11
|
permissions:
|
|
10
12
|
contents: read
|
|
@@ -14,11 +16,13 @@ defaults:
|
|
|
14
16
|
shell: bash
|
|
15
17
|
|
|
16
18
|
jobs:
|
|
17
|
-
|
|
18
|
-
name:
|
|
19
|
+
package:
|
|
20
|
+
name: Validate package
|
|
19
21
|
runs-on: ubuntu-24.04
|
|
20
22
|
env:
|
|
23
|
+
ACTIONLINT_VERSION: "1.7.12"
|
|
21
24
|
IMPORT_NAME: src_py_lib
|
|
25
|
+
MARKDOWNLINT_CLI2_VERSION: "0.22.1"
|
|
22
26
|
PYTHON_VERSION: "3.11"
|
|
23
27
|
UV_VERSION: "0.11.7"
|
|
24
28
|
|
|
@@ -27,6 +31,34 @@ jobs:
|
|
|
27
31
|
uses: actions/checkout@v6
|
|
28
32
|
with:
|
|
29
33
|
persist-credentials: false
|
|
34
|
+
ref: ${{ inputs.ref || github.ref }}
|
|
35
|
+
|
|
36
|
+
- name: Cache actionlint
|
|
37
|
+
id: cache-actionlint
|
|
38
|
+
uses: actions/cache@v4
|
|
39
|
+
with:
|
|
40
|
+
path: ~/.local/bin/actionlint
|
|
41
|
+
key: actionlint-${{ runner.os }}-${{ runner.arch }}-${{ env.ACTIONLINT_VERSION }}
|
|
42
|
+
|
|
43
|
+
- name: Install actionlint
|
|
44
|
+
if: steps.cache-actionlint.outputs.cache-hit != 'true'
|
|
45
|
+
run: |
|
|
46
|
+
mkdir -p "${HOME}/.local/bin"
|
|
47
|
+
go install "github.com/rhysd/actionlint/cmd/actionlint@v${ACTIONLINT_VERSION}"
|
|
48
|
+
install -m 0755 "${HOME}/go/bin/actionlint" "${HOME}/.local/bin/actionlint"
|
|
49
|
+
|
|
50
|
+
- name: Lint GitHub Actions
|
|
51
|
+
run: |
|
|
52
|
+
"${HOME}/.local/bin/actionlint"
|
|
53
|
+
|
|
54
|
+
- name: Cache npm
|
|
55
|
+
uses: actions/cache@v4
|
|
56
|
+
with:
|
|
57
|
+
path: ~/.npm
|
|
58
|
+
key: npm-${{ runner.os }}-markdownlint-cli2-${{ env.MARKDOWNLINT_CLI2_VERSION }}
|
|
59
|
+
|
|
60
|
+
- name: Lint Markdown
|
|
61
|
+
run: npx --yes "markdownlint-cli2@${MARKDOWNLINT_CLI2_VERSION}"
|
|
30
62
|
|
|
31
63
|
- name: Set up Python
|
|
32
64
|
uses: actions/setup-python@v6
|
|
@@ -34,6 +66,14 @@ jobs:
|
|
|
34
66
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
35
67
|
cache: pip
|
|
36
68
|
|
|
69
|
+
- name: Cache uv
|
|
70
|
+
uses: actions/cache@v4
|
|
71
|
+
with:
|
|
72
|
+
path: ~/.cache/uv
|
|
73
|
+
key: uv-${{ runner.os }}-py${{ env.PYTHON_VERSION }}-${{ hashFiles('uv.lock') }}
|
|
74
|
+
restore-keys: |
|
|
75
|
+
uv-${{ runner.os }}-py${{ env.PYTHON_VERSION }}-
|
|
76
|
+
|
|
37
77
|
- name: Install uv
|
|
38
78
|
run: |
|
|
39
79
|
python -m pip install --upgrade pip
|
|
@@ -42,9 +82,6 @@ jobs:
|
|
|
42
82
|
- name: Validate lockfile
|
|
43
83
|
run: uv lock --check
|
|
44
84
|
|
|
45
|
-
- name: Lint Markdown
|
|
46
|
-
run: npx --yes markdownlint-cli2
|
|
47
|
-
|
|
48
85
|
- name: Lint Python
|
|
49
86
|
run: uv run --frozen ruff check .
|
|
50
87
|
|
|
@@ -85,9 +122,3 @@ jobs:
|
|
|
85
122
|
if src_py_lib.__name__ != os.environ["IMPORT_NAME"]:
|
|
86
123
|
raise SystemExit(f"unexpected import name: {src_py_lib.__name__}")
|
|
87
124
|
PY
|
|
88
|
-
|
|
89
|
-
- name: Upload wheel artifact
|
|
90
|
-
uses: actions/upload-artifact@v7
|
|
91
|
-
with:
|
|
92
|
-
name: src-py-lib-wheel
|
|
93
|
-
path: dist/*.whl
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
## Standard commands
|
|
15
15
|
|
|
16
16
|
```sh
|
|
17
|
-
|
|
17
|
+
actionlint
|
|
18
|
+
npx --yes markdownlint-cli2@0.22.1
|
|
18
19
|
uv sync
|
|
19
20
|
uv run ruff format .
|
|
20
21
|
uv run ruff check .
|
|
@@ -56,11 +57,14 @@ uv run python -m unittest discover -s tests
|
|
|
56
57
|
verifies that it matches `project.version` before building GitHub release
|
|
57
58
|
assets and publishing to PyPI.
|
|
58
59
|
- Prepare releases on a branch from current `main`. Set `VERSION`, then run:
|
|
60
|
+
- As part of every release bump, find old release-version literals in
|
|
61
|
+
`AGENTS.md`, `README.md`, and release snippets, and replace them with the
|
|
62
|
+
new version where they are meant to stay current.
|
|
59
63
|
|
|
60
64
|
```sh
|
|
61
65
|
set -euo pipefail
|
|
62
66
|
|
|
63
|
-
VERSION=0.1.
|
|
67
|
+
VERSION=0.1.2
|
|
64
68
|
BRANCH="release-v${VERSION}"
|
|
65
69
|
|
|
66
70
|
git fetch origin --tags --prune
|
|
@@ -96,7 +100,8 @@ uv lock
|
|
|
96
100
|
set -euo pipefail
|
|
97
101
|
|
|
98
102
|
uv lock --check
|
|
99
|
-
|
|
103
|
+
actionlint
|
|
104
|
+
npx --yes markdownlint-cli2@0.22.1
|
|
100
105
|
uv run ruff check .
|
|
101
106
|
uv run ruff format --check .
|
|
102
107
|
uv run pyright
|
|
@@ -111,7 +116,7 @@ rm -rf /tmp/src-py-lib-release-check
|
|
|
111
116
|
```sh
|
|
112
117
|
set -euo pipefail
|
|
113
118
|
|
|
114
|
-
VERSION=0.1.
|
|
119
|
+
VERSION=0.1.2
|
|
115
120
|
BRANCH="release-v${VERSION}"
|
|
116
121
|
GH_REPO="sourcegraph/src-py-lib"
|
|
117
122
|
|
|
@@ -135,7 +140,7 @@ gh pr merge "${BRANCH}" --repo "${GH_REPO}" --squash --delete-branch
|
|
|
135
140
|
```sh
|
|
136
141
|
set -euo pipefail
|
|
137
142
|
|
|
138
|
-
VERSION=0.1.
|
|
143
|
+
VERSION=0.1.2
|
|
139
144
|
|
|
140
145
|
git fetch origin --tags --prune
|
|
141
146
|
git switch main
|
|
@@ -149,7 +154,7 @@ git push origin "v${VERSION}"
|
|
|
149
154
|
```sh
|
|
150
155
|
set -euo pipefail
|
|
151
156
|
|
|
152
|
-
VERSION=0.1.
|
|
157
|
+
VERSION=0.1.2
|
|
153
158
|
GH_REPO="sourcegraph/src-py-lib"
|
|
154
159
|
|
|
155
160
|
RUN_ID="$(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: src-py-lib
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Reusable libraries for Sourcegraph projects
|
|
5
5
|
Project-URL: Homepage, https://github.com/sourcegraph/src-py-lib
|
|
6
6
|
Project-URL: Issues, https://github.com/sourcegraph/src-py-lib/issues
|
|
@@ -31,6 +31,13 @@ This repo was created for Sourcegraph Implementation Engineering deployments,
|
|
|
31
31
|
and is not intended, designed, built, or supported for use in any other scenario.
|
|
32
32
|
Feel free to open issues or PRs, but responses are best effort.
|
|
33
33
|
|
|
34
|
+
## Semantic Versioning
|
|
35
|
+
|
|
36
|
+
- Release versions are `major.minor.patch`
|
|
37
|
+
- Because this project is still major version 0:
|
|
38
|
+
- Minor version updates are breaking changes
|
|
39
|
+
- Patch version updates are not breaking changes
|
|
40
|
+
|
|
34
41
|
## Install
|
|
35
42
|
|
|
36
43
|
From PyPI:
|
|
@@ -8,6 +8,13 @@ This repo was created for Sourcegraph Implementation Engineering deployments,
|
|
|
8
8
|
and is not intended, designed, built, or supported for use in any other scenario.
|
|
9
9
|
Feel free to open issues or PRs, but responses are best effort.
|
|
10
10
|
|
|
11
|
+
## Semantic Versioning
|
|
12
|
+
|
|
13
|
+
- Release versions are `major.minor.patch`
|
|
14
|
+
- Because this project is still major version 0:
|
|
15
|
+
- Minor version updates are breaking changes
|
|
16
|
+
- Patch version updates are not breaking changes
|
|
17
|
+
|
|
11
18
|
## Install
|
|
12
19
|
|
|
13
20
|
From PyPI:
|
|
@@ -10,7 +10,7 @@ dev = [
|
|
|
10
10
|
|
|
11
11
|
[project]
|
|
12
12
|
name = "src-py-lib"
|
|
13
|
-
version = "0.1.
|
|
13
|
+
version = "0.1.2"
|
|
14
14
|
description = "Reusable libraries for Sourcegraph projects"
|
|
15
15
|
readme = "README.md"
|
|
16
16
|
requires-python = ">=3.11"
|
|
@@ -45,7 +45,7 @@ Issues = "https://github.com/sourcegraph/src-py-lib/issues"
|
|
|
45
45
|
packages = ["src/src_py_lib"]
|
|
46
46
|
|
|
47
47
|
[tool.pyright]
|
|
48
|
-
include = ["src/src_py_lib"]
|
|
48
|
+
include = ["src/src_py_lib", "tests"]
|
|
49
49
|
typeCheckingMode = "strict"
|
|
50
50
|
extraPaths = ["src"]
|
|
51
51
|
pythonVersion = "3.11"
|
|
@@ -37,6 +37,14 @@ from src_py_lib.clients.slack import (
|
|
|
37
37
|
from src_py_lib.clients.sourcegraph import (
|
|
38
38
|
SourcegraphClient,
|
|
39
39
|
SourcegraphClientConfig,
|
|
40
|
+
SourcegraphJaegerTraceError,
|
|
41
|
+
SourcegraphJaegerTraceSummary,
|
|
42
|
+
SourcegraphTrace,
|
|
43
|
+
decode_external_service_id,
|
|
44
|
+
decode_repository_id,
|
|
45
|
+
decode_sourcegraph_node_id,
|
|
46
|
+
encode_repository_id,
|
|
47
|
+
encode_sourcegraph_node_id,
|
|
40
48
|
normalize_sourcegraph_endpoint,
|
|
41
49
|
sourcegraph_client_from_config,
|
|
42
50
|
)
|
|
@@ -49,7 +57,7 @@ from src_py_lib.utils.config import (
|
|
|
49
57
|
from src_py_lib.utils.config import (
|
|
50
58
|
config_parse_args as parse_args,
|
|
51
59
|
)
|
|
52
|
-
from src_py_lib.utils.http import HTTPClient, HTTPClientError
|
|
60
|
+
from src_py_lib.utils.http import HTTPClient, HTTPClientError, HTTPResponse
|
|
53
61
|
from src_py_lib.utils.json_cache import load_json_cache, load_json_subset, save_json_cache
|
|
54
62
|
from src_py_lib.utils.json_types import (
|
|
55
63
|
JSONDict,
|
|
@@ -63,8 +71,10 @@ from src_py_lib.utils.json_types import (
|
|
|
63
71
|
from src_py_lib.utils.logging import (
|
|
64
72
|
LoggingConfig,
|
|
65
73
|
LoggingSettings,
|
|
74
|
+
TraceContext,
|
|
66
75
|
configure_logging,
|
|
67
76
|
critical,
|
|
77
|
+
current_trace_context,
|
|
68
78
|
debug,
|
|
69
79
|
error,
|
|
70
80
|
event,
|
|
@@ -73,10 +83,15 @@ from src_py_lib.utils.logging import (
|
|
|
73
83
|
log_context,
|
|
74
84
|
logging_context,
|
|
75
85
|
logging_settings_from_config,
|
|
86
|
+
new_trace_context,
|
|
76
87
|
resolve_log_level_name,
|
|
88
|
+
sampled_traceparent,
|
|
77
89
|
stage,
|
|
78
90
|
startup_event,
|
|
79
91
|
submit_with_log_context,
|
|
92
|
+
trace_context,
|
|
93
|
+
trace_context_from_traceparent,
|
|
94
|
+
traceparent_header,
|
|
80
95
|
warning,
|
|
81
96
|
)
|
|
82
97
|
from src_py_lib.utils.tsv import write_tsv
|
|
@@ -116,6 +131,7 @@ __all__ = [
|
|
|
116
131
|
"GoogleSheetsError",
|
|
117
132
|
"HTTPClient",
|
|
118
133
|
"HTTPClientError",
|
|
134
|
+
"HTTPResponse",
|
|
119
135
|
"JSONDict",
|
|
120
136
|
"LinearClient",
|
|
121
137
|
"LinearClientConfig",
|
|
@@ -128,12 +144,22 @@ __all__ = [
|
|
|
128
144
|
"SlackPacer",
|
|
129
145
|
"SourcegraphClient",
|
|
130
146
|
"SourcegraphClientConfig",
|
|
147
|
+
"SourcegraphJaegerTraceError",
|
|
148
|
+
"SourcegraphJaegerTraceSummary",
|
|
149
|
+
"SourcegraphTrace",
|
|
150
|
+
"TraceContext",
|
|
131
151
|
"aliased_batched_query",
|
|
132
152
|
"config_field",
|
|
133
153
|
"config_snapshot",
|
|
134
154
|
"configure_logging",
|
|
135
155
|
"critical",
|
|
156
|
+
"current_trace_context",
|
|
136
157
|
"debug",
|
|
158
|
+
"decode_external_service_id",
|
|
159
|
+
"decode_repository_id",
|
|
160
|
+
"decode_sourcegraph_node_id",
|
|
161
|
+
"encode_repository_id",
|
|
162
|
+
"encode_sourcegraph_node_id",
|
|
137
163
|
"error",
|
|
138
164
|
"event",
|
|
139
165
|
"gh_cli_token",
|
|
@@ -153,18 +179,23 @@ __all__ = [
|
|
|
153
179
|
"logging_settings_from_config",
|
|
154
180
|
"log",
|
|
155
181
|
"log_context",
|
|
182
|
+
"new_trace_context",
|
|
156
183
|
"normalize_sourcegraph_endpoint",
|
|
157
184
|
"parse_args",
|
|
158
185
|
"pr_ref_from_url",
|
|
159
186
|
"quota_project_from_adc",
|
|
160
187
|
"resolve_log_level_name",
|
|
161
188
|
"save_json_cache",
|
|
189
|
+
"sampled_traceparent",
|
|
162
190
|
"slack_client_from_config",
|
|
163
191
|
"sourcegraph_client_from_config",
|
|
164
192
|
"stage",
|
|
165
193
|
"startup_event",
|
|
166
194
|
"stream_connection_nodes",
|
|
167
195
|
"submit_with_log_context",
|
|
196
|
+
"trace_context",
|
|
197
|
+
"trace_context_from_traceparent",
|
|
198
|
+
"traceparent_header",
|
|
168
199
|
"warning",
|
|
169
200
|
"write_tsv",
|
|
170
201
|
]
|
|
@@ -9,11 +9,13 @@ from dataclasses import dataclass, field
|
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
from typing import cast
|
|
11
11
|
|
|
12
|
-
from src_py_lib.utils.http import HTTPClient, HTTPClientError
|
|
12
|
+
from src_py_lib.utils.http import HTTPClient, HTTPClientError, HTTPResponse
|
|
13
13
|
from src_py_lib.utils.json_types import JSONDict, JSONValue, json_dict, json_list, json_str
|
|
14
14
|
from src_py_lib.utils.logging import event
|
|
15
15
|
|
|
16
16
|
_OPERATION_NAME_RE = re.compile(r"\b(?:query|mutation|subscription)\s+(\w+)")
|
|
17
|
+
HeaderProvider = Mapping[str, str] | Callable[[], Mapping[str, str]]
|
|
18
|
+
GraphQLResponseHook = Callable[[HTTPResponse, Mapping[str, str]], None]
|
|
17
19
|
|
|
18
20
|
GRAPHQL_INTROSPECTION_QUERY = """
|
|
19
21
|
query IntrospectionQuery {
|
|
@@ -130,10 +132,11 @@ class GraphQLClient:
|
|
|
130
132
|
"""POST JSON GraphQL operations and return the `data` object."""
|
|
131
133
|
|
|
132
134
|
url: str
|
|
133
|
-
headers:
|
|
135
|
+
headers: HeaderProvider
|
|
134
136
|
label: str
|
|
135
137
|
http: HTTPClient = field(default_factory=HTTPClient)
|
|
136
138
|
tolerate_partial_errors: bool = False
|
|
139
|
+
response_hook: GraphQLResponseHook | None = None
|
|
137
140
|
|
|
138
141
|
def execute(
|
|
139
142
|
self,
|
|
@@ -251,7 +254,16 @@ class GraphQLClient:
|
|
|
251
254
|
query_bytes=len(query.encode("utf-8")),
|
|
252
255
|
) as fields:
|
|
253
256
|
try:
|
|
254
|
-
|
|
257
|
+
request_headers = self._headers()
|
|
258
|
+
if self.response_hook is None:
|
|
259
|
+
payload = self.http.json(
|
|
260
|
+
"POST", self.url, headers=request_headers, json_body=body
|
|
261
|
+
)
|
|
262
|
+
else:
|
|
263
|
+
payload, response = self.http.json_response(
|
|
264
|
+
"POST", self.url, headers=request_headers, json_body=body
|
|
265
|
+
)
|
|
266
|
+
self.response_hook(response, request_headers)
|
|
255
267
|
except HTTPClientError as exception:
|
|
256
268
|
raise GraphQLError(
|
|
257
269
|
f"{self.label} GraphQL request failed: {exception}",
|
|
@@ -269,6 +281,11 @@ class GraphQLClient:
|
|
|
269
281
|
)
|
|
270
282
|
return data
|
|
271
283
|
|
|
284
|
+
def _headers(self) -> dict[str, str]:
|
|
285
|
+
if callable(self.headers):
|
|
286
|
+
return dict(self.headers())
|
|
287
|
+
return dict(self.headers)
|
|
288
|
+
|
|
272
289
|
|
|
273
290
|
def operation_name(query: str) -> str:
|
|
274
291
|
"""Extract the operation name from a GraphQL document."""
|