name: sing-box sdk 24.10.6

on:
  workflow_dispatch:
    inputs:
      rr_wrt_branch:
        description: rr-wrt branch for SDK artifact lookup
        required: false
        default: rr-wrt-v24.10.6
      rr_wrt_artifact_name:
        description: rr-wrt SDK artifact name
        required: false
        default: openwrt-filogic-sdk-ci

jobs:
  build:
    runs-on: ubuntu-22.04
    timeout-minutes: 240
    env:
      DEBIAN_FRONTEND: noninteractive
    steps:
      - name: checkout
        uses: actions/checkout@v4

      - name: install deps
        run: |
          set -euxo pipefail
          sudo apt-get update
          sudo apt-get install -y \
            bash build-essential ca-certificates curl file findutils gawk git grep \
            gzip jq rsync sed tar unzip wget xz-utils zstd

      - name: setup external go
        uses: actions/setup-go@v5
        with:
          go-version-file: sing-box-rr/go.mod
          cache: false

      - name: download sdk from rr-wrt artifact
        shell: bash
        env:
          SAM_GAD: ${{ secrets.SAM_GAD }}
        run: |
          set -euxo pipefail
          if [ -z "${SAM_GAD:-}" ]; then
            echo "SAM_GAD secret is required for Gitea API artifact download"
            exit 1
          fi

          RR_OWNER="routerich"
          RR_REPO="rr-wrt"
          RR_BRANCH='${{ inputs.rr_wrt_branch }}'
          RR_ARTIFACT_NAME='${{ inputs.rr_wrt_artifact_name }}'
          API_BASE="https://git.routerich.ru/api/v1/repos/${RR_OWNER}/${RR_REPO}/actions"

          if [[ "$SAM_GAD" == *:* ]]; then
            AUTH_ARGS=(-u "$SAM_GAD")
          else
            AUTH_ARGS=(-H "Authorization: token $SAM_GAD")
          fi

          artifacts_json="$RUNNER_TEMP/rr-wrt-artifacts.json"
          curl -fsSL "${AUTH_ARGS[@]}" \
            "${API_BASE}/artifacts?name=${RR_ARTIFACT_NAME}&per_page=100&page=1" \
            -o "$artifacts_json"

          jq -r '
            def arr:
              if type == "array" then .
              elif has("artifacts") then .artifacts
              elif has("data") then .data
              else [] end;
            arr[]? | "\(.id // "na")\t\(.name // "na")\t\(.workflow_run.head_branch? // .workflow_run.branch? // .workflow_run.ref? // .ref? // "na")\t\(.expired? // false)"
          ' "$artifacts_json" > "$RUNNER_TEMP/rr-wrt-artifacts-list.txt" || true
          head -n 20 "$RUNNER_TEMP/rr-wrt-artifacts-list.txt" || true

          artifact_id="$(jq -r --arg n "$RR_ARTIFACT_NAME" --arg b "$RR_BRANCH" '
            def arr:
              if type == "array" then .
              elif has("artifacts") then .artifacts
              elif has("data") then .data
              else [] end;
            [
              arr[]?
              | select((.name // "") == $n)
              | select(
                  (
                    .workflow_run.head_branch?
                    // .workflow_run.branch?
                    // .workflow_run.ref?
                    // .ref?
                    // .source_branch?
                    // ""
                  ) == $b
                )
              | select((.expired? // false) == false)
            ]
            | sort_by(.id // 0)
            | reverse
            | .[0].id // empty
          ' "$artifacts_json")"

          if [ -z "$artifact_id" ]; then
            artifact_id="$(jq -r --arg n "$RR_ARTIFACT_NAME" '
              def arr:
                if type == "array" then .
                elif has("artifacts") then .artifacts
                elif has("data") then .data
                else [] end;
              [
                arr[]?
                | select((.name // "") == $n)
                | select((.expired? // false) == false)
              ]
              | sort_by(.id // 0)
              | reverse
              | .[0].id // empty
            ' "$artifacts_json")"
          fi

          if [ -z "$artifact_id" ]; then
            echo "No artifact found: name=${RR_ARTIFACT_NAME}, branch=${RR_BRANCH}"
            exit 1
          fi

          mkdir -p "$RUNNER_TEMP/sdk" "$RUNNER_TEMP/sdk-artifact"
          SDK_ARTIFACT_ZIP="$RUNNER_TEMP/sdk-artifact.zip"
          curl -fL "${AUTH_ARGS[@]}" \
            "${API_BASE}/artifacts/${artifact_id}/zip" \
            -o "$SDK_ARTIFACT_ZIP"

          unzip -q "$SDK_ARTIFACT_ZIP" -d "$RUNNER_TEMP/sdk-artifact"

          SDK_ARCHIVE="$(find "$RUNNER_TEMP/sdk-artifact" -type f -name '*.tar.zst' | head -n1)"
          test -n "$SDK_ARCHIVE"

          tar --zstd -xf "$SDK_ARCHIVE" -C "$RUNNER_TEMP/sdk"

          SDK_DIR="$(find "$RUNNER_TEMP/sdk" -mindepth 1 -maxdepth 1 -type d | head -n1)"
          test -n "$SDK_DIR"

          echo "SDK_SOURCE_ARTIFACT_ID=$artifact_id" >> "$GITHUB_ENV"
          echo "SDK_ARCHIVE=$SDK_ARCHIVE" >> "$GITHUB_ENV"
          echo "SDK_DIR=$SDK_DIR" >> "$GITHUB_ENV"

      - name: stage sing-box-rr package into sdk
        shell: bash
        run: |
          set -euxo pipefail
          test -d "$SDK_DIR"

          rm -rf "$SDK_DIR/package/sing-box-rr"
          mkdir -p "$SDK_DIR/package/sing-box-rr"

          rsync -a --delete ./sing-box-rr/ "$SDK_DIR/package/sing-box-rr/"
          cp -f ./VERSION "$SDK_DIR/package/VERSION"
          cp -f ./SOURCE_DATE_EPOCH "$SDK_DIR/package/SOURCE_DATE_EPOCH"

      - name: build package in sdk
        id: build
        continue-on-error: true
        shell: bash
        run: |
          set -euxo pipefail
          mkdir -p logs
          cd "$SDK_DIR"

          go version > "$GITHUB_WORKSPACE/logs/go-version.log" 2>&1
          command -v go > "$GITHUB_WORKSPACE/logs/go-bin.log" 2>&1
          make defconfig > "$GITHUB_WORKSPACE/logs/sdk-defconfig.log" 2>&1

          set +e
          # Clean first so the package rebuilds even when VERSION stays unchanged.
          make -j"$(nproc)" package/sing-box-rr/clean > "$GITHUB_WORKSPACE/logs/pkg-clean.log" 2>&1
          make -j"$(nproc)" package/sing-box-rr/compile V=s GO_BIN="$(command -v go)" > "$GITHUB_WORKSPACE/logs/pkg-build.log" 2>&1
          rc=$?
          if [ "$rc" -ne 0 ]; then
            tail -n 400 "$GITHUB_WORKSPACE/logs/pkg-build.log" || true
          fi
          exit "$rc"

      - name: collect packages artifact
        if: always()
        shell: bash
        run: |
          set -euo pipefail
          mkdir -p artifacts/packages logs

          find "$SDK_DIR/bin/packages" -type f -name 'sing-box-rr_*.ipk' -print | sort > logs/packages-found.txt || true

          pkg="$(tail -n1 logs/packages-found.txt || true)"
          if [ -n "${pkg:-}" ]; then
            cp -f "$pkg" artifacts/packages/
          else
            echo "err sing-box-rr package not found in sdk output" | tee -a logs/packages-filter.txt
          fi

          pkg_count=$(find artifacts/packages -maxdepth 1 -type f -name 'sing-box-rr_*.ipk' | wc -l | tr -d ' ')
          if [ "$pkg_count" -ne 1 ]; then
            echo "err expected exactly 1 sing-box-rr package in artifact, got $pkg_count" | tee -a logs/packages-filter.txt
            exit 1
          fi

          ls -lah artifacts/packages > logs/packages-ls.txt 2>&1 || true

      - name: upload logs
        if: always()
        uses: christopherhx/gitea-upload-artifact@v4
        with:
          name: sing-box-rr-build-logs
          path: logs/
          if-no-files-found: warn
          compression-level: 0

      - name: upload sdk archive
        if: always()
        uses: christopherhx/gitea-upload-artifact@v4
        with:
          name: openwrt-sdk-24.10.6
          path: ${{ env.SDK_ARCHIVE }}
          if-no-files-found: warn
          compression-level: 0

      - name: upload packages artifact
        if: always()
        uses: christopherhx/gitea-upload-artifact@v4
        with:
          name: sing-box-rr-packages-24.10.6
          path: artifacts/packages/
          if-no-files-found: warn
          compression-level: 0

      - name: fail workflow if build failed
        if: steps.build.outcome == 'failure'
        run: |
          echo "package build failed"
          exit 1
