name: ci-nightly-build

on:
  schedule:
    - cron: "0 3 * * *"
  workflow_dispatch:

permissions:
  contents: write

jobs:
  check-new-commit:
    runs-on: ubuntu-latest
    outputs:
      sha: ${{ steps.head.outputs.sha }}
      skip: ${{ steps.check.outputs.skip }}
    steps:
      - name: get HEAD SHA
        id: head
        run: |
          SHA=$(gh api repos/${{ github.repository }}/commits/main --jq '.sha')
          echo "sha=$SHA" >> "$GITHUB_OUTPUT"
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: check if already built
        id: check
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GH_REPO: ${{ github.repository }}
        run: |
          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
            echo "skip=false" >> "$GITHUB_OUTPUT"
            exit 0
          fi
          BODY=$(gh release view nightly-build --json body --jq '.body' 2>/dev/null || echo "")
          if echo "$BODY" | grep -q "${{ steps.head.outputs.sha }}"; then
            echo "No new commit since last build — skipping."
            echo "skip=true" >> "$GITHUB_OUTPUT"
          else
            echo "skip=false" >> "$GITHUB_OUTPUT"
          fi

  appimage:
    needs: check-new-commit
    if: needs.check-new-commit.outputs.skip != 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7

      - name: setup-python
        uses: actions/setup-python@v7
        with:
          python-version: "3.14"
          cache: "pip"
          cache-dependency-path: "pyproject.toml"

      - name: install python-appimage
        run: pip install python-appimage

      - name: create requirements.txt
        run: |
          echo $PWD > ./appimage/requirements.txt
          cat ./appimage/pre-requirements.txt >> ./appimage/requirements.txt

      - name: build AppImage
        run: python -m python_appimage build app -p 3.14 ./appimage

      - name: rename to nightly
        run: mv xonsh-x86_64.AppImage xonsh-nightly.AppImage

      - name: upload artifact
        uses: actions/upload-artifact@v7
        with:
          name: xonsh-nightly.AppImage
          path: xonsh-nightly.AppImage

      - name: update nightly-build release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          COMMIT_DATE=$(TZ=UTC git log -1 --date=format-local:'%Y-%m-%d %H:%M:%S UTC' --format='%cd')
          python .github/scripts/update-nightly-release-descr.py header \
            --sha "${{ github.sha }}" --date "$COMMIT_DATE"
          sha256sum xonsh-nightly.AppImage > xonsh-nightly.AppImage.sha256
          gh release upload nightly-build xonsh-nightly.AppImage xonsh-nightly.AppImage.sha256 --clobber
          python .github/scripts/update-nightly-release-descr.py line \
            --file xonsh-nightly.AppImage --sha "${{ github.sha }}"

  nuitka-linux:
    needs: check-new-commit
    if: needs.check-new-commit.outputs.skip != 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7

      - name: setup-python
        uses: actions/setup-python@v7
        with:
          python-version: "3.13"
          cache: "pip"
          cache-dependency-path: "pyproject.toml"

      - name: install system deps
        run: |
          sudo apt-get update -qq
          sudo apt-get install -y curl git vim patchelf elfutils binutils-common binutils \
            gcc ccache libpython3-dev

      - name: install nuitka and deps
        run: |
          pip install -U pip setuptools wheel certifi
          pip install nuitka ordered-set zstandard
          pip install -e '.[full]'

      - name: build standalone onefile
        run: |
          XONSH_PKG=$(python -c "import xonsh; print(xonsh.__path__[0])")
          python -m nuitka \
            --onefile \
            --show-progress \
            --show-scons \
            --show-modules \
            --output-filename=xonsh-nightly-nuitka-linux.bin \
            --include-package=xonsh \
            --include-package=xontrib \
            --include-package=xompletions \
            --include-package-data=xonsh \
            --include-package-data=xontrib \
            --include-package-data=xompletions \
            --include-package=pip --include-package=setuptools --include-package=wheel \
            --include-package=certifi --include-package-data=certifi \
            --include-module=ujson \
            --include-package=pygments --include-package=prompt_toolkit \
            --include-module=pyperclip --include-package=click \
            --assume-yes-for-downloads \
            "$XONSH_PKG" 2>&1 | tee nuitka-build.log

      - name: upload build log and crash report
        if: failure()
        uses: actions/upload-artifact@v7
        with:
          name: nuitka-logs-linux
          path: |
            nuitka-build.log
            nuitka-crash-report.xml
          if-no-files-found: ignore

