name: Stable Deployment Workflow
on:
  pull_request:
    branches:
      - master
  push:
    branches:
      - master
  schedule:
    - cron: "0 0 * * *"

permissions:
  contents: read
  checks: write
  pull-requests: write

jobs:
  lint:
    name: Lint PyFunceble

    runs-on: "${{ matrix.os }}"

    strategy:
      fail-fast: false
      matrix:
        python_version:
          - "3.12"
        os:
          - ubuntu-latest

    steps:
      - uses: actions/checkout@v6
        name: Clone repository

      - name: Set up Python ${{ matrix.python_version }}
        uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python_version }}

      - name: Install dependencies
        run: |
          pip install --upgrade pip
          pip install .[test,dev]

      - name: Lint PyFunceble with Pylint
        run: pylint PyFunceble

      - name: Lint tests with Pylint
        run: pylint tests

  deps_safety_check:
    name: Check the safety of our dependencies.

    runs-on: "${{ matrix.os }}"

    strategy:
      fail-fast: false
      matrix:
        python_version:
          - "3.12"
        os:
          - ubuntu-latest

    steps:
      - uses: actions/checkout@v6
        name: Clone repository

      - name: Set up Python ${{ matrix.python_version }}
        uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python_version }}

      - name: Install dependencies
        run: |
          pip install --upgrade pip
          pip install .
          pip install safety

      - name: Check the safety of our dependencies.
        run: safety check -i 51668 -i 62044 -i 67599 -i 70612

  sec_check:
    name: Check the safety of PyFunceble

    runs-on: "${{ matrix.os }}"

    strategy:
      fail-fast: false
      matrix:
        python_version:
          - "3.12"
        os:
          - ubuntu-latest

    steps:
      - uses: actions/checkout@v6
        name: Clone repository

      - name: Set up Python ${{ matrix.python_version }}
        uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python_version }}

      - name: Install dependencies
        run: |
          pip install --upgrade pip
          pip install .[test,dev]

      - name: Check the safety of the codebase with Bandit
        run: bandit --ini=setup.cfg -r PyFunceble

  test:
    needs: [lint, deps_safety_check, sec_check]
    name: "[${{ matrix.os }}-py${{ matrix.python_version }}] Test PyFunceble"

    runs-on: "${{ matrix.os }}"

    strategy:
      fail-fast: false
      matrix:
        python_version:
          - "3.10"
          - "3.11"
          - "3.12"
          - "3.13"
        os:
          - ubuntu-latest
          - macos-latest
          - windows-latest

    steps:
      - uses: actions/checkout@v6
        name: Clone repository

      - name: Set up Python ${{ matrix.python_version }}
        uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python_version }}

      - name: Install dependencies
        run: |
          pip install --upgrade pip
          pip install .[test]
          pip install coveralls

      - name: Test PyFunceble as defined by tox.ini
        run: |
          tox -c tox.ini

      - name: Upload Coverage
        continue-on-error: true
        run: |
          coveralls
        env:
          COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
          COVERALLS_PARALLEL: true

  coveralls:
    continue-on-error: true
    needs: test
    name: Finish Coveralls

    runs-on: "${{ matrix.os }}"

    strategy:
      fail-fast: false
      matrix:
        python_version:
          - "3.12"
        os:
          - ubuntu-latest

    steps:
      - name: Sending finish flag to coveralls.io
        uses: coverallsapp/github-action@v2
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          parallel-finished: true

  deploy_to_pypi:
    needs: test
    name: "Deploy 📦 to the PyPi"

    if: github.event_name == 'push' && github.ref == 'refs/heads/master'

    runs-on: "${{ matrix.os }}"

    strategy:
      fail-fast: false
      matrix:
        python_version:
          - "3.12"
        os:
          - ubuntu-latest

    steps:
      - uses: actions/checkout@v6
        name: Clone repository

      - name: Set up Python ${{ matrix.python_version }}
        uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python_version }}

      - name: Install dependencies
        run: |
          pip install --upgrade pip
          pip install twine wheel setuptools

      - name: Build 📦
        run: |
          python setup.py sdist bdist_wheel

      - name: Check 📦
        run: |
          twine check dist/*

      - name: Publish 📦 to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          password: ${{ secrets.PYPI_API_TOKEN }}
          skip-existing: true

  deploy_to_docker_hub:
    needs: test
    name: "Deploy 📦 to the Docker Hub"

    if: github.event_name == 'push' && github.ref == 'refs/heads/master'

    runs-on: "${{ matrix.os }}"

    strategy:
      fail-fast: false
      matrix:
        python_version:
          - "3.12"
        os:
          - ubuntu-latest

    env:
      DOCKER_PYTHON_VERSION: "3.12"
      BUILDER_CLONE_DIRNAME: pyfunceble_docker
      OUR_DOCKER_USERNAME: ${{ secrets.OUR_DOCKER_USERNAME }}
      OUR_DOCKER_PASSWORD: ${{ secrets.OUR_DOCKER_PASSWORD }}
      OUR_DOCKER_EMAIL: ${{ secrets.OUR_DOCKER_EMAIL }}

    steps:
      - uses: actions/checkout@v6
        name: Clone repository

      - uses: actions/checkout@v6
        name: Clone docker 📦 repository
        with:
          repository: PyFunceble/docker
          path: ${{ env.BUILDER_CLONE_DIRNAME }}/

      - name: Set up Python ${{ matrix.python_version }}
        uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python_version }}

      - name: Install dependencies
        run: |
          pip install --upgrade pip
          pip install setuptools wheel
          pip install ${{ env.BUILDER_CLONE_DIRNAME }}/.

      - name: Get version of builder
        run: |
          pyfunceble-docker-builder --version

      - name: Read package name
        run: |
          python setup.py --name

      - name: Read package version
        run: |
          python setup.py --version

      - name: Read commit ID
        run: |
          git log -1 --format=format:'%H'

      - name: Build, Check and Publish 📦
        run: >
          pyfunceble-docker-builder -b ${{ env.BUILDER_CLONE_DIRNAME }}/builder
          -p "$(python setup.py --name)"
          --pyfunceble-version="$(python setup.py --version)"
          --python-version="${DOCKER_PYTHON_VERSION}"
          --is-latest --publish --commit="$(git log -1 --format=format:'%H')"

  deploy_to_aur:
    needs: deploy_to_pypi
    name: "Deploy 📦 to the AUR"

    if: github.event_name == 'push' && github.ref == 'refs/heads/master'

    runs-on: "${{ matrix.os }}"

    strategy:
      fail-fast: false
      matrix:
        os:
          - ubuntu-latest

    container:
      image: archlinux

    steps:
      - name: Store the SSH key
        run: |
          echo "${{ secrets.AUR_SSH_KEY }}" | install -Dm600 /dev/stdin /root/.ssh/id_rsa

      - name: Get time for cache
        id: cache_time
        run: echo "time=$(date +%F-%T)" >> ${GITHUB_OUTPUT}

      - name: Set up cache
        uses: actions/cache@master
        with:
          path: /var/cache/pacman/pkg
          key: pacman-cache-x86_64-${{ steps.cache_time.outputs.time }}
          restore-keys: pacman-cache-x86_64-

      - name: Install dependencies
        run: |
          pacman -Syu --needed --noconfirm && \
          pacman -S --needed --noconfirm git binutils pacman-contrib openssh rsync python python-setuptools jq

      - uses: actions/checkout@v6
        name: Clone repository

      - name: Publish 📦 to the AUR - if necessary
        env:
          GIT_SSH_COMMAND: "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
        run: |
          aurRepoDir=/tmp/pyfunceble
          githubRepoDir="${PWD}"
          buildDir="/tmp/build"

          latest=$(python3 setup.py --version)

          if [[ $(python3 setup.py --name) == "PyFunceble-dev" ]]
          then
            licenseURL="https://raw.githubusercontent.com/funilrys/PdyFunceble/dev/LICENSE"
          else
            licenseURL="https://raw.githubusercontent.com/funilrys/PyFunceble/master/LICENSE"
          fi

          genericURL='https://files.pythonhosted.org/packages/source/${upstreamName::1}/${upstreamName}/${upstreamName}-${pkgver}.tar.gz'

          git config --global --add safe.directory ${GITHUB_WORKSPACE}
          git config --global --add safe.directory ${aurRepoDir}
          git config --global --add safe.directory ${githubRepoDir}
          git config --global user.name ${{ github.actor }}
          git config --global user.email ${{ secrets.GIT_EMAIL }}
          git clone ssh://aur@aur.archlinux.org/pyfunceble.git ${aurRepoDir}

          rsync --progress --delete -r --exclude={'*.gz','*.xz','.github','pkg','src','.git','LICENSE'} ${aurRepoDir}/ ${buildDir}/

          cd ${buildDir}

          current=$(grep -P "^pkgver" PKGBUILD | cut -d= -f2)

          echo "Previous version: ${current}"
          echo "New version: ${latest}"

          useradd makepkg
          chown makepkg:root . -R

          sed "/^pkgver=/s/.*/pkgver=${latest}/" -i PKGBUILD
          sed "/^pkgrel=/s/.*/pkgrel=1/" -i PKGBUILD
          sed "s,^source=(.*),source=(\"${genericURL}\" \"${licenseURL}\")," -i PKGBUILD

          su makepkg -c "updpkgsums"
          su makepkg -c "makepkg --printsrcinfo" > .SRCINFO

          rsync --progress --delete -r --exclude={'*.gz','*.xz','.github','pkg','src','.git','LICENSE'} ${buildDir}/ ${aurRepoDir}/

          cd ${aurRepoDir}

          git add .
          git diff --quiet --exit-code --cached || git commit -m "Update PyFunceble to v${latest}"
          git push origin master
