src-auth-perms-sync 0.2.1__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.
Files changed (62) hide show
  1. src_auth_perms_sync-0.2.1/.env.example +36 -0
  2. src_auth_perms_sync-0.2.1/.github/workflows/ci.yml +77 -0
  3. src_auth_perms_sync-0.2.1/.github/workflows/release.yml +356 -0
  4. src_auth_perms_sync-0.2.1/.gitignore +23 -0
  5. src_auth_perms_sync-0.2.1/.markdownlint-cli2.yaml +9 -0
  6. src_auth_perms_sync-0.2.1/.python-version +1 -0
  7. src_auth_perms_sync-0.2.1/AGENTS.md +288 -0
  8. src_auth_perms_sync-0.2.1/LICENSE +21 -0
  9. src_auth_perms_sync-0.2.1/PKG-INFO +256 -0
  10. src_auth_perms_sync-0.2.1/README.md +233 -0
  11. src_auth_perms_sync-0.2.1/SECURITY.md +3 -0
  12. src_auth_perms_sync-0.2.1/dev/TODO.md +81 -0
  13. src_auth_perms_sync-0.2.1/dev/dead-code-audit.md +195 -0
  14. src_auth_perms_sync-0.2.1/dev/git-worktrees.md +89 -0
  15. src_auth_perms_sync-0.2.1/dev/hooks/pre-commit +28 -0
  16. src_auth_perms_sync-0.2.1/dev/python-versions.md +40 -0
  17. src_auth_perms_sync-0.2.1/dev/test-command-permutations.py +1817 -0
  18. src_auth_perms_sync-0.2.1/dev/test-plan.md +207 -0
  19. src_auth_perms_sync-0.2.1/maps-example.yaml +39 -0
  20. src_auth_perms_sync-0.2.1/pyproject.toml +66 -0
  21. src_auth_perms_sync-0.2.1/renovate.json +14 -0
  22. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/__init__.py +1 -0
  23. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/__main__.py +6 -0
  24. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/cli.py +646 -0
  25. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/orgs/__init__.py +1 -0
  26. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/orgs/command.py +7 -0
  27. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/orgs/queries.py +44 -0
  28. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/orgs/sync.py +1167 -0
  29. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/orgs/types.py +103 -0
  30. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/permissions/__init__.py +1 -0
  31. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/permissions/apply.py +420 -0
  32. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/permissions/command.py +918 -0
  33. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/permissions/full_set.py +880 -0
  34. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/permissions/mapping.py +627 -0
  35. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/permissions/maps.py +291 -0
  36. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/permissions/queries.py +180 -0
  37. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/permissions/restore.py +913 -0
  38. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/permissions/snapshot.py +1502 -0
  39. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/permissions/sourcegraph.py +392 -0
  40. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/permissions/types.py +116 -0
  41. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/permissions/workflow.py +526 -0
  42. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/shared/__init__.py +1 -0
  43. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/shared/backups.py +119 -0
  44. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/shared/id_codec.py +67 -0
  45. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/shared/queries.py +65 -0
  46. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/shared/run_context.py +34 -0
  47. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/shared/saml_groups.py +267 -0
  48. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/shared/site_config.py +366 -0
  49. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/shared/sourcegraph.py +69 -0
  50. src_auth_perms_sync-0.2.1/src/src_auth_perms_sync/shared/types.py +69 -0
  51. src_auth_perms_sync-0.2.1/tests/__init__.py +1 -0
  52. src_auth_perms_sync-0.2.1/tests/integration/__init__.py +1 -0
  53. src_auth_perms_sync-0.2.1/tests/integration/test_cli_entrypoint.py +20 -0
  54. src_auth_perms_sync-0.2.1/tests/unit/__init__.py +1 -0
  55. src_auth_perms_sync-0.2.1/tests/unit/test_backups.py +95 -0
  56. src_auth_perms_sync-0.2.1/tests/unit/test_cli_config.py +295 -0
  57. src_auth_perms_sync-0.2.1/tests/unit/test_id_codec.py +26 -0
  58. src_auth_perms_sync-0.2.1/tests/unit/test_maps.py +75 -0
  59. src_auth_perms_sync-0.2.1/tests/unit/test_restore.py +106 -0
  60. src_auth_perms_sync-0.2.1/tests/unit/test_saml_groups.py +242 -0
  61. src_auth_perms_sync-0.2.1/tests/unit/test_snapshot.py +384 -0
  62. src_auth_perms_sync-0.2.1/uv.lock +392 -0
