name: EasyTier Core

on:
  push:
    branches: ["develop", "main"]
  pull_request:
    branches: ["develop", "main"]

env:
  CARGO_TERM_COLOR: always

defaults:
  run:
    # necessary for windows
    shell: bash

jobs:
  pre_job:
    # continue-on-error: true # Uncomment once integration is finished
    runs-on: ubuntu-latest
    # Map a step output to a job output
    outputs:
      should_skip: ${{ steps.skip_check.outputs.should_skip }}
    steps:
      - id: skip_check
        uses: fkirc/skip-duplicate-actions@v5
        with:
          # All of these options are optional, so you can remove them if you are happy with the defaults
          concurrent_skipping: 'never'
          skip_after_successful_duplicate: 'true'
          paths: '["Cargo.toml", "Cargo.lock", "easytier/**", ".github/workflows/core.yml"]'
  build:
    strategy:
      fail-fast: false
      matrix:
        include:
          - TARGET: aarch64-unknown-linux-musl
            OS: ubuntu-latest
          - TARGET: x86_64-unknown-linux-musl
            OS: ubuntu-latest
          - TARGET: mips-unknown-linux-musl
            OS: ubuntu-latest
          - TARGET: mipsel-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

          - TARGET: armv7-unknown-linux-musleabihf # raspberry pi 2-3-4, not tested
            OS: ubuntu-latest
          - TARGET: armv7-unknown-linux-musleabi # raspberry pi 2-3-4, not tested
            OS: ubuntu-latest
          - TARGET: arm-unknown-linux-musleabihf # raspberry pi 0-1, not tested
            OS: ubuntu-latest
          - TARGET: arm-unknown-linux-musleabi # raspberry pi 0-1, not tested
            OS: ubuntu-latest
    runs-on: ${{ matrix.OS }}
    env:
      NAME: easytier
      TARGET: ${{ matrix.TARGET }}
      OS: ${{ matrix.OS }}
      OSS_BUCKET: ${{ secrets.ALIYUN_OSS_BUCKET }}
    needs: pre_job
    if: needs.pre_job.outputs.should_skip != 'true'
    steps:
      - uses: actions/checkout@v3

      - uses: actions/setup-node@v4
        with:
          node-version: 21

      - name: Cargo cache
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo
            ./target
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

      - name: Install rust target
        run: bash ./.github/workflows/install_rust.sh

      - name: Setup protoc
        uses: arduino/setup-protoc@v2
        with:
          # GitHub repo token to use to avoid rate limiter
          repo-token: ${{ secrets.GITHUB_TOKEN }}

      - name: Build Core & Cli
        run: |
          if [[ $OS =~ ^ubuntu.*$ && $TARGET =~ ^mips.*$ ]]; then
            cargo +nightly build -r --verbose --target $TARGET -Z build-std=std,panic_abort --no-default-features --features mips
          else
            cargo build --release --verbose --target $TARGET
          fi

      - name: Install UPX
        if: ${{ matrix.OS != 'macos-latest' }}
        uses: crazy-max/ghaction-upx@v3
        with:
          version: latest
          install-only: true

      - name: Compress
        run: |
          mkdir -p ./artifacts/objects/
          # windows is the only OS using a different convention for executable file name
          if [[ $OS =~ ^windows.*$ ]]; then
              SUFFIX=.exe
              cp easytier/third_party/Packet.dll ./artifacts/objects/
              cp easytier/third_party/wintun.dll ./artifacts/objects/
          fi
          if [[ $GITHUB_REF_TYPE =~ ^tag$ ]]; then
            TAG=$GITHUB_REF_NAME
          else
            TAG=$GITHUB_SHA
          fi

          if [[ ! $OS =~ ^macos.*$ ]]; then
            upx --lzma --best ./target/$TARGET/release/easytier-core"$SUFFIX"
            upx --lzma --best ./target/$TARGET/release/easytier-cli"$SUFFIX"
          fi

          mv ./target/$TARGET/release/easytier-core"$SUFFIX" ./artifacts/objects/
          mv ./target/$TARGET/release/easytier-cli"$SUFFIX" ./artifacts/objects/

          tar -cvf ./artifacts/$NAME-$TARGET-$TAG.tar -C ./artifacts/objects/ .
          rm -rf ./artifacts/objects/

      - name: Archive artifact
        uses: actions/upload-artifact@v4
        with:
          name: easytier-${{ matrix.OS }}-${{ matrix.TARGET }}
          path: |
            ./artifacts/*

      - name: Upload OSS
        if: ${{ env.OSS_BUCKET != '' }}
        uses: Menci/upload-to-oss@main
        with:
          access-key-id: ${{ secrets.ALIYUN_OSS_ACCESS_ID }}
          access-key-secret: ${{ secrets.ALIYUN_OSS_ACCESS_KEY }}
          endpoint: ${{ secrets.ALIYUN_OSS_ENDPOINT }}
          bucket: ${{ secrets.ALIYUN_OSS_BUCKET }}
          local-path: ./artifacts/
          remote-path: /easytier-releases/${{ github.sha }}/
          no-delete-remote-files: true
          retry: 5
  core-result:
    if: needs.pre_job.outputs.should_skip != 'true' && always()
    runs-on: ubuntu-latest
    needs:
      - pre_job
      - build
    steps:
      - name: Mark result as failed
        if: needs.build.result != 'success'
        run: exit 1
