name: Build and Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Version to release (e.g., v1.0.0)'
required: true
type: string
prerelease:
description: 'Is this a pre-release?'
required: false
type: boolean
default: false
env:
CARGO_INCREMENTAL: 0
RUST_BACKTRACE: short
PACKAGE_NAME: quickswitch
PACKAGE_VERSION: 0.1.0
jobs:
create-release:
permissions:
contents: write
runs-on: ubuntu-latest
outputs:
release_id: ${{ steps.create-release.outputs.result }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Get package info
run: |
echo "PACKAGE_VERSION=$(grep '^version' Cargo.toml | head -n1 | cut -d'=' -f2 | tr -d ' "' )" >> $GITHUB_ENV
echo "PACKAGE_NAME=$(grep '^name' Cargo.toml | head -n1 | cut -d'=' -f2 | tr -d ' "' )" >> $GITHUB_ENV
- name: Create release
id: create-release
uses: actions/github-script@v7
with:
script: |
const { data } = await github.rest.repos.createRelease({
owner: context.repo.owner,
repo: context.repo.repo,
tag_name: `${{ github.event.inputs.version || github.ref_name }}`,
name: `${{ env.PACKAGE_NAME }} Plugin v${{ env.PACKAGE_VERSION }}`,
body: 'Release created by GitHub Actions. See the assets below to download and install.',
draft: true,
prerelease: ${{ github.event.inputs.prerelease || 'false' }}
})
return data.id
build-plugins:
needs: create-release
permissions:
contents: write
strategy:
fail-fast: false
matrix:
include:
- platform: 'macos-latest'
target: 'universal-apple-darwin'
arch: 'universal'
lib_suffix: ''
file_extension: ''
platform_name: 'macos'
- platform: 'ubuntu-22.04'
target: 'x86_64-unknown-linux-gnu'
arch: 'x86_64'
lib_suffix: ''
file_extension: ''
platform_name: 'linux'
- platform: 'windows-latest'
target: 'x86_64-pc-windows-msvc'
arch: 'x86_64'
lib_suffix: '.exe'
file_extension: 'exe'
platform_name: 'windows'
runs-on: ${{ matrix.platform }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Get package name from Cargo.toml
id: package-info
shell: bash
run: |
PACKAGE_NAME=$(grep '^name' Cargo.toml | head -n1 | cut -d'=' -f2 | tr -d ' "')
PACKAGE_VERSION=$(grep '^version' Cargo.toml | head -n1 | cut -d'=' -f2 | tr -d ' "')
echo "package_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT
echo "package_version=$PACKAGE_VERSION" >> $GITHUB_OUTPUT
# Generate library name based on platform
LIB_NAME="${PACKAGE_NAME}${{ matrix.lib_suffix }}"
echo "lib_name=$LIB_NAME" >> $GITHUB_OUTPUT
echo "Package name: $PACKAGE_NAME"
echo "Package version: $PACKAGE_VERSION"
echo "Library base name: $LIB_BASE_NAME"
echo "Library name: $LIB_NAME"
- name: Install dependencies (ubuntu only)
if: matrix.platform == 'ubuntu-22.04'
run: |
sudo apt-get update
sudo apt-get install -y build-essential
- name: Rust setup
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || matrix.target }}
- name: Rust cache
uses: swatinem/rust-cache@v2
with:
workspaces: '. -> target'
key: ${{ matrix.platform }}-${{ matrix.target }}-plugins
- name: Build plugin
shell: bash
run: |
LIB_NAME="${{ steps.package-info.outputs.lib_name }}"
echo "Building library: $LIB_NAME"
if [ "${{ matrix.platform }}" = "macos-latest" ]; then
# Build for both architectures and create universal binary
cargo build --release --target aarch64-apple-darwin
cargo build --release --target x86_64-apple-darwin
lipo -create -output "target/release/$LIB_NAME" \
"target/aarch64-apple-darwin/release/$LIB_NAME" \
"target/x86_64-apple-darwin/release/$LIB_NAME"
else
cargo build --release --target ${{ matrix.target }}
# File is already in the correct location: target/${{ matrix.target }}/release/$LIB_NAME
fi
- name: List built files (debug)
shell: bash
run: |
LIB_NAME="${{ steps.package-info.outputs.lib_name }}"
echo "Looking for library: $LIB_NAME"
echo "Contents of target/release:"
ls -la target/release/ || echo "release directory not found"
echo "Contents of target/${{ matrix.target }}/release:"
ls -la target/${{ matrix.target }}/release/ || echo "target-specific directory not found"
- name: Upload plugin to release
uses: actions/github-script@v7
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
script: |
const fs = require('fs');
const path = require('path');
const libName = '${{ steps.package-info.outputs.lib_name }}';
const packageName = '${{ steps.package-info.outputs.package_name }}';
const packageVersion = '${{ steps.package-info.outputs.package_version }}';
let assetPath;
if ('${{ matrix.platform }}' === 'macos-latest') {
assetPath = `target/release/${libName}`;
} else {
assetPath = `target/${{ matrix.target }}/release/${libName}`;
}
// Generate asset name using package name, version and architecture
const assetName = `${{ matrix.platform_name }}-${packageName}-v${packageVersion}-${{ matrix.arch }}.${{ matrix.file_extension }}`;
console.log(`Uploading ${assetPath} as ${assetName}`);
const stats = fs.statSync(assetPath);
const fileSizeInBytes = stats.size;
const fileContent = fs.readFileSync(assetPath);
await github.rest.repos.uploadReleaseAsset({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: ${{ needs.create-release.outputs.release_id }},
name: assetName,
data: fileContent
});
publish-release:
permissions:
contents: write
runs-on: ubuntu-latest
needs: [create-release, build-plugins]
steps:
- name: Publish release
id: publish-release
uses: actions/github-script@v7
env:
release_id: ${{ needs.create-release.outputs.release_id }}
with:
script: |
github.rest.repos.updateRelease({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: process.env.release_id,
draft: false
})