From 0e0dfabe67af4d38f9656d9604bf918b5203cfe0 Mon Sep 17 00:00:00 2001 From: sayakpaul Date: Fri, 10 Jul 2026 08:56:31 +0530 Subject: [PATCH 1/2] feat: implement opening PRs to non-owned repos. --- .github/scripts/dispatch.py | 18 ++ .github/scripts/pr_comment_kernel_bot.py | 4 + .github/scripts/test_upload_and_report.py | 188 ++++++++++++ .github/scripts/upload_and_report.py | 280 ++++++++++++++++++ .github/scripts/windows/upload_and_report.ps1 | 106 +++++++ .github/workflows/build-mac.yaml | 51 +++- .github/workflows/build-windows.yaml | 42 ++- .github/workflows/build.yaml | 53 +++- .github/workflows/sign-old-builds.yaml | 29 +- msa/build.toml | 2 +- sgl-flash-attn3/build.toml | 2 +- 11 files changed, 734 insertions(+), 41 deletions(-) create mode 100644 .github/scripts/test_upload_and_report.py create mode 100644 .github/scripts/upload_and_report.py create mode 100644 .github/scripts/windows/upload_and_report.ps1 diff --git a/.github/scripts/dispatch.py b/.github/scripts/dispatch.py index 35e56706f..09b4f83e9 100644 --- a/.github/scripts/dispatch.py +++ b/.github/scripts/dispatch.py @@ -151,6 +151,7 @@ def _build_inputs( head_sha: str, target_branch: str, upload: bool, + comment_pr_number: str, ) -> dict: inputs = { "kernel_name": kernel_name, @@ -169,6 +170,11 @@ def _build_inputs( inputs["target_branch"] = target_branch if not upload: inputs["upload"] = "false" + # PR to report Hub upload pull-request links back to. Distinct from + # pr_number (which selects the branch to check out): release/merge uploads + # build from the default branch but still comment on the originating PR. + if comment_pr_number: + inputs["comment_pr_number"] = comment_pr_number return inputs @@ -232,6 +238,7 @@ def _plan_build_actions( head_sha: str, target_branch: str, upload: bool, + comment_pr_number: str, ) -> None: backends = read_backends(kernel_name) or [] workflows = select_workflows(kernel_name, notes=plan.notes) @@ -272,6 +279,7 @@ def _plan_build_actions( head_sha=head_sha, target_branch=target_branch, upload=upload, + comment_pr_number=comment_pr_number, ), }, description=f"for kernel `{kernel_name}` on ref `{ref}`", @@ -292,6 +300,7 @@ def plan_dispatch( head_sha: str = "", target_branch: str = "", upload: bool = True, + comment_pr_number: str = "", run_security: bool = False, security_only: bool = False, ) -> DispatchPlan: @@ -311,6 +320,7 @@ def plan_dispatch( head_sha=head_sha, target_branch=target_branch, upload=upload, + comment_pr_number=comment_pr_number, ) if want_security: @@ -458,6 +468,7 @@ def dispatch( head_sha: str = "", target_branch: str = "", upload: bool = True, + comment_pr_number: str = "", run_security: bool = False, security_only: bool = False, ) -> DispatchResult: @@ -479,6 +490,7 @@ def dispatch( head_sha=head_sha, target_branch=target_branch, upload=upload, + comment_pr_number=comment_pr_number, run_security=run_security, security_only=security_only, ) @@ -583,6 +595,11 @@ def main() -> int: action="store_true", help="Build only, do not upload", ) + parser.add_argument( + "--comment-pr-number", + default="", + help="PR to report Hub upload pull-request links back to (for --create-pr uploads)", + ) parser.add_argument( "--dry-run", action="store_true", @@ -631,6 +648,7 @@ def main() -> int: head_sha=args.head_sha, target_branch=args.target_branch, upload=not args.no_upload, + comment_pr_number=args.comment_pr_number, run_security=args.security, security_only=args.security_only, dispatch_key_prefix=args.dispatch_key_prefix, diff --git a/.github/scripts/pr_comment_kernel_bot.py b/.github/scripts/pr_comment_kernel_bot.py index 490fd7d28..a25ef5ff6 100644 --- a/.github/scripts/pr_comment_kernel_bot.py +++ b/.github/scripts/pr_comment_kernel_bot.py @@ -875,6 +875,10 @@ def main(*, dry_run: bool = False): head_sha=pr_head_sha or "", target_branch=target_branch, upload=dispatch_upload, + # For uploads, report Hub create-pr links back to this PR. Only + # external-org kernels (repo-id outside kernels-community) actually + # open PRs and comment; direct uploads ignore this. + comment_pr_number=str(issue_number) if dispatch_upload else "", # The audit is per-PR, so request it only once (on the first kernel). run_security=run_security and index == 0, dry_run=dry_run, diff --git a/.github/scripts/test_upload_and_report.py b/.github/scripts/test_upload_and_report.py new file mode 100644 index 000000000..bd836a7eb --- /dev/null +++ b/.github/scripts/test_upload_and_report.py @@ -0,0 +1,188 @@ +import os +import sys +from pathlib import Path +from unittest import mock + +sys.path.insert(0, os.path.dirname(__file__)) + +import upload_and_report as uar # noqa: E402 + + +def test_external_kernel_uses_repo_id_and_create_pr(): + # Repo-id outside kernels-community -> upload to that repo-id via PR, + # ignoring the repo_prefix (external kernels publish to their own repo). + assert uar.resolve_upload_target("MiniMaxAI/msa", "msa", "kernels-community") == ( + "MiniMaxAI/msa", + True, + ) + assert uar.resolve_upload_target("MiniMaxAI/msa", "msa", "kernels-staging") == ( + "MiniMaxAI/msa", + True, + ) + assert uar.resolve_upload_target( + "sgl-project/sgl-flash-attn3", "sgl-flash-attn3", "kernels-community" + ) == ("sgl-project/sgl-flash-attn3", True) + + +def test_community_kernel_uses_prefix_no_create_pr(): + assert uar.resolve_upload_target( + "kernels-community/relu", "relu", "kernels-community" + ) == ("kernels-community/relu", False) + # repo_prefix override (build-and-stage) still routes directly, no PR. + assert uar.resolve_upload_target( + "kernels-community/relu", "relu", "kernels-staging" + ) == ("kernels-staging/relu", False) + + +def test_missing_repo_id_falls_back_to_prefix(): + assert uar.resolve_upload_target(None, "foo", "kernels-community") == ( + "kernels-community/foo", + False, + ) + + +def test_parse_pr_urls(): + out = ( + "progress...\n" + "Pull request created: https://hf.co/kernels/MiniMaxAI/msa/discussions/3\n" + "Pull request created: https://hf.co/kernels/MiniMaxAI/msa/discussions/4\n" + ) + assert uar.parse_pr_urls(out) == [ + "https://hf.co/kernels/MiniMaxAI/msa/discussions/3", + "https://hf.co/kernels/MiniMaxAI/msa/discussions/4", + ] + assert uar.parse_pr_urls("No changes to upload.\n") == [] + + +def test_success_comment_lists_links(): + msg = uar.format_success_comment( + "msa", "MiniMaxAI/msa", "Build / cuda / x86_64-linux", ["url1", "url2"] + ) + assert "pull request opened" in msg + assert "MiniMaxAI/msa" in msg + assert "- url1" in msg and "- url2" in msg + + +def test_success_comment_no_changes(): + msg = uar.format_success_comment("msa", "MiniMaxAI/msa", "Build", []) + assert "no changes to upload" in msg + + +def test_failure_comment_includes_run_url_and_code(): + msg = uar.format_failure_comment( + "msa", "MiniMaxAI/msa", "Build", "http://run/1", 2 + ) + assert "failed" in msg + assert "http://run/1" in msg + assert "exit code 2" in msg + + +def _fake_kernel(tmp_path: Path, repo_id: str) -> Path: + kdir = tmp_path / "kern" + kdir.mkdir() + (kdir / "build.toml").write_text( + f'[general.hub]\nrepo-id = "{repo_id}"\n' + ) + return kdir + + +def test_read_repo_id(tmp_path): + kdir = _fake_kernel(tmp_path, "MiniMaxAI/msa") + assert uar.read_repo_id(kdir) == "MiniMaxAI/msa" + assert uar.read_repo_id(tmp_path / "missing") is None + + +def _run_main(argv, posts): + def fake_post(url, token, data): + posts.append((url, data)) + + with mock.patch.object(uar, "github_api_post", fake_post), mock.patch.dict( + os.environ, + {"GITHUB_TOKEN": "tok", "GITHUB_REPOSITORY": "huggingface/kernels-community"}, + ): + old = sys.argv + sys.argv = ["upload_and_report.py"] + argv + try: + return uar.main() + finally: + sys.argv = old + + +def _builder_script(tmp_path: Path, name: str, body: str) -> str: + script = tmp_path / name + script.write_text("#!/bin/bash\n" + body) + script.chmod(0o755) + return str(script) + + +def test_main_external_success_comments(tmp_path): + kdir = _fake_kernel(tmp_path, "MiniMaxAI/msa") + builder = _builder_script( + tmp_path, + "ok.sh", + "echo 'Pull request created: https://hf.co/kernels/MiniMaxAI/msa/discussions/9'\n", + ) + posts = [] + rc = _run_main( + [ + "--kernel", str(kdir), + "--repo-prefix", "kernels-community", + "--comment-pr-number", "42", + "--label", "Build / cuda", + "--run-url", "http://run", + "--builder", f"{builder} up", + ], + posts, + ) + assert rc == 0 + assert len(posts) == 1 + url, data = posts[0] + assert url.endswith("/issues/42/comments") + assert "discussions/9" in data["body"] + + +def test_main_external_failure_comments_and_propagates(tmp_path): + kdir = _fake_kernel(tmp_path, "MiniMaxAI/msa") + builder = _builder_script(tmp_path, "fail.sh", "echo boom >&2\nexit 3\n") + posts = [] + rc = _run_main( + [ + "--kernel", str(kdir), + "--comment-pr-number", "42", + "--run-url", "http://run/9", + "--builder", f"{builder} up", + ], + posts, + ) + assert rc == 3 + assert len(posts) == 1 + assert "failed" in posts[0][1]["body"] + + +def test_main_community_does_not_comment(tmp_path): + kdir = _fake_kernel(tmp_path, "kernels-community/relu") + builder = _builder_script(tmp_path, "ok.sh", "echo hi\n") + posts = [] + rc = _run_main( + [ + "--kernel", str(kdir), + "--repo-prefix", "kernels-community", + "--comment-pr-number", "42", + "--builder", f"{builder} up", + ], + posts, + ) + assert rc == 0 + assert posts == [] + + +def test_main_external_without_comment_pr_number_does_not_comment(tmp_path): + kdir = _fake_kernel(tmp_path, "MiniMaxAI/msa") + builder = _builder_script(tmp_path, "ok.sh", "echo hi\n") + posts = [] + rc = _run_main( + ["--kernel", str(kdir), "--builder", f"{builder} up"], + posts, + ) + assert rc == 0 + assert posts == [] diff --git a/.github/scripts/upload_and_report.py b/.github/scripts/upload_and_report.py new file mode 100644 index 000000000..376916c2c --- /dev/null +++ b/.github/scripts/upload_and_report.py @@ -0,0 +1,280 @@ +"""Upload a built kernel to the Hub and report the outcome back to a PR. + +This wraps the `kernel-builder upload` invocation used by the build workflows so +that kernels living outside the `kernels-community` org are uploaded through a +pull request (the CI bot has no write access to third-party orgs) instead of a +direct commit. + +Routing is decided from the kernel's `build.toml` `repo-id`: + +* org == `kernels-community` -> direct upload to `/` + (unchanged behaviour; `repo_prefix` lets `build-and-stage` target + `kernels-staging`). +* org != `kernels-community` -> upload to the real `repo-id` from `build.toml` + with `--create-pr`, which opens a pull request on the Hub. `repo_prefix` is + ignored: an external kernel is always published to its own repository. + +When `--create-pr` is used and a `--comment-pr-number` is given, the Hub pull +request links (printed by the uploader as `Pull request created: `) are +posted back as a comment on the originating GitHub PR. If the upload fails, a +failure comment is posted instead. Direct (`kernels-community`) uploads are left +untouched and never comment. + +The process exit code mirrors the uploader's, so a failed upload still fails the +build step. +""" + +import argparse +import json +import os +import re +import shlex +import subprocess +import sys +import tomllib +import urllib.error +import urllib.request +from pathlib import Path + +COMMUNITY_ORG = "kernels-community" +PR_URL_RE = re.compile(r"^Pull request created:\s*(\S+)\s*$", re.MULTILINE) + + +def read_repo_id(kernel_dir: Path) -> str | None: + """Return the `[general.hub] repo-id` declared in the kernel's build.toml.""" + build_toml = kernel_dir / "build.toml" + if not build_toml.exists(): + return None + with open(build_toml, "rb") as f: + config = tomllib.load(f) + repo_id = config.get("general", {}).get("hub", {}).get("repo-id") + return repo_id if isinstance(repo_id, str) and repo_id else None + + +def repo_org(repo_id: str) -> str: + return repo_id.split("/", 1)[0] + + +def resolve_upload_target( + repo_id: str | None, kernel: str, repo_prefix: str +) -> tuple[str, bool]: + """Return (upload_repo_id, create_pr) for the upload. + + External kernels (repo-id org != kernels-community) upload to their own + repo-id via a pull request; everything else keeps the direct + `/` behaviour. + """ + if repo_id and repo_org(repo_id) != COMMUNITY_ORG: + return repo_id, True + return f"{repo_prefix}/{kernel}", False + + +def parse_pr_urls(stdout: str) -> list[str]: + return PR_URL_RE.findall(stdout) + + +def github_api_post(url: str, token: str, data: dict) -> None: + body = json.dumps(data).encode("utf-8") + req = urllib.request.Request( + url=url, + data=body, + method="POST", + headers={ + "Accept": "application/vnd.github+json", + "Authorization": f"Bearer {token}", + "X-GitHub-Api-Version": "2022-11-28", + "Content-Type": "application/json", + }, + ) + with urllib.request.urlopen(req) as resp: + resp.read() + + +def post_pr_comment( + repo: str, token: str, pr_number: str, message: str +) -> bool: + url = f"https://api.github.com/repos/{repo}/issues/{pr_number}/comments" + try: + github_api_post(url, token, {"body": message}) + return True + except urllib.error.HTTPError as e: + err_text = e.read().decode("utf-8", errors="replace") + print(f"Failed to post PR comment (HTTP {e.code}).", file=sys.stderr) + print(err_text, file=sys.stderr) + return False + except urllib.error.URLError as e: + print(f"Failed to post PR comment: {e}", file=sys.stderr) + return False + + +def format_success_comment( + kernel: str, repo_id: str, label: str, pr_urls: list[str] +) -> str: + header = "### Kernel upload → pull request opened" + context = ( + f"Kernel `{kernel}` ({label}) targets `{repo_id}`, which is outside " + f"`{COMMUNITY_ORG}`, so the build was uploaded via pull request:" + ) + if pr_urls: + links = "\n".join(f"- {url}" for url in pr_urls) + return f"{header}\n\n{context}\n\n{links}" + # Upload succeeded but the Hub reported nothing to change, so no PR opened. + return ( + "### Kernel upload\n\n" + f"Kernel `{kernel}` ({label}) → `{repo_id}`: upload completed, but no " + "pull request was opened (no changes to upload)." + ) + + +def format_failure_comment( + kernel: str, repo_id: str, label: str, run_url: str | None, returncode: int +) -> str: + details = ( + f" See the [workflow run]({run_url}) for details." if run_url else "" + ) + return ( + "### Kernel upload failed\n\n" + f"Uploading kernel `{kernel}` ({label}) to `{repo_id}` via pull request " + f"failed (exit code {returncode}).{details}" + ) + + +def run_upload( + builder_cmd: list[str], + *, + upload_repo_id: str, + upload_path: str | None, + branch: str | None, + create_pr: bool, + cwd: Path, +) -> tuple[int, str]: + """Run the uploader, streaming stderr live and capturing stdout. + + The uploader prints progress/diagnostics to stderr (streamed to the CI log) + and the `Pull request created: ` lines to stdout (captured here so the + PR links can be reported back). + """ + cmd = list(builder_cmd) + if upload_path: + cmd.append(upload_path) + cmd += ["--repo-type", "kernel", "--repo-id", upload_repo_id] + if branch: + cmd += ["--branch", branch] + if create_pr: + cmd.append("--create-pr") + + print(f"+ {' '.join(cmd)}", file=sys.stderr, flush=True) + # stderr inherits the console (live progress); stdout is captured for URLs. + proc = subprocess.run(cmd, cwd=str(cwd), stdout=subprocess.PIPE, text=True) + if proc.stdout: + # Echo captured stdout so it still shows up in the workflow logs. + sys.stdout.write(proc.stdout) + sys.stdout.flush() + return proc.returncode, proc.stdout or "" + + +def main() -> int: + parser = argparse.ArgumentParser( + description="Upload a kernel and report PR links back to a GitHub PR." + ) + parser.add_argument("--kernel", required=True, help="Kernel directory name") + parser.add_argument( + "--repo-prefix", + default=COMMUNITY_ORG, + help="Hub org prefix for direct (kernels-community) uploads", + ) + parser.add_argument( + "--branch", default="", help="Target branch for the upload (optional)" + ) + parser.add_argument( + "--upload-path", + default="", + help="Positional path passed to the uploader (e.g. build/ on Windows)", + ) + parser.add_argument( + "--comment-pr-number", + default="", + help="GitHub PR number to report create-pr links to (empty = no comment)", + ) + parser.add_argument( + "--repo", + default=os.environ.get("GITHUB_REPOSITORY", ""), + help="GitHub repo (owner/repo) for commenting; defaults to $GITHUB_REPOSITORY", + ) + parser.add_argument( + "--label", + default="", + help="Human-readable build label for the comment (e.g. 'Build / cuda / x86_64-linux')", + ) + parser.add_argument( + "--run-url", default="", help="Workflow run URL (used in failure comments)" + ) + parser.add_argument( + "--builder", + required=True, + help="Uploader command up to and including `upload` " + '(e.g. "nix run -L github:huggingface/kernels#kernel-builder -- upload")', + ) + args = parser.parse_args() + + builder_cmd = shlex.split(args.builder) + if not builder_cmd: + print("Error: empty --builder command.", file=sys.stderr) + return 2 + + kernel_dir = Path(args.kernel) + repo_id = read_repo_id(kernel_dir) + upload_repo_id, create_pr = resolve_upload_target( + repo_id, args.kernel, args.repo_prefix + ) + + label = args.label or "Build" + if create_pr: + print( + f"Kernel `{args.kernel}` repo-id `{repo_id}` is outside " + f"`{COMMUNITY_ORG}`; uploading via pull request.", + file=sys.stderr, + ) + else: + print( + f"Kernel `{args.kernel}` uploads directly to `{upload_repo_id}`.", + file=sys.stderr, + ) + + returncode, stdout = run_upload( + builder_cmd, + upload_repo_id=upload_repo_id, + upload_path=args.upload_path or None, + branch=args.branch or None, + create_pr=create_pr, + cwd=kernel_dir, + ) + + # Only create-pr uploads report back; direct uploads keep prior behaviour. + if not create_pr: + return returncode + + token = os.environ.get("GITHUB_TOKEN", "") + if not args.comment_pr_number or not args.repo or not token: + if not token: + print( + "No GITHUB_TOKEN available; skipping PR comment.", file=sys.stderr + ) + return returncode + + if returncode == 0: + pr_urls = parse_pr_urls(stdout) + message = format_success_comment( + args.kernel, upload_repo_id, label, pr_urls + ) + else: + message = format_failure_comment( + args.kernel, upload_repo_id, label, args.run_url or None, returncode + ) + + post_pr_comment(args.repo, token, args.comment_pr_number, message) + return returncode + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/.github/scripts/windows/upload_and_report.ps1 b/.github/scripts/windows/upload_and_report.ps1 new file mode 100644 index 000000000..563e1035d --- /dev/null +++ b/.github/scripts/windows/upload_and_report.ps1 @@ -0,0 +1,106 @@ +<# +.SYNOPSIS + Upload a built kernel to the Hub (Windows) and report the outcome to a PR. + +.DESCRIPTION + PowerShell counterpart of .github/scripts/upload_and_report.py. Kernels whose + build.toml repo-id lives outside `kernels-community` are uploaded through a + pull request (--create-pr) to their real repo-id, and the resulting Hub PR + links are posted back on the originating GitHub PR. Direct kernels-community + uploads keep the prior / behaviour and never comment. + + Windows currently only builds kernels-community kernels (dispatch allowlist), + so the create-pr path is here for correctness if that ever changes. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)][string]$KernelBuilder, + [Parameter(Mandatory = $true)][string]$KernelSource, + [string]$RepoPrefix = "kernels-community", + [string]$Branch = "", + [string]$CommentPrNumber = "", + [string]$Repo = $env:GITHUB_REPOSITORY, + [string]$Label = "Build (Windows)", + [string]$RunUrl = "" +) + +$ErrorActionPreference = "Stop" +# Do not let a non-zero uploader exit throw before we can capture $LASTEXITCODE +# and post a failure comment; we handle the exit code explicitly below. +$PSNativeCommandUseErrorActionPreference = $false +$CommunityOrg = "kernels-community" + +# Resolve the upload target from build.toml. External-org kernels upload to +# their real repo-id via a pull request; everything else uploads directly. +$uploadRepoId = "$RepoPrefix/$KernelSource" +$createPr = $false +$buildTomlPath = Join-Path $KernelSource "build.toml" +if (Test-Path $buildTomlPath) { + $match = Select-String -Path $buildTomlPath -Pattern '^\s*repo-id\s*=\s*"([^"]+)"' | + Select-Object -First 1 + if ($match) { + $tomlRepoId = $match.Matches[0].Groups[1].Value + $org = $tomlRepoId.Split('/')[0] + if ($org -ne $CommunityOrg) { + $uploadRepoId = $tomlRepoId + $createPr = $true + } + } +} + +if ($createPr) { + Write-Host "Kernel '$KernelSource' repo-id '$uploadRepoId' is outside '$CommunityOrg'; uploading via pull request." +} else { + Write-Host "Kernel '$KernelSource' uploads directly to '$uploadRepoId'." +} + +$uploadArgs = @("upload", (Join-Path $KernelSource "build"), "--repo-type", "kernel", "--repo-id", $uploadRepoId) +if ($Branch -ne "") { $uploadArgs += @("--branch", $Branch) } +if ($createPr) { $uploadArgs += "--create-pr" } + +Write-Host "+ $KernelBuilder $($uploadArgs -join ' ')" +# Capture combined output so PR links can be parsed, while still echoing it. +$output = & $KernelBuilder @uploadArgs 2>&1 +$exitCode = $LASTEXITCODE +$output | ForEach-Object { Write-Host $_ } + +# Direct uploads keep prior behaviour: propagate the exit code, no comment. +if (-not $createPr) { exit $exitCode } + +if ($CommentPrNumber -eq "" -or $Repo -eq "" -or -not $env:GITHUB_TOKEN) { + if (-not $env:GITHUB_TOKEN) { Write-Host "No GITHUB_TOKEN available; skipping PR comment." } + exit $exitCode +} + +if ($exitCode -eq 0) { + $prUrls = @() + foreach ($line in $output) { + $m = [regex]::Match([string]$line, '^Pull request created:\s*(\S+)\s*$') + if ($m.Success) { $prUrls += $m.Groups[1].Value } + } + if ($prUrls.Count -gt 0) { + $links = ($prUrls | ForEach-Object { "- $_" }) -join "`n" + $message = "### Kernel upload -> pull request opened`n`nKernel ``$KernelSource`` ($Label) targets ``$uploadRepoId``, which is outside ``$CommunityOrg``, so the build was uploaded via pull request:`n`n$links" + } else { + $message = "### Kernel upload`n`nKernel ``$KernelSource`` ($Label) -> ``$uploadRepoId``: upload completed, but no pull request was opened (no changes to upload)." + } +} else { + $details = if ($RunUrl -ne "") { " See the [workflow run]($RunUrl) for details." } else { "" } + $message = "### Kernel upload failed`n`nUploading kernel ``$KernelSource`` ($Label) to ``$uploadRepoId`` via pull request failed (exit code $exitCode).$details" +} + +try { + $headers = @{ + Authorization = "Bearer $env:GITHUB_TOKEN" + Accept = "application/vnd.github+json" + "X-GitHub-Api-Version" = "2022-11-28" + } + $bodyJson = @{ body = $message } | ConvertTo-Json + Invoke-RestMethod -Method Post -ContentType "application/json" ` + -Uri "https://api.github.com/repos/$Repo/issues/$CommentPrNumber/comments" ` + -Headers $headers -Body $bodyJson | Out-Null +} catch { + Write-Host "Failed to post PR comment: $_" +} + +exit $exitCode diff --git a/.github/workflows/build-mac.yaml b/.github/workflows/build-mac.yaml index 2957d1b49..fd8601b08 100644 --- a/.github/workflows/build-mac.yaml +++ b/.github/workflows/build-mac.yaml @@ -52,11 +52,18 @@ on: required: false type: string default: "" + comment_pr_number: + description: "PR to report Hub upload PR links back to (empty = no comment)" + required: false + type: string + default: "" permissions: contents: read statuses: write id-token: write + # Lets the upload step comment Hub create-pr links back on the originating PR. + pull-requests: write concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} @@ -197,37 +204,59 @@ jobs: cosign sign-blob "$metadata_file" --bundle "${metadata_file}.sigstore" --yes done < <(find "$KERNEL/build" -mindepth 2 -maxdepth 2 -name "metadata.json") - # Upload built artifacts to both model and kernel Hub repos. + # Upload built artifacts to the Hub. Kernels whose build.toml repo-id lives + # outside kernels-community are uploaded via a pull request (--create-pr, + # handled inside upload_and_report.py) and the PR links are reported back + # on the originating PR. - name: Upload kernel to Hub if: steps.validate.outputs.skip == 'false' && inputs.skip_build != true && inputs.mode != 'pr' && inputs.upload != false env: HF_TOKEN: ${{ secrets.HF_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} KERNEL: ${{ steps.validate.outputs.kernel }} REPO_PREFIX: ${{ inputs.repo_prefix }} TARGET_BRANCH: ${{ inputs.target_branch }} + COMMENT_PR_NUMBER: ${{ inputs.comment_pr_number }} + BUILD_LABEL: ${{ github.workflow }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} run: | - cd "$KERNEL" - BRANCH_FLAG="" + BRANCH_ARGS=() if [ -n "$TARGET_BRANCH" ]; then - BRANCH_FLAG="--branch $TARGET_BRANCH" + BRANCH_ARGS=(--branch "$TARGET_BRANCH") fi - nix run -L github:huggingface/kernels#kernel-builder -- upload --repo-type kernel --repo-id "$REPO_PREFIX/$KERNEL" $BRANCH_FLAG + python3 .github/scripts/upload_and_report.py \ + --kernel "$KERNEL" \ + --repo-prefix "$REPO_PREFIX" \ + --comment-pr-number "$COMMENT_PR_NUMBER" \ + --label "$BUILD_LABEL" \ + --run-url "$RUN_URL" \ + "${BRANCH_ARGS[@]}" \ + --builder "nix run -L github:huggingface/kernels#kernel-builder -- upload" # v1 kernels without an explicit branch override also get uploaded to main. - name: Upload v1 kernels to main if: steps.validate.outputs.skip == 'false' && inputs.skip_build != true && inputs.mode != 'pr' && inputs.upload != false && inputs.target_branch == '' env: HF_TOKEN: ${{ secrets.HF_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} KERNEL: ${{ steps.validate.outputs.kernel }} REPO_PREFIX: ${{ inputs.repo_prefix }} + COMMENT_PR_NUMBER: ${{ inputs.comment_pr_number }} + BUILD_LABEL: ${{ github.workflow }} / main + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} run: | - cd "$KERNEL" - - if [ -f "build.toml" ]; then - VERSION=$(grep -E '^\s*version\s*=\s*1\s*$' build.toml || true) - BRANCH=$(grep -E '^\s*branch\s*=' build.toml || true) + if [ -f "$KERNEL/build.toml" ]; then + VERSION=$(grep -E '^\s*version\s*=\s*1\s*$' "$KERNEL/build.toml" || true) + BRANCH=$(grep -E '^\s*branch\s*=' "$KERNEL/build.toml" || true) if [ -n "$VERSION" ] && [ -z "$BRANCH" ]; then - nix run -L github:huggingface/kernels#kernel-builder -- upload --repo-type kernel --repo-id "$REPO_PREFIX/$KERNEL" --branch main + python3 .github/scripts/upload_and_report.py \ + --kernel "$KERNEL" \ + --repo-prefix "$REPO_PREFIX" \ + --comment-pr-number "$COMMENT_PR_NUMBER" \ + --label "$BUILD_LABEL" \ + --run-url "$RUN_URL" \ + --branch main \ + --builder "nix run -L github:huggingface/kernels#kernel-builder -- upload" fi fi diff --git a/.github/workflows/build-windows.yaml b/.github/workflows/build-windows.yaml index fe75c55ea..8c4dbac3a 100644 --- a/.github/workflows/build-windows.yaml +++ b/.github/workflows/build-windows.yaml @@ -52,10 +52,17 @@ on: required: false type: string default: "" + comment_pr_number: + description: "PR to report Hub upload PR links back to (empty = no comment)" + required: false + type: string + default: "" permissions: contents: read statuses: write + # Lets the upload step comment Hub create-pr links back on the originating PR. + pull-requests: write concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} @@ -337,25 +344,30 @@ jobs: cmake --build . --config Release --target local_install Pop-Location - # Upload built artifacts to both model and kernel Hub repos. + # Upload built artifacts to the Hub. Kernels whose build.toml repo-id lives + # outside kernels-community are uploaded via a pull request (--create-pr, + # handled inside upload_and_report.ps1) and the PR links reported back. - name: Upload kernel to Hub if: steps.validate.outputs.skip == 'false' && steps.check-backend.outputs.supported == 'true' && inputs.skip_build != true && inputs.mode != 'pr' && inputs.upload != false shell: pwsh env: HF_TOKEN: ${{ secrets.HF_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} KERNEL_SOURCE: ${{ steps.validate.outputs.kernel }} REPO_PREFIX: ${{ inputs.repo_prefix }} TARGET_BRANCH: ${{ inputs.target_branch }} + COMMENT_PR_NUMBER: ${{ inputs.comment_pr_number }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} run: | $KB = "$env:GITHUB_WORKSPACE\kernels\kernel-builder\target\debug\kernel-builder.exe" - - $branchArgs = @() - if ($env:TARGET_BRANCH -ne "") { - $branchArgs = @("--branch", $env:TARGET_BRANCH) - } - - # Upload to both model and kernel repo types - & $KB upload "$env:KERNEL_SOURCE\build" --repo-type kernel --repo-id "$env:REPO_PREFIX/$env:KERNEL_SOURCE" @branchArgs + & "$env:GITHUB_WORKSPACE\.github\scripts\windows\upload_and_report.ps1" ` + -KernelBuilder $KB ` + -KernelSource $env:KERNEL_SOURCE ` + -RepoPrefix $env:REPO_PREFIX ` + -Branch $env:TARGET_BRANCH ` + -CommentPrNumber $env:COMMENT_PR_NUMBER ` + -Label "${{ github.workflow }} / ${{ matrix.platform.backend }}" ` + -RunUrl $env:RUN_URL # v1 kernels without an explicit branch override also get uploaded to main. - name: Upload v1 kernels to main @@ -363,8 +375,11 @@ jobs: shell: pwsh env: HF_TOKEN: ${{ secrets.HF_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} KERNEL_SOURCE: ${{ steps.validate.outputs.kernel }} REPO_PREFIX: ${{ inputs.repo_prefix }} + COMMENT_PR_NUMBER: ${{ inputs.comment_pr_number }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} run: | $KB = "$env:GITHUB_WORKSPACE\kernels\kernel-builder\target\debug\kernel-builder.exe" @@ -374,7 +389,14 @@ jobs: $content = Get-Content $buildTomlPath -Raw if ($content -match '(?m)^\s*version\s*=\s*1\s*(\r)?$' -and $content -notmatch '(?m)^\s*branch\s*=') { Write-Host "Kernel version is 1 and no branch override, uploading to main branch..." - & $KB upload "$env:KERNEL_SOURCE\build" --repo-type kernel --repo-id "$env:REPO_PREFIX/$env:KERNEL_SOURCE" --branch main + & "$env:GITHUB_WORKSPACE\.github\scripts\windows\upload_and_report.ps1" ` + -KernelBuilder $KB ` + -KernelSource $env:KERNEL_SOURCE ` + -RepoPrefix $env:REPO_PREFIX ` + -Branch "main" ` + -CommentPrNumber $env:COMMENT_PR_NUMBER ` + -Label "${{ github.workflow }} / ${{ matrix.platform.backend }} / main" ` + -RunUrl $env:RUN_URL } else { Write-Host "Kernel version is not 1 or branch is overridden, skipping main branch upload" } diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 37561cad2..dc9b8dc8f 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -52,6 +52,11 @@ on: required: false type: string default: "" + comment_pr_number: + description: "PR to report Hub upload PR links back to (empty = no comment)" + required: false + type: string + default: "" permissions: contents: read @@ -190,11 +195,13 @@ jobs: group: ${{ matrix.runner }} # PR builds get 10h; release builds get 20h (more variants to compile). timeout-minutes: ${{ inputs.mode == 'pr' && 600 || 1200 }} - # id-token: write is needed for cosign. + # id-token: write is needed for cosign; pull-requests: write lets the + # upload step comment Hub create-pr links back on the originating PR. permissions: contents: read statuses: write id-token: write + pull-requests: write steps: # When building for a PR, check out the PR head; otherwise use default branch. - name: Checkout PR branch @@ -250,38 +257,60 @@ jobs: cosign sign-blob "$metadata_file" --bundle "${metadata_file}.sigstore" --yes done < <(find "$KERNEL/build" -mindepth 2 -maxdepth 2 -name "metadata.json") - # Upload built artifacts to both model and kernel Hub repos. + # Upload built artifacts to the Hub. Kernels whose build.toml repo-id lives + # outside kernels-community are uploaded via a pull request (--create-pr, + # handled inside upload_and_report.py) and the PR links are reported back + # on the originating PR. - name: Upload kernel to Hub if: inputs.mode != 'pr' && inputs.upload != false env: HF_TOKEN: ${{ secrets.HF_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} KERNEL: ${{ needs.setup.outputs.kernel }} REPO_PREFIX: ${{ inputs.repo_prefix }} TARGET_BRANCH: ${{ inputs.target_branch }} + COMMENT_PR_NUMBER: ${{ inputs.comment_pr_number }} + BUILD_LABEL: ${{ github.workflow }} / ${{ matrix.backend }} / ${{ matrix.arch }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} run: | - cd "$KERNEL" - BRANCH_FLAG="" + BRANCH_ARGS=() if [ -n "$TARGET_BRANCH" ]; then - BRANCH_FLAG="--branch $TARGET_BRANCH" + BRANCH_ARGS=(--branch "$TARGET_BRANCH") fi - nix run -L github:huggingface/kernels#kernel-builder -- upload --repo-type kernel --repo-id "$REPO_PREFIX/$KERNEL" $BRANCH_FLAG + python3 .github/scripts/upload_and_report.py \ + --kernel "$KERNEL" \ + --repo-prefix "$REPO_PREFIX" \ + --comment-pr-number "$COMMENT_PR_NUMBER" \ + --label "$BUILD_LABEL" \ + --run-url "$RUN_URL" \ + "${BRANCH_ARGS[@]}" \ + --builder "nix run -L github:huggingface/kernels#kernel-builder -- upload" # v1 kernels without an explicit branch override also get uploaded to main. - name: Upload v1 kernels to main if: inputs.mode != 'pr' && inputs.upload != false && inputs.target_branch == '' env: HF_TOKEN: ${{ secrets.HF_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} KERNEL: ${{ needs.setup.outputs.kernel }} REPO_PREFIX: ${{ inputs.repo_prefix }} + COMMENT_PR_NUMBER: ${{ inputs.comment_pr_number }} + BUILD_LABEL: ${{ github.workflow }} / ${{ matrix.backend }} / ${{ matrix.arch }} / main + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} run: | - cd "$KERNEL" - # Check if build.toml exists, has version = 1, and does not specify a branch. - if [ -f "build.toml" ]; then - VERSION=$(grep -E '^\s*version\s*=\s*1\s*$' build.toml || true) - BRANCH=$(grep -E '^\s*branch\s*=' build.toml || true) + if [ -f "$KERNEL/build.toml" ]; then + VERSION=$(grep -E '^\s*version\s*=\s*1\s*$' "$KERNEL/build.toml" || true) + BRANCH=$(grep -E '^\s*branch\s*=' "$KERNEL/build.toml" || true) if [ -n "$VERSION" ] && [ -z "$BRANCH" ]; then - nix run -L github:huggingface/kernels#kernel-builder -- upload --repo-type kernel --repo-id "$REPO_PREFIX/$KERNEL" --branch main + python3 .github/scripts/upload_and_report.py \ + --kernel "$KERNEL" \ + --repo-prefix "$REPO_PREFIX" \ + --comment-pr-number "$COMMENT_PR_NUMBER" \ + --label "$BUILD_LABEL" \ + --run-url "$RUN_URL" \ + --branch main \ + --builder "nix run -L github:huggingface/kernels#kernel-builder -- upload" fi fi diff --git a/.github/workflows/sign-old-builds.yaml b/.github/workflows/sign-old-builds.yaml index 4a291833b..e5c1ef67d 100644 --- a/.github/workflows/sign-old-builds.yaml +++ b/.github/workflows/sign-old-builds.yaml @@ -69,8 +69,16 @@ jobs: VERSION=$(grep -E '^\s*version\s*=' "$kernel/build.toml" | grep -oE '[0-9]+') VERSION_BRANCH="v${VERSION}" + # Resolve the Hub repo-id from build.toml. Kernels whose repo-id is + # outside kernels-community live in their own org (e.g. MiniMaxAI/msa), + # so download from and upload to that repo (uploads open a PR). + REPO_ID=$(grep -E '^\s*repo-id\s*=' "$kernel/build.toml" | head -1 | sed -E 's/.*=[[:space:]]*"([^"]+)".*/\1/') + if [ -z "$REPO_ID" ]; then + REPO_ID="$REPO_PREFIX/$kernel" + fi + # Download existing kernel artifacts from the version branch. - ( cd "$kernel" && uvx --with huggingface_hub python3 -c "from huggingface_hub import snapshot_download; snapshot_download('$REPO_PREFIX/$kernel', repo_type='kernel', local_dir='.', revision='$VERSION_BRANCH')" ) + ( cd "$kernel" && uvx --with huggingface_hub python3 -c "from huggingface_hub import snapshot_download; snapshot_download('$REPO_ID', repo_type='kernel', local_dir='.', revision='$VERSION_BRANCH')" ) # Remove build variants that are not suitable for hashing: # - no __init__.py (not a Python kernel build) @@ -101,15 +109,24 @@ jobs: nix run -L github:huggingface/kernels#kernel-builder -- \ fill-card "$kernel" "$kernel"/build/CARD.md - # Upload signed artifacts back to the Hub (kernel repo type). - ( cd "$kernel" && nix run -L github:huggingface/kernels#kernel-builder -- \ - upload --repo-type kernel --repo-id "$REPO_PREFIX/$kernel" --branch "$VERSION_BRANCH" ) + # Upload signed artifacts back to the Hub (kernel repo type). For + # external-org kernels this opens a pull request (--create-pr, + # handled inside upload_and_report.py); there is no PR to comment on + # here, so no --comment-pr-number is passed. + python3 .github/scripts/upload_and_report.py \ + --kernel "$kernel" \ + --repo-prefix "$REPO_PREFIX" \ + --branch "$VERSION_BRANCH" \ + --builder "nix run -L github:huggingface/kernels#kernel-builder -- upload" # v1 kernels without an explicit branch in build.toml also get uploaded to main. BRANCH=$(grep -E '^\s*branch\s*=' "$kernel/build.toml" || true) if [ "$VERSION" = "1" ] && [ -z "$BRANCH" ]; then - ( cd "$kernel" && nix run -L github:huggingface/kernels#kernel-builder -- \ - upload --repo-type kernel --repo-id "$REPO_PREFIX/$kernel" --branch main ) + python3 .github/scripts/upload_and_report.py \ + --kernel "$kernel" \ + --repo-prefix "$REPO_PREFIX" \ + --branch main \ + --builder "nix run -L github:huggingface/kernels#kernel-builder -- upload" fi # Clean up to reclaim disk space before the next kernel. diff --git a/msa/build.toml b/msa/build.toml index 23438a74a..8d74f25f1 100644 --- a/msa/build.toml +++ b/msa/build.toml @@ -10,7 +10,7 @@ upstream = "https://github.com/MiniMax-AI/MSA" version = 0 [general.hub] -repo-id = "kernels-community/msa" +repo-id = "MiniMaxAI/msa" [general.cuda] minver = "12.8" diff --git a/sgl-flash-attn3/build.toml b/sgl-flash-attn3/build.toml index 353c699fc..624adf64a 100644 --- a/sgl-flash-attn3/build.toml +++ b/sgl-flash-attn3/build.toml @@ -8,7 +8,7 @@ backends = ["cuda"] minver = "12.8" [general.hub] -repo-id = "kernels-community/sgl-flash-attn3" +repo-id = "sgl-project/sgl-flash-attn3" [torch] src = [ From 18dd02195e5fbe104e087de157e866b2b5ccc150 Mon Sep 17 00:00:00 2001 From: sayakpaul Date: Fri, 10 Jul 2026 09:10:36 +0530 Subject: [PATCH 2/2] up --- .github/scripts/windows/upload_and_report.ps1 | 106 ------------------ .github/workflows/build-windows.yaml | 45 +++----- 2 files changed, 17 insertions(+), 134 deletions(-) delete mode 100644 .github/scripts/windows/upload_and_report.ps1 diff --git a/.github/scripts/windows/upload_and_report.ps1 b/.github/scripts/windows/upload_and_report.ps1 deleted file mode 100644 index 563e1035d..000000000 --- a/.github/scripts/windows/upload_and_report.ps1 +++ /dev/null @@ -1,106 +0,0 @@ -<# -.SYNOPSIS - Upload a built kernel to the Hub (Windows) and report the outcome to a PR. - -.DESCRIPTION - PowerShell counterpart of .github/scripts/upload_and_report.py. Kernels whose - build.toml repo-id lives outside `kernels-community` are uploaded through a - pull request (--create-pr) to their real repo-id, and the resulting Hub PR - links are posted back on the originating GitHub PR. Direct kernels-community - uploads keep the prior / behaviour and never comment. - - Windows currently only builds kernels-community kernels (dispatch allowlist), - so the create-pr path is here for correctness if that ever changes. -#> -[CmdletBinding()] -param( - [Parameter(Mandatory = $true)][string]$KernelBuilder, - [Parameter(Mandatory = $true)][string]$KernelSource, - [string]$RepoPrefix = "kernels-community", - [string]$Branch = "", - [string]$CommentPrNumber = "", - [string]$Repo = $env:GITHUB_REPOSITORY, - [string]$Label = "Build (Windows)", - [string]$RunUrl = "" -) - -$ErrorActionPreference = "Stop" -# Do not let a non-zero uploader exit throw before we can capture $LASTEXITCODE -# and post a failure comment; we handle the exit code explicitly below. -$PSNativeCommandUseErrorActionPreference = $false -$CommunityOrg = "kernels-community" - -# Resolve the upload target from build.toml. External-org kernels upload to -# their real repo-id via a pull request; everything else uploads directly. -$uploadRepoId = "$RepoPrefix/$KernelSource" -$createPr = $false -$buildTomlPath = Join-Path $KernelSource "build.toml" -if (Test-Path $buildTomlPath) { - $match = Select-String -Path $buildTomlPath -Pattern '^\s*repo-id\s*=\s*"([^"]+)"' | - Select-Object -First 1 - if ($match) { - $tomlRepoId = $match.Matches[0].Groups[1].Value - $org = $tomlRepoId.Split('/')[0] - if ($org -ne $CommunityOrg) { - $uploadRepoId = $tomlRepoId - $createPr = $true - } - } -} - -if ($createPr) { - Write-Host "Kernel '$KernelSource' repo-id '$uploadRepoId' is outside '$CommunityOrg'; uploading via pull request." -} else { - Write-Host "Kernel '$KernelSource' uploads directly to '$uploadRepoId'." -} - -$uploadArgs = @("upload", (Join-Path $KernelSource "build"), "--repo-type", "kernel", "--repo-id", $uploadRepoId) -if ($Branch -ne "") { $uploadArgs += @("--branch", $Branch) } -if ($createPr) { $uploadArgs += "--create-pr" } - -Write-Host "+ $KernelBuilder $($uploadArgs -join ' ')" -# Capture combined output so PR links can be parsed, while still echoing it. -$output = & $KernelBuilder @uploadArgs 2>&1 -$exitCode = $LASTEXITCODE -$output | ForEach-Object { Write-Host $_ } - -# Direct uploads keep prior behaviour: propagate the exit code, no comment. -if (-not $createPr) { exit $exitCode } - -if ($CommentPrNumber -eq "" -or $Repo -eq "" -or -not $env:GITHUB_TOKEN) { - if (-not $env:GITHUB_TOKEN) { Write-Host "No GITHUB_TOKEN available; skipping PR comment." } - exit $exitCode -} - -if ($exitCode -eq 0) { - $prUrls = @() - foreach ($line in $output) { - $m = [regex]::Match([string]$line, '^Pull request created:\s*(\S+)\s*$') - if ($m.Success) { $prUrls += $m.Groups[1].Value } - } - if ($prUrls.Count -gt 0) { - $links = ($prUrls | ForEach-Object { "- $_" }) -join "`n" - $message = "### Kernel upload -> pull request opened`n`nKernel ``$KernelSource`` ($Label) targets ``$uploadRepoId``, which is outside ``$CommunityOrg``, so the build was uploaded via pull request:`n`n$links" - } else { - $message = "### Kernel upload`n`nKernel ``$KernelSource`` ($Label) -> ``$uploadRepoId``: upload completed, but no pull request was opened (no changes to upload)." - } -} else { - $details = if ($RunUrl -ne "") { " See the [workflow run]($RunUrl) for details." } else { "" } - $message = "### Kernel upload failed`n`nUploading kernel ``$KernelSource`` ($Label) to ``$uploadRepoId`` via pull request failed (exit code $exitCode).$details" -} - -try { - $headers = @{ - Authorization = "Bearer $env:GITHUB_TOKEN" - Accept = "application/vnd.github+json" - "X-GitHub-Api-Version" = "2022-11-28" - } - $bodyJson = @{ body = $message } | ConvertTo-Json - Invoke-RestMethod -Method Post -ContentType "application/json" ` - -Uri "https://api.github.com/repos/$Repo/issues/$CommentPrNumber/comments" ` - -Headers $headers -Body $bodyJson | Out-Null -} catch { - Write-Host "Failed to post PR comment: $_" -} - -exit $exitCode diff --git a/.github/workflows/build-windows.yaml b/.github/workflows/build-windows.yaml index 8c4dbac3a..53355624f 100644 --- a/.github/workflows/build-windows.yaml +++ b/.github/workflows/build-windows.yaml @@ -52,8 +52,12 @@ on: required: false type: string default: "" + # Accepted but unused: Windows only builds kernels-community kernels + # (dispatch allowlist), which upload directly and never open a pull + # request, so there is nothing to report back. Declared so dispatches that + # always pass this input (see dispatch.py) are not rejected with HTTP 422. comment_pr_number: - description: "PR to report Hub upload PR links back to (empty = no comment)" + description: "Unused on Windows (kept for dispatch input compatibility)" required: false type: string default: "" @@ -61,8 +65,6 @@ on: permissions: contents: read statuses: write - # Lets the upload step comment Hub create-pr links back on the originating PR. - pull-requests: write concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} @@ -344,30 +346,27 @@ jobs: cmake --build . --config Release --target local_install Pop-Location - # Upload built artifacts to the Hub. Kernels whose build.toml repo-id lives - # outside kernels-community are uploaded via a pull request (--create-pr, - # handled inside upload_and_report.ps1) and the PR links reported back. + # Upload built artifacts to both model and kernel Hub repos. Windows only + # builds kernels-community kernels, so uploads always go directly (no + # --create-pr); external-org kernels are handled on the linux/mac builds. - name: Upload kernel to Hub if: steps.validate.outputs.skip == 'false' && steps.check-backend.outputs.supported == 'true' && inputs.skip_build != true && inputs.mode != 'pr' && inputs.upload != false shell: pwsh env: HF_TOKEN: ${{ secrets.HF_TOKEN }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} KERNEL_SOURCE: ${{ steps.validate.outputs.kernel }} REPO_PREFIX: ${{ inputs.repo_prefix }} TARGET_BRANCH: ${{ inputs.target_branch }} - COMMENT_PR_NUMBER: ${{ inputs.comment_pr_number }} - RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} run: | $KB = "$env:GITHUB_WORKSPACE\kernels\kernel-builder\target\debug\kernel-builder.exe" - & "$env:GITHUB_WORKSPACE\.github\scripts\windows\upload_and_report.ps1" ` - -KernelBuilder $KB ` - -KernelSource $env:KERNEL_SOURCE ` - -RepoPrefix $env:REPO_PREFIX ` - -Branch $env:TARGET_BRANCH ` - -CommentPrNumber $env:COMMENT_PR_NUMBER ` - -Label "${{ github.workflow }} / ${{ matrix.platform.backend }}" ` - -RunUrl $env:RUN_URL + + $branchArgs = @() + if ($env:TARGET_BRANCH -ne "") { + $branchArgs = @("--branch", $env:TARGET_BRANCH) + } + + # Upload to both model and kernel repo types + & $KB upload "$env:KERNEL_SOURCE\build" --repo-type kernel --repo-id "$env:REPO_PREFIX/$env:KERNEL_SOURCE" @branchArgs # v1 kernels without an explicit branch override also get uploaded to main. - name: Upload v1 kernels to main @@ -375,11 +374,8 @@ jobs: shell: pwsh env: HF_TOKEN: ${{ secrets.HF_TOKEN }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} KERNEL_SOURCE: ${{ steps.validate.outputs.kernel }} REPO_PREFIX: ${{ inputs.repo_prefix }} - COMMENT_PR_NUMBER: ${{ inputs.comment_pr_number }} - RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} run: | $KB = "$env:GITHUB_WORKSPACE\kernels\kernel-builder\target\debug\kernel-builder.exe" @@ -389,14 +385,7 @@ jobs: $content = Get-Content $buildTomlPath -Raw if ($content -match '(?m)^\s*version\s*=\s*1\s*(\r)?$' -and $content -notmatch '(?m)^\s*branch\s*=') { Write-Host "Kernel version is 1 and no branch override, uploading to main branch..." - & "$env:GITHUB_WORKSPACE\.github\scripts\windows\upload_and_report.ps1" ` - -KernelBuilder $KB ` - -KernelSource $env:KERNEL_SOURCE ` - -RepoPrefix $env:REPO_PREFIX ` - -Branch "main" ` - -CommentPrNumber $env:COMMENT_PR_NUMBER ` - -Label "${{ github.workflow }} / ${{ matrix.platform.backend }} / main" ` - -RunUrl $env:RUN_URL + & $KB upload "$env:KERNEL_SOURCE\build" --repo-type kernel --repo-id "$env:REPO_PREFIX/$env:KERNEL_SOURCE" --branch main } else { Write-Host "Kernel version is not 1 or branch is overridden, skipping main branch upload" }