feat: add prerelease RPM builds from upstream main branch
Some checks failed
deploy-ui / build-and-deploy (push) Has been cancelled

Poll upstream main branch HEAD alongside release tags. When a new commit
is detected, build and publish prerelease RPMs to a separate unstable
repo at rpm.lair.cafe/fedora/$releasever/$basearch/unstable/.

RPM versioning uses the Fedora snapshot convention (e.g.
0.8.1-0.1.20260511git1a2b3c4.fc43) so stable releases automatically
supersede any installed prerelease.

- RPM spec: conditional Release field via mistralrs_prerelease define
- poll-upstream.yml: new check-prerelease job fetches main HEAD + Cargo.toml version
- build-prerelease.yml: new workflow for commit-based builds without --locked
- UI: fetch both stable/unstable manifests, show channel badges, add
  unstable repo setup instructions to home page

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-11 14:21:28 +03:00
parent fff56a626c
commit a79eafd70f
8 changed files with 423 additions and 25 deletions

View File

@@ -0,0 +1,209 @@
name: build-prerelease
on:
workflow_dispatch:
inputs:
commit:
description: "mistral.rs upstream commit SHA"
required: true
type: string
version:
description: "Version from upstream Cargo.toml (e.g. 0.8.1)"
required: true
type: string
date:
description: "Commit date as YYYYMMDD"
required: true
type: string
short_sha:
description: "Short commit SHA (7 chars)"
required: true
type: string
concurrency:
group: prerelease-build
cancel-in-progress: true
jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- name: cuda13
fedora_version: "43"
runner: cuda-13.0
cuda_home: /usr/local/cuda-13.0
cargo_features: "cuda cudnn flash-attn nccl"
compute_caps: "120"
build_jobs: 12
nvcc_threads: 4
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v4
- name: Install/update Rust toolchain
run: |
if command -v rustup &> /dev/null; then
rustup update stable
else
curl --proto '=https' --tlsv1.2 --silent --show-error --fail https://sh.rustup.rs | sh -s -- -y
fi
echo "${HOME}/.cargo/bin" >> "$GITHUB_PATH"
- name: Clone mistral.rs at commit
run: |
git clone https://github.com/EricLBuehler/mistral.rs.git src/
cd src
git checkout "${{ inputs.commit }}"
- name: Build mistralrs
run: |
export PATH="${{ matrix.cuda_home }}/bin:${PATH}"
export LD_LIBRARY_PATH="${{ matrix.cuda_home }}/targets/x86_64-linux/lib:${{ matrix.cuda_home }}/lib64:${LD_LIBRARY_PATH:-}"
export LIBRARY_PATH="${{ matrix.cuda_home }}/targets/x86_64-linux/lib:${{ matrix.cuda_home }}/lib64:${LIBRARY_PATH:-}"
cd src
cargo build --release --features "${{ matrix.cargo_features }}"
env:
CUDA_COMPUTE_CAP: ${{ matrix.compute_caps }}
CARGO_BUILD_JOBS: ${{ matrix.build_jobs }}
NVCC_THREADS: ${{ matrix.nvcc_threads }}
- name: Collect artifacts
run: |
mkdir --parents artifacts
cp src/target/release/mistralrs "artifacts/mistralrs-${{ matrix.name }}"
echo "built: $(artifacts/mistralrs-${{ matrix.name }} --version 2>&1 | head -1)"
- name: Upload binary artifact
uses: actions/upload-artifact@v3
with:
name: mistralrs-${{ matrix.name }}-fc${{ matrix.fedora_version }}
path: artifacts/mistralrs-${{ matrix.name }}
retention-days: 1
package:
needs: build
runs-on: fedora-43
strategy:
fail-fast: false
matrix:
include:
- name: cuda13
fedora_version: "43"
steps:
- uses: actions/checkout@v4
- name: Download binary
uses: actions/download-artifact@v3
with:
name: mistralrs-${{ matrix.name }}-fc${{ matrix.fedora_version }}
path: artifacts/
- name: Build RPM
run: |
rm -f ~/.rpmmacros
rpmdev-setuptree
cp artifacts/mistralrs-${{ matrix.name }} ~/rpmbuild/SOURCES/
cp rpm/systemd/mistralrs@.service ~/rpmbuild/SOURCES/
cp rpm/systemd/mistralrs@.conf.example ~/rpmbuild/SOURCES/
rpmbuild -bb rpm/mistralrs.spec \
--define "mistralrs_version ${{ inputs.version }}" \
--define "mistralrs_flavour ${{ matrix.name }}" \
--define "mistralrs_prerelease 0.1.${{ inputs.date }}git${{ inputs.short_sha }}" \
--undefine dist \
--define "dist .fc${{ matrix.fedora_version }}"
- name: Upload RPM
uses: actions/upload-artifact@v3
with:
name: rpm-${{ matrix.name }}-fc${{ matrix.fedora_version }}
path: ~/rpmbuild/RPMS/x86_64/*.rpm
retention-days: 7
publish:
needs: package
runs-on: fedora-43
concurrency:
group: rpm-publish
cancel-in-progress: false
env:
RPM_REPO_HOST: oolon.kosherinata.internal
strategy:
fail-fast: false
matrix:
include:
- fedora_version: "43"
steps:
- uses: actions/checkout@v4
- name: Download RPMs for fc${{ matrix.fedora_version }}
uses: actions/download-artifact@v3
with:
path: rpms/
pattern: rpm-*-fc${{ matrix.fedora_version }}
- name: Flatten RPM artifacts
run: |
find rpms/ -name '*.rpm' -exec mv --target-directory=rpms/ {} +
find rpms/ -mindepth 1 -type d -empty -delete
- name: Check for sequoia-sq
run: |
if ! command -v sq &> /dev/null; then
echo "ERROR: sequoia-sq is not installed. Install with: sudo dnf install sequoia-sq"
exit 1
fi
- name: Import signing key
run: |
echo "${{ secrets.RPM_SIGNING_KEY }}" | gpg --batch --import
fpr=$(gpg --batch --with-colons --list-keys "${{ secrets.RPM_SIGNING_KEY_ID }}" | awk -F: '/^fpr:/ { print $10; exit }')
echo "${fpr}:6:" | gpg --batch --import-ownertrust
sed "s/@GPG_NAME@/${{ secrets.RPM_SIGNING_KEY_ID }}/" rpm/rpmmacros > ~/.rpmmacros
- name: Sign RPMs
run: |
for rpm in rpms/*.rpm; do
echo "signing ${rpm}..."
rpm --addsign "${rpm}"
done
- name: Set up SSH
run: |
install --directory --mode 700 ~/.ssh
echo "${RSYNC_SSH_KEY}" | install --mode 600 /dev/stdin ~/.ssh/id_ed25519
env:
RSYNC_SSH_KEY: ${{ secrets.RSYNC_SSH_KEY }}
- name: Test SSH connectivity
run: |
ssh -o StrictHostKeyChecking=accept-new "gitea_ci@${RPM_REPO_HOST}" exit
- name: Ensure unstable repo directory exists
run: |
ssh "gitea_ci@${RPM_REPO_HOST}" \
"mkdir --parents /var/www/rpm/fedora/${{ matrix.fedora_version }}/x86_64/unstable"
- name: Sync RPMs to unstable repo
run: |
rsync \
--archive \
--verbose \
--chmod D755,F644 \
rpms/*.rpm \
"gitea_ci@${RPM_REPO_HOST}:/var/www/rpm/fedora/${{ matrix.fedora_version }}/x86_64/unstable/"
- name: Update unstable repo metadata
run: |
ssh "gitea_ci@${RPM_REPO_HOST}" \
"cd /var/www/rpm/fedora/${{ matrix.fedora_version }}/x86_64/unstable && createrepo_c --update ."
- name: Generate packages.json for unstable
run: |
scp script/generate-packages-json.py "gitea_ci@${RPM_REPO_HOST}:/tmp/"
ssh "gitea_ci@${RPM_REPO_HOST}" \
"python3 /tmp/generate-packages-json.py \
--repodata-dir /var/www/rpm/fedora/${{ matrix.fedora_version }}/x86_64/unstable/repodata \
--output /var/www/rpm/fedora/${{ matrix.fedora_version }}/x86_64/unstable/packages.json \
--base-url https://rpm.lair.cafe/fedora/${{ matrix.fedora_version }}/x86_64/unstable"

View File

@@ -83,3 +83,73 @@ jobs:
--header 'Content-Type: application/json' \
--url "${{ github.server_url }}/api/v1/repos/${{ github.repository }}/actions/workflows/build-release.yml/dispatches" \
--data "{\"ref\":\"refs/heads/main\",\"inputs\":{\"tag\":\"${{ steps.upstream.outputs.tag }}\"}}"
check-prerelease:
runs-on: fedora-43
steps:
- name: Get upstream main branch HEAD
id: upstream
run: |
response=$(curl --silent --show-error --fail --location \
--header 'Accept: application/vnd.github+json' \
--url 'https://api.github.com/repos/EricLBuehler/mistral.rs/commits/main')
sha=$(echo "${response}" | jq -r .sha)
short_sha=$(echo "${sha}" | head --bytes=7)
date=$(echo "${response}" | jq -r '.commit.committer.date[:10]' | tr -d '-')
echo "sha=${sha}" >> "$GITHUB_OUTPUT"
echo "short_sha=${short_sha}" >> "$GITHUB_OUTPUT"
echo "date=${date}" >> "$GITHUB_OUTPUT"
echo "Upstream main HEAD: ${sha} (${date})"
- name: Get version from upstream Cargo.toml
id: version
run: |
version=$(curl --silent --show-error --fail --location \
--header 'Accept: application/vnd.github.raw+json' \
--url "https://api.github.com/repos/EricLBuehler/mistral.rs/contents/Cargo.toml?ref=${{ steps.upstream.outputs.sha }}" \
| grep '^version' | head --lines=1 | sed 's/.*"\(.*\)".*/\1/')
echo "version=${version}" >> "$GITHUB_OUTPUT"
echo "Upstream Cargo.toml version: ${version}"
- name: Check if prerelease is already published
id: published
run: |
prerelease="0.1.${UPSTREAM_DATE}git${UPSTREAM_SHORT_SHA}"
needs_build=false
for target in "43:cuda13"; do
fedora_version="${target%%:*}"
flavour="${target##*:}"
base_url="https://rpm.lair.cafe/fedora/${fedora_version}/x86_64/unstable"
rpm_name="mistralrs-${flavour}-${UPSTREAM_VERSION}-${prerelease}.fc${fedora_version}.x86_64.rpm"
http_code=$(curl \
--silent \
--write-out "%{http_code}" \
--output /dev/null \
--head \
--url "${base_url}/${rpm_name}")
if [ "${http_code}" = "404" ]; then
echo "missing: ${base_url}/${rpm_name}"
needs_build=true
continue
elif [ "${http_code}" != "200" ]; then
echo "unexpected HTTP ${http_code} for ${base_url}/${rpm_name}"
exit 1
fi
echo "found: ${base_url}/${rpm_name}"
done
echo "already_built=$( [ "${needs_build}" = "true" ] && echo false || echo true )" >> "$GITHUB_OUTPUT"
env:
UPSTREAM_VERSION: ${{ steps.version.outputs.version }}
UPSTREAM_DATE: ${{ steps.upstream.outputs.date }}
UPSTREAM_SHORT_SHA: ${{ steps.upstream.outputs.short_sha }}
- name: Trigger prerelease build workflow
if: steps.published.outputs.already_built == 'false'
run: |
curl --fail --silent --show-error --location \
--request POST \
--header "Authorization: token ${{ secrets.DISPATCH_TOKEN }}" \
--header 'Content-Type: application/json' \
--url "${{ github.server_url }}/api/v1/repos/${{ github.repository }}/actions/workflows/build-prerelease.yml/dispatches" \
--data "{\"ref\":\"refs/heads/main\",\"inputs\":{\"commit\":\"${{ steps.upstream.outputs.sha }}\",\"version\":\"${{ steps.version.outputs.version }}\",\"date\":\"${{ steps.upstream.outputs.date }}\",\"short_sha\":\"${{ steps.upstream.outputs.short_sha }}\"}}"