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
256 changes: 238 additions & 18 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,52 @@ on:
description: Release tag to publish (required when publish_release is true)
required: false
type: string
bundle_variant:
description: Which bundle variant to build when manually dispatching
required: false
default: portable
type: choice
options:
- portable
- cuda

permissions:
contents: write

jobs:
build-and-release:
ensure-release:
runs-on: ubuntu-latest
steps:
- name: Checkout workflow ref
uses: actions/checkout@v5

- name: Ensure GitHub release exists
env:
GH_TOKEN: ${{ github.token }}
TAG_NAME: ${{ github.event_name == 'push' && github.ref_name || inputs.tag_name }}
run: |
set -euo pipefail

if [[ "${GITHUB_EVENT_NAME}" != "push" && "${{ inputs.publish_release }}" != "true" ]]; then
exit 0
fi

if gh release view "$TAG_NAME" >/dev/null 2>&1; then
exit 0
fi

if ! git ls-remote --exit-code origin "refs/tags/$TAG_NAME" >/dev/null 2>&1; then
echo "::error::tag $TAG_NAME does not exist on origin"
exit 1
fi

gh release create "$TAG_NAME" \
--title "$TAG_NAME" \
--generate-notes
Comment on lines +57 to +59
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Prevent gh release create from auto-creating wrong tags

The ensure-release job creates releases with gh release create "$TAG_NAME" before the workflow validates that tag_name is real and matches checked-out code, and it does so without --verify-tag. In a manual dispatch with publish_release=true, a typo/nonexistent tag can create an unintended tag/release from the default branch and then fail later in build steps, leaving incorrect release state behind. Add --verify-tag (or defer creation until after tag validation) to avoid this side effect.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 4df9b4c by checking that the requested tag exists on origin before creating a release, so a typo/nonexistent tag cannot auto-create an unintended release/tag.

Comment on lines +57 to +59
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Delay release creation until bundle builds succeed

The ensure-release job creates the GitHub release before build-portable/build-cuda run, so on tag pushes (or dispatch publishes) any later build failure leaves a newly published release with no assets because the downstream publish-release-* job is skipped. This is a release-state regression from the previous single-job flow and can expose broken/empty releases to users unless maintainers manually clean them up. Create the release only in the publish stage (or keep it draft until uploads complete) so publication is atomic.

Useful? React with 👍 / 👎.


build-portable:
if: github.event_name == 'push' || inputs.bundle_variant != 'cuda'
needs: ensure-release
runs-on: ubuntu-latest
steps:
- name: Checkout current ref
Expand Down Expand Up @@ -90,35 +130,215 @@ jobs:
} >> "$GITHUB_OUTPUT"

- name: Build release bundle
env:
WHISPERS_RELEASE_BUNDLE_PREFIX: whispers
WHISPERS_RELEASE_FEATURES: local-rewrite,osd
run: scripts/build-release-bundle.sh "${{ steps.meta.outputs.version }}"

- name: Upload release bundle artifact
uses: actions/upload-artifact@v4
with:
name: ${{ steps.meta.outputs.bundle }}
name: portable-release-bundle
path: |
dist/${{ steps.meta.outputs.bundle }}.tar.gz
dist/${{ steps.meta.outputs.bundle }}.tar.gz.sha256

- name: Publish GitHub release
if: steps.meta.outputs.publish == 'true'
build-cuda:
if: github.event_name == 'push' || inputs.bundle_variant == 'cuda'
needs: ensure-release
runs-on: ubuntu-latest
steps:
- name: Checkout current ref
if: github.event_name != 'workflow_dispatch' || inputs.publish_release != true
uses: actions/checkout@v5

- name: Checkout requested release tag
if: github.event_name == 'workflow_dispatch' && inputs.publish_release == true
uses: actions/checkout@v5
with:
ref: ${{ inputs.tag_name }}

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable

- name: Install Linux build deps
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake clang pkg-config libasound2-dev

- name: Install CUDA toolkit
uses: Jimver/cuda-toolkit@v0.2.30
with:
cuda: "12.5.0"

- name: Expose CUDA toolkit paths
run: |
echo "CUDAToolkit_ROOT=$CUDA_PATH" >> "$GITHUB_ENV"
sudo ln -sfn "$CUDA_PATH" /usr/local/cuda

- name: Cache cargo
uses: Swatinem/rust-cache@v2

- name: Compute release metadata
id: meta
env:
GH_TOKEN: ${{ github.token }}
TAG_NAME: ${{ steps.meta.outputs.tag_name }}
BUNDLE_NAME: ${{ steps.meta.outputs.bundle }}
INPUT_PUBLISH_RELEASE: ${{ inputs.publish_release }}
INPUT_TAG_NAME: ${{ inputs.tag_name }}
run: |
set -euo pipefail

assets=(
"dist/${BUNDLE_NAME}.tar.gz"
"dist/${BUNDLE_NAME}.tar.gz.sha256"
)
version=$(awk -F '"' '$1 ~ /^version *=/ { print $2; exit }' Cargo.toml)
source_bundle="whispers-${version}-x86_64-unknown-linux-gnu"
final_bundle="whispers-cuda-${version}-x86_64-unknown-linux-gnu"
publish=false
tag_name=""

if gh release view "$TAG_NAME" >/dev/null 2>&1; then
gh release upload "$TAG_NAME" "${assets[@]}" --clobber
else
gh release create "$TAG_NAME" "${assets[@]}" \
--title "$TAG_NAME" \
--generate-notes \
--target "$GITHUB_SHA"
if [[ "${GITHUB_EVENT_NAME}" == "push" ]]; then
publish=true
tag_name="${GITHUB_REF_NAME}"
elif [[ "${INPUT_PUBLISH_RELEASE:-false}" == "true" ]]; then
publish=true
tag_name="${INPUT_TAG_NAME}"
fi

if [[ "$publish" == "true" ]]; then
if [[ -z "$tag_name" ]]; then
echo "::error::tag_name is required when publish_release=true"
exit 1
fi
if [[ "$tag_name" != "v$version" ]]; then
echo "::error::tag ${tag_name} does not match Cargo.toml version v${version}"
exit 1
fi
checked_out_commit=$(git rev-parse HEAD)
tag_commit=$(git rev-list -n1 "$tag_name")
if [[ "$checked_out_commit" != "$tag_commit" ]]; then
echo "::error::checked out ${checked_out_commit} but tag ${tag_name} points to ${tag_commit}"
exit 1
fi
fi

{
echo "source_bundle=$source_bundle"
echo "bundle=$final_bundle"
echo "publish=$publish"
echo "tag_name=$tag_name"
echo "version=$version"
} >> "$GITHUB_OUTPUT"

- name: Build CUDA release bundle
env:
WHISPERS_RELEASE_BUNDLE_PREFIX: whispers-cuda
WHISPERS_RELEASE_FEATURES: cuda,local-rewrite,osd
run: |
set -euo pipefail

scripts/build-release-bundle.sh "${{ steps.meta.outputs.version }}"

source_bundle="${{ steps.meta.outputs.source_bundle }}"
final_bundle="${{ steps.meta.outputs.bundle }}"

if [[ "$source_bundle" != "$final_bundle" && -f "dist/${source_bundle}.tar.gz" ]]; then
temp_dir="$(mktemp -d)"
cleanup() {
rm -rf "$temp_dir"
}
trap cleanup EXIT

tar -xzf "dist/${source_bundle}.tar.gz" -C "$temp_dir"
mv "$temp_dir/${source_bundle}" "$temp_dir/${final_bundle}"

tar \
--sort=name \
--mtime="@$(git log -1 --format=%ct HEAD)" \
--owner=0 \
--group=0 \
--numeric-owner \
-C "$temp_dir" \
-czf "dist/${final_bundle}.tar.gz" \
"$final_bundle"

(
cd dist
sha256sum "${final_bundle}.tar.gz" > "${final_bundle}.tar.gz.sha256"
Comment on lines +241 to +263
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Repack legacy bundles instead of renaming CUDA tarball only

In build-cuda, this fallback only renames dist/whispers-...tar.gz to dist/whispers-cuda-...tar.gz and rewrites the checksum, but it does not change the archive’s internal top-level directory. For manual dispatches that publish older tags (where scripts/build-release-bundle.sh still emits whispers-<ver>-...), the uploaded CUDA asset name and its contents diverge, and packaging/aur/whispers-cuda-bin/PKGBUILD (which expects whispers-cuda-<ver>-... in package()) will fail when extracting/installing. Repack the archive with the CUDA root name (or block publishing from tags without prefix support).

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 4df9b4c by repacking legacy CUDA bundles under the whispers-cuda-... top-level directory instead of only renaming the tarball path, so the uploaded asset contents match the whispers-cuda-bin PKGBUILD expectations.

rm -f "${source_bundle}.tar.gz" "${source_bundle}.tar.gz.sha256"
)
fi

- name: Upload CUDA release bundle artifact
uses: actions/upload-artifact@v4
with:
name: cuda-release-bundle
path: |
dist/${{ steps.meta.outputs.bundle }}.tar.gz
dist/${{ steps.meta.outputs.bundle }}.tar.gz.sha256

publish-release-push:
if: github.event_name == 'push'
needs:
- ensure-release
- build-portable
- build-cuda
runs-on: ubuntu-latest
steps:
- name: Download portable artifact
uses: actions/download-artifact@v4
with:
name: portable-release-bundle
path: dist

- name: Download CUDA artifact
uses: actions/download-artifact@v4
with:
name: cuda-release-bundle
path: dist

- name: Publish release assets
env:
GH_TOKEN: ${{ github.token }}
TAG_NAME: ${{ github.ref_name }}
run: |
set -euo pipefail
gh release upload "$TAG_NAME" dist/* --clobber

publish-release-portable-dispatch:
if: github.event_name == 'workflow_dispatch' && inputs.publish_release == true && inputs.bundle_variant != 'cuda'
needs:
- ensure-release
- build-portable
runs-on: ubuntu-latest
steps:
- name: Download portable artifact
uses: actions/download-artifact@v4
with:
name: portable-release-bundle
path: dist

- name: Publish portable release assets
env:
GH_TOKEN: ${{ github.token }}
TAG_NAME: ${{ inputs.tag_name }}
run: |
set -euo pipefail
gh release upload "$TAG_NAME" dist/* --clobber

publish-release-cuda-dispatch:
if: github.event_name == 'workflow_dispatch' && inputs.publish_release == true && inputs.bundle_variant == 'cuda'
needs:
- ensure-release
- build-cuda
runs-on: ubuntu-latest
steps:
- name: Download CUDA artifact
uses: actions/download-artifact@v4
with:
name: cuda-release-bundle
path: dist

- name: Publish CUDA release assets
env:
GH_TOKEN: ${{ github.token }}
TAG_NAME: ${{ inputs.tag_name }}
run: |
set -euo pipefail
gh release upload "$TAG_NAME" dist/* --clobber
29 changes: 22 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,20 @@

### Arch Linux (`paru`)

#### CUDA-enabled

```sh
# prebuilt GitHub release bundle with CUDA support
paru -S whispers-cuda-bin

# latest main branch build with CUDA support
paru -S whispers-cuda-git
```

Use these when you want the CUDA-enabled local path from the AUR.

#### Portable / non-CUDA

```sh
# prebuilt GitHub release bundle
paru -S whispers-bin
Expand All @@ -44,9 +58,10 @@ paru -S whispers-bin
paru -S whispers-git
```

- `whispers-bin` installs the published Linux x86_64 release bundle.
- `whispers-git` builds the latest `main` branch from source.
- Both AUR packages currently ship the portable `local-rewrite,osd` feature set.
- `whispers-cuda-bin` installs the published Linux x86_64 CUDA bundle.
- `whispers-cuda-git` builds the latest `main` branch with `cuda,local-rewrite,osd`.
- `whispers-bin` installs the published portable non-CUDA Linux x86_64 bundle.
- `whispers-git` builds the latest `main` branch with the portable `local-rewrite,osd` feature set.

### Cargo

Expand Down Expand Up @@ -175,13 +190,13 @@ Those bundles include the current status snapshot plus best-effort stack and ope

Tagged releases publish a Linux x86_64 bundle with:

- `whispers`
- `whispers-osd`
- `whispers-rewrite-worker`
- a portable `whispers-<version>-x86_64-unknown-linux-gnu.tar.gz`
- a CUDA-enabled `whispers-cuda-<version>-x86_64-unknown-linux-gnu.tar.gz`
- `whispers`, `whispers-osd`, and `whispers-rewrite-worker`
- Bash, Zsh, and Fish completions
- `README.md`, `config.example.toml`, `LICENSE`, and `NOTICE`

That bundle is what the `whispers-bin` AUR package installs.
Those bundles are what the `whispers-bin` and `whispers-cuda-bin` AUR packages install.

## License

Expand Down
19 changes: 13 additions & 6 deletions packaging/aur/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@

This repository keeps the maintained AUR sources for:

- `whispers-bin`: installs the GitHub release bundle
- `whispers-git`: builds the latest `main` branch from source
- `whispers-bin`: installs the portable GitHub release bundle
- `whispers-git`: builds the latest `main` branch without CUDA
- `whispers-cuda-bin`: installs the CUDA-enabled GitHub release bundle
- `whispers-cuda-git`: builds the latest `main` branch with CUDA

Both packages currently ship the portable `local-rewrite,osd` feature set.
Current feature sets:

- `whispers-bin` / `whispers-git`: `local-rewrite,osd`
- `whispers-cuda-bin` / `whispers-cuda-git`: `cuda,local-rewrite,osd`

## Refreshing metadata

Expand All @@ -16,11 +21,11 @@ directory:
makepkg --printsrcinfo > .SRCINFO
```

## Updating `whispers-bin`
## Updating `whispers-bin` / `whispers-cuda-bin`

1. Cut a GitHub release for `vX.Y.Z`.
2. Update `pkgver` and `sha256sums` in `packaging/aur/whispers-bin/PKGBUILD`.
3. Regenerate `packaging/aur/whispers-bin/.SRCINFO`.
2. Update `pkgver` and `sha256sums` in the matching `*-bin/PKGBUILD`.
3. Regenerate the matching `*-bin/.SRCINFO`.

## Publishing to the AUR

Expand All @@ -29,3 +34,5 @@ matching directory to:

- `ssh://aur@aur.archlinux.org/whispers-bin.git`
- `ssh://aur@aur.archlinux.org/whispers-git.git`
- `ssh://aur@aur.archlinux.org/whispers-cuda-bin.git`
- `ssh://aur@aur.archlinux.org/whispers-cuda-git.git`
2 changes: 2 additions & 0 deletions packaging/aur/whispers-bin/.SRCINFO
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ pkgbase = whispers-bin
provides = whispers
conflicts = whispers
conflicts = whispers-git
conflicts = whispers-cuda-bin
conflicts = whispers-cuda-git
source = whispers-bin-0.2.1.tar.gz::https://github.com/OneNoted/whispers/releases/download/v0.2.1/whispers-0.2.1-x86_64-unknown-linux-gnu.tar.gz
sha256sums = b5f1ce5d1e66cece42bb5129c0eb7ab93cc118a7e705847a4a1c8e75cd60ad1e

Expand Down
2 changes: 1 addition & 1 deletion packaging/aur/whispers-bin/PKGBUILD
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ license=('MIT')
depends=('alsa-lib' 'gcc-libs' 'glibc' 'noto-fonts' 'wl-clipboard')
optdepends=('python: experimental faster-whisper and NeMo runtimes')
provides=('whispers')
conflicts=('whispers' 'whispers-git')
conflicts=('whispers' 'whispers-git' 'whispers-cuda-bin' 'whispers-cuda-git')
source=(
"$pkgname-$pkgver.tar.gz::$url/releases/download/v$pkgver/whispers-$pkgver-x86_64-unknown-linux-gnu.tar.gz"
)
Expand Down
Loading