Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 66 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@ on:
pull_request:
branches: [main]

permissions:
contents: read

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"

jobs:
build-webgpu-bridge:
name: Build WebGPU Bridge (WASM)
runs-on: ubuntu-latest
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
LLAMA_WEBGPU_SMOKE_MODEL_URL: https://huggingface.co/aladar/llama-2-tiny-random-GGUF/resolve/main/llama-2-tiny-random.gguf
LLAMA_WEBGPU_SMOKE_MODEL_SHA256: 81f226c62d28ed4a1a9b9fa080fcd9f0cc40e0f9d5680036583ff98fbcd035cb
LLAMA_WEBGPU_SMOKE_MODEL_CACHE: ~/.cache/llama-web-bridge/state-smoke-models
Expand Down Expand Up @@ -112,3 +117,63 @@ jobs:
${{ runner.temp }}/webgpu_bridge_dist/llama_webgpu_core.wasm
${{ runner.temp }}/webgpu_bridge_dist/llama_webgpu_core_mem64.js
${{ runner.temp }}/webgpu_bridge_dist/llama_webgpu_core_mem64.wasm

dispatch-publish-assets:
name: Dispatch asset publish
needs: build-webgpu-bridge
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
actions: write
contents: read
env:
ASSETS_REPO: leehack/llama-web-bridge-assets
VERSION_FILE: llama_cpp.version
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Dispatch publish when llama.cpp pin changed
env:
GH_TOKEN: ${{ github.token }}
BEFORE_SHA: ${{ github.event.before }}
run: |
set -euo pipefail

if [ -z "${BEFORE_SHA}" ] || [[ "${BEFORE_SHA}" =~ ^0+$ ]]; then
echo "No comparable before SHA for ${GITHUB_SHA}; skipping automatic publish dispatch."
exit 0
fi

if git diff --quiet "${BEFORE_SHA}" "${GITHUB_SHA}" -- "${VERSION_FILE}"; then
echo "${VERSION_FILE} did not change; skipping automatic publish dispatch."
exit 0
fi

changed_files="$(git diff --name-only "${BEFORE_SHA}" "${GITHUB_SHA}" -- "${VERSION_FILE}")"
echo "Changed files in main push:"
echo "${changed_files}"

LLAMA_CPP_TAG="$(tr -d '[:space:]' < "${VERSION_FILE}")"
if [ -z "${LLAMA_CPP_TAG}" ]; then
echo "error: ${VERSION_FILE} is empty"
exit 1
fi

gh workflow run publish_assets.yml \
--repo "${GITHUB_REPOSITORY}" \
--ref main \
-f assets_tag=auto \
-f assets_repo="${ASSETS_REPO}" \
-f source_ref="${GITHUB_SHA}"

echo "Dispatched publish_assets.yml for the next assets tag from source ${GITHUB_SHA} using llama.cpp ${LLAMA_CPP_TAG}."
{
echo "### Asset publish dispatched"
echo
echo "- Assets repo: \`${ASSETS_REPO}\`"
echo "- Assets tag: next patch tag resolved by \`publish_assets.yml\`"
echo "- llama.cpp tag: \`${LLAMA_CPP_TAG}\`"
echo "- Source commit: \`${GITHUB_SHA}\`"
} >> "${GITHUB_STEP_SUMMARY}"
70 changes: 63 additions & 7 deletions .github/workflows/publish_assets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
workflow_dispatch:
inputs:
assets_tag:
description: Tag to publish to assets repo (for example v0.1.1)
description: Tag to publish to assets repo (for example v0.1.1), or auto for the next patch tag
required: true
assets_repo:
description: Asset repository in owner/repo format
Expand All @@ -14,6 +14,10 @@ on:
description: Optional llama.cpp tag override; defaults to llama_cpp.version
required: false
default: ''
source_ref:
description: Optional llama-web-bridge source ref/SHA to build; defaults to the workflow ref
required: false
default: ''
push:
tags:
- 'v*'
Expand All @@ -23,18 +27,27 @@ env:
ASSETS_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.assets_tag || github.ref_name }}
ASSETS_REPO: ${{ github.event_name == 'workflow_dispatch' && inputs.assets_repo || 'leehack/llama-web-bridge-assets' }}
REQUESTED_LLAMA_CPP_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.llama_cpp_tag || '' }}
REQUESTED_SOURCE_REF: ${{ github.event_name == 'workflow_dispatch' && inputs.source_ref || github.sha }}

permissions:
contents: read

concurrency:
group: publish-bridge-assets
cancel-in-progress: false

