sampo-github-action 0.13.0

GitHub Action runner for Sampo CLI (release/publish orchestrator)
name: "Sampo GitHub Action"
description: "Run Sampo release and/or publish in CI"
author: "bruits"

inputs:
  command:
    description: "Operation: auto | release | publish"
    required: false
    default: "auto"
  dry-run:
    description: "Simulate actions without modifying files or publishing"
    required: false
    default: "false"
  working-directory:
    description: "Path to repository root (defaults to GITHUB_WORKSPACE)"
    required: false
  cargo-token:
    description: "crates.io token (exported as CARGO_REGISTRY_TOKEN)"
    required: false
  args:
    description: "Extra flags forwarded to cargo publish via `sampo publish -- …`"
    required: false
  base-branch:
    description: "Base branch for the Release PR when auto prepares it"
    required: false
  pr-branch:
    description: "Branch name for the Release PR when auto prepares it"
    required: false
  pr-title:
    description: "Title for the Release PR when auto prepares it"
    required: false
  stabilize-pr-branch:
    description: "Branch name for the Stabilize PR when auto prepares it"
    required: false
  stabilize-pr-title:
    description: "Title for the Stabilize PR when auto prepares it"
    required: false
  create-github-release:
    description: "If true, create GitHub releases for new tags when publishing"
    required: false
    default: "false"
  open-discussion:
    description: "Open GitHub Discussion for releases. Either 'true' (all packages), 'false' (none), or a comma-separated list of package names (e.g. 'sampo,sampo-github-action')"
    required: false
    default: "false"
  discussion-category:
    description: "Preferred Discussions category slug (default: 'announcements' if it exists)"
    required: false
  release-assets:
    description: "Comma or newline separated paths/globs for pre-built release assets (optional)"
    required: false
  github-token:
    description: "GitHub token to create/update PRs (defaults to GITHUB_TOKEN env)"
    required: false
  use-local-build:
    description: "If true, build and use the local version instead of installing from crates.io"
    required: false
    default: "false"

outputs:
  released:
    description: "Whether the release step ran successfully"
    value: ${{ steps.run.outputs.released }}
  published:
    description: "Whether the publish step ran successfully"
    value: ${{ steps.run.outputs.published }}