#       - name: smoke test
#         run: |
#           chmod +x xonsh-nightly-nuitka-linux.bin
#           ./xonsh-nightly-nuitka-linux.bin -c 'echo "nuitka build ok"'

      - name: upload artifact
        uses: actions/upload-artifact@v7
        with:
          name: xonsh-nightly-nuitka-linux.bin
          path: xonsh-nightly-nuitka-linux.bin

      - name: upload to nightly-build release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          until gh release view nightly-build &>/dev/null; do sleep 5; done
          sha256sum xonsh-nightly-nuitka-linux.bin > xonsh-nightly-nuitka-linux.bin.sha256
          gh release upload nightly-build xonsh-nightly-nuitka-linux.bin xonsh-nightly-nuitka-linux.bin.sha256 --clobber
          python .github/scripts/update-nightly-release-descr.py line \
            --file xonsh-nightly-nuitka-linux.bin --sha "${{ github.sha }}"

  nuitka-macos:
    needs: check-new-commit
    if: needs.check-new-commit.outputs.skip != 'true'
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v7

      - name: setup-python
        uses: actions/setup-python@v7
        with:
          python-version: "3.13"
          cache: "pip"
          cache-dependency-path: "pyproject.toml"

      - name: install nuitka and deps
        run: |
          pip install -U pip setuptools wheel certifi
          pip install nuitka ordered-set zstandard
          pip install -e '.[full]'

      - name: build standalone onefile
        run: |
          XONSH_PKG=$(python -c "import xonsh; print(xonsh.__path__[0])")
          python -m nuitka \
            --onefile \
            --show-progress \
            --show-scons \
            --show-modules \
            --output-filename=xonsh-nightly-nuitka-macos.bin \
            --include-package=xonsh \
            --include-package=xontrib \
            --include-package=xompletions \
            --include-package-data=xonsh \
            --include-package-data=xontrib \
            --include-package-data=xompletions \
            --include-package=pip --include-package=setuptools --include-package=wheel \
            --include-package=certifi --include-package-data=certifi \
            --include-module=ujson \
            --include-package=pygments --include-package=prompt_toolkit \
            --include-module=pyperclip --include-package=click \
            --assume-yes-for-downloads \
            "$XONSH_PKG" 2>&1 | tee nuitka-build.log

      - name: upload build log and crash report
        if: failure()
        uses: actions/upload-artifact@v7
        with:
          name: nuitka-logs-macos
          path: |
            nuitka-build.log
            nuitka-crash-report.xml
          if-no-files-found: ignore

