Skip to content
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
2d770d4
Attempt to fix UI coverage
SchrodingersGat Jun 2, 2026
9fc4036
Update CI workflows:
SchrodingersGat Jun 2, 2026
30ee59e
Restore line
SchrodingersGat Jun 2, 2026
a430c95
Simplify test
SchrodingersGat Jun 2, 2026
b839c71
Merge branch 'master' into ui-coverage
SchrodingersGat Jun 2, 2026
93e35fe
Simplify test matrix
SchrodingersGat Jun 2, 2026
023f463
Fix env vars
SchrodingersGat Jun 2, 2026
32ebb47
Adjust matrix
SchrodingersGat Jun 2, 2026
ad1aae8
Adjust output names
SchrodingersGat Jun 2, 2026
6657294
Fix paths
SchrodingersGat Jun 2, 2026
b7a66ef
Simplify qc_checks
SchrodingersGat Jun 2, 2026
d54053f
Merge branch 'master' into ui-coverage
SchrodingersGat Jun 2, 2026
64a72a7
Revert missing line
SchrodingersGat Jun 2, 2026
b9a8ced
Simplify coverage calls
SchrodingersGat Jun 3, 2026
5ca3d5b
Run firefox test against port 8000
SchrodingersGat Jun 3, 2026
cc9d82b
Fix VITE_COVERAGE env var
SchrodingersGat Jun 3, 2026
3900262
Capture browser name in report output
SchrodingersGat Jun 3, 2026
cc36fe9
Increase timeout again
SchrodingersGat Jun 3, 2026
ac7f6c2
Enhanced feedback from playwright startup
SchrodingersGat Jun 3, 2026
7b27b04
Split UI checks into separate file
SchrodingersGat Jun 3, 2026
96d8b92
Merge branch 'master' into ui-coverage
SchrodingersGat Jun 3, 2026
c080d57
Fix workflow deps
SchrodingersGat Jun 3, 2026
2f0ad21
Shard chromium build
SchrodingersGat Jun 3, 2026
f0c7a8a
Adjust reporter type
SchrodingersGat Jun 3, 2026
731ca18
Reduce uncessesary build steps
SchrodingersGat Jun 3, 2026
b335262
Merge commit 'a0b2452ba5918d175df3aea0eade3a1aea6363a8' into ui-coverage
SchrodingersGat Jun 4, 2026
31c1ba4
Tweak paths filter
SchrodingersGat Jun 4, 2026
695d451
Reduce retries
SchrodingersGat Jun 4, 2026
8fb6825
Also generate HTML reports
SchrodingersGat Jun 4, 2026
f5f46f8
Tweak reporter output
SchrodingersGat Jun 4, 2026
9414c8f
Merge branch 'master' into ui-coverage
SchrodingersGat Jun 4, 2026
cf67281
Merge branch 'master' into ui-coverage
SchrodingersGat Jun 4, 2026
8bffbc6
Fix custom splash URLs
SchrodingersGat Jun 4, 2026
2070f53
Fix envs for customization tests
SchrodingersGat Jun 4, 2026
a190b8f
Shard the firefox runner too
SchrodingersGat Jun 4, 2026
c891574
Ignore customization tests for firefox too
SchrodingersGat Jun 4, 2026
a81eeff
Don't upload if tests fail
SchrodingersGat Jun 4, 2026
297e95d
Merge commit '1b8217e8b3ebb961c7aadf2b4a7ac49b37cf8263' into ui-coverage
SchrodingersGat Jun 4, 2026
6f63fe8
Fix triggers
SchrodingersGat Jun 4, 2026
171f562
Remove merged test coverage
SchrodingersGat Jun 4, 2026
ecf3bb0
Pin download action
SchrodingersGat Jun 4, 2026
abbb938
Error if no artifact files found
SchrodingersGat Jun 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
383 changes: 383 additions & 0 deletions .github/workflows/frontend.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,383 @@
# Playwright testing for frontend code
# Runs the following tests:
# - Playwright tests in Firefox (against compiled frontend code)
# - Playwright tests in Chromium (coverage enabled, against vite frontend code)
# - Build frontend code and upload as artifact