runs:
  using: "composite"
  steps:
    - id: run
      name: Run Sampo
      shell: bash
      env:
        INPUT_COMMAND: ${{ inputs.command }}
        INPUT_DRY_RUN: ${{ inputs['dry-run'] }}
        INPUT_WORKING_DIRECTORY: ${{ inputs['working-directory'] }}
        INPUT_CARGO_TOKEN: ${{ inputs['cargo-token'] }}
        INPUT_ARGS: ${{ inputs.args }}
        INPUT_BASE_BRANCH: ${{ inputs['base-branch'] }}
        INPUT_PR_BRANCH: ${{ inputs['pr-branch'] }}
        INPUT_PR_TITLE: ${{ inputs['pr-title'] }}
        INPUT_STABILIZE_PR_BRANCH: ${{ inputs['stabilize-pr-branch'] }}
        INPUT_STABILIZE_PR_TITLE: ${{ inputs['stabilize-pr-title'] }}
        INPUT_CREATE_GITHUB_RELEASE: ${{ inputs['create-github-release'] }}
        INPUT_OPEN_DISCUSSION: ${{ inputs['open-discussion'] }}
        INPUT_DISCUSSION_CATEGORY: ${{ inputs['discussion-category'] }}
        INPUT_RELEASE_ASSETS: ${{ inputs['release-assets'] }}
        INPUT_GITHUB_TOKEN: ${{ inputs['github-token'] }}
        INPUT_USE_LOCAL_BUILD: ${{ inputs['use-local-build'] }}
      run: |
        set -euo pipefail

        # If an explicit token input is provided, use it
        if [[ -n "${INPUT_GITHUB_TOKEN:-}" ]]; then
          export GITHUB_TOKEN="${INPUT_GITHUB_TOKEN}"
        fi

        # Ensure Rust available
        if ! command -v cargo >/dev/null 2>&1; then
          echo "Installing Rust toolchain..."
          if ! command -v curl >/dev/null 2>&1; then
            if command -v apt-get >/dev/null 2>&1; then
              echo "Installing curl..."
              sudo apt-get update -y
              sudo apt-get install -y curl
            else
              echo "curl is required to install Rust and was not found." >&2
              exit 1
            fi
          fi
          curl https://sh.rustup.rs -sSf | sh -s -- -y
          source "$HOME/.cargo/env"
        fi

        # Install cargo-binstall for faster binary installation
        if ! command -v cargo-binstall >/dev/null 2>&1; then
          echo "Installing cargo-binstall..."
          curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
        fi

        # Install or build sampo-github-action binary
        if [[ "${INPUT_USE_LOCAL_BUILD:-}" == "true" || "${INPUT_USE_LOCAL_BUILD:-}" == "1" ]]; then
          echo "Building local sampo-github-action..."
          if [[ -f "${GITHUB_WORKSPACE}/Cargo.toml" && -d "${GITHUB_WORKSPACE}/crates/sampo-github-action" ]]; then
            echo "Found local sampo repository, building from source..."
            cd "${GITHUB_WORKSPACE}"
            cargo build --release --bin sampo-github-action
            # Add the binary to PATH
            mkdir -p "$HOME/.local/bin"
            cp target/release/sampo-github-action "$HOME/.local/bin/"
            echo "$HOME/.local/bin" >> $GITHUB_PATH
          else
            echo "Local build requested but sampo repository structure not found, falling back to published version..."
            cargo binstall --no-confirm sampo-github-action
          fi
        else
          echo "Installing sampo-github-action..."
          cargo binstall --no-confirm sampo-github-action
        fi

        # Ensure git available (needed for tags and pushing)
        if ! command -v git >/dev/null 2>&1; then
          echo "Installing git..."
          if command -v apt-get >/dev/null 2>&1; then
            sudo apt-get update -y
            sudo apt-get install -y git
          else
            echo "git is required by this action and was not found." >&2
            exit 1
          fi
        fi

        # Determine workspace root
        WORKDIR="${INPUT_WORKING_DIRECTORY:-${GITHUB_WORKSPACE:-.}}"
        echo "Using workspace: ${WORKDIR}"
        if [[ ! -d "${WORKDIR}" ]]; then
          echo "Workspace directory does not exist: ${WORKDIR}" >&2
          exit 1
        fi

        # Compute boolean flags based on explicit true values
        DRY_FLAG=""
        if [[ "${INPUT_DRY_RUN:-}" == "true" || "${INPUT_DRY_RUN:-}" == "1" ]]; then
          DRY_FLAG="--dry-run"
        fi

        CREATE_GH_RELEASE_FLAG=""
        if [[ "${INPUT_CREATE_GITHUB_RELEASE:-}" == "true" || "${INPUT_CREATE_GITHUB_RELEASE:-}" == "1" ]]; then
          CREATE_GH_RELEASE_FLAG="--create-github-release"
        fi

        # Run sampo-github-action binary directly
        cd "${WORKDIR}"
        sampo-github-action \
          --mode "${INPUT_COMMAND}" \
          ${DRY_FLAG} \
          ${INPUT_WORKING_DIRECTORY:+--working-directory "${INPUT_WORKING_DIRECTORY}"} \
          ${INPUT_CARGO_TOKEN:+--cargo-token "${INPUT_CARGO_TOKEN}"} \
          ${INPUT_ARGS:+--args "${INPUT_ARGS}"} \
          ${INPUT_BASE_BRANCH:+--base-branch "${INPUT_BASE_BRANCH}"} \
          ${INPUT_PR_BRANCH:+--pr-branch "${INPUT_PR_BRANCH}"} \
          ${INPUT_PR_TITLE:+--pr-title "${INPUT_PR_TITLE}"} \
          ${CREATE_GH_RELEASE_FLAG}

        # Capture outputs exposed by the binary via GITHUB_OUTPUT
        # (Already written by the binary)

branding:
  icon: "upload-cloud"
  color: "blue"