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.
- linux_mirror_bench-0.1.1/.dockerignore +28 -0
- linux_mirror_bench-0.1.1/.editorconfig +18 -0
- linux_mirror_bench-0.1.1/.github/ISSUE_TEMPLATE/bug_report.yml +70 -0
- linux_mirror_bench-0.1.1/.github/ISSUE_TEMPLATE/config.yml +6 -0
- linux_mirror_bench-0.1.1/.github/ISSUE_TEMPLATE/feature_request.yml +37 -0
- linux_mirror_bench-0.1.1/.github/PULL_REQUEST_TEMPLATE.md +32 -0
- linux_mirror_bench-0.1.1/.github/dependabot.yml +43 -0
- linux_mirror_bench-0.1.1/.github/workflows/ci.yml +157 -0
- linux_mirror_bench-0.1.1/.github/workflows/release-please.yml +33 -0
- linux_mirror_bench-0.1.1/.github/workflows/release.yml +155 -0
- linux_mirror_bench-0.1.1/.gitignore +72 -0
- linux_mirror_bench-0.1.1/.markdownlint.yaml +7 -0
- linux_mirror_bench-0.1.1/.pre-commit-config.yaml +101 -0
- linux_mirror_bench-0.1.1/.release-please-config.json +6 -0
- linux_mirror_bench-0.1.1/.release-please-manifest.json +3 -0
- linux_mirror_bench-0.1.1/.tool-versions +1 -0
- linux_mirror_bench-0.1.1/.yamllint.yaml +11 -0
- linux_mirror_bench-0.1.1/AGENTS.md +128 -0
- linux_mirror_bench-0.1.1/CHANGELOG.md +49 -0
- linux_mirror_bench-0.1.1/CODEOWNERS +2 -0
- linux_mirror_bench-0.1.1/CONTRIBUTING.md +83 -0
- linux_mirror_bench-0.1.1/Dockerfile +68 -0
- linux_mirror_bench-0.1.1/LICENSE +661 -0
- linux_mirror_bench-0.1.1/Makefile +100 -0
- linux_mirror_bench-0.1.1/PKG-INFO +410 -0
- linux_mirror_bench-0.1.1/README.md +385 -0
- linux_mirror_bench-0.1.1/SECURITY.md +57 -0
- linux_mirror_bench-0.1.1/pyproject.toml +78 -0
- linux_mirror_bench-0.1.1/src/mirror_bench/__init__.py +3 -0
- linux_mirror_bench-0.1.1/src/mirror_bench/__main__.py +4 -0
- linux_mirror_bench-0.1.1/src/mirror_bench/benchmark/__init__.py +1 -0
- linux_mirror_bench-0.1.1/src/mirror_bench/benchmark/probe.py +251 -0
- linux_mirror_bench-0.1.1/src/mirror_bench/benchmark/scorer.py +130 -0
- linux_mirror_bench-0.1.1/src/mirror_bench/benchmark/tls.py +33 -0
- linux_mirror_bench-0.1.1/src/mirror_bench/benchmark/transport.py +40 -0
- linux_mirror_bench-0.1.1/src/mirror_bench/cli.py +337 -0
- linux_mirror_bench-0.1.1/src/mirror_bench/discovery/__init__.py +43 -0
- linux_mirror_bench-0.1.1/src/mirror_bench/discovery/arch.py +62 -0
- linux_mirror_bench-0.1.1/src/mirror_bench/discovery/base.py +43 -0
- linux_mirror_bench-0.1.1/src/mirror_bench/discovery/debian.py +86 -0
- linux_mirror_bench-0.1.1/src/mirror_bench/discovery/fedora.py +184 -0
- linux_mirror_bench-0.1.1/src/mirror_bench/discovery/mint.py +104 -0
- linux_mirror_bench-0.1.1/src/mirror_bench/discovery/ubuntu.py +112 -0
- linux_mirror_bench-0.1.1/src/mirror_bench/display.py +266 -0
- linux_mirror_bench-0.1.1/src/mirror_bench/distro.py +173 -0
- linux_mirror_bench-0.1.1/src/mirror_bench/models.py +111 -0
- linux_mirror_bench-0.1.1/tests/__init__.py +0 -0
- linux_mirror_bench-0.1.1/tests/conftest.py +32 -0
- linux_mirror_bench-0.1.1/tests/fixtures/arch_status.json +50 -0
- linux_mirror_bench-0.1.1/tests/fixtures/debian_masterlist.txt +19 -0
- linux_mirror_bench-0.1.1/tests/fixtures/fedora_mirrorlist.txt +5 -0
- linux_mirror_bench-0.1.1/tests/fixtures/mint_mirrors.html +37 -0
- linux_mirror_bench-0.1.1/tests/fixtures/ubuntu_mirrors.txt +3 -0
- linux_mirror_bench-0.1.1/tests/test_cli.py +189 -0
- linux_mirror_bench-0.1.1/tests/test_discovery.py +272 -0
- linux_mirror_bench-0.1.1/tests/test_distro.py +117 -0
- linux_mirror_bench-0.1.1/tests/test_integration.py +36 -0
- linux_mirror_bench-0.1.1/tests/test_probe.py +123 -0
- linux_mirror_bench-0.1.1/tests/test_scorer.py +138 -0
- 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,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/
|