linux-mirror-bench 0.1.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 (60) hide show
  1. linux_mirror_bench-0.1.1/.dockerignore +28 -0
  2. linux_mirror_bench-0.1.1/.editorconfig +18 -0
  3. linux_mirror_bench-0.1.1/.github/ISSUE_TEMPLATE/bug_report.yml +70 -0
  4. linux_mirror_bench-0.1.1/.github/ISSUE_TEMPLATE/config.yml +6 -0
  5. linux_mirror_bench-0.1.1/.github/ISSUE_TEMPLATE/feature_request.yml +37 -0
  6. linux_mirror_bench-0.1.1/.github/PULL_REQUEST_TEMPLATE.md +32 -0
  7. linux_mirror_bench-0.1.1/.github/dependabot.yml +43 -0
  8. linux_mirror_bench-0.1.1/.github/workflows/ci.yml +157 -0
  9. linux_mirror_bench-0.1.1/.github/workflows/release-please.yml +33 -0
  10. linux_mirror_bench-0.1.1/.github/workflows/release.yml +155 -0
  11. linux_mirror_bench-0.1.1/.gitignore +72 -0
  12. linux_mirror_bench-0.1.1/.markdownlint.yaml +7 -0
  13. linux_mirror_bench-0.1.1/.pre-commit-config.yaml +101 -0
  14. linux_mirror_bench-0.1.1/.release-please-config.json +6 -0
  15. linux_mirror_bench-0.1.1/.release-please-manifest.json +3 -0
  16. linux_mirror_bench-0.1.1/.tool-versions +1 -0
  17. linux_mirror_bench-0.1.1/.yamllint.yaml +11 -0
  18. linux_mirror_bench-0.1.1/AGENTS.md +128 -0
  19. linux_mirror_bench-0.1.1/CHANGELOG.md +49 -0
  20. linux_mirror_bench-0.1.1/CODEOWNERS +2 -0
  21. linux_mirror_bench-0.1.1/CONTRIBUTING.md +83 -0
  22. linux_mirror_bench-0.1.1/Dockerfile +68 -0
  23. linux_mirror_bench-0.1.1/LICENSE +661 -0
  24. linux_mirror_bench-0.1.1/Makefile +100 -0
  25. linux_mirror_bench-0.1.1/PKG-INFO +410 -0
  26. linux_mirror_bench-0.1.1/README.md +385 -0
  27. linux_mirror_bench-0.1.1/SECURITY.md +57 -0
  28. linux_mirror_bench-0.1.1/pyproject.toml +78 -0
  29. linux_mirror_bench-0.1.1/src/mirror_bench/__init__.py +3 -0
  30. linux_mirror_bench-0.1.1/src/mirror_bench/__main__.py +4 -0
  31. linux_mirror_bench-0.1.1/src/mirror_bench/benchmark/__init__.py +1 -0
  32. linux_mirror_bench-0.1.1/src/mirror_bench/benchmark/probe.py +251 -0
  33. linux_mirror_bench-0.1.1/src/mirror_bench/benchmark/scorer.py +130 -0
  34. linux_mirror_bench-0.1.1/src/mirror_bench/benchmark/tls.py +33 -0
  35. linux_mirror_bench-0.1.1/src/mirror_bench/benchmark/transport.py +40 -0
  36. linux_mirror_bench-0.1.1/src/mirror_bench/cli.py +337 -0
  37. linux_mirror_bench-0.1.1/src/mirror_bench/discovery/__init__.py +43 -0
  38. linux_mirror_bench-0.1.1/src/mirror_bench/discovery/arch.py +62 -0
  39. linux_mirror_bench-0.1.1/src/mirror_bench/discovery/base.py +43 -0
  40. linux_mirror_bench-0.1.1/src/mirror_bench/discovery/debian.py +86 -0
  41. linux_mirror_bench-0.1.1/src/mirror_bench/discovery/fedora.py +184 -0
  42. linux_mirror_bench-0.1.1/src/mirror_bench/discovery/mint.py +104 -0
  43. linux_mirror_bench-0.1.1/src/mirror_bench/discovery/ubuntu.py +112 -0
  44. linux_mirror_bench-0.1.1/src/mirror_bench/display.py +266 -0
  45. linux_mirror_bench-0.1.1/src/mirror_bench/distro.py +173 -0
  46. linux_mirror_bench-0.1.1/src/mirror_bench/models.py +111 -0
  47. linux_mirror_bench-0.1.1/tests/__init__.py +0 -0
  48. linux_mirror_bench-0.1.1/tests/conftest.py +32 -0
  49. linux_mirror_bench-0.1.1/tests/fixtures/arch_status.json +50 -0
  50. linux_mirror_bench-0.1.1/tests/fixtures/debian_masterlist.txt +19 -0
  51. linux_mirror_bench-0.1.1/tests/fixtures/fedora_mirrorlist.txt +5 -0
  52. linux_mirror_bench-0.1.1/tests/fixtures/mint_mirrors.html +37 -0
  53. linux_mirror_bench-0.1.1/tests/fixtures/ubuntu_mirrors.txt +3 -0
  54. linux_mirror_bench-0.1.1/tests/test_cli.py +189 -0
  55. linux_mirror_bench-0.1.1/tests/test_discovery.py +272 -0
  56. linux_mirror_bench-0.1.1/tests/test_distro.py +117 -0
  57. linux_mirror_bench-0.1.1/tests/test_integration.py +36 -0
  58. linux_mirror_bench-0.1.1/tests/test_probe.py +123 -0
  59. linux_mirror_bench-0.1.1/tests/test_scorer.py +138 -0
  60. linux_mirror_bench-0.1.1/uv.lock +424 -0
