🏡 index : quine-global/hyper.git

name: Create Release

on:
  push:
    tags:
      - "v*"
  workflow_dispatch:

concurrency:
  group: release-${{ github.ref }}
  cancel-in-progress: true

env:
  NODE_VERSION: 22.22.2
  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  CSC_LINK: ${{ secrets.MAC_CERT_P12_BASE64 }}
  CSC_KEY_PASSWORD: ${{ secrets.MAC_CERT_P12_PASSWORD }}
  WIN_CSC_LINK: ${{ secrets.WIN_CERT_P12_BASE64 }}
  WIN_CSC_KEY_PASSWORD: ${{ secrets.WIN_CERT_P12_PASSWORD }}
  APPLE_ID: ${{ secrets.APPLE_ID }}
  APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_PASSWORD }}

jobs:
  validate-tag:
    name: Validate Tag Matches package.json
    if: github.ref_type == 'tag'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6.0.3
      - name: Check tag matches package.json version
        run: |
          TAG="${{ github.ref_name }}"
          ROOT_VERSION="v$(jq -r .version package.json)"
          APP_VERSION="v$(jq -r .version app/package.json)"
          FAILED=0
          if [ "$TAG" != "$ROOT_VERSION" ]; then
            echo "Error: tag '$TAG' does not match package.json version '$ROOT_VERSION'"
            FAILED=1
          fi
          if [ "$TAG" != "$APP_VERSION" ]; then
            echo "Error: tag '$TAG' does not match app/package.json version '$APP_VERSION'"
            FAILED=1
          fi
          exit $FAILED

  build:
    name: Build ${{ matrix.name }}
    needs: validate-tag
    if: always() && (needs.validate-tag.result == 'success' || needs.validate-tag.result == 'skipped')
    strategy:
      matrix:
        include:
          - os: ubuntu-latest
            name: Ubuntu
            matrix-name: ubuntu
          - os: macos-latest
            name: macOS
            matrix-name: macos
          - os: windows-latest
            name: Windows
            matrix-name: win
    runs-on: ${{ matrix.os }}
    steps:
      - name: Checkout code
        uses: actions/checkout@v6.0.3

      - name: Build
        uses: ./.github/actions/build
        env:
          NODE_VERSION: ${{ env.NODE_VERSION }}
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          node-version: ${{ env.NODE_VERSION }}
          matrix-os: ${{ matrix.os }}
          matrix-name: ${{ matrix.matrix-name }}
          upload-artifact: true

  # ARM Linux:

  build-linux-armv7l:
    name: Build Linux ARMv7l
    needs: validate-tag
    if: always() && (needs.validate-tag.result == 'success' || needs.validate-tag.result == 'skipped')
    # qemu-user-static, used here and by arm-runner-action, is not packaged on Ubuntu 26.04
    runs-on: ubuntu-24.04
    steps:
      - name: Checkout code
        uses: actions/checkout@v6.0.3

      - name: Set up QEMU and binfmt
        run: |
          # Install qemu-user-static
          sudo apt-get update
          sudo apt-get install -y qemu-user-static binfmt-support python3-setuptools
          
          # Install distutils for node-gyp
          sudo apt-get install -y python3-distutils || sudo apt-get install -y python3-dev python-is-python3

          # Download and install binfmt configurations
          wget https://github.com/qemu/qemu/raw/master/scripts/qemu-binfmt-conf.sh
          chmod +x qemu-binfmt-conf.sh
          sudo ./qemu-binfmt-conf.sh --qemu-path /usr/bin --qemu-suffix -static --debian

          # Import the binfmt configurations
          sudo update-binfmts --import qemu-arm
          sudo update-binfmts --import qemu-aarch64

          # Verify they exist
          ls -la /proc/sys/fs/binfmt_misc/qemu-arm* || true

      - name: Build ARMv7l
        uses: ./.github/actions/build-linux-arm
        env:
          NODE_VERSION: ${{ env.NODE_VERSION }}
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          node-version: ${{ env.NODE_VERSION }}
          matrix-name: armv7l
          matrix-cpu: cortex-a8
          matrix-image: raspios_lite:latest
          upload-artifact: true

  build-linux-arm64:
    name: Build Linux ARM64
    needs: validate-tag
    if: always() && (needs.validate-tag.result == 'success' || needs.validate-tag.result == 'skipped')
    # qemu-user-static, used here and by arm-runner-action, is not packaged on Ubuntu 26.04
    runs-on: ubuntu-24.04
    steps:
      - name: Checkout code
        uses: actions/checkout@v6.0.3

      - name: Set up QEMU and binfmt
        # Needed so flatpak-builder's bwrap sandbox can run aarch64 build
        # commands on this x86_64 runner.
        run: |
          sudo apt-get update
          sudo apt-get install -y qemu-user-static binfmt-support

          wget https://github.com/qemu/qemu/raw/master/scripts/qemu-binfmt-conf.sh
          chmod +x qemu-binfmt-conf.sh
          sudo ./qemu-binfmt-conf.sh --qemu-path /usr/bin --qemu-suffix -static --debian

          sudo update-binfmts --import qemu-aarch64

          ls -la /proc/sys/fs/binfmt_misc/qemu-aarch64* || true

      - name: Build ARM64
        uses: ./.github/actions/build-linux-arm
        env:
          NODE_VERSION: ${{ env.NODE_VERSION }}
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          node-version: ${{ env.NODE_VERSION }}
          matrix-name: arm64
          matrix-cpu: cortex-a53
          matrix-image: raspios_lite_arm64:latest
          upload-artifact: true

  ###

  upload-release:
    name: Upload and Create Release
    needs:
      - build
      - build-linux-armv7l
      - build-linux-arm64
    if: always() && github.ref_type == 'tag' && needs.build.result == 'success' && needs['build-linux-armv7l'].result == 'success' && needs['build-linux-arm64'].result == 'success'
    runs-on: ubuntu-latest
    steps:
      - name: Download all artifacts
        uses: actions/download-artifact@v8.0.1
        with:
          path: ./artifacts

      - name: List downloaded artifacts
        run: ls -R ./artifacts

      - name: Ensure non-empty artifacts
        run: |
          echo "Checking for zero-byte files in artifacts/..."
          find artifacts/ -type f -empty -print -delete
          echo "Cleaned up any zero-byte files."
          echo "Remaining files:"
          ls -R artifacts/

      - name: Dump release assets for debugging
        if: always()
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # GitHub CLI needs this
        run: |
          echo "Fetching release assets for tag: ${{ github.ref_name }}"
          gh release view "${{ github.ref_name }}" --repo "${{ github.repository }}" --json assets --jq '.assets[] | "\(.name) - \(.url)"' || true

      - name: Create GitHub Release
        # TODO Pinned to work around https://github.com/softprops/action-gh-release/issues/445
        uses: softprops/action-gh-release@v3.0.0
        env:
          NODE_VERSION: ${{ env.NODE_VERSION }}
          ACTIONS_STEP_DEBUG: true
        with:
          preserve_order: true
          overwrite: true
          name: Release ${{ github.ref_name }}
          tag_name: ${{ github.ref }}
          token: ${{ secrets.GITHUB_TOKEN }}
          draft: true
          files: |
            artifacts/**/*.dmg
            artifacts/**/*.snap
            artifacts/**/*.AppImage
            artifacts/**/*.deb
            artifacts/**/*.pacman
            artifacts/**/*.rpm
            artifacts/**/*.exe
            artifacts/**/*.flatpak