name: Frontend

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

env:
python_version: 3.11
node_version: 24
# The OS version must be set per job
server_start_sleep: 60

GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INVENTREE_DB_ENGINE: postgresql
INVENTREE_DB_NAME: inventree
INVENTREE_DB_HOST: "127.0.0.1"
INVENTREE_DB_PORT: 5432
INVENTREE_DB_USER: inventree_user
INVENTREE_DB_PASSWORD: inventree_password
INVENTREE_DEBUG: true
INVENTREE_PLUGINS_ENABLED: false
INVENTREE_MEDIA_ROOT: /home/runner/work/InvenTree/test_inventree_media
INVENTREE_STATIC_ROOT: /home/runner/work/InvenTree/test_inventree_static
INVENTREE_BACKUP_DIR: /home/runner/work/InvenTree/test_inventree_backup
INVENTREE_SITE_URL: http://localhost:8000

permissions:
contents: read

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 }}
api: ${{ steps.filter.outputs.api }}
force: ${{ steps.force.outputs.force }}
cicd: ${{ steps.filter.outputs.cicd }}
requirements: ${{ steps.filter.outputs.requirements }}
runner-perf: ${{ steps.runner-perf.outputs.runner }}
performance: ${{ steps.performance.outputs.force-performance }}
submit-performance: ${{ steps.runner-perf.outputs.submit-performance }}
Comment thread
SchrodingersGat marked this conversation as resolved.
Outdated

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # pin@v6.0.2
with:
persist-credentials: false
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # pin@v4.0.1
id: filter
with:
filters: |
server:
- 'src/backend/InvenTree/**'
- 'src/backend/requirements.txt'
- 'src/backend/requirements-dev.txt'
migrations:
- '**/test_migrations.py'
- '**/migrations/**'
- '.github/workflows**'
- 'src/backend/requirements.txt'
api:
- 'src/backend/InvenTree/InvenTree/api_version.py'
frontend:
- 'src/frontend/**'
cicd:
- '.github/workflows/**'
requirements:
- 'src/backend/requirements.txt'
- 'src/backend/requirements-dev.txt'
- 'docs/requirements.txt'
- 'contrib/dev_reqs/requirements.txt'
- name: Is CI being forced?
run: echo "force=true" >> $GITHUB_OUTPUT
id: force
if: |
contains(github.event.pull_request.labels.*.name, 'dependency') ||
contains(github.event.pull_request.labels.*.name, 'full-run')
- name: Is performance testing being forced?
run: echo "force-performance=true" >> $GITHUB_OUTPUT
id: performance
if: |
contains(github.event.pull_request.labels.*.name, 'performance-run')
- name: Which runner to use?
env:
GITHUB_REF: ${{ github.ref }}
PERFORMANCE: ${{ steps.performance.outputs.force-performance }}
id: runner-perf
# decide if we are running in inventree/inventree -> use codspeed-macro runner else ubuntu-24.04
run: |
is_main_push=false
if [[ '${{ github.event_name }}' == 'push' && "$GITHUB_REF" == 'refs/heads/master' ]]; then
is_main_push=true
fi
if [[ '${{ github.repository }}' == 'inventree/InvenTree' && ( "$is_main_push" == 'true' || "$PERFORMANCE" == 'true' ) ]]; then
echo "runner=codspeed-macro" >> "$GITHUB_OUTPUT"
echo "submit-performance=true" >> "$GITHUB_OUTPUT"
else
echo "runner=ubuntu-24.04" >> "$GITHUB_OUTPUT"
echo "submit-performance=false" >> "$GITHUB_OUTPUT"
fi
Comment thread
SchrodingersGat marked this conversation as resolved.
Outdated

