shellql 0.1.6-beta

A Vim- and tmux-inspired terminal database manager for developers
Documentation
name: Release

on:
  workflow_run:
    workflows: ["CI"]
    types: [completed]
  workflow_dispatch:
    inputs:
      tag:
        description: "Existing release tag to build (e.g. v0.1.2-beta)"
        required: true
        type: string

permissions:
  contents: write

env:
  CARGO_TERM_COLOR: always

jobs:
  prepare:
    name: Prepare release tag
    runs-on: ubuntu-latest
    if: >-
      github.event_name == 'workflow_dispatch' ||
      (
        github.event_name == 'workflow_run' &&
        github.event.workflow_run.conclusion == 'success' &&
        github.event.workflow_run.event == 'push' &&
        github.event.workflow_run.head_branch == 'main' &&
        github.event.workflow_run.actor.login != 'github-actions[bot]'
      )
    outputs:
      release_tag: ${{ steps.prepare.outputs.release_tag }}
      should_release: ${{ steps.prepare.outputs.should_release }}

    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          ref: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_sha || github.sha }}

      - name: Install Rust toolchain
        if: github.event_name == 'workflow_run'
        uses: dtolnay/rust-toolchain@stable

      - name: Cache Cargo dependencies
        if: github.event_name == 'workflow_run'
        uses: Swatinem/rust-cache@v2

      - name: Resolve tag (manual / auto-bump after CI on main)
        id: prepare
        env:
          MANUAL_TAG: ${{ github.event.inputs.tag }}
        shell: bash
        run: |
          set -euo pipefail

          # 1) Manual dispatch path: use provided tag.
          if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then
            if [[ ! "${MANUAL_TAG}" =~ ^v ]]; then
              echo "Manual tag must start with 'v' (got: ${MANUAL_TAG})" >&2
              exit 1
            fi
            echo "release_tag=${MANUAL_TAG}" >> "$GITHUB_OUTPUT"
            echo "should_release=true" >> "$GITHUB_OUTPUT"
            exit 0
          fi

          # 2) CI-success on main path: auto-bump beta patch, commit, tag, push.
          ./scripts/bump-beta.sh

          VERSION="$(awk '
            $0=="[package]" { in_pkg=1; next }
            /^\[/ && $0!="[package]" { in_pkg=0 }
            in_pkg && $1=="version" {
              gsub(/"/, "", $3)
              print $3
              exit
            }
          ' Cargo.toml)"

          if [[ -z "${VERSION}" ]]; then
            echo "Could not read version from Cargo.toml" >&2
            exit 1
          fi

          TAG="v${VERSION}"

          git config user.name "github-actions[bot]"
          git config user.email "41898282+github-actions[bot]@users.noreply.github.com"

          if ! git diff --quiet -- Cargo.toml Cargo.lock; then
            git add Cargo.toml Cargo.lock
            git commit -m "chore(release): bump version to ${VERSION}"
            git push origin HEAD:main
          fi

          if git rev-parse "${TAG}" >/dev/null 2>&1; then
            echo "Tag ${TAG} already exists; skipping tag creation."
          else
            git tag -a "${TAG}" -m "Release ${TAG}"
            git push origin "${TAG}"
          fi

          echo "release_tag=${TAG}" >> "$GITHUB_OUTPUT"
          echo "should_release=true" >> "$GITHUB_OUTPUT"

  build:
    name: Build — ${{ matrix.target }}
    runs-on: ${{ matrix.os }}
    needs: prepare
    if: needs.prepare.outputs.should_release == 'true'

    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            binary_name: shql
            asset_name: shql-linux-x86_64

          - os: macos-14
            target: aarch64-apple-darwin
            binary_name: shql
            asset_name: shql-macos-arm64

          - os: windows-latest
            target: x86_64-pc-windows-msvc
            binary_name: shql.exe
            asset_name: shql-windows-x86_64.exe

    steps:
      - name: Checkout code at release tag
        uses: actions/checkout@v4
        with:
          ref: ${{ needs.prepare.outputs.release_tag }}

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - name: Cache Cargo dependencies
        uses: Swatinem/rust-cache@v2
        with:
          key: ${{ matrix.target }}

      - name: Build release binary
        run: cargo build --release --locked --target ${{ matrix.target }}

      - name: Rename binary (Unix)
        if: matrix.os != 'windows-latest'
        run: |
          cp target/${{ matrix.target }}/release/${{ matrix.binary_name }} ${{ matrix.asset_name }}

      - name: Rename binary (Windows)
        if: matrix.os == 'windows-latest'
        shell: pwsh
        run: |
          Copy-Item "target/${{ matrix.target }}/release/${{ matrix.binary_name }}" "${{ matrix.asset_name }}"

      - name: Upload binary artifact
        uses: actions/upload-artifact@v4
        with:
          name: ${{ matrix.asset_name }}
          path: ${{ matrix.asset_name }}

  release:
    name: Create GitHub Release
    runs-on: ubuntu-latest
    needs: [prepare, build]
    if: needs.prepare.outputs.should_release == 'true'

    steps:
      - name: Download all binaries
        uses: actions/download-artifact@v4
        with:
          path: binaries/
          merge-multiple: true

      - name: Create release and upload binaries
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ needs.prepare.outputs.release_tag }}
          generate_release_notes: true
          prerelease: ${{ contains(needs.prepare.outputs.release_tag, '-beta') }}
          files: binaries/*