name: release

on:
  push:
    tags:
      - "v*"

permissions:
  contents: write
  packages: write

jobs:
  test:
    uses: ./.github/workflows/runtest.yml

  build-and-release:
    needs: test
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v7
      - name: set up go
        uses: actions/setup-go@v7
        with:
          go-version: "1.25"

      - name: extract version
        run: |
          echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
          # single source of truth so the cross-compile steps can't drift
          echo "LDFLAGS=-s -w -X main.version=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV

      - name: build for windows
        run: |
          GOOS=windows GOARCH=amd64 go build -ldflags="${{ env.LDFLAGS }}" -o sif-windows-amd64.exe ./cmd/sif
          GOOS=windows GOARCH=386 go build -ldflags="${{ env.LDFLAGS }}" -o sif-windows-386.exe ./cmd/sif

      - name: build for macOS
        run: |
          GOOS=darwin GOARCH=amd64 go build -ldflags="${{ env.LDFLAGS }}" -o sif-macos-amd64 ./cmd/sif
          GOOS=darwin GOARCH=arm64 go build -ldflags="${{ env.LDFLAGS }}" -o sif-macos-arm64 ./cmd/sif

      - name: build for linux
        run: |
          GOOS=linux GOARCH=amd64 go build -ldflags="${{ env.LDFLAGS }}" -o sif-linux-amd64 ./cmd/sif
          GOOS=linux GOARCH=386 go build -ldflags="${{ env.LDFLAGS }}" -o sif-linux-386 ./cmd/sif
          GOOS=linux GOARCH=arm64 go build -ldflags="${{ env.LDFLAGS }}" -o sif-linux-arm64 ./cmd/sif

      - name: package releases with modules
        run: |
          for binary in sif-linux-amd64 sif-linux-386 sif-linux-arm64 sif-macos-amd64 sif-macos-arm64; do
            mkdir -p "dist/${binary}"
            cp "${binary}" "dist/${binary}/sif"
            cp -r modules "dist/${binary}/"
            tar -czf "${binary}.tar.gz" -C dist "${binary}"
          done
          for binary in sif-windows-amd64 sif-windows-386; do
            mkdir -p "dist/${binary}"
            cp "${binary}.exe" "dist/${binary}/sif.exe"
            cp -r modules "dist/${binary}/"
            cd dist && zip -r "../${binary}.zip" "${binary}" && cd ..
          done

      - name: build debian packages
        run: |
          declare -A arch_map=(
            ["sif-linux-amd64"]="amd64"
            ["sif-linux-386"]="i386"
            ["sif-linux-arm64"]="arm64"
          )

          for binary in sif-linux-amd64 sif-linux-386 sif-linux-arm64; do
            arch="${arch_map[$binary]}"
            pkg_dir="sif_${{ env.VERSION }}_${arch}"

            mkdir -p "${pkg_dir}/DEBIAN"
            mkdir -p "${pkg_dir}/usr/bin"
            mkdir -p "${pkg_dir}/usr/share/sif/modules"

            cp "${binary}" "${pkg_dir}/usr/bin/sif"
            chmod 755 "${pkg_dir}/usr/bin/sif"
            cp -r modules/* "${pkg_dir}/usr/share/sif/modules/"

            cat > "${pkg_dir}/DEBIAN/control" << EOF
          Package: sif
          Version: ${{ env.VERSION }}
          Section: security
          Priority: optional
          Architecture: ${arch}
          Maintainer: vmfunc <celeste@linux.com>
          Homepage: https://github.com/vmfunc/sif
          Description: Modular pentesting toolkit
           sif is a fast, concurrent, and extensible pentesting toolkit written in Go.
           It supports multiple scan types including directory fuzzing, subdomain
           enumeration, port scanning, and vulnerability detection.
          EOF

            dpkg-deb --build "${pkg_dir}"
          done

      - name: generate checksums
        run: |
          sha256sum \
            sif-windows-amd64.zip \
            sif-windows-386.zip \
            sif-macos-amd64.tar.gz \
            sif-macos-arm64.tar.gz \
            sif-linux-amd64.tar.gz \
            sif-linux-386.tar.gz \
            sif-linux-arm64.tar.gz \
            sif_*.deb \
            > checksums-sha256.txt

      - name: generate SBOM
        uses: anchore/sbom-action@v0
        with:
          artifact-name: sbom.spdx.json
          output-file: sbom.spdx.json

      - name: generate changelog
        id: changelog
        uses: actions/github-script@v9
        with:
          result-encoding: string
          script: |
            const { data: releases } = await github.rest.repos.listReleases({
              owner: context.repo.owner,
              repo: context.repo.repo,
              per_page: 1,
            });

            const prev = releases.length > 0 ? releases[0].tag_name : '';
            const range = prev ? `${prev}...${context.ref}` : '';

            const { data: commits } = await github.rest.repos.compareCommitsWithBasehead({
              owner: context.repo.owner,
              repo: context.repo.repo,
              basehead: prev ? `${prev}...${{ github.ref_name }}` : `${{ github.sha }}~10...${{ github.sha }}`,
            }).catch(() => ({ data: { commits: [] } }));

            let log = '';
            for (const c of commits.commits || []) {
              const msg = c.commit.message.split('\n')[0];
              const sha = c.sha.substring(0, 7);
              log += `- ${msg} (${sha})\n`;
            }

            return log || 'initial release';

      - name: create release
        uses: softprops/action-gh-release@v3
        with:
          name: sif v${{ env.VERSION }}
          body: |
            ## what's changed

            ${{ steps.changelog.outputs.result }}

            ## install

            **homebrew / linuxbrew**
            ```bash
            # coming soon
            ```

            **debian / ubuntu**
            ```bash
            sudo dpkg -i sif_${{ env.VERSION }}_amd64.deb
            ```

            **go install**
            ```bash
            go install github.com/vmfunc/sif/cmd/sif@v${{ env.VERSION }}
            ```

            **binary download** - grab the right archive from below.

            ## verification

            ```bash
            sha256sum -c checksums-sha256.txt
            ```
          draft: false
          prerelease: ${{ contains(github.ref_name, '-') }}
          files: |
            sif-windows-amd64.zip
            sif-windows-386.zip
            sif-macos-amd64.tar.gz
            sif-macos-arm64.tar.gz
            sif-linux-amd64.tar.gz
            sif-linux-386.tar.gz
            sif-linux-arm64.tar.gz
            sif_*_amd64.deb
            sif_*_i386.deb
            sif_*_arm64.deb
            checksums-sha256.txt
            sbom.spdx.json
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: push to cloudsmith
        if: ${{ !contains(github.ref_name, '-') }}
        env:
          CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }}
        run: |
          pip install cloudsmith-cli
          for deb in sif_*.deb; do
            cloudsmith push deb sif/deb/any-distro/any-version "$deb" -k "$CLOUDSMITH_API_KEY"
          done
