repro-lambda 0.8.0__tar.gz → 0.8.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.
- repro_lambda-0.8.1/.release-please-manifest.json +3 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/CHANGELOG.md +7 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/PKG-INFO +1 -1
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/pyproject.toml +1 -1
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/src/repro_lambda/__init__.py +1 -1
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/src/repro_lambda/sources.py +11 -2
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_sources.py +54 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/uv.lock +1 -1
- repro_lambda-0.8.0/.release-please-manifest.json +0 -3
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/.github/workflows/build.yml +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/.github/workflows/ci.yml +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/.github/workflows/move-major-tag.yml +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/.github/workflows/promote.yml +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/.github/workflows/publish.yml +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/.github/workflows/release.yml +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/.gitignore +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/.pre-commit-config.yaml +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/LICENSE +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/README.md +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/SETUP.md +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/USAGE.md +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/assets/social-preview.html +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/assets/social-preview.png +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/examples/complete/README.md +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/examples/complete/builds/catalog.json +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/examples/complete/lambdas.toml +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/examples/complete/main.tf +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/examples/complete/outputs.tf +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/examples/complete/src/app/app.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/examples/complete/src/app/requirements.arm64.lock +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/examples/complete/variables.tf +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/examples/complete/versions.tf +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/release-please-config.json +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/src/repro_lambda/__main__.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/src/repro_lambda/build.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/src/repro_lambda/catalog.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/src/repro_lambda/cli.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/src/repro_lambda/docker_runner.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/src/repro_lambda/git_guard.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/src/repro_lambda/hasher.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/src/repro_lambda/manifest.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/src/repro_lambda/promote.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/src/repro_lambda/s3_uploader.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/src/repro_lambda/source_locker.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/src/repro_lambda/source_stager.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/src/repro_lambda/verify.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/src/repro_lambda/zip_packager.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/__init__.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/conftest.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/fixtures/sample_nodejs_lambda/handler/index.js +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/fixtures/sample_nodejs_lambda/handler/package-lock.json +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/fixtures/sample_nodejs_lambda/handler/package.json +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/fixtures/sample_nodejs_lambda/lambdas.toml +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/fixtures/sample_python_lambda/handler/app.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/fixtures/sample_python_lambda/handler/requirements.arm64.lock +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/fixtures/sample_python_lambda/handler/requirements.in +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/fixtures/sample_python_lambda/lambdas.toml +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_build_integration.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_build_nodejs.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_catalog.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_cli_build.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_cli_lock.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_cli_smoke.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_docker_runner.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_docker_runner_nodejs.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_e2e_nodejs_lambda.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_e2e_python_lambda.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_extra_files.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_git_guard.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_hasher.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_manifest.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_per_lambda_builder.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_promote.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_python_byte_compat_regression.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_s3_uploader.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_source_locker.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_source_stager.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_sources_hash.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_sources_schema.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_verify.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_zip_excludes.py +0 -0
- {repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/test_zip_packager.py +0 -0
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.8.1](https://github.com/antonbabenko/repro-lambda/compare/v0.8.0...v0.8.1) (2026-09-23)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **sources:** fall back to the release assets endpoint when the tag view lists none ([#17](https://github.com/antonbabenko/repro-lambda/issues/17)) ([3a5608b](https://github.com/antonbabenko/repro-lambda/commit/3a5608b8cd7294f66986b1a61e4607efd052163a))
|
|
9
|
+
|
|
3
10
|
## [0.8.0](https://github.com/antonbabenko/repro-lambda/compare/v0.7.2...v0.8.0) (2026-09-18)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: repro-lambda
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.1
|
|
4
4
|
Summary: Build reproducible AWS Lambda packages outside Terraform, optimized for terraform-aws-lambda by serverless.tf.
|
|
5
5
|
Project-URL: Homepage, https://github.com/antonbabenko/repro-lambda
|
|
6
6
|
Project-URL: Repository, https://github.com/antonbabenko/repro-lambda
|
|
@@ -34,6 +34,7 @@ import tempfile
|
|
|
34
34
|
import zipfile
|
|
35
35
|
from http.client import HTTPSConnection
|
|
36
36
|
from pathlib import Path
|
|
37
|
+
from typing import Any
|
|
37
38
|
from urllib.parse import urljoin, urlsplit, urlunsplit
|
|
38
39
|
|
|
39
40
|
from repro_lambda import __version__
|
|
@@ -183,7 +184,7 @@ def _stream_to(resp, sink: io.BufferedWriter, max_bytes: int) -> str:
|
|
|
183
184
|
return h.hexdigest()
|
|
184
185
|
|
|
185
186
|
|
|
186
|
-
def _http_get_json(url: str, headers: dict[str, str]) ->
|
|
187
|
+
def _http_get_json(url: str, headers: dict[str, str]) -> Any:
|
|
187
188
|
buf = io.BytesIO()
|
|
188
189
|
writer = io.BufferedWriter(_RawSink(buf))
|
|
189
190
|
_http_request(url, headers, writer, _JSON_MAX_BYTES)
|
|
@@ -219,7 +220,15 @@ def _github_asset_url(src: Source, token: str | None) -> tuple[str, dict[str, st
|
|
|
219
220
|
auth = {"Authorization": f"Bearer {token}", "Accept": "application/vnd.github+json"}
|
|
220
221
|
release = _http_get_json(api, auth)
|
|
221
222
|
want = src.resolved_asset
|
|
222
|
-
|
|
223
|
+
assets = release.get("assets", [])
|
|
224
|
+
if not any(a.get("name") == want for a in assets) and "id" in release:
|
|
225
|
+
# The tag view can serve a stale, empty `assets` list for a while after an
|
|
226
|
+
# upload; the per-release assets endpoint is current.
|
|
227
|
+
# ponytail: first 100 assets only, paginate if a release ever carries more.
|
|
228
|
+
assets = _http_get_json(
|
|
229
|
+
f"{_GITHUB_API}/repos/{src.repo}/releases/{release['id']}/assets?per_page=100", auth
|
|
230
|
+
)
|
|
231
|
+
for asset in assets:
|
|
223
232
|
if asset.get("name") == want:
|
|
224
233
|
asset_id = asset["id"]
|
|
225
234
|
dl = f"{_GITHUB_API}/repos/{src.repo}/releases/assets/{asset_id}"
|
|
@@ -358,6 +358,60 @@ def test_github_source_requires_token(tmp_path: Path):
|
|
|
358
358
|
sources._github_asset_url(src, None)
|
|
359
359
|
|
|
360
360
|
|
|
361
|
+
def _gh_src() -> Source:
|
|
362
|
+
return Source(
|
|
363
|
+
name="p",
|
|
364
|
+
type="github_release",
|
|
365
|
+
sha256=SHA_PLACEHOLDER,
|
|
366
|
+
extract="tar.gz",
|
|
367
|
+
dest="p",
|
|
368
|
+
repo="o/r",
|
|
369
|
+
tag="t",
|
|
370
|
+
asset="a.tgz",
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def test_github_asset_falls_back_to_assets_endpoint(monkeypatch):
|
|
375
|
+
# GitHub can serve releases/tags/<tag> with a stale, empty `assets` list right after
|
|
376
|
+
# an upload, while /releases/{id}/assets already lists the file.
|
|
377
|
+
calls = []
|
|
378
|
+
|
|
379
|
+
def fake_get(url, headers):
|
|
380
|
+
calls.append(url)
|
|
381
|
+
if url.endswith("/releases/tags/t"):
|
|
382
|
+
return {"id": 7, "assets": []}
|
|
383
|
+
assert url.endswith("/releases/7/assets?per_page=100")
|
|
384
|
+
return [{"name": "other", "id": 1}, {"name": "a.tgz", "id": 42}]
|
|
385
|
+
|
|
386
|
+
monkeypatch.setattr(sources, "_http_get_json", fake_get)
|
|
387
|
+
url, headers = sources._github_asset_url(_gh_src(), "tok")
|
|
388
|
+
assert url.endswith("/repos/o/r/releases/assets/42")
|
|
389
|
+
assert headers["Accept"] == "application/octet-stream"
|
|
390
|
+
assert len(calls) == 2
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def test_github_asset_embedded_list_needs_no_second_call(monkeypatch):
|
|
394
|
+
calls = []
|
|
395
|
+
|
|
396
|
+
def fake_get(url, headers):
|
|
397
|
+
calls.append(url)
|
|
398
|
+
return {"id": 7, "assets": [{"name": "a.tgz", "id": 42}]}
|
|
399
|
+
|
|
400
|
+
monkeypatch.setattr(sources, "_http_get_json", fake_get)
|
|
401
|
+
url, _ = sources._github_asset_url(_gh_src(), "tok")
|
|
402
|
+
assert url.endswith("/releases/assets/42")
|
|
403
|
+
assert len(calls) == 1
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
def test_github_asset_missing_everywhere_raises(monkeypatch):
|
|
407
|
+
def fake_get(url, headers):
|
|
408
|
+
return {"id": 7, "assets": []} if url.endswith("/tags/t") else []
|
|
409
|
+
|
|
410
|
+
monkeypatch.setattr(sources, "_http_get_json", fake_get)
|
|
411
|
+
with pytest.raises(SourceFetchError, match="not found"):
|
|
412
|
+
sources._github_asset_url(_gh_src(), "tok")
|
|
413
|
+
|
|
414
|
+
|
|
361
415
|
# --- staging + end-to-end (no network) -------------------------------------
|
|
362
416
|
|
|
363
417
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/fixtures/sample_nodejs_lambda/handler/index.js
RENAMED
|
File without changes
|
|
File without changes
|
{repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/fixtures/sample_nodejs_lambda/handler/package.json
RENAMED
|
File without changes
|
|
File without changes
|
{repro_lambda-0.8.0 → repro_lambda-0.8.1}/tests/fixtures/sample_python_lambda/handler/app.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|