ferrflow 4.4.0

Universal semantic versioning for monorepos and classic repos
Documentation
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.'
    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: Configure git identity for ferrflow[bot]
      # When bot: true, release commits must be authored by ferrflow[bot] (not
      # the checkout actor or the runner's previous git identity). libgit2
      # reads the repo config, so we set it here before `ferrflow release`
      # does any committing. The bot user ID (278126555) is stable for the
      # hosted ferrflow GitHub App; self-hosters running their own App should
      # replace these values with their bot's identity.
      if: inputs.bot == 'true'
      shell: bash
      run: |
        git config user.name "ferrflow[bot]"
        git config user.email "278126555+ferrflow[bot]@users.noreply.github.com"

    - 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) || '' }}