name: 'FerrFlow Release'
description: 'Universal semantic versioning for monorepos and classic repos'
author: 'FerrLabs'
branding:
icon: 'tag'
color: 'orange'
inputs:
version:
description: 'FerrFlow version to use (e.g. 1.2.3). Defaults to latest.'
required: false
default: 'latest'
mode:
description: 'Action mode: "release" runs the full release pipeline. "preview" posts a PR comment with version bump preview. "publish" runs the configured publishers for the currently-released version (no bump/tag) — for a separate job that has the build toolchain + registry auth the publishers need.'
required: false
default: 'release'
dry_run:
description: 'Run without creating releases or pushing changes'
required: false
default: 'false'
force_version:
description: 'Force a specific version, skipping commit analysis. Format: VERSION (single repo) or NAME@VERSION (monorepo)'
required: false
default: ''
bot:
description: 'Opt into the hosted FerrFlow bot identity (ferrflow[bot]). Requires permissions.id-token: write on the caller workflow. If false/unset, the caller''s token or GITHUB_TOKEN is used as before.'
required: false
default: 'false'
bot_endpoint:
description: 'Override the hosted bot token endpoint. Defaults to https://api.ferrlabs.com/api/v1/ferrflow/token.'
required: false
default: 'https://api.ferrlabs.com/api/v1/ferrflow/token'
bot_audience:
description: 'OIDC audience requested from the GitHub Actions runner. Must match the server-side expected audience.'
required: false
default: 'ferrflow.ferrlabs.com'
runs:
using: composite
steps:
- name: Install FerrFlow
shell: bash
run: |
set -euo pipefail
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
# Git Bash / MSYS / Cygwin on Windows runners all report a compound
# kernel name like "mingw64_nt-10.0". Normalise to "windows".
case "$OS" in
linux) PLATFORM="linux" ; EXT="tar.gz" ;;
darwin) PLATFORM="darwin" ; EXT="tar.gz" ;;
mingw*|msys*|cygwin*) PLATFORM="windows" ; EXT="zip" ;;
*) echo "Unsupported OS: $OS" && exit 1 ;;
esac
case "$ARCH" in
x86_64) ARCH_NAME="x64" ;;
aarch64|arm64) ARCH_NAME="arm64" ;;
*) echo "Unsupported architecture: $ARCH" && exit 1 ;;
esac
ARCHIVE="ferrflow-${PLATFORM}-${ARCH_NAME}.${EXT}"
if [ "${{ inputs.version }}" = "latest" ]; then
URL="https://github.com/FerrLabs/FerrFlow/releases/latest/download/${ARCHIVE}"
else
URL="https://github.com/FerrLabs/FerrFlow/releases/download/v${{ inputs.version }}/${ARCHIVE}"
fi
INSTALL_DIR="${RUNNER_TEMP:-$HOME/.local/bin}/ferrflow-bin"
mkdir -p "$INSTALL_DIR"
if [ "$PLATFORM" = "windows" ]; then
# Can't pipe into unzip (needs a seekable file), so download first.
TMP_ZIP="${RUNNER_TEMP:-/tmp}/ferrflow.zip"
curl --fail --location --silent --show-error --output "$TMP_ZIP" "$URL"
unzip -q -o "$TMP_ZIP" -d "$INSTALL_DIR"
rm -f "$TMP_ZIP"
# No chmod needed on Windows; the .exe is already executable.
else
curl --fail --location --silent --show-error "$URL" | tar -xz -C "$INSTALL_DIR"
chmod +x "$INSTALL_DIR/ferrflow"
fi
echo "$INSTALL_DIR" >> "$GITHUB_PATH"
- name: Preview release
if: inputs.mode == 'preview'
shell: bash
env:
FERRFLOW_BOT: ${{ inputs.bot }}
FERRFLOW_BOT_ENDPOINT: ${{ inputs.bot_endpoint }}
FERRFLOW_BOT_AUDIENCE: ${{ inputs.bot_audience }}
run: ferrflow check --comment
- name: Run FerrFlow release
if: inputs.mode == 'release'
shell: bash
env:
FERRFLOW_BOT: ${{ inputs.bot }}
FERRFLOW_BOT_ENDPOINT: ${{ inputs.bot_endpoint }}
FERRFLOW_BOT_AUDIENCE: ${{ inputs.bot_audience }}
run: ferrflow ${{ inputs.dry_run == 'true' && '--dry-run' || '' }} release ${{ inputs.force_version != '' && format('--force-version {0}', inputs.force_version) || '' }}
- name: Run FerrFlow publishers
if: inputs.mode == 'publish'
shell: bash
run: ferrflow ${{ inputs.dry_run == 'true' && '--dry-run' || '' }} publish