#       - name: smoke test
#         run: |
#           chmod +x xonsh-nightly-nuitka-macos.bin
#           ./xonsh-nightly-nuitka-macos.bin -c 'echo "nuitka build ok"'

      - name: upload artifact
        uses: actions/upload-artifact@v7
        with:
          name: xonsh-nightly-nuitka-macos.bin
          path: xonsh-nightly-nuitka-macos.bin

      - name: upload to nightly-build release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          until gh release view nightly-build &>/dev/null; do sleep 5; done
          shasum -a 256 xonsh-nightly-nuitka-macos.bin > xonsh-nightly-nuitka-macos.bin.sha256
          gh release upload nightly-build xonsh-nightly-nuitka-macos.bin xonsh-nightly-nuitka-macos.bin.sha256 --clobber
          python .github/scripts/update-nightly-release-descr.py line \
            --file xonsh-nightly-nuitka-macos.bin --sha "${{ github.sha }}"

  windows-inno6:
    needs: check-new-commit
    if: needs.check-new-commit.outputs.skip != 'true'
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@v7

      - uses: actions/checkout@v7
        with:
          repository: xonsh/xonsh-winget
          path: winget

      - name: setup-python
        uses: actions/setup-python@v7
        with:
          python-version: "3.12"

      - name: install dependencies
        run: pip install 'xonsh[full]' click jinja2

      - name: install inno setup 6
        run: choco install innosetup -y --no-progress

      - name: build installer
        shell: bash
        working-directory: winget
        run: |
          xonsh build.xsh build --git --version nightly --python-version 3.14.3
          xonsh build.xsh installer --version nightly --inno-version 6 --include-inno-tag

      - name: collect artifact
        shell: bash
        run: |
          mv winget/dist/*.exe xonsh-nightly-inno6-setup.exe

      - name: upload artifact
        uses: actions/upload-artifact@v7
        with:
          name: xonsh-nightly-inno6-setup.exe
          path: xonsh-nightly-inno6-setup.exe

      - name: upload to nightly-build release
        shell: bash
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          until gh release view nightly-build &>/dev/null; do sleep 5; done
          sha256sum xonsh-nightly-inno6-setup.exe > xonsh-nightly-inno6-setup.exe.sha256
          gh release upload nightly-build xonsh-nightly-inno6-setup.exe xonsh-nightly-inno6-setup.exe.sha256 --clobber
          python .github/scripts/update-nightly-release-descr.py line \
            --file xonsh-nightly-inno6-setup.exe --sha "${{ github.sha }}"

  windows-inno5:
    needs: check-new-commit
    if: needs.check-new-commit.outputs.skip != 'true'
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@v7

      - uses: actions/checkout@v7
        with:
          repository: xonsh/xonsh-winget
          path: winget

      - name: setup-python
        uses: actions/setup-python@v7
        with:
          python-version: "3.12"

      - name: install dependencies
        run: pip install 'xonsh[full]' click jinja2

      - name: install inno setup 5
        shell: pwsh
        run: |
          $url = "https://github.com/xonsh/xonsh-winget/raw/main/inno/innosetup-5.6.1.exe"
          $exe = "$env:RUNNER_TEMP\innosetup5.exe"
          Invoke-WebRequest -Uri $url -OutFile $exe
          Start-Process -FilePath $exe -ArgumentList '/VERYSILENT','/SUPPRESSMSGBOXES','/NORESTART','/SP-' -Wait

      - name: build installer
        shell: bash
        working-directory: winget
        run: |
          xonsh build.xsh build --git --version nightly --python-version 3.13.1
          xonsh build.xsh installer --version nightly --inno-version 5 --include-python-tag --include-inno-tag

      - name: collect artifact
        shell: bash
        run: |
          mv winget/dist/*.exe xonsh-nightly-inno5-setup.exe

      - name: upload artifact
        uses: actions/upload-artifact@v7
        with:
          name: xonsh-nightly-inno5-setup.exe
          path: xonsh-nightly-inno5-setup.exe

      - name: upload to nightly-build release
        shell: bash
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          until gh release view nightly-build &>/dev/null; do sleep 5; done
          sha256sum xonsh-nightly-inno5-setup.exe > xonsh-nightly-inno5-setup.exe.sha256
          gh release upload nightly-build xonsh-nightly-inno5-setup.exe xonsh-nightly-inno5-setup.exe.sha256 --clobber
          python .github/scripts/update-nightly-release-descr.py line \
            --file xonsh-nightly-inno5-setup.exe --sha "${{ github.sha }}"

  flatpak:
    needs: check-new-commit
    if: needs.check-new-commit.outputs.skip != 'true'
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v7

      - uses: actions/checkout@v7
        with:
          repository: xonsh/xonsh-flatpak
          path: flatpak-build

      - name: install system deps
        run: |
          sudo apt-get update -qq
          sudo apt-get install -y -qq flatpak flatpak-builder

      - name: install build script deps
        run: pip install ./flatpak-build

      - name: setup flathub and runtimes
        run: |
          flatpak remote-add --user --if-not-exists flathub \
            https://flathub.org/repo/flathub.flatpakrepo
          flatpak install --user -y flathub \
            org.freedesktop.Platform/x86_64/24.08 \
            org.freedesktop.Sdk/x86_64/24.08

      - name: build flatpak
        working-directory: flatpak-build
        run: xonsh build.xsh --git-url xonsh/xonsh --no-deps

      - name: rename to nightly
        run: mv flatpak-build/xonsh.flatpak xonsh-nightly.flatpak

      - name: upload artifact
        uses: actions/upload-artifact@v7
        with:
          name: xonsh-nightly.flatpak
          path: xonsh-nightly.flatpak

      - name: upload to nightly-build release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          until gh release view nightly-build &>/dev/null; do sleep 5; done
          sha256sum xonsh-nightly.flatpak > xonsh-nightly.flatpak.sha256
          gh release upload nightly-build xonsh-nightly.flatpak xonsh-nightly.flatpak.sha256 --clobber
          python .github/scripts/update-nightly-release-descr.py line \
            --file xonsh-nightly.flatpak --sha "${{ github.sha }}"
