name: Build
on:
  workflow_dispatch:
    inputs:
      version:
        description: "Tag version to release"
        required: true
  push:
    paths-ignore:
      - "docs/**"
      - "README.md"
      - ".github/ISSUE_TEMPLATE/**"
    branches:
      - Alpha
    tags:
      - "v*"
  pull_request:
    branches:
      - Alpha
concurrency:
  group: "${{ github.workflow }}-${{ github.ref }}"
  cancel-in-progress: true
  
env:
  REGISTRY: docker.io
jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        jobs:
          - { goos: darwin, goarch: amd64, goamd64: v1, output: amd64-compatible } # old style file name will be removed in next released
          - { goos: darwin, goarch: amd64, goamd64: v3, output: amd64 }
          - { goos: darwin, goarch: amd64, goamd64: v1, output: amd64-v1 }
          - { goos: darwin, goarch: amd64, goamd64: v2, output: amd64-v2 }
          - { goos: darwin, goarch: amd64, goamd64: v3, output: amd64-v3 }
          - { goos: darwin, goarch: arm64, output: arm64 }

          - { goos: linux, goarch: '386', go386: sse2, output: '386', debian: i386, rpm: i386}
          - { goos: linux, goarch: '386', go386: softfloat, output: '386-softfloat' }
          - { goos: linux, goarch: amd64, goamd64: v1, output: amd64-compatible} # old style file name will be removed in next released
          - { goos: linux, goarch: amd64, goamd64: v3, output: amd64, debian: amd64, rpm: x86_64, pacman: x86_64}
          - { goos: linux, goarch: amd64, goamd64: v1, output: amd64-v1, debian: amd64, rpm: x86_64, pacman: x86_64, test: test }
          - { goos: linux, goarch: amd64, goamd64: v2, output: amd64-v2, debian: amd64, rpm: x86_64, pacman: x86_64}
          - { goos: linux, goarch: amd64, goamd64: v3, output: amd64-v3, debian: amd64, rpm: x86_64, pacman: x86_64}
          - { goos: linux, goarch: arm64, output: arm64, debian: arm64, rpm: aarch64, pacman: aarch64}  
          - { goos: linux, goarch: arm, goarm: '5', output: armv5 }
          - { goos: linux, goarch: arm, goarm: '6', output: armv6, debian: armel, rpm: armv6hl} 
          - { goos: linux, goarch: arm, goarm: '7', output: armv7, debian: armhf, rpm: armv7hl, pacman: armv7hl}
          - { goos: linux, goarch: mips, gomips: hardfloat, output: mips-hardfloat }
          - { goos: linux, goarch: mips, gomips: softfloat, output: mips-softfloat }
          - { goos: linux, goarch: mipsle, gomips: hardfloat, output: mipsle-hardfloat }
          - { goos: linux, goarch: mipsle, gomips: softfloat, output: mipsle-softfloat }
          - { goos: linux, goarch: mips64, output: mips64 }
          - { goos: linux, goarch: mips64le, output: mips64le, debian: mips64el, rpm: mips64el }
          - { goos: linux, goarch: loong64, output: loong64-abi1, abi: '1', debian: loongarch64, rpm: loongarch64 }
          - { goos: linux, goarch: loong64, output: loong64-abi2, abi: '2', debian: loong64, rpm: loong64 }
          - { goos: linux, goarch: riscv64, output: riscv64, debian: riscv64, rpm: riscv64 }
          - { goos: linux, goarch: s390x, output: s390x, debian: s390x, rpm: s390x }
          - { goos: linux, goarch: ppc64le, output: ppc64le, debian: ppc64el, rpm: ppc64le }

          # Go 1.26 with special patch can work on Windows 7
          # https://github.com/MetaCubeX/go/commits/release-branch.go1.26/
          - { goos: windows, goarch: '386', output: '386' }
          - { goos: windows, goarch: amd64, goamd64: v1, output: amd64-compatible } # old style file name will be removed in next released
          - { goos: windows, goarch: amd64, goamd64: v3, output: amd64 }
          - { goos: windows, goarch: amd64, goamd64: v1, output: amd64-v1 }
          - { goos: windows, goarch: amd64, goamd64: v2, output: amd64-v2 }
          - { goos: windows, goarch: amd64, goamd64: v3, output: amd64-v3 }
          - { goos: windows, goarch: arm64, output: arm64 }

          - { goos: freebsd, goarch: '386', output: '386' }
          - { goos: freebsd, goarch: amd64, goamd64: v1, output: amd64-compatible } # old style file name will be removed in next released
          - { goos: freebsd, goarch: amd64, goamd64: v3, output: amd64 }
          - { goos: freebsd, goarch: amd64, goamd64: v1, output: amd64-v1 }
          - { goos: freebsd, goarch: amd64, goamd64: v2, output: amd64-v2 }
          - { goos: freebsd, goarch: amd64, goamd64: v3, output: amd64-v3 }
          - { goos: freebsd, goarch: arm64, output: arm64 }

          - { goos: android, goarch: '386', ndk: i686-linux-android34, output: '386' }
          - { goos: android, goarch: amd64, ndk: x86_64-linux-android34, output: amd64 }
          - { goos: android, goarch: arm, ndk: armv7a-linux-androideabi34, output: armv7 }
          - { goos: android, goarch: arm64, ndk: aarch64-linux-android34, output: arm64-v8 }

          # Go 1.25 with special patch can work on Windows 7
          # https://github.com/MetaCubeX/go/commits/release-branch.go1.25/
          - { goos: windows, goarch: '386', output: '386-go125', goversion: '1.25' }
          - { goos: windows, goarch: amd64, goamd64: v1, output: amd64-v1-go125, goversion: '1.25' }
          - { goos: windows, goarch: amd64, goamd64: v2, output: amd64-v2-go125, goversion: '1.25' }
          - { goos: windows, goarch: amd64, goamd64: v3, output: amd64-v3-go125, goversion: '1.25' }

          # Go 1.24 with special patch can work on Windows 7
          # https://github.com/MetaCubeX/go/commits/release-branch.go1.24/
          - { goos: windows, goarch: '386', output: '386-go124', goversion: '1.24' }
          - { goos: windows, goarch: amd64, goamd64: v1, output: amd64-v1-go124, goversion: '1.24' }
          - { goos: windows, goarch: amd64, goamd64: v2, output: amd64-v2-go124, goversion: '1.24' }
          - { goos: windows, goarch: amd64, goamd64: v3, output: amd64-v3-go124, goversion: '1.24' }

          # Go 1.23 with special patch can work on Windows 7
          # https://github.com/MetaCubeX/go/commits/release-branch.go1.23/
          - { goos: windows, goarch: '386', output: '386-go123', goversion: '1.23' }
          - { goos: windows, goarch: amd64, goamd64: v1, output: amd64-v1-go123, goversion: '1.23' }
          - { goos: windows, goarch: amd64, goamd64: v2, output: amd64-v2-go123, goversion: '1.23' }
          - { goos: windows, goarch: amd64, goamd64: v3, output: amd64-v3-go123, goversion: '1.23' }

          # Go 1.22 with special patch can work on Windows 7
          # https://github.com/MetaCubeX/go/commits/release-branch.go1.22/
          - { goos: windows, goarch: '386', output: '386-go122', goversion: '1.22' }
          - { goos: windows, goarch: amd64, goamd64: v1, output: amd64-v1-go122, goversion: '1.22' }
          - { goos: windows, goarch: amd64, goamd64: v2, output: amd64-v2-go122, goversion: '1.22' }
          - { goos: windows, goarch: amd64, goamd64: v3, output: amd64-v3-go122, goversion: '1.22' }

          # Go 1.21 can revert commit `9e4385` to work on Windows 7
          # https://github.com/golang/go/issues/64622#issuecomment-1847475161
          # (OR we can just use golang1.21.4 which unneeded any patch)
          - { goos: windows, goarch: '386', output: '386-go121', goversion: '1.21' }
          - { goos: windows, goarch: amd64, goamd64: v1, output: amd64-v1-go121, goversion: '1.21' }
          - { goos: windows, goarch: amd64, goamd64: v2, output: amd64-v2-go121, goversion: '1.21' }
          - { goos: windows, goarch: amd64, goamd64: v3, output: amd64-v3-go121, goversion: '1.21' }

          # Go 1.20 is the last release that will run on any release of Windows 7, 8, Server 2008 and Server 2012. Go 1.21 will require at least Windows 10 or Server 2016.
          - { goos: windows, goarch: '386', output: '386-go120', goversion: '1.20' }
          - { goos: windows, goarch: amd64, goamd64: v1, output: amd64-v1-go120, goversion: '1.20' }
          - { goos: windows, goarch: amd64, goamd64: v2, output: amd64-v2-go120, goversion: '1.20' }
          - { goos: windows, goarch: amd64, goamd64: v3, output: amd64-v3-go120, goversion: '1.20' }

          # Go 1.24 is the last release that will run on macOS 11 Big Sur. Go 1.25 will require macOS 12 Monterey or later.
          - { goos: darwin, goarch: arm64, output: arm64-go124, goversion: '1.24' }
          - { goos: darwin, goarch: amd64, goamd64: v1, output: amd64-v1-go124, goversion: '1.24' }
          - { goos: darwin, goarch: amd64, goamd64: v2, output: amd64-v2-go124, goversion: '1.24' }
          - { goos: darwin, goarch: amd64, goamd64: v3, output: amd64-v3-go124, goversion: '1.24' }

          # Go 1.22 is the last release that will run on macOS 10.15 Catalina. Go 1.23 will require macOS 11 Big Sur or later.
          - { goos: darwin, goarch: arm64, output: arm64-go122, goversion: '1.22' }
          - { goos: darwin, goarch: amd64, goamd64: v1, output: amd64-v1-go122, goversion: '1.22' }
          - { goos: darwin, goarch: amd64, goamd64: v2, output: amd64-v2-go122, goversion: '1.22' }
          - { goos: darwin, goarch: amd64, goamd64: v3, output: amd64-v3-go122, goversion: '1.22' }

          # Go 1.20 is the last release that will run on macOS 10.13 High Sierra or 10.14 Mojave. Go 1.21 will require macOS 10.15 Catalina or later.
          - { goos: darwin, goarch: arm64, output: arm64-go120, goversion: '1.20' }
          - { goos: darwin, goarch: amd64, goamd64: v1, output: amd64-v1-go120, goversion: '1.20' }
          - { goos: darwin, goarch: amd64, goamd64: v2, output: amd64-v2-go120, goversion: '1.20' }
          - { goos: darwin, goarch: amd64, goamd64: v3, output: amd64-v3-go120, goversion: '1.20' }

          # Go 1.23 is the last release that requires Linux kernel version 2.6.32 or later. Go 1.24 will require Linux kernel version 3.2 or later.
          - { goos: linux, goarch: '386', output: '386-go123', goversion: '1.23' }
          - { goos: linux, goarch: amd64, goamd64: v1, output: amd64-v1-go123, goversion: '1.23', test: test }
          - { goos: linux, goarch: amd64, goamd64: v2, output: amd64-v2-go123, goversion: '1.23' }
          - { goos: linux, goarch: amd64, goamd64: v3, output: amd64-v3-go123, goversion: '1.23' }

          # only for test
          - { goos: linux, goarch: '386', output: '386-go120', goversion: '1.20' }
          - { goos: linux, goarch: amd64, goamd64: v1, output: amd64-v1-go120, goversion: '1.20', test: test }
          - { goos: linux, goarch: amd64, goamd64: v2, output: amd64-v2-go120, goversion: '1.20' }
          - { goos: linux, goarch: amd64, goamd64: v3, output: amd64-v3-go120, goversion: '1.20' }

    steps:
    - uses: actions/checkout@v5

    - name: Set up Go
      if: ${{ matrix.jobs.goversion == '' && matrix.jobs.abi != '1' }}
      uses: actions/setup-go@v6
      with:
        go-version: '1.26'
        check-latest: true # Always check for the latest patch release

    - name: Set up Go
      if: ${{ matrix.jobs.goversion != '' && matrix.jobs.abi != '1' }}
      uses: actions/setup-go@v6
      with:
        go-version: ${{ matrix.jobs.goversion }}
        check-latest: true # Always check for the latest patch release

    - name: Set up Go1.26 loongarch abi1
      if: ${{ matrix.jobs.goarch == 'loong64' && matrix.jobs.abi == '1' }}
      run: |
        wget -q https://github.com/MetaCubeX/loongarch64-golang/releases/download/1.26.0/go1.26.0.linux-amd64-abi1.tar.gz
        mkdir -p $HOME/usr/local
        tar zxf go1.26.0.linux-amd64-abi1.tar.gz -C $HOME/usr/local
        echo "$HOME/usr/local/go/bin" >> $GITHUB_PATH

      # TODO: remove after CL747663 merged, see: https://github.com/golang/go/issues/77731
    - name: Apply CL747663 for Golang1.26
      if: ${{ matrix.jobs.goversion == '' }}
      run: |
        cd $(go env GOROOT)
        patch --verbose -p 1 < $GITHUB_WORKSPACE/.github/patch/cl747663.patch

      # this patch file only works on golang1.26.x
      # that means after golang1.27 release it must be changed
      # see: https://github.com/MetaCubeX/go/commits/release-branch.go1.26/
      # revert:
      # 693def151adff1af707d82d28f55dba81ceb08e1: "crypto/rand,runtime: switch RtlGenRandom for ProcessPrng"
      # 7c1157f9544922e96945196b47b95664b1e39108: "net: remove sysSocket fallback for Windows 7"
      # 48042aa09c2f878c4faa576948b07fe625c4707a: "syscall: remove Windows 7 console handle workaround"
      # a17d959debdb04cd550016a3501dd09d50cd62e7: "runtime: always use LoadLibraryEx to load system libraries"
      # f0894a00f4b756d4b9b4078af2e686b359493583: "os: remove 5ms sleep on Windows in (*Process).Wait"
      # sepical fix:
      # - os.RemoveAll not working on Windows7
    - name: Revert Golang1.26 commit for Windows7/8
      if: ${{ matrix.jobs.goos == 'windows' && matrix.jobs.goversion == '' }}
      run: |
        cd $(go env GOROOT)
        patch --verbose -p 1 < $GITHUB_WORKSPACE/.github/patch/go1.26.patch

      # this patch file only works on golang1.25.x
      # that means after golang1.26 release it must be changed
      # see: https://github.com/MetaCubeX/go/commits/release-branch.go1.25/
      # revert:
      # 693def151adff1af707d82d28f55dba81ceb08e1: "crypto/rand,runtime: switch RtlGenRandom for ProcessPrng"
      # 7c1157f9544922e96945196b47b95664b1e39108: "net: remove sysSocket fallback for Windows 7"
      # 48042aa09c2f878c4faa576948b07fe625c4707a: "syscall: remove Windows 7 console handle workaround"
      # a17d959debdb04cd550016a3501dd09d50cd62e7: "runtime: always use LoadLibraryEx to load system libraries"
      # f0894a00f4b756d4b9b4078af2e686b359493583: "os: remove 5ms sleep on Windows in (*Process).Wait"
      # sepical fix:
      # - os.RemoveAll not working on Windows7
    - name: Revert Golang1.25 commit for Windows7/8
      if: ${{ matrix.jobs.goos == 'windows' && matrix.jobs.goversion == '1.25' }}
      run: |
        cd $(go env GOROOT)
        patch --verbose -p 1 < $GITHUB_WORKSPACE/.github/patch/go1.25.patch

      # this patch file only works on golang1.24.x
      # that means after golang1.25 release it must be changed
      # see: https://github.com/MetaCubeX/go/commits/release-branch.go1.24/
      # revert:
      # 693def151adff1af707d82d28f55dba81ceb08e1: "crypto/rand,runtime: switch RtlGenRandom for ProcessPrng"
      # 7c1157f9544922e96945196b47b95664b1e39108: "net: remove sysSocket fallback for Windows 7"
      # 48042aa09c2f878c4faa576948b07fe625c4707a: "syscall: remove Windows 7 console handle workaround"
      # a17d959debdb04cd550016a3501dd09d50cd62e7: "runtime: always use LoadLibraryEx to load system libraries"
    - name: Revert Golang1.24 commit for Windows7/8
      if: ${{ matrix.jobs.goos == 'windows' && matrix.jobs.goversion == '1.24' }}
      run: |
        cd $(go env GOROOT)
        patch --verbose -p 1 < $GITHUB_WORKSPACE/.github/patch/go1.24.patch

      # this patch file only works on golang1.23.x
      # that means after golang1.24 release it must be changed
      # see: https://github.com/MetaCubeX/go/commits/release-branch.go1.23/
      # revert:
      # 693def151adff1af707d82d28f55dba81ceb08e1: "crypto/rand,runtime: switch RtlGenRandom for ProcessPrng"
      # 7c1157f9544922e96945196b47b95664b1e39108: "net: remove sysSocket fallback for Windows 7"
      # 48042aa09c2f878c4faa576948b07fe625c4707a: "syscall: remove Windows 7 console handle workaround"
      # a17d959debdb04cd550016a3501dd09d50cd62e7: "runtime: always use LoadLibraryEx to load system libraries"
    - name: Revert Golang1.23 commit for Windows7/8
      if: ${{ matrix.jobs.goos == 'windows' && matrix.jobs.goversion == '1.23' }}
      run: |
        cd $(go env GOROOT)
        patch --verbose -p 1 < $GITHUB_WORKSPACE/.github/patch/go1.23.patch

      # this patch file only works on golang1.22.x
      # that means after golang1.23 release it must be changed
      # see: https://github.com/MetaCubeX/go/commits/release-branch.go1.22/
      # revert:
      # 693def151adff1af707d82d28f55dba81ceb08e1: "crypto/rand,runtime: switch RtlGenRandom for ProcessPrng"
      # 7c1157f9544922e96945196b47b95664b1e39108: "net: remove sysSocket fallback for Windows 7"
      # 48042aa09c2f878c4faa576948b07fe625c4707a: "syscall: remove Windows 7 console handle workaround"
      # a17d959debdb04cd550016a3501dd09d50cd62e7: "runtime: always use LoadLibraryEx to load system libraries"
    - name: Revert Golang1.22 commit for Windows7/8
      if: ${{ matrix.jobs.goos == 'windows' && matrix.jobs.goversion == '1.22' }}
      run: |
        cd $(go env GOROOT)
        patch --verbose -p 1 < $GITHUB_WORKSPACE/.github/patch/go1.22.patch

      # modify from https://github.com/restic/restic/issues/4636#issuecomment-1896455557
    - name: Revert Golang1.21 commit for Windows7/8
      if: ${{ matrix.jobs.goos == 'windows' && matrix.jobs.goversion == '1.21' }}
      run: |
        cd $(go env GOROOT)
        patch --verbose -p 1 < $GITHUB_WORKSPACE/.github/patch/go1.21.patch

    - name: Set variables
      run: |
        VERSION="${GITHUB_REF_NAME,,}-$(git rev-parse --short HEAD)"
        VERSION="${VERSION//\//-}"
        PackageVersion="$(curl -s "https://api.github.com/repos/MetaCubeX/mihomo/releases/latest" | jq -r '.tag_name' | sed 's/v//g' | awk -F '.' '{$NF = $NF + 1; print}' OFS='.').${VERSION/-/.}"
        if [ -n "${{ github.event.inputs.version }}" ]; then
          VERSION=${{ github.event.inputs.version }}
          PackageVersion="${VERSION#v}"
        fi
        echo "VERSION=${VERSION}" >> $GITHUB_ENV
        echo "PackageVersion=${PackageVersion}" >> $GITHUB_ENV
      
        echo "BUILDTIME=$(date)" >> $GITHUB_ENV
        echo "CGO_ENABLED=0" >> $GITHUB_ENV
        echo "BUILDTAG=-extldflags --static" >> $GITHUB_ENV
        echo "GOTOOLCHAIN=local" >> $GITHUB_ENV

    - name: Setup NDK
      if: ${{ matrix.jobs.goos == 'android' }}
      uses: nttld/setup-ndk@v1
      id: setup-ndk
      with:
        ndk-version: r29-beta1

    - name: Set NDK path
      if: ${{ matrix.jobs.goos == 'android' }}
      run: |
        echo "CC=${{steps.setup-ndk.outputs.ndk-path}}/toolchains/llvm/prebuilt/linux-x86_64/bin/${{matrix.jobs.ndk}}-clang" >> $GITHUB_ENV
        echo "CGO_ENABLED=1" >> $GITHUB_ENV
        echo "BUILDTAG=" >> $GITHUB_ENV

    - name: Test
      if: ${{ matrix.jobs.test == 'test' }}
      run: |
        go test ./...
        echo "---test with_gvisor---"
        go test ./... -tags "with_gvisor" -count=1

    - name: Update CA
      run: |
        sudo apt-get update && sudo apt-get install ca-certificates
        sudo update-ca-certificates
        cp -f /etc/ssl/certs/ca-certificates.crt component/ca/ca-certificates.crt

    - name: Build core
      env:
        GOOS: ${{matrix.jobs.goos}}
        GOARCH: ${{matrix.jobs.goarch}}
        GOAMD64: ${{matrix.jobs.goamd64}}
        GO386: ${{matrix.jobs.go386}}
        GOARM: ${{matrix.jobs.goarm}}
        GOMIPS: ${{matrix.jobs.gomips}}
      run: |
        go env
        go build -v -tags "with_gvisor" -trimpath -ldflags "${BUILDTAG} -X 'github.com/metacubex/mihomo/constant.Version=${VERSION}' -X 'github.com/metacubex/mihomo/constant.BuildTime=${BUILDTIME}' -w -s -buildid="
        if [ "${{matrix.jobs.goos}}" = "windows" ]; then
          cp mihomo.exe mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}.exe
          zip -r mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}.zip mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}.exe
        else
          cp mihomo mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}
          gzip -c mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}} > mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}.gz
          rm mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}
        fi

    - name: Package DEB
      if: matrix.jobs.debian != ''
      run: |
        set -xeuo pipefail
        sudo gem install fpm
        cp .github/release/.fpm_systemd .fpm

        fpm -t deb \
          -v "${PackageVersion}" \
          -p "mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}.deb" \
          --architecture ${{ matrix.jobs.debian }} \
          mihomo=/usr/bin/mihomo

    - name: Package RPM
      if: matrix.jobs.rpm != ''
      run: |
        set -xeuo pipefail
        sudo gem install fpm
        cp .github/release/.fpm_systemd .fpm

        fpm -t rpm \
          -v "${PackageVersion}" \
          -p "mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}.rpm" \
          --architecture ${{ matrix.jobs.rpm }} \
          mihomo=/usr/bin/mihomo

    - name: Package Pacman
      if: matrix.jobs.pacman != ''
      run: |
        set -xeuo pipefail
        sudo gem install fpm
        sudo apt-get update && sudo apt-get install -y libarchive-tools
        cp .github/release/.fpm_systemd .fpm

        fpm -t pacman \
          -v "${PackageVersion}" \
          -p "mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}.pkg.tar.zst" \
          --architecture ${{ matrix.jobs.pacman }} \
          mihomo=/usr/bin/mihomo

    - name: Save version
      run: |
        echo ${VERSION} > version.txt
      shell: bash

    - name: Archive production artifacts
      uses: actions/upload-artifact@v4
      with:
        name: "${{ matrix.jobs.goos }}-${{ matrix.jobs.output }}"
        path: |
          mihomo*.gz
          mihomo*.deb
          mihomo*.rpm
          mihomo*.pkg.tar.zst
          mihomo*.zip
          version.txt
          checksums.txt

  Upload-Prerelease:
    permissions: write-all
    if: ${{ github.event_name != 'workflow_dispatch' && github.ref_type == 'branch' && !startsWith(github.event_name, 'pull_request') }}
    needs: [build]
    runs-on: ubuntu-latest
    steps:
    - name: Download all workflow run artifacts
      uses: actions/download-artifact@v4
      with:
        path: bin/
        merge-multiple: true

    - name: Calculate checksums
      run: |
        cd bin/
        find . -type f -not -name "checksums.*" -not -name "version.txt" | sort | xargs sha256sum > checksums.txt
        cat checksums.txt
      shell: bash

    - name: Delete current release assets
      uses: 8Mi-Tech/delete-release-assets-action@main
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        tag: Prerelease-${{ github.ref_name }}
        deleteOnlyFromDrafts: false
    - name: Set Env
      run: |
        echo "BUILDTIME=$(TZ=Asia/Shanghai date)" >> $GITHUB_ENV
      shell: bash

    - name: Tag Repo
      uses: richardsimko/update-tag@v1
      with:
        tag_name: Prerelease-${{ github.ref_name }}
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      
    - run: |
        cat > release.txt << 'EOF'
        Release created at  ${{ env.BUILDTIME }}
        Synchronize ${{ github.ref_name }} branch code updates, keeping only the latest version
        <br>
        [我应该下载哪个文件? / Which file should I download?](https://github.com/MetaCubeX/mihomo/wiki/FAQ)
        [二进制文件筛选 / Binary file selector](https://metacubex.github.io/Meta-Docs/startup/#_1)
        [查看文档 / Docs](https://metacubex.github.io/Meta-Docs/)
        EOF

    - name: Upload Prerelease
      uses: softprops/action-gh-release@v1
      if: ${{  success() }}
      with:
        tag_name: Prerelease-${{ github.ref_name }}
        files: |
          bin/*
        prerelease: true
        generate_release_notes: true
        body_path: release.txt

  Upload-Release:
    permissions: write-all
    if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version != '' }}
    needs: [build]
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v5
        with:
          ref: Meta
          fetch-depth: '0'
          fetch-tags: 'true'

      - name: Get tags
        run: |
          echo "CURRENTVERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
          git fetch --tags
          echo "PREVERSION=$(git describe --tags --abbrev=0 HEAD)" >> $GITHUB_ENV

      - name: Force push Alpha branch to Meta
        run: |
          git config --global user.email "github-actions[bot]@users.noreply.github.com"
          git config --global user.name "github-actions[bot]"
          git fetch origin Alpha:Alpha
          git push origin Alpha:Meta --force
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Tag the commit on Alpha
        run: |
          git checkout Alpha 
          git tag ${{ github.event.inputs.version }}
          git push origin ${{ github.event.inputs.version }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Generate release notes
        run: |
            cp ./.github/genReleaseNote.sh ./
            bash ./genReleaseNote.sh -v ${PREVERSION}...${CURRENTVERSION}
            rm ./genReleaseNote.sh
  
      - uses: actions/download-artifact@v4
        with:
          path: bin/
          merge-multiple: true
  
      - name: Display structure of downloaded files
        run: ls -R
        working-directory: bin
  
      - name: Upload Release
        uses: softprops/action-gh-release@v2
        if: ${{ success() }}
        with:
          tag_name: ${{ github.event.inputs.version }}
          files: bin/*
          body_path: release.md

  Docker:
    if: ${{ !startsWith(github.event_name, 'pull_request') }}
    permissions: write-all
    needs: [build]
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v5
        with:
          fetch-depth: 0

      - uses: actions/download-artifact@v4
        with:
          path: bin/
          merge-multiple: true

      - name: Display structure of downloaded files
        run: ls -R
        working-directory: bin

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Setup Docker buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: latest
      
      # Extract metadata (tags, labels) for Docker
      # https://github.com/docker/metadata-action
      - name: Extract Docker metadata
        if: ${{ github.event_name != 'workflow_dispatch' }}
        id: meta_alpha
        uses: docker/metadata-action@v5
        with:
          images: '${{ env.REGISTRY }}/${{ github.repository }}'
      
      # Extract metadata (tags, labels) for Docker
      # https://github.com/docker/metadata-action
      - name: Extract Docker metadata
        if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version != '' }}
        id: meta_release
        uses: docker/metadata-action@v5
        with:
          images: '${{ env.REGISTRY }}/${{ github.repository }}'
          tags: |
            ${{ github.event.inputs.version }}
          flavor: |
            latest=true
          labels: org.opencontainers.image.version=${{ github.event.inputs.version }}
      
      - name: Show files
        run: |
          ls .
          ls bin/
      
      - name: login to docker REGISTRY
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ secrets.DOCKER_HUB_USER }}
          password: ${{ secrets.DOCKER_HUB_TOKEN }}

      # Build and push Docker image with Buildx (don't push on PR)
      # https://github.com/docker/build-push-action
      - name: Build and push Docker image
        if: ${{ github.event_name != 'workflow_dispatch' }}
        uses: docker/build-push-action@v5
        with:
          context: .
          file: ./Dockerfile
          push: ${{ github.event_name != 'pull_request' }}
          platforms: |
            linux/386
            linux/amd64
            linux/arm64
            linux/arm/v7
          tags: ${{ steps.meta_alpha.outputs.tags }}
          labels: ${{ steps.meta_alpha.outputs.labels }}
      
      - name: Build and push Docker image
        if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version != '' }}
        uses: docker/build-push-action@v5
        with:
          context: .
          file: ./Dockerfile
          push: ${{ github.event_name != 'pull_request' }}
          platforms: |
            linux/386
            linux/amd64
            linux/arm64
            linux/arm/v7
          tags: ${{ steps.meta_release.outputs.tags }}
          labels: ${{ steps.meta_release.outputs.labels }}