Compare commits

..

5 Commits

Author SHA1 Message Date
Oliver d3a58ea2b1
Bump InvenTree software version to 1.1.1 (#10745) 2025-11-03 11:14:42 +11:00
github-actions[bot] 555455a9d1
fix: typo ins installer stops script from working (#10744) (#10746)
(cherry picked from commit e1bf67b32c)

Co-authored-by: Matthias Mair <code@mjmair.com>
2025-11-03 00:43:11 +01:00
github-actions[bot] e834ea8aa7
Docs fix (#10738) (#10739)
* Fix heading in helpers.md

* Helper func docs

(cherry picked from commit 46615e447b)

Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
2025-11-03 10:30:08 +11:00
github-actions[bot] e23e3730b2
fix uv (#10742) (#10743)
https://github.com/inventree/InvenTree/security/dependabot/248
(cherry picked from commit d7daf660ef)

Co-authored-by: Matthias Mair <code@mjmair.com>
2025-11-03 10:24:45 +11:00
Oliver 34436f933d
Bump version number to 1.1.0 (#10733)
* Bump version number to 1.1.0

* Add release tag to CHANGELOG.md

* Cleanup

* Remove links
2025-11-02 13:18:23 +11:00
973 changed files with 303828 additions and 435830 deletions

View File

@ -1,7 +1,9 @@
# Dockerfile for the InvenTree devcontainer # Dockerfile for the InvenTree devcontainer
# This container is used for development of the InvenTree project, and includes all necessary dependencies for both backend and frontend development.
FROM mcr.microsoft.com/devcontainers/python:3.12-trixie@sha256:5440cb68898d190ad6c6e8a4634ce89d0645bea47f9c8beb75612bb8e3983711 # In contrast with the "production" image (which is based on an Alpine image)
# we use a Debian-based image for the devcontainer
FROM mcr.microsoft.com/devcontainers/python:3.11-bookworm@sha256:5140e54af7a0399a4932dd4c4653d085fcf451b093d7424867df1828ffbb9b81
# InvenTree paths # InvenTree paths
ENV INVENTREE_HOME="/home/inventree" ENV INVENTREE_HOME="/home/inventree"
@ -23,24 +25,19 @@ RUN chmod +x init.sh
# Install required base packages # Install required base packages
RUN apt update && apt install -y \ RUN apt update && apt install -y \
python3-dev python3-venv \ python3.11-dev python3.11-venv \
postgresql-client \ postgresql-client \
libldap2-dev libsasl2-dev \ libldap2-dev libsasl2-dev \
libpango-1.0-0 libcairo2 \ libpango1.0-0 libcairo2 \
poppler-utils weasyprint poppler-utils weasyprint
# Install packages required for frontend development # Install packages required for frontend development
RUN apt install -y nodejs npm RUN apt install -y \
yarn nodejs npm
# Update to the latest stable node version # Update to the latest stable node version
RUN npm install -g n --ignore-scripts && n lts RUN npm install -g n --ignore-scripts && n lts
# Install yarn RUN yarn config set network-timeout 600000 -g
RUN npm install -g yarn
# Ensure node and yarn are available at the command line
RUN node --version && yarn --version
RUN yarn config set httpTimeout 600000 --home
ENTRYPOINT ["/bin/bash", "./init.sh"] ENTRYPOINT ["/bin/bash", "./init.sh"]

79
.devops/test_stats.yml Normal file
View File

@ -0,0 +1,79 @@
trigger:
batch: true
branches:
include:
- master
- stable
- refs/tags/*
paths:
include:
- src/backend
pool:
vmImage: ubuntu-latest
strategy:
matrix:
Python39:
PYTHON_VERSION: '3.9'
maxParallel: 3
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '$(PYTHON_VERSION)'
architecture: 'x64'
- task: PythonScript@0
displayName: 'Export project path'
inputs:
scriptSource: 'inline'
script: |
"""Search all subdirectories for `manage.py`."""
from glob import iglob
from os import path
# Python >= 3.5
manage_py = next(iglob(path.join('**', 'manage.py'), recursive=True), None)
if not manage_py:
raise SystemExit('Could not find a Django project')
project_location = path.dirname(path.abspath(manage_py))
print('Found Django project in', project_location)
print('##vso[task.setvariable variable=projectRoot]{}'.format(project_location))
- script: |
python -m pip install --upgrade pip setuptools wheel uv
uv pip install --require-hashes -r src/backend/requirements.txt
uv pip install --require-hashes -r src/backend/requirements-dev.txt
sudo apt-get install poppler-utils
sudo apt-get install libpoppler-dev
uv pip install unittest-xml-reporting coverage invoke
displayName: 'Install prerequisites'
env:
UV_SYSTEM_PYTHON: 1
- script: |
pushd '$(projectRoot)'
invoke update --uv
coverage run manage.py test --testrunner xmlrunner.extra.djangotestrunner.XMLTestRunner --no-input
coverage xml -i
displayName: 'Run tests'
env:
INVENTREE_DB_ENGINE: sqlite3
INVENTREE_DB_NAME: inventree
INVENTREE_MEDIA_ROOT: ./media
INVENTREE_STATIC_ROOT: ./static
INVENTREE_BACKUP_DIR: ./backup
INVENTREE_SITE_URL: http://localhost:8000
INVENTREE_PLUGINS_ENABLED: true
UV_SYSTEM_PYTHON: 1
INVENTREE_DEBUG: true
INVENTREE_LOG_LEVEL: INFO
- task: PublishTestResults@2
inputs:
testResultsFiles: "**/TEST-*.xml"
testRunTitle: 'Python $(PYTHON_VERSION)'
condition: succeededOrFailed()
- task: PublishCodeCoverageResults@2
inputs:
summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml'

3
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,3 @@
polar: inventree
github: inventree
custom: [paypal.me/inventree]

View File

@ -13,5 +13,5 @@ runs:
invoke export-records -f data.json invoke export-records -f data.json
python3 ./src/backend/InvenTree/manage.py flush --noinput python3 ./src/backend/InvenTree/manage.py flush --noinput
invoke migrate invoke migrate
invoke import-records -c -f data.json --strict invoke import-records -c -f data.json
invoke import-records -c -f data.json --strict invoke import-records -c -f data.json

View File

@ -15,10 +15,6 @@ inputs:
required: false required: false
description: 'Install the InvenTree requirements?' description: 'Install the InvenTree requirements?'
default: 'false' default: 'false'
static:
required: false
description: 'Should the static files be built?'
default: 'false'
dev-install: dev-install:
required: false required: false
description: 'Install the InvenTree development requirements?' description: 'Install the InvenTree development requirements?'
@ -39,14 +35,14 @@ runs:
using: 'composite' using: 'composite'
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
with: with:
persist-credentials: false persist-credentials: false
# Python installs # Python installs
- name: Set up Python ${{ env.python_version }} - name: Set up Python ${{ env.python_version }}
if: ${{ inputs.python == 'true' && env.python_version != '3.14' }} if: ${{ inputs.python == 'true' }}
uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0 uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # pin@v5.0.0
with: with:
python-version: ${{ env.python_version }} python-version: ${{ env.python_version }}
cache: pip cache: pip
@ -55,11 +51,6 @@ runs:
src/backend/requirements-dev.txt src/backend/requirements-dev.txt
contrib/container/requirements.txt contrib/container/requirements.txt
contrib/dev_reqs/requirements.txt contrib/dev_reqs/requirements.txt
- name: Setup Python 3.14
if: ${{ inputs.python == 'true' && env.python_version == '3.14' }}
uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0
with:
python-version: ${{ env.python_version }}
- name: Install Base Python Dependencies - name: Install Base Python Dependencies
if: ${{ inputs.python == 'true' }} if: ${{ inputs.python == 'true' }}
shell: bash shell: bash
@ -98,16 +89,12 @@ runs:
- name: Install dev requirements - name: Install dev requirements
if: ${{ inputs.dev-install == 'true' || inputs.install == 'true' }} if: ${{ inputs.dev-install == 'true' || inputs.install == 'true' }}
shell: bash shell: bash
run: invoke install --dev run: uv pip install --require-hashes -r src/backend/requirements-dev.txt
- name: Run invoke install - name: Run invoke install
if: ${{ inputs.install == 'true' }} if: ${{ inputs.install == 'true' }}
shell: bash shell: bash
run: invoke install run: invoke install --uv
- name: Run invoke update - name: Run invoke update
if: ${{ inputs.update == 'true' }} if: ${{ inputs.update == 'true' }}
shell: bash shell: bash
run: invoke update --skip-backup --skip-static --no-frontend run: invoke update --uv --skip-backup --skip-static
- name: Collect static files
if: ${{ inputs.static == 'true' }}
shell: bash
run: invoke static --skip-plugins

View File

@ -4,8 +4,6 @@ updates:
directory: / directory: /
schedule: schedule:
interval: weekly interval: weekly
cooldown:
default-days: 7
groups: groups:
dependencies: dependencies:
patterns: patterns:
@ -15,15 +13,11 @@ updates:
directory: /contrib/container directory: /contrib/container
schedule: schedule:
interval: weekly interval: weekly
cooldown:
default-days: 7
- package-ecosystem: docker - package-ecosystem: docker
directory: /.devcontainer directory: /.devcontainer
schedule: schedule:
interval: weekly interval: weekly
cooldown:
default-days: 7
- package-ecosystem: pip - package-ecosystem: pip
directories: directories:
@ -34,8 +28,6 @@ updates:
schedule: schedule:
interval: weekly interval: weekly
day: friday day: friday
cooldown:
default-days: 7
groups: groups:
dependencies: dependencies:
patterns: patterns:
@ -49,8 +41,6 @@ updates:
- /src/frontend - /src/frontend
schedule: schedule:
interval: weekly interval: weekly
cooldown:
default-days: 7
groups: groups:
dependencies: dependencies:
patterns: patterns:

View File

@ -1,101 +0,0 @@
"""Script to check a data file exported using the 'export-records' command.
This script is intended to be used as part of the CI workflow,
in conjunction with the "workflows/import_export.yaml" workflow.
In reads the exported data file, to ensure that:
- The file can be read and parsed as JSON
- The file contains the expected metadata
- The file contains the expected plugin configuration
- The file contains the expected plugin database records
"""
PLUGIN_KEY = 'dummy_app_plugin'
PLUGIN_SLUG = 'dummy-app-plugin'
import argparse
import json
import os
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Check exported data file')
parser.add_argument('datafile', help='Path to the exported data file (JSON)')
args = parser.parse_args()
if not os.path.isfile(args.datafile):
print(f'Error: File not found: {args.datafile}')
exit(1)
with open(args.datafile, encoding='utf-8') as f:
try:
data = json.load(f)
print(f'Successfully loaded data from {args.datafile}')
print(f'Number of records: {len(data)}')
except json.JSONDecodeError as e:
print(f'Error: Failed to parse JSON file: {e}')
exit(1)
found_metadata = False
found_installed_apps = False
found_plugin_config = False
plugin_data_records = {}
# Inspect the data and check that it has the expected structure and content.
for entry in data:
# Check metadata entry for expected values
if entry.get('metadata', False):
print('Found metadata entry')
found_metadata = True
expected_apps = ['InvenTree', 'allauth', 'dbbackup', PLUGIN_KEY]
apps = entry.get('installed_apps', [])
for app in expected_apps:
if app not in apps:
print(f'- Expected app "{app}" not found in installed apps list')
exit(1)
found_installed_apps = True
elif entry.get('model', None) == 'plugin.pluginconfig':
key = entry['fields']['key']
if key == PLUGIN_SLUG:
print(f'Found plugin configuration for plugin "{PLUGIN_KEY}"')
found_plugin_config = True
elif entry.get('model', None) == f'{PLUGIN_KEY}.examplemodel':
key = entry['fields']['key']
value = entry['fields']['value']
plugin_data_records[key] = value
if not found_metadata:
print('Error: No metadata entry found in exported data')
exit(1)
if not found_installed_apps:
print(
f'Error: Plugin "{PLUGIN_KEY}" not found in installed apps list in metadata'
)
exit(1)
if not found_plugin_config:
print(f'Error: No plugin configuration found for plugin "{PLUGIN_KEY}"')
exit(1)
# Check the extracted plugin records
expected_keys = ['alpha', 'beta', 'gamma', 'delta']
for key in expected_keys:
if key not in plugin_data_records:
print(
f'Error: Expected plugin record with key "{key}" not found in exported data'
)
exit(1)
print('All checks passed successfully!')

View File

@ -264,7 +264,6 @@ def main() -> bool:
# Determine which docker tag we are going to use # Determine which docker tag we are going to use
docker_tags: Optional[list[str]] = None docker_tags: Optional[list[str]] = None
pkg_channel = None
if GITHUB_REF_TYPE == 'tag': if GITHUB_REF_TYPE == 'tag':
# GITHUB_REF should be of the form /refs/heads/<tag> # GITHUB_REF should be of the form /refs/heads/<tag>
@ -279,14 +278,10 @@ def main() -> bool:
docker_tags = [version_tag, 'stable'] if highest_release else [version_tag] docker_tags = [version_tag, 'stable'] if highest_release else [version_tag]
# Add release-line tag
pkg_channel = '.'.join(version_tag.split('.')[:2]) + '.x'
elif GITHUB_REF_TYPE == 'branch': elif GITHUB_REF_TYPE == 'branch':
# Otherwise we know we are targeting the 'master' branch # Otherwise we know we are targeting the 'master' branch
docker_tags = ['latest'] docker_tags = ['latest']
highest_release = False highest_release = False
pkg_channel = GITHUB_BASE_REF
else: else:
print('Unsupported branch / version combination:') print('Unsupported branch / version combination:')
@ -315,8 +310,6 @@ def main() -> bool:
if GITHUB_REF_TYPE == 'tag' and highest_release: if GITHUB_REF_TYPE == 'tag' and highest_release:
env_file.write('stable_release=true\n') env_file.write('stable_release=true\n')
env_file.write(f'pkg_channel={pkg_channel}\n')
return True return True

View File

@ -25,7 +25,7 @@ jobs:
) )
steps: steps:
- name: Backport Action - name: Backport Action
uses: sorenlouv/backport-github-action@8a6c0381851f43f9f1fddc7303f0e9015eb57b62 # v12.0.4 uses: sqren/backport-github-action@ad888e978060bc1b2798690dd9d03c4036560947 # pin@v9.2.2
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
auto_backport_label_prefix: backport-to- auto_backport_label_prefix: backport-to-

View File

@ -9,7 +9,7 @@ on:
- l10 - l10
env: env:
python_version: 3.12 python_version: 3.9
permissions: permissions:
contents: read contents: read
@ -31,7 +31,7 @@ jobs:
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false

View File

@ -39,10 +39,10 @@ jobs:
docker: ${{ steps.filter.outputs.docker }} docker: ${{ steps.filter.outputs.docker }}
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # pin@v3.0.2
id: filter id: filter
with: with:
filters: | filters: |
@ -62,12 +62,12 @@ jobs:
contents: read contents: read
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
python_version: 3.12 python_version: "3.11"
runs-on: ubuntu-latest # in the future we can try to use alternative runners here runs-on: ubuntu-latest # in the future we can try to use alternative runners here
steps: steps:
- name: Check out repo - name: Check out repo
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: Test Docker Image - name: Test Docker Image
@ -84,16 +84,6 @@ jobs:
docker run --rm inventree-test test -f /home/inventree/gunicorn.conf.py docker run --rm inventree-test test -f /home/inventree/gunicorn.conf.py
docker run --rm inventree-test test -f /home/inventree/src/backend/requirements.txt docker run --rm inventree-test test -f /home/inventree/src/backend/requirements.txt
docker run --rm inventree-test test -f /home/inventree/src/backend/InvenTree/manage.py docker run --rm inventree-test test -f /home/inventree/src/backend/InvenTree/manage.py
# Check that backend translations were compiled into the image (a few representative languages)
docker run --rm inventree-test test -f /home/inventree/src/backend/InvenTree/locale/de/LC_MESSAGES/django.mo
docker run --rm inventree-test test -f /home/inventree/src/backend/InvenTree/locale/fr/LC_MESSAGES/django.mo
docker run --rm inventree-test test -f /home/inventree/src/backend/InvenTree/locale/ru/LC_MESSAGES/django.mo
docker run --rm inventree-test test -f /home/inventree/src/backend/InvenTree/locale/zh_Hans/LC_MESSAGES/django.mo
# Check that frontend translations (lingui) were compiled into the static build output (a few representative languages)
docker run --rm inventree-test grep -q '"src/locales/de/messages.ts"' /home/inventree/src/backend/InvenTree/web/static/web/.vite/manifest.json
docker run --rm inventree-test grep -q '"src/locales/fr/messages.ts"' /home/inventree/src/backend/InvenTree/web/static/web/.vite/manifest.json
docker run --rm inventree-test grep -q '"src/locales/ru/messages.ts"' /home/inventree/src/backend/InvenTree/web/static/web/.vite/manifest.json
docker run --rm inventree-test grep -q '"src/locales/zh_Hans/messages.ts"' /home/inventree/src/backend/InvenTree/web/static/web/.vite/manifest.json
- name: Build Docker Image - name: Build Docker Image
# Build the development docker image (using docker-compose.yml) # Build the development docker image (using docker-compose.yml)
run: docker compose --project-directory . -f contrib/container/dev-docker-compose.yml build --no-cache run: docker compose --project-directory . -f contrib/container/dev-docker-compose.yml build --no-cache
@ -134,12 +124,12 @@ jobs:
contents: read contents: read
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
python_version: 3.12 python_version: "3.11"
runs-on: ubuntu-latest # in the future we can try to use alternative runners here runs-on: ubuntu-latest # in the future we can try to use alternative runners here
steps: steps:
- name: Check out repo - name: Check out repo
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: Run Migration Tests - name: Run Migration Tests
@ -158,16 +148,16 @@ jobs:
id-token: write id-token: write
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
python_version: 3.12 python_version: "3.11"
runs-on: ubuntu-latest # in the future we can try to use alternative runners here runs-on: ubuntu-latest # in the future we can try to use alternative runners here
steps: steps:
- name: Check out repo - name: Check out repo
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: Set Up Python ${{ env.python_version }} - name: Set Up Python ${{ env.python_version }}
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # pin@v6.0.0
with: with:
python-version: ${{ env.python_version }} python-version: ${{ env.python_version }}
- name: Version Check - name: Version Check
@ -178,13 +168,13 @@ jobs:
echo "git_commit_date=$(git show -s --format=%ci)" >> $GITHUB_ENV echo "git_commit_date=$(git show -s --format=%ci)" >> $GITHUB_ENV
- name: Set up QEMU - name: Set up QEMU
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0 uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # pin@v3.6.0
- name: Set up Docker Buildx - name: Set up Docker Buildx
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # pin@v3.11.1
- name: Set up cosign - name: Set up cosign
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # pin@v4.0.0
- name: Check if Dockerhub login is required - name: Check if Dockerhub login is required
id: docker_login id: docker_login
run: | run: |
@ -195,14 +185,14 @@ jobs:
fi fi
- name: Login to Dockerhub - name: Login to Dockerhub
if: github.event_name != 'pull_request' && steps.docker_login.outputs.skip_dockerhub_login != 'true' if: github.event_name != 'pull_request' && steps.docker_login.outputs.skip_dockerhub_login != 'true'
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # pin@v3.6.0
with: with:
username: ${{ secrets.DOCKER_USERNAME }} username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}
- name: Log into registry ghcr.io - name: Log into registry ghcr.io
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # pin@v3.6.0
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
@ -211,16 +201,16 @@ jobs:
- name: Extract Docker metadata - name: Extract Docker metadata
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
id: meta id: meta
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0 uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # pin@v5.8.0
with: with:
images: | images: |
inventree/inventree inventree/inventree
ghcr.io/${{ github.repository }} ghcr.io/${{ github.repository }}
- uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1 - uses: depot/setup-action@b0b1ea4f69e92ebf5dea3f8713a1b0c37b2126a5 # pin@v1
- name: Push Docker Images - name: Push Docker Images
id: push-docker id: push-docker
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
uses: depot/build-push-action@98e78adca7817480b8185f474a400b451d74e287 # v1 uses: depot/build-push-action@9785b135c3c76c33db102e45be96a25ab55cd507 # pin@v1
with: with:
project: jczzbjkk68 project: jczzbjkk68
context: . context: .

View File

@ -1,312 +0,0 @@
# 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*", "dependabot/**", "backport/**"]
pull_request:
branches-ignore: ["l10*"]
env:
python_version: 3.12
node_version: 24
plugin_creator_version: 1.20.0
# 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:
frontend: ${{ steps.filter.outputs.frontend }}
force: ${{ steps.force.outputs.force }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
id: filter
with:
filters: |
frontend:
- 'src/frontend/**'
- 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')
build:
name: Build
runs-on: ubuntu-24.04
timeout-minutes: 60
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
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 # v7.0.1
with:
name: frontend-build
path: src/backend/InvenTree/web/static/web
include-hidden-files: true
firefox:
name: Tests [Firefox ${{ matrix.shard }} / 2]
runs-on: ubuntu-24.04
timeout-minutes: 60
needs: ["build", "paths-filter"]
if: github.ref == 'refs/heads/master' || needs.paths-filter.outputs.frontend == 'true' || needs.paths-filter.outputs.force == 'true'
strategy:
fail-fast: false
matrix:
shard: [1, 2]
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
permissions:
contents: read # Required for actions/checkout
id-token: write # Required for GitHub OIDC
env:
VITE_COVERAGE: false
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
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@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.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==${{ env.plugin_creator_version }}
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
env INVENTREE_CUSTOM_SPLASH="img/playwright_custom_splash.png" INVENTREE_CUSTOM_LOGO="img/playwright_custom_logo.png" PLAYWRIGHT_BASE_URL=http://localhost:8000 npx playwright test --project=firefox --shard=${{ matrix.shard }}/2
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: ${{ !cancelled() && steps.tests.outcome == 'failure' }}
with:
name: playwright-report-firefox-${{ matrix.shard }}
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: github.ref == 'refs/heads/master' || 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
permissions:
contents: read # Required for actions/checkout
id-token: write # Required for GitHub OIDC
env:
COVERAGE: true
VITE_COVERAGE: true
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
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@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.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==${{ env.plugin_creator_version }}
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
npx nyc playwright test --project=chromium --shard=${{ matrix.shard }}/4
- name: Playwright Report [${{ matrix.shard }} / 4]
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: ${{ !cancelled() && steps.tests.outcome == 'failure' }}
with:
name: playwright-report-chromium-${{ matrix.shard }}
path: src/frontend/playwright-report/
if-no-files-found: error
retention-days: 7
- name: Upload Coverage Artifact [${{ matrix.shard }} / 4]
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
id: coverage-upload
if: ${{ !cancelled() && steps.tests.outcome != 'failure' }}
with:
name: coverage-${{ matrix.shard }}
path: src/frontend/.nyc_output/
if-no-files-found: error
include-hidden-files: true
retention-days: 1
# 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@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Environment Setup
uses: ./.github/actions/setup
with:
npm: true
install: false
update: false
- name: Download Coverage Artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
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@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
slug: inventree/InvenTree
flags: web
files: ./coverage/lcov.info

View File

@ -1,120 +0,0 @@
# Ensure that data import / export functionality works as expected.
# - Create a dataset in a Postgres database (including plugin data)
# - Export the dataset to an agnostic format (JSON)
# - Import the dataset into a Sqlite database
name: Import / Export
on:
push:
branches-ignore: ["l10*", "dependabot/**", "backport/**"]
pull_request:
branches-ignore: ["l10*"]
permissions:
contents: read
env:
python_version: 3.12
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INVENTREE_DEBUG: false
INVENTREE_LOG_LEVEL: WARNING
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
INVENTREE_PLUGINS_ENABLED: true
INVENTREE_AUTO_UPDATE: true
INVENTREE_PLUGINS_MANDATORY: "dummy-app-plugin"
INVENTREE_GLOBAL_SETTINGS: '{"ENABLE_PLUGINS_APP": true}'
DATA_FILE: /home/runner/work/InvenTree/test_inventree_data.json
INVENTREE_DB_ENGINE: postgresql
INVENTREE_DB_NAME: inventree
INVENTREE_DB_USER: inventree
INVENTREE_DB_PASSWORD: password
INVENTREE_DB_HOST: "127.0.0.1"
INVENTREE_DB_PORT: 5432
jobs:
paths-filter:
name: filter
runs-on: ubuntu-latest
outputs:
server: ${{ steps.filter.outputs.server }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
id: filter
with:
filters: |
server:
- .github/workflows/import_export.yaml
- .github/scripts/check_exported_data.py
- 'src/backend/**'
- 'tasks.py'
test:
runs-on: ubuntu-latest
needs: paths-filter
if: needs.paths-filter.outputs.server == 'true' || contains(github.event.pull_request.labels.*.name, 'full-run')
services:
postgres:
image: postgres:17
env:
POSTGRES_USER: inventree
POSTGRES_PASSWORD: password
ports:
- 5432:5432
steps:
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
persist-credentials: false
- name: Environment Setup
uses: ./.github/actions/setup
with:
apt-dependency: gettext poppler-utils libpq-dev
pip-dependency: psycopg
update: true
static: false
- name: Setup Postgres Database
run: |
invoke migrate
invoke dev.setup-test -i
- name: Create Plugin Data
run: |
pip install -U inventree-dummy-app-plugin==0.1.0
invoke migrate
cd src/backend/InvenTree && python manage.py create_dummy_data
- name: Export Postgres Dataset
run: |
invoke export-records -o -f ${{ env.DATA_FILE }}
python .github/scripts/check_exported_data.py ${{ env.DATA_FILE }}
invoke dev.delete-data --force
- name: Update Environment Variables for Sqlite
run: |
echo "Updating environment variables for Sqlite"
echo "INVENTREE_DB_ENGINE=sqlite" >> $GITHUB_ENV
echo "INVENTREE_DB_NAME=/home/runner/work/InvenTree/test_inventree_db.sqlite3" >> $GITHUB_ENV
- name: Setup Sqlite Database
run: |
invoke migrate
test -f /home/runner/work/InvenTree/test_inventree_db.sqlite3 || (echo "Sqlite database not created" && exit 1)
- name: Import Sqlite Dataset
run: |
invoke import-records -c -f ${{ env.DATA_FILE }} --strict
cd src/backend/InvenTree && python manage.py check_dummy_data
- name: Export Sqlite Dataset
run: |
invoke export-records -o -f ${{ env.DATA_FILE }}
python .github/scripts/check_exported_data.py ${{ env.DATA_FILE }}

View File

@ -4,13 +4,13 @@ name: QC
on: on:
push: push:
branches-ignore: ["l10*", "dependabot/**", "backport/**"] branches-ignore: ["l10*"]
pull_request: pull_request:
branches-ignore: ["l10*"] branches-ignore: ["l10*"]
env: env:
python_version: 3.12 python_version: 3.9
node_version: 24 node_version: 20
# The OS version must be set per job # The OS version must be set per job
server_start_sleep: 60 server_start_sleep: 60
@ -39,15 +39,12 @@ jobs:
force: ${{ steps.force.outputs.force }} force: ${{ steps.force.outputs.force }}
cicd: ${{ steps.filter.outputs.cicd }} cicd: ${{ steps.filter.outputs.cicd }}
requirements: ${{ steps.filter.outputs.requirements }} 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 }}
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # pin@v3.0.2
id: filter id: filter
with: with:
filters: | filters: |
@ -77,47 +74,24 @@ jobs:
if: | if: |
contains(github.event.pull_request.labels.*.name, 'dependency') || contains(github.event.pull_request.labels.*.name, 'dependency') ||
contains(github.event.pull_request.labels.*.name, 'full-run') 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
code-style: pre-commit:
name: Style [prek] name: Style [pre-commit]
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
needs: paths-filter needs: paths-filter
if: needs.paths-filter.outputs.cicd == 'true' || needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.frontend == 'true' || needs.paths-filter.outputs.requirements == 'true' || needs.paths-filter.outputs.force == 'true' if: needs.paths-filter.outputs.cicd == 'true' || needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.frontend == 'true' || needs.paths-filter.outputs.requirements == 'true' || needs.paths-filter.outputs.force == 'true'
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: Set up Python ${{ env.python_version }} - name: Set up Python ${{ env.python_version }}
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # pin@v6.0.0
with: with:
python-version: ${{ env.python_version }} python-version: ${{ env.python_version }}
cache: "pip" cache: "pip"
- name: Run pre commit hook Checks - name: Run pre-commit Checks
uses: j178/prek-action@e98a699c41eb69ab013a45817a0406469a748f8d # v2.0.5 uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # pin@v3.0.1
- name: Check Version - name: Check Version
run: | run: |
pip install --require-hashes -r contrib/dev_reqs/requirements.txt pip install --require-hashes -r contrib/dev_reqs/requirements.txt
@ -126,11 +100,11 @@ jobs:
typecheck: typecheck:
name: Style [Typecheck] name: Style [Typecheck]
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
needs: [code-style, paths-filter] needs: [paths-filter, pre-commit]
if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.requirements == 'true' || needs.paths-filter.outputs.force == 'true' if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.requirements == 'true' || needs.paths-filter.outputs.force == 'true'
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: Environment Setup - name: Environment Setup
@ -142,7 +116,7 @@ jobs:
update: true update: true
- name: Check types - name: Check types
run: | run: |
ty check --python ${Python_ROOT_DIR}/bin/python3 src/backend ty check --python ${Python_ROOT_DIR}/bin/python3
mkdocs: mkdocs:
name: Style [Documentation] name: Style [Documentation]
@ -152,11 +126,11 @@ jobs:
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: Set up Python ${{ env.python_version }} - name: Set up Python ${{ env.python_version }}
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # pin@v6.0.0
with: with:
python-version: ${{ env.python_version }} python-version: ${{ env.python_version }}
- name: Check Config - name: Check Config
@ -165,7 +139,7 @@ jobs:
pip install --require-hashes -r docs/requirements.txt pip install --require-hashes -r docs/requirements.txt
python docs/ci/check_mkdocs_config.py python docs/ci/check_mkdocs_config.py
- name: Check Links - name: Check Links
uses: tcort/github-action-markdown-link-check@e7c7a18363c842693fadde5d41a3bd3573a7a225 # v1 uses: gaurav-nelson/github-action-markdown-link-check@5c5dfc0ac2e225883c0e5f03a85311ec2830d368 # pin@v1
with: with:
folder-path: docs folder-path: docs
config-file: docs/mlc_config.json config-file: docs/mlc_config.json
@ -190,7 +164,7 @@ jobs:
version: ${{ steps.version.outputs.version }} version: ${{ steps.version.outputs.version }}
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: Environment Setup - name: Environment Setup
@ -202,7 +176,7 @@ jobs:
- name: Export API Documentation - name: Export API Documentation
run: invoke dev.schema --ignore-warnings --filename src/backend/InvenTree/schema.yml run: invoke dev.schema --ignore-warnings --filename src/backend/InvenTree/schema.yml
- name: Upload schema - name: Upload schema
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # pin@v5.0.0
with: with:
name: schema.yml name: schema.yml
path: src/backend/InvenTree/schema.yml path: src/backend/InvenTree/schema.yml
@ -222,7 +196,7 @@ jobs:
echo "Downloaded api.yaml" echo "Downloaded api.yaml"
- name: Running OpenAPI Spec diff action - name: Running OpenAPI Spec diff action
id: breaking_changes id: breaking_changes
uses: oasdiff/oasdiff-action/diff@3e9d440d37f468355457604348009f50e0cddbf3 # v0.1.4 uses: oasdiff/oasdiff-action/diff@1c611ffb1253a72924624aa4fb662e302b3565d3 # pin@main
with: with:
base: "api.yaml" base: "api.yaml"
revision: "src/backend/InvenTree/schema.yml" revision: "src/backend/InvenTree/schema.yml"
@ -251,17 +225,17 @@ jobs:
- name: Extract settings / tags - name: Extract settings / tags
run: invoke int.export-definitions --basedir docs run: invoke int.export-definitions --basedir docs
- name: Upload settings - name: Upload settings
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # pin@v5.0.0
with: with:
name: inventree_settings.json name: inventree_settings.json
path: docs/generated/inventree_settings.json path: docs/generated/inventree_settings.json
- name: Upload tags - name: Upload tags
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # pin@v5.0.0
with: with:
name: inventree_tags.yml name: inventree_tags.yml
path: docs/generated/inventree_tags.yml path: docs/generated/inventree_tags.yml
- name: Upload filters - name: Upload filters
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # pin@v5.0.0
with: with:
name: inventree_filters.yml name: inventree_filters.yml
path: docs/generated/inventree_filters.yml path: docs/generated/inventree_filters.yml
@ -275,7 +249,7 @@ jobs:
version: ${{ needs.schema.outputs.version }} version: ${{ needs.schema.outputs.version }}
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
name: Checkout Code name: Checkout Code
with: with:
repository: inventree/schema repository: inventree/schema
@ -284,7 +258,7 @@ jobs:
- name: Create artifact directory - name: Create artifact directory
run: mkdir -p artifact run: mkdir -p artifact
- name: Download schema artifact - name: Download schema artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # pin@v6.0.0
with: with:
path: artifact path: artifact
merge-multiple: true merge-multiple: true
@ -301,20 +275,17 @@ jobs:
echo "after move" echo "after move"
ls -la artifact ls -la artifact
rm -rf artifact rm -rf artifact
- uses: stefanzweifel/git-auto-commit-action@4a55954c782fc1ea30b9056cd3e7a2b40ca8887d # v7.2.0 - uses: stefanzweifel/git-auto-commit-action@28e16e81777b558cc906c8750092100bbb34c5e3 # pin@v7.0.0
name: Commit schema changes name: Commit schema changes
with: with:
commit_message: "Update API schema for ${{ env.version }} / ${{ github.sha }}" commit_message: "Update API schema for ${{ env.version }} / ${{ github.sha }}"
python: python:
name: Tests - inventree-python name: Tests - inventree-python
runs-on: ${{ needs.paths-filter.outputs.runner-perf }} runs-on: ubuntu-24.04
needs: ["code-style", "paths-filter"] needs: ["pre-commit", "paths-filter"]
if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.force == 'true' || needs.paths-filter.outputs.performance == 'true' if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.force == 'true'
permissions:
contents: read
id-token: write
env: env:
WRAPPER_NAME: inventree-python WRAPPER_NAME: inventree-python
@ -329,20 +300,17 @@ jobs:
INVENTREE_SITE_URL: http://127.0.0.1:12345 INVENTREE_SITE_URL: http://127.0.0.1:12345
INVENTREE_DEBUG: true INVENTREE_DEBUG: true
INVENTREE_LOG_LEVEL: WARNING INVENTREE_LOG_LEVEL: WARNING
node_version: '>=24'
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: true
- name: Environment Setup - name: Environment Setup
uses: ./.github/actions/setup uses: ./.github/actions/setup
with: with:
apt-dependency: gettext poppler-utils apt-dependency: gettext poppler-utils
dev-install: true dev-install: true
update: true update: true
static: true
npm: true
- name: Download Python Code For `${WRAPPER_NAME}` - name: Download Python Code For `${WRAPPER_NAME}`
run: git clone --depth 1 https://github.com/inventree/${WRAPPER_NAME} ./${WRAPPER_NAME} run: git clone --depth 1 https://github.com/inventree/${WRAPPER_NAME} ./${WRAPPER_NAME}
- name: Start InvenTree Server - name: Start InvenTree Server
@ -356,30 +324,18 @@ jobs:
cd ${WRAPPER_NAME} cd ${WRAPPER_NAME}
invoke check-server invoke check-server
coverage run -m unittest discover -s test/ coverage run -m unittest discover -s test/
- name: Prepare environment for performance tests
run: |
pip uninstall pytest-django -y
cd ${WRAPPER_NAME}
pip install .
if: needs.paths-filter.outputs.submit-performance == 'true'
- name: Performance Reporting
uses: CodSpeedHQ/action@a4a36bb07c0638b0b4ca52bf1f3dad1b4289e52f # v4.18.1
# check if we are in inventree/inventree - reporting only works in that OIDC context
if: github.repository == 'inventree/InvenTree' && needs.paths-filter.outputs.submit-performance == 'true'
with:
mode: walltime
run: pytest ./src/performance --codspeed
coverage: coverage:
name: Tests - DB [SQLite] + Coverage ${{ matrix.python_version }} name: Tests - DB [SQLite] + Coverage ${{ matrix.python_version }}
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
needs: ["code-style", "paths-filter"] needs: ["pre-commit", "paths-filter"]
if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.force == 'true' if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.force == 'true'
continue-on-error: true # continue if a step fails so that coverage gets pushed continue-on-error: true # continue if a step fails so that coverage gets pushed
strategy: strategy:
matrix: matrix:
python_version: [3.12, 3.14] python_version: [3.9]
# python_version: [3.9, 3.12] # Disabled due to requirement issues
env: env:
INVENTREE_DB_NAME: ./inventree.sqlite INVENTREE_DB_NAME: ./inventree.sqlite
@ -390,7 +346,7 @@ jobs:
python_version: ${{ matrix.python_version }} python_version: ${{ matrix.python_version }}
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: Environment Setup - name: Environment Setup
@ -399,7 +355,6 @@ jobs:
apt-dependency: gettext poppler-utils apt-dependency: gettext poppler-utils
dev-install: true dev-install: true
update: true update: true
static: true
- name: Data Export Test - name: Data Export Test
uses: ./.github/actions/migration uses: ./.github/actions/migration
- name: Test Translations - name: Test Translations
@ -409,60 +364,23 @@ jobs:
- name: Coverage Tests - name: Coverage Tests
run: invoke dev.test --check --coverage --translations run: invoke dev.test --check --coverage --translations
- name: Upload raw coverage to artifacts - name: Upload raw coverage to artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # pin@v5.0.0
with: with:
name: coverage name: coverage
path: .coverage path: .coverage
retention-days: 14 retention-days: 14
- name: Upload coverage reports to Codecov - name: Upload coverage reports to Codecov
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # pin@v5.5.1
if: always() if: always()
with: with:
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}
slug: inventree/InvenTree slug: inventree/InvenTree
flags: backend flags: backend
performance:
name: Tests - Performance
runs-on: ${{ needs.paths-filter.outputs.runner-perf }}
needs: ["code-style", "paths-filter"]
# check if we are in inventree/inventree - reporting only works in that OIDC context
if: (needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.force == 'true') && github.repository == 'inventree/InvenTree' && needs.paths-filter.outputs.submit-performance == 'true'
permissions:
contents: read
id-token: write
env:
INVENTREE_DB_NAME: inventree_unit_test_db.sqlite
INVENTREE_DB_ENGINE: sqlite3
INVENTREE_PLUGINS_ENABLED: true
INVENTREE_CONSOLE_LOG: false
INVENTREE_AUTO_UPDATE: true
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Environment Setup
uses: ./.github/actions/setup
with:
apt-dependency: gettext poppler-utils
dev-install: true
update: true
npm: true
env:
node_version: '>=24'
- name: Performance Reporting
uses: CodSpeedHQ/action@a4a36bb07c0638b0b4ca52bf1f3dad1b4289e52f # v4.18.1
with:
mode: walltime
run: inv dev.test --pytest
postgres: postgres:
name: Tests - DB [PostgreSQL] name: Tests - DB [PostgreSQL]
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
needs: ["code-style", "paths-filter"] needs: ["pre-commit", "paths-filter"]
if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.force == 'true' if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.force == 'true'
env: env:
@ -479,7 +397,7 @@ jobs:
services: services:
postgres: postgres:
image: postgres:17 image: postgres:14
env: env:
POSTGRES_USER: inventree POSTGRES_USER: inventree
POSTGRES_PASSWORD: password POSTGRES_PASSWORD: password
@ -492,7 +410,7 @@ jobs:
- 6379:6379 - 6379:6379
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: Environment Setup - name: Environment Setup
@ -502,7 +420,6 @@ jobs:
pip-dependency: psycopg django-redis>=5.0.0 pip-dependency: psycopg django-redis>=5.0.0
dev-install: true dev-install: true
update: true update: true
static: true
- name: Run Tests - name: Run Tests
run: invoke dev.test --check --translations run: invoke dev.test --check --translations
- name: Data Export Test - name: Data Export Test
@ -512,7 +429,7 @@ jobs:
name: Tests - DB [MySQL] name: Tests - DB [MySQL]
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
needs: ["code-style", "paths-filter"] needs: ["pre-commit", "paths-filter"]
if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.force == 'true' if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.force == 'true'
env: env:
@ -541,7 +458,7 @@ jobs:
- 3306:3306 - 3306:3306
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: Environment Setup - name: Environment Setup
@ -551,7 +468,6 @@ jobs:
pip-dependency: mysqlclient pip-dependency: mysqlclient
dev-install: true dev-install: true
update: true update: true
static: true
- name: Run Tests - name: Run Tests
run: invoke dev.test --check --translations run: invoke dev.test --check --translations
- name: Data Export Test - name: Data Export Test
@ -576,7 +492,7 @@ jobs:
services: services:
postgres: postgres:
image: postgres:17 image: postgres:14
env: env:
POSTGRES_USER: inventree POSTGRES_USER: inventree
POSTGRES_PASSWORD: password POSTGRES_PASSWORD: password
@ -584,7 +500,7 @@ jobs:
- 5432:5432 - 5432:5432
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: Environment Setup - name: Environment Setup
@ -597,7 +513,7 @@ jobs:
- name: Run Tests - name: Run Tests
run: invoke dev.test --check --migrations --report --coverage --translations run: invoke dev.test --check --migrations --report --coverage --translations
- name: Upload coverage reports to Codecov - name: Upload coverage reports to Codecov
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # pin@v5.5.1
if: always() if: always()
with: with:
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}
@ -618,7 +534,7 @@ jobs:
INVENTREE_PLUGINS_ENABLED: false INVENTREE_PLUGINS_ENABLED: false
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false
name: Checkout Code name: Checkout Code
@ -664,18 +580,132 @@ jobs:
chmod +rw /home/runner/work/InvenTree/db.sqlite3 chmod +rw /home/runner/work/InvenTree/db.sqlite3
invoke migrate invoke migrate
web_ui:
name: Tests - Web UI
runs-on: ubuntu-24.04
timeout-minutes: 60
needs: ["pre-commit", "paths-filter"]
if: needs.paths-filter.outputs.frontend == 'true' || needs.paths-filter.outputs.force == 'true'
services:
postgres:
image: postgres:15
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:
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
VITE_COVERAGE_BUILD: true
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with:
persist-credentials: false
- name: Environment Setup
uses: ./.github/actions/setup
with:
npm: true
install: true
update: true
apt-dependency: 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
cd src/frontend && npx playwright install --with-deps
- name: Run Playwright tests
id: tests
run: cd src/frontend && npx nyc playwright test
- uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # pin@v5.0.0
if: ${{ !cancelled() && steps.tests.outcome == 'failure' }}
with:
name: playwright-report
path: src/frontend/playwright-report/
retention-days: 14
- name: Report coverage
run: cd src/frontend && npx nyc report --report-dir ./coverage --temp-dir .nyc_output --reporter=lcov --exclude-after-remap false
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # pin@v5.5.1
with:
token: ${{ secrets.CODECOV_TOKEN }}
slug: inventree/InvenTree
flags: web
- name: Upload bundler info
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
run: |
cd src/frontend
yarn install
yarn run build
web_ui_build:
name: Build - Web UI
runs-on: ubuntu-24.04
timeout-minutes: 60
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
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 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@330a01c490aca151604b8cf639adc76d48f6c5d4 # pin@v5.0.0
with:
name: frontend-build
path: src/backend/InvenTree/web/static/web
include-hidden-files: true
zizmor: zizmor:
name: Security [Zizmor] name: Security [Zizmor]
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
needs: ["code-style", "paths-filter"] needs: ["pre-commit", "paths-filter"]
if: needs.paths-filter.outputs.cicd == 'true' || needs.paths-filter.outputs.force == 'true' if: needs.paths-filter.outputs.cicd == 'true' || needs.paths-filter.outputs.force == 'true'
permissions: permissions:
security-events: write security-events: write
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: Run zizmor 🌈 - uses: hynek/setup-cached-uv@757bedc3f972eb7227a1aa657651f15a8527c817 # pin@v2
uses: zizmorcore/zizmor-action@192e21d79ab29983730a13d1382995c2307fbcaa # v0.5.7 - name: Run zizmor
run: uvx zizmor --format sarif . > results.sarif
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # pin@v3
with:
sarif_file: results.sarif
category: zizmor

