name: CI

on:
  workflow_dispatch:
  pull_request:
      branches:
      - main
  push:
    branches:
      - main
      - ci/*
    tags:
      - 'v0.[0-9]+.[0-9]+'
      - 'v0.[0-9]+.[0-9]+-beta.[0-9]+'
      - 'v0.[0-9]+.[0-9]+-alpha.[0-9]+'

jobs:
  build:
    strategy:
      fail-fast: false
      matrix:
        target:
            - x86_64-unknown-linux-gnu
            - x86_64-unknown-linux-musl
            - x86_64-apple-darwin
            - aarch64-apple-darwin
            - x86_64-pc-windows-msvc
        include:
          - target: x86_64-unknown-linux-gnu
            os: ubuntu-latest
          - target: x86_64-unknown-linux-musl
            os: ubuntu-latest
          - target: x86_64-apple-darwin
            os: macos-latest
          - target: aarch64-apple-darwin
            os: macos-latest
          - target: x86_64-pc-windows-msvc
            os: windows-latest
    runs-on: ${{ matrix.os }}
    env:
      # emit backtraces on panics.
      RUST_BACKTRACE: 1
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 1
      - name: Get the build metadata
        shell: bash
        run: |
          echo "version=$(grep -m 1 '^version = ' Cargo.toml | cut -f 3 -d ' ' | tr -d \")" >> $GITHUB_ENV
          echo "rust_version=$(grep 'channel' rust-toolchain.toml | sed 's/.*= *\"\(.*\)\"/\1/')" >> $GITHUB_ENV
      - name: Install Rust
        uses: actions-rs/toolchain@v1
        with:
          toolchain: "${{ env.rust_version }}"
          target: ${{ matrix.target }}
          override: true
          profile: minimal
          components: rustfmt, clippy
      - name: Install musl tools
        if: matrix.target == 'x86_64-unknown-linux-musl'
        run: sudo apt-get install -y musl-tools
      - uses: swatinem/rust-cache@v2.9.1

      - name: rust fmt
        uses: actions-rs/cargo@v1
        with:
          command: fmt
          args: --all -- --check
      - name: clippy
        uses: actions-rs/clippy-check@v1
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          args: --all-features

      - name: Build debug
        uses: actions-rs/cargo@v1
        with:
          use-cross: ${{ matrix.usecross }}
          command: build
          args: --verbose --locked --all --target ${{ matrix.target }}

      - name: Build release
        uses: actions-rs/cargo@v1
        with:
          use-cross: ${{ matrix.usecross }}
          command: build
          args: --verbose --locked --all --release --target ${{ matrix.target }}

      - name: Prepare unix archive
        if: matrix.os != 'windows-latest'
        working-directory: target/${{ matrix.target }}/release
        run: |
          strip rblog
          tar czvf ../../../rblog-v${{ env.version }}-${{ matrix.target }}.tar.gz rblog

      - name: Prepare windows archive
        if: matrix.os == 'windows-latest'
        working-directory: target/${{ matrix.target }}/release
        run: |
          strip rblog.exe
          7z a ../../../rblog-v${{ env.version }}-${{ matrix.target }}.zip rblog.exe

      - name: Upload unix artifact
        uses: actions/upload-artifact@v7
        if: matrix.os != 'windows-latest'
        with:
          name: rblog-v${{ env.version }}-${{ matrix.target }}.tar.gz
          path: rblog-v${{ env.version }}-${{ matrix.target }}.tar.gz
          if-no-files-found: error

      - name: Upload windows artifact
        uses: actions/upload-artifact@v7
        if: matrix.os == 'windows-latest'
        with:
          name: rblog-v${{ env.version }}-${{ matrix.target }}.zip
          path: rblog-v${{ env.version }}-${{ matrix.target }}.zip
          if-no-files-found: error

  publish_crate:
    if: startsWith(github.ref, 'refs/tags/')
    needs:
      - build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 1
      - name: Get Rust version
        shell: bash
        run: |
          echo "rust_version=$(grep 'channel' rust-toolchain.toml | sed 's/.*= *\"\(.*\)\"/\1/')" >> $GITHUB_ENV
      - name: Install Rust
        uses: actions-rs/toolchain@v1
        with:
          toolchain: "${{ env.rust_version }}"
          profile: minimal
          override: true
      - name: Login to crates.io
        uses: actions-rs/cargo@v1
        with:
          command: login
          args: ${{ secrets.CRATES_TOKEN }}
      - name: Publish to crates.io
        uses: actions-rs/cargo@v1
        with:
          command: publish

  release:
    if: startsWith(github.ref, 'refs/tags/')
    needs: 
      - publish_crate
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Get the build metadata
        shell: bash
        run: |
          echo "version=$(grep -m 1 '^version = ' Cargo.toml | cut -f 3 -d ' ' | tr -d \")" >> $GITHUB_ENV
      - name: Download x86_64-unknown-linux-gnu.tar.gz
        uses: actions/download-artifact@v8
        with:
          name: rblog-v${{ env.version }}-x86_64-unknown-linux-gnu.tar.gz
          path: .
      - name: Download x86_64-unknown-linux-musl.tar.gz
        uses: actions/download-artifact@v8
        with:
          name: rblog-v${{ env.version }}-x86_64-unknown-linux-musl.tar.gz
          path: .
      - name: Download rblog-x86_64-apple-darwin.tar.gz
        uses: actions/download-artifact@v8
        with:
          name: rblog-v${{ env.version }}-x86_64-apple-darwin.tar.gz
          path: .
      - name: Download rblog-aarch64-apple-darwin.tar.gz
        uses: actions/download-artifact@v8
        with:
          name: rblog-v${{ env.version }}-aarch64-apple-darwin.tar.gz
          path: .
      - name: rblog-x86_64-pc-windows-msvc.zip
        uses: actions/download-artifact@v8
        with:
          name: rblog-v${{ env.version }}-x86_64-pc-windows-msvc.zip
          path: .
      - name: Generate checksums
        run: for file in rblog-*; do openssl dgst -sha256 -r "$file" | awk '{print $1}' > "${file}.sha256"; done
      - name: Create GitHub release
        uses: softprops/action-gh-release@v3
        with:
          files: |
            rblog-v${{ env.version }}-x86_64-unknown-linux-gnu.tar.gz
            rblog-v${{ env.version }}-x86_64-unknown-linux-gnu.tar.gz.sha256
            rblog-v${{ env.version }}-x86_64-unknown-linux-musl.tar.gz
            rblog-v${{ env.version }}-x86_64-unknown-linux-musl.tar.gz.sha256
            rblog-v${{ env.version }}-x86_64-apple-darwin.tar.gz
            rblog-v${{ env.version }}-x86_64-apple-darwin.tar.gz.sha256
            rblog-v${{ env.version }}-aarch64-apple-darwin.tar.gz
            rblog-v${{ env.version }}-aarch64-apple-darwin.tar.gz.sha256
            rblog-v${{ env.version }}-x86_64-pc-windows-msvc.zip
            rblog-v${{ env.version }}-x86_64-pc-windows-msvc.zip.sha256
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  docker:
    needs: 
      - build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Get the build metadata
        shell: bash
        run: |
          echo "version=$(grep -m 1 '^version = ' Cargo.toml | cut -f 3 -d ' ' | tr -d \")" >> $GITHUB_ENV
      - name: Download x86_64-unknown-linux-musl.tar.gz
        uses: actions/download-artifact@v8
        with:
          name: rblog-v${{ env.version }}-x86_64-unknown-linux-musl.tar.gz
          path: .
      - name: Copy rblog binary to docker directory
        run: |
          tar -xvf rblog-v${{ env.version }}-x86_64-unknown-linux-musl.tar.gz
          cp ./rblog ./pkg/docker/rblog
          mkdir ./pkg/docker/data
          cp ./blog.yaml ./pkg/docker/data/
          cp -r ./posts ./pkg/docker/data/
      - name: Log in to Docker Hub
        if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
        uses: docker/login-action@v4.2.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      - name: Build and push nightly docker image
        uses: docker/build-push-action@v7.2.0
        with:
          context: ./pkg/docker
          file: ./pkg/docker/Dockerfile
          platforms: linux/amd64
          push: ${{ github.ref == 'refs/heads/main' }}
          no-cache: true
          tags: ${{ github.ref == 'refs/heads/main' && format('{0}/rblog:nightly', secrets.DOCKERHUB_USERNAME) || 'rblog:ci' }}
      - name: Build and push latest docker image
        uses: docker/build-push-action@v7.2.0
        if: startsWith(github.ref, 'refs/tags/v')
        with:
          context: ./pkg/docker
          file: ./pkg/docker/Dockerfile
          platforms: linux/amd64
          push: true
          no-cache: true
          tags: |
            ${{ secrets.DOCKERHUB_USERNAME }}/rblog:${{ github.ref_name }}
            ${{ secrets.DOCKERHUB_USERNAME }}/rblog:latest
      - name: Docker Hub Description
        if: github.ref == 'refs/heads/main'
        uses: peter-evans/dockerhub-description@v5
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
          repository: prabirshrestha/rblog

  publish_aur_package:
    runs-on: ubuntu-latest
    if: startsWith(github.ref, 'refs/tags/')
    needs:
      - release
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
        with:
          fetch-depth: 1
      - name: Get the build metadata
        shell: bash
        run: |
          echo "PKG_NAME=$(grep -m 1 '^name = ' Cargo.toml | cut -f 3 -d ' ' | tr -d \")" >> $GITHUB_ENV
      - name: Create PKGBUILD
        shell: bash
        run: |
          cd ${GITHUB_WORKSPACE}/packages/aur
          ./genpkgbuild.sh
      - name: Publish Release to AUR
        uses: KSXGitHub/github-actions-deploy-aur@v4.1.3
        with:
          pkgname: ${{ env.PKG_NAME }}-bin
          pkgbuild: packages/aur/PKGBUILD
          commit_username: ${{ secrets.AUR_USERNAME }}
          commit_email: ${{ secrets.AUR_EMAIL }}
          ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
