name: Release

on:
  push:
    tags:
      - v*

jobs:
  build:
    name: Build
    strategy:
      matrix:
        config:
          - { os: macos-latest, GOOS: darwin }
          - { os: ubuntu-latest, GOOS: linux }
          - { os: ubuntu-latest, GOOS: windows }
          - { os: ubuntu-latest, GOOS: freebsd }
          - { os: ubuntu-latest, GOOS: netbsd }
          - { os: ubuntu-latest, GOOS: openbsd }
          - { os: ubuntu-latest, GOOS: dragonfly }
    runs-on: ${{ matrix.config.os }}
    env:
      GOOS: ${{ matrix.config.GOOS }}
    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Set up Go
        uses: ./.github/actions/setup-go

      - shell: bash
        run: |
          echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_ENV

      - id: cache
        uses: actions/cache@v5
        with:
          path: dist/${{ matrix.config.GOOS }}
          key: "release-${{ matrix.config.GOOS }}-${{ env.sha_short }}"

      - name: Log in to Docker Hub
        if: env.GOOS == 'linux'
        run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
  
      - name: Run GoReleaser
        uses: ./.github/actions/goreleaser
        with:
          args: release --clean --split
        env:
          GITHUB_TOKEN: ${{ secrets.RELEASE_GH_TOKEN }}
          GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}

  release:
    name: Release
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Set up Go
        uses: ./.github/actions/setup-go

      - name: Test
        run: go test ./...

      - shell: bash
        run: |
          echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_ENV

      - uses: actions/cache@v5
        with: { path: dist/darwin, key: "release-darwin-${{ env.sha_short }}" }
      - uses: actions/cache@v5
        with: { path: dist/linux, key: "release-linux-${{ env.sha_short }}" }
      - uses: actions/cache@v5
        with: { path: dist/windows, key: "release-windows-${{ env.sha_short }}" }
      - uses: actions/cache@v5
        with: { path: dist/freebsd, key: "release-freebsd-${{ env.sha_short }}" }
      - uses: actions/cache@v5
        with: { path: dist/netbsd, key: "release-netbsd-${{ env.sha_short }}" }
      - uses: actions/cache@v5
        with: { path: dist/openbsd, key: "release-openbsd-${{ env.sha_short }}" }
      - uses: actions/cache@v5
        with: { path: dist/dragonfly, key: "release-dragonfly-${{ env.sha_short }}" }

      - name: Log in to Docker Hub
        run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin

      - name: Run GoReleaser
        uses: ./.github/actions/goreleaser
        with:
          args: continue --merge --verbose
        env:
          GITHUB_TOKEN: ${{ secrets.RELEASE_GH_TOKEN }}
          DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
          GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}

      - name: Flatten artifacts
        run: |
          for d in dist/{darwin,linux,windows,freebsd,netbsd,openbsd,dragonfly}; do
            mv $d/* dist/
            rmdir $d
          done

      - name: Upload Build Artifacts
        uses: actions/upload-artifact@v6
        with:
          name: dist
          path: dist

  publishToDepo:
    name: Publish to Depo
    needs: release
    if: ${{ !endsWith(github.ref, '-debug') }}
    runs-on: ubuntu-latest
    steps:
      - name: Download Build Artifacts
        uses: actions/download-artifact@v7
        with:
          name: dist
          path: dist

      - name: Build Debian/RPM/APK repositories
        # Manually build unsigned Debian, RPM and APK repositories
        # For Debian (the key needs to be *not* armored):
        #   deb [signed-by=/etc/apt/keyrings/nextdns.gpg] https://repo.nextdns.io/deb stable main
        # For yum:
        #   yum-config-manager --add-repo https://repo.nextdns.io/nextdns.repo
        # For zypper:
        #   zypper ar -f https://repo.nextdns.io/nextdns.repo nextdns
        # For Alpine
        #   curl -s https://repo.nextdns.io/nextdns.pub > /etc/apk/keys/nextdns.pub
        #   echo https://repo.nextdns.io/apk > /etc/apk/repositories
        run: |
          echo "::group::Install packages"
          sudo apt-get -qyy install gzip apt-utils gnupg > /dev/null
          echo "::endgroup::"
          cd dist
          mkdir -p r/deb/pool r/rpm r/apk
          for d in *.deb; do
            pkg=${d%_linux_*}
            arch=${d#*linux_}
            arch=${arch%.deb}
            case $arch in
              386) deb_arch=i386;;
              amd64) deb_arch=amd64;;
              armv5) deb_arch=armel;;
              armv6) deb_arch=armhf;;
              arm64) deb_arch=arm64;;
              mips*_hardfloat) deb_arch=;;
              mips64le_*) deb_arch=mips64el;;
              mipsle_*) deb_arch=mipsel;;
              mips_*) deb_arch=mips;;
              *) deb_arch=;;
            esac
            case $arch in
              386) rpm_arch=i686;;
              amd64) rpm_arch=x86_64;;
              armv7) rpm_arch=armhfp;;
              arm64) rpm_arch=aarch64;;
              *) rpm_arch=;;
            esac
            case $arch in
              386) alpine_arch=x86;;
              amd64) alpine_arch=x86_64;;
              armv6) alpine_arch=armhf;;
              armv7) alpine_arch=armv7;;
              arm64) alpine_arch=aarch64;;
              *) alpine_arch=;;
            esac
            echo "::group::Handle repository actions for $arch"
            if [ "$deb_arch" ]; then
              echo "Debian: ${deb_arch}"
              cp $d r/deb/pool/${pkg}_${deb_arch}.deb
              (
              cd r/deb
              mkdir -p dists/stable/main/binary-${deb_arch}
              apt-ftparchive --arch $deb_arch packages pool \
                | sed "s/^Architecture:.*/Architecture: ${deb_arch}/" \
                > dists/stable/main/binary-${deb_arch}/Packages
              gzip -k dists/stable/main/binary-${deb_arch}/Packages
              )
            fi
            if [ "$rpm_arch" ]; then
              echo "RPM: ${rpm_arch}"
              cp ${d%.deb}.rpm r/rpm/${pkg}_${rpm_arch}.rpm
            fi
            if [ "$alpine_arch" ]; then
              echo "Alpine: ${alpine_arch}"
              mkdir -p r/apk/$alpine_arch
              cp ${d%.deb}.apk r/apk/$alpine_arch/nextdns-${pkg#nextdns_}.apk
            fi
            echo "::endgroup::"
          done
          echo "::group::Create Debian release file"
          (
            cd r/deb
            echo Origin: NextDNS
            echo Label: NextDNS
            echo Suite: stable
            echo Components: main
            apt-ftparchive release dists/stable
          ) > r/deb/dists/stable/Release
          echo "::endgroup::"
          echo "::group::Create RPM repository"
          (
            cd r/rpm
            # No createrepo available in Ubuntu 20.04
            docker run --rm -w $PWD -v $PWD:$PWD almalinux:8 \
              sh -c "yum install -y createrepo &&
                     createrepo . &&
                     chown -R $(id -u):$(id -g) ."
          )
          cat <<EOF > r/nextdns.repo
          [nextdns]
          name=nextdns
          baseurl=https://repo.nextdns.io/rpm
          enabled=1
          gpgcheck=0
          repo_gpgcheck=1
          gpgkey=https://repo.nextdns.io/nextdns-armored.gpg
          EOF
          echo "::endgroup::"
          echo "::group::Create APK index files"
          (
            cd r/apk
            docker run --rm -w $PWD -v $PWD:$PWD alpine:3.19 sh -c '
              for arch in */; do
                echo "Indexing $arch"
                (
                  cd $arch
                  apk index --allow-untrusted -o APKINDEX.unsigned.tar.gz *.apk
                )
              done
            '
          )
          echo "::endgroup::"

      - name: Sign repositories
        # Key should be exported with:
        #  gpg --armor --export-secret-keys nextdns@nextdns.io
        run: |
          echo "::group::Preparing keys"
          cd dist/r
          echo "$GPG_KEY" | gpg --import
          gpg --export > nextdns.gpg
          gpg --export --armor > nextdns-armored.gpg
          echo "$REPO_KEY" > /tmp/nextdns
          openssl rsa -in /tmp/nextdns -pubout > nextdns.pub
          echo "::endgroup::"

          echo "::group::Signing Debian repository"
          gpg --output deb/dists/stable/Release.gpg --detach-sign deb/dists/stable/Release
          gpg --output deb/dists/stable/InRelease --clearsign --detach-sign deb/dists/stable/Release
          echo "::endgroup::"

          echo "::group::Signing RPM repository"
          gpg --detach-sign --armor rpm/repodata/repomd.xml
          echo "::endgroup::"

          echo "::group::Signing APK repository"
          docker run --rm -w $PWD -v $PWD:$PWD -v /tmp/nextdns:/tmp/nextdns alpine:3.19 sh -c '
            apk add alpine-sdk
            cd apk
            for arch in */; do
              cp $arch/APKINDEX.unsigned.tar.gz $arch/APKINDEX.tar.gz
              abuild-sign -k /tmp/nextdns $arch/APKINDEX.tar.gz
            done
          '
          echo "::endgroup::"
        env:
          GPG_KEY: ${{ secrets.GPG_KEY }}
          REPO_KEY: ${{ secrets.REPO_KEY }}

      - name: Publish repositories
        run: |
          cd dist
          aws s3 sync --no-progress --exclude "*" --include "*.deb" --include "*.rpm" --include "*.apk" \
            --storage-class REDUCED_REDUNDANCY --acl public-read \
            r/ s3://${AWS_BUCKET}/
          aws s3 sync --no-progress \
            --storage-class REDUCED_REDUNDANCY --acl public-read \
            --cache-control "max-age=300, must-revalidate" \
            r/ s3://${AWS_BUCKET}/
          aws s3 sync --no-progress --delete \
            --storage-class REDUCED_REDUNDANCY --acl public-read \
            r/ s3://${AWS_BUCKET}/
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.S3_REPO_KEY }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_REPO_SECRET }}
          AWS_DEFAULT_REGION: us-east-1
          AWS_BUCKET: repo.nextdns.io

  publishToOpenWRT:
    name: Publish to OpenWRT
    needs: publishToDepo
    if: ${{ !endsWith(github.ref, '-debug') }}
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Set environment variables
        run: |
          TAG=$(echo $GITHUB_REF | sed 's/refs\/tags\///')
          VERSION=${TAG:1}
          AUTHOR_NAME="Olivier Poitrey"
          AUTHOR_EMAIL=rs@nextdns.io

          # Must match OpenWrt's PKG_SOURCE_URL format (codeload + v$(PKG_VERSION) + trailing '?')
          OPENWRT_SOURCE_URL="https://codeload.github.com/nextdns/nextdns/tar.gz/v${VERSION}?"
          OPENWRT_HASH=$(curl -fsSL "${OPENWRT_SOURCE_URL}" | sha256sum | cut -d' ' -f1)

          export PR_TITLE="nextdns: update to version $VERSION";

          echo "OPENWRT_HASH=$OPENWRT_HASH"

          echo "OPENWRT_HASH=$OPENWRT_HASH" >> $GITHUB_ENV
          echo "OPENWRT_SOURCE_URL=$OPENWRT_SOURCE_URL" >> $GITHUB_ENV
          echo "VERSION=$VERSION" >> $GITHUB_ENV
          echo "AUTHOR_NAME=$AUTHOR_NAME" >> $GITHUB_ENV
          echo "AUTHOR_EMAIL=$AUTHOR_EMAIL" >> $GITHUB_ENV
          echo "PR_TITLE=$PR_TITLE" >> $GITHUB_ENV

      - name: Checkout OpenWRT packages repository fork
        uses: actions/checkout@v6
        with:
          repository: openwrt/packages
          ref: master

      - name: Rebase fork
        run: |
          git remote add upstream https://github.com/openwrt/packages.git
          git fetch upstream
          git reset --hard upstream/master

      - name: Update nextdns Makefile
        run: |
          sed -i 's/^PKG_VERSION:=.*/PKG_VERSION:=${{ env.VERSION }}/' net/nextdns/Makefile
          sed -i 's/^PKG_RELEASE:=.*/PKG_RELEASE:=1/' net/nextdns/Makefile
          sed -i 's/^PKG_SOURCE:=.*/PKG_SOURCE:=nextdns-$(PKG_VERSION).tar.gz/' net/nextdns/Makefile
          sed -i 's/^PKG_SOURCE_VERSION:=.*/PKG_SOURCE_VERSION:=v$(PKG_VERSION)/' net/nextdns/Makefile
          sed -i 's!^PKG_SOURCE_URL:=.*!PKG_SOURCE_URL:=https://codeload.github.com/nextdns/nextdns/tar.gz/v$(PKG_VERSION)?!' net/nextdns/Makefile
          sed -i 's/^PKG_HASH:=.*/PKG_HASH:=${{ env.OPENWRT_HASH }}/' net/nextdns/Makefile

      - name: Create pull request towards OpenWRT
        uses: peter-evans/create-pull-request@v8
        with:
          token: ${{ secrets.RELEASE_GH_TOKEN }}
          commit-message: |
            nextdns: update to version ${{ env.VERSION }}

            Update nextdns package to upstream version ${{ env.VERSION }}

            Signed-off-by: ${{ env.AUTHOR_NAME }} <${{ env.AUTHOR_EMAIL }}>
          title: ${{ env.PR_TITLE }}
          branch: nextdns-${{ env.VERSION }}-master
          body: Update to version ${{ env.VERSION }}
          base: master
          author: ${{ env.AUTHOR_NAME }} <${{ env.AUTHOR_EMAIL }}>
          committer: ${{ env.AUTHOR_NAME }} <${{ env.AUTHOR_EMAIL }}>
          push-to-fork: rs/openwrt-packages

  publishToAURSource:
    runs-on: ubuntu-latest
    needs: release
    if: ${{ !endsWith(github.ref, '-debug') }}
    steps:
      - name: Check out source repository
        uses: actions/checkout@v6

      - name: Set environment variables
        run: |
          TAG=$(echo $GITHUB_REF | sed 's/refs\/tags\///')
          VERSION=${TAG:1}
          echo "VERSION=$VERSION" >> $GITHUB_ENV

      - name: Set up SSH for AUR clone
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_nextdns
          chmod 600 ~/.ssh/id_nextdns
          echo -e "Host aur.archlinux.org\n\tStrictHostKeyChecking no\n\tIdentityFile ~/.ssh/id_nextdns\n" >> ~/.ssh/config
          git config core.sshCommand "ssh -i ~/.ssh/id_nextdns"

      - name: Clone AUR repository
        run: |
          git clone aur@aur.archlinux.org:nextdns.git aur-nextdns
          cd aur-nextdns
          git config user.name "NextDNS Team"
          git config user.email "team@nextdns.io"

      - name: Update PKGBUILD version
        working-directory: aur-nextdns
        run: |
          sed -i 's/^pkgver=.*/pkgver=${{ env.VERSION }}/' PKGBUILD
          docker run --rm -v "${{ github.workspace }}/aur-nextdns:/aur-nextdns" archlinux:latest bash -c '
            useradd -m builder &&
            cd /aur-nextdns &&
            sed "/^sha256sums=/,/)/d" PKGBUILD > PKGBUILD.new &&
            chmod -R o+w /aur-nextdns &&
            su builder -c "
                makepkg -g >> PKGBUILD.new &&
                mv PKGBUILD.new PKGBUILD &&
                makepkg --printsrcinfo > .SRCINFO
            "
          '

      - name: Commit and push changes
        working-directory: aur-nextdns
        run: |
          git add PKGBUILD .SRCINFO
          git commit -m "Bump version to ${{ env.VERSION }}"
          git push origin master

  publishToAUR:
    runs-on: ubuntu-latest
    needs: release
    if: ${{ !endsWith(github.ref, '-debug') }}
    steps:
      - name: Check out source repository
        uses: actions/checkout@v6

      - name: Set environment variables
        run: |
          TAG=$(echo $GITHUB_REF | sed 's/refs\/tags\///')
          VERSION=${TAG:1}
          echo "VERSION=$VERSION" >> $GITHUB_ENV

      - name: Set up SSH for AUR clone
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_nextdns
          chmod 600 ~/.ssh/id_nextdns
          echo -e "Host aur.archlinux.org\n\tStrictHostKeyChecking no\n\tIdentityFile ~/.ssh/id_nextdns\n" >> ~/.ssh/config
          git config core.sshCommand "ssh -i ~/.ssh/id_nextdns"

      - name: Clone AUR repository
        run: |
          git clone aur@aur.archlinux.org:nextdns-bin.git aur-nextdns
          cd aur-nextdns
          git config user.name "NextDNS Team"
          git config user.email "team@nextdns.io"

      - name: Update PKGBUILD version
        working-directory: aur-nextdns
        run: |
          sed -i 's/^pkgver=.*/pkgver=${{ env.VERSION }}/' PKGBUILD
          docker run --rm -v "${{ github.workspace }}/aur-nextdns:/aur-nextdns" archlinux:latest bash -c '
            useradd -m builder &&
            chmod -R o+w /aur-nextdns &&
            cd /aur-nextdns &&
            sed "/^sha256sums/d" PKGBUILD > PKGBUILD.new &&
            awk "/^source_armv7h/ {print; system(\"su builder -c \\\"makepkg -g\\\"\"); next} {print}" PKGBUILD.new > PKGBUILD &&
            su builder -c "makepkg --printsrcinfo > .SRCINFO" &&
            rm PKGBUILD.new
          '

      - name: Commit and push changes
        working-directory: aur-nextdns
        run: |
          git add PKGBUILD .SRCINFO
          git commit -m "Bump version to ${{ env.VERSION }}"
          git push origin master