View File

@ -7,7 +7,7 @@ on:
permissions: permissions:
contents: read contents: read
env: env:
python_version: 3.12 python_version: 3.9
jobs: jobs:
stable: stable:
@ -20,7 +20,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: Version Check - name: Version Check
@ -28,7 +28,7 @@ jobs:
pip install --require-hashes -r contrib/dev_reqs/requirements.txt pip install --require-hashes -r contrib/dev_reqs/requirements.txt
python3 .github/scripts/version_check.py python3 .github/scripts/version_check.py
- name: Push to Stable Branch - name: Push to Stable Branch
uses: ad-m/github-push-action@881a6320fdb16eb5318c5054f31c218aec2b324c # v1.3.0 uses: ad-m/github-push-action@77c5b412c50b723d2a4fbc6d71fb5723bcd439aa # pin@v1.0.0
if: env.stable_release == 'true' if: env.stable_release == 'true'
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
@ -42,10 +42,8 @@ jobs:
id-token: write id-token: write
contents: write contents: write
attestations: write attestations: write
artifact-metadata: write
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: Environment Setup - name: Environment Setup
@ -57,7 +55,7 @@ jobs:
- name: Build frontend - name: Build frontend
run: cd src/frontend && npm run compile && npm run build run: cd src/frontend && npm run compile && npm run build
- name: Create SBOM for frontend - name: Create SBOM for frontend
uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0 uses: anchore/sbom-action@8e94d75ddd33f69f691467e42275782e4bfefe84 # pin@v0
with: with:
artifact-name: frontend-build.spdx artifact-name: frontend-build.spdx
path: src/frontend path: src/frontend
@ -67,38 +65,32 @@ jobs:
run: cd src/backend/InvenTree/web/static/web/.vite && echo "${REF_NAME}" > tag.txt run: cd src/backend/InvenTree/web/static/web/.vite && echo "${REF_NAME}" > tag.txt
env: env:
REF_NAME: ${{ github.ref_name }} REF_NAME: ${{ github.ref_name }}
- name: Write version file - SOURCE
run: cd src/backend/InvenTree/web/static/web/.vite && echo "GitHub Actions build on $(date --utc +%Y-%m-%dT%H:%M:%SZ)" > source.txt
- name: Zip frontend - name: Zip frontend
run: | run: |
cd src/backend/InvenTree/web/static/web cd src/backend/InvenTree/web/static/web
zip -r ../frontend-build.zip * .vite zip -r ../frontend-build.zip * .vite
- name: Attest Build Provenance - name: Attest Build Provenance
id: attest id: attest
uses: actions/attest@a1948c3f048ba23858d222213b7c278aabede763 # v4.1.1 uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # pin@v1
with: with:
subject-path: "${{ github.workspace }}/src/backend/InvenTree/web/static/frontend-build.zip" subject-path: "${{ github.workspace }}/src/backend/InvenTree/web/static/frontend-build.zip"
- name: Upload frontend - name: Upload frontend
run: gh release upload ${REF} src/backend/InvenTree/web/static/frontend-build.zip#frontend-build.zip uses: svenstaro/upload-release-action@81c65b7cd4de9b2570615ce3aad67a41de5b1a13 # pin@2.11.2
env:
REF: ${{ github.ref_name }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload frontend to artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with: with:
name: frontend-build repo_token: ${{ secrets.GITHUB_TOKEN }}
path: src/backend/InvenTree/web/static/frontend-build.zip file: src/backend/InvenTree/web/static/frontend-build.zip
- name: Rename Attestation Bundle asset_name: frontend-build.zip
run: | tag: ${{ github.ref }}
mv ${BUNDLE_PATH} src/backend/InvenTree/web/static/frontend-build.intoto.jsonl overwrite: true
env:
BUNDLE_PATH: ${{ steps.attest.outputs.bundle-path}}
- name: Upload Attestation - name: Upload Attestation
run: gh release upload ${REF} src/backend/InvenTree/web/static/frontend-build.intoto.jsonl#frontend-build.intoto.jsonl uses: svenstaro/upload-release-action@81c65b7cd4de9b2570615ce3aad67a41de5b1a13 # pin@2.11.2
env: with:
REF: ${{ github.ref_name }} repo_token: ${{ secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} asset_name: frontend-build.intoto.jsonl
file: ${{ steps.attest.outputs.bundle-path}}
tag: ${{ github.ref }}
overwrite: true
docs: docs:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
@ -115,7 +107,7 @@ jobs:
INVENTREE_DEBUG: true INVENTREE_DEBUG: true
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: Environment Setup - name: Environment Setup
@ -135,142 +127,10 @@ jobs:
cd docs/site cd docs/site
zip -r docs-html.zip * zip -r docs-html.zip *
- name: Publish documentation - name: Publish documentation
run: gh release upload ${REF} docs/site/docs-html.zip#docs-html.zip uses: svenstaro/upload-release-action@81c65b7cd4de9b2570615ce3aad67a41de5b1a13 # pin@2.11.2
env:
REF: ${{ github.ref_name }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
build-pkgr:
if: github.repository == 'inventree/InvenTree'
name: ${{ matrix.target }}
runs-on: ubuntu-latest
needs: [build]
permissions:
contents: write
strategy:
fail-fast: false
matrix:
target:
- ubuntu:24.04
- ubuntu:26.04
- debian:13
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with: with:
fetch-depth: 0 repo_token: ${{ secrets.GITHUB_TOKEN }}
persist-credentials: false file: docs/site/docs-html.zip
- name: Get frontend artifact asset_name: docs-html.zip
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 tag: ${{ github.ref }}
with: overwrite: true
name: frontend-build
- name: Setup
id: setup
env:
NODE_ID: ${{ github.event.release.node_id }}
BRANCH: ${{ github.event.release.target_commitish }}
TARGET: ${{github.event.release.target_commitish}}
REPO: ${{ github.repository }}
VERSION_REF: ${{ github.ref_name }}
GH_TOKEN: ${{ github.token }}
run: |
# Get info
gh api -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /repos/$REPO/commits/$TARGET > commit.json
# Extract info
echo "INFO extract | Extracting info from github"
DATE=$(jq -r '.commit.committer.date' commit.json)
SIGNATURE=$(jq -r '.commit.verification.signature' commit.json)
FULL_SHA=$(jq -r '.sha' commit.json)
SHA=$(echo "$FULL_SHA" | cut -c1-7)
echo "INFO write | Write VERSION information"
echo "$VERSION" > VERSION
echo "INVENTREE_COMMIT_HASH='$SHA'" >> VERSION
echo "INVENTREE_COMMIT_SHA='$FULL_SHA'" >> VERSION
echo "INVENTREE_COMMIT_DATE='$DATE'" >> VERSION
echo "INVENTREE_PKG_INSTALLER='PKG'" >> VERSION
echo "INVENTREE_PKG_BRANCH='$BRANCH'" >> VERSION
echo "INVENTREE_PKG_TARGET='$TARGET'" >> VERSION
echo "NODE_ID='$NODE_ID'" >> VERSION
echo "SIGNATURE='$SIGNATURE'" >> VERSION
echo "INFO write | Written VERSION information"
echo "### VERSION ###"
cat VERSION
echo "### VERSION ###"
# Move frontend build into place
mkdir -p src/backend/InvenTree/web/static
unzip -qq frontend-build.zip -d src/backend/InvenTree/web/static/web
echo "INFO write release_version"
echo "VERSION=$VERSION_REF" >> $GITHUB_OUTPUT
echo "REF=$GITHUB_REF" >> $GITHUB_OUTPUT
# Disable before.sh for now - will need to be removed once we switch to go.packager.io fully
echo "#!/bin/bash" > contrib/packager.io/before.sh
echo "calculate release channel"
pip install --require-hashes -r contrib/dev_reqs/requirements.txt
python3 .github/scripts/version_check.py
- name: Package - current release channel
uses: pkgr/action/package@c5666febcd31750da6428042193fc5b2fb765435 # main
id: package
with:
target: ${{ matrix.target }}
version: ${{ steps.setup.outputs.version }}
debug: true
cache_prefix: ${{ github.ref_name }}
env: |
INVENTREE_DB_ENGINE=sqlite3
INVENTREE_DB_NAME=database.sqlite3
INVENTREE_PLUGINS_ENABLED=true
INVENTREE_MEDIA_ROOT=/opt/inventree/media
INVENTREE_STATIC_ROOT=/opt/inventree/static
INVENTREE_BACKUP_DIR=/opt/inventree/backup
INVENTREE_PLUGIN_FILE=/opt/inventree/plugins.txt
INVENTREE_CONFIG_FILE=/opt/inventree/config.yaml
APP_REPO=inventree/InvenTree
- name: Publish to go.packager.io - current release channel
uses: pkgr/action/publish@c5666febcd31750da6428042193fc5b2fb765435 # main
with:
target: ${{ matrix.target }}
token: ${{ secrets.PACKAGER_RELEASE_TOKEN }}
repository: inventree/InvenTree
channel: ${{ env.pkg_channel }}
file: ${{ steps.package.outputs.package_path }}
- name: Publish to artifact
run: gh release upload ${REF} ${PACKAGE_PATH}#${PACKAGE_NAME}
env:
REF: ${{ github.ref_name }}
PACKAGE_PATH: ${{ steps.package.outputs.package_path }}
PACKAGE_NAME: ${{ matrix.target }}-${{ steps.setup.outputs.version }}.tar.gz
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Package - stable release channel
uses: pkgr/action/package@c5666febcd31750da6428042193fc5b2fb765435 # main
id: package-stable
with:
target: ${{ matrix.target }}
version: ${{ steps.setup.outputs.version }}
debug: true
cache_prefix: ${{ github.ref_name }}
env: |
INVENTREE_DB_ENGINE=sqlite3
INVENTREE_DB_NAME=database.sqlite3
INVENTREE_PLUGINS_ENABLED=true
INVENTREE_MEDIA_ROOT=/opt/inventree/media
INVENTREE_STATIC_ROOT=/opt/inventree/static
INVENTREE_BACKUP_DIR=/opt/inventree/backup
INVENTREE_PLUGIN_FILE=/opt/inventree/plugins.txt
INVENTREE_CONFIG_FILE=/opt/inventree/config.yaml
APP_REPO=inventree/InvenTree
- name: Publish to go.packager.io - stable release channel
uses: pkgr/action/publish@c5666febcd31750da6428042193fc5b2fb765435 # main
with:
target: ${{ matrix.target }}
token: ${{ secrets.PACKAGER_RELEASE_TOKEN }}
repository: inventree/InvenTree
channel: stable
file: ${{ steps.package-stable.outputs.package_path }}

View File

@ -32,7 +32,7 @@ jobs:
steps: steps:
- name: "Checkout code" - name: "Checkout code"
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
@ -59,7 +59,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab. # format to the repository Actions tab.
- name: "Upload artifact" - name: "Upload artifact"
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with: with:
name: SARIF file name: SARIF file
path: results.sarif path: results.sarif
@ -67,6 +67,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard. # Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning" - name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v4.31.0
with: with:
sarif_file: results.sarif sarif_file: results.sarif

View File

@ -16,7 +16,7 @@ jobs:
pull-requests: write pull-requests: write
steps: steps:
- uses: actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899 # v10.3.0 - uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # pin@v10.1.0
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: "This issue seems stale. Please react to show this is still important." stale-issue-message: "This issue seems stale. Please react to show this is still important."

View File

@ -6,8 +6,8 @@ on:
- master - master
env: env:
python_version: 3.12 python_version: 3.9
node_version: 24 node_version: 20
permissions: permissions:
contents: read contents: read
@ -32,9 +32,9 @@ jobs:
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
with: with:
persist-credentials: false persist-credentials: true
- name: Environment Setup - name: Environment Setup
uses: ./.github/actions/setup uses: ./.github/actions/setup
with: with:
@ -56,7 +56,7 @@ jobs:
echo "Resetting to HEAD~" echo "Resetting to HEAD~"
git reset HEAD~ || true git reset HEAD~ || true
- name: crowdin action - name: crowdin action
uses: crowdin/github-action@52aa776766211d83d975df51f3b9c53c2f8ba35f # v2 uses: crowdin/github-action@08713f00a50548bfe39b37e8f44afb53e7a802d4 # pin@v2
with: with:
upload_sources: true upload_sources: true
upload_translations: false upload_translations: false

View File

@ -9,7 +9,7 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
with: with:
persist-credentials: false persist-credentials: false
- name: Setup - name: Setup
@ -18,7 +18,7 @@ jobs:
run: pip-compile --output-file=requirements.txt requirements.in -U run: pip-compile --output-file=requirements.txt requirements.in -U
- name: Update requirements-dev.txt - name: Update requirements-dev.txt
run: pip-compile --generate-hashes --output-file=requirements-dev.txt requirements-dev.in -U run: pip-compile --generate-hashes --output-file=requirements-dev.txt requirements-dev.in -U
- uses: stefanzweifel/git-auto-commit-action@fd157da78fa13d9383e5580d1fd1184d89554b51 # v4.15.1 - uses: stefanzweifel/git-auto-commit-action@fd157da78fa13d9383e5580d1fd1184d89554b51 # pin@v4.15.1
with: with:
commit_message: "[Bot] Updated dependency" commit_message: "[Bot] Updated dependency"
branch: dep-update branch: dep-update

8
.gitignore vendored
View File

@ -37,11 +37,6 @@ local_settings.py
*.backup *.backup
*.old *.old
# Files generated by profiling tools
*.prof
*.log
*.sql
# Files used for testing # Files used for testing
inventree-demo-dataset/ inventree-demo-dataset/
inventree-data/ inventree-data/
@ -116,6 +111,3 @@ api.yaml
# web frontend (static files) # web frontend (static files)
src/backend/InvenTree/web/static src/backend/InvenTree/web/static
InvenTree/web/static InvenTree/web/static
# performance test results
.codspeed/

View File

@ -6,7 +6,7 @@ buildpack: https://github.com/matmair/null-buildpack#master
env: env:
- INVENTREE_DB_ENGINE=sqlite3 - INVENTREE_DB_ENGINE=sqlite3
- INVENTREE_DB_NAME=database.sqlite3 - INVENTREE_DB_NAME=database.sqlite3
- INVENTREE_PLUGINS_ENABLED=true - INVENTREE_PLUGINS_ENABLED
- INVENTREE_MEDIA_ROOT=/opt/inventree/media - INVENTREE_MEDIA_ROOT=/opt/inventree/media
- INVENTREE_STATIC_ROOT=/opt/inventree/static - INVENTREE_STATIC_ROOT=/opt/inventree/static
- INVENTREE_BACKUP_DIR=/opt/inventree/backup - INVENTREE_BACKUP_DIR=/opt/inventree/backup
@ -20,10 +20,9 @@ before:
- contrib/packager.io/before.sh - contrib/packager.io/before.sh
dependencies: dependencies:
- curl - curl
- poppler-utils - "python3.9 | python3.10 | python3.11 | python3.12 | python3.13 | python3.14"
- "python3.12 | python3.13 | python3.14" - "python3.9-venv | python3.10-venv | python3.11-venv | python3.12-venv | python3.13-venv | python3.14-venv"
- "python3.12-venv | python3.13-venv | python3.14-venv" - "python3.9-dev | python3.10-dev | python3.11-dev | python3.12-dev | python3.13-dev | python3.14-dev"
- "python3.12-dev | python3.13-dev | python3.14-dev"
- python3-pip - python3-pip
- python3-cffi - python3-cffi
- python3-brotli - python3-brotli
@ -36,6 +35,8 @@ dependencies:
- jq - jq
- "libffi7 | libffi8" - "libffi7 | libffi8"
targets: targets:
ubuntu-20.04: true
ubuntu-22.04: true
ubuntu-24.04: true ubuntu-24.04: true
ubuntu-26.04: true debian-11: true
debian-13: true debian-12: true

View File

@ -10,7 +10,7 @@ exclude: |
)$ )$
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0 rev: v5.0.0
hooks: hooks:
- id: trailing-whitespace - id: trailing-whitespace
- id: end-of-file-fixer - id: end-of-file-fixer
@ -18,53 +18,45 @@ repos:
exclude: mkdocs.yml exclude: mkdocs.yml
- id: mixed-line-ending - id: mixed-line-ending
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.12 rev: v0.11.13
hooks: hooks:
- id: ruff-format - id: ruff-format
args: [--preview] args: [--preview]
- id: ruff-check - id: ruff
args: [ args: [
--fix, --fix,
# --unsafe-fixes, # --unsafe-fixes,
--preview --preview
] ]
- repo: https://github.com/astral-sh/uv-pre-commit - repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.11.12 rev: 0.7.12
hooks: hooks:
- id: pip-compile - id: pip-compile
name: pip-compile requirements-dev.in name: pip-compile requirements-dev.in
args: [src/backend/requirements-dev.in, -o, src/backend/requirements-dev.txt, -c, src/backend/requirements.txt] args: [src/backend/requirements-dev.in, -o, src/backend/requirements-dev.txt, --no-strip-extras, --generate-hashes]
files: src/backend/requirements-dev\.(in|txt)$
- id: pip-compile
name: pip-compile requirements-dev.in 3.14
args: [src/backend/requirements-dev.in, -o, src/backend/requirements-dev-3.14.txt, -c, src/backend/requirements-3.14.txt, --python-version=3.14, -c, src/backend/requirements.txt, -c, src/backend/requirements-dev.txt]
files: src/backend/requirements-dev\.(in|txt)$ files: src/backend/requirements-dev\.(in|txt)$
- id: pip-compile - id: pip-compile
name: pip-compile requirements.txt name: pip-compile requirements.txt
args: [src/backend/requirements.in, -o, src/backend/requirements.txt] args: [src/backend/requirements.in, -o, src/backend/requirements.txt, --no-strip-extras, --generate-hashes]
files: src/backend/requirements\.(in|txt)$ files: src/backend/requirements\.(in|txt)$
- id: pip-compile - id: pip-compile
name: pip-compile requirements.txt 3.14 name: pip-compile requirements.txt
args: [src/backend/requirements.in, -o, src/backend/requirements-3.14.txt, --python-version=3.14, -c, src/backend/requirements.txt] args: [contrib/dev_reqs/requirements.in, -o, contrib/dev_reqs/requirements.txt, --no-strip-extras, --generate-hashes, -b, src/backend/requirements.txt]
files: src/backend/requirements\.(in|txt)$
- id: pip-compile
name: pip-compile contrib/dev_reqs/requirements.txt
args: [contrib/dev_reqs/requirements.in, -o, contrib/dev_reqs/requirements.txt, -c, src/backend/requirements.txt]
files: contrib/dev_reqs/requirements\.(in|txt)$ files: contrib/dev_reqs/requirements\.(in|txt)$
- id: pip-compile - id: pip-compile
name: pip-compile docs/requirements.txt name: pip-compile requirements.txt
args: [docs/requirements.in, -o, docs/requirements.txt, -c, src/backend/requirements.txt] args: [docs/requirements.in, -o, docs/requirements.txt, --no-strip-extras, --generate-hashes, -b, src/backend/requirements.txt]
files: docs/requirements\.(in|txt)$ files: docs/requirements\.(in|txt)$
- id: pip-compile - id: pip-compile
name: pip-compile contrib/container/requirements.txt name: pip-compile requirements.txt
args: [contrib/container/requirements.in, -o, contrib/container/requirements.txt, --python-version=3.14, -c, src/backend/requirements.txt] args: [contrib/container/requirements.in, -o, contrib/container/requirements.txt, --python-version=3.11, --no-strip-extras, --generate-hashes, -b, src/backend/requirements.txt]
files: contrib/container/requirements\.(in|txt)$ files: contrib/container/requirements\.(in|txt)$
- repo: https://github.com/Riverside-Healthcare/djLint - repo: https://github.com/Riverside-Healthcare/djLint
rev: v1.36.4 rev: v1.36.4
hooks: hooks:
- id: djlint-django - id: djlint-django
- repo: https://github.com/codespell-project/codespell - repo: https://github.com/codespell-project/codespell
rev: v2.4.2 rev: v2.4.1
hooks: hooks:
- id: codespell - id: codespell
additional_dependencies: additional_dependencies:
@ -79,16 +71,16 @@ repos:
src/frontend/vite.config.ts | src/frontend/vite.config.ts |
)$ )$
- repo: https://github.com/biomejs/pre-commit - repo: https://github.com/biomejs/pre-commit
rev: v2.4.14 rev: v2.0.0-beta.5
hooks: hooks:
- id: biome-check - id: biome-check
additional_dependencies: ["@biomejs/biome@1.9.4"] additional_dependencies: ["@biomejs/biome@1.9.4"]
files: ^src/frontend/.*\.(js|ts|tsx)$ files: ^src/frontend/.*\.(js|ts|tsx)$
- repo: https://github.com/gitleaks/gitleaks - repo: https://github.com/gitleaks/gitleaks
rev: v8.30.1 rev: v8.27.2
hooks: hooks:
- id: gitleaks - id: gitleaks
language_version: 1.25.4 language_version: 1.23.6
#- repo: https://github.com/jumanjihouse/pre-commit-hooks #- repo: https://github.com/jumanjihouse/pre-commit-hooks
# rev: 3.0.0 # rev: 3.0.0
# hooks: # hooks:
@ -97,4 +89,3 @@ repos:
rev: 0.4.3 rev: 0.4.3
hooks: hooks:
- id: teyit - id: teyit
language_version: python3.12

