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_target: 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: arm64, output: arm64 } - { goos: darwin, goarch: amd64, goamd64: v1, output: amd64-compatible } - { goos: darwin, goarch: amd64, goamd64: v3, output: amd64 } - { goos: linux, goarch: '386', output: '386' } - { goos: linux, goarch: amd64, goamd64: v1, output: amd64-compatible, test: test } - { goos: linux, goarch: amd64, goamd64: v3, output: amd64 } - { goos: linux, goarch: arm64, output: arm64 } - { goos: linux, goarch: arm, goarm: '5', output: armv5 } - { goos: linux, goarch: arm, goarm: '6', output: armv6 } - { goos: linux, goarch: arm, goarm: '7', output: armv7 } - { 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 } - { goos: linux, goarch: loong64, output: loong64-abi1, abi: '1' } - { goos: linux, goarch: loong64, output: loong64-abi2, abi: '2' } - { goos: linux, goarch: riscv64, output: riscv64 } - { goos: linux, goarch: s390x, output: s390x } - { goos: windows, goarch: '386', output: '386' } - { goos: windows, goarch: amd64, goamd64: v1, output: amd64-compatible } - { goos: windows, goarch: amd64, goamd64: v3, output: amd64 } - { goos: windows, goarch: arm, goarm: '7', output: armv7 } - { goos: windows, goarch: arm64, output: arm64 } - { goos: freebsd, goarch: '386', output: '386' } - { goos: freebsd, goarch: amd64, goamd64: v1, output: amd64-compatible } - { goos: freebsd, goarch: amd64, goamd64: v3, output: amd64 } - { 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.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-compatible-go122, goversion: '1.22' } - { goos: windows, goarch: amd64, goamd64: v3, output: amd64-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-compatible-go121, goversion: '1.21' } - { goos: windows, goarch: amd64, goamd64: v3, output: amd64-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-compatible-go120, goversion: '1.20' } - { goos: windows, goarch: amd64, goamd64: v3, output: amd64-go120, goversion: '1.20' } # 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-compatible-go122, goversion: '1.22' } - { goos: darwin, goarch: amd64, goamd64: v3, output: amd64-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-compatible-go120, goversion: '1.20' } - { goos: darwin, goarch: amd64, goamd64: v3, output: amd64-go120, goversion: '1.20' } # only for test - { goos: linux, goarch: '386', output: '386-go120', goversion: '1.20' } - { goos: linux, goarch: amd64, goamd64: v1, output: amd64-compatible-go120, goversion: '1.20', test: test } - { goos: linux, goarch: amd64, goamd64: v3, output: amd64-go120, goversion: '1.20' } steps: - uses: actions/checkout@v4 - name: Set up Go if: ${{ matrix.jobs.goversion == '' && matrix.jobs.goarch != 'loong64' }} uses: actions/setup-go@v5 with: go-version: '1.23' - name: Set up Go if: ${{ matrix.jobs.goversion != '' && matrix.jobs.goarch != 'loong64' }} uses: actions/setup-go@v5 with: go-version: ${{ matrix.jobs.goversion }} - name: Set up Go1.22 loongarch abi1 if: ${{ matrix.jobs.goarch == 'loong64' && matrix.jobs.abi == '1' }} run: | wget -q https://github.com/MetaCubeX/loongarch64-golang/releases/download/1.22.4/go1.22.4.linux-amd64-abi1.tar.gz sudo tar zxf go1.22.4.linux-amd64-abi1.tar.gz -C /usr/local echo "/usr/local/go/bin" >> $GITHUB_PATH - name: Set up Go1.22 loongarch abi2 if: ${{ matrix.jobs.goarch == 'loong64' && matrix.jobs.abi == '2' }} run: | wget -q https://github.com/MetaCubeX/loongarch64-golang/releases/download/1.22.4/go1.22.4.linux-amd64-abi2.tar.gz sudo tar zxf go1.22.4.linux-amd64-abi2.tar.gz -C /usr/local echo "/usr/local/go/bin" >> $GITHUB_PATH # modify from https://github.com/restic/restic/issues/4636#issuecomment-1896455557 # 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 == '' }} run: | cd $(go env GOROOT) curl https://github.com/MetaCubeX/go/commit/9ac42137ef6730e8b7daca016ece831297a1d75b.diff | patch --verbose -p 1 curl https://github.com/MetaCubeX/go/commit/21290de8a4c91408de7c2b5b68757b1e90af49dd.diff | patch --verbose -p 1 curl https://github.com/MetaCubeX/go/commit/6a31d3fa8e47ddabc10bd97bff10d9a85f4cfb76.diff | patch --verbose -p 1 curl https://github.com/MetaCubeX/go/commit/69e2eed6dd0f6d815ebf15797761c13f31213dd6.diff | patch --verbose -p 1 # modify from https://github.com/restic/restic/issues/4636#issuecomment-1896455557 # 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) curl https://github.com/MetaCubeX/go/commit/9779155f18b6556a034f7bb79fb7fb2aad1e26a9.diff | patch --verbose -p 1 curl https://github.com/MetaCubeX/go/commit/ef0606261340e608017860b423ffae5c1ce78239.diff | patch --verbose -p 1 curl https://github.com/MetaCubeX/go/commit/7f83badcb925a7e743188041cb6e561fc9b5b642.diff | patch --verbose -p 1 curl https://github.com/MetaCubeX/go/commit/83ff9782e024cb328b690cbf0da4e7848a327f4f.diff | patch --verbose -p 1 # 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) curl https://github.com/golang/go/commit/9e43850a3298a9b8b1162ba0033d4c53f8637571.diff | patch --verbose -R -p 1 - name: Set variables if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version != '' }} run: echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV shell: bash - name: Set variables if: ${{ github.event_name != 'workflow_dispatch' && github.ref_name == 'Alpha' }} run: echo "VERSION=alpha-$(git rev-parse --short HEAD)" >> $GITHUB_ENV shell: bash - name: Set Time Variable run: | 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: r27 - 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 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}} 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: Create DEB package if: ${{ matrix.jobs.goos == 'linux' && !contains(matrix.jobs.goarch, 'mips') }} run: | sudo apt-get install dpkg if [ "${{matrix.jobs.abi}}" = "1" ]; then ARCH=loongarch64 elif [ "${{matrix.jobs.goarm}}" = "7" ]; then ARCH=armhf elif [ "${{matrix.jobs.goarch}}" = "arm" ]; then ARCH=armel else ARCH=${{matrix.jobs.goarch}} fi PackageVersion=$(curl -s "https://api.github.com/repos/MetaCubeX/mihomo/releases/latest" | grep -o '"tag_name": "[^"]*' | grep -o '[^"]*$' | sed 's/v//g' ) if [ $(git branch | awk -F ' ' '{print $2}') = "Alpha" ]; then PackageVersion="$(echo "${PackageVersion}" | awk -F '.' '{$NF = $NF + 1; print}' OFS='.')-${VERSION}" fi mkdir -p mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}/DEBIAN mkdir -p mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}/usr/bin mkdir -p mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}/etc/mihomo mkdir -p mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}/etc/systemd/system/ mkdir -p mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}/usr/share/licenses/mihomo cp mihomo mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}/usr/bin/mihomo cp LICENSE mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}/usr/share/licenses/mihomo/ cp .github/mihomo.service mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}/etc/systemd/system/ cat > mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}/etc/mihomo/config.yaml < mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}/DEBIAN/control < Homepage: https://wiki.metacubex.one/ Description: The universal proxy platform. EOF dpkg-deb -Z gzip --build mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION} - name: Convert DEB to RPM if: ${{ matrix.jobs.goos == 'linux' && !contains(matrix.jobs.goarch, 'mips') }} run: | sudo apt-get install -y alien alien --to-rpm --scripts mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}.deb mv mihomo*.rpm mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}.rpm # - name: Convert DEB to PKG # if: ${{ matrix.jobs.goos == 'linux' && !contains(matrix.jobs.goarch, 'mips') && !contains(matrix.jobs.goarch, 'loong64') }} # run: | # docker pull archlinux # docker run --rm -v ./:/mnt archlinux bash -c " # pacman -Syu pkgfile base-devel --noconfirm # curl -L https://github.com/helixarch/debtap/raw/master/debtap > /usr/bin/debtap # chmod 755 /usr/bin/debtap # debtap -u # debtap -Q /mnt/mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}.deb # " # mv mihomo*.pkg.tar.zst mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}.pkg.tar.zst - 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*.zip version.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: 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
[我应该下载哪个文件? / 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@v4 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@v4 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 }}