localqueue 1.1.0__tar.gz → 1.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.
- {localqueue-1.1.0 → localqueue-1.1.1}/.github/workflows/ci.yml +104 -3
- localqueue-1.1.1/.github/workflows/docs.yml +68 -0
- localqueue-1.1.1/.github/workflows/release.yml +91 -0
- localqueue-1.1.1/.github/workflows/wheels.yml +298 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/.gitignore +5 -0
- localqueue-1.1.1/.pre-commit-config.yaml +31 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/CHANGELOG.md +21 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/Cargo.lock +1 -1
- {localqueue-1.1.0 → localqueue-1.1.1}/Cargo.toml +1 -1
- {localqueue-1.1.0 → localqueue-1.1.1}/PKG-INFO +28 -11
- {localqueue-1.1.0 → localqueue-1.1.1}/README.md +19 -9
- {localqueue-1.1.0 → localqueue-1.1.1}/benchmarks/queue_bench.py +10 -7
- localqueue-1.1.1/deny.toml +19 -0
- localqueue-1.1.1/docs/getting-started.md +75 -0
- localqueue-1.1.1/docs/index.md +52 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/docs/internal/initial_idea.md +0 -1
- {localqueue-1.1.0 → localqueue-1.1.1}/pyproject.toml +46 -2
- {localqueue-1.1.0 → localqueue-1.1.1}/python/localqueue/bus/bus.py +2 -3
- {localqueue-1.1.0 → localqueue-1.1.1}/python/localqueue/bus/topology.py +2 -5
- localqueue-1.1.1/scripts/check_release_version.py +56 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/stress/run_soak.py +4 -4
- localqueue-1.1.1/tasks/plan.md +663 -0
- localqueue-1.1.1/tasks/todo.md +83 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/tests/test_batch.py +2 -7
- {localqueue-1.1.0 → localqueue-1.1.1}/tests/test_bus.py +24 -30
- {localqueue-1.1.0 → localqueue-1.1.1}/tests/test_bus_static_topology.py +9 -28
- {localqueue-1.1.0 → localqueue-1.1.1}/tests/test_bus_topology.py +0 -1
- {localqueue-1.1.0 → localqueue-1.1.1}/tests/test_concurrency.py +0 -1
- {localqueue-1.1.0 → localqueue-1.1.1}/tests/test_contract.py +3 -7
- {localqueue-1.1.0 → localqueue-1.1.1}/tests/test_core.py +1 -2
- {localqueue-1.1.0 → localqueue-1.1.1}/tests/test_maintenance.py +0 -1
- {localqueue-1.1.0 → localqueue-1.1.1}/tests/test_worker.py +0 -3
- localqueue-1.1.1/uv.lock +1253 -0
- localqueue-1.1.1/zensical.toml +30 -0
- localqueue-1.1.0/.github/workflows/wheels.yml +0 -173
- {localqueue-1.1.0 → localqueue-1.1.1}/.github/workflows/stress.yml +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/LICENSE +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/benchmarks/README.md +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/docs/event-bus.md +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/docs/guarantees.md +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/examples/basic.py +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/python/localqueue/__init__.py +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/python/localqueue/bus/__init__.py +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/python/localqueue/bus/consumer.py +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/python/localqueue/bus/event.py +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/python/localqueue/bus/registry.py +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/python/localqueue/bus/subscription.py +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/python/localqueue/core.py +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/python/localqueue/exceptions.py +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/python/localqueue/job.py +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/python/localqueue/localqueue.pyi +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/python/localqueue/worker.py +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/src/error.rs +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/src/lib.rs +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/src/queue.rs +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/src/schema.rs +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/src/storage.rs +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/tests/__init__.py +0 -0
- {localqueue-1.1.0 → localqueue-1.1.1}/tests/test_gil.py +0 -0
|
@@ -14,6 +14,52 @@ concurrency:
|
|
|
14
14
|
cancel-in-progress: true
|
|
15
15
|
|
|
16
16
|
jobs:
|
|
17
|
+
python-quality:
|
|
18
|
+
name: Python lint and types
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- name: Check out repository
|
|
22
|
+
uses: actions/checkout@v6
|
|
23
|
+
|
|
24
|
+
- name: Set up Python
|
|
25
|
+
uses: actions/setup-python@v6
|
|
26
|
+
with:
|
|
27
|
+
python-version: '3.14'
|
|
28
|
+
cache: pip
|
|
29
|
+
|
|
30
|
+
- name: Install Python quality tools
|
|
31
|
+
run: |
|
|
32
|
+
python -m pip install --upgrade \
|
|
33
|
+
"pydantic>=2,<3" \
|
|
34
|
+
"ruff>=0.15,<1" \
|
|
35
|
+
"pyrefly>=1.1,<2"
|
|
36
|
+
|
|
37
|
+
- name: Run Ruff
|
|
38
|
+
run: |
|
|
39
|
+
ruff check .
|
|
40
|
+
ruff format --check .
|
|
41
|
+
|
|
42
|
+
- name: Run Pyrefly
|
|
43
|
+
env:
|
|
44
|
+
PYTHONPATH: python
|
|
45
|
+
run: pyrefly check --preset default --progress-bar no python/localqueue
|
|
46
|
+
|
|
47
|
+
secrets:
|
|
48
|
+
name: Secret scan
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
steps:
|
|
51
|
+
- name: Check out repository
|
|
52
|
+
uses: actions/checkout@v6
|
|
53
|
+
with:
|
|
54
|
+
fetch-depth: 0
|
|
55
|
+
|
|
56
|
+
- name: Run Gitleaks
|
|
57
|
+
uses: gitleaks/gitleaks-action@v2
|
|
58
|
+
env:
|
|
59
|
+
# The CLI result is the quality gate. Keep SARIF uploads opt-in so
|
|
60
|
+
# a transient Actions artifact quota cannot hide scan results.
|
|
61
|
+
GITLEAKS_ENABLE_UPLOAD_ARTIFACT: "false"
|
|
62
|
+
|
|
17
63
|
rust-quality:
|
|
18
64
|
name: Rust format and Clippy
|
|
19
65
|
runs-on: ubuntu-latest
|
|
@@ -43,6 +89,18 @@ jobs:
|
|
|
43
89
|
- name: Run Clippy
|
|
44
90
|
run: cargo clippy --locked --all-targets --all-features -- -D warnings
|
|
45
91
|
|
|
92
|
+
rust-dependencies:
|
|
93
|
+
name: Rust dependencies
|
|
94
|
+
runs-on: ubuntu-latest
|
|
95
|
+
steps:
|
|
96
|
+
- name: Check out repository
|
|
97
|
+
uses: actions/checkout@v6
|
|
98
|
+
|
|
99
|
+
- name: Run cargo-deny
|
|
100
|
+
uses: EmbarkStudios/cargo-deny-action@v2
|
|
101
|
+
with:
|
|
102
|
+
command: check
|
|
103
|
+
|
|
46
104
|
msrv:
|
|
47
105
|
name: Rust MSRV 1.83
|
|
48
106
|
runs-on: ubuntu-latest
|
|
@@ -81,7 +139,19 @@ jobs:
|
|
|
81
139
|
python-version: ${{ matrix.python }}
|
|
82
140
|
cache: pip
|
|
83
141
|
|
|
84
|
-
- name:
|
|
142
|
+
- name: Cache Cargo dependencies and build outputs
|
|
143
|
+
uses: actions/cache@v4
|
|
144
|
+
with:
|
|
145
|
+
path: |
|
|
146
|
+
~/.cargo/registry
|
|
147
|
+
~/.cargo/git
|
|
148
|
+
target
|
|
149
|
+
key: ${{ runner.os }}-cargo-py${{ matrix.python }}-${{ hashFiles('Cargo.toml', 'Cargo.lock') }}
|
|
150
|
+
restore-keys: |
|
|
151
|
+
${{ runner.os }}-cargo-py${{ matrix.python }}-
|
|
152
|
+
${{ runner.os }}-cargo-
|
|
153
|
+
|
|
154
|
+
- name: Build extension in a virtual environment
|
|
85
155
|
shell: bash
|
|
86
156
|
run: |
|
|
87
157
|
python -m venv .venv
|
|
@@ -93,13 +163,44 @@ jobs:
|
|
|
93
163
|
python -m pip install --upgrade \
|
|
94
164
|
"maturin>=1.14,<2" \
|
|
95
165
|
"pytest>=8,<10" \
|
|
166
|
+
"pytest-cov>=7,<8" \
|
|
96
167
|
"pydantic>=2,<3"
|
|
97
|
-
maturin develop --
|
|
168
|
+
maturin develop --locked
|
|
169
|
+
|
|
170
|
+
- name: Run tests
|
|
171
|
+
if: matrix.os != 'ubuntu-latest' || matrix.python != '3.14'
|
|
172
|
+
shell: bash
|
|
173
|
+
run: |
|
|
174
|
+
if [ "$RUNNER_OS" = "Windows" ]; then
|
|
175
|
+
source .venv/Scripts/activate
|
|
176
|
+
else
|
|
177
|
+
source .venv/bin/activate
|
|
178
|
+
fi
|
|
98
179
|
pytest -ra
|
|
99
180
|
|
|
181
|
+
- name: Run tests with branch coverage
|
|
182
|
+
if: matrix.os == 'ubuntu-latest' && matrix.python == '3.14'
|
|
183
|
+
shell: bash
|
|
184
|
+
run: |
|
|
185
|
+
source .venv/bin/activate
|
|
186
|
+
pytest -ra \
|
|
187
|
+
--cov=localqueue \
|
|
188
|
+
--cov-branch \
|
|
189
|
+
--cov-report=term-missing \
|
|
190
|
+
--cov-report=xml \
|
|
191
|
+
--cov-fail-under=80
|
|
192
|
+
|
|
193
|
+
- name: Upload coverage to Codecov
|
|
194
|
+
if: matrix.os == 'ubuntu-latest' && matrix.python == '3.14'
|
|
195
|
+
uses: codecov/codecov-action@v5
|
|
196
|
+
with:
|
|
197
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
198
|
+
files: coverage.xml
|
|
199
|
+
fail_ci_if_error: false
|
|
200
|
+
|
|
100
201
|
wheel-smoke:
|
|
101
202
|
name: Build and smoke-test wheel
|
|
102
|
-
needs: [rust-quality, python-tests]
|
|
203
|
+
needs: [python-quality, secrets, rust-quality, rust-dependencies, python-tests]
|
|
103
204
|
runs-on: ubuntu-latest
|
|
104
205
|
steps:
|
|
105
206
|
- name: Check out repository
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
name: Documentation
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
paths:
|
|
6
|
+
- "docs/**"
|
|
7
|
+
- "zensical.toml"
|
|
8
|
+
- ".github/workflows/docs.yml"
|
|
9
|
+
- "pyproject.toml"
|
|
10
|
+
- "uv.lock"
|
|
11
|
+
push:
|
|
12
|
+
branches: [main]
|
|
13
|
+
paths:
|
|
14
|
+
- "docs/**"
|
|
15
|
+
- "zensical.toml"
|
|
16
|
+
- ".github/workflows/docs.yml"
|
|
17
|
+
- "pyproject.toml"
|
|
18
|
+
- "uv.lock"
|
|
19
|
+
workflow_dispatch:
|
|
20
|
+
|
|
21
|
+
permissions:
|
|
22
|
+
contents: read
|
|
23
|
+
|
|
24
|
+
concurrency:
|
|
25
|
+
group: docs-${{ github.workflow }}-${{ github.ref }}
|
|
26
|
+
cancel-in-progress: true
|
|
27
|
+
|
|
28
|
+
jobs:
|
|
29
|
+
build:
|
|
30
|
+
name: Build documentation
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
steps:
|
|
33
|
+
- name: Check out repository
|
|
34
|
+
uses: actions/checkout@v6
|
|
35
|
+
|
|
36
|
+
- name: Set up Python
|
|
37
|
+
uses: actions/setup-python@v6
|
|
38
|
+
with:
|
|
39
|
+
python-version: '3.14'
|
|
40
|
+
cache: pip
|
|
41
|
+
|
|
42
|
+
- name: Install Zensical
|
|
43
|
+
run: python -m pip install --upgrade "zensical>=0.0.51,<0.1"
|
|
44
|
+
|
|
45
|
+
- name: Build site
|
|
46
|
+
run: zensical build --clean
|
|
47
|
+
|
|
48
|
+
- name: Upload Pages artifact
|
|
49
|
+
if: github.event_name != 'pull_request'
|
|
50
|
+
uses: actions/upload-pages-artifact@v5
|
|
51
|
+
with:
|
|
52
|
+
path: site
|
|
53
|
+
|
|
54
|
+
deploy:
|
|
55
|
+
name: Deploy documentation
|
|
56
|
+
if: github.event_name != 'pull_request'
|
|
57
|
+
needs: build
|
|
58
|
+
runs-on: ubuntu-latest
|
|
59
|
+
permissions:
|
|
60
|
+
pages: write
|
|
61
|
+
id-token: write
|
|
62
|
+
environment:
|
|
63
|
+
name: github-pages
|
|
64
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
65
|
+
steps:
|
|
66
|
+
- name: Deploy to GitHub Pages
|
|
67
|
+
id: deployment
|
|
68
|
+
uses: actions/deploy-pages@v5
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
name: Create release tag
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
dry_run:
|
|
7
|
+
description: Calculate the next version without writing, tagging, or pushing
|
|
8
|
+
required: true
|
|
9
|
+
default: true
|
|
10
|
+
type: boolean
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: write
|
|
14
|
+
|
|
15
|
+
concurrency:
|
|
16
|
+
group: release
|
|
17
|
+
cancel-in-progress: false
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
release:
|
|
21
|
+
name: Calculate and tag release
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- name: Check out main with full history
|
|
25
|
+
uses: actions/checkout@v6
|
|
26
|
+
with:
|
|
27
|
+
ref: main
|
|
28
|
+
fetch-depth: 0
|
|
29
|
+
|
|
30
|
+
- name: Confirm main is current
|
|
31
|
+
run: |
|
|
32
|
+
git fetch origin main --tags
|
|
33
|
+
test "$(git rev-parse HEAD)" = "$(git rev-parse origin/main)"
|
|
34
|
+
|
|
35
|
+
- name: Set up Python
|
|
36
|
+
uses: actions/setup-python@v6
|
|
37
|
+
with:
|
|
38
|
+
python-version: '3.14'
|
|
39
|
+
|
|
40
|
+
- name: Set up Rust
|
|
41
|
+
uses: dtolnay/rust-toolchain@stable
|
|
42
|
+
|
|
43
|
+
- name: Install release and test tooling
|
|
44
|
+
run: |
|
|
45
|
+
python -m pip install --upgrade \
|
|
46
|
+
"python-semantic-release>=10.6,<11" \
|
|
47
|
+
"maturin>=1.14,<2" \
|
|
48
|
+
"pytest>=8,<10" \
|
|
49
|
+
"pydantic>=2,<3"
|
|
50
|
+
|
|
51
|
+
- name: Validate release history
|
|
52
|
+
run: |
|
|
53
|
+
current_version=$(python -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')
|
|
54
|
+
last_released=$(semantic-release version --print-last-released)
|
|
55
|
+
test "$current_version" = "$last_released" || {
|
|
56
|
+
echo "pyproject.toml is $current_version but Semantic Release sees $last_released." >&2
|
|
57
|
+
echo "Reconcile the published release tag with main before automating the next release." >&2
|
|
58
|
+
exit 1
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
- name: Calculate next version
|
|
62
|
+
id: version
|
|
63
|
+
run: |
|
|
64
|
+
version=$(semantic-release version --print)
|
|
65
|
+
echo "version=$version" >> "$GITHUB_OUTPUT"
|
|
66
|
+
echo "tag=v$version" >> "$GITHUB_OUTPUT"
|
|
67
|
+
|
|
68
|
+
- name: Report dry run
|
|
69
|
+
if: inputs.dry_run
|
|
70
|
+
run: |
|
|
71
|
+
echo "Next release would be ${{ steps.version.outputs.tag }}"
|
|
72
|
+
|
|
73
|
+
- name: Create local release commit and tag
|
|
74
|
+
if: inputs.dry_run == false
|
|
75
|
+
env:
|
|
76
|
+
GH_TOKEN: ${{ github.token }}
|
|
77
|
+
run: semantic-release version --no-push --no-vcs-release
|
|
78
|
+
|
|
79
|
+
- name: Validate versioned tree
|
|
80
|
+
if: inputs.dry_run == false
|
|
81
|
+
run: |
|
|
82
|
+
python scripts/check_release_version.py --tag "${{ steps.version.outputs.tag }}"
|
|
83
|
+
cargo fmt --all --check
|
|
84
|
+
cargo check --locked
|
|
85
|
+
maturin develop --release --locked
|
|
86
|
+
pytest -ra
|
|
87
|
+
|
|
88
|
+
- name: Push release commit and tag atomically
|
|
89
|
+
if: inputs.dry_run == false
|
|
90
|
+
run: |
|
|
91
|
+
git push --atomic origin HEAD:main "${{ steps.version.outputs.tag }}"
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
name: Wheels
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
release_ref:
|
|
7
|
+
description: Existing v* tag to publish; leave empty for a build-only run
|
|
8
|
+
required: false
|
|
9
|
+
type: string
|
|
10
|
+
push:
|
|
11
|
+
tags: ['v*']
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
prepare-release:
|
|
18
|
+
name: Prepare release
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
permissions:
|
|
21
|
+
contents: write
|
|
22
|
+
outputs:
|
|
23
|
+
release_mode: ${{ steps.release.outputs.release_mode }}
|
|
24
|
+
release_ref: ${{ steps.release.outputs.release_ref }}
|
|
25
|
+
steps:
|
|
26
|
+
- name: Resolve release mode
|
|
27
|
+
id: release
|
|
28
|
+
env:
|
|
29
|
+
INPUT_RELEASE_REF: ${{ inputs.release_ref }}
|
|
30
|
+
REF_NAME: ${{ github.ref_name }}
|
|
31
|
+
REF_TYPE: ${{ github.ref_type }}
|
|
32
|
+
shell: bash
|
|
33
|
+
run: |
|
|
34
|
+
if [[ -n "$INPUT_RELEASE_REF" ]]; then
|
|
35
|
+
release_ref="$INPUT_RELEASE_REF"
|
|
36
|
+
release_mode=true
|
|
37
|
+
elif [[ "$REF_TYPE" == "tag" && "$REF_NAME" == v* ]]; then
|
|
38
|
+
release_ref="$REF_NAME"
|
|
39
|
+
release_mode=true
|
|
40
|
+
else
|
|
41
|
+
release_ref="$REF_NAME"
|
|
42
|
+
release_mode=false
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
if [[ "$release_mode" == true && "$release_ref" != v* ]]; then
|
|
46
|
+
echo "release_ref must start with v" >&2
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
echo "release_mode=$release_mode" >> "$GITHUB_OUTPUT"
|
|
51
|
+
echo "release_ref=$release_ref" >> "$GITHUB_OUTPUT"
|
|
52
|
+
|
|
53
|
+
- name: Create draft GitHub release
|
|
54
|
+
if: steps.release.outputs.release_mode == 'true'
|
|
55
|
+
env:
|
|
56
|
+
GH_TOKEN: ${{ github.token }}
|
|
57
|
+
RELEASE_REF: ${{ steps.release.outputs.release_ref }}
|
|
58
|
+
run: |
|
|
59
|
+
gh release view "$RELEASE_REF" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1 || \
|
|
60
|
+
gh release create "$RELEASE_REF" \
|
|
61
|
+
--repo "$GITHUB_REPOSITORY" \
|
|
62
|
+
--verify-tag \
|
|
63
|
+
--draft \
|
|
64
|
+
--generate-notes \
|
|
65
|
+
--title "$RELEASE_REF"
|
|
66
|
+
|
|
67
|
+
- name: Refuse to rebuild an already published release
|
|
68
|
+
if: steps.release.outputs.release_mode == 'true'
|
|
69
|
+
env:
|
|
70
|
+
GH_TOKEN: ${{ github.token }}
|
|
71
|
+
RELEASE_REF: ${{ steps.release.outputs.release_ref }}
|
|
72
|
+
run: |
|
|
73
|
+
if gh release view "$RELEASE_REF" --repo "$GITHUB_REPOSITORY" \
|
|
74
|
+
--json isDraft --jq '.isDraft == false' | grep -qx true; then
|
|
75
|
+
echo "release $RELEASE_REF is already published" >&2
|
|
76
|
+
exit 1
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
validate-release:
|
|
80
|
+
name: Validate release version
|
|
81
|
+
needs: prepare-release
|
|
82
|
+
runs-on: ubuntu-latest
|
|
83
|
+
steps:
|
|
84
|
+
- name: Check out release source
|
|
85
|
+
uses: actions/checkout@v6
|
|
86
|
+
with:
|
|
87
|
+
ref: ${{ needs.prepare-release.outputs.release_ref }}
|
|
88
|
+
|
|
89
|
+
- name: Validate tag and package metadata
|
|
90
|
+
if: needs.prepare-release.outputs.release_mode == 'true'
|
|
91
|
+
run: python scripts/check_release_version.py --tag "${{ needs.prepare-release.outputs.release_ref }}"
|
|
92
|
+
|
|
93
|
+
build:
|
|
94
|
+
name: ${{ matrix.name }}
|
|
95
|
+
needs: [prepare-release, validate-release]
|
|
96
|
+
permissions:
|
|
97
|
+
contents: write
|
|
98
|
+
strategy:
|
|
99
|
+
fail-fast: false
|
|
100
|
+
matrix:
|
|
101
|
+
include:
|
|
102
|
+
- name: linux-x86_64
|
|
103
|
+
os: ubuntu-latest
|
|
104
|
+
target: x86_64-unknown-linux-gnu
|
|
105
|
+
manylinux: '2_17'
|
|
106
|
+
- name: linux-aarch64
|
|
107
|
+
os: ubuntu-latest
|
|
108
|
+
target: aarch64-unknown-linux-gnu
|
|
109
|
+
manylinux: '2_17'
|
|
110
|
+
- name: macos-x86_64
|
|
111
|
+
os: macos-15-intel
|
|
112
|
+
target: x86_64-apple-darwin
|
|
113
|
+
manylinux: off
|
|
114
|
+
- name: macos-arm64
|
|
115
|
+
os: macos-15
|
|
116
|
+
target: aarch64-apple-darwin
|
|
117
|
+
manylinux: off
|
|
118
|
+
- name: windows-x86_64
|
|
119
|
+
os: windows-latest
|
|
120
|
+
target: x86_64-pc-windows-msvc
|
|
121
|
+
manylinux: off
|
|
122
|
+
runs-on: ${{ matrix.os }}
|
|
123
|
+
steps:
|
|
124
|
+
- name: Check out repository
|
|
125
|
+
uses: actions/checkout@v6
|
|
126
|
+
with:
|
|
127
|
+
ref: ${{ needs.prepare-release.outputs.release_ref }}
|
|
128
|
+
|
|
129
|
+
- name: Set up QEMU for Linux ARM64
|
|
130
|
+
if: matrix.name == 'linux-aarch64'
|
|
131
|
+
uses: docker/setup-qemu-action@v3
|
|
132
|
+
|
|
133
|
+
- name: Set up Python interpreters
|
|
134
|
+
uses: actions/setup-python@v6
|
|
135
|
+
with:
|
|
136
|
+
python-version: |
|
|
137
|
+
3.10
|
|
138
|
+
3.11
|
|
139
|
+
3.12
|
|
140
|
+
3.13
|
|
141
|
+
3.14
|
|
142
|
+
|
|
143
|
+
- name: Build wheels with maturin
|
|
144
|
+
uses: PyO3/maturin-action@v1
|
|
145
|
+
with:
|
|
146
|
+
command: build
|
|
147
|
+
target: ${{ matrix.target }}
|
|
148
|
+
manylinux: ${{ matrix.manylinux }}
|
|
149
|
+
args: --release --locked --find-interpreter --compatibility pypi
|
|
150
|
+
maturin-version: v1.14.1
|
|
151
|
+
|
|
152
|
+
- name: Set up smoke-test Python
|
|
153
|
+
uses: actions/setup-python@v6
|
|
154
|
+
with:
|
|
155
|
+
python-version: '3.13'
|
|
156
|
+
|
|
157
|
+
- name: Install one wheel for smoke testing
|
|
158
|
+
if: matrix.name != 'linux-aarch64'
|
|
159
|
+
shell: bash
|
|
160
|
+
run: |
|
|
161
|
+
python -m pip install --upgrade "pydantic>=2,<3"
|
|
162
|
+
python -m pip install --force-reinstall --no-index target/wheels/*cp313*.whl
|
|
163
|
+
|
|
164
|
+
- name: Smoke-test installed wheel outside the checkout
|
|
165
|
+
if: matrix.name != 'linux-aarch64'
|
|
166
|
+
shell: bash
|
|
167
|
+
run: |
|
|
168
|
+
cd "$RUNNER_TEMP"
|
|
169
|
+
python - <<'PY'
|
|
170
|
+
import tempfile
|
|
171
|
+
|
|
172
|
+
from localqueue import EnqueueItem, SimpleQueue
|
|
173
|
+
from localqueue.bus import BaseEvent, BusTopology, EventBus
|
|
174
|
+
|
|
175
|
+
class WheelEvent(BaseEvent):
|
|
176
|
+
value: int
|
|
177
|
+
|
|
178
|
+
with tempfile.TemporaryDirectory() as path:
|
|
179
|
+
queue = SimpleQueue(path)
|
|
180
|
+
queue.put_many([
|
|
181
|
+
{"platform": "wheel"},
|
|
182
|
+
EnqueueItem({"platform": "batch"}, job_id="batch-1"),
|
|
183
|
+
])
|
|
184
|
+
job = queue.get(block=False)
|
|
185
|
+
queue.ack(job)
|
|
186
|
+
job = queue.get(block=False)
|
|
187
|
+
queue.ack(job)
|
|
188
|
+
assert queue.stats()["acked"] == 2
|
|
189
|
+
queue.close()
|
|
190
|
+
|
|
191
|
+
topology = BusTopology({"smoke": [WheelEvent]})
|
|
192
|
+
bus = EventBus(path, topology=topology)
|
|
193
|
+
smoke = bus.subscription("smoke")
|
|
194
|
+
|
|
195
|
+
@smoke.handler(WheelEvent)
|
|
196
|
+
def handle(event: WheelEvent) -> None:
|
|
197
|
+
assert event.value == 1
|
|
198
|
+
|
|
199
|
+
receipt = bus.dispatch(WheelEvent(value=1))
|
|
200
|
+
assert receipt.subscriptions == ("smoke",)
|
|
201
|
+
bus.close()
|
|
202
|
+
PY
|
|
203
|
+
|
|
204
|
+
- name: Validate Linux ARM64 wheel artifact
|
|
205
|
+
if: matrix.name == 'linux-aarch64'
|
|
206
|
+
shell: bash
|
|
207
|
+
run: test -n "$(find target/wheels -name '*cp313*.whl' -print -quit)"
|
|
208
|
+
|
|
209
|
+
- name: Build source distribution
|
|
210
|
+
if: matrix.name == 'linux-x86_64'
|
|
211
|
+
uses: PyO3/maturin-action@v1
|
|
212
|
+
with:
|
|
213
|
+
command: sdist
|
|
214
|
+
args: --out target/dist
|
|
215
|
+
maturin-version: v1.14.1
|
|
216
|
+
|
|
217
|
+
- name: Upload wheels
|
|
218
|
+
if: needs.prepare-release.outputs.release_mode != 'true'
|
|
219
|
+
uses: actions/upload-artifact@v4
|
|
220
|
+
with:
|
|
221
|
+
name: wheels-${{ matrix.name }}
|
|
222
|
+
path: target/wheels/*.whl
|
|
223
|
+
if-no-files-found: error
|
|
224
|
+
|
|
225
|
+
- name: Upload source distribution
|
|
226
|
+
if: matrix.name == 'linux-x86_64' && needs.prepare-release.outputs.release_mode != 'true'
|
|
227
|
+
uses: actions/upload-artifact@v4
|
|
228
|
+
with:
|
|
229
|
+
name: source-distribution
|
|
230
|
+
path: target/dist/*.tar.gz
|
|
231
|
+
if-no-files-found: error
|
|
232
|
+
|
|
233
|
+
- name: Upload distributions to draft GitHub release
|
|
234
|
+
if: needs.prepare-release.outputs.release_mode == 'true'
|
|
235
|
+
shell: bash
|
|
236
|
+
env:
|
|
237
|
+
GH_TOKEN: ${{ github.token }}
|
|
238
|
+
RELEASE_REF: ${{ needs.prepare-release.outputs.release_ref }}
|
|
239
|
+
run: |
|
|
240
|
+
gh release upload "$RELEASE_REF" target/wheels/*.whl \
|
|
241
|
+
--repo "$GITHUB_REPOSITORY" \
|
|
242
|
+
--clobber
|
|
243
|
+
|
|
244
|
+
if [[ "${{ matrix.name }}" == "linux-x86_64" ]]; then
|
|
245
|
+
gh release upload "$RELEASE_REF" target/dist/*.tar.gz \
|
|
246
|
+
--repo "$GITHUB_REPOSITORY" \
|
|
247
|
+
--clobber
|
|
248
|
+
fi
|
|
249
|
+
|
|
250
|
+
publish:
|
|
251
|
+
name: Publish complete release to PyPI
|
|
252
|
+
if: needs.prepare-release.outputs.release_mode == 'true'
|
|
253
|
+
needs: [prepare-release, build]
|
|
254
|
+
runs-on: ubuntu-latest
|
|
255
|
+
environment: pypi
|
|
256
|
+
permissions:
|
|
257
|
+
contents: write
|
|
258
|
+
id-token: write
|
|
259
|
+
steps:
|
|
260
|
+
- name: Download distributions from draft GitHub release
|
|
261
|
+
env:
|
|
262
|
+
GH_TOKEN: ${{ github.token }}
|
|
263
|
+
RELEASE_REF: ${{ needs.prepare-release.outputs.release_ref }}
|
|
264
|
+
run: |
|
|
265
|
+
mkdir -p target/dist
|
|
266
|
+
gh release download "$RELEASE_REF" \
|
|
267
|
+
--repo "$GITHUB_REPOSITORY" \
|
|
268
|
+
--dir target/dist
|
|
269
|
+
|
|
270
|
+
for python_tag in cp310 cp311 cp312 cp313 cp314; do
|
|
271
|
+
wheel_count=$(find target/dist -name "*-${python_tag}-${python_tag}-*.whl" | wc -l)
|
|
272
|
+
if [[ "$wheel_count" -ne 5 ]]; then
|
|
273
|
+
echo "expected 5 wheels for $python_tag, found $wheel_count" >&2
|
|
274
|
+
exit 1
|
|
275
|
+
fi
|
|
276
|
+
done
|
|
277
|
+
|
|
278
|
+
test "$(find target/dist -name '*.tar.gz' | wc -l)" -eq 1
|
|
279
|
+
|
|
280
|
+
- name: Install uv
|
|
281
|
+
uses: astral-sh/setup-uv@v8.3.2
|
|
282
|
+
|
|
283
|
+
- name: Publish all artifacts
|
|
284
|
+
run: |
|
|
285
|
+
uv publish \
|
|
286
|
+
--trusted-publishing always \
|
|
287
|
+
--check-url https://pypi.org/simple/ \
|
|
288
|
+
target/dist/*
|
|
289
|
+
|
|
290
|
+
- name: Publish GitHub release
|
|
291
|
+
env:
|
|
292
|
+
GH_TOKEN: ${{ github.token }}
|
|
293
|
+
RELEASE_REF: ${{ needs.prepare-release.outputs.release_ref }}
|
|
294
|
+
run: |
|
|
295
|
+
gh release edit "$RELEASE_REF" \
|
|
296
|
+
--repo "$GITHUB_REPOSITORY" \
|
|
297
|
+
--draft=false \
|
|
298
|
+
--latest
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
default_language_version:
|
|
2
|
+
python: python3.10
|
|
3
|
+
|
|
4
|
+
repos:
|
|
5
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
6
|
+
rev: v5.0.0
|
|
7
|
+
hooks:
|
|
8
|
+
- id: check-toml
|
|
9
|
+
- id: check-yaml
|
|
10
|
+
- id: end-of-file-fixer
|
|
11
|
+
- id: trailing-whitespace
|
|
12
|
+
|
|
13
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
14
|
+
rev: v0.15.22
|
|
15
|
+
hooks:
|
|
16
|
+
- id: ruff-check
|
|
17
|
+
args: [--fix]
|
|
18
|
+
- id: ruff-format
|
|
19
|
+
|
|
20
|
+
- repo: https://github.com/gitleaks/gitleaks
|
|
21
|
+
rev: v8.30.1
|
|
22
|
+
hooks:
|
|
23
|
+
- id: gitleaks
|
|
24
|
+
|
|
25
|
+
- repo: local
|
|
26
|
+
hooks:
|
|
27
|
+
- id: cargo-fmt
|
|
28
|
+
name: cargo fmt
|
|
29
|
+
entry: cargo fmt --all --check
|
|
30
|
+
language: system
|
|
31
|
+
pass_filenames: false
|
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `localqueue` are documented here.
|
|
4
4
|
|
|
5
|
+
<!-- version list -->
|
|
6
|
+
|
|
7
|
+
## [1.1.1] - 2026-07-21
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Zensical documentation site with a durable, two-process getting-started
|
|
12
|
+
guide and GitHub Pages deployment workflow.
|
|
13
|
+
- Python branch-coverage reporting, Ruff, Pyrefly, pre-commit, Gitleaks, and
|
|
14
|
+
cargo-deny quality gates.
|
|
15
|
+
- Manual Conventional Commits release workflow with Python, Cargo, lockfile,
|
|
16
|
+
tag, and wheel-release consistency checks.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- The README quickstart now demonstrates a producer persisting a job before a
|
|
21
|
+
later worker process consumes it.
|
|
22
|
+
- CI caches Rust build outputs and uses debug builds for test jobs while wheel
|
|
23
|
+
builds remain optimized release builds.
|
|
24
|
+
|
|
5
25
|
## [1.1.0] - 2026-07-21
|
|
6
26
|
|
|
7
27
|
### Added
|
|
@@ -80,6 +100,7 @@ storage migration:
|
|
|
80
100
|
leases, bounded retries, dead-letter handling, receipt fencing, and
|
|
81
101
|
multiprocess safety on one machine.
|
|
82
102
|
|
|
103
|
+
[1.1.1]: https://github.com/brunoportis/localqueue/compare/v1.1.0...v1.1.1
|
|
83
104
|
[1.1.0]: https://github.com/brunoportis/localqueue/compare/v1.0.1...v1.1.0
|
|
84
105
|
[1.0.1]: https://github.com/brunoportis/localqueue/compare/v1.0.0...v1.0.1
|
|
85
106
|
[1.0.0]: https://github.com/brunoportis/localqueue/releases/tag/v1.0.0
|