9
.vscode/launch.json vendored
View File

@ -11,7 +11,7 @@
"program": "${workspaceFolder}/src/backend/InvenTree/manage.py", "program": "${workspaceFolder}/src/backend/InvenTree/manage.py",
"args": [ "args": [
"runserver", "runserver",
"0.0.0.0:8000", // expose server in network (useful for testing with mobile app) // "0.0.0.0:8000", // expose server in network (useful for testing with mobile app)
// "--noreload" // disable auto-reload // "--noreload" // disable auto-reload
], ],
"django": true, "django": true,
@ -35,10 +35,7 @@
"request": "launch", "request": "launch",
"program": "${workspaceFolder}/src/backend/InvenTree/manage.py", "program": "${workspaceFolder}/src/backend/InvenTree/manage.py",
"args": [ "args": [
"runserver", "runserver"
"0.0.0.0:8000",
// "--sync",// Synchronize worker tasks to foreground thread
// "--noreload", // disable auto-reload
], ],
"django": true, "django": true,
"justMyCode": false "justMyCode": false
@ -47,7 +44,7 @@
"name": "InvenTree invoke schema", "name": "InvenTree invoke schema",
"type": "debugpy", "type": "debugpy",
"request": "launch", "request": "launch",
"program": "${workspaceFolder}/.venv/lib/python3.12/site-packages/invoke/__main__.py", "program": "${workspaceFolder}/.venv/lib/python3.9/site-packages/invoke/__main__.py",
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}",
"args": [ "args": [
"dev.schema","--ignore-warnings" "dev.schema","--ignore-warnings"

View File

@ -1,5 +0,0 @@
See [CONTRIBUTING.md](CONTRIBUTING.md) for codebase guidance.
Security reports must follow the security policy in [SECURITY.md](docs/docs/SECURITY.md) and provide how they interact with the [threat model](docs/docs/concepts/threat_model.md).
Do not open a pull request without manual review by a human. Do not file AI generated issues under any circumstances.
Using AI generated content in issue/PR discussions might lead to code of conduct violations and/or bans.

View File

@ -1,130 +1,10 @@
# Changelog # Changelog
All major notable changes to this project will be documented in this file (starting with 1.0.0). All notable changes to this project will be documented in this file (starting with 1.0.0).
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased - xxxx.xx.xx
### Breaking Changes
- [#12223](https://github.com/inventree/InvenTree/pull/12223) removes support for python 3.11 and stops providing packages for Debian 11 and Ubuntu 20.04.
### Added
- [#12295](https://github.com/inventree/InvenTree/pull/12295) adds "consumable" field to the Part model and API endpoints
- [#12250](https://github.com/inventree/InvenTree/pull/12250) adds "active" field to the ProjectCode model and API endpoints
### Changed
- [#12274](https://github.com/inventree/InvenTree/pull/12274) fixes a bug in rendering the "table field" component in frontend forms. Any plugins which make use of the "table field" component in their forms may be affected by this change, and will need to update their form definitions accordingly.
### Removed
## 1.4.0 - 2026-06-24
### Breaking Changes
- [#12160](https://github.com/inventree/InvenTree/pull/12160) changes the way that remote URIs are loaded into the PDF report generator. Remote URIs (e.g. `http://` and `https://`) are now blocked by default, and can be enabled via the `REPORT_FETCH_URLS` system setting. This change was made to improve the security of the report generation process, as allowing remote URL fetching can potentially expose internal network services to SSRF attacks. Additionally, file URIs (e.g. `file://`) are now always blocked, and assets must be embedded as `data:` URIs before reaching the PDF generator.
- [#12107](https://github.com/inventree/InvenTree/pull/12107) makes a breaking change to the `SalesOrderStatusGroups` enum, fixing a bug where the "shipped" status was not included in the "active" group. This change may affect any external client applications which make use of the `SalesOrderStatusGroups` enum, as the "shipped" status will now be included in the "active" group instead of the "complete" group. If you are using this enum in an external client application, you will need to update your application to account for this change.
- [#9604](https://github.com/inventree/InvenTree/pull/9604) refactors user API endpoint to be less ambiguous
- [#11893](https://github.com/inventree/InvenTree/pull/11893) bumps Node environment to version 24 LTS - this is only relevant if you build the frontend assets yourself
### Added
- [#12208](https://github.com/inventree/InvenTree/pull/12208) adds custom locale support for rendering currencies, dates and numbers within reports. This allows users to specify a custom locale for report rendering, which can be used to control the formatting of dates, numbers and currency values in the generated reports.
- [#12204](https://github.com/inventree/InvenTree/pull/12204) adds new filtering options to PartCategoryTree and StockLocationTree API endpoints, allowing tree data to be fetched dynamically
- [#12165](https://github.com/inventree/InvenTree/pull/12165) adds support for parameters against the PartCategory model
- [#12103](https://github.com/inventree/InvenTree/pull/12103) adds column-based filtering to table views in the user interface. This extends the existing table filtering functionality by allowing users to apply filters directly to individual columns.
- [#12093](https://github.com/inventree/InvenTree/pull/12093) adds "read_only" attribute to PluginSetting API endpoint, which indicates whether a particular plugin setting is read-only (i.e. cannot be modified via the API)
- [#12079](https://github.com/inventree/InvenTree/pull/12079) adds the ability to save filter groups for table and calendar views in the user interface. This allows users to save and reuse commonly used filter configurations, improving the usability and efficiency of the interface.
- [#12077](https://github.com/inventree/InvenTree/pull/12077) adds "tags" fields to multiple new model types and a /api/tag/ endpoint for fetching tags. Also adds the ability to filter various model types by tags.
- [#12019](https://github.com/inventree/InvenTree/pull/12019) adds a "location" field to the StockCount API endpoint, allowing users to specify a location when performing a stock count. This field is optional, and if not provided, the stock count will be performed without changing the location of the stock item. If a location is provided, the stock item(s) will be moved to the specified location as part of the stock count operation.
- [#12011](https://github.com/inventree/InvenTree/pull/12011) adds a "creation_date" field to the StockItem API endpoint, allowing users to track when each stock item was created. This field is read-only and is automatically set to the current date and time when a new stock item is created.
- [#12000](https://github.com/inventree/InvenTree/pull/12000) adds support for auto-allocation of stock items against sales orders. This includes both backend and frontend changes, allowing users to trigger auto-allocation via the API or through the UI. The auto-allocation process will attempt to allocate available stock items to the sales order line items, based on the specified stock sorting and allocation rules.
- [#11920](https://github.com/inventree/InvenTree/pull/11920) adds support for renaming attachments after they have been uploaded. This includes both backend and frontend changes, allowing users to rename attachments via the API or through the UI.
- [#11914](https://github.com/inventree/InvenTree/pull/11914) adds a "maximum_stock" field to the Part model, allowing users to specify a maximum preferred stock level for each part. This is used in conjunction with the existing "minimum_stock" field to allow users to define a preferred stock range for each part. The "high_stock" filter has also been added to the Part API endpoint, allowing users to filter parts which are above their maximum stock level.
- [#11631](https://github.com/inventree/InvenTree/pull/11631) adds "raw_amount" field to the BomItem model, allowing BOM quantities to account for the units of measure of the underlying part.
- [#11872](https://github.com/inventree/InvenTree/pull/11872) adds a global setting to allow or disallow the deletion of serialized stock items.
- [#11861](https://github.com/inventree/InvenTree/pull/11861) adds support for bulk-replacing a component in multiple BOMs simultaneously
- [#11853](https://github.com/inventree/InvenTree/pull/11853) adds BOM comparison functionality, allowing users to compare the BOM of one assembly with another assembly.
- [#11809](https://github.com/inventree/InvenTree/pull/11809) adds multi-level subassembly display mode to the BOM table, allowing users to view multiple levels of subassemblies in a single table view. This is an optional display mode which can be toggled on or off by the user.
- [#11778](https://github.com/inventree/InvenTree/pull/11778) adds inline supplier part creation to po line item addition dialog.
- [#11772](https://github.com/inventree/InvenTree/pull/11772) the UI now warns if you navigate away from a note panel with unsaved changes
- [#11788](https://github.com/inventree/InvenTree/pull/11788) adds support for custom permissions checks on database models defined in plugins. If a model defines a `check_user_permission` classmethod, this will be called to determine if a user has permission to view the model. This is required for plugin models which do not have the required ruleset definitions for the standard permission system.
- [#9570](https://github.com/inventree/InvenTree/pull/9570) adds support for defining primary actions via plugins
### Changed
- [#12197](https://github.com/inventree/InvenTree/pull/12197) requires staff permissions to restart machines via the API.
- [#12142](https://github.com/inventree/InvenTree/pull/12142) prevents users from printing reports or labels against models for which they do not have adequate permissions. This change improves the security of the system by ensuring that users cannot access or print reports or labels for models they do not have permission to view.
- [#11990](https://github.com/inventree/InvenTree/pull/11990) build output operations performed via the API now offload the work to a background task, and now return a task ID which can be used to monitor the progress of the task. This allows for better performance and responsiveness when performing build output operations, as the work is performed asynchronously in the background.
- [#11825](https://github.com/inventree/InvenTree/pull/11825) adds a new "bom" ruleset and associated permissions for BOM management, separate from the "part" ruleset which remains focused on part management. This allows for more granular control over user permissions, allowing users to have different levels of access to part management and BOM management functionality.
- [#11816](https://github.com/inventree/InvenTree/pull/11816) makes the `issued_by` field on the `Build` API read only, and instead sets the `issued_by` field to the current user when a build is created. This change was made to ensure that the `issued_by` field accurately reflects the user who created the build, and to prevent users from setting this field to an arbitrary value when creating or updating a build.
### Removed
- [#12071](https://github.com/inventree/InvenTree/pull/12071) removes the "review_needed" field on the StockItem model. Note that this field was never exposed to the API or any business logic, and is essentially a no-op field which is not used for anything. This field was removed to simplify the StockItem model and reduce confusion around its purpose.
- [#11962](https://github.com/inventree/InvenTree/pull/11962) removes the "remote_image" field from the Part API endpoint, which (previously) allowed the user to specify a remote URL for an image to be downloaded and associated with the part. This field was removed due to security concerns around downloading images from arbitrary URLs. If you were using this field in an external client application, you will need to update your application to use the new "download_image_from_url" API endpoint instead.
## 1.3.0 - 2026-04-11
### Breaking Changes
- [#11303](https://github.com/inventree/InvenTree/pull/11303) removes the `default_supplier` field from the `Part` model. Instead, the `SupplierPart` model now has a `primary` field which is used to indicate which supplier is the default for a given part. Any external client applications which made use of the old `default_supplier` field will need to be updated.
- [#11500](https://github.com/inventree/InvenTree/pull/11500) fixes a spelling mistake in the database configuration values, which may affect some users running the PostgreSQL database backend. The `tcp_keepalives_internal` option has been renamed to `tcp_keepalives_interval` to reflect the correct PostgreSQL configuration option name. If you are using PostgreSQL, and have set a custom value for the `tcp_keepalives_internal` option, you will need to update this to `tcp_keepalives_interval` in your configuration (either via environment variable or config file).
### Added
- [#11702](https://github.com/inventree/InvenTree/pull/11702) adds "last updated" and "updated by" fields for label and report templates, allowing users to track when a template was last modified and by whom.
- [#11685](https://github.com/inventree/InvenTree/pull/11685) exposes the data importer wizard to the plugin interface, allowing plugins to trigger the data importer wizard and perform custom data imports from the UI.
- [#11692](https://github.com/inventree/InvenTree/pull/11692) adds line item numbering for external orders (purchase, sales and return orders). This allows users to specify a line number for each line item on the order, which can be used for reference purposes. The line number is optional, and can be left blank if not required. The line number is stored as a string, to allow for more flexible formatting (e.g. "1", "1.1", "A", etc).
- [#11641](https://github.com/inventree/InvenTree/pull/11641) adds support for custom parameters against the SalesOrderShipment model.
- [#11527](https://github.com/inventree/InvenTree/pull/11527) adds a new API endpoint for monitoring the status of a particular background task. This endpoint allows clients to check the status of a background task and receive updates when the task is complete. This is useful for long-running tasks that may take some time to complete, allowing clients to provide feedback to users about the progress of the task.
- [#11405](https://github.com/inventree/InvenTree/pull/11405) adds default table filters, which hide inactive items by default. The default table filters are overridden by user filter selection, and only apply to the table view initially presented to the user. This means that users can still view inactive items if they choose to, but they will not be shown by default.
- [#11222](https://github.com/inventree/InvenTree/pull/11222) adds support for data import using natural keys, allowing for easier association of related objects without needing to know their internal database IDs.
- [#11383](https://github.com/inventree/InvenTree/pull/11383) adds "exists_for_model_id", "exists_for_related_model", and "exists_for_related_model_id" filters to the ParameterTemplate API endpoint. These filters allow users to check for the existence of parameters associated with specific models or related models, improving the flexibility and usability of the API.
- [#10887](https://github.com/inventree/InvenTree/pull/10887) adds the ability to auto-allocate tracked items against specific build outputs. Currently, this will only allocate items where the serial number of the tracked item matches the serial number of the build output, but in future this may be extended to allow for more flexible allocation rules.
- [#11372](https://github.com/inventree/InvenTree/pull/11372) adds backup metadata setter and restore metadata validator functions to ensure common footguns are harder to trigger when using the backup and restore functionality.
- [#11374](https://github.com/inventree/InvenTree/pull/11374) adds `updated_at` field on purchase, sales and return orders.
- [#11074](https://github.com/inventree/InvenTree/pull/11074) adds "Keep form open" option on create form which leaves dialog with form opened after form submitting.
### Changed
- [#11648](https://github.com/inventree/InvenTree/pull/11648) improves the import/export process, allowing data records defined by plugins to be loaded when importing a database from a file.
- [#11630](https://github.com/inventree/InvenTree/pull/11630) enhances the `import_records` and `export_records` system commands, by adding a metadata entry to the exported data file to allow for compatibility checks during data import.
### Removed
- [#11581](https://github.com/inventree/InvenTree/pull/11581) removes the ability to specify arbitrary filters when performing bulk operations via the API. This functionality represented a significant security risk, and was not required for any existing use cases. Bulk operations now only work with a provided list of primary keys.
## 1.2.0 - 2026-02-12
### Breaking Changes
- [#10699](https://github.com/inventree/InvenTree/pull/10699) removes the `PartParameter` and `PartParameterTemplate` models (and associated API endpoints). These have been replaced with generic `Parameter` and `ParameterTemplate` models (and API endpoints). Any external client applications which made use of the old endpoints will need to be updated.
- [#11035](https://github.com/inventree/InvenTree/pull/11035) moves to a single endpoint for all metadata operations. The previous endpoints for PartMetadata, SupplierPartMetadata, etc have been removed. Any external client applications which made use of the old endpoints will need to be updated.
### Added
- Adds "Category" columns to BOM and Build Item tables and APIs in [#10722](https://github.com/inventree/InvenTree/pull/10772)
- Adds generic "Parameter" and "ParameterTemplate" models (and associated API endpoints) in [#10699](https://github.com/inventree/InvenTree/pull/10699)
- Adds parameter support for multiple new model types in [#10699](https://github.com/inventree/InvenTree/pull/10699)
- Allows report generator to produce PDF input controls in [#10969](https://github.com/inventree/InvenTree/pull/10969)
- UI overhaul of parameter management in [#10699](https://github.com/inventree/InvenTree/pull/10699)
- Allow input controls within generated PDF reports in [#10969](https://github.com/inventree/InvenTree/pull/10969)
### Changed
- Improved stocktake functionality in [#11257](https://github.com/inventree/InvenTree/pull/11257)
### Removed
- Removed python 3.9 / 3.10 support as part of Django 5.2 upgrade in [#10730](https://github.com/inventree/InvenTree/pull/10730)
- Removed the "PartParameter" and "PartParameterTemplate" models (and associated API endpoints) in [#10699](https://github.com/inventree/InvenTree/pull/10699)
- Removed the "ManufacturerPartParameter" model (and associated API endpoints) [#10699](https://github.com/inventree/InvenTree/pull/10699)
- Removed individual metadata endpoints for all models ([#11035](https://github.com/inventree/InvenTree/pull/11035))
## 1.1.0 - 2025-11-02 ## 1.1.0 - 2025-11-02
### Added ### Added

View File

@ -1,5 +0,0 @@
See [CONTRIBUTING.md](CONTRIBUTING.md) for codebase guidance.
Security reports must follow the security policy in [SECURITY.md](docs/docs/SECURITY.md) and provide how they interact with the [threat model](docs/docs/concepts/threat_model.md).
Do not open a pull request without manual review by a human. Do not file AI generated issues under any circumstances.
Using AI generated content in issue/PR discussions might lead to code of conduct violations and/or bans.

View File

@ -1,28 +1,15 @@
# Contributing to InvenTree ### Contributing to InvenTree
Hi there, thank you for your interest in contributing! Hi there, thank you for your interest in contributing!
Please read our contribution guidelines, before submitting your first pull request to the InvenTree codebase. Please read our contribution guidelines, before submitting your first pull request to the InvenTree codebase.
## About InvenTree ### Project File Structure
InvenTree is an open-source inventory management system designed for makers, engineers, and small manufacturers.
The codebase is split into two independently deployable layers:
**Backend — Django (Python)**
A REST API built with Django and Django REST Framework. It owns all business logic, the database schema, background task processing (Django-Q2), plugin execution, and report generation. The backend can be used standalone via the API without the frontend.
**Frontend — React (TypeScript)**
A single-page application built with React 19, Mantine 9, and Vite. It communicates exclusively through the backend REST API. It has its own build pipeline, test suite (Playwright), and i18n system (Lingui). The frontend lives entirely in `src/frontend/` and has no Django awareness.
When making changes, be clear about which layer you are working in — they have separate toolchains, test runners, and linting rules.
## Project File Structure
The InvenTree project is split into two main components: frontend and backend. This source is located in the `src` directory. All other files are used for project management, documentation, and testing. The InvenTree project is split into two main components: frontend and backend. This source is located in the `src` directory. All other files are used for project management, documentation, and testing.
``` ```bash
InvenTree/ InvenTree/
├─ .devops/ # Files for Azure DevOps
├─ .github/ # Files for GitHub ├─ .github/ # Files for GitHub
│ ├─ actions/ # Reused actions │ ├─ actions/ # Reused actions
│ ├─ ISSUE_TEMPLATE/ # Templates for issues and pull requests │ ├─ ISSUE_TEMPLATE/ # Templates for issues and pull requests
@ -52,209 +39,12 @@ InvenTree/
│ │ ├─ tsconfig.json # Settings for frontend compilation │ │ ├─ tsconfig.json # Settings for frontend compilation
├─ .pkgr.yml # Build definition for Debian/Ubuntu packages ├─ .pkgr.yml # Build definition for Debian/Ubuntu packages
├─ .pre-commit-config.yaml # Code formatter/linter configuration ├─ .pre-commit-config.yaml # Code formatter/linter configuration
├─ biome.json # JS/TS linting and formatting config
├─ CONTRIBUTING.md # Contribution guidelines and overview ├─ CONTRIBUTING.md # Contribution guidelines and overview
├─ Procfile # Process definition for Debian/Ubuntu packages ├─ Procfile # Process definition for Debian/Ubuntu packages
├─ pyproject.toml # Python tooling config (Ruff, pytest, coverage, djLint, ty)
├─ README.md # General project information and overview ├─ README.md # General project information and overview
├─ runtime.txt # Python runtime settings for Debian/Ubuntu packages build
├─ SECURITY.md # Project security policy ├─ SECURITY.md # Project security policy
├─ tasks.py # Action definitions for development, testing and deployment ├─ tasks.py # Action definitions for development, testing and deployment
``` ```
### Backend app domains
The following Django apps are defined in `src/backend/InvenTree/`:
| Directory | Domain |
|-----------|--------|
| `build/` | Build (manufacturing/assembly) orders |
| `common/` | Shared models, settings, utilities |
| `company/` | Suppliers, customers, manufacturers |
| `data_exporter/` | Data export functionality |
| `generic/` | Shared enums, events, and state machine utilities |
| `importer/` | Data import functionality |
| `InvenTree/` | Core configuration (settings, URLs, middleware) |
| `machine/` | Support for external machines and devices |
| `order/` | Purchase orders and sales orders |
| `part/` | Parts catalogue and categories |
| `stock/` | Stock items and locations |
| `report/` | Report templates and generation |
| `plugin/` | Plugin system |
| `users/` | User accounts and permissions |
| `web/` | Serves the React frontend static build to Django |
### Frontend layout
```
src/frontend/src/
components/ # Reusable React components
pages/ # Page-level route components
tables/ # Data table components
forms/ # Form components
hooks/ # Custom React hooks
states/ # Zustand global state
locales/ # i18n translation catalogues (Lingui)
```
## Development Setup
The project uses [Invoke](https://www.pyinvoketasks.com/) (`tasks.py`) as the task runner.
```bash
# One-time setup: creates venv at dev/venv/, installs deps, sets up pre-commit hooks
invoke dev.setup-dev
# Apply database migrations
invoke migrate
# Create an admin account (required to log in)
invoke superuser
# Terminal 1 — Django dev server (port 8000)
invoke dev.server
# Terminal 2 — Vite dev server with HMR (port 5173)
invoke dev.frontend-server
# Terminal 3 (optional) — Background task worker
invoke worker
```
A VS Code Dev Container configuration is available at `.devcontainer/` and includes PostgreSQL 15 and Redis 7 sidecar services.
To see all available tasks, run `invoke --list`.
## Running Backend Tests
Always pass `--keepdb` to backend test commands. It reuses the existing test database instead of rebuilding it from scratch on every run, which is significantly faster.
```bash
# All backend tests
invoke dev.test --keepdb
# Specific test module
invoke dev.test --keepdb --runtest=company.test_api
# With coverage
invoke dev.test --keepdb --coverage
# Migration tests only (skip --keepdb here — migrations must run against a fresh DB)
invoke dev.test --migrations
```
## Running Frontend Tests
Frontend tests use [Playwright](https://playwright.dev/) and target Chromium and Firefox. The test runner automatically starts the Vite dev server (port 5173), the Django backend (port 8000), and the background worker — no manual server startup is needed.
```bash
# Open Playwright's interactive UI (recommended for local development)
invoke dev.frontend-test
# Run tests in headless mode from the frontend directory
cd src/frontend && npx playwright test
# Run a specific test file
cd src/frontend && npx playwright test tests/pui_login.spec.ts
# Run tests in a specific browser only
cd src/frontend && npx playwright test --project=chromium
```
Test files live in `src/frontend/tests/` and follow the `pui_*.spec.ts` naming convention.
Locally, tests run with a single worker (required for Vite HMR compatibility). In CI they run with multiple workers against a production build for speed.
## Code Style and Linting
All formatting and linting runs automatically on commit via pre-commit hooks. Never skip them.
### Python (Backend)
Tool: **Ruff** (replaces Black, isort, flake8, and others).
```bash
ruff check src/backend/ # Lint
ruff format src/backend/ # Format
```
- Google-style docstrings enforced
- Enabled rule sets: A, B, C, D, F, I, N, SIM, PIE, PLE, PLW, RUF, UP, W
- Type checking: `ty` (configured in `pyproject.toml`)
### Django Templates
Tool: **djLint**
```bash
djlint src/backend/ --check
```
### JavaScript / TypeScript (Frontend)
Tool: **Biome** (replaces ESLint + Prettier).
```bash
cd src/frontend
yarn biome check . # Lint + format check
yarn biome format . # Format only
```
- Single quotes, space indentation
- `noUnusedImports` is an error
## Making Changes
### Backend
- Each Django app has its own `models.py`, `serializers.py`, `views.py`, `urls.py`, and `filters.py`.
- API endpoints use Django REST Framework; document them with drf-spectacular decorators.
- After changing models, create a migration: `invoke dev.makemigrations`.
- Tests live in `test_*.py` files within each app directory.
- Background tasks go through Django-Q2; define them in the app's `tasks.py`.
### Frontend
- Pages register themselves in `src/frontend/src/router.tsx`.
- Server state fetching uses TanStack Query (React Query); avoid raw `useEffect` for data fetching.
- Global UI state uses Zustand stores in `states/`.
- UI components come from Mantine 9.x; use the Mantine component library before writing custom CSS.
- Add i18n strings with Lingui (`t` macro / `Trans` component); run `invoke int.frontend-trans` to extract from source and compile. (`invoke dev.translate` is for the full translation pipeline and is not intended for local use.)
- Playwright tests live in `src/frontend/tests/`.
### Dependencies
**Python:** Add packages to `src/backend/requirements.in` (or `requirements-dev.in` for dev-only tools). The pre-commit hook runs `pip-compile` automatically on commit to regenerate `requirements.txt`. Never edit `requirements.txt` directly.
**Frontend:** Add packages with `yarn add <package>` from `src/frontend/`.
### Migrations
- Never edit existing migration files; always generate new ones.
- Keep migrations reversible where possible.
- Migration tests run in CI under the tag `migration_test`.
## CI / CD
GitHub Actions workflows live in `.github/workflows/`. Key workflows:
| Workflow | Purpose |
|----------|---------|
| `qc_checks.yaml` | Lint, type-check, backend tests, API schema |
| `frontend.yaml` | Playwright E2E tests, frontend build |
| `docker.yaml` | Docker image builds |
| `translations.yaml` | Crowdin i18n sync |
CI uses path-based filtering — only affected jobs run per PR. Coverage tracked via Codecov; quality analysis via SonarCloud.
## Key Conventions
- **REST API versioning:** Endpoint changes must not break the published API schema. Run `invoke dev.schema` and check the diff before opening a PR.
- **Plugin safety:** The plugin system (`plugin/`) is a public extension point; avoid breaking its interfaces.
- **No hardcoded secrets:** gitleaks runs in pre-commit and CI — any credential-shaped string will block merges.
- **Database portability:** Code must work on PostgreSQL, MySQL/MariaDB, and SQLite. Avoid database-specific SQL or ORM features.
- **Frontend translations:** Every user-visible string must be wrapped in a Lingui `t` macro or `<Trans>` component.
- **Test tagging:** Tag slow or special tests (`@tag('migration_test')`, `@tag('performance_test')`) so CI can filter them selectively.
---
Refer to our [contribution guidelines](https://docs.inventree.org/en/latest/develop/contributing/) for more information! Refer to our [contribution guidelines](https://docs.inventree.org/en/latest/develop/contributing/) for more information!

View File

@ -4,11 +4,12 @@
<p>Open Source Inventory Management System </p> <p>Open Source Inventory Management System </p>
<!-- Badges --> <!-- Badges -->
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/license/MIT)![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/inventree/inventree)[![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/inventree)](https://artifacthub.io/packages/search?repo=inventree) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/license/MIT)![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/inventree/inventree)
![CI](https://github.com/inventree/inventree/actions/workflows/qc_checks.yaml/badge.svg) ![CI](https://github.com/inventree/inventree/actions/workflows/qc_checks.yaml/badge.svg)
[![Documentation Status](https://readthedocs.org/projects/inventree/badge/?version=latest)](https://inventree.readthedocs.io/en/latest/?badge=latest) [![Documentation Status](https://readthedocs.org/projects/inventree/badge/?version=latest)](https://inventree.readthedocs.io/en/latest/?badge=latest)
![Docker Build](https://github.com/inventree/inventree/actions/workflows/docker.yaml/badge.svg) ![Docker Build](https://github.com/inventree/inventree/actions/workflows/docker.yaml/badge.svg)
[![Netlify Status](https://api.netlify.com/api/v1/badges/9bbb2101-0a4d-41e7-ad56-b63fb6053094/deploy-status)](https://app.netlify.com/sites/inventree/deploys) [![Netlify Status](https://api.netlify.com/api/v1/badges/9bbb2101-0a4d-41e7-ad56-b63fb6053094/deploy-status)](https://app.netlify.com/sites/inventree/deploys)
[![Performance Testing](https://dev.azure.com/InvenTree/InvenTree%20test%20statistics/_apis/build/status%2Fmatmair.InvenTree?branchName=testing)](https://dev.azure.com/InvenTree/InvenTree%20test%20statistics/_build/latest?definitionId=3&branchName=testing)
[![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/7179/badge)](https://bestpractices.coreinfrastructure.org/projects/7179) [![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/7179/badge)](https://bestpractices.coreinfrastructure.org/projects/7179)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/inventree/InvenTree/badge)](https://securityscorecards.dev/viewer/?uri=github.com/inventree/InvenTree) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/inventree/InvenTree/badge)](https://securityscorecards.dev/viewer/?uri=github.com/inventree/InvenTree)
@ -55,7 +56,7 @@ InvenTree is designed to be **extensible**, and provides multiple options for **
* [InvenTree API](https://docs.inventree.org/en/latest/api/) * [InvenTree API](https://docs.inventree.org/en/latest/api/)
* [Python module](https://docs.inventree.org/en/latest/api/python/) * [Python module](https://docs.inventree.org/en/latest/api/python/)
* [Plugin interface](https://docs.inventree.org/en/latest/plugins/) * [Plugin interface](https://docs.inventree.org/en/latest/plugins/)
* [Third party tools](https://inventree.org/extend/integrate/) * [Third party tools](https://docs.inventree.org/en/latest/plugins/integrate/)
<!-- TechStack --> <!-- TechStack -->
### :space_invader: Tech Stack ### :space_invader: Tech Stack
@ -76,7 +77,6 @@ InvenTree is designed to be **extensible**, and provides multiple options for **
<ul> <ul>
<li><a href="https://www.postgresql.org/">PostgreSQL</a></li> <li><a href="https://www.postgresql.org/">PostgreSQL</a></li>
<li><a href="https://www.mysql.com/">MySQL</a></li> <li><a href="https://www.mysql.com/">MySQL</a></li>
<li><a href="https://www.mariadb.org/">MariaDB</a></li>
<li><a href="https://www.sqlite.org/">SQLite</a></li> <li><a href="https://www.sqlite.org/">SQLite</a></li>
<li><a href="https://redis.io/">Redis</a></li> <li><a href="https://redis.io/">Redis</a></li>
</ul> </ul>
@ -200,8 +200,6 @@ Find a full list of used third-party libraries in the license information dialog
</a> </a>
<a href="https://www.netlify.com"> <img src="https://www.netlify.com/v3/img/components/netlify-color-bg.svg" alt="Deploys by Netlify" /> </a> <a href="https://www.netlify.com"> <img src="https://www.netlify.com/v3/img/components/netlify-color-bg.svg" alt="Deploys by Netlify" /> </a>
<a href="https://crowdin.com"> <img src="https://crowdin.com/images/crowdin-logo.svg" alt="Translation by Crowdin" /> </a> <br> <a href="https://crowdin.com"> <img src="https://crowdin.com/images/crowdin-logo.svg" alt="Translation by Crowdin" /> </a> <br>
<a href="https://codspeed.io/inventree/InvenTree?utm_source=badge"><img src="https://img.shields.io/endpoint?url=https://codspeed.io/badge.json" alt="CodSpeed Badge"/></a>
<a href="https://flakiness.io/InvenTree/InvenTree"><img src="https://img.shields.io/endpoint?url=https%3A%2F%2Fflakiness.io%2Fapi%2Fbadge%3Finput%3D%257B%2522badgeToken%2522%253A%2522badge-35mqq5Ht4uL3vGF8lR9P2D%2522%257D" alt="Flakiness Badge"/></a>
</p> </p>

View File

@ -1,6 +1,3 @@
ignore:
- "src/backend/InvenTree/**/test_migrations.py"
coverage: coverage:
status: status:
project: project:
@ -24,7 +21,7 @@ flag_management:
carryforward: true carryforward: true
statuses: statuses:
- type: project - type: project
target: 38% target: 40%
- name: web - name: web
carryforward: true carryforward: true
statuses: statuses:
@ -43,10 +40,8 @@ component_management:
name: Backend Apps name: Backend Apps
paths: paths:
- src/backend/InvenTree/build/** - src/backend/InvenTree/build/**
- src/backend/InvenTree/common/**
- src/backend/InvenTree/company/** - src/backend/InvenTree/company/**
- src/backend/InvenTree/data_exporter/** - src/backend/InvenTree/data_exporter/**
- src/backend/InvenTree/generic/**
- src/backend/InvenTree/importer/** - src/backend/InvenTree/importer/**
- src/backend/InvenTree/machine/** - src/backend/InvenTree/machine/**
- src/backend/InvenTree/order/** - src/backend/InvenTree/order/**
@ -72,8 +67,7 @@ component_management:
- component_id: web - component_id: web
name: Frontend name: Frontend
paths: paths:
- src/frontend/lib/** - src/frontend/**
- src/frontend/src/**
statuses: statuses:
- type: project - type: project
target: 68% # 90% target: 68% # 90%

View File

@ -12,7 +12,6 @@ INVENTREE_TAG=stable
INVENTREE_SITE_URL="http://inventree.localhost" INVENTREE_SITE_URL="http://inventree.localhost"
#INVENTREE_SITE_URL="http://192.168.1.2" # You can specify a local IP address here #INVENTREE_SITE_URL="http://192.168.1.2" # You can specify a local IP address here
#INVENTREE_SITE_URL="https://inventree.my-domain.com" # Or a public domain name (which you control) #INVENTREE_SITE_URL="https://inventree.my-domain.com" # Or a public domain name (which you control)
INVENTREE_WEB_PORT=8000
# InvenTree proxy forwarding settings # InvenTree proxy forwarding settings
INVENTREE_USE_X_FORWARDED_HOST=True INVENTREE_USE_X_FORWARDED_HOST=True

View File

@ -2,7 +2,6 @@
# The following environment variables may be used: # The following environment variables may be used:
# - INVENTREE_SITE_URL: The upstream URL of the InvenTree site (default: inventree.localhost) # - INVENTREE_SITE_URL: The upstream URL of the InvenTree site (default: inventree.localhost)
# - INVENTREE_SERVER: The internal URL of the InvenTree container (default: http://inventree-server:8000) # - INVENTREE_SERVER: The internal URL of the InvenTree container (default: http://inventree-server:8000)
# - INVENTREE_WEB_PORT: The port on which the InvenTree web server listens (default: 8000)
# #
# Note that while this file is a good starting point, it may need to be modified to suit your specific requirements # Note that while this file is a good starting point, it may need to be modified to suit your specific requirements
# #
@ -21,7 +20,7 @@
header Allow GET,HEAD,OPTIONS header Allow GET,HEAD,OPTIONS
header Access-Control-Allow-Origin * header Access-Control-Allow-Origin *
header Access-Control-Allow-Methods GET,HEAD,OPTIONS header Access-Control-Allow-Methods GET,HEAD,OPTIONS
header Access-Control-Allow-Headers Authorization,Content-Type,User-Agent,traceparent header Access-Control-Allow-Headers Authorization,Content-Type,User-Agent
@cors_preflight{args[0]} method OPTIONS @cors_preflight{args[0]} method OPTIONS

View File

@ -9,8 +9,7 @@
# - Runs InvenTree web server under django development server # - Runs InvenTree web server under django development server
# - Monitors source files for any changes, and live-reloads server # - Monitors source files for any changes, and live-reloads server
# Base image last bumped 2026-06-16 FROM python:3.11-slim-trixie@sha256:1d6131b5d479888b43200645e03a78443c7157efbdb730e6b48129740727c312 AS inventree_base
FROM python:3.14.6-slim-trixie@sha256:b877e50bd90de10af8d82c57a022fc2e0dc731c5320d762a27986facfc3355c1 AS inventree_base
# Build arguments for this image # Build arguments for this image
ARG commit_tag="" ARG commit_tag=""
@ -18,7 +17,6 @@ ARG commit_hash=""
ARG commit_date="" ARG commit_date=""
ARG data_dir="data" ARG data_dir="data"
ARG NODE_VERSION=24
ENV PYTHONUNBUFFERED=1 ENV PYTHONUNBUFFERED=1
ENV PIP_DISABLE_PIP_VERSION_CHECK=1 ENV PIP_DISABLE_PIP_VERSION_CHECK=1
@ -119,11 +117,15 @@ RUN pip install --user --require-hashes -r base_requirements.txt --no-cache-dir
rm -rf /root/.cache/pip rm -rf /root/.cache/pip
# Install frontend build dependencies # Install frontend build dependencies
# pinned to v0.40.5 RUN apt-get update && apt-get install -y --no-install-recommends \
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/1889911f0841e669de0be5bd02c737a3f1fd20fa/install.sh | bash && \ nodejs npm \
bash -c "export NVM_DIR="$HOME/.nvm" && source $HOME/.nvm/nvm.sh && \ && apt-get clean \
nvm install $NODE_VERSION && corepack enable yarn && yarn config set network-timeout 600000 -g" && rm -rf /var/lib/apt/lists/*
RUN bash -c "source $HOME/.nvm/nvm.sh && cd '${INVENTREE_HOME}' && invoke int.frontend-compile --extract"
RUN npm install -g n yarn --ignore-scripts && \
yarn config set network-timeout 600000 -g
RUN bash -c "n lts"
RUN cd "${INVENTREE_HOME}" && invoke int.frontend-compile --extract
# InvenTree production image: # InvenTree production image:
# - Copies required files from local directory # - Copies required files from local directory
@ -146,11 +148,8 @@ ENV PATH=/root/.local/bin:$PATH
COPY --from=builder_stage ${INVENTREE_BACKEND_DIR}/InvenTree/web/static/web ${INVENTREE_BACKEND_DIR}/InvenTree/web/static/web COPY --from=builder_stage ${INVENTREE_BACKEND_DIR}/InvenTree/web/static/web ${INVENTREE_BACKEND_DIR}/InvenTree/web/static/web
COPY --from=builder_stage /root/.local /root/.local COPY --from=builder_stage /root/.local /root/.local
# Compile Django backend translations during image build
RUN bash -c "cd '${INVENTREE_HOME}' && invoke int.backend-compilemessages"
# Launch the production server # Launch the production server
CMD ["sh", "-c", "exec gunicorn -c ./gunicorn.conf.py InvenTree.wsgi -b ${INVENTREE_WEB_ADDR}:${INVENTREE_WEB_PORT} --chdir ${INVENTREE_BACKEND_DIR}/InvenTree"] CMD ["sh", "-c", "exec gunicorn -c ./gunicorn.conf.py InvenTree.wsgi -b 0.0.0.0:8000 --chdir ${INVENTREE_BACKEND_DIR}/InvenTree"]
FROM builder_stage AS dev FROM builder_stage AS dev

View File

@ -3,7 +3,7 @@
# - gunicorn as the InvenTree web server # - gunicorn as the InvenTree web server
# - django-q as the InvenTree background worker process # - django-q as the InvenTree background worker process
# - Caddy as a reverse proxy # - Caddy as a reverse proxy
# - redis as the cache manager (optional, enabled by default) # - redis as the cache manager (optional, disabled by default)
# --------------------- # ---------------------
# READ BEFORE STARTING! # READ BEFORE STARTING!
@ -64,8 +64,6 @@ services:
- .env - .env
expose: expose:
- ${INVENTREE_CACHE_PORT:-6379} - ${INVENTREE_CACHE_PORT:-6379}
volumes:
- ${INVENTREE_EXT_VOLUME}/redis:/data
restart: always restart: always
# InvenTree web server service # InvenTree web server service
@ -76,14 +74,12 @@ services:
container_name: inventree-server container_name: inventree-server
# Only change this port if you understand the stack. # Only change this port if you understand the stack.
expose: expose:
- ${INVENTREE_WEB_PORT:-8000} - 8000
depends_on: depends_on:
- inventree-db - inventree-db
- inventree-cache - inventree-cache
env_file: env_file:
- .env - .env
environment:
INVENTREE_SERVER: http://inventree-server:${INVENTREE_WEB_PORT}
volumes: volumes:
# Data volume must map to /home/inventree/data # Data volume must map to /home/inventree/data
- ${INVENTREE_EXT_VOLUME}:/home/inventree/data:z - ${INVENTREE_EXT_VOLUME}:/home/inventree/data:z

View File

@ -19,7 +19,7 @@ threads = 4
# Worker timeout (default = 90 seconds) # Worker timeout (default = 90 seconds)
timeout = int(os.environ.get('INVENTREE_GUNICORN_TIMEOUT', '90')) timeout = os.environ.get('INVENTREE_GUNICORN_TIMEOUT', '90')
# Number of worker processes # Number of worker processes
workers = os.environ.get('INVENTREE_GUNICORN_WORKERS', None) workers = os.environ.get('INVENTREE_GUNICORN_WORKERS', None)
@ -43,13 +43,7 @@ preload_app = True
def post_fork(server, worker): def post_fork(server, worker):
"""Post-fork hook called after each worker process is forked.""" """Post-fork hook to set up logging for each worker."""
from django.db import connections
# Close any DB connections inherited from the master process — PostgreSQL
# connections are not fork-safe, so each worker must open its own.
connections.close_all()
from django.conf import settings from django.conf import settings
if not settings.TRACING_ENABLED: if not settings.TRACING_ENABLED:

View File

@ -1,4 +1,4 @@
#!/bin/bash #!/bin/ash
# exit when any command fails # exit when any command fails
set -e set -e

View File

@ -1,23 +1,23 @@
# Base python requirements for docker containers # Base python requirements for docker containers
# Basic package requirements # Basic package requirements
invoke # Invoke build tool invoke>=2.2.0 # Invoke build tool
pyyaml pyyaml>=6.0.1
setuptools setuptools>=69.0.0
wheel wheel>=0.41.0
# Database links # Database links
psycopg[binary, pool] psycopg[binary, pool]
mysqlclient mysqlclient>=2.2.0
mariadb mariadb>=1.1.8
# gunicorn web server # gunicorn web server
gunicorn gunicorn>=22.0.0
# LDAP required packages # LDAP required packages
django-auth-ldap # Django integration for ldap auth django-auth-ldap # Django integration for ldap auth
python-ldap # LDAP auth support python-ldap # LDAP auth support
django<6.0 # Force lower to match main project django<5.0 # Force lower to match main project
# Upgraded python package installer # Upgraded python package installer
uv uv

View File

@ -1,34 +1,27 @@
# This file was autogenerated by uv via the following command: # This file was autogenerated by uv via the following command:
# uv pip compile contrib/container/requirements.in -o contrib/container/requirements.txt --python-version=3.14 -c src/backend/requirements.txt # uv pip compile contrib/container/requirements.in -o contrib/container/requirements.txt --python-version=3.11 --no-strip-extras --generate-hashes -b src/backend/requirements.txt
asgiref==3.11.1 \ asgiref==3.10.0 \
--hash=sha256:5f184dc43b7e763efe848065441eac62229c9f7b0475f41f80e207a114eda4ce \ --hash=sha256:aef8a81283a34d0ab31630c9b7dfe70c812c95eba78171367ca8745e88124734 \
--hash=sha256:e8667a091e69529631969fd45dc268fa79b99c92c5fcdda727757e52146ec133 --hash=sha256:d89f2d8cd8b56dada7d52fa7dc8075baa08fb836560710d38c292a7a3f78c04e
# via django
django==4.2.25 \
--hash=sha256:2391ab3d78191caaae2c963c19fd70b99e9751008da22a0adcc667c5a4f8d311 \
--hash=sha256:9584cf26b174b35620e53c2558b09d7eb180a655a3470474f513ff9acb494f8c
# via # via
# -c src/backend/requirements.txt
# django
django==5.2.15 \
--hash=sha256:0eb4a9bb1853a35b0286dbc6d916bd352c8c2687195a7f2d6f80cefd840e4970 \
--hash=sha256:5154a9bf84ac01dde011e367f355c07dbb329532e06810dcf3ef2af269e236e7
# via
# -c src/backend/requirements.txt
# -r contrib/container/requirements.in # -r contrib/container/requirements.in
# django-auth-ldap # django-auth-ldap
django-auth-ldap==5.3.0 \ django-auth-ldap==5.2.0 \
--hash=sha256:743d8107b146240b46f7e97207dc06cb11facc0cd70dce490b7ca09dd5643d19 \ --hash=sha256:08ba6efc0340d9874725a962311b14991e29a33593eb150a8fb640709dbfa80f \
--hash=sha256:aa880415983149b072f876d976ef8ec755a438090e176817998263a6ed9e1038 --hash=sha256:7dc6eb576ba36051850b580e4bdf4464e04bbe7367c3827a3121b4d7c51fb175
# via -r contrib/container/requirements.in
gunicorn==23.0.0 \
--hash=sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d \
--hash=sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec
# via -r contrib/container/requirements.in
invoke==2.2.1 \
--hash=sha256:2413bc441b376e5cd3f55bb5d364f973ad8bdd7bf87e53c79de3c11bf3feecc8 \
--hash=sha256:515bf49b4a48932b79b024590348da22f39c4942dff991ad1fb8b8baea1be707
# via -r contrib/container/requirements.in # via -r contrib/container/requirements.in
gunicorn==26.0.0 \
--hash=sha256:40233d26a5f0d1872916188c276e21641155111c2853f0c2cd55260aec0d24fc \
--hash=sha256:ca9346f85e3a4aeeb64d491045c16b9a35647abd37ea15efe53080eb8b090baf
# via
# -c src/backend/requirements.txt
# -r contrib/container/requirements.in
invoke==3.0.3 \
--hash=sha256:437b6a622223824380bfb4e64f612711a6b648c795f565efc8625af66fb57f0c \
--hash=sha256:f11327165e5cbb89b2ad1d88d3292b5113332c43b8553b494da435d6ec6f5053
# via
# -c src/backend/requirements.txt
# -r contrib/container/requirements.in
mariadb==1.1.14 \ mariadb==1.1.14 \
--hash=sha256:0f5fc74023f2e479be159542633f8b5865fee18a36e5a6d4e262387b39a692ee \ --hash=sha256:0f5fc74023f2e479be159542633f8b5865fee18a36e5a6d4e262387b39a692ee \
--hash=sha256:1a50b4612c0dd5b69690cebb34cef552a7f64dcadeb5aa91d70cd99bf01bc5b3 \ --hash=sha256:1a50b4612c0dd5b69690cebb34cef552a7f64dcadeb5aa91d70cd99bf01bc5b3 \
@ -44,91 +37,97 @@ mariadb==1.1.14 \
--hash=sha256:98d552a8bb599eceaa88f65002ad00bd88aeed160592c273a7e5c1d79ab733dd \ --hash=sha256:98d552a8bb599eceaa88f65002ad00bd88aeed160592c273a7e5c1d79ab733dd \
--hash=sha256:e6d702a53eccf20922e47f2f45cfb5c7a0c2c6c0a46e4ee2d8a80d0ff4a52f34 --hash=sha256:e6d702a53eccf20922e47f2f45cfb5c7a0c2c6c0a46e4ee2d8a80d0ff4a52f34
# via -r contrib/container/requirements.in # via -r contrib/container/requirements.in
mysqlclient==2.2.8 \ mysqlclient==2.2.7 \
--hash=sha256:000c7ec3d11e7c411db832e4cfcd7f05db47464326381f5d5ae991b4bb572f93 \ --hash=sha256:199dab53a224357dd0cb4d78ca0e54018f9cee9bf9ec68d72db50e0a23569076 \
--hash=sha256:260cce0e81446c83bf0a389e0fae38d68547d9f8fc0833bc733014e10ce28a99 \ --hash=sha256:201a6faa301011dd07bca6b651fe5aaa546d7c9a5426835a06c3172e1056a3c5 \
--hash=sha256:60c9ed339dc09e3d5380cc2a9f42e86754fee25a661ced77a02df77990664c92 \ --hash=sha256:24ae22b59416d5fcce7e99c9d37548350b4565baac82f95e149cac6ce4163845 \
--hash=sha256:86db31bba7b3480fec2751350e9790e24f016f89af33a87bab7e79f7196474e8 \ --hash=sha256:2e3c11f7625029d7276ca506f8960a7fd3c5a0a0122c9e7404e6a8fe961b3d22 \
--hash=sha256:8ed20c5615a915da451bb308c7d0306648a4fd9a2809ba95c992690006306199 \ --hash=sha256:4b4c0200890837fc64014cc938ef2273252ab544c1b12a6c1d674c23943f3f2e \
--hash=sha256:9bed7c8d3b629bdc09e17fb628d5b3b0a5fd1f12b09432b464b9126c727bedc0 \ --hash=sha256:92af368ed9c9144737af569c86d3b6c74a012a6f6b792eb868384787b52bb585 \
--hash=sha256:a81f5e12f8d05439709cb02fba97f9f76d1a6c528164f2260d8798fec969e300 --hash=sha256:977e35244fe6ef44124e9a1c2d1554728a7b76695598e4b92b37dc2130503069 \
--hash=sha256:a22d99d26baf4af68ebef430e3131bb5a9b722b79a9fcfac6d9bbf8a88800687
# via -r contrib/container/requirements.in # via -r contrib/container/requirements.in
packaging==26.2 \ packaging==25.0 \
--hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \ --hash=sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484 \
--hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661 --hash=sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f
# via # via
# -c src/backend/requirements.txt
# gunicorn # gunicorn
# mariadb # mariadb
# wheel psycopg[binary, pool]==3.2.11 \
psycopg[binary, pool]==3.3.4 \ --hash=sha256:217231b2b6b72fba88281b94241b2f16043ee67f81def47c52a01b72ff0c086a \
--hash=sha256:b6bbc25ccf05c8fad3b061d9db2ef0909a555171b84b07f29458a447253d679a \ --hash=sha256:398bb484ed44361e041c8f804ed7af3d2fcefbffdace1d905b7446c319321706
--hash=sha256:e21207764952cff81b6b8bdacad9a3939f2793367fdac2987b3aac36a651b5bc
# via -r contrib/container/requirements.in # via -r contrib/container/requirements.in
psycopg-binary==3.3.4 \ psycopg-binary==3.2.11 \
--hash=sha256:018fbed325936da502feb546642c982dcc4b9ffdea32dfef78dbf3b7f7ad4070 \ --hash=sha256:00221bfeb9594ca6e01207b032c300fa6f889d918bf0de47f4571c1f9f6e1578 \
--hash=sha256:0579252a1202cd73e4da137a1426e2dae993ae44e757605344282af3a082848c \ --hash=sha256:110a2036007230416fcc2c17bfe7aaa2c1fa9b6e9d21e2cd551523e3f6489759 \
--hash=sha256:136f199a407b5348b9b857c504aff60c77622a28482e7195839ce1b51238c4cc \ --hash=sha256:199f88a05dd22133eab2deb30348ef7a70c23d706c8e63fdc904234163c63517 \
--hash=sha256:13a7f380824c35896dcac7fe0f61440f7ca49d6dc73f3c13a9a4471e6a3b302e \ --hash=sha256:1db270e6bdbd183e3908cd9bb832506b99e1f2222a2fc2145f980c3ba1c8c30f \
--hash=sha256:17a21953a9e5ff3a16dab692625a3676e2f101db5e40072f39dbee2250194d68 \ --hash=sha256:20d41bcd9ac289d44ac1f6151594f7883483b4ad14680a63e04b639dc90c3349 \
--hash=sha256:1dc1f79fd16bb1f3f4421417a514607539f17804d95c7ed617265369d1981cae \ --hash=sha256:23c77dbbffe8ba679213877f7204f4599bd545b65d2d69982fd685a3fea35b11 \
--hash=sha256:1fbaa292a3c8bb61b45df1ad3da1908ccee7cb889db9425e3557d9e34e2a4829 \ --hash=sha256:260738ae222b41dbefd0d84cb2e150a112f90b41688630f57fdac487ab6d6f38 \
--hash=sha256:22cdbf5f91ef7bb91fe0c5757e1962d3127a8010256eefd9c61fcaf441802097 \ --hash=sha256:27eb6367350b75fef882c40cd6f748bfd976db2f8651f7511956f11efc15154f \
--hash=sha256:26df2717e59c0473e4465a97dfb1b7afebaa479277870fd5784d1436470db47c \ --hash=sha256:2a438fad4cc081b018431fde0e791b6d50201526edf39522a85164f606c39ddb \
--hash=sha256:276904e3452d6a23d474ef9a21eee19f20eed3d53ddd2576af033827e0ba0992 \ --hash=sha256:30e2c114d26554ae677088de5d4133cc112344d7a233200fdbf4a2ca5754c7ec \
--hash=sha256:28b7398fdd19db3232c884fb24550bdfe951221f510e195e233299e4c9b78f97 \ --hash=sha256:31f1d5630afa673c37a6327f8e3efa1f17d4e4e42972643b3478b52275233529 \
--hash=sha256:2c09aad7051326e7603c14e50636db9c01f78272dc54b3accff03d46370461e6 \ --hash=sha256:32bd319a68420631a320bb450921c8320641621a92556c97b38b1e116010c344 \
--hash=sha256:32a6fbf8481e3a370d0d72b860d35948a693cb01281da217f7b2f307636e591a \ --hash=sha256:3bd2c8fb1dec6f93383fbaa561591fa3d676e079f9cb9889af17c3020a19715f \
--hash=sha256:41f2ec0fea529832982bcb6c9415de3c86264ebe562b77a467c0fbcd7efbba8d \ --hash=sha256:3f32b09fba85d9e239229bdc5b6254420c02054f6954fe7fbd1ecf1ca93009ed \
--hash=sha256:46893c26858be12cc49ca4226ed6a60b4bfccadd946b3bebb783a60b38788228 \ --hash=sha256:478a68d50f34f6203642d245e2046d266c719ab4e593a1bb94c3be5f82e1aee1 \
--hash=sha256:47c656a8a7ba6eb0cff1801a4caaa9c8bdc12d03080e273aff1c8ac39971a77e \ --hash=sha256:47f6cf8a1d02d25238bdb8741ac641ff0ec22b1c6ff6a2acd057d0da5c712842 \
--hash=sha256:494ca54901be8cf9eb7e02c25b731f2317c378efa44f43e8f9bd0e1184ae7be4 \ --hash=sha256:49d76391b225f72dd63fcab87937ccf307ae0f093b5a382eeacf05f19a57c176 \
--hash=sha256:514404ed543efd620c85602b747df2a23cf1241b4067199e1a66f2d2757aaa41 \ --hash=sha256:4cae9bdc482e36e825d5102a9f3010e729f33a4ca83fc8a1f439ba16eb61e1f1 \
--hash=sha256:574ea21a9651958f1535c5a1c649c7409e9168bcbffa29a3f2f961f58b322949 \ --hash=sha256:54a30f00a51b9043048b3e7ee806ffd31fc5fbd02a20f0e69d21306ff33dc473 \
--hash=sha256:580ae30a5f95ccd90008ec697d3ed6a4a2047a516407ad904283fa42086936e9 \ --hash=sha256:566d02a0b85b994e40b4f6276b3423c59e8157f10b73bd2e634f8e0a3dfb1890 \
--hash=sha256:5ab28a2a7649df3b72e6b674b4c190e448e8e77cf496a65bd846472048de2089 \ --hash=sha256:5768a9e7d393b2edd3a28de5a6d5850d054a016ed711f7044a9072f19f5e50d5 \
--hash=sha256:5c4ab71be17bdca30cb34c34c4e1496e2f5d6f20c199c12bad226070b22ef9bf \ --hash=sha256:581358e770a4536e546841b78fd0fe318added4a82443bf22d0bbe3109cf9582 \
--hash=sha256:612a627d733f695b1de1f9b4bd511c15f999a5d8b915d444bbd7dd71cf3370da \ --hash=sha256:58997db1aa48a1119e26c1c2f893d1c92339bd3be5d1f25334f22eaeaeeca90e \
--hash=sha256:6402a9d8146cf4b3974ded3fd28a971e83dc6a0333eb7822524a3aa20b546578 \ --hash=sha256:58d8f9f80ae79ba7f2a0509424939236220d7d66a4f8256ae999b882cc58065b \
--hash=sha256:6b9016b1714da4dd5ecaaa75b82098aa5a0b87854ce9b092e21c27c4ae23e014 \ --hash=sha256:592fb928efe0674a7400af914bcf931eb5267d36237925947aaecf63bd9a91aa \
--hash=sha256:71e55ccbdfae79a2ed9c6369c3008a3025817ff9d7e27b32a2d84e2a4267e66e \ --hash=sha256:5bc571786a256a2fa2d8f13b5ecf714020b753bc76c2fa6d308e46751946dc31 \
--hash=sha256:7465bfe6087d2d5b42d4c53b9b11ca9f218e477317a4a162a10e3c19e984ba8e \ --hash=sha256:5f6f948ff1cd252003ff534d7b50a2b25453b4212b283a7514ff8751bdb68c37 \
--hash=sha256:75a9067e236f9b9ae3535b66fe99bddb33d39c0de10112e49b9ab11eee53dc31 \ --hash=sha256:5fb27dd9c52ae13cb4de90244207155b694f76a75a816115ead2d573f40e1e36 \
--hash=sha256:773d573e11f437ce0bdb95b7c18dc58390494f96d43f8b45b9760436114f7652 \ --hash=sha256:6688807ed07436c18e9946d01372bc80b9d20b7732cde27de9313e0860910c84 \
--hash=sha256:77df19583501ea288eaf15ac0fe7ad01e6d8091a91d5c41df5c718f307d8e31b \ --hash=sha256:6b9632c42f76d5349e7dd50025cff02688eb760b258e891ad2c6428e7e4917d5 \
--hash=sha256:7f7668f30b9dd5163197e5cbf4e0efd54e00f0a859cc566ce56cfc31f4054839 \ --hash=sha256:720e19ff2d1c425b6be18bd20ba35010c7927e492bcfecbae1085a89caa7db7c \
--hash=sha256:8c0056529e68dbe9184cd4019a1f3d8f3a4ead2f6fc7a5afcf27d3314edd1277 \ --hash=sha256:749d23fbfd642a7abfef5fc0f6ca185fa82a2c0f895e6eab42c3f2a5d88f6011 \
--hash=sha256:94596f9e7633ee3f6440711d43bb70aa31cc0a46a900ab8b4201a366ace5c9e7 \ --hash=sha256:7608c9fa58b85426093ab8777080e8f134d89915c05c51fa270e7aee317f2b38 \
--hash=sha256:ab8cca8ef8fb1ccf5b048ae5bd78ba55b9e4b5d472e3ce5ca39ff4d2a9c249e4 \ --hash=sha256:766089fdaa8af1b5f7e2ec9fd7ad190c865e226b4fb0e7b1bd8dbcd62b5b923e \
--hash=sha256:ad3bc94054876155549fdaedf4a46d1ec69d39a5bcee377148afe498e84c4b8e \ --hash=sha256:7744b4ed1f3b76fe37de7e9ef98014482fe74b6d3dfe1026cc4cfb4b4404e74f \
--hash=sha256:b56b603ebcea8aa10b46228b8410ba7f13e7c2ee54389d4d9be0927fd8ce2a70 \ --hash=sha256:7b3c5474dbad63bcccb8d14d4d4c7c19f1dc6f8e8c1914cbc771d261cf8eddca \
--hash=sha256:b6f5a29e9c775b9f12a1a717aa7a2c80f9e1db6f27ba44a5b59c80ac61d2ffcf \ --hash=sha256:81e57d1f00af9b7414c8d00ac77892b3786ddd69a23c27dee47cae8fd3543b07 \
--hash=sha256:b7bfff1ca23732b488cbca3076fc11bc98d520ee122514fdb17a8e20d3338f5a \ --hash=sha256:82fe30afbdd66fbdad583b02baad5c15930a3dc8a3756d2ae15fc874e9be8ec8 \
--hash=sha256:bdef84570ebbce1d42b4e7ea952d21c414c5f118ad02fee00c5625f35e134429 \ --hash=sha256:8792e502a16a0b28d9fd23571fe492271a00c4b2b55f6c0b8377e47032758cd3 \
--hash=sha256:c37e024c07308cd06cf3ec51bfd0e7f6157585a4d84d1bce4a7f5f7913719bf8 \ --hash=sha256:91268f04380964a5e767f8102d05f1e23312ddbe848de1a9514b08b3fc57d354 \
--hash=sha256:c677c4ad433cb7150c8cd304a0769ae3bcfbe5ea0676eb53faa7b1443b16d0d3 \ --hash=sha256:9b4b0fc4e774063ae64c92cc57e2b10160150de68c96d71743218159d953869d \
--hash=sha256:cf7f73a4a792bc5db58a4b385d8a1467e8d468f7548702fb0ed1e9b7501b1c13 \ --hash=sha256:9bdc762600fcc8e4ad3224734a4e70cc226207fd8f2de47c36b115efeed01782 \
--hash=sha256:cffc3408d77a27973f33e5d909b624cce683db5fc25964b02fe0aae7886c1007 \ --hash=sha256:9ea3ebe1706fd78d6ac0dd1cf692a77cfacd5ba967c82128f9863a5e48f63c47 \
--hash=sha256:d7b4d40c153fa352ab3cca530f3a0baedf7621b2ebcbd7f084009522c21788fc \ --hash=sha256:9f12a34bddaeffa7840a61163595ec0d70a9db855896865dcfbb731510014484 \
--hash=sha256:dbfdb9b6cc79f31104a7b162a2b921b765fcc62af6c00540a167a8de47e4ed38 \ --hash=sha256:a3a59d404e1fb8ec47116f66f5adf48a8993a8aac0dad0395a923155fd55ee38 \
--hash=sha256:df1d567fc430f6df15c9fcf67d87685fc49bdb325adc0db5af1adfb2f44eb5c9 \ --hash=sha256:b051aa1e67f0d03ccdb4503d716f22da56229896526f0aa721e5a199baa9e5d4 \
--hash=sha256:e2631da29253a98bd496e6c4813b24e09a4fe3fb2a9e88513305d6f8747cce95 \ --hash=sha256:b2fa94ce40bc4b408149d83a6204fc5e53c3e9d3cd5b749de2e7e9671a049cf7 \
--hash=sha256:e7510c37550f91a187e3660a8cc50d4b760f8c3b8b2f89ebc5698cd2c7f2c85d \ --hash=sha256:c45f61202e5691090a697e599997eaffa3ec298209743caa4fd346145acabafe \
--hash=sha256:eb05ee1c2b817d27c537333224c9e83c7afb86fe7296ba970990068baf819b16 \ --hash=sha256:c594c199869099c59c85b9f4423370b6212491fb929e7fcda0da1768761a2c2c \
--hash=sha256:eb4eed2079c01a4850bf467deacfab56d356d4225040170af03dc9958321242d \ --hash=sha256:d27f51b8ce291da4af749ef850adb4520bfe52c2ff4677402c719ff35af03f00 \
--hash=sha256:ee17a2cf4943cde261adfad1bbc5bf38d6b3776d7afff74c7cabcbeaeb08c260 \ --hash=sha256:d59db908d9baaa057a43dd5aa8352f3e3de4b8c57f295172d5fe521e97d6c39d \
--hash=sha256:f80e3f2b5331dbbf0901bcb658056c03eeb2c1ef31d774afb0d61598b242e744 \ --hash=sha256:d7e490848d7bedf6c1d2180233a33d31d554a1b0823f80a0236ebb7d3b6caf12 \
--hash=sha256:f9b1c2533af01cd7648378599f82b0b8ae32f293296e6eec5753a625bc97ef28 \ --hash=sha256:e3b6328bc2f3ca233f9a5f08d266089b96a534eca9ee4e45cb92d0a8d4629d9c \
--hash=sha256:fa1cbc10768a796c96d3243656016bf4e337c81c71097270bb7b0ad6210d9765 \ --hash=sha256:e3f5887019dfb094c60e7026968ca3a964ca16305807ba5e43f9a78483767d5f \
--hash=sha256:fbd1d4ed566895ad2d3bf4ddfd8bae90026930ddf29df3b9d91d32c8c47866a7 --hash=sha256:e7575ca710277cc3e9257ff803a3e0e3cb7cc1b7851639cb783a7cd55ebfc815 \
--hash=sha256:e7f4dff472a529c9027f294c8842ab535bbed7e2928fe1f4fc28b27f2463d6d5 \
--hash=sha256:eab6959fade522e586b8ec37d3fe337ce10861965edef3292f52e66e36dc375d \
--hash=sha256:f5e7415b5d0f58edf2708842c66605092df67f3821161d861b09695fc326c4de \
--hash=sha256:f72146ad5b69ea177c2707578e5a4a9422b79e50d5a80992dabc5619b0929771 \
--hash=sha256:fa2aa5094dc962967ca0978c035b3ef90329b802501ef12a088d3bac6a55598e \
--hash=sha256:fe5e3648e855df4fba1d70c18aef18c9880ea8d123fdfae754c18787c8cb37b3 \
--hash=sha256:ff64883cff66fe797cd958c0ff7f53fc36a28239b9e0dc80189ce1c03ce47153
# via psycopg # via psycopg
psycopg-pool==3.3.1 \ psycopg-pool==3.2.6 \
--hash=sha256:2af5b432941c4c9ad5c87b3fa410aec910ec8f7c122855897983a06c45f2e4b5 \ --hash=sha256:0f92a7817719517212fbfe2fd58b8c35c1850cdd2a80d36b581ba2085d9148e5 \
--hash=sha256:b10b10b7a175d5cc1592147dc5b7eec8a9e0834eb3ed2c4a92c858e2f51eb63c --hash=sha256:5887318a9f6af906d041a0b1dc1c60f8f0dda8340c2572b74e10907b51ed5da7
# via psycopg # via psycopg
pyasn1==0.6.3 \ pyasn1==0.6.1 \
--hash=sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf \ --hash=sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629 \
--hash=sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde --hash=sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034
# via # via
# pyasn1-modules # pyasn1-modules
# python-ldap # python-ldap
@ -136,8 +135,8 @@ pyasn1-modules==0.4.2 \
--hash=sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a \ --hash=sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a \
--hash=sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6 --hash=sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6
# via python-ldap # via python-ldap
python-ldap==3.4.7 \ python-ldap==3.4.5 \
--hash=sha256:bacd9fb680d20263d8570ade1cf234d90d281149a8beb4f079dd8f33f7613dc8 --hash=sha256:b2f6ef1c37fe2c6a5a85212efe71311ee21847766a7d45fcb711f3b270a5f79a
# via # via
# -r contrib/container/requirements.in # -r contrib/container/requirements.in
# django-auth-ldap # django-auth-ldap
@ -215,49 +214,43 @@ pyyaml==6.0.3 \
--hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \ --hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \
--hash=sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926 \ --hash=sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926 \
--hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0 --hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0
# via # via -r contrib/container/requirements.in
# -c src/backend/requirements.txt setuptools==80.9.0 \
# -r contrib/container/requirements.in --hash=sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922 \
setuptools==82.0.1 \ --hash=sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c
--hash=sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9 \ # via -r contrib/container/requirements.in
--hash=sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb sqlparse==0.5.3 \
# via --hash=sha256:09f67787f56a0b16ecdbde1bfc7f5d9c3371ca683cfeaa8e6ff60b4807ec9272 \
# -c src/backend/requirements.txt --hash=sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca
# -r contrib/container/requirements.in # via django
sqlparse==0.5.5 \
--hash=sha256:12a08b3bf3eec877c519589833aed092e2444e68240a3577e8e26148acc7b1ba \
--hash=sha256:e20d4a9b0b8585fdf63b10d30066c7c94c5d7a7ec47c889a2d83a3caa93ff28e
# via
# -c src/backend/requirements.txt
# django
typing-extensions==4.15.0 \ typing-extensions==4.15.0 \
--hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \ --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \
--hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548 --hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
# via # via
# -c src/backend/requirements.txt # psycopg
# psycopg-pool # psycopg-pool
uv==0.11.24 \ uv==0.9.7 \
--hash=sha256:047d763d20d71968c00f4afec40b0e75d9da7e3693f725b9f502d84a25256893 \ --hash=sha256:0fdbfad5b367e7a3968264af6da5bbfffd4944a90319042f166e8df1a2d9de09 \
--hash=sha256:0e100b9cbc59beff2730840ac989b1f100cc03c90514e7cab6992a1f3f13784e \ --hash=sha256:134e0daac56f9e399ccdfc9e4635bc0a13c234cad9224994c67bae462e07399a \
--hash=sha256:3176668ea8a2318d775c0d9188661c61ccc36790220724b1d360fcc8945d520e \ --hash=sha256:1aaf79b4234400e9e2fbf5b50b091726ccbb0b6d4d032edd3dfd4c9673d89dca \
--hash=sha256:356435577fae11fafe7a067ee3269cccefd35b031b83a3a36c87fe9d192bffba \ --hash=sha256:34fe0af83fcafb9e2b786f4bd633a06c878d548a7c479594ffb5607db8778471 \
--hash=sha256:38f38c9449aafd71dc0fa35e66a8a547ee48947b2f2f94084893c2afe6058cfa \ --hash=sha256:555ee72146b8782c73d755e4a21c9885c6bfc81db0ffca2220d52dddae007eb7 \
--hash=sha256:438f8291fb9daea30a4bd333299b82e6ef755578302745a021162f328cfcfc68 \ --hash=sha256:56a440ccde7624a7bc070e1c2492b358c67aea9b8f17bc243ea27c5871c8d02c \
--hash=sha256:48a6123f71b801e0e0b8a38520b011632ad81e0a043445044ce5b1a7b1cec7b6 \ --hash=sha256:62b315f62669899076a1953fba6baf50bd2b57f66f656280491331dcedd7e6c6 \
--hash=sha256:6ecdad43e870f88d3772d9d37e877259ae35ec374d51589805cdcf6196205829 \ --hash=sha256:635e82c2d0d8b001618af82e4f2724350f15814f6462a71b3ebd44adec21f03c \
--hash=sha256:79757f90b7765996366b80e77cad13555c7f7e1282ca8d8b686ee21773ab0b77 \ --hash=sha256:7019f4416925f4091b9d28c1cf3e8444cf910c4ede76bdf1f6b9a56ca5f97985 \
--hash=sha256:8346b0086d213b80430f3bb4477379a8a4fa550b03447d23c84eee85c2e52bc4 \ --hash=sha256:777bb1de174319245a35e4f805d3b4484d006ebedae71d3546f95e7c28a5f436 \
--hash=sha256:8602a1b6300a3a948afacc62e1cb933c8394c27966db85ed7e29483300b69dc4 \ --hash=sha256:89697fa0d7384ba047daf75df844ee7800235105e41d08e0c876861a2b4aa90e \
--hash=sha256:9312b6fd44361674e9c847a828ded792493766697816261e05848a024fe34129 \ --hash=sha256:8cf6bc2482d1293cc630f66b862b494c09acda9b7faff7307ef52667a2b3ad49 \
--hash=sha256:bf568c62dddd55ad9c85a16ffdfbcc7746be9c3159ed644e4f9e6f5e44905cbb \ --hash=sha256:b5f1fb8203a77853db176000e8f30d5815ab175dc46199db059f97a72fc51110 \
--hash=sha256:c4ab221c0a949f8006a7582786dae384706b2f82016a0db60baa7cc696042705 \ --hash=sha256:bb8bfcc2897f7653522abc2cae80233af756ad857bfbbbbe176f79460cbba417 \
--hash=sha256:c8ec3caf656645f58b53cb9aee9aa95cfc65c82ba2d7f1362bfd2660d1484307 \ --hash=sha256:bcf878528bd079fe8ae15928b5dfa232fac8b0e1854a2102da6ae1a833c31276 \
--hash=sha256:d6a49543c659c0cf1ff4c944955d97e69dbce4b76e3d284f5a92cea19133ebb6 \ --hash=sha256:c9810ee8173dce129c49b338d5e97f3d7c7e9435f73e0b9b26c2f37743d3bb9e \
--hash=sha256:e499579f557abf17b8ffd1490d3e827748aea096f6eaa66737e729e046449f08 \ --hash=sha256:d13da6521d4e841b1e0a9fda82e793dcf8458a323a9e8955f50903479d0bfa97 \
--hash=sha256:e7e78c18686202c8b8715bebb83bfaf58f82d7fb848b6a5ae4e925a9fac3de4c \ --hash=sha256:d6e5fe28ca05a4b576c0e8da5f69251dc187a67054829cfc4afb2bfa1767114b \
--hash=sha256:ed0c9a9d7909f0e48a9dafe666ca9ebefe2a1534e51ed05c0a7de7406465f868 --hash=sha256:edd768f6730bba06aa10fdbd80ee064569f7236806f636bf65b68136a430aad0
# via -r contrib/container/requirements.in # via -r contrib/container/requirements.in
wheel==0.47.0 \ wheel==0.45.1 \
--hash=sha256:212281cab4dff978f6cedd499cd893e1f620791ca6ff7107cf270781e587eced \ --hash=sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729 \
--hash=sha256:cc72bd1009ba0cf63922e28f94d9d83b920aa2bb28f798a31d0691b02fa3c9b3 --hash=sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248
# via -r contrib/container/requirements.in # via -r contrib/container/requirements.in

View File

@ -1,4 +1,4 @@
# Packages needed for CI/packages # Packages needed for CI/packages
requests==2.34.2 requests==2.32.5
pyyaml==6.0.3 pyyaml==6.0.3
jc jc==1.25.6

View File

@ -1,157 +1,135 @@
# This file was autogenerated by uv via the following command: # This file was autogenerated by uv via the following command:
# uv pip compile contrib/dev_reqs/requirements.in -o contrib/dev_reqs/requirements.txt -c src/backend/requirements.txt # uv pip compile contrib/dev_reqs/requirements.in -o contrib/dev_reqs/requirements.txt --no-strip-extras --generate-hashes -b src/backend/requirements.txt
certifi==2026.6.17 \ certifi==2025.10.5 \
--hash=sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432 \ --hash=sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de \
--hash=sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db --hash=sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43
# via # via requests
# -c src/backend/requirements.txt charset-normalizer==3.4.4 \
# requests --hash=sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad \
charset-normalizer==3.4.7 \ --hash=sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93 \
--hash=sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc \ --hash=sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394 \
--hash=sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c \ --hash=sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89 \
--hash=sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67 \ --hash=sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc \
--hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \ --hash=sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86 \
--hash=sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0 \ --hash=sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63 \
--hash=sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c \ --hash=sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d \
--hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \ --hash=sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f \
--hash=sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444 \ --hash=sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8 \
--hash=sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153 \ --hash=sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0 \
--hash=sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9 \ --hash=sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505 \
--hash=sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01 \ --hash=sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161 \
--hash=sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217 \ --hash=sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af \
--hash=sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b \ --hash=sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152 \
--hash=sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c \ --hash=sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318 \
--hash=sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a \ --hash=sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72 \
--hash=sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83 \ --hash=sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4 \
--hash=sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5 \ --hash=sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e \
--hash=sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7 \ --hash=sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3 \
--hash=sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb \ --hash=sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576 \
--hash=sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c \ --hash=sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c \
--hash=sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1 \ --hash=sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1 \
--hash=sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42 \ --hash=sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8 \
--hash=sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab \ --hash=sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1 \
--hash=sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df \ --hash=sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2 \
--hash=sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e \ --hash=sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44 \
--hash=sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207 \ --hash=sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26 \
--hash=sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18 \ --hash=sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88 \
--hash=sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734 \ --hash=sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016 \
--hash=sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38 \ --hash=sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede \
--hash=sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110 \ --hash=sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf \
--hash=sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18 \ --hash=sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a \
--hash=sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44 \ --hash=sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc \
--hash=sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d \ --hash=sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0 \
--hash=sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48 \ --hash=sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84 \
--hash=sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e \ --hash=sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db \
--hash=sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5 \ --hash=sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1 \
--hash=sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d \ --hash=sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7 \
--hash=sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53 \ --hash=sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed \
--hash=sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790 \ --hash=sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8 \
--hash=sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c \ --hash=sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133 \
--hash=sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b \ --hash=sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e \
--hash=sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116 \ --hash=sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef \
--hash=sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d \ --hash=sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14 \
--hash=sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10 \ --hash=sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2 \
--hash=sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6 \ --hash=sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0 \
--hash=sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2 \ --hash=sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d \
--hash=sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776 \ --hash=sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828 \
--hash=sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a \ --hash=sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f \
--hash=sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265 \ --hash=sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf \
--hash=sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008 \ --hash=sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6 \
--hash=sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943 \ --hash=sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328 \
--hash=sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374 \ --hash=sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090 \
--hash=sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246 \ --hash=sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa \
--hash=sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e \ --hash=sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381 \
--hash=sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5 \ --hash=sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c \
--hash=sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616 \ --hash=sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb \
--hash=sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15 \ --hash=sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc \
--hash=sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41 \ --hash=sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a \
--hash=sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960 \ --hash=sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec \
--hash=sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752 \ --hash=sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc \
--hash=sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e \ --hash=sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac \
--hash=sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72 \ --hash=sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e \
--hash=sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7 \ --hash=sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313 \
--hash=sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8 \ --hash=sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569 \
--hash=sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b \ --hash=sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3 \
--hash=sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4 \ --hash=sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d \
--hash=sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545 \ --hash=sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525 \
--hash=sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706 \ --hash=sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894 \
--hash=sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366 \ --hash=sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3 \
--hash=sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb \ --hash=sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9 \
--hash=sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a \ --hash=sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a \
--hash=sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e \ --hash=sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9 \
--hash=sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00 \ --hash=sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14 \
--hash=sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f \ --hash=sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25 \
--hash=sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a \ --hash=sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50 \
--hash=sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1 \ --hash=sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf \
--hash=sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66 \ --hash=sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1 \
--hash=sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356 \ --hash=sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3 \
--hash=sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319 \ --hash=sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac \
--hash=sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4 \ --hash=sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e \
--hash=sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad \ --hash=sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815 \
--hash=sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d \ --hash=sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c \
--hash=sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5 \ --hash=sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6 \
--hash=sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7 \ --hash=sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6 \
--hash=sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0 \ --hash=sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e \
--hash=sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686 \ --hash=sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4 \
--hash=sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34 \ --hash=sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84 \
--hash=sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49 \ --hash=sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69 \
--hash=sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c \ --hash=sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15 \
--hash=sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1 \ --hash=sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191 \
--hash=sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e \ --hash=sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0 \
--hash=sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60 \ --hash=sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897 \
--hash=sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0 \ --hash=sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd \
--hash=sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274 \ --hash=sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2 \
--hash=sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d \ --hash=sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794 \
--hash=sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0 \ --hash=sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d \
--hash=sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae \ --hash=sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074 \
--hash=sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f \ --hash=sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3 \
--hash=sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d \ --hash=sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224 \
--hash=sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe \ --hash=sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838 \
--hash=sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3 \ --hash=sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a \
--hash=sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393 \ --hash=sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d \
--hash=sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1 \ --hash=sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d \
--hash=sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af \ --hash=sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f \
--hash=sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44 \ --hash=sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8 \
--hash=sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00 \ --hash=sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490 \
--hash=sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c \ --hash=sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966 \
--hash=sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3 \ --hash=sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9 \
--hash=sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7 \ --hash=sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3 \
--hash=sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd \ --hash=sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e \
--hash=sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e \ --hash=sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608
--hash=sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b \ # via requests
--hash=sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8 \ idna==3.11 \
--hash=sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259 \ --hash=sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea \
--hash=sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859 \ --hash=sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902
--hash=sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46 \ # via requests
--hash=sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30 \ jc==1.25.6 \
--hash=sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b \ --hash=sha256:27f58befc7ae0a4c63322926c5f1ec892e3eac4a065eff3b07cfe420a6924a07 \
--hash=sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46 \ --hash=sha256:7367b59e6e0da8babeede1e5b0da083f3c5aa6b6e585b4aed28dd7c4b2d76162
--hash=sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24 \
--hash=sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a \
--hash=sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24 \
--hash=sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc \
--hash=sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215 \
--hash=sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063 \
--hash=sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832 \
--hash=sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6 \
--hash=sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79 \
--hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464
# via
# -c src/backend/requirements.txt
# requests
idna==3.18 \
--hash=sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2 \
--hash=sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848
# via
# -c src/backend/requirements.txt
# requests
jc==1.25.7 \
--hash=sha256:5ed6a0da915c931c04693cab806d5c31d9ef14ca998c6c32308460d37cb30baf \
--hash=sha256:63481e34d92715781e1b094eca7d76d122a14489463d45b7f3e8180f44ea3a10
# via -r contrib/dev_reqs/requirements.in # via -r contrib/dev_reqs/requirements.in
pygments==2.20.0 \ pygments==2.19.2 \
--hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \ --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \
--hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b
# via jc # via jc
pyyaml==6.0.3 \ pyyaml==6.0.3 \
--hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \ --hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \
@ -227,26 +205,77 @@ pyyaml==6.0.3 \
--hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \ --hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \
--hash=sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926 \ --hash=sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926 \
--hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0 --hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0
# via # via -r contrib/dev_reqs/requirements.in
# -c src/backend/requirements.txt requests==2.32.5 \
# -r contrib/dev_reqs/requirements.in --hash=sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 \
requests==2.34.2 \ --hash=sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf
--hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \ # via -r contrib/dev_reqs/requirements.in
--hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed ruamel-yaml==0.18.15 \
# via --hash=sha256:148f6488d698b7a5eded5ea793a025308b25eca97208181b6a026037f391f701 \
# -c src/backend/requirements.txt --hash=sha256:dbfca74b018c4c3fba0b9cc9ee33e53c371194a9000e694995e620490fd40700
# -r contrib/dev_reqs/requirements.in
ruamel-yaml==0.19.1 \
--hash=sha256:27592957fedf6e0b62f281e96effd28043345e0e66001f97683aa9a40c667c93 \
--hash=sha256:53eb66cd27849eff968ebf8f0bf61f46cdac2da1d1f3576dd4ccee9b25c31993
# via jc # via jc
urllib3==2.7.0 \ ruamel-yaml-clib==0.2.14 \
--hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \ --hash=sha256:090782b5fb9d98df96509eecdbcaffd037d47389a89492320280d52f91330d78 \
--hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897 --hash=sha256:0a54e5e40a7a691a426c2703b09b0d61a14294d25cfacc00631aa6f9c964df0d \
# via --hash=sha256:10d9595b6a19778f3269399eff6bab642608e5966183abc2adbe558a42d4efc9 \
# -c src/backend/requirements.txt --hash=sha256:16a60d69f4057ad9a92f3444e2367c08490daed6428291aa16cefb445c29b0e9 \
# requests --hash=sha256:18c041b28f3456ddef1f1951d4492dbebe0f8114157c1b3c981a4611c2020792 \
xmltodict==1.0.4 \ --hash=sha256:1c1acc3a0209ea9042cc3cfc0790edd2eddd431a2ec3f8283d081e4d5018571e \
--hash=sha256:6d94c9f834dd9e44514162799d344d815a3a4faec913717a9ecbfa5be1bb8e61 \ --hash=sha256:1f118b707eece8cf84ecbc3e3ec94d9db879d85ed608f95870d39b2d2efa5dca \
--hash=sha256:a4a00d300b0e1c59fc2bfccb53d7b2e88c32f200df138a0dd2229f842497026a --hash=sha256:2070bf0ad1540d5c77a664de07ebcc45eebd1ddcab71a7a06f26936920692beb \
--hash=sha256:26a8de280ab0d22b6e3ec745b4a5a07151a0f74aad92dd76ab9c8d8d7087720d \
--hash=sha256:275f938692013a3883edbd848edde6d9f26825d65c9a2eb1db8baa1adc96a05d \
--hash=sha256:27c070cf3888e90d992be75dd47292ff9aa17dafd36492812a6a304a1aedc182 \
--hash=sha256:29757bdb7c142f9595cc1b62ec49a3d1c83fab9cef92db52b0ccebaad4eafb98 \
--hash=sha256:4ccba93c1e5a40af45b2f08e4591969fa4697eae951c708f3f83dcbf9f6c6bb1 \
--hash=sha256:4f4a150a737fccae13fb51234d41304ff2222e3b7d4c8e9428ed1a6ab48389b8 \
--hash=sha256:557df28dbccf79b152fe2d1b935f6063d9cc431199ea2b0e84892f35c03bb0ee \
--hash=sha256:5ac5ff9425d8acb8f59ac5b96bcb7fd3d272dc92d96a7c730025928ffcc88a7a \
--hash=sha256:5bae1a073ca4244620425cd3d3aa9746bde590992b98ee8c7c8be8c597ca0d4e \
--hash=sha256:5e56ac47260c0eed992789fa0b8efe43404a9adb608608631a948cee4fc2b052 \
--hash=sha256:6aeadc170090ff1889f0d2c3057557f9cd71f975f17535c26a5d37af98f19c27 \
--hash=sha256:6d5472f63a31b042aadf5ed28dd3ef0523da49ac17f0463e10fda9c4a2773352 \
--hash=sha256:70eda7703b8126f5e52fcf276e6c0f40b0d314674f896fc58c47b0aef2b9ae83 \
--hash=sha256:7df6f6e9d0e33c7b1d435defb185095386c469109de723d514142632a7b9d07f \
--hash=sha256:7e4f9da7e7549946e02a6122dcad00b7c1168513acb1f8a726b1aaf504a99d32 \
--hash=sha256:803f5044b13602d58ea378576dd75aa759f52116a0232608e8fdada4da33752e \
--hash=sha256:808c7190a0fe7ae7014c42f73897cf8e9ef14ff3aa533450e51b1e72ec5239ad \
--hash=sha256:81f6d3b19bc703679a5705c6a16dabdc79823c71d791d73c65949be7f3012c02 \
--hash=sha256:83bbd8354f6abb3fdfb922d1ed47ad8d1db3ea72b0523dac8d07cdacfe1c0fcf \
--hash=sha256:8dd3c2cc49caa7a8d64b67146462aed6723a0495e44bf0aa0a2e94beaa8432f6 \
--hash=sha256:915748cfc25b8cfd81b14d00f4bfdb2ab227a30d6d43459034533f4d1c207a2a \
--hash=sha256:94f3efb718f8f49b031f2071ec7a27dd20cbfe511b4dfd54ecee54c956da2b31 \
--hash=sha256:9bd8fe07f49c170e09d76773fb86ad9135e0beee44f36e1576a201b0676d3d1d \
--hash=sha256:9bf6b699223afe6c7fe9f2ef76e0bfa6dd892c21e94ce8c957478987ade76cd8 \
--hash=sha256:a05ba88adf3d7189a974b2de7a9d56731548d35dc0a822ec3dc669caa7019b29 \
--hash=sha256:a0ac90efbc7a77b0d796c03c8cc4e62fd710b3f1e4c32947713ef2ef52e09543 \
--hash=sha256:a0cb71ccc6ef9ce36eecb6272c81afdc2f565950cdcec33ae8e6cd8f7fc86f27 \
--hash=sha256:a37f40a859b503304dd740686359fcf541d6fb3ff7fc10f539af7f7150917c68 \
--hash=sha256:a911aa73588d9a8b08d662b9484bc0567949529824a55d3885b77e8dd62a127a \
--hash=sha256:aef953f3b8bd0b50bd52a2e52fb54a6a2171a1889d8dea4a5959d46c6624c451 \
--hash=sha256:b28caeaf3e670c08cb7e8de221266df8494c169bd6ed8875493fab45be9607a4 \
--hash=sha256:b30110b29484adc597df6bd92a37b90e63a8c152ca8136aad100a02f8ba6d1b6 \
--hash=sha256:b5b0f7e294700b615a3bcf6d28b26e6da94e8eba63b079f4ec92e9ba6c0d6b54 \
--hash=sha256:c099cafc1834d3c5dac305865d04235f7c21c167c8dd31ebc3d6bbc357e2f023 \
--hash=sha256:d73a0187718f6eec5b2f729b0f98e4603f7bd9c48aa65d01227d1a5dcdfbe9e8 \
--hash=sha256:d8354515ab62f95a07deaf7f845886cc50e2f345ceab240a3d2d09a9f7d77853 \
--hash=sha256:dba72975485f2b87b786075e18a6e5d07dc2b4d8973beb2732b9b2816f1bad70 \
--hash=sha256:dd7546c851e59c06197a7c651335755e74aa383a835878ca86d2c650c07a2f85 \
--hash=sha256:df3ec9959241d07bc261f4983d25a1205ff37703faf42b474f15d54d88b4f8c9 \
--hash=sha256:e1d1735d97fd8a48473af048739379975651fab186f8a25a9f683534e6904179 \
--hash=sha256:e501c096aa3889133d674605ebd018471bc404a59cbc17da3c5924421c54d97c \
--hash=sha256:e7cb9ad1d525d40f7d87b6df7c0ff916a66bc52cb61b66ac1b2a16d0c1b07640 \
--hash=sha256:f4e97a1cf0b7a30af9e1d9dad10a5671157b9acee790d9e26996391f49b965a2 \
--hash=sha256:f8b2acb0ffdd2ce8208accbec2dca4a06937d556fdcaefd6473ba1b5daa7e3c4 \
--hash=sha256:fb04c5650de6668b853623eceadcdb1a9f2fee381f5d7b6bc842ee7c239eeec4 \
--hash=sha256:fbc08c02e9b147a11dfcaa1ac8a83168b699863493e183f7c0c8b12850b7d259 \
--hash=sha256:ff86876889ea478b1381089e55cf9e345707b312beda4986f823e1d95e8c0f59
# via ruamel-yaml
urllib3==2.5.0 \
--hash=sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760 \
--hash=sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc
# via requests
xmltodict==1.0.2 \
--hash=sha256:54306780b7c2175a3967cad1db92f218207e5bc1aba697d887807c0fb68b7649 \
--hash=sha256:62d0fddb0dcbc9f642745d8bbf4d81fd17d6dfaec5a15b5c1876300aad92af0d
# via jc # via jc

View File

@ -15,7 +15,7 @@ root_command() {
no_call=${args[--no-call]} no_call=${args[--no-call]}
dry_run=${args[--dry-run]} dry_run=${args[--dry-run]}
REQS="wget apt-transport-https curl gpg" REQS="wget apt-transport-https"
function do_call() { function do_call() {
if [[ $dry_run ]]; then if [[ $dry_run ]]; then

View File

@ -5,7 +5,7 @@ publisher=${args[publisher]}
no_call=${args[--no-call]} no_call=${args[--no-call]}
dry_run=${args[--dry-run]} dry_run=${args[--dry-run]}
REQS="wget apt-transport-https curl gpg" REQS="wget apt-transport-https"
function do_call() { function do_call() {
if [[ $dry_run ]]; then if [[ $dry_run ]]; then

View File

@ -4,8 +4,8 @@
# #
Color_Off='\033[0m' Color_Off='\033[0m'
On_Red='\033[41m' On_Red='\033[41m'
PYTHON_FROM=11 PYTHON_FROM=9
PYTHON_TO=15 PYTHON_TO=14
function detect_docker() { function detect_docker() {
if [ -n "$(grep docker </proc/1/cgroup)" ]; then if [ -n "$(grep docker </proc/1/cgroup)" ]; then
@ -61,7 +61,7 @@ function detect_python() {
echo "# POI07| No python environment found - using environment variable: ${SETUP_PYTHON}" echo "# POI07| No python environment found - using environment variable: ${SETUP_PYTHON}"
fi fi
# Try to detect a python between lowest and highest supported in reverse order # Try to detect a python between 3.9 and 3.12 in reverse order
if [ -z "$(which ${SETUP_PYTHON})" ]; then if [ -z "$(which ${SETUP_PYTHON})" ]; then
echo "# POI07| Trying to detecting python3.${PYTHON_FROM} to python3.${PYTHON_TO} - using newest version" echo "# POI07| Trying to detecting python3.${PYTHON_FROM} to python3.${PYTHON_TO} - using newest version"
for i in $(seq $PYTHON_TO -1 $PYTHON_FROM); do for i in $(seq $PYTHON_TO -1 $PYTHON_FROM); do
@ -79,7 +79,7 @@ function detect_python() {
echo "${On_Red}" echo "${On_Red}"
echo "# POI07| Python ${SETUP_PYTHON} not found - aborting!" echo "# POI07| Python ${SETUP_PYTHON} not found - aborting!"
echo "# POI07| Please ensure python can be executed with the command '$SETUP_PYTHON' by the current user '$USER'." echo "# POI07| Please ensure python can be executed with the command '$SETUP_PYTHON' by the current user '$USER'."
echo "# POI07| If you are using a different python version, please set the environment variable SETUP_PYTHON to the correct command - eg. 'python3.12'." echo "# POI07| If you are using a different python version, please set the environment variable SETUP_PYTHON to the correct command - eg. 'python3.10'."
echo "${Color_Off}" echo "${Color_Off}"
exit 1 exit 1
fi fi

View File

@ -26,7 +26,7 @@ export DATA_DIR=${APP_HOME}/data
export SETUP_NGINX_FILE=${SETUP_NGINX_FILE:-/etc/nginx/sites-enabled/inventree.conf} export SETUP_NGINX_FILE=${SETUP_NGINX_FILE:-/etc/nginx/sites-enabled/inventree.conf}
export SETUP_ADMIN_PASSWORD_FILE=${CONF_DIR}/admin_password.txt export SETUP_ADMIN_PASSWORD_FILE=${CONF_DIR}/admin_password.txt
export SETUP_NO_CALLS=${SETUP_NO_CALLS:-false} export SETUP_NO_CALLS=${SETUP_NO_CALLS:-false}
export SETUP_PYTHON=${SETUP_PYTHON:-python3.12} export SETUP_PYTHON=${SETUP_PYTHON:-python3.9}
export SETUP_ADMIN_NOCREATION=${SETUP_ADMIN_NOCREATION:-false} export SETUP_ADMIN_NOCREATION=${SETUP_ADMIN_NOCREATION:-false}
# SETUP_DEBUG can be set to get debug info # SETUP_DEBUG can be set to get debug info
# SETUP_EXTRA_PIP can be set to install extra pip packages # SETUP_EXTRA_PIP can be set to install extra pip packages

View File

@ -4,92 +4,32 @@
This repository hosts the [official documentation](https://inventree.readthedocs.io/) for [InvenTree](https://github.com/inventree/inventree), an open source inventory management system. This repository hosts the [official documentation](https://inventree.readthedocs.io/) for [InvenTree](https://github.com/inventree/inventree), an open source inventory management system.
## Prerequisites To serve this documentation locally (e.g. for development), you will need to have Python 3 installed on your system.
InvenTree uses [MkDocs](https://www.mkdocs.org/) to convert [Markdown](https://www.mkdocs.org/user-guide/writing-your-docs/#writing-with-markdown) format `.md` files into HTML suitable for viewing in a web browser. ## Setup
!!! info "Prerequisites" Run the following commands from the top-level project directory:
To build and serve this documentation locally (e.g. for development), you will need:
* Python 3 installed on your system.
* An existing InvenTree installation containing the virtual environment that was created during installation.
These instructions assume you followed the [InvenTree bare metal installation instructions](./docs/start/install.md), so you'll have an `inventree` user, a home directory at `/home/inventree`, the InvenTree source code cloned from [GitHub](https://github.com/inventree/inventree) into `/home/inventree/src`, and a virtual environment at `/home/inventree/env`. If you installed InvenTree some other way, this might vary, and you'll have to adjust these instructions accordingly.
!!! warning "Your InvenTree install will be updated!"
Some of the commands that follow will make changes to your install, for example, by running any pending database migrations. There's a small risk this may cause issues with your existing installation. If you can't risk this, consider setting up a separate InvenTree installation specifically for documentation development.
## Building the documentation locally
To build the documentation locally, run these commands as the `inventree` user:
``` ```
$ cd /home/inventree $ git clone https://github.com/inventree/inventree
$ source env/bin/activate
```
!!! info "(env) prefix"
The shell prompt should now display the `(env)` prefix, showing that you are operating within the context of the python virtual environment
You can now install the additional packages needed by mkdocs:
```
$ cd src
$ pip install --require-hashes -r docs/requirements.txt $ pip install --require-hashes -r docs/requirements.txt
``` ```
## Schema generation ## Serve Locally
Building the documentation requires extracting the API schema from the source code. To serve the pages locally, run the following command (from the top-level project directory):
!!! tip
This command is only required when building the documentation for the first time, or when changes have been made to the API schema.
``` ```
$ invoke build-docs $ mkdocs serve -f docs/mkdocs.yml -a localhost:8080
``` ```
You will see output similar to this (truncated for brevity): ## Edit Documentation Files
```
Running InvenTree database migrations...
Exporting definitions...
Exporting settings definition to '/home/inventree/src/docs/generated/inventree_settings.json'...
Exported InvenTree settings definitions to '/home/inventree/src/docs/generated/inventree_settings.json'
Exported InvenTree tag definitions to '/home/inventree/src/docs/generated/inventree_tags.yml'
Exported InvenTree filter definitions to '/home/inventree/src/docs/generated/inventree_filters.yml'
Exported InvenTree report context definitions to '/home/inventree/src/docs/generated/inventree_report_context.json'
Exporting definitions complete
Exporting schema file to '/home/inventree/src/docs/generated/schema.yml'
Schema export completed: /home/inventree/src/docs/generated/schema.yml Once the server is running, it will monitor the documentation files for any changes, and update the served pages.
Documentation build complete, but mkdocs not requested
```
## Viewing the documentation
Generate the HTML files from the markdown source files, and start the MkDocs webpage server:
```
$ mkdocs serve -f docs/mkdocs.yml
```
You can then point your web browser at http://localhost:8080/
Alternatively, you can use the `invoke` command:
```
$ invoke dev.docs-server
```
If you need to, use the `-a` option after `mkdocs` or `invoke` to set the address and port. Run `invoke dev.docs-server --help` for details.
## Editing the Documentation Files
Once the server is running, it will monitor the documentation files for changes, and regenerate the HTML pages as required. Refresh your web browser to see the changes.
### Admonitions ### Admonitions
"Admonition" blocks can be added to the documentation source as follows: "Admonition" blocks can be added as follow:
``` ```
!!! info "This is the admonition block title" !!! info "This is the admonition block title"
This is the admonition block content This is the admonition block content

View File

@ -54,7 +54,7 @@ Each user is assigned an authentication token which can be used to access the AP
If a user does not know their access token, it can be requested via the API interface itself, using a basic authentication request. If a user does not know their access token, it can be requested via the API interface itself, using a basic authentication request.
To obtain a valid token, perform a GET request to `/api/user/me/token/`. No data are required, but a valid username / password combination must be supplied in the authentication headers. To obtain a valid token, perform a GET request to `/api/user/token/`. No data are required, but a valid username / password combination must be supplied in the authentication headers.
!!! info "Credentials" !!! info "Credentials"
Ensure that a valid username:password combination are supplied as basic authorization headers. Ensure that a valid username:password combination are supplied as basic authorization headers.
@ -106,7 +106,7 @@ response = request.get('http://localhost:8080/api/part/', data=data, headers=hea
InvenTree has built-in support for using [oAuth2](https://oauth.net/2/) and OpenID Connect (OIDC) for authentication to the API. This enables using the instance as a very limited identity provider. InvenTree has built-in support for using [oAuth2](https://oauth.net/2/) and OpenID Connect (OIDC) for authentication to the API. This enables using the instance as a very limited identity provider.
A default application using a public client with PKCE enabled ships with each instance. Intended to be used with the python api and configured with very wide scopes this can also be used for quick tests - the client_id is `zDFnsiRheJIOKNx6aCQ0quBxECg1QBHtVFDPloJ6`. A default application using a public client with PKCE enabled ships with each instance. Intended to be used with the python api and configured with very wide scopes this can also be used for quick tests - the cliend_id is `zDFnsiRheJIOKNx6aCQ0quBxECg1QBHtVFDPloJ6`.
#### Managing applications #### Managing applications
@ -146,7 +146,7 @@ r:delete:stock
Users can only perform REST API actions which align with their assigned [role permissions](../settings/permissions.md#roles). Users can only perform REST API actions which align with their assigned [role permissions](../settings/permissions.md#roles).
Once a user has *authenticated* via the API, a list of the available roles can be retrieved from: Once a user has *authenticated* via the API, a list of the available roles can be retrieved from:
`/api/user/me/roles/` `/api/user/roles/`
For example, when accessing the API from a *superuser* account: For example, when accessing the API from a *superuser* account:

View File

@ -67,7 +67,7 @@ print("Minimum stock:", part.minimum_stock)
### Adding Parameters ### Adding Parameters
Each [part](../../part/index.md) can have multiple [parameters](../../concepts/parameters.md). For the example of the sofa (above) *length* and *weight* make sense. Each parameter has a parameter template that combines the parameter name with a unit. So we first have to create the parameter templates and afterwards add the parameter values to the sofa. Each [part](../../part/index.md) can have multiple [parameters](../../part/parameter.md). For the example of the sofa (above) *length* and *weight* make sense. Each parameter has a parameter template that combines the parameter name with a unit. So we first have to create the parameter templates and afterwards add the parameter values to the sofa.
```python ```python
from inventree.part import Parameter from inventree.part import Parameter

View File

@ -7,7 +7,7 @@ The API schema as documented below is generated using the [drf-spectactular](htt
## API Version ## API Version
This documentation is for API version: `459` This documentation is for API version: `352`
!!! tip "API Schema History" !!! tip "API Schema History"
We track API schema changes, and provide a snapshot of each API schema version in the [API schema repository](https://github.com/inventree/schema/). We track API schema changes, and provide a snapshot of each API schema version in the [API schema repository](https://github.com/inventree/schema/).

View File

@ -67,15 +67,13 @@ Transfer the currently selected stock location into another location. Scanning a
Receive incoming purchase order items into the selected location. Scanning a *new* barcode which is associated with an item in an incoming purchase order will receive the item into the selected location. Receive incoming purchase order items into the selected location. Scanning a *new* barcode which is associated with an item in an incoming purchase order will receive the item into the selected location.
*Note: Both purchase order number and supplier SKU's are required to be found on the barcode for this function to find the associated line item. Missing one will lead to an error.*
#### Scan Items Into Location #### Scan Items Into Location
the *Scan Items Into Location* action allows you to scan items into the selected location. Scanning a valid barcode associated with a stock item (already in the database) will result in that item being transferred to the selected location. the *Scan Items Into Location* action allows you to scan items into the selected location. Scanning a valid barcode associated with a stock item (already in the database) will result in that item being transferred to the selected location.
### Stock Item Actions ### Stock Item Actions
From the [Stock Item detail page](./stock.md#details-tab), the following barcode actions may be available: From the [Stock Item detail page](./stock.md#stock-item-detail-view), the following barcode actions may be available:
{{ image("app/barcode_stock_item_actions.png", "Stock item barcode actions") }} {{ image("app/barcode_stock_item_actions.png", "Stock item barcode actions") }}
@ -107,8 +105,6 @@ From the [Purchase Order detail page](./po.md#purchase-order-detail) page, the f
Receive incoming purchase order items against the selected purchase order. Scanning a *new* barcode which is associated with an item in an incoming purchase order will receive the item into stock. Receive incoming purchase order items against the selected purchase order. Scanning a *new* barcode which is associated with an item in an incoming purchase order will receive the item into stock.
*Note: supplier SKU's are required to be found on the barcode for this function to find the associated line item.*
### Sales Order Actions ### Sales Order Actions
The following barcode actions are available for [Sales Orders](./so.md): The following barcode actions are available for [Sales Orders](./so.md):

View File

@ -1,35 +0,0 @@
---
title: Build Orders
---
## Build Order List
The build order list display lists all build orders:
{{ image("app/build_list.png", "Build order list") }}
Select an individual build order to display the detail view for that order.
### Filtering
Displayed build orders can be subsequently filtered using the search input at the top of the screen
## Build Order Detail
{{ image("app/build_detail.png", "Build order detail") }}
### Edit Build Order Details
From the detail view, select the *Edit* button in the top-right of the screen. This opens the build order editing display.
### Required Parts Tab
The *Required Parts* tab shows the parts required to complete this build order:
{{ image("app/build_required_parts.png", "Build order required parts") }}
### Build Outputs Tab
The *Build Outputs* tab shows the stock items which have been produced as part of this build order:
{{ image("app/build_outputs.png", "Build order outputs") }}

View File

@ -28,9 +28,6 @@ The InvenTree app can be downloaded from either the Android or Apple app stores,
<span class='fab fa-android'></span> [Android Play Store](https://play.google.com/store/apps/details?id=inventree.inventree_app). <span class='fab fa-android'></span> [Android Play Store](https://play.google.com/store/apps/details?id=inventree.inventree_app).
!!! info "APK Download"
As an alternative to using the Android Play Store, the InvenTree app APK file can be downloaded directly via our [polar.sh](https://polar.sh/inventree/products/299bf0d5-af88-4e0f-becf-c007ad37ecf2) page.
### iOS ### iOS
<span class='fab fa-apple'></span> [Apple App Store](https://apps.apple.com/au/app/inventree/id1581731101#?platform=iphone) <span class='fab fa-apple'></span> [Apple App Store](https://apps.apple.com/au/app/inventree/id1581731101#?platform=iphone)

View File

@ -30,7 +30,7 @@ The *Line Items* tab shows the line items associated with this purchase order:
{{ image("app/po_lines.png", "Purchase order line items") }} {{ image("app/po_lines.png", "Purchase order line items") }}
Select a particular line item to view the details for that line, and receive the line item into stock. Long press on a particular line item to receive the item into stock.
### Stock Items ### Stock Items

View File

@ -77,7 +77,7 @@ The *Part Settings* view allows you to configure various options governing what
| Option | Description | | Option | Description |
| --- | --- | | --- | --- |
| Parameters | Enable display of parameters in the part detail view | | Parameters | Enable display of part parameters in the part detail view |
| BOM | Enable bill of materials display in the part detail view | | BOM | Enable bill of materials display in the part detail view |
| Stock History | Enable display of stock history in the stock detail view | | Stock History | Enable display of stock history in the stock detail view |
| Test Results | Enable display of test results in the stock detail view | | Test Results | Enable display of test results in the stock detail view |

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 266 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Some files were not shown because too many files have changed in this diff Show More