mirror of
https://github.com/inventree/InvenTree.git
synced 2025-12-17 12:25:04 -06:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b807e47619 | ||
|
|
40e9b33da6 | ||
|
|
72dceb28be | ||
|
|
1a01e8abee | ||
|
|
df0bb34620 | ||
|
|
75a397aab8 | ||
|
|
f4fd84f50f |
18
.github/workflows/docker.yaml
vendored
18
.github/workflows/docker.yaml
vendored
@@ -74,6 +74,14 @@ jobs:
|
||||
python3 ci/version_check.py
|
||||
echo "git_commit_hash=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
|
||||
echo "git_commit_date=$(git show -s --format=%ci)" >> $GITHUB_ENV
|
||||
- name: Test Docker Image
|
||||
id: test-docker
|
||||
run: |
|
||||
docker build . --target production --tag inventree-test
|
||||
docker run --rm inventree-test invoke --version
|
||||
docker run --rm inventree-test invoke --list
|
||||
docker run --rm inventree-test gunicorn --version
|
||||
docker run --rm inventree-test pg_dump --version
|
||||
- name: Build Docker Image
|
||||
# Build the development docker image (using docker-compose.yml)
|
||||
run: docker-compose build --no-cache
|
||||
@@ -137,8 +145,8 @@ jobs:
|
||||
inventree/inventree
|
||||
ghcr.io/inventree/inventree
|
||||
|
||||
- name: Build and Push
|
||||
id: build-and-push
|
||||
- name: Push Docker Images
|
||||
id: push-docker
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # pin@v5.0.0
|
||||
with:
|
||||
@@ -152,9 +160,3 @@ jobs:
|
||||
build-args: |
|
||||
commit_hash=${{ env.git_commit_hash }}
|
||||
commit_date=${{ env.git_commit_date }}
|
||||
|
||||
- name: Sign the published image
|
||||
if: ${{ false }} # github.event_name != 'pull_request'
|
||||
env:
|
||||
COSIGN_EXPERIMENTAL: "true"
|
||||
run: cosign sign ${{ steps.meta.outputs.tags }}@${{ steps.build-and-push.outputs.digest }}
|
||||
|
||||
11
Dockerfile
11
Dockerfile
@@ -48,8 +48,6 @@ ENV INVENTREE_BACKGROUND_WORKERS="4"
|
||||
ENV INVENTREE_WEB_ADDR=0.0.0.0
|
||||
ENV INVENTREE_WEB_PORT=8000
|
||||
|
||||
ENV VIRTUAL_ENV=/usr/local
|
||||
|
||||
LABEL org.label-schema.schema-version="1.0" \
|
||||
org.label-schema.build-date=${DATE} \
|
||||
org.label-schema.vendor="inventree" \
|
||||
@@ -65,8 +63,11 @@ RUN apk add --no-cache \
|
||||
libjpeg libwebp zlib \
|
||||
# Weasyprint requirements : https://doc.courtbouillon.org/weasyprint/stable/first_steps.html#alpine-3-12
|
||||
py3-pip py3-pillow py3-cffi py3-brotli pango poppler-utils openldap \
|
||||
# Core database packages
|
||||
postgresql13-client && \
|
||||
# Postgres client
|
||||
postgresql13-client \
|
||||
# MySQL / MariaDB client
|
||||
mariadb-client mariadb-connector-c \
|
||||
&& \
|
||||
# fonts
|
||||
apk --update --upgrade --no-cache add fontconfig ttf-freefont font-noto terminus-font && fc-cache -f
|
||||
|
||||
@@ -96,7 +97,7 @@ FROM inventree_base as prebuild
|
||||
|
||||
ENV PATH=/root/.local/bin:$PATH
|
||||
RUN ./install_build_packages.sh --no-cache --virtual .build-deps && \
|
||||
pip install --user uv --no-cache-dir && pip install -r base_requirements.txt -r requirements.txt --no-cache && \
|
||||
pip install --user -r base_requirements.txt -r requirements.txt --no-cache && \
|
||||
apk --purge del .build-deps
|
||||
|
||||
# Frontend builder image:
|
||||
|
||||
@@ -87,11 +87,24 @@ def generateTestKey(test_name: str) -> str:
|
||||
key = test_name.strip().lower()
|
||||
key = key.replace(' ', '')
|
||||
|
||||
# Remove any characters that cannot be used to represent a variable
|
||||
key = re.sub(r'[^a-zA-Z0-9_]', '', key)
|
||||
def valid_char(char: str):
|
||||
"""Determine if a particular character is valid for use in a test key."""
|
||||
if not char.isprintable():
|
||||
return False
|
||||
|
||||
# If the key starts with a digit, prefix with an underscore
|
||||
if key[0].isdigit():
|
||||
if char.isidentifier():
|
||||
return True
|
||||
|
||||
if char.isalnum():
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
# Remove any characters that cannot be used to represent a variable
|
||||
key = ''.join([c for c in key if valid_char(c)])
|
||||
|
||||
# If the key starts with a non-identifier character, prefix with an underscore
|
||||
if len(key) > 0 and not key[0].isidentifier():
|
||||
key = '_' + key
|
||||
|
||||
return key
|
||||
|
||||
@@ -294,7 +294,10 @@ if LDAP_AUTH:
|
||||
|
||||
# get global options from dict and use ldap.OPT_* as keys and values
|
||||
global_options_dict = get_setting(
|
||||
'INVENTREE_LDAP_GLOBAL_OPTIONS', 'ldap.global_options', {}, dict
|
||||
'INVENTREE_LDAP_GLOBAL_OPTIONS',
|
||||
'ldap.global_options',
|
||||
default_value=None,
|
||||
typecast=dict,
|
||||
)
|
||||
global_options = {}
|
||||
for k, v in global_options_dict.items():
|
||||
@@ -364,7 +367,10 @@ if LDAP_AUTH:
|
||||
)
|
||||
AUTH_LDAP_DENY_GROUP = get_setting('INVENTREE_LDAP_DENY_GROUP', 'ldap.deny_group')
|
||||
AUTH_LDAP_USER_FLAGS_BY_GROUP = get_setting(
|
||||
'INVENTREE_LDAP_USER_FLAGS_BY_GROUP', 'ldap.user_flags_by_group', {}, dict
|
||||
'INVENTREE_LDAP_USER_FLAGS_BY_GROUP',
|
||||
'ldap.user_flags_by_group',
|
||||
default_value=None,
|
||||
typecast=dict,
|
||||
)
|
||||
AUTH_LDAP_FIND_GROUP_PERMS = True
|
||||
|
||||
@@ -482,7 +488,7 @@ Configure the database backend based on the user-specified values.
|
||||
logger.debug('Configuring database backend:')
|
||||
|
||||
# Extract database configuration from the config.yaml file
|
||||
db_config = CONFIG.get('database', {})
|
||||
db_config = CONFIG.get('database', None)
|
||||
|
||||
if not db_config:
|
||||
db_config = {}
|
||||
@@ -558,7 +564,10 @@ Ref: https://docs.djangoproject.com/en/3.2/ref/settings/#std:setting-OPTIONS
|
||||
# connecting to the database server (such as a replica failover) don't sit and
|
||||
# wait for possibly an hour or more, just tell the client something went wrong
|
||||
# and let the client retry when they want to.
|
||||
db_options = db_config.get('OPTIONS', db_config.get('options', {}))
|
||||
db_options = db_config.get('OPTIONS', db_config.get('options', None))
|
||||
|
||||
if db_options is None:
|
||||
db_options = {}
|
||||
|
||||
# Specific options for postgres backend
|
||||
if 'postgres' in db_engine: # pragma: no cover
|
||||
@@ -721,7 +730,10 @@ if TRACING_ENABLED: # pragma: no cover
|
||||
logger.info('OpenTelemetry tracing enabled')
|
||||
|
||||
_t_resources = get_setting(
|
||||
'INVENTREE_TRACING_RESOURCES', 'tracing.resources', {}, dict
|
||||
'INVENTREE_TRACING_RESOURCES',
|
||||
'tracing.resources',
|
||||
default_value={},
|
||||
typecast=dict,
|
||||
)
|
||||
cstm_tags = {'inventree.env.' + k: v for k, v in inventree_tags.items()}
|
||||
tracing_resources = {**cstm_tags, **_t_resources}
|
||||
@@ -733,7 +745,12 @@ if TRACING_ENABLED: # pragma: no cover
|
||||
console=get_boolean_setting(
|
||||
'INVENTREE_TRACING_CONSOLE', 'tracing.console', False
|
||||
),
|
||||
auth=get_setting('INVENTREE_TRACING_AUTH', 'tracing.auth', {}),
|
||||
auth=get_setting(
|
||||
'INVENTREE_TRACING_AUTH',
|
||||
'tracing.auth',
|
||||
default_value=None,
|
||||
typecast=dict,
|
||||
),
|
||||
is_http=get_setting('INVENTREE_TRACING_IS_HTTP', 'tracing.is_http', True),
|
||||
append_http=get_boolean_setting(
|
||||
'INVENTREE_TRACING_APPEND_HTTP', 'tracing.append_http', True
|
||||
@@ -1158,7 +1175,9 @@ CUSTOM_SPLASH = get_custom_file(
|
||||
'INVENTREE_CUSTOM_SPLASH', 'customize.splash', 'custom splash'
|
||||
)
|
||||
|
||||
CUSTOMIZE = get_setting('INVENTREE_CUSTOMIZE', 'customize', {})
|
||||
CUSTOMIZE = get_setting(
|
||||
'INVENTREE_CUSTOMIZE', 'customize', default_value=None, typecast=dict
|
||||
)
|
||||
|
||||
# Load settings for the frontend interface
|
||||
FRONTEND_SETTINGS = config.get_frontend_settings(debug=DEBUG)
|
||||
|
||||
@@ -19,7 +19,7 @@ from dulwich.repo import NotGitRepository, Repo
|
||||
from .api_version import INVENTREE_API_TEXT, INVENTREE_API_VERSION
|
||||
|
||||
# InvenTree software version
|
||||
INVENTREE_SW_VERSION = '0.14.0 dev'
|
||||
INVENTREE_SW_VERSION = '0.14.2'
|
||||
|
||||
# Discover git
|
||||
try:
|
||||
|
||||
@@ -138,6 +138,8 @@ def update_parameter_values(apps, schema_editor):
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
atomic = False
|
||||
|
||||
dependencies = [
|
||||
('part', '0108_auto_20230516_1334'),
|
||||
]
|
||||
|
||||
@@ -3428,6 +3428,13 @@ class PartTestTemplate(InvenTree.models.InvenTreeMetadataModel):
|
||||
|
||||
self.key = helpers.generateTestKey(self.test_name)
|
||||
|
||||
if len(self.key) == 0:
|
||||
raise ValidationError({
|
||||
'test_name': _(
|
||||
'Invalid template name - must include at least one alphanumeric character'
|
||||
)
|
||||
})
|
||||
|
||||
self.validate_unique()
|
||||
super().clean()
|
||||
|
||||
@@ -3445,7 +3452,9 @@ class PartTestTemplate(InvenTree.models.InvenTreeMetadataModel):
|
||||
|
||||
if tests.exists():
|
||||
raise ValidationError({
|
||||
'test_name': _('Test with this name already exists for this part')
|
||||
'test_name': _(
|
||||
'Test template with the same key already exists for part'
|
||||
)
|
||||
})
|
||||
|
||||
super().validate_unique(exclude)
|
||||
|
||||
@@ -431,6 +431,29 @@ class TestTemplateTest(TestCase):
|
||||
|
||||
self.assertEqual(variant.getTestTemplates().count(), n + 1)
|
||||
|
||||
def test_key_generation(self):
|
||||
"""Test the key generation method."""
|
||||
variant = Part.objects.get(pk=10004)
|
||||
|
||||
invalid_names = ['', '+', '+++++++', ' ', '<>$&&&']
|
||||
|
||||
for name in invalid_names:
|
||||
template = PartTestTemplate(part=variant, test_name=name)
|
||||
with self.assertRaises(ValidationError):
|
||||
template.clean()
|
||||
|
||||
valid_names = [
|
||||
'Собранный щит',
|
||||
'!! 123 Собранный щит <><><> $$$$$ !!!',
|
||||
'----hello world----',
|
||||
'Olá Mundo',
|
||||
'我不懂中文',
|
||||
]
|
||||
|
||||
for name in valid_names:
|
||||
template = PartTestTemplate(part=variant, test_name=name)
|
||||
template.clean()
|
||||
|
||||
|
||||
class PartSettingsTest(InvenTreeTestCase):
|
||||
"""Tests to ensure that the user-configurable default values work as expected.
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
# Note that for postgreslql, we use the 13 version, which matches the version used in the InvenTree docker image
|
||||
|
||||
apk add gcc g++ musl-dev openssl-dev libffi-dev cargo python3-dev openldap-dev \
|
||||
libstdc++ build-base linux-headers py3-grpcio \
|
||||
jpeg-dev openjpeg-dev libwebp-dev zlib-dev \
|
||||
sqlite sqlite-dev \
|
||||
mariadb-connector-c-dev mariadb-client mariadb-dev \
|
||||
|
||||
@@ -45,7 +45,7 @@ python-barcode[images] # Barcode generator
|
||||
python-dotenv # Environment variable management
|
||||
pyyaml>=6.0.1 # YAML parsing
|
||||
qrcode[pil] # QR code generator
|
||||
rapidfuzz # Fuzzy string matching
|
||||
rapidfuzz # Fuzzy string matching
|
||||
regex # Advanced regular expressions
|
||||
sentry-sdk # Error reporting (optional)
|
||||
setuptools # Standard dependency
|
||||
@@ -53,6 +53,7 @@ tablib[xls,xlsx,yaml] # Support for XLS and XLSX formats
|
||||
weasyprint # PDF generation
|
||||
|
||||
# OpenTelemetry dependencies
|
||||
grpcio==1.54.2 # Pinned to ensure docker image builds correctly
|
||||
opentelemetry-api
|
||||
opentelemetry-sdk
|
||||
opentelemetry-exporter-otlp
|
||||
|
||||
@@ -137,7 +137,7 @@ googleapis-common-protos==1.62.0
|
||||
# via
|
||||
# opentelemetry-exporter-otlp-proto-grpc
|
||||
# opentelemetry-exporter-otlp-proto-http
|
||||
grpcio==1.60.1
|
||||
grpcio==1.54.2
|
||||
# via opentelemetry-exporter-otlp-proto-grpc
|
||||
gunicorn==21.2.0
|
||||
html5lib==1.1
|
||||
|
||||
Reference in New Issue
Block a user