@@ -0,0 +1,28 @@
1
+ .git
2
+ .github
3
+ .venv
4
+ .venv-*/
5
+ dist/
6
+ build/
7
+ *.egg-info/
8
+ __pycache__/
9
+ *.pyc
10
+ *.pyo
11
+ .ruff_cache/
12
+ .mypy_cache/
13
+ .pytest_cache/
14
+ .coverage
15
+ htmlcov/
16
+ tests/
17
+ docs/
18
+ .pre-commit-config.yaml
19
+ .yamllint.yaml
20
+ .markdownlint.yaml
21
+ .editorconfig
22
+ .gitignore
23
+ .dockerignore
24
+ Makefile
25
+ CHANGELOG.md
26
+ CONTRIBUTING.md
27
+ AGENTS.md
28
+ SECURITY.md
@@ -0,0 +1,18 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ indent_style = space
7
+ indent_size = 4
8
+ insert_final_newline = true
9
+ trim_trailing_whitespace = true
10
+
11
+ [*.{yml,yaml,json,md,toml}]
12
+ indent_size = 2
13
+
14
+ [Makefile]
15
+ indent_style = tab
16
+
17
+ [Dockerfile]
18
+ indent_size = 2
@@ -0,0 +1,70 @@
1
+ ---
2
+ name: Bug report
3
+ description: Something is broken or behaves unexpectedly.
4
+ title: "bug: "
5
+ labels: [bug]
6
+ body:
7
+ - type: markdown
8
+ attributes:
9
+ value: |
10
+ Thanks for taking the time to file a bug. Please fill out every section
11
+ so it can be triaged without a back-and-forth.
12
+
13
+ - type: input
14
+ id: version
15
+ attributes:
16
+ label: mirror-bench version
17
+ description: Output of `mirror-bench --version` or the git SHA.
18
+ placeholder: "0.1.0"
19
+ validations:
20
+ required: true
21
+
22
+ - type: input
23
+ id: install
24
+ attributes:
25
+ label: How did you install it?
26
+ placeholder: "pipx / uv tool / docker pull ghcr.io/... / source"
27
+ validations:
28
+ required: true
29
+
30
+ - type: input
31
+ id: host
32
+ attributes:
33
+ label: Host OS + Python
34
+ placeholder: "Ubuntu 24.04, Python 3.14.4 / macOS 15.0 / Fedora 41 container"
35
+ validations:
36
+ required: true
37
+
38
+ - type: textarea
39
+ id: command
40
+ attributes:
41
+ label: Command you ran
42
+ description: Include the full invocation.
43
+ render: shell
44
+ placeholder: "mirror-bench bench --distro ubuntu --country US --top 5"
45
+ validations:
46
+ required: true
47
+
48
+ - type: textarea
49
+ id: expected
50
+ attributes:
51
+ label: Expected behavior
52
+ validations:
53
+ required: true
54
+
55
+ - type: textarea
56
+ id: actual
57
+ attributes:
58
+ label: Actual behavior
59
+ description: Paste output, errors, or a screenshot.
60
+ render: text
61
+ validations:
62
+ required: true
63
+
64
+ - type: textarea
65
+ id: extras
66
+ attributes:
67
+ label: Anything else?
68
+ description: Relevant context — firewall, proxy, VPN, weird network, etc.
69
+ validations:
70
+ required: false
@@ -0,0 +1,6 @@
1
+ ---
2
+ blank_issues_enabled: false
3
+ contact_links:
4
+ - name: Security vulnerability
5
+ url: https://github.com/MysticRyuujin/mirror-bench/security/advisories/new
6
+ about: Please report security issues privately — see SECURITY.md.
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: Feature request
3
+ description: Suggest a new capability or improvement.
4
+ title: "feat: "
5
+ labels: [enhancement]
6
+ body:
7
+ - type: textarea
8
+ id: problem
9
+ attributes:
10
+ label: What problem would this solve?
11
+ description: Describe the real-world use case, not the implementation.
12
+ validations:
13
+ required: true
14
+
15
+ - type: textarea
16
+ id: proposal
17
+ attributes:
18
+ label: Proposed solution
19
+ description: Sketch the UX or API. CLI flag shapes, output columns, etc.
20
+ validations:
21
+ required: false
22
+
23
+ - type: textarea
24
+ id: alternatives
25
+ attributes:
26
+ label: Alternatives considered
27
+ description: Workarounds you tried, related tools, etc.
28
+ validations:
29
+ required: false
30
+
31
+ - type: checkboxes
32
+ id: scope
33
+ attributes:
34
+ label: Scope sanity-check
35
+ options:
36
+ - label: This stays read-only (does not modify /etc/apt, /etc/yum.repos.d, pacman mirrorlist, etc.)
37
+ required: true
@@ -0,0 +1,32 @@
1
+ # Pull request
2
+
3
+ Keep the PR title Conventional-Commit shaped: `feat(scope): summary`.
4
+
5
+ ## Summary
6
+
7
+ What does this change and why? One or two paragraphs max.
8
+
9
+ ## Type of change
10
+
11
+ - [ ] feat — new user-visible capability
12
+ - [ ] fix — bug fix
13
+ - [ ] refactor — no behavior change
14
+ - [ ] docs
15
+ - [ ] chore / ci
16
+ - [ ] breaking change (describe migration below)
17
+
18
+ ## How did you verify this?
19
+
20
+ - [ ] `make ci-local` passes
21
+ - [ ] Unit tests added/updated
22
+ - [ ] Integration tests (`make test-integration`) pass, if relevant
23
+ - [ ] Tested the CLI manually against at least one real distro
24
+ - [ ] Docker image builds and `docker run` behaves correctly (if Docker changed)
25
+
26
+ ## Breaking changes / migration
27
+
28
+ Delete this section if not applicable.
29
+
30
+ ## Related issues
31
+
32
+ `Closes #123`, `Refs #456`.
@@ -0,0 +1,43 @@
1
+ ---
2
+ version: 2
3
+ updates:
4
+ - package-ecosystem: pip
5
+ directory: /
6
+ schedule:
7
+ interval: weekly
8
+ day: monday
9
+ open-pull-requests-limit: 10
10
+ commit-message:
11
+ prefix: deps
12
+ include: scope
13
+ groups:
14
+ runtime:
15
+ dependency-type: production
16
+ update-types: [minor, patch]
17
+ dev:
18
+ dependency-type: development
19
+ update-types: [minor, patch, major]
20
+ major-runtime:
21
+ dependency-type: production
22
+ update-types: [major]
23
+
24
+ - package-ecosystem: github-actions
25
+ directory: /
26
+ schedule:
27
+ interval: weekly
28
+ day: monday
29
+ open-pull-requests-limit: 10
30
+ commit-message:
31
+ prefix: deps(actions)
32
+ groups:
33
+ actions:
34
+ patterns: ["*"]
35
+
36
+ - package-ecosystem: docker
37
+ directory: /
38
+ schedule:
39
+ interval: weekly
40
+ day: monday
41
+ open-pull-requests-limit: 5
42
+ commit-message:
43
+ prefix: deps(docker)
@@ -0,0 +1,157 @@
1
+ ---
2
+ name: CI
3
+
4
+ on:
5
+ push:
6
+ branches: [main]
7
+ pull_request:
8
+ workflow_dispatch:
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ concurrency:
14
+ group: ${{ github.workflow }}-${{ github.ref }}
15
+ cancel-in-progress: true
16
+
17
+ env:
18
+ PYTHON_VERSION: "3.14"
19
+ UV_VERSION: "0.11.7"
20
+
21
+ jobs:
22
+ pre-commit:
23
+ name: Pre-commit
24
+ runs-on: ubuntu-latest
25
+ steps:
26
+ - uses: actions/checkout@v6
27
+ - uses: actions/setup-python@v6
28
+ with:
29
+ python-version: ${{ env.PYTHON_VERSION }}
30
+ - uses: astral-sh/setup-uv@v7
31
+ with:
32
+ version: ${{ env.UV_VERSION }}
33
+ enable-cache: true
34
+ - name: pre-commit/action
35
+ uses: pre-commit/action@v3.0.1
36
+
37
+ lint:
38
+ name: Lint + format
39
+ runs-on: ubuntu-latest
40
+ steps:
41
+ - uses: actions/checkout@v6
42
+ - uses: astral-sh/setup-uv@v7
43
+ with:
44
+ version: ${{ env.UV_VERSION }}
45
+ enable-cache: true
46
+ cache-dependency-glob: pyproject.toml
47
+ - run: uv sync --frozen --all-extras || uv sync --all-extras
48
+ - name: Ruff check
49
+ run: uv run ruff check --output-format=github .
50
+ - name: Ruff format check
51
+ run: uv run ruff format --check .
52
+
53
+ typecheck:
54
+ name: Mypy (strict)
55
+ runs-on: ubuntu-latest
56
+ steps:
57
+ - uses: actions/checkout@v6
58
+ - uses: astral-sh/setup-uv@v7
59
+ with:
60
+ version: ${{ env.UV_VERSION }}
61
+ enable-cache: true
62
+ cache-dependency-glob: pyproject.toml
63
+ - run: uv sync --frozen --all-extras || uv sync --all-extras
64
+ - name: mypy
65
+ run: uv run mypy src tests
66
+
67
+ test:
68
+ name: Tests (Python ${{ matrix.python }})
69
+ runs-on: ubuntu-latest
70
+ strategy:
71
+ fail-fast: false
72
+ matrix:
73
+ python: ["3.14"]
74
+ steps:
75
+ - uses: actions/checkout@v6
76
+ - uses: actions/setup-python@v6
77
+ with:
78
+ python-version: ${{ matrix.python }}
79
+ - uses: astral-sh/setup-uv@v7
80
+ with:
81
+ version: ${{ env.UV_VERSION }}
82
+ enable-cache: true
83
+ cache-dependency-glob: pyproject.toml
84
+ - run: uv sync --frozen --all-extras || uv sync --all-extras
85
+ - name: pytest
86
+ run: uv run pytest -v --tb=short
87
+ - name: Smoke-test the built CLI
88
+ run: |
89
+ uv build
90
+ uv run --no-project --with "./dist/$(ls dist/ | grep .whl | head -n1)" mirror-bench --help
91
+
92
+ security:
93
+ name: Security scan (bandit + pip-audit)
94
+ runs-on: ubuntu-latest
95
+ steps:
96
+ - uses: actions/checkout@v6
97
+ - uses: astral-sh/setup-uv@v7
98
+ with:
99
+ version: ${{ env.UV_VERSION }}
100
+ enable-cache: true
101
+ cache-dependency-glob: pyproject.toml
102
+ - run: uv sync --frozen --all-extras || uv sync --all-extras
103
+ - name: Bandit
104
+ run: uv run --with "bandit[toml]" bandit -c pyproject.toml -r src
105
+ - name: pip-audit (runtime deps)
106
+ run: |
107
+ uv export --no-emit-project --format requirements.txt > .audit-reqs.txt
108
+ uv run --with pip-audit pip-audit --progress-spinner off --strict --disable-pip -r .audit-reqs.txt
109
+
110
+ docker:
111
+ name: Docker build + Trivy scan
112
+ runs-on: ubuntu-latest
113
+ permissions:
114
+ contents: read
115
+ security-events: write
116
+ steps:
117
+ - uses: actions/checkout@v6
118
+ - uses: docker/setup-buildx-action@v4
119
+ - name: Build image
120
+ uses: docker/build-push-action@v7
121
+ with:
122
+ context: .
123
+ push: false
124
+ load: true
125
+ tags: mirror-bench:ci
126
+ cache-from: type=gha
127
+ cache-to: type=gha,mode=max
128
+ - name: Trivy scan (image)
129
+ uses: aquasecurity/trivy-action@v0.36.0
130
+ with:
131
+ image-ref: mirror-bench:ci
132
+ format: sarif
133
+ output: trivy-image.sarif
134
+ severity: HIGH,CRITICAL
135
+ ignore-unfixed: true
136
+ exit-code: "1"
137
+ - name: Upload Trivy SARIF
138
+ if: always()
139
+ uses: github/codeql-action/upload-sarif@v4
140
+ with:
141
+ sarif_file: trivy-image.sarif
142
+ category: trivy-image
143
+ - name: Smoke test container
144
+ run: docker run --rm mirror-bench:ci --help
145
+
146
+ all-green:
147
+ name: CI green
148
+ runs-on: ubuntu-latest
149
+ needs: [pre-commit, lint, typecheck, test, security, docker]
150
+ if: always()
151
+ steps:
152
+ - name: Aggregate result
153
+ run: |
154
+ if [[ "${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}" == "true" ]]; then
155
+ echo "One or more jobs failed."
156
+ exit 1
157
+ fi
@@ -0,0 +1,33 @@
1
+ ---
2
+ # Release-Please — turns merged Conventional Commits on main into a
3
+ # versioned release PR. Merging that PR creates a git tag, which the
4
+ # `release.yml` workflow listens for to build + publish the wheel and image.
5
+
6
+ name: Release Please
7
+
8
+ on:
9
+ push:
10
+ branches: [main]
11
+
12
+ permissions:
13
+ contents: write
14
+ pull-requests: write
15
+
16
+ jobs:
17
+ release-please:
18
+ runs-on: ubuntu-latest
19
+ outputs:
20
+ release_created: ${{ steps.release.outputs.release_created }}
21
+ tag_name: ${{ steps.release.outputs.tag_name }}
22
+ version: ${{ steps.release.outputs.version }}
23
+ steps:
24
+ # GITHUB_TOKEN can't trigger downstream workflows (GitHub security
25
+ # feature). Falls back to GITHUB_TOKEN locally; CI with RELEASE_TOKEN
26
+ # set (a fine-grained PAT with contents:write + pull-requests:write)
27
+ # lets the created tag trigger release.yml automatically.
28
+ - id: release
29
+ uses: googleapis/release-please-action@v5
30
+ with:
31
+ token: ${{ secrets.RELEASE_TOKEN || secrets.GITHUB_TOKEN }}
32
+ config-file: .release-please-config.json
33
+ manifest-file: .release-please-manifest.json
@@ -0,0 +1,155 @@
1
+ ---
2
+ name: Release
3
+
4
+ on:
5
+ push:
6
+ tags:
7
+ - "v*"
8
+ workflow_dispatch:
9
+ inputs:
10
+ tag:
11
+ description: Tag to release (e.g. v0.1.0)
12
+ required: true
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ concurrency:
18
+ group: release-${{ github.ref }}
19
+ cancel-in-progress: false
20
+
21
+ env:
22
+ PYTHON_VERSION: "3.14"
23
+ UV_VERSION: "0.11.7"
24
+ REGISTRY: ghcr.io
25
+ IMAGE_NAME: ${{ github.repository }}
26
+
27
+ jobs:
28
+ build-wheel:
29
+ name: Build sdist + wheel
30
+ runs-on: ubuntu-latest
31
+ outputs:
32
+ version: ${{ steps.version.outputs.value }}
33
+ steps:
34
+ - uses: actions/checkout@v6
35
+ - uses: actions/setup-python@v6
36
+ with:
37
+ python-version: ${{ env.PYTHON_VERSION }}
38
+ - uses: astral-sh/setup-uv@v7
39
+ with:
40
+ version: ${{ env.UV_VERSION }}
41
+ - id: version
42
+ run: |
43
+ ref="${{ github.event.inputs.tag || github.ref_name }}"
44
+ echo "value=${ref#v}" >> "$GITHUB_OUTPUT"
45
+ - run: uv build
46
+ - uses: actions/upload-artifact@v7
47
+ with:
48
+ name: dist
49
+ path: dist/
50
+ retention-days: 7
51
+
52
+ publish-pypi:
53
+ name: Publish to PyPI (OIDC)
54
+ needs: build-wheel
55
+ runs-on: ubuntu-latest
56
+ environment:
57
+ name: pypi
58
+ url: https://pypi.org/project/linux-mirror-bench/
59
+ permissions:
60
+ id-token: write # trusted publishing
61
+ steps:
62
+ - uses: actions/download-artifact@v8
63
+ with:
64
+ name: dist
65
+ path: dist/
66
+ - uses: pypa/gh-action-pypi-publish@release/v1
67
+ with:
68
+ skip-existing: true
69
+
70
+ attest-wheel:
71
+ name: Attest wheel provenance
72
+ needs: [build-wheel, publish-pypi]
73
+ runs-on: ubuntu-latest
74
+ permissions:
75
+ id-token: write
76
+ attestations: write
77
+ contents: read
78
+ steps:
79
+ - uses: actions/download-artifact@v8
80
+ with:
81
+ name: dist
82
+ path: dist/
83
+ - uses: actions/attest-build-provenance@v4
84
+ with:
85
+ subject-path: "dist/*"
86
+
87
+ docker:
88
+ name: Build + push container
89
+ needs: build-wheel
90
+ runs-on: ubuntu-latest
91
+ permissions:
92
+ contents: read
93
+ packages: write
94
+ id-token: write
95
+ attestations: write
96
+ steps:
97
+ - uses: actions/checkout@v6
98
+ - uses: docker/setup-qemu-action@v4
99
+ - uses: docker/setup-buildx-action@v4
100
+ - uses: docker/login-action@v4
101
+ with:
102
+ registry: ${{ env.REGISTRY }}
103
+ username: ${{ github.actor }}
104
+ password: ${{ secrets.GITHUB_TOKEN }}
105
+ - id: meta
106
+ uses: docker/metadata-action@v6
107
+ with:
108
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
109
+ tags: |
110
+ type=semver,pattern={{version}}
111
+ type=semver,pattern={{major}}.{{minor}}
112
+ type=semver,pattern={{major}}
113
+ type=raw,value=latest,enable={{is_default_branch}}
114
+ labels: |
115
+ org.opencontainers.image.title=mirror-bench
116
+ org.opencontainers.image.description=Cross-distro Linux package mirror benchmarking
117
+ org.opencontainers.image.licenses=AGPL-3.0-or-later
118
+ - id: build
119
+ uses: docker/build-push-action@v7
120
+ with:
121
+ context: .
122
+ platforms: linux/amd64,linux/arm64
123
+ push: true
124
+ tags: ${{ steps.meta.outputs.tags }}
125
+ labels: ${{ steps.meta.outputs.labels }}
126
+ build-args: |
127
+ VERSION=${{ needs.build-wheel.outputs.version }}
128
+ cache-from: type=gha
129
+ cache-to: type=gha,mode=max
130
+ sbom: true
131
+ provenance: mode=max
132
+ - name: Attest container image
133
+ uses: actions/attest-build-provenance@v4
134
+ with:
135
+ subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
136
+ subject-digest: ${{ steps.build.outputs.digest }}
137
+ push-to-registry: true
138
+
139
+ github-release:
140
+ name: GitHub release
141
+ needs: [build-wheel, publish-pypi, docker]
142
+ runs-on: ubuntu-latest
143
+ permissions:
144
+ contents: write
145
+ steps:
146
+ - uses: actions/checkout@v6
147
+ - uses: actions/download-artifact@v8
148
+ with:
149
+ name: dist
150
+ path: dist/
151
+ - uses: softprops/action-gh-release@v3
152
+ with:
153
+ tag_name: ${{ github.event.inputs.tag || github.ref_name }}
154
+ generate_release_notes: true
155
+ files: dist/*
@@ -0,0 +1,72 @@
1
+ # -- Python --------------------------------------------------------------
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ *.egg
7
+ *.egg-info/
8
+
9
+ # -- Virtual environments -------------------------------------------------
10
+ .venv/
11
+ venv/
12
+ env/
13
+ ENV/
14
+ __pypackages__/
15
+ # uv.lock IS committed — it pins the exact dependency graph for reproducible
16
+ # installs, Docker image builds, and CI. Do not gitignore it.
17
+
18
+ # -- Build artifacts ------------------------------------------------------
19
+ build/
20
+ dist/
21
+ wheels/
22
+ *.manifest
23
+ *.spec
24
+
25
+ # -- Test + coverage ------------------------------------------------------
26
+ .coverage
27
+ .coverage.*
28
+ coverage.xml
29
+ htmlcov/
30
+ .pytest_cache/
31
+ .tox/
32
+ .nox/
33
+ .hypothesis/
34
+ .audit-reqs.txt # transient artifact from `make security` / CI pip-audit
35
+
36
+ # -- Type checking --------------------------------------------------------
37
+ .mypy_cache/
38
+ .pyre/
39
+ .pytype/
40
+ .ruff_cache/
41
+
42
+ # -- Jupyter --------------------------------------------------------------
43
+ .ipynb_checkpoints/
44
+
45
+ # -- IDE / editors --------------------------------------------------------
46
+ .idea/
47
+ .vscode/
48
+ *.swp
49
+ *.swo
50
+ *~
51
+
52
+ # -- OS -------------------------------------------------------------------
53
+ .DS_Store
54
+ Thumbs.db
55
+ desktop.ini
56
+
57
+ # -- Logs -----------------------------------------------------------------
58
+ *.log
59
+
60
+ # -- Secrets: never commit. Add a concrete `.env.example` if needed. ------
61
+ .env
62
+ .env.*
63
+ !.env.example
64
+ *.pem
65
+ *.key
66
+ *.crt
67
+ *.p12
68
+ *.pfx
69
+
70
+ # -- Node (prettier pulls in node under pre-commit's cache, not here;
71
+ # this guards against accidental `npm init` in-tree) -------------------
72
+ node_modules/
@@ -0,0 +1,7 @@
1
+ ---
2
+ # 80 chars is too narrow for prose READMEs with command examples; tables and
3
+ # fenced code blocks are exempted because neither can meaningfully wrap.
4
+ MD013:
5
+ line_length: 120
6
+ code_blocks: false
7
+ tables: false