Studio: fetch the release source asset for exact (mix) source builds (#6195)
* Studio: fetch the release source asset for exact (mix) source builds The source-build fallback rebuilt the codeload/archive URL from the source repo and commit. A mix build's merged tree is never pushed to any repo (it ships only as the release's llama.cpp-source-commit-<sha>.tar.gz asset), so codeload 404s on the merge commit and an uncovered host could not build from source. When an exact-source asset exists, fetch it directly from the release and keep codeload as the fallback for vanilla builds whose commit is real. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
d0ffe26383
commit
36bc0394d9
2 changed files with 133 additions and 1 deletions
|
|
@ -1095,6 +1095,20 @@ def commit_source_archive_urls(repo: str, source_commit: str) -> list[str]:
|
|||
]
|
||||
|
||||
|
||||
def release_asset_download_url(
|
||||
repo: str | None, release_tag: str | None, asset_name: str | None
|
||||
) -> str | None:
|
||||
"""Direct download URL for a release asset, or None if any part is missing.
|
||||
A mix build's merged commit is never pushed, so its source tree is only
|
||||
reachable as this asset (codeload would 404 on the merge commit)."""
|
||||
if not repo or not release_tag or not asset_name:
|
||||
return None
|
||||
return (
|
||||
f"https://github.com/{repo}/releases/download/"
|
||||
f"{urllib.parse.quote(release_tag, safe = '')}/{urllib.parse.quote(asset_name, safe = '')}"
|
||||
)
|
||||
|
||||
|
||||
def github_release_assets(repo: str, tag: str) -> dict[str, str]:
|
||||
payload = fetch_json(
|
||||
f"https://api.github.com/repos/{repo}/releases/tags/{urllib.parse.quote(tag, safe = '')}"
|
||||
|
|
@ -4495,13 +4509,17 @@ def hydrate_source_tree(
|
|||
expected_sha256: str | None,
|
||||
source_label: str | None = None,
|
||||
exact_source: bool = False,
|
||||
asset_url: str | None = None,
|
||||
) -> None:
|
||||
archive_path = work_dir / f"llama.cpp-source-{source_ref}.tar.gz"
|
||||
source_urls = (
|
||||
repo_urls = (
|
||||
commit_source_archive_urls(source_repo, source_ref)
|
||||
if exact_source
|
||||
else upstream_source_archive_urls(source_ref)
|
||||
)
|
||||
# Prefer the published release asset (the only copy of a mix build's merged
|
||||
# tree); fall back to codeload/archive for vanilla builds whose commit is real.
|
||||
source_urls = ([asset_url] if asset_url else []) + repo_urls
|
||||
label = source_label or f"llama.cpp source tree for {source_ref}"
|
||||
extract_dir = Path(tempfile.mkdtemp(prefix = "source-extract-", dir = work_dir))
|
||||
|
||||
|
|
@ -6404,6 +6422,15 @@ def validate_prebuilt_choice(
|
|||
source_repo, source_ref, source_archive, exact_source = preferred_source_archive(
|
||||
approved_checksums, llama_tag
|
||||
)
|
||||
# For an exact (mix) source the merge commit lives only in the release asset,
|
||||
# not in any repo, so fetch the asset directly; codeload stays the fallback.
|
||||
asset_url = (
|
||||
release_asset_download_url(
|
||||
approved_checksums.repo, approved_checksums.release_tag, source_archive.asset_name
|
||||
)
|
||||
if exact_source and source_archive is not None
|
||||
else None
|
||||
)
|
||||
if exact_source:
|
||||
log(f"hydrating exact llama.cpp source for {source_repo}@{source_ref} into {install_dir}")
|
||||
else:
|
||||
|
|
@ -6420,6 +6447,7 @@ def validate_prebuilt_choice(
|
|||
else f"llama.cpp source tree for {llama_tag}"
|
||||
),
|
||||
exact_source = exact_source,
|
||||
asset_url = asset_url,
|
||||
)
|
||||
log(f"overlaying prebuilt bundle {choice.name} into {install_dir}")
|
||||
server_path, quantize_path = install_from_archives(choice, host, install_dir, work_dir)
|
||||
|
|
|
|||
|
|
@ -206,6 +206,110 @@ def test_hydrate_source_tree_extracts_upstream_archive_contents(
|
|||
assert not (install_dir / f"llama.cpp-{upstream_tag}").exists()
|
||||
|
||||
|
||||
def test_release_asset_download_url():
|
||||
fn = INSTALL_LLAMA_PREBUILT.release_asset_download_url
|
||||
assert fn(
|
||||
"unslothai/llama.cpp", "b9000-mix-abc1234", "llama.cpp-source-commit-deadbeef.tar.gz"
|
||||
) == (
|
||||
"https://github.com/unslothai/llama.cpp/releases/download/"
|
||||
"b9000-mix-abc1234/llama.cpp-source-commit-deadbeef.tar.gz"
|
||||
)
|
||||
# Any missing component -> None (no asset url, caller falls back to codeload).
|
||||
assert fn(None, "b9000", "x.tar.gz") is None
|
||||
assert fn("unslothai/llama.cpp", None, "x.tar.gz") is None
|
||||
assert fn("unslothai/llama.cpp", "b9000", None) is None
|
||||
|
||||
|
||||
def _mk_source_tarball(path: Path, tag: str) -> None:
|
||||
with tarfile.open(path, "w:gz") as archive:
|
||||
add_bytes_to_tar(
|
||||
archive, f"llama.cpp-{tag}/CMakeLists.txt", b"cmake_minimum_required(VERSION 3.14)\n"
|
||||
)
|
||||
add_bytes_to_tar(
|
||||
archive,
|
||||
f"llama.cpp-{tag}/convert_hf_to_gguf.py",
|
||||
b"#!/usr/bin/env python3\nimport gguf\n",
|
||||
)
|
||||
add_bytes_to_tar(archive, f"llama.cpp-{tag}/gguf-py/gguf/__init__.py", b"__all__ = []\n")
|
||||
|
||||
|
||||
def test_hydrate_source_tree_prefers_release_asset_for_mix(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
):
|
||||
# A mix build's merge commit is in no repo, so the codeload/archive URLs 404.
|
||||
# hydrate must fetch the release asset and never touch codeload.
|
||||
commit = "a" * 40
|
||||
archive_path = tmp_path / "merged-source.tar.gz"
|
||||
_mk_source_tarball(archive_path, f"b9000-mix-{commit[:7]}")
|
||||
asset_url = INSTALL_LLAMA_PREBUILT.release_asset_download_url(
|
||||
"unslothai/llama.cpp", "b9000-mix-abc1234", f"llama.cpp-source-commit-{commit}.tar.gz"
|
||||
)
|
||||
codeload_urls = set(
|
||||
INSTALL_LLAMA_PREBUILT.commit_source_archive_urls("unslothai/llama.cpp", commit)
|
||||
)
|
||||
seen = []
|
||||
|
||||
def fake_download_file(url: str, destination: Path) -> None:
|
||||
seen.append(url)
|
||||
if url in codeload_urls:
|
||||
raise AssertionError("codeload was hit even though the release asset was available")
|
||||
assert url == asset_url
|
||||
destination.write_bytes(archive_path.read_bytes())
|
||||
|
||||
monkeypatch.setattr(INSTALL_LLAMA_PREBUILT, "download_file", fake_download_file)
|
||||
|
||||
install_dir = tmp_path / "install"
|
||||
work_dir = tmp_path / "work"
|
||||
work_dir.mkdir()
|
||||
hydrate_source_tree(
|
||||
commit,
|
||||
install_dir,
|
||||
work_dir,
|
||||
source_repo = "unslothai/llama.cpp",
|
||||
expected_sha256 = sha256_file(archive_path),
|
||||
exact_source = True,
|
||||
asset_url = asset_url,
|
||||
)
|
||||
assert seen == [asset_url]
|
||||
assert (install_dir / "CMakeLists.txt").exists()
|
||||
assert (install_dir / "convert_hf_to_gguf.py").exists()
|
||||
|
||||
|
||||
def test_hydrate_source_tree_falls_back_to_codeload_when_asset_missing(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
):
|
||||
# If the release asset 404s, fall back to codeload/archive (vanilla path).
|
||||
commit = "b" * 40
|
||||
archive_path = tmp_path / "vanilla-source.tar.gz"
|
||||
_mk_source_tarball(archive_path, f"commit-{commit[:7]}")
|
||||
asset_url = INSTALL_LLAMA_PREBUILT.release_asset_download_url(
|
||||
"unslothai/llama.cpp", "b9000", f"llama.cpp-source-commit-{commit}.tar.gz"
|
||||
)
|
||||
codeload_urls = INSTALL_LLAMA_PREBUILT.commit_source_archive_urls("unslothai/llama.cpp", commit)
|
||||
|
||||
def fake_download_file(url: str, destination: Path) -> None:
|
||||
if url == asset_url:
|
||||
raise RuntimeError("404 Not Found")
|
||||
assert url in codeload_urls
|
||||
destination.write_bytes(archive_path.read_bytes())
|
||||
|
||||
monkeypatch.setattr(INSTALL_LLAMA_PREBUILT, "download_file", fake_download_file)
|
||||
|
||||
install_dir = tmp_path / "install"
|
||||
work_dir = tmp_path / "work"
|
||||
work_dir.mkdir()
|
||||
hydrate_source_tree(
|
||||
commit,
|
||||
install_dir,
|
||||
work_dir,
|
||||
source_repo = "unslothai/llama.cpp",
|
||||
expected_sha256 = sha256_file(archive_path),
|
||||
exact_source = True,
|
||||
asset_url = asset_url,
|
||||
)
|
||||
assert (install_dir / "CMakeLists.txt").exists()
|
||||
|
||||
|
||||
def test_validate_prebuilt_choice_creates_repo_shaped_linux_install(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue