name: Release
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
tag:
description: "Tag to release (e.g. v5.2.1)"
required: true
permissions:
contents: write
jobs:
build:
strategy:
matrix:
include:
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
name: hvac-linux-x86_64
deb: true
- target: aarch64-unknown-linux-gnu
os: ubuntu-latest
name: hvac-linux-aarch64
deb: true
- target: x86_64-apple-darwin
os: macos-latest
name: hvac-macos-x86_64
deb: false
- target: aarch64-apple-darwin
os: macos-latest
name: hvac-macos-aarch64
deb: false
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.target }}
- name: Install cross-compilation tools
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu
echo '[target.aarch64-unknown-linux-gnu]' >> ~/.cargo/config.toml
echo 'linker = "aarch64-linux-gnu-gcc"' >> ~/.cargo/config.toml
- name: Build
run: cargo build --release --target ${{ matrix.target }}
- name: Package tarball
run: |
# Copy the binary alongside config.yaml so Homebrew's etc.install
# finds it; having config.yaml in the tarball is harmless for other
# install paths.
cp target/${{ matrix.target }}/release/hvac .
tar czf ${{ matrix.name }}.tar.gz hvac config.yaml
rm hvac
sha256sum ${{ matrix.name }}.tar.gz > ${{ matrix.name }}.tar.gz.sha256
- name: Install cargo-deb
if: matrix.deb
run: cargo install cargo-deb --locked
- name: Build .deb package
if: matrix.deb
run: |
cargo deb --no-build --target ${{ matrix.target }}
DEB_PATH=$(ls target/${{ matrix.target }}/debian/hvac_*.deb | head -n1)
# Normalise filename to a predictable shape we can advertise in the README
ARCH=$([ "${{ matrix.target }}" = "x86_64-unknown-linux-gnu" ] && echo amd64 || echo arm64)
VERSION="${GITHUB_REF_NAME#v}"
NEW_NAME="hvac_${VERSION}_${ARCH}.deb"
cp "$DEB_PATH" "$NEW_NAME"
sha256sum "$NEW_NAME" > "$NEW_NAME.sha256"
- name: Upload tarball artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.name }}
path: |
${{ matrix.name }}.tar.gz
${{ matrix.name }}.tar.gz.sha256
- name: Upload .deb artifact
if: matrix.deb
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.name }}-deb
path: |
hvac_*.deb
hvac_*.deb.sha256
publish:
needs: build
runs-on: ubuntu-latest
outputs:
version: ${{ steps.meta.outputs.version }}
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
merge-multiple: true
- name: Compute version
id: meta
run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
- name: Create GitHub Release
uses: softprops/action-gh-release@v3
with:
generate_release_notes: true
files: |
hvac-linux-x86_64.tar.gz
hvac-linux-x86_64.tar.gz.sha256
hvac-linux-aarch64.tar.gz
hvac-linux-aarch64.tar.gz.sha256
hvac-macos-x86_64.tar.gz
hvac-macos-x86_64.tar.gz.sha256
hvac-macos-aarch64.tar.gz
hvac-macos-aarch64.tar.gz.sha256
hvac_${{ steps.meta.outputs.version }}_amd64.deb
hvac_${{ steps.meta.outputs.version }}_amd64.deb.sha256
hvac_${{ steps.meta.outputs.version }}_arm64.deb
hvac_${{ steps.meta.outputs.version }}_arm64.deb.sha256
crates-io:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Publish to crates.io
run: cargo publish --allow-dirty
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
homebrew:
needs: publish
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
merge-multiple: true
- name: Compute SHA256 checksums
id: sha
run: |
echo "linux_x86_64=$(sha256sum hvac-linux-x86_64.tar.gz | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"
echo "linux_aarch64=$(sha256sum hvac-linux-aarch64.tar.gz | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"
echo "macos_x86_64=$(sha256sum hvac-macos-x86_64.tar.gz | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"
echo "macos_aarch64=$(sha256sum hvac-macos-aarch64.tar.gz | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"
- name: Update Homebrew formula
env:
GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
run: |
VERSION="${GITHUB_REF_NAME#v}"
TAG="${GITHUB_REF_NAME}"
cat > hvac.rb << 'FORMULA'
class Hvac < Formula
desc "GPU-accelerated media transcoder (HEVC/h265 via NVENC, VAAPI, VideoToolbox)"
homepage "https://github.com/JackDanger/hvac"
version "VERSION_PLACEHOLDER"
license "MIT"
on_macos do
if Hardware::CPU.arm?
url "MACOS_AARCH64_URL"
sha256 "MACOS_AARCH64_SHA"
else
url "MACOS_X86_64_URL"
sha256 "MACOS_X86_64_SHA"
end
end
on_linux do
if Hardware::CPU.arm?
url "LINUX_AARCH64_URL"
sha256 "LINUX_AARCH64_SHA"
else
url "LINUX_X86_64_URL"
sha256 "LINUX_X86_64_SHA"
end
end
depends_on "ffmpeg"
def install
bin.install "hvac"
etc.install "config.yaml" => "hvac/config.yaml"
end
def caveats
<<~EOS
hvac requires a GPU with hardware HEVC encoding:
macOS: Apple VideoToolbox (built into all Apple Silicon and recent Intel Macs)
Linux: NVIDIA NVENC (hevc_nvenc) or Intel/AMD VAAPI (hevc_vaapi)
A starter config was installed to:
#{etc}/hvac/config.yaml
Run `hvac --dry-run /path/to/videos` to preview what would be transcoded.
EOS
end
test do
assert_match version.to_s, shell_output("#{bin}/hvac --version")
end
end
FORMULA
# Remove leading whitespace from heredoc, then substitute real values.
sed -i 's/^ //' hvac.rb
sed -i "s/VERSION_PLACEHOLDER/${VERSION}/" hvac.rb
sed -i "s|MACOS_AARCH64_URL|https://github.com/JackDanger/hvac/releases/download/${TAG}/hvac-macos-aarch64.tar.gz|" hvac.rb
sed -i "s/MACOS_AARCH64_SHA/${{ steps.sha.outputs.macos_aarch64 }}/" hvac.rb
sed -i "s|MACOS_X86_64_URL|https://github.com/JackDanger/hvac/releases/download/${TAG}/hvac-macos-x86_64.tar.gz|" hvac.rb
sed -i "s/MACOS_X86_64_SHA/${{ steps.sha.outputs.macos_x86_64 }}/" hvac.rb
sed -i "s|LINUX_AARCH64_URL|https://github.com/JackDanger/hvac/releases/download/${TAG}/hvac-linux-aarch64.tar.gz|" hvac.rb
sed -i "s/LINUX_AARCH64_SHA/${{ steps.sha.outputs.linux_aarch64 }}/" hvac.rb
sed -i "s|LINUX_X86_64_URL|https://github.com/JackDanger/hvac/releases/download/${TAG}/hvac-linux-x86_64.tar.gz|" hvac.rb
sed -i "s/LINUX_X86_64_SHA/${{ steps.sha.outputs.linux_x86_64 }}/" hvac.rb
# Push to homebrew-tap repo
git clone "https://x-access-token:${GH_TOKEN}@github.com/JackDanger/homebrew-tap.git"
cp hvac.rb homebrew-tap/Formula/hvac.rb
cd homebrew-tap
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Formula/hvac.rb
git commit -m "Update hvac to ${VERSION}"
git push
aur:
needs: publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Bump pkgver in PKGBUILD
run: |
VERSION="${GITHUB_REF_NAME#v}"
sed -i "s/^pkgver=.*/pkgver=${VERSION}/" packaging/aur/PKGBUILD
sed -i "s/^pkgrel=.*/pkgrel=1/" packaging/aur/PKGBUILD
- name: Publish to AUR
uses: KSXGitHub/github-actions-deploy-aur@v4.1.3
with:
pkgname: hvac
pkgbuild: packaging/aur/PKGBUILD
commit_username: jackdanger
commit_email: jack@jackdanger.com
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
commit_message: "Release v${{ needs.publish.outputs.version }}"
ssh_keyscan_types: rsa,ecdsa,ed25519
updpkgsums: true
apt-repo:
needs: build
runs-on: ubuntu-latest
if: github.repository_owner == 'JackDanger'
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/download-artifact@v4
with:
pattern: "*-deb"
merge-multiple: true
path: incoming/
- name: Install apt-utils
run: sudo apt-get install -y --no-install-recommends apt-utils
- name: Import GPG signing key
run: |
echo "${{ secrets.APT_SIGNING_KEY }}" | gpg --batch --import
KEY_ID=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/ { print $5; exit }')
gpg --armor --export "$KEY_ID" > key.gpg
- name: Set up gh-pages worktree
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
if git show-ref --verify --quiet refs/remotes/origin/gh-pages; then
git worktree add -B gh-pages apt-repo origin/gh-pages
else
git worktree add --orphan -b gh-pages apt-repo
touch apt-repo/.nojekyll
fi
cp key.gpg apt-repo/key.gpg
- name: Update apt repository
run: bash scripts/update-apt-repo.sh incoming/ apt-repo/
- name: Commit and push
run: |
cd apt-repo
git add -A
git diff --staged --quiet && exit 0
git commit -m "apt: add hvac ${{ github.ref_name }}"
git push origin gh-pages