jobs:
build-bridge-assets:
name: Build bridge assets
runs-on: ubuntu-latest
outputs:
llama_cpp_tag: ${{ steps.resolve-publish-parameters.outputs.llama_cpp_tag }}
assets_tag: ${{ steps.resolve-publish-parameters.outputs.assets_tag }}
source_commit: ${{ steps.resolve-publish-parameters.outputs.source_commit }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ env.REQUESTED_SOURCE_REF }}

- name: Setup Node.js
uses: actions/setup-node@v4
Expand All @@ -53,7 +66,43 @@ jobs:

- name: Resolve publish parameters
id: resolve-publish-parameters
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail

SOURCE_COMMIT="$(git rev-parse HEAD)"

if [ "${ASSETS_TAG}" = "auto" ]; then
if [[ ! "${REQUESTED_SOURCE_REF}" =~ ^[0-9a-f]{40}$ ]]; then
echo "error: assets_tag=auto requires source_ref to be a full source commit SHA: ${REQUESTED_SOURCE_REF}"
exit 1
fi
if [ "${SOURCE_COMMIT}" != "${REQUESTED_SOURCE_REF}" ]; then
echo "error: checked-out source commit ${SOURCE_COMMIT} does not match requested source_ref ${REQUESTED_SOURCE_REF}"
exit 1
fi
fi