build:
name: Build
runs-on: ubuntu-24.04
timeout-minutes: 60

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # pin@v6.0.2
with:
persist-credentials: false
- 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 && yarn run compile && yarn run lib && yarn run build
- name: Write version file - SHA
run: cd src/backend/InvenTree/web/static/web/.vite && echo "$GITHUB_SHA" > sha.txt
- name: Zip frontend
run: |
cd src/backend/InvenTree/web/static
zip -r frontend-build.zip web/ web/.vite
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # pin@v7.0.1
with:
name: frontend-build
path: src/backend/InvenTree/web/static/web
include-hidden-files: true

firefox:
name: Tests [Firefox]
runs-on: ubuntu-24.04
timeout-minutes: 60
needs: ["build", "paths-filter"]
if: needs.paths-filter.outputs.frontend == 'true' || needs.paths-filter.outputs.force == 'true'
services:
postgres:
image: postgres:17
env:
POSTGRES_DB: inventree
POSTGRES_USER: inventree_user
POSTGRES_PASSWORD: inventree_password
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U testuser"
--health-interval 10s
--health-timeout 5s
--health-retries 5

env:
VITE_COVERAGE: false

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # pin@v6.0.2
with:
persist-credentials: false
- name: Environment Setup
uses: ./.github/actions/setup
with:
npm: true
install: true
update: true
apt-dependency: gettext postgresql-client libpq-dev
pip-dependency: psycopg2
- name: Set up test data
run: |
invoke dev.setup-test -iv
invoke int.rebuild-thumbnails
- name: Install dependencies
run: invoke int.frontend-compile --extract
- name: Cache Playwright browsers
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # pin@v4.3.0
id: playwright-cache
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ hashFiles('src/frontend/yarn.lock') }}
- name: Install Playwright browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: cd src/frontend && npx playwright install --with-deps
- name: Install Playwright OS dependencies
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: cd src/frontend && npx playwright install-deps
- name: Install Sample Plugin
run: |
pip install -U inventree-plugin-creator
create-inventree-plugin --default
cd MyCustomPlugin && pip install -e . && cd frontend && npm install && npm run translate && npm run build
- name: Run Playwright tests
id: tests
run: |
cd src/frontend
cp ./tests/fixtures/playwright_custom_logo.png ../backend/InvenTree/InvenTree/static/img/playwright_custom_logo.png
cp ./tests/fixtures/playwright_custom_splash.png ../backend/InvenTree/InvenTree/static/img/playwright_custom_splash.png
invoke static
PLAYWRIGHT_BASE_URL=http://localhost:8000 npx playwright test --project=firefox
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # pin@v7.0.1
if: ${{ !cancelled() && steps.tests.outcome == 'failure' }}
with:
name: playwright-report-firefox
path: src/frontend/playwright-report/
retention-days: 14

chromium:
name: Tests [Chromium ${{ matrix.shard }} / 4]
runs-on: ubuntu-24.04
timeout-minutes: 60
needs: ["build", "paths-filter"]
if: needs.paths-filter.outputs.frontend == 'true' || needs.paths-filter.outputs.force == 'true'
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3, 4]
services:
postgres:
image: postgres:17
env:
POSTGRES_DB: inventree
POSTGRES_USER: inventree_user
POSTGRES_PASSWORD: inventree_password
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U testuser"
--health-interval 10s
--health-timeout 5s
--health-retries 5

