hashcards 0.2.1

A plain text-based spaced repetition system.
name: Release

on:
  workflow_dispatch:

permissions:
  contents: write

jobs:
  create-release:
    runs-on: ubuntu-latest
    outputs:
      # The version of the new release.
      version: ${{ steps.parse.outputs.version }}
    steps:
      - name: checkout
        uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

      - name: verify Cargo.toml version matches changelog
        run: |
          CHANGELOG_VERSION=$(python release.py version)
          CARGO_VERSION=$(grep '^version = ' Cargo.toml | head -n1 | sed 's/version = "\(.*\)"/\1/')

          echo "CHANGELOG.xml version: $CHANGELOG_VERSION"
          echo "Cargo.toml version: $CARGO_VERSION"

          if [ "$CHANGELOG_VERSION" != "$CARGO_VERSION" ]; then
            echo "❌ Version mismatch!"
            echo "Update Cargo.toml to version $CHANGELOG_VERSION before releasing"
            exit 1
          fi

          echo "✅ Versions match"

      - name: parse release version from CHANGELOG.xml
        id: parse
        run: |
          VERSION=$(python release.py version)
          echo "Found version: $VERSION"
          echo "version=$VERSION" >> $GITHUB_OUTPUT

      - name: parse release notes from CHANGELOG.xml
        run: |
          python release.py markdown > release-notes.md

      - name: check if tag exists
        run: |
          if git rev-parse "v${{ steps.parse.outputs.version }}" >/dev/null 2>&1; then
            echo "Tag v${{ steps.parse.outputs.version }} already exists!"
            exit 1
          fi

      - name: check if release exists
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          VERSION="v${{ steps.parse.outputs.version }}"

          # Check if GitHub release exists (including drafts)
          if gh release view "$VERSION" >/dev/null 2>&1; then
            echo "❌ GitHub release $VERSION already exists!"
            echo "Delete it first: gh release delete $VERSION"
            exit 1
          fi

          echo "✅ No conflicts found"

      - name: create release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          gh release create "v${{ steps.parse.outputs.version }}" \
            --title "v${{ steps.parse.outputs.version }}" \
            --notes-file release-notes.md \
            --draft

  build:
    needs: create-release
    strategy:
      matrix:
        include:
          - name: linux-amd64
            os: ubuntu-latest
            target: x86_64-unknown-linux-gnu

          - name: macos-arm64
            os: macos-latest
            target: aarch64-apple-darwin

    runs-on: ${{ matrix.os }}
    steps:
      - name: checkout
        uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

      - name: use rust nightly
        uses: dtolnay/rust-toolchain@55d80eb3c5a4228eec5390a083c092095115c6f1 # nightly
        with:
          toolchain: nightly
          targets: ${{ matrix.target }}

      - name: install cross-compilation tools
        if: matrix.os == 'ubuntu-latest'
        run: |
          sudo apt-get update
          sudo apt-get install -y musl-tools
          if [ "${{ matrix.target }}" = "aarch64-unknown-linux-gnu" ]; then
            sudo apt-get install -y gcc-aarch64-linux-gnu
          fi

      - name: cargo fetch
        run: cargo fetch --target ${{ matrix.target }}

      - name: download katex fonts
        run: make

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

      - name: package
        shell: bash
        run: |
          ARCHIVE_NAME="hashcards-v${{ needs.create-release.outputs.version }}-${{ matrix.name }}"
          BINARY_PATH="target/${{ matrix.target }}/release/hashcards"

          # Check: does the binary exist?
          if [ ! -f "${BINARY_PATH}" ]; then
            echo "❌ Binary not found at ${BINARY_PATH}"
            exit 1
          fi

          mkdir -p "${ARCHIVE_NAME}"
          cp "${BINARY_PATH}" "${ARCHIVE_NAME}/hashcards"
          tar czf "${ARCHIVE_NAME}.tar.gz" "${ARCHIVE_NAME}"
          rm -rf "${ARCHIVE_NAME}"

          echo "asset=${ARCHIVE_NAME}.tar.gz" >> $GITHUB_ENV

      - name: upload to release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          gh release upload "v${{ needs.create-release.outputs.version }}" "${{ env.asset }}"

  publish:
    needs:
      - create-release
      - build
    runs-on: ubuntu-latest
    steps:
      - name: checkout
        uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

      - name: publish release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          gh release edit "v${{ needs.create-release.outputs.version }}" --draft=false
          echo "✅ Release v${{ needs.create-release.outputs.version }} published!"