name: CI
#concurrency:
#  group: ${{ github.ref }}
#  cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
on:
  # # Triggers the workflow on push but only for the master branch
  push:
    branches: [master, develop]
    paths-ignore:
      - "**.md"
      - version.properties

  # Note: This is different from "pull_request". Need to specify ref when doing checkouts.
  pull_request_target:
    branches: [master, develop]
    paths-ignore:
      - "**.md"
      #- "**.yml"

  workflow_dispatch:

jobs:
  setup:
    strategy:
      fail-fast: false
      matrix:
        arch: [esp32, esp32s3, esp32c3, nrf52840, rp2040, stm32, check]
    runs-on: ubuntu-latest
    steps:
      - id: checkout
        uses: actions/checkout@v4
        name: Checkout base
      - id: jsonStep
        run: |
          TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}})
          echo "$TARGETS"
          echo "${{matrix.arch}}=$(jq -cn --argjson environments "$TARGETS" '{board: $environments}')" >> $GITHUB_OUTPUT
    outputs:
      esp32: ${{ steps.jsonStep.outputs.esp32 }}
      esp32s3: ${{ steps.jsonStep.outputs.esp32s3 }}
      esp32c3: ${{ steps.jsonStep.outputs.esp32c3 }}
      nrf52840: ${{ steps.jsonStep.outputs.nrf52840 }}
      rp2040: ${{ steps.jsonStep.outputs.rp2040 }}
      stm32: ${{ steps.jsonStep.outputs.stm32 }}
      check: ${{ steps.jsonStep.outputs.check }}

  check:
    needs: setup
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(needs.setup.outputs.check) }}

    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build base
        id: base
        uses: ./.github/actions/setup-base
      - name: Check ${{ matrix.board }}
        run: bin/check-all.sh ${{ matrix.board }}

  build-esp32:
    needs: setup
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(needs.setup.outputs.esp32) }}
    uses: ./.github/workflows/build_esp32.yml
    with:
      board: ${{ matrix.board }}

  build-esp32-s3:
    needs: setup
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(needs.setup.outputs.esp32s3) }}
    uses: ./.github/workflows/build_esp32_s3.yml
    with:
      board: ${{ matrix.board }}

  build-esp32-c3:
    needs: setup
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(needs.setup.outputs.esp32c3) }}
    uses: ./.github/workflows/build_esp32_c3.yml
    with:
      board: ${{ matrix.board }}

  build-nrf52:
    needs: setup
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(needs.setup.outputs.nrf52840) }}
    uses: ./.github/workflows/build_nrf52.yml
    with:
      board: ${{ matrix.board }}

  build-rpi2040:
    needs: setup
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(needs.setup.outputs.rp2040) }}
    uses: ./.github/workflows/build_rpi2040.yml
    with:
      board: ${{ matrix.board }}

  build-stm32:
    needs: setup
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(needs.setup.outputs.stm32) }}
    uses: ./.github/workflows/build_stm32.yml
    with:
      board: ${{ matrix.board }}

  package-raspbian:
    uses: ./.github/workflows/package_raspbian.yml

  package-raspbian-armv7l:
    uses: ./.github/workflows/package_raspbian_armv7l.yml

  package-native:
    uses: ./.github/workflows/package_amd64.yml

  after-checks:
    runs-on: ubuntu-latest
    needs: [check]
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          ref: ${{github.event.pull_request.head.ref}}
          repository: ${{github.event.pull_request.head.repo.full_name}}

  gather-artifacts:
    permissions:
      contents: write
      pull-requests: write
    runs-on: ubuntu-latest
    needs:
      [
        build-esp32,
        build-esp32-s3,
        build-esp32-c3,
        build-nrf52,
        build-rpi2040,
        build-stm32,
        package-raspbian,
        package-raspbian-armv7l,
        package-native,
      ]
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          ref: ${{github.event.pull_request.head.ref}}
          repository: ${{github.event.pull_request.head.repo.full_name}}

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

      - name: Display structure of downloaded files
        run: ls -R

      - name: Get release version string
        run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
        id: version

      - name: Move files up
        run: mv -b -t ./ ./release/meshtasticd_linux_* ./bin/config-dist.yaml ./bin/device-*.sh ./bin/device-*.bat

      - name: Repackage in single firmware zip
        uses: actions/upload-artifact@v4
        with:
          name: firmware-${{ steps.version.outputs.version }}
          overwrite: true
          path: |
            ./firmware-*.bin
            ./firmware-*.uf2
            ./firmware-*.hex
            ./firmware-*-ota.zip
            ./device-*.sh
            ./device-*.bat
            ./meshtasticd_linux_*
            ./config-dist.yaml
            ./littlefs-*.bin
            ./bleota*bin
            ./Meshtastic_nRF52_factory_erase*.uf2
          retention-days: 90

      - uses: actions/download-artifact@v4
        with:
          name: firmware-${{ steps.version.outputs.version }}
          merge-multiple: true
          path: ./output

      # For diagnostics
      - name: Show artifacts
        run: ls -lR

      - name: Device scripts permissions
        run: |
          chmod +x ./output/device-install.sh
          chmod +x ./output/device-update.sh

      - name: Zip firmware
        run: zip -j -9 -r ./firmware-${{ steps.version.outputs.version }}.zip ./output

      - name: Repackage in single elfs zip
        uses: actions/upload-artifact@v4
        with:
          name: debug-elfs-${{ steps.version.outputs.version }}.zip
          overwrite: true
          path: ./*.elf
          retention-days: 30

      - name: Create request artifacts
        continue-on-error: true # FIXME: Why are we getting 502, but things still work?
        if: ${{ github.event_name == 'pull_request_target' || github.event_name == 'pull_request' }}
        uses: gavv/pull-request-artifacts@v2.1.0
        with:
          commit: ${{ (github.event.pull_request_target || github.event.pull_request).head.sha }}
          repo-token: ${{ secrets.GITHUB_TOKEN }}
          artifacts-token: ${{ secrets.ARTIFACTS_TOKEN }}
          artifacts-repo: meshtastic/artifacts
          artifacts-branch: device
          artifacts: ./firmware-${{ steps.version.outputs.version }}.zip

  release-artifacts:
    runs-on: ubuntu-latest
    if: ${{ github.event_name == 'workflow_dispatch' }}
    needs: [gather-artifacts, after-checks]
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: 3.x

      - name: Get release version string
        run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
        id: version

      - uses: actions/download-artifact@v4
        with:
          name: firmware-${{ steps.version.outputs.version }}
          merge-multiple: true
          path: ./output

      - name: Display structure of downloaded files
        run: ls -R

      - name: Device scripts permissions
        run: |
          chmod +x ./output/device-install.sh
          chmod +x ./output/device-update.sh

      - name: Zip firmware
        run: zip -j -9 -r ./firmware-${{ steps.version.outputs.version }}.zip ./output -x meshtasticd_*

      - uses: actions/download-artifact@v4
        with:
          name: debug-elfs-${{ steps.version.outputs.version }}.zip
          merge-multiple: true
          path: ./elfs

      - name: Zip Elfs
        run: zip -j -9 -r ./debug-elfs-${{ steps.version.outputs.version }}.zip ./elfs

      # For diagnostics
      - name: Show artifacts
        run: ls -lR

      - name: Create release
        uses: actions/create-release@v1
        id: create_release
        with:
          draft: true
          prerelease: true
          release_name: Meshtastic Firmware ${{ steps.version.outputs.version }} Alpha
          tag_name: v${{ steps.version.outputs.version }}
          body: |
            Autogenerated by github action, developer should edit as required before publishing...
        env:
          GITHUB_TOKEN: ${{ github.token }}

      - name: Add bins to release
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ github.token }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./firmware-${{ steps.version.outputs.version }}.zip
          asset_name: firmware-${{ steps.version.outputs.version }}.zip
          asset_content_type: application/zip

      - name: Add debug elfs to release
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ github.token }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./debug-elfs-${{ steps.version.outputs.version }}.zip
          asset_name: debug-elfs-${{ steps.version.outputs.version }}.zip
          asset_content_type: application/zip

      - uses: actions/download-artifact@v4
        with:
          pattern: meshtasticd_${{ steps.version.outputs.version }}_*.deb
          merge-multiple: true
          path: ./output

      - name: Add raspbian aarch64 .deb
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ github.token }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
          asset_name: meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
          asset_content_type: application/vnd.debian.binary-package

      - name: Add raspbian armv7l .deb
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ github.token }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_armhf.deb
          asset_name: meshtasticd_${{ steps.version.outputs.version }}_armhf.deb
          asset_content_type: application/vnd.debian.binary-package

      - name: Add raspbian amd64 .deb
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ github.token }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
          asset_name: meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
          asset_content_type: application/vnd.debian.binary-package

      - name: Bump version.properties
        run: >-
          bin/bump_version.py

      - name: Create version.properties pull request
        uses: peter-evans/create-pull-request@v7
        with:
          title: Bump version.properties
          add-paths: |
            version.properties

      - name: Checkout meshtastic/meshtastic.github.io
        uses: actions/checkout@v4
        with:
          repository: meshtastic/meshtastic.github.io
          token: ${{ secrets.ARTIFACTS_TOKEN }}
          path: meshtastic.github.io

      - name: Display structure of downloaded files
        run: ls -R

      - name: Extract firmware.zip
        run: |
          unzip ./firmware-${{ steps.version.outputs.version }}.zip -d meshtastic.github.io/firmware-${{ steps.version.outputs.version }}

      - name: Display structure of downloaded files
        run: ls -R

      - name: Commit and push changes
        run: |
          cd meshtastic.github.io
          find . -type f -name 'meshtasticd_*' -exec rm -f {} +
          git config --global user.name "github-actions[bot]"
          git config --global user.email "github-actions[bot]@users.noreply.github.com"
          git add .
          git commit -m "Add firmware version ${{ steps.version.outputs.version }}"
          git push