Skip to content
Merged
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
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ jobs:
name: rustfmt
runs-on: macos-latest
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
with:
components: rustfmt
- run: cargo fmt --all -- --check
Expand All @@ -29,15 +29,15 @@ jobs:
name: build + clippy
runs-on: macos-14 # Apple Silicon
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
with:
components: clippy
- name: Install MLX (provides mlx-c)
run: brew install mlx-c
- name: Resolve MLX_C_PREFIX
run: echo "MLX_C_PREFIX=$(brew --prefix mlx-c)" >> "$GITHUB_ENV"
- uses: Swatinem/rust-cache@v2
- uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2
- name: clippy
run: cargo clippy --workspace --all-targets --all-features -- -D warnings
- name: build
Expand Down
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ PROF_GEN ?= 500
AUDIT_IGNORES := --ignore RUSTSEC-2024-0436 --ignore RUSTSEC-2025-0119

.PHONY: help build check test fmt fmt-check lint audit deny precommit hooks \
ci ci-metrics tag release-package release-sha tap-sync \
ci ci-metrics tag release-package release-sha release-sign tap-sync \
clean serve chat info logs-tail metrics-summary \
metrics-init metrics-doctor metrics-doctor-fix metrics-export \
metrics-backup metrics-replay-pending metrics-prompts-sync \
Expand Down Expand Up @@ -178,6 +178,9 @@ release-package: ## build + bundle dist/rmlx-v<ver>-aarch64-apple-darwin.tar.gz
release-sha: ## print sha256 of the v<ver> GitHub source tarball (append --write to patch the formula)
bash scripts/release/source_sha256.sh

release-sign: ## keyless cosign-sign dist/rmlx-v<ver>-...tar.gz -> .cosign.bundle (needs cosign + browser OIDC)
bash scripts/release/sign_artifact.sh

tap-sync: ## copy packaging/homebrew/rmlx.rb into the homebrew-rmlx tap and push
bash scripts/release/sync_tap.sh

Expand Down
2 changes: 0 additions & 2 deletions deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ yanked = "deny"
ignore = [
# `paste` archived. Transitive via `tokenizers`.
"RUSTSEC-2024-0436",
# `number_prefix` unmaintained. Transitive via `indicatif` -> `tokenizers`.
"RUSTSEC-2025-0119",
]

# ---- licenses -----------------------------------------------------------
Expand Down
27 changes: 25 additions & 2 deletions docs/RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,19 @@ crates are `publish = false`). There is no separate `VERSION` file.
dist/rmlx-v<version>-aarch64-apple-darwin.tar.gz \
dist/rmlx-v<version>-aarch64-apple-darwin.tar.gz.sha256
```
7. **Formula url + sha256:** bump the `url` line in
7. **Sign the artifact (keyless cosign):** `make release-sign` →
`dist/rmlx-v<version>-aarch64-apple-darwin.tar.gz.cosign.bundle` (needs
`brew install cosign`; opens a browser OIDC prompt). Upload it:
```sh
gh release upload v<version> \
dist/rmlx-v<version>-aarch64-apple-darwin.tar.gz.cosign.bundle
```
The release binary is built locally (hosted CI has no Metal), so the
`.sha256` alone is self-attested. The cosign bundle binds the tarball to
your authenticated identity + the public Rekor log — real provenance for
the prebuilt binary. Consumer-side verification is in "Verify both install
paths".
8. **Formula url + sha256:** bump the `url` line in
`packaging/homebrew/rmlx.rb` to the new `v<version>` tag tarball, **then**
`make release-sha` (or `bash scripts/release/source_sha256.sh --write`) for
the sha256.
Expand All @@ -47,7 +59,7 @@ crates are `publish = false`). There is no separate `VERSION` file.
> sha against the old tag's url and `brew install` fails with a sha
> mismatch. Always edit the `url` line yourself.
Commit the formula bump via a PR (`main` is ruleset-protected; see below).
8. **Publish the tap:** `make tap-sync` (copies the formula into
9. **Publish the tap:** `make tap-sync` (copies the formula into
`Pushkinist/homebrew-rmlx` as `Formula/rmlx.rb` and pushes).

## Dependency-bump PRs (Dependabot)
Expand Down Expand Up @@ -84,6 +96,17 @@ tar xzf rmlx-v<version>-aarch64-apple-darwin.tar.gz
./rmlx-v<version>-aarch64-apple-darwin/rmlx --version
```

**Provenance (cosign bundle, if the release ships one):**
```sh
gh release download v<version> -p '*.cosign.bundle'
cosign verify-blob \
--bundle rmlx-v<version>-aarch64-apple-darwin.tar.gz.cosign.bundle \
--certificate-identity <maintainer-oidc-email> \
--certificate-oidc-issuer <issuer-url> \
rmlx-v<version>-aarch64-apple-darwin.tar.gz
# issuer: GitHub https://github.com/login/oauth · Google https://accounts.google.com
```

**Homebrew (build from source):**
```sh
brew tap Pushkinist/rmlx
Expand Down
50 changes: 50 additions & 0 deletions scripts/release/sign_artifact.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
# sign_artifact.sh — keyless (sigstore) signature for the release tarball.
#
# Produces, alongside dist/rmlx-v<ver>-aarch64-apple-darwin.tar.gz:
# <tarball>.cosign.bundle self-contained cert + signature + Rekor proof
#
# Keyless signing: cosign opens a browser for an OIDC login (GitHub / Google),
# obtains a short-lived Fulcio certificate bound to that identity, signs the
# tarball, and records the signature in the public Rekor transparency log. There
# is no private key to store or leak. Upload the .cosign.bundle as a release
# asset; consumers verify with the command this script prints (also documented
# in docs/RELEASING.md).
#
# The release binary is built locally (hosted CI has no Metal — see RELEASING),
# so this is the provenance signal the prebuilt tarball would otherwise lack:
# the bundle binds the artifact to the maintainer's authenticated identity.
set -euo pipefail

REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
cd "$REPO_ROOT"

command -v cosign >/dev/null 2>&1 || {
echo "error: cosign not found. Install it first: brew install cosign" >&2
exit 1
}

VER=$(awk -F'"' '/^version = /{print $2; exit}' Cargo.toml)
[ -n "$VER" ] || { echo "error: could not read version from Cargo.toml" >&2; exit 1; }

TARBALL="dist/rmlx-v${VER}-aarch64-apple-darwin.tar.gz"
[ -f "$TARBALL" ] || {
echo "error: $TARBALL not found — run 'make release-package' first" >&2
exit 1
}

BUNDLE="${TARBALL}.cosign.bundle"
echo "==> keyless-signing ${TARBALL} (a browser OIDC prompt will open)"
cosign sign-blob --yes --bundle "$BUNDLE" "$TARBALL"
echo "==> wrote ${BUNDLE}"
echo
echo "Upload it to the release:"
echo " gh release upload v${VER} ${BUNDLE}"
echo
echo "Verify (substitute the identity you authenticated as):"
echo " cosign verify-blob \\"
echo " --bundle ${BUNDLE} \\"
echo " --certificate-identity <your-oidc-email> \\"
echo " --certificate-oidc-issuer <issuer-url> \\"
echo " ${TARBALL}"
echo " (GitHub issuer: https://github.com/login/oauth · Google: https://accounts.google.com)"
Loading