# Checks for each PR / push

name: QC

on:
  push:
    branches-ignore: ['l10*']
  pull_request:
    branches-ignore: ['l10*']

env:
  python_version: 3.9
  node_version: 16
  # The OS version must be set per job
  server_start_sleep: 60

  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  INVENTREE_DB_ENGINE: sqlite3
  INVENTREE_DB_NAME: inventree
  INVENTREE_MEDIA_ROOT: ../test_inventree_media
  INVENTREE_STATIC_ROOT: ../test_inventree_static
  INVENTREE_BACKUP_DIR: ../test_inventree_backup

jobs:
  paths-filter:
    name: Filter
    runs-on: ubuntu-latest

    outputs:
      server: ${{ steps.filter.outputs.server }}
      migrations: ${{ steps.filter.outputs.migrations }}
      frontend: ${{ steps.filter.outputs.frontend }}

    steps:
    - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
    - uses: dorny/paths-filter@v2
      id: filter
      with:
        filters: |
          server:
            - 'InvenTree/**'
            - 'requirements.txt'
            - 'requirements-dev.txt'
          migrations:
            - '**/migrations/**'
            - '.github/workflows**'
          frontend:
            - 'src/frontend/**'

  pep_style:
    name: Style [Python]
    runs-on: ubuntu-20.04

    needs: paths-filter
    if: needs.paths-filter.outputs.server == 'true'

    steps:
      - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
      - name: Environment Setup
        uses: ./.github/actions/setup
        with:
          dev-install: true
      - name: Run flake8
        run: flake8 InvenTree --extend-ignore=D

  javascript:
    name: Style - Classic UI [JS]
    runs-on: ubuntu-20.04

    needs: ['pep_style', 'pre-commit']

    steps:
      - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
      - name: Environment Setup
        uses: ./.github/actions/setup
        with:
          npm: true
          install: true
      - name: Check Templated JS Files
        run: |
          cd ci
          python3 check_js_templates.py
      - name: Lint Javascript Files
        run: |
          python InvenTree/manage.py prerender
          npx eslint InvenTree/InvenTree/static_i18n/i18n/*.js

  pre-commit:
    name: Style [pre-commit]
    runs-on: ubuntu-20.04
    needs: paths-filter
    if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.frontend == 'true'

    steps:
      - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
      - name: Set up Python ${{ env.python_version }}
        uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 # pin@v4.3.0
        with:
          python-version: ${{ env.python_version }}
          cache: 'pip'
      - name: Run pre-commit Checks
        uses: pre-commit/action@646c83fcd040023954eafda54b4db0192ce70507 # pin@v3.0.0
      - name: Check Version
        run: |
          pip install requests
          python3 ci/version_check.py

  mkdocs:
    name: Style [Documentation]
    runs-on: ubuntu-20.04

    needs: paths-filter

    steps:
      - name: Checkout Code
        uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
      - name: Set up Python ${{ env.python_version }}
        uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 # pin@v4.3.0
        with:
          python-version: ${{ env.python_version }}
      - name: Check Config
        run: |
          pip install pyyaml
          python docs/ci/check_mkdocs_config.py
      - name: Check Links
        run: |
          pip install linkcheckmd requests
          python -m linkcheckmd docs --recurse

  python:
    name: Tests - inventree-python
    runs-on: ubuntu-20.04

    needs: pre-commit

    env:
      wrapper_name: inventree-python
      INVENTREE_DB_ENGINE: django.db.backends.sqlite3
      INVENTREE_DB_NAME: ../inventree_unit_test_db.sqlite3
      INVENTREE_ADMIN_USER: testuser
      INVENTREE_ADMIN_PASSWORD: testpassword
      INVENTREE_ADMIN_EMAIL: test@test.com
      INVENTREE_PYTHON_TEST_SERVER: http://localhost:12345
      INVENTREE_PYTHON_TEST_USERNAME: testuser
      INVENTREE_PYTHON_TEST_PASSWORD: testpassword

    steps:
      - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
      - name: Environment Setup
        uses: ./.github/actions/setup
        with:
          apt-dependency: gettext poppler-utils
          dev-install: true
          update: true
          npm: true
      - name: Download Python Code For `${{ env.wrapper_name }}`
        run: git clone --depth 1 https://github.com/inventree/${{ env.wrapper_name }}
          ./${{ env.wrapper_name }}
      - name: Start InvenTree Server
        run: |
          invoke delete-data -f
          invoke import-fixtures
          invoke server -a 127.0.0.1:12345 &
          invoke wait
      - name: Run Tests For `${{ env.wrapper_name }}`
        run: |
          cd ${{ env.wrapper_name }}
          invoke check-server
          coverage run -m unittest discover -s test/

  docstyle:
    name: Style [Python Docstrings]
    runs-on: ubuntu-20.04

    needs: pre-commit
    continue-on-error: true

    steps:
      - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
      - name: Environment Setup
        uses: ./.github/actions/setup
        with:
          install: true
      - name: Run flake8
        run: flake8 InvenTree --statistics

  coverage:
    name: Tests - DB [SQLite] + Coverage
    runs-on: ubuntu-20.04

    needs: [ 'pep_style', 'pre-commit' ]
    continue-on-error: true # continue if a step fails so that coverage gets pushed

    env:
      INVENTREE_DB_NAME: ./inventree.sqlite
      INVENTREE_DB_ENGINE: sqlite3
      INVENTREE_PLUGINS_ENABLED: true
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

    steps:
      - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
      - name: Environment Setup
        uses: ./.github/actions/setup
        with:
          apt-dependency: gettext poppler-utils
          dev-install: true
          update: true
      - name: Data Export Test
        uses: ./.github/actions/migration
      - name: Test Translations
        run: invoke translate
      - name: Check Migration Files
        run: python3 ci/check_migration_files.py
      - name: Coverage Tests
        run: invoke test --coverage
      - name: Upload Coverage Report
        uses: coverallsapp/github-action@v2
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}

  postgres:
    name: Tests - DB [PostgreSQL]
    runs-on: ubuntu-20.04
    needs: [ 'pep_style', 'pre-commit' ]

    env:
      INVENTREE_DB_ENGINE: django.db.backends.postgresql
      INVENTREE_DB_USER: inventree
      INVENTREE_DB_PASSWORD: password
      INVENTREE_DB_HOST: '127.0.0.1'
      INVENTREE_DB_PORT: 5432
      INVENTREE_DEBUG: info
      INVENTREE_CACHE_HOST: localhost
      INVENTREE_PLUGINS_ENABLED: true

    services:
      postgres:
        image: postgres:14
        env:
          POSTGRES_USER: inventree
          POSTGRES_PASSWORD: password
        ports:
          - 5432:5432

      redis:
        image: redis
        ports:
          - 6379:6379

    steps:
      - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
      - name: Environment Setup
        uses: ./.github/actions/setup
        with:
          apt-dependency: gettext poppler-utils libpq-dev
          pip-dependency: psycopg2 django-redis>=5.0.0
          dev-install: true
          update: true
      - name: Run Tests
        run: invoke test
      - name: Data Export Test
        uses: ./.github/actions/migration

  mysql:
    name: Tests - DB [MySQL]
    runs-on: ubuntu-20.04

    needs: [ 'pep_style', 'pre-commit' ]
    if: github.event_name == 'push'

    env:
      # Database backend configuration
      INVENTREE_DB_ENGINE: django.db.backends.mysql
      INVENTREE_DB_USER: root
      INVENTREE_DB_PASSWORD: password
      INVENTREE_DB_HOST: '127.0.0.1'
      INVENTREE_DB_PORT: 3306
      INVENTREE_DEBUG: info
      INVENTREE_PLUGINS_ENABLED: true

    services:
      mysql:
        image: mysql:latest
        env:
          MYSQL_ALLOW_EMPTY_PASSWORD: yes
          MYSQL_DATABASE: ${{ env.INVENTREE_DB_NAME }}
          MYSQL_USER: inventree
          MYSQL_PASSWORD: password
          MYSQL_ROOT_PASSWORD: password
        options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s
          --health-retries=3
        ports:
          - 3306:3306

    steps:
      - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
      - name: Environment Setup
        uses: ./.github/actions/setup
        with:
          apt-dependency: gettext poppler-utils libmysqlclient-dev
          pip-dependency: mysqlclient
          dev-install: true
          update: true
      - name: Run Tests
        run: invoke test
      - name: Data Export Test
        uses: ./.github/actions/migration

  migration-tests:
    name: Tests - Migrations [PostgreSQL]
    runs-on: ubuntu-latest
    needs: paths-filter
    if: github.ref == 'refs/heads/master' && needs.paths-filter.outputs.migrations == 'true'

    env:
      INVENTREE_DB_ENGINE: django.db.backends.postgresql
      INVENTREE_DB_NAME: inventree
      INVENTREE_DB_USER: inventree
      INVENTREE_DB_PASSWORD: password
      INVENTREE_DB_HOST: '127.0.0.1'
      INVENTREE_DB_PORT: 5432
      INVENTREE_DEBUG: info
      INVENTREE_PLUGINS_ENABLED: false

    services:
      postgres:
        image: postgres:14
        env:
          POSTGRES_USER: inventree
          POSTGRES_PASSWORD: password
        ports:
          - 5432:5432

    steps:
      - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
      - name: Environment Setup
        uses: ./.github/actions/setup
        with:
          apt-dependency: gettext poppler-utils libpq-dev
          pip-dependency: psycopg2
          dev-install: true
          update: true
      - name: Run Tests
        run: invoke test --migrations --report

  migrations-checks:
    name: Tests - Full Migration [SQLite]
    runs-on: ubuntu-latest
    needs: paths-filter
    if: github.ref == 'refs/heads/master' && needs.paths-filter.outputs.migrations == 'true'

    env:
      INVENTREE_DB_ENGINE: sqlite3
      INVENTREE_DB_NAME: /home/runner/work/InvenTree/db.sqlite3
      INVENTREE_DEBUG: info
      INVENTREE_PLUGINS_ENABLED: false

    steps:
    - uses: actions/checkout@v3
      name: Checkout Code
    - name: Environment Setup
      uses: ./.github/actions/setup
      with:
        install: true
    - name: Fetch Database
      run: git clone --depth 1 https://github.com/inventree/test-db ./test-db

    - name: Latest Database
      run: |
        cp test-db/latest.sqlite3 /home/runner/work/InvenTree/db.sqlite3
        chmod +rw /home/runner/work/InvenTree/db.sqlite3
        invoke migrate

    - name: 0.10.0 Database
      run: |
        rm /home/runner/work/InvenTree/db.sqlite3
        cp test-db/stable_0.10.0.sqlite3 /home/runner/work/InvenTree/db.sqlite3
        chmod +rw /home/runner/work/InvenTree/db.sqlite3
        invoke migrate

    - name: 0.11.0 Database
      run: |
        rm /home/runner/work/InvenTree/db.sqlite3
        cp test-db/stable_0.11.0.sqlite3 /home/runner/work/InvenTree/db.sqlite3
        chmod +rw /home/runner/work/InvenTree/db.sqlite3
        invoke migrate

    - name: 0.12.0 Database
      run: |
        rm /home/runner/work/InvenTree/db.sqlite3
        cp test-db/stable_0.12.0.sqlite3 /home/runner/work/InvenTree/db.sqlite3
        chmod +rw /home/runner/work/InvenTree/db.sqlite3
        invoke migrate

  platform_ui:
    name: Tests - Platform UI
    runs-on: ubuntu-20.04
    timeout-minutes: 60
    needs: ['pre-commit', 'paths-filter']
    if: needs.paths-filter.outputs.frontend == 'true'
    env:
      INVENTREE_DB_ENGINE: sqlite3
      INVENTREE_DB_NAME: /home/runner/work/InvenTree/db.sqlite3
      INVENTREE_DEBUG: True
      INVENTREE_PLUGINS_ENABLED: false

    steps:
      - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
      - name: Environment Setup
        uses: ./.github/actions/setup
        with:
          npm: true
          install: true
          update: true
      - name: Set up test data
        run: invoke setup-test -i
      - name: Install dependencies
        run: inv frontend-compile
      - name: Install Playwright Browsers
        run: cd src/frontend && npx playwright install --with-deps
      - name: Run Playwright tests
        run: cd src/frontend &&  npx playwright test
      - uses: actions/upload-artifact@v3
        if: always()
        with:
          name: playwright-report
          path: src/frontend/playwright-report/
          retention-days: 30

  platform_ui_build:
    name: Build - UI Platform
    runs-on: ubuntu-20.04
    timeout-minutes: 60

    steps:
      - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v3.1.0
      - name: Environment Setup
        uses: ./.github/actions/setup
        with:
          npm: true
      - name: Install dependencies
        run: cd src/frontend && yarn install
      - name: Build frontend
        run: cd src/frontend && npm run build
      - name: Zip frontend
        run: |
          cd InvenTree/web/static
          zip -r frontend-build.zip web/
      - uses: actions/upload-artifact@v3
        with:
          name: frontend-build
          path: InvenTree/web/static/web