env:
COVERAGE: true
VITE_COVERAGE: true

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # pin@v6.0.2
with:
persist-credentials: false
- name: Environment Setup
uses: ./.github/actions/setup
with:
npm: true
install: true
update: true
apt-dependency: gettext postgresql-client libpq-dev
pip-dependency: psycopg2
- name: Set up test data
run: |
invoke dev.setup-test -iv
invoke int.rebuild-thumbnails
- name: Install dependencies
run: invoke int.frontend-compile --extract
- name: Cache Playwright browsers
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # pin@v4.3.0
id: playwright-cache
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ hashFiles('src/frontend/yarn.lock') }}
- name: Install Playwright browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: cd src/frontend && npx playwright install --with-deps
- name: Install Playwright OS dependencies
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: cd src/frontend && npx playwright install-deps
- name: Install Sample Plugin
run: |
pip install -U inventree-plugin-creator
create-inventree-plugin --default
cd MyCustomPlugin && pip install -e . && cd frontend && npm install && npm run translate && npm run build
- name: Playwright [${{ matrix.shard }} / 4]
id: tests
run: |
cd src/frontend
cp ./tests/fixtures/playwright_custom_logo.png ../backend/InvenTree/InvenTree/static/img/playwright_custom_logo.png
cp ./tests/fixtures/playwright_custom_splash.png ../backend/InvenTree/InvenTree/static/img/playwright_custom_splash.png
npx nyc playwright test --project=chromium --shard=${{ matrix.shard }}/4
- name: Upload Blob Report [${{ matrix.shard }} / 4]
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # pin@v7.0.1
id: blob-upload
if: always()
with:
name: blob-report-${{ matrix.shard }}
path: blob-report/
retention-days: 1
- name: Upload Coverage Artifact [${{ matrix.shard }} / 4]
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # pin@v7.0.1
id: coverage-upload
if: always()
with:
name: coverage-${{ matrix.shard }}
path: .nyc_output/
retention-days: 1
- name: Playwright Report [${{ matrix.shard }} / 4]
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # pin@v7.0.1
if: ${{ !cancelled() && steps.tests.outcome == 'failure' }}
with:
name: playwright-report-chromium
path: src/frontend/playwright-report/
retention-days: 7

# Recombine the coverage reports from the 4 shards, and upload to Codecov
coverage:
name: Merge coverage reports and upload to Codecov
runs-on: ubuntu-latest
needs: chromium
timeout-minutes: 30
if: always()

steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # pin@v6.0.2
with:
persist-credentials: false

- name: Environment Setup
uses: ./.github/actions/setup
with:
npm: true
install: false
update: false

- name: Download Blob Reports
uses: actions/download-artifact@v8

Check failure

Code scanning / zizmor

unpinned action reference: action is not pinned to a hash (required by blanket policy) Error

unpinned action reference: action is not pinned to a hash (required by blanket policy)
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
with:
pattern: blob-report-*
path: all-blob-reports/
merge-multiple: true

- name: Merge Playwright reports
run: npx playwright merge-reports --reporter html ./all-blob-reports

- name: Upload Merged HTML Report
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # pin@v7.0.1
with:
name: playwright-report
path: playwright-report/
retention-days: 7

- name: Download Coverage Artifacts
uses: actions/download-artifact@v8

Check failure

Code scanning / zizmor

unpinned action reference: action is not pinned to a hash (required by blanket policy) Error

unpinned action reference: action is not pinned to a hash (required by blanket policy)
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
with:
pattern: coverage-*
path: all-coverage/
merge-multiple: true

- name: Merge Coverage Reports
run: |
mkdir -p .nyc_output
cp all-coverage/*.json .nyc_output/ 2>/dev/null || true
npx nyc merge .nyc_output merged-coverage.json
npx nyc report \
--tempdir .nyc_output \
--reporter=lcov \
--reporter=text-summary \
--report-dir ./coverage \

- name: Upload coverage reports to Codecov
if: ${{ !cancelled() && github.ref == 'refs/heads/master' }}
uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # pin@v6.0.1
with:
token: ${{ secrets.CODECOV_TOKEN }}
slug: inventree/InvenTree
flags: web
files: ./coverage/lcov.info

# - name: Upload bundler info
# if: ${{ !cancelled() && github.ref == 'refs/heads/master' }}
# env:
# CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
# run: |
# cd src/frontend
# yarn install
# yarn run build
Loading
Loading