@@ -0,0 +1,36 @@
1
+ # Environment variables can be provided in either an .env file, or the shell environment
2
+ # Defaults match `uv run src-auth-perms-sync --help`
3
+
4
+ # .env file path is CLI-only: `--env-file PATH` (default: .env)
5
+
6
+ # Sourcegraph instance URL
7
+ # Default: https://sourcegraph.com
8
+ SRC_ENDPOINT="https://sourcegraph.example.com"
9
+
10
+ # Access token from a user account with Site Admin permissions
11
+ # Generate at: $SRC_ENDPOINT/settings/tokens
12
+ # Required
13
+ # Default: None
14
+ SRC_ACCESS_TOKEN="sgp_..."
15
+
16
+ # Logging verbosity
17
+ # Default: INFO
18
+ # Options: DEBUG, INFO, WARNING, ERROR, CRITICAL
19
+ # SRC_LOG_LEVEL="DEBUG"
20
+
21
+ # Concurrent Sourcegraph API worker threads
22
+ # Default: 32
23
+ # SRC_AUTH_PERMS_SYNC_PARALLELISM=32
24
+
25
+ # Max attempts per HTTP request before giving up
26
+ # Default: 5
27
+ # SRC_AUTH_PERMS_SYNC_MAX_ATTEMPTS=5
28
+
29
+ # With mutating commands: skip before/after snapshots and validation
30
+ # Default: false
31
+ # SRC_AUTH_PERMS_SYNC_NO_BACKUP=false
32
+
33
+ # Seconds between logging compute resource samples
34
+ # Default: 10
35
+ # Set 0 to disable
36
+ # SRC_AUTH_PERMS_SYNC_SAMPLE_INTERVAL=10
@@ -0,0 +1,77 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches:
7
+ - main
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ defaults:
13
+ run:
14
+ shell: bash
15
+
16
+ jobs:
17
+ test:
18
+ name: Build and test
19
+ runs-on: ubuntu-24.04
20
+ env:
21
+ PACKAGE_NAME: src-auth-perms-sync
22
+ PYTHON_VERSION: "3.11"
23
+ UV_VERSION: "0.11.7"
24
+
25
+ steps:
26
+ - name: Check out code
27
+ uses: actions/checkout@v6
28
+ with:
29
+ fetch-depth: 0
30
+ persist-credentials: false
31
+
32
+ - name: Set up Python
33
+ uses: actions/setup-python@v6
34
+ with:
35
+ python-version: ${{ env.PYTHON_VERSION }}
36
+ cache: pip
37
+
38
+ - name: Install uv
39
+ run: |
40
+ python -m pip install --upgrade pip
41
+ python -m pip install "uv==${UV_VERSION}"
42
+
43
+ - name: Validate lockfile
44
+ run: uv lock --check
45
+
46
+ - name: Lint
47
+ run: uv run --frozen ruff check .
48
+
49
+ - name: Check formatting
50
+ run: uv run --frozen ruff format --check .
51
+
52
+ - name: Type check
53
+ run: uv run --frozen pyright
54
+
55
+ - name: Run tests
56
+ run: uv run --frozen python -m unittest discover -s tests
57
+
58
+ - name: Smoke test source checkout CLI
59
+ run: uv run --frozen src-auth-perms-sync --help >/tmp/src-auth-perms-sync-help.txt
60
+
61
+ - name: Build wheel
62
+ run: uv build --wheel --out-dir dist --no-create-gitignore
63
+
64
+ - name: Smoke test installed wheel
65
+ run: |
66
+ python -m venv build/ci-venv
67
+ . build/ci-venv/bin/activate
68
+ python -m pip install --upgrade pip
69
+ python -m pip install dist/src_auth_perms_sync-*.whl
70
+ src-auth-perms-sync --help >/tmp/src-auth-perms-sync-installed-help.txt
71
+ python -m src_auth_perms_sync --help >/tmp/src-auth-perms-sync-module-help.txt
72
+
73
+ - name: Upload wheel artifact
74
+ uses: actions/upload-artifact@v7
75
+ with:
76
+ name: src-auth-perms-sync-wheel
77
+ path: dist/*.whl
@@ -0,0 +1,356 @@
1
+ name: Build customer release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+ inputs:
9
+ tag:
10
+ description: "Existing release tag to publish, for example v0.1.0"
11
+ required: true
12
+ type: string
13
+
14
+ permissions:
15
+ contents: write
16
+
17
+ concurrency:
18
+ group: release-${{ github.event.inputs.tag || github.ref_name }}
19
+ cancel-in-progress: false
20
+
21
+ defaults:
22
+ run:
23
+ shell: bash
24
+
25
+ jobs:
26
+ wheelhouse:
27
+ name: ${{ matrix.platform }}-py311 wheelhouse
28
+ runs-on: ${{ matrix.runs_on }}
29
+ strategy:
30
+ fail-fast: false
31
+ # The first matrix leg creates the release; later legs upload more assets.
32
+ max-parallel: 1
33
+ matrix:
34
+ include:
35
+ - platform: linux-x86_64
36
+ runs_on: ubuntu-24.04
37
+ asset_basename: src-auth-perms-sync-linux-x64
38
+ target_description: Linux x64
39
+ expected_machine: x86_64
40
+ - platform: macos-arm64
41
+ runs_on: macos-26
42
+ asset_basename: src-auth-perms-sync-macos-arm64
43
+ target_description: macOS arm64
44
+ expected_machine: arm64
45
+ env:
46
+ ASSET_BASENAME: ${{ matrix.asset_basename }}
47
+ PACKAGE_NAME: src-auth-perms-sync
48
+ PYTHON_VERSION: "3.11"
49
+ TARGET_DESCRIPTION: ${{ matrix.target_description }}
50
+ UV_VERSION: "0.11.7"
51
+
52
+ steps:
53
+ - name: Check out release ref
54
+ uses: actions/checkout@v6
55
+ with:
56
+ fetch-depth: 0
57
+ persist-credentials: false
58
+ ref: ${{ github.event.inputs.tag || github.ref }}
59
+
60
+ - name: Set up Python
61
+ uses: actions/setup-python@v6
62
+ with:
63
+ python-version: ${{ env.PYTHON_VERSION }}
64
+ cache: pip
65
+
66
+ - name: Install build tools
67
+ run: |
68
+ python -m pip install --upgrade pip
69
+ python -m pip install "uv==${UV_VERSION}"
70
+
71
+ - name: Validate release inputs
72
+ id: release
73
+ run: |
74
+ release_tag="${{ github.event.inputs.tag || github.ref_name }}"
75
+ if [[ ! "${release_tag}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
76
+ echo "::error title=Invalid release tag::Use a vMAJOR.MINOR.PATCH tag, got '${release_tag}'."
77
+ exit 1
78
+ fi
79
+ if ! git rev-parse --verify --quiet "refs/tags/${release_tag}" >/dev/null; then
80
+ echo "::error title=Missing tag::Tag '${release_tag}' was not fetched. Create and push it before running this workflow."
81
+ exit 1
82
+ fi
83
+ tag_revision="$(git rev-list -n 1 "${release_tag}")"
84
+ git fetch --no-tags origin main
85
+ main_revision="$(git rev-parse origin/main)"
86
+ if ! git merge-base --is-ancestor "${tag_revision}" "${main_revision}"; then
87
+ echo "::error title=Tag is not on main::Tag '${release_tag}' points at ${tag_revision}, which is not reachable from origin/main."
88
+ echo "::error::Merge the release PR first, then tag the main commit."
89
+ exit 1
90
+ fi
91
+
92
+ project_version=$(uv run --frozen python - <<'PY'
93
+ import tomllib
94
+
95
+ with open("pyproject.toml", "rb") as pyproject_file:
96
+ print(tomllib.load(pyproject_file)["project"]["version"])
97
+ PY
98
+ )
99
+ if [[ "v${project_version}" != "${release_tag}" ]]; then
100
+ echo "::error title=Version mismatch::pyproject.toml version '${project_version}' does not match tag '${release_tag}'."
101
+ exit 1
102
+ fi
103
+
104
+ echo "tag=${release_tag}" >> "${GITHUB_OUTPUT}"
105
+
106
+ - name: Validate package
107
+ run: |
108
+ actual_machine=$(uv run --frozen python - <<'PY'
109
+ import platform
110
+
111
+ print(platform.machine())
112
+ PY
113
+ )
114
+ if [[ "${actual_machine}" != "${{ matrix.expected_machine }}" ]]; then
115
+ echo "::error title=Wrong runner architecture::Expected ${{ matrix.expected_machine }}, got ${actual_machine}."
116
+ exit 1
117
+ fi
118
+
119
+ uv lock --check
120
+ uv run --frozen ruff check src/src_auth_perms_sync/
121
+ uv run --frozen ruff format --check src/src_auth_perms_sync/
122
+ uv run --frozen pyright
123
+ uv run --frozen src-auth-perms-sync --help >/tmp/src-auth-perms-sync-help.txt
124
+
125
+ - name: Build wheelhouse tarball
126
+ id: build
127
+ run: |
128
+ release_tag="${{ steps.release.outputs.tag }}"
129
+ release_dir="build/release/${ASSET_BASENAME}"
130
+ wheelhouse_dir="${release_dir}/wheelhouse"
131
+ dist_dir="build/release/dist"
132
+ requirements_file="build/release/requirements.txt"
133
+ runtime_requirements_file="build/release/runtime-requirements.txt"
134
+ asset_path="build/release/${ASSET_BASENAME}.tar.gz"
135
+ checksum_path="${asset_path}.sha256"
136
+
137
+ rm -rf build/release
138
+ mkdir -p "${wheelhouse_dir}" "${dist_dir}"
139
+
140
+ uv build --wheel --out-dir "${dist_dir}" --no-create-gitignore
141
+ project_wheels=("${dist_dir}"/*.whl)
142
+ if [[ "${#project_wheels[@]}" -ne 1 ]]; then
143
+ echo "::error title=Unexpected wheel count::Expected one project wheel, found ${#project_wheels[@]}."
144
+ exit 1
145
+ fi
146
+ project_wheel_path="${project_wheels[0]}"
147
+ project_wheel_name="$(basename "${project_wheel_path}")"
148
+ if [[ ! -f "${project_wheel_path}" ]]; then
149
+ echo "::error title=Missing project wheel::Expected ${project_wheel_path} to exist."
150
+ exit 1
151
+ fi
152
+
153
+ uv export \
154
+ --no-dev \
155
+ --no-emit-project \
156
+ --no-hashes \
157
+ --no-header \
158
+ --no-annotate \
159
+ --frozen \
160
+ --output-file "${requirements_file}"
161
+
162
+ cp "${requirements_file}" "${runtime_requirements_file}"
163
+ if grep -q '^\./' "${runtime_requirements_file}"; then
164
+ echo "::error title=Unexpected local dependency::Runtime requirements must resolve from PyPI."
165
+ exit 1
166
+ fi
167
+
168
+ python -m pip wheel \
169
+ --only-binary=:all: \
170
+ --wheel-dir "${wheelhouse_dir}" \
171
+ --requirement "${runtime_requirements_file}"
172
+
173
+ cp "${project_wheel_path}" "${wheelhouse_dir}/"
174
+ src_py_lib_wheels=("${wheelhouse_dir}"/src_py_lib-*.whl)
175
+ if [[ "${#src_py_lib_wheels[@]}" -ne 1 ]]; then
176
+ echo "::error title=Unexpected src-py-lib wheel count::Expected one src-py-lib wheel, found ${#src_py_lib_wheels[@]}."
177
+ exit 1
178
+ fi
179
+
180
+ cat > "${wheelhouse_dir}/INSTALL.txt" <<EOF
181
+ # src-auth-perms-sync ${release_tag} offline install
182
+
183
+ This wheelhouse targets ${TARGET_DESCRIPTION} with Python 3.11.
184
+
185
+ tar -xzf ${ASSET_BASENAME}.tar.gz
186
+ python3.11 -m venv .venv
187
+ . .venv/bin/activate
188
+ pip install --no-index --find-links ./wheelhouse ${PACKAGE_NAME}
189
+ src-auth-perms-sync --help
190
+
191
+ Connected install from PyPI:
192
+
193
+ pip install ${PACKAGE_NAME}
194
+
195
+ GitHub release asset install, using the same project wheel uploaded to PyPI:
196
+
197
+ pip install "https://github.com/sourcegraph/src-auth-perms-sync/releases/download/${release_tag}/${project_wheel_name}"
198
+ EOF
199
+
200
+ (cd "${wheelhouse_dir}" && shasum -a 256 *.whl > WHEELS.sha256)
201
+
202
+ test -f "${project_wheel_path}"
203
+ test -f "${wheelhouse_dir}"/src_auth_perms_sync-*.whl
204
+ test -f "${wheelhouse_dir}"/src_py_lib-*.whl
205
+ if find "${wheelhouse_dir}" -type f \
206
+ ! -name '*.whl' \
207
+ ! -name INSTALL.txt \
208
+ ! -name WHEELS.sha256 \
209
+ | grep .; then
210
+ echo "::error title=Unexpected wheelhouse content::Wheelhouse contains non-wheel payloads."
211
+ exit 1
212
+ fi
213
+
214
+ tar -C "${release_dir}" -czf "${asset_path}" wheelhouse
215
+ (
216
+ cd "$(dirname "${asset_path}")"
217
+ shasum -a 256 "$(basename "${asset_path}")" > "$(basename "${checksum_path}")"
218
+ )
219
+
220
+ echo "asset_path=${asset_path}" >> "${GITHUB_OUTPUT}"
221
+ echo "checksum_path=${checksum_path}" >> "${GITHUB_OUTPUT}"
222
+ echo "project_wheel_path=${project_wheel_path}" >> "${GITHUB_OUTPUT}"
223
+ echo "project_wheel_name=${project_wheel_name}" >> "${GITHUB_OUTPUT}"
224
+
225
+ - name: Validate offline install from tarball
226
+ run: |
227
+ validation_dir=$(mktemp -d)
228
+ tar -xzf "${{ steps.build.outputs.asset_path }}" -C "${validation_dir}"
229
+
230
+ python3.11 -m venv "${validation_dir}/.venv"
231
+ . "${validation_dir}/.venv/bin/activate"
232
+
233
+ PIP_CACHE_DIR="${validation_dir}/pip-cache" \
234
+ GIT_ALLOW_PROTOCOL=file \
235
+ pip install \
236
+ --no-cache-dir \
237
+ --no-index \
238
+ --find-links "${validation_dir}/wheelhouse" \
239
+ "${PACKAGE_NAME}"
240
+ src-auth-perms-sync --help >/tmp/src-auth-perms-sync-release-help.txt
241
+
242
+ - name: Write release notes
243
+ id: notes
244
+ run: |
245
+ release_tag="${{ steps.release.outputs.tag }}"
246
+ project_wheel_name="${{ steps.build.outputs.project_wheel_name }}"
247
+ notes_path="build/release/release-notes.md"
248
+ cat > "${notes_path}" <<EOF
249
+ ## Customer install
250
+
251
+ ### Restricted/offline Linux x64 + Python 3.11 install
252
+
253
+ Download \`src-auth-perms-sync-linux-x64.tar.gz\`, then run:
254
+
255
+ \`\`\`sh
256
+ tar -xzf src-auth-perms-sync-linux-x64.tar.gz
257
+ python3.11 -m venv .venv
258
+ . .venv/bin/activate
259
+ pip install --no-index --find-links ./wheelhouse ${PACKAGE_NAME}
260
+ src-auth-perms-sync --help
261
+ \`\`\`
262
+
263
+ ### Restricted/offline macOS arm64 + Python 3.11 install
264
+
265
+ Download \`src-auth-perms-sync-macos-arm64.tar.gz\`, then run:
266
+
267
+ \`\`\`sh
268
+ tar -xzf src-auth-perms-sync-macos-arm64.tar.gz
269
+ python3.11 -m venv .venv
270
+ . .venv/bin/activate
271
+ pip install --no-index --find-links ./wheelhouse ${PACKAGE_NAME}
272
+ src-auth-perms-sync --help
273
+ \`\`\`
274
+
275
+ The tarball includes this project, \`src-py-lib\`, and all runtime wheels.
276
+ Verify the download with the matching \`.sha256\` file.
277
+
278
+ ### Connected PyPI install
279
+
280
+ \`\`\`sh
281
+ pip install ${PACKAGE_NAME}
282
+ \`\`\`
283
+
284
+ ### GitHub release asset install
285
+
286
+ \`\`\`sh
287
+ pip install "https://github.com/sourcegraph/src-auth-perms-sync/releases/download/${release_tag}/${project_wheel_name}"
288
+ \`\`\`
289
+ EOF
290
+ echo "path=${notes_path}" >> "${GITHUB_OUTPUT}"
291
+
292
+ - name: Upload workflow artifact
293
+ uses: actions/upload-artifact@v7
294
+ with:
295
+ name: ${{ env.ASSET_BASENAME }}
296
+ path: |
297
+ ${{ steps.build.outputs.asset_path }}
298
+ ${{ steps.build.outputs.checksum_path }}
299
+ ${{ steps.build.outputs.project_wheel_path }}
300
+ ${{ steps.notes.outputs.path }}
301
+
302
+ - name: Upload PyPI artifact
303
+ if: matrix.platform == 'linux-x86_64'
304
+ uses: actions/upload-artifact@v7
305
+ with:
306
+ name: pypi-distributions
307
+ path: ${{ steps.build.outputs.project_wheel_path }}
308
+
309
+ - name: Publish GitHub release assets
310
+ env:
311
+ GH_TOKEN: ${{ github.token }}
312
+ run: |
313
+ release_tag="${{ steps.release.outputs.tag }}"
314
+ asset_path="${{ steps.build.outputs.asset_path }}"
315
+ checksum_path="${{ steps.build.outputs.checksum_path }}"
316
+ project_wheel_path="${{ steps.build.outputs.project_wheel_path }}"
317
+ notes_path="${{ steps.notes.outputs.path }}"
318
+ release_assets=("${asset_path}" "${checksum_path}")
319
+
320
+ if [[ "${{ matrix.platform }}" == "linux-x86_64" ]]; then
321
+ release_assets+=("${project_wheel_path}")
322
+ fi
323
+
324
+ if gh release view "${release_tag}" >/dev/null 2>&1; then
325
+ gh release edit "${release_tag}" --title "${release_tag}" --notes-file "${notes_path}"
326
+ gh release upload "${release_tag}" "${release_assets[@]}" --clobber
327
+ else
328
+ gh release create "${release_tag}" \
329
+ "${release_assets[@]}" \
330
+ --title "${release_tag}" \
331
+ --notes-file "${notes_path}" \
332
+ --verify-tag
333
+ fi
334
+
335
+ pypi:
336
+ name: Publish PyPI package
337
+ needs: wheelhouse
338
+ runs-on: ubuntu-24.04
339
+ permissions:
340
+ contents: read
341
+ id-token: write
342
+ environment:
343
+ name: pypi
344
+ url: https://pypi.org/project/src-auth-perms-sync/
345
+
346
+ steps:
347
+ - name: Download built distribution
348
+ uses: actions/download-artifact@v7
349
+ with:
350
+ name: pypi-distributions
351
+ path: dist
352
+
353
+ - name: Publish PyPI package
354
+ uses: pypa/gh-action-pypi-publish@release/v1
355
+ with:
356
+ packages-dir: dist
@@ -0,0 +1,23 @@
1
+ # Ignore
2
+ __pycache__
3
+ .DS_Store
4
+ .playwright-mcp
5
+ .pypirc
6
+ .pyright
7
+ .pytest_cache
8
+ .ruff_cache
9
+ .venv
10
+ *.env*
11
+ *.gql
12
+ *.py[cod]
13
+ *.py[oc]
14
+ *.yaml
15
+ build/
16
+ dist/
17
+ src-auth-perms-sync-runs/
18
+ wheels/
19
+
20
+ # Allow
21
+ !.env.example
22
+ !.markdownlint-cli2.yaml
23
+ !maps-example.yaml
@@ -0,0 +1,9 @@
1
+ globs:
2
+ - "**/*.md"
3
+ ignores:
4
+ - ".venv/**"
5
+ - "build/**"
6
+ - "dist/**"
7
+ config:
8
+ MD013:
9
+ line_length: 100
@@ -0,0 +1 @@
1
+ 3.11