if [ "${ASSETS_TAG}" = "auto" ]; then
LATEST_ASSETS_TAG="$(gh release view --repo "${ASSETS_REPO}" --json tagName --jq '.tagName // ""')"
if [[ ! "${LATEST_ASSETS_TAG}" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
echo "error: latest assets release tag is not a vMAJOR.MINOR.PATCH tag: ${LATEST_ASSETS_TAG}"
exit 1
fi
MAJOR="${BASH_REMATCH[1]}"
MINOR="${BASH_REMATCH[2]}"
PATCH="${BASH_REMATCH[3]}"
RESOLVED_ASSETS_TAG="v${MAJOR}.${MINOR}.$((PATCH + 1))"
else
RESOLVED_ASSETS_TAG="${ASSETS_TAG}"
fi

if [[ ! "${RESOLVED_ASSETS_TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "error: assets tag must be a vMAJOR.MINOR.PATCH tag or auto: ${RESOLVED_ASSETS_TAG}"
exit 1
fi

if [ -n "$REQUESTED_LLAMA_CPP_TAG" ]; then
LLAMA_CPP_TAG="$REQUESTED_LLAMA_CPP_TAG"
else
Expand All @@ -63,12 +112,20 @@ jobs:
echo "error: llama.cpp tag is empty"
exit 1
fi
if [[ ! "$LLAMA_CPP_TAG" =~ ^b[0-9]+$ ]]; then
echo "error: llama.cpp tag must match b[0-9]+: ${LLAMA_CPP_TAG}"
exit 1
fi
echo "ASSETS_TAG=$RESOLVED_ASSETS_TAG" >> "$GITHUB_ENV"
echo "LLAMA_CPP_TAG=$LLAMA_CPP_TAG" >> "$GITHUB_ENV"
echo "assets_tag=$RESOLVED_ASSETS_TAG" >> "$GITHUB_OUTPUT"
echo "llama_cpp_tag=$LLAMA_CPP_TAG" >> "$GITHUB_OUTPUT"
echo "source_commit=$SOURCE_COMMIT" >> "$GITHUB_OUTPUT"
echo "event=${{ github.event_name }}"
echo "assets_tag=${ASSETS_TAG}"
echo "assets_tag=${RESOLVED_ASSETS_TAG}"
echo "assets_repo=${ASSETS_REPO}"
echo "llama_cpp_tag=${LLAMA_CPP_TAG}"
echo "source_commit=${SOURCE_COMMIT}"

- name: Clone llama.cpp source
run: |
Expand All @@ -88,9 +145,8 @@ jobs:
- name: Generate manifest and checksums
env:
OUT_DIR: ${{ runner.temp }}/webgpu_bridge_dist
ASSETS_TAG: ${{ env.ASSETS_TAG }}
SOURCE_REPO: ${{ github.repository }}
SOURCE_COMMIT: ${{ github.sha }}
SOURCE_COMMIT: ${{ steps.resolve-publish-parameters.outputs.source_commit }}
run: |
test -f "$OUT_DIR/llama_webgpu_bridge.js"
test -f "$OUT_DIR/llama_webgpu_bridge_worker.js"
Expand Down Expand Up @@ -166,6 +222,8 @@ jobs:
name: Publish to assets repository
needs: build-bridge-assets
runs-on: ubuntu-latest
env:
ASSETS_TAG: ${{ needs.build-bridge-assets.outputs.assets_tag }}
steps:
- name: Validate assets PAT secret
env:
Expand All @@ -190,8 +248,6 @@ jobs:
path: bridge-dist

- name: Publish assets and tag
env:
ASSETS_TAG: ${{ env.ASSETS_TAG }}
run: |
if git -C assets-repo ls-remote --exit-code --tags origin "refs/tags/$ASSETS_TAG" >/dev/null 2>&1; then
echo "error: tag already exists in assets repo: $ASSETS_TAG"
Expand Down Expand Up @@ -224,7 +280,7 @@ jobs:
ASSETS_REPO: ${{ env.ASSETS_REPO }}
LLAMA_CPP_TAG: ${{ needs.build-bridge-assets.outputs.llama_cpp_tag }}
SOURCE_REPO: ${{ github.repository }}
SOURCE_COMMIT: ${{ github.sha }}
SOURCE_COMMIT: ${{ needs.build-bridge-assets.outputs.source_commit }}
run: |
NOTES="$(cat <<EOF
Bridge assets published from ${SOURCE_REPO}@${SOURCE_COMMIT} (llama.cpp ${LLAMA_CPP_TAG}).
Expand Down
9 changes: 9 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ python3 scripts/state_persistence_browser_smoke.py \

- CI build gate: `.github/workflows/ci.yml`
- Resolves the default llama.cpp checkout from `llama_cpp.version`.
- After a successful `push` run on `main`, dispatches the publish workflow only
when the pushed commit range changed `llama_cpp.version`. The dispatch uses
job-scoped `actions: write`, passes the validated source SHA, and lets the
serialized publish workflow resolve the next patch assets tag; PR CI never
publishes assets.
- Automated llama.cpp bump PR: `.github/workflows/auto_llama_cpp_update.yml`
- Runs on a schedule/manual dispatch, compares `llama_cpp.version` against the
latest `ggml-org/llama.cpp` release, and manages one stable
Expand Down Expand Up @@ -118,6 +123,10 @@ python3 scripts/state_persistence_browser_smoke.py \
- Passes the resolved `llama.cpp` tag as a job output so asset release notes
match the generated manifest.
- Requires `WEBGPU_BRIDGE_ASSETS_PAT`
- Serializes publishes with workflow concurrency so manual and CI-dispatched
asset releases cannot race.
- Supports `assets_tag=auto` plus `source_ref=<sha>` for CI-dispatched
publishes from the exact source commit that already passed `main` CI.
- Pushes assets + tag to `llama-web-bridge-assets`

## Change Boundaries
Expand Down
16 changes: 16 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ query strings, and fragments before printing the location.
- Preserve `llama_cpp.version` as the single source of truth for default CI and
publish builds. Manual publish overrides are allowed for temporary validation,
but tag-triggered publishes should use the pinned file.
- Main-branch CI automatically dispatches `publish_assets.yml` after a successful
build/smoke only when the pushed commit range changed `llama_cpp.version`. The
dispatch passes the validated source SHA and lets the serialized publish
workflow compute the next patch tag from `llama-web-bridge-assets`; PR CI must
never publish assets.
- The auto-update workflow manages the stable `automation/bump-llama-cpp` branch
and updates an existing PR instead of opening duplicates. It should include the
upstream release notes, compare link, and commit range in the PR body, then
Expand All @@ -109,6 +114,17 @@ query strings, and fragments before printing the location.

Use workflow `.github/workflows/publish_assets.yml`:

Automatic publish from CI:

1. Merge a PR that changes `llama_cpp.version`.
2. Let the `main` CI build and browser smoke pass.
3. The final CI job dispatches `publish_assets.yml` with `assets_tag=auto` and
`source_ref` set to the validated main commit. The serialized publish workflow
computes the next patch assets tag and leaves `llama_cpp_tag` empty so the
publish reads the merged pin.

Manual publish:

1. Set input `assets_tag` (new tag).
2. Optionally set `assets_repo`; leave `llama_cpp_tag` empty to use
`llama_cpp.version`, or set it only for an explicit temporary override.
Expand Down
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,11 @@ Publish workflow:

Trigger modes:

- Automatic: push a `v*` tag in this repo (for example `v0.1.5`)
- Automatic after a llama.cpp pin merge: when `main` CI succeeds for a push that
changed `llama_cpp.version`, CI dispatches `publish_assets.yml` with
`assets_tag=auto` and the validated source SHA. The serialized publish workflow
resolves the next patch tag from `leehack/llama-web-bridge-assets`.
- Automatic tag publish: push a `v*` tag in this repo (for example `v0.1.5`)
- Manual: run workflow dispatch with explicit inputs

Required repository secret:
Expand All @@ -213,7 +217,16 @@ The publish workflow carries the resolved `llama.cpp` tag from the build job to
the release job as an explicit job output, so the asset release notes match the
`manifest.json` `llama_cpp_tag` value.

Example publish:
Automatic llama.cpp pin publish:

1. Merge a PR that changes `llama_cpp.version`.
2. `CI` builds and browser-smokes the merged `main` commit.
3. If CI succeeds, the final CI job dispatches `Publish Bridge Assets` with the
validated source SHA, `assets_tag=auto`, and no `llama_cpp_tag` override. The
publish workflow resolves the next patch tag and the manifest uses the merged
pin.

Tag publish example:

1. Create/push a release tag in this repo (for example `v0.1.5`)
2. `Publish Bridge Assets` runs automatically and publishes the same tag to
Expand Down
47 changes: 46 additions & 1 deletion scripts/verify_ci_reliability.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,15 +198,60 @@ def main() -> int:
"ci.yml must resolve the llama.cpp tag from llama_cpp.version, support explicit dispatch, and avoid hard-coded stale defaults",
errors,
)
require(
"dispatch-publish-assets:" in ci
and "needs: build-webgpu-bridge" in ci
and "if: github.event_name == 'push' && github.ref == 'refs/heads/main'" in ci
and "actions: write" in ci
and "fetch-depth: 0" in ci
and "git diff --quiet \"${BEFORE_SHA}\" \"${GITHUB_SHA}\" -- \"${VERSION_FILE}\"" in ci
and "gh workflow run publish_assets.yml" in ci
and "-f assets_tag=auto" in ci
and "-f assets_repo=\"${ASSETS_REPO}\"" in ci
and "-f source_ref=\"${GITHUB_SHA}\"" in ci,
"ci.yml must dispatch asset publishing only after successful main pushes that changed llama_cpp.version, with actions:write scoped to the dispatch job and auto tag resolution delegated to publish_assets.yml",
errors,
)
require(
"REQUESTED_LLAMA_CPP_TAG" in publish
and "source_ref:" in publish
and "REQUESTED_SOURCE_REF" in publish
and "ref: ${{ env.REQUESTED_SOURCE_REF }}" in publish
and "tr -d '[:space:]' < llama_cpp.version" in publish
and "outputs:" in publish
and "llama_cpp_tag: ${{ steps.resolve-publish-parameters.outputs.llama_cpp_tag }}" in publish
and "assets_tag: ${{ steps.resolve-publish-parameters.outputs.assets_tag }}" in publish
and "source_commit: ${{ steps.resolve-publish-parameters.outputs.source_commit }}" in publish
and "LLAMA_CPP_TAG: ${{ needs.build-bridge-assets.outputs.llama_cpp_tag }}" in publish
and "SOURCE_COMMIT: ${{ needs.build-bridge-assets.outputs.source_commit }}" in publish
and "llama.cpp tag must match b[0-9]+" in publish
and "default: b9116" not in publish
and "|| 'b9116'" not in publish,
"publish_assets.yml must default to llama_cpp.version, pass the resolved tag across jobs, and still allow a manual override",
"publish_assets.yml must default to llama_cpp.version, support an explicit source ref, pass resolved tags/commit across jobs, and still allow a manual override",
errors,
)
require(
"if [ \"${ASSETS_TAG}\" = \"auto\" ]; then" in publish
and "assets_tag=auto requires source_ref to be a full source commit SHA" in publish
and "checked-out source commit ${SOURCE_COMMIT} does not match requested source_ref" in publish
and "gh release view --repo \"${ASSETS_REPO}\" --json tagName" in publish
and "RESOLVED_ASSETS_TAG=\"v${MAJOR}.${MINOR}.$((PATCH + 1))\"" in publish
and "assets tag must be a vMAJOR.MINOR.PATCH tag or auto" in publish,
"publish_assets.yml must resolve automatic next patch asset tags inside the serialized publish workflow",
errors,
)
require(
"-f source_ref=\"${GITHUB_SHA}\"" in ci
and "SOURCE_COMMIT=\"$(git rev-parse HEAD)\"" in publish
and "OUT_DIR: ${{ runner.temp }}/webgpu_bridge_dist\n ASSETS_TAG: ${{ env.ASSETS_TAG }}" not in publish,
"CI-dispatched publishes must build the exact validated source SHA and manifest generation must inherit the runtime-resolved assets tag",
errors,
)
require(
"concurrency:" in publish
and "group: publish-bridge-assets" in publish
and "cancel-in-progress: false" in publish,
"publish_assets.yml must serialize asset publishes so automatic and manual releases cannot race",
errors,
)
require(
Expand Down
Loading