src-py-lib 0.1.1__tar.gz → 0.1.3__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.3/.github/workflows/ci.yml +16 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/.github/workflows/release.yml +76 -36
- src_py_lib-0.1.3/.github/workflows/validate.yml +135 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/AGENTS.md +11 -6
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/PKG-INFO +8 -1
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/README.md +7 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/pyproject.toml +2 -2
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/src/src_py_lib/__init__.py +32 -1
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/src/src_py_lib/clients/graphql.py +20 -3
- src_py_lib-0.1.3/src/src_py_lib/clients/sourcegraph.py +472 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/src/src_py_lib/utils/http.py +69 -3
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/src/src_py_lib/utils/logging.py +121 -12
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/tests/test_logging_http_clients.py +127 -4
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/uv.lock +1 -1
- src_py_lib-0.1.1/.github/workflows/ci.yml +0 -93
- 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.3}/.gitignore +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/.markdownlint-cli2.yaml +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/.python-version +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/LICENSE +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/SECURITY.md +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/renovate.json +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/src/src_py_lib/clients/__init__.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/src/src_py_lib/clients/github.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/src/src_py_lib/clients/google_sheets.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/src/src_py_lib/clients/linear.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/src/src_py_lib/clients/one_password.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/src/src_py_lib/clients/slack.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/src/src_py_lib/py.typed +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/src/src_py_lib/utils/__init__.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/src/src_py_lib/utils/config.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/src/src_py_lib/utils/json_cache.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/src/src_py_lib/utils/json_types.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/src/src_py_lib/utils/tsv.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/tests/test_import.py +0 -0
- {src_py_lib-0.1.1 → src_py_lib-0.1.3}/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,6 +23,13 @@ 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
|
+
build-package: false
|
|
32
|
+
|
|
26
33
|
wheel:
|
|
27
34
|
name: Build wheel
|
|
28
35
|
runs-on: ubuntu-24.04
|
|
@@ -45,10 +52,16 @@ jobs:
|
|
|
45
52
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
46
53
|
cache: pip
|
|
47
54
|
|
|
55
|
+
- name: Cache uv
|
|
56
|
+
uses: actions/cache@v5
|
|
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
|
-
run:
|
|
50
|
-
python -m pip install --upgrade pip
|
|
51
|
-
python -m pip install "uv==${UV_VERSION}"
|
|
64
|
+
run: python -m pip install "uv==${UV_VERSION}"
|
|
52
65
|
|
|
53
66
|
- name: Validate release inputs
|
|
54
67
|
id: release
|
|
@@ -62,6 +75,14 @@ jobs:
|
|
|
62
75
|
echo "::error title=Missing tag::Tag '${release_tag}' was not fetched. Create and push it before running this workflow."
|
|
63
76
|
exit 1
|
|
64
77
|
fi
|
|
78
|
+
tag_revision="$(git rev-list -n 1 "${release_tag}")"
|
|
79
|
+
git fetch --no-tags origin main
|
|
80
|
+
main_revision="$(git rev-parse origin/main)"
|
|
81
|
+
if ! git merge-base --is-ancestor "${tag_revision}" "${main_revision}"; then
|
|
82
|
+
echo "::error title=Tag is not on main::Tag '${release_tag}' points at ${tag_revision}, which is not reachable from origin/main."
|
|
83
|
+
echo "::error::Merge the release PR first, then tag the main commit."
|
|
84
|
+
exit 1
|
|
85
|
+
fi
|
|
65
86
|
|
|
66
87
|
project_version=$(uv run --frozen python - <<'PY'
|
|
67
88
|
import tomllib
|
|
@@ -77,22 +98,6 @@ jobs:
|
|
|
77
98
|
|
|
78
99
|
echo "tag=${release_tag}" >> "${GITHUB_OUTPUT}"
|
|
79
100
|
|
|
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
101
|
- name: Build distributions
|
|
97
102
|
id: build
|
|
98
103
|
run: |
|
|
@@ -115,23 +120,29 @@ jobs:
|
|
|
115
120
|
wheel_path="${project_wheels[0]}"
|
|
116
121
|
wheel_name="$(basename "${wheel_path}")"
|
|
117
122
|
source_distribution_path="${source_distributions[0]}"
|
|
118
|
-
|
|
123
|
+
source_distribution_name="$(basename "${source_distribution_path}")"
|
|
124
|
+
wheel_checksum_path="${wheel_path}.sha256"
|
|
125
|
+
source_distribution_checksum_path="${source_distribution_path}.sha256"
|
|
119
126
|
|
|
120
127
|
(
|
|
121
128
|
cd "$(dirname "${wheel_path}")"
|
|
122
|
-
shasum -a 256 "${wheel_name}" > "$(basename "${
|
|
129
|
+
shasum -a 256 "${wheel_name}" > "$(basename "${wheel_checksum_path}")"
|
|
130
|
+
shasum -a 256 "${source_distribution_name}" > "$(basename "${source_distribution_checksum_path}")"
|
|
123
131
|
)
|
|
124
132
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
133
|
+
{
|
|
134
|
+
echo "wheel_path=${wheel_path}"
|
|
135
|
+
echo "wheel_name=${wheel_name}"
|
|
136
|
+
echo "source_distribution_path=${source_distribution_path}"
|
|
137
|
+
echo "source_distribution_name=${source_distribution_name}"
|
|
138
|
+
echo "wheel_checksum_path=${wheel_checksum_path}"
|
|
139
|
+
echo "source_distribution_checksum_path=${source_distribution_checksum_path}"
|
|
140
|
+
} >> "${GITHUB_OUTPUT}"
|
|
129
141
|
|
|
130
142
|
- name: Smoke test installed wheel
|
|
131
143
|
run: |
|
|
132
144
|
python -m venv build/release/install-venv
|
|
133
145
|
. build/release/install-venv/bin/activate
|
|
134
|
-
python -m pip install --upgrade pip
|
|
135
146
|
python -m pip install "${{ steps.build.outputs.wheel_path }}"
|
|
136
147
|
python - <<'PY'
|
|
137
148
|
import os
|
|
@@ -147,6 +158,7 @@ jobs:
|
|
|
147
158
|
run: |
|
|
148
159
|
release_tag="${{ steps.release.outputs.tag }}"
|
|
149
160
|
wheel_name="${{ steps.build.outputs.wheel_name }}"
|
|
161
|
+
source_distribution_name="${{ steps.build.outputs.source_distribution_name }}"
|
|
150
162
|
notes_path="build/release/release-notes.md"
|
|
151
163
|
cat > "${notes_path}" <<EOF
|
|
152
164
|
## Install
|
|
@@ -163,13 +175,19 @@ jobs:
|
|
|
163
175
|
pip install "https://github.com/sourcegraph/src-py-lib/releases/download/${release_tag}/${wheel_name}"
|
|
164
176
|
\`\`\`
|
|
165
177
|
|
|
178
|
+
Source distribution:
|
|
179
|
+
|
|
180
|
+
\`\`\`sh
|
|
181
|
+
curl -LO "https://github.com/sourcegraph/src-py-lib/releases/download/${release_tag}/${source_distribution_name}"
|
|
182
|
+
\`\`\`
|
|
183
|
+
|
|
166
184
|
Or install this tag with uv:
|
|
167
185
|
|
|
168
186
|
\`\`\`sh
|
|
169
187
|
uv add "git+https://github.com/sourcegraph/src-py-lib.git@${release_tag}"
|
|
170
188
|
\`\`\`
|
|
171
189
|
|
|
172
|
-
Verify downloaded
|
|
190
|
+
Verify downloaded assets with the matching \`.sha256\` files.
|
|
173
191
|
EOF
|
|
174
192
|
echo "path=${notes_path}" >> "${GITHUB_OUTPUT}"
|
|
175
193
|
|
|
@@ -179,7 +197,9 @@ jobs:
|
|
|
179
197
|
name: src-py-lib-release
|
|
180
198
|
path: |
|
|
181
199
|
${{ steps.build.outputs.wheel_path }}
|
|
182
|
-
${{ steps.build.outputs.
|
|
200
|
+
${{ steps.build.outputs.source_distribution_path }}
|
|
201
|
+
${{ steps.build.outputs.wheel_checksum_path }}
|
|
202
|
+
${{ steps.build.outputs.source_distribution_checksum_path }}
|
|
183
203
|
${{ steps.notes.outputs.path }}
|
|
184
204
|
|
|
185
205
|
- name: Upload PyPI artifact
|
|
@@ -190,22 +210,41 @@ jobs:
|
|
|
190
210
|
${{ steps.build.outputs.wheel_path }}
|
|
191
211
|
${{ steps.build.outputs.source_distribution_path }}
|
|
192
212
|
|
|
213
|
+
github-release:
|
|
214
|
+
name: Publish GitHub release assets
|
|
215
|
+
needs: [validate, wheel]
|
|
216
|
+
runs-on: ubuntu-24.04
|
|
217
|
+
|
|
218
|
+
steps:
|
|
219
|
+
- name: Download release assets
|
|
220
|
+
uses: actions/download-artifact@v7
|
|
221
|
+
with:
|
|
222
|
+
name: src-py-lib-release
|
|
223
|
+
path: release-assets
|
|
224
|
+
|
|
193
225
|
- name: Publish GitHub release assets
|
|
194
226
|
env:
|
|
195
227
|
GH_TOKEN: ${{ github.token }}
|
|
196
228
|
run: |
|
|
197
|
-
release_tag="${{
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
229
|
+
release_tag="${{ github.event.inputs.tag || github.ref_name }}"
|
|
230
|
+
notes_path="$(find release-assets -name release-notes.md -print -quit)"
|
|
231
|
+
mapfile -t release_assets < <(find release-assets -type f ! -name release-notes.md | sort)
|
|
232
|
+
|
|
233
|
+
if [[ -z "${notes_path}" ]]; then
|
|
234
|
+
echo "::error title=Missing release notes::release-notes.md was not found in release artifact."
|
|
235
|
+
exit 1
|
|
236
|
+
fi
|
|
237
|
+
if [[ "${#release_assets[@]}" -eq 0 ]]; then
|
|
238
|
+
echo "::error title=Missing release assets::No release assets were downloaded."
|
|
239
|
+
exit 1
|
|
240
|
+
fi
|
|
201
241
|
|
|
202
242
|
if gh release view "${release_tag}" >/dev/null 2>&1; then
|
|
203
243
|
gh release edit "${release_tag}" --title "${release_tag}" --notes-file "${notes_path}"
|
|
204
|
-
gh release upload "${release_tag}" "${
|
|
244
|
+
gh release upload "${release_tag}" "${release_assets[@]}" --clobber
|
|
205
245
|
else
|
|
206
246
|
gh release create "${release_tag}" \
|
|
207
|
-
"${
|
|
208
|
-
"${checksum_path}" \
|
|
247
|
+
"${release_assets[@]}" \
|
|
209
248
|
--title "${release_tag}" \
|
|
210
249
|
--notes-file "${notes_path}" \
|
|
211
250
|
--verify-tag
|
|
@@ -213,7 +252,7 @@ jobs:
|
|
|
213
252
|
|
|
214
253
|
pypi:
|
|
215
254
|
name: Publish PyPI package
|
|
216
|
-
needs: wheel
|
|
255
|
+
needs: [validate, wheel]
|
|
217
256
|
runs-on: ubuntu-24.04
|
|
218
257
|
permissions:
|
|
219
258
|
contents: read
|
|
@@ -233,3 +272,4 @@ jobs:
|
|
|
233
272
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
234
273
|
with:
|
|
235
274
|
packages-dir: dist
|
|
275
|
+
skip-existing: true
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
name: Validate
|
|
2
|
+
|
|
3
|
+
on:
|
|
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
|
|
10
|
+
build-package:
|
|
11
|
+
description: "Build and smoke-test package artifacts. Release builds do this separately."
|
|
12
|
+
required: false
|
|
13
|
+
type: boolean
|
|
14
|
+
default: true
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
defaults:
|
|
20
|
+
run:
|
|
21
|
+
shell: bash
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
package:
|
|
25
|
+
name: Validate package
|
|
26
|
+
runs-on: ubuntu-24.04
|
|
27
|
+
env:
|
|
28
|
+
ACTIONLINT_VERSION: "1.7.12"
|
|
29
|
+
IMPORT_NAME: src_py_lib
|
|
30
|
+
MARKDOWNLINT_CLI2_VERSION: "0.22.1"
|
|
31
|
+
PYTHON_VERSION: "3.11"
|
|
32
|
+
UV_VERSION: "0.11.7"
|
|
33
|
+
|
|
34
|
+
steps:
|
|
35
|
+
- name: Check out code
|
|
36
|
+
uses: actions/checkout@v6
|
|
37
|
+
with:
|
|
38
|
+
persist-credentials: false
|
|
39
|
+
ref: ${{ inputs.ref || github.ref }}
|
|
40
|
+
|
|
41
|
+
- name: Cache actionlint
|
|
42
|
+
id: cache-actionlint
|
|
43
|
+
uses: actions/cache@v5
|
|
44
|
+
with:
|
|
45
|
+
path: ~/.local/bin/actionlint
|
|
46
|
+
key: actionlint-${{ runner.os }}-${{ runner.arch }}-${{ env.ACTIONLINT_VERSION }}
|
|
47
|
+
|
|
48
|
+
- name: Install actionlint
|
|
49
|
+
if: steps.cache-actionlint.outputs.cache-hit != 'true'
|
|
50
|
+
run: |
|
|
51
|
+
mkdir -p "${HOME}/.local/bin"
|
|
52
|
+
asset="actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"
|
|
53
|
+
checksums="actionlint_${ACTIONLINT_VERSION}_checksums.txt"
|
|
54
|
+
base_url="https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}"
|
|
55
|
+
|
|
56
|
+
curl -fsSLO "${base_url}/${asset}"
|
|
57
|
+
curl -fsSLO "${base_url}/${checksums}"
|
|
58
|
+
grep " ${asset}$" "${checksums}" | sha256sum --check
|
|
59
|
+
tar -xzf "${asset}" -C "${HOME}/.local/bin" actionlint
|
|
60
|
+
chmod 0755 "${HOME}/.local/bin/actionlint"
|
|
61
|
+
|
|
62
|
+
- name: Lint GitHub Actions
|
|
63
|
+
run: |
|
|
64
|
+
"${HOME}/.local/bin/actionlint"
|
|
65
|
+
|
|
66
|
+
- name: Cache npm
|
|
67
|
+
uses: actions/cache@v5
|
|
68
|
+
with:
|
|
69
|
+
path: ~/.npm
|
|
70
|
+
key: npm-${{ runner.os }}-markdownlint-cli2-${{ env.MARKDOWNLINT_CLI2_VERSION }}
|
|
71
|
+
|
|
72
|
+
- name: Lint Markdown
|
|
73
|
+
run: npx --yes "markdownlint-cli2@${MARKDOWNLINT_CLI2_VERSION}"
|
|
74
|
+
|
|
75
|
+
- name: Set up Python
|
|
76
|
+
uses: actions/setup-python@v6
|
|
77
|
+
with:
|
|
78
|
+
python-version: ${{ env.PYTHON_VERSION }}
|
|
79
|
+
cache: pip
|
|
80
|
+
|
|
81
|
+
- name: Cache uv
|
|
82
|
+
uses: actions/cache@v5
|
|
83
|
+
with:
|
|
84
|
+
path: ~/.cache/uv
|
|
85
|
+
key: uv-${{ runner.os }}-py${{ env.PYTHON_VERSION }}-${{ hashFiles('uv.lock') }}
|
|
86
|
+
restore-keys: |
|
|
87
|
+
uv-${{ runner.os }}-py${{ env.PYTHON_VERSION }}-
|
|
88
|
+
|
|
89
|
+
- name: Install uv
|
|
90
|
+
run: python -m pip install "uv==${UV_VERSION}"
|
|
91
|
+
|
|
92
|
+
- name: Validate lockfile
|
|
93
|
+
run: uv lock --check
|
|
94
|
+
|
|
95
|
+
- name: Lint Python
|
|
96
|
+
run: uv run --frozen ruff check .
|
|
97
|
+
|
|
98
|
+
- name: Check Python formatting
|
|
99
|
+
run: uv run --frozen ruff format --check .
|
|
100
|
+
|
|
101
|
+
- name: Type check
|
|
102
|
+
run: uv run --frozen pyright
|
|
103
|
+
|
|
104
|
+
- name: Run tests
|
|
105
|
+
run: uv run --frozen python -m unittest discover -s tests
|
|
106
|
+
|
|
107
|
+
- name: Smoke test source checkout import
|
|
108
|
+
run: |
|
|
109
|
+
uv run --frozen python - <<'PY'
|
|
110
|
+
import os
|
|
111
|
+
|
|
112
|
+
import src_py_lib
|
|
113
|
+
|
|
114
|
+
if src_py_lib.__name__ != os.environ["IMPORT_NAME"]:
|
|
115
|
+
raise SystemExit(f"unexpected import name: {src_py_lib.__name__}")
|
|
116
|
+
PY
|
|
117
|
+
|
|
118
|
+
- name: Build wheel
|
|
119
|
+
if: inputs.build-package
|
|
120
|
+
run: uv build --wheel --out-dir dist --no-create-gitignore
|
|
121
|
+
|
|
122
|
+
- name: Smoke test installed wheel
|
|
123
|
+
if: inputs.build-package
|
|
124
|
+
run: |
|
|
125
|
+
python -m venv build/ci-venv
|
|
126
|
+
. build/ci-venv/bin/activate
|
|
127
|
+
python -m pip install dist/*.whl
|
|
128
|
+
python - <<'PY'
|
|
129
|
+
import os
|
|
130
|
+
|
|
131
|
+
import src_py_lib
|
|
132
|
+
|
|
133
|
+
if src_py_lib.__name__ != os.environ["IMPORT_NAME"]:
|
|
134
|
+
raise SystemExit(f"unexpected import name: {src_py_lib.__name__}")
|
|
135
|
+
PY
|
|
@@ -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.3
|
|
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.3"
|
|
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."""
|