Compare commits

..

8 Commits

Author SHA1 Message Date
Matthias Mair
bca375dae5 [0.17.x] feat: add cluster monitor task (#9812) (#9815)
* feat: add cluster monitor task (#9812)

(cherry picked from commit 00c974b629)

* fix style

* fix style
2025-06-22 09:41:59 +10:00
Matthias Mair
533556b7e4 fix: package - various changes (#9802)
* fail on install

* move site setting up to ensure site is set early

* fix version file path

* ensure subdirs are created too

* ensure downloaded files are also collected into static

* update order

* bump qc workers

* update version
2025-06-19 12:21:46 +10:00
Matthias Mair
821d7b01f3 fix stable doc release (#9796) 2025-06-17 08:17:08 +10:00
github-actions[bot]
9e08b58f89 Handle case where owner is null (#9732) (#9733)
(cherry picked from commit 89f8f132e1)

Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
2025-06-03 16:05:09 +10:00
github-actions[bot]
be04d0c4fc Handle failed partial_rebuild (#9723) (#9724)
(cherry picked from commit 5c5549c233)

Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
2025-06-02 22:46:15 +10:00
Oliver
2a7f5f94c8 Security fix (#9727)
* Add max limit for 'skip' parameter
2025-06-02 22:43:48 +10:00
Oliver
314b161076 Update version.py (#9725)
Bump version number to `0.17.13`
2025-06-02 22:35:08 +10:00
github-actions[bot]
92759a5671 fix(backend): record export is empty when include permissions flag is used (#9704) (#9719)
(cherry picked from commit 22ba802d69)

Co-authored-by: Gustaf Järgren <gurreja@gmail.com>
2025-06-02 20:28:41 +10:00
12 changed files with 57 additions and 28 deletions

View File

@@ -65,7 +65,7 @@ jobs:
javascript:
name: Style - Classic UI [JS]
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
needs: ["pre-commit"]
@@ -87,7 +87,7 @@ jobs:
pre-commit:
name: Style [pre-commit]
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
needs: paths-filter
if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.frontend == 'true' || needs.paths-filter.outputs.force == 'true'
@@ -107,7 +107,7 @@ jobs:
mkdocs:
name: Style [Documentation]
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
needs: paths-filter
@@ -133,7 +133,7 @@ jobs:
schema:
name: Tests - API Schema Documentation
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
needs: paths-filter
if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.force == 'true'
env:
@@ -204,7 +204,7 @@ jobs:
schema-push:
name: Push new schema
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
needs: [paths-filter, schema]
if: needs.schema.result == 'success' && github.ref == 'refs/heads/master' && needs.paths-filter.outputs.api == 'true' && github.repository_owner == 'inventree'
env:
@@ -232,7 +232,7 @@ jobs:
python:
name: Tests - inventree-python
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
needs: ["pre-commit", "paths-filter"]
if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.force == 'true'
@@ -274,7 +274,7 @@ jobs:
coverage:
name: Tests - DB [SQLite] + Coverage ${{ matrix.python_version }}
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
needs: ["pre-commit", "paths-filter"]
if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.force == 'true'
@@ -317,7 +317,7 @@ jobs:
postgres:
name: Tests - DB [PostgreSQL]
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
needs: ["pre-commit", "paths-filter"]
if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.force == 'true'
@@ -361,7 +361,7 @@ jobs:
mysql:
name: Tests - DB [MySQL]
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
needs: ["pre-commit", "paths-filter"]
if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.force == 'true'
@@ -505,7 +505,7 @@ jobs:
platform_ui:
name: Tests - Platform UI
runs-on: ubuntu-20.04
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'
@@ -561,7 +561,7 @@ jobs:
platform_ui_build:
name: Build - UI Platform
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
timeout-minutes: 60
steps:

View File

@@ -116,7 +116,7 @@ jobs:
- name: Build documentation
run: |
invoke migrate
invoke int.export-definitions --basedir "docs"
invoke int.export-settings-definitions --filename docs/inventree_settings.json --overwrite
invoke dev.schema --filename docs/schema.yml --ignore-warnings
python docs/extract_schema.py docs/schema.yml
mkdocs build -f docs/mkdocs.yml

View File

@@ -300,7 +300,7 @@ function update_or_install() {
# Run update as app user
echo "# POI12| Updating InvenTree"
sudo -u ${APP_USER} --preserve-env=$SETUP_ENVS bash -c "cd ${APP_HOME} && pip install wheel"
sudo -u ${APP_USER} --preserve-env=$SETUP_ENVS bash -c "cd ${APP_HOME} && invoke update | sed -e 's/^/# POI12| u | /;'"
sudo -u ${APP_USER} --preserve-env=$SETUP_ENVS bash -c "set -e && cd ${APP_HOME} && invoke update | sed -e 's/^/# POI12| u | /;'"
# Make sure permissions are correct again
echo "# POI12| Set permissions for data dir and media: ${DATA_DIR}"

View File

@@ -53,12 +53,12 @@ create_admin
# run updates
stop_inventree
set_site
update_or_install
# Write config file
if [ "${SETUP_CONF_LOADED}" = "true" ]; then
set_env
fi
set_site
start_inventree
# show info

View File

@@ -641,7 +641,16 @@ class InvenTreeTree(MetadataMixin, PluginValidationMixin, MPTTModel):
# 3. Update the tree structure
if tree_id:
self.__class__.objects.partial_rebuild(tree_id)
try:
self.__class__.objects.partial_rebuild(tree_id)
except Exception:
logger.warning(
'Failed to rebuild tree for %s <%s>',
self.__class__.__name__,
self.pk,
)
# If the partial rebuild fails, rebuild the entire tree
self.__class__.objects.rebuild()
else:
self.__class__.objects.rebuild()

View File

@@ -71,7 +71,7 @@ BASE_DIR = config.get_base_dir()
CONFIG = config.load_config_data(set_cache=True)
# Load VERSION data if it exists
version_file = BASE_DIR.parent.joinpath('VERSION')
version_file = BASE_DIR.parent.parent.parent.joinpath('VERSION')
if version_file.exists():
print('load version from file')
load_dotenv(version_file)

View File

@@ -18,7 +18,7 @@ from django.conf import settings
from .api_version import INVENTREE_API_TEXT, INVENTREE_API_VERSION
# InvenTree software version
INVENTREE_SW_VERSION = '0.17.12'
INVENTREE_SW_VERSION = '0.17.14'
logger = logging.getLogger('inventree')

View File

@@ -34,6 +34,7 @@ class LabelPrintingOptionsSerializer(serializers.Serializer):
label=_('Skip Labels'),
help_text=_('Skip this number of labels when printing label sheets'),
min_value=0,
max_value=500,
)
border = serializers.BooleanField(

View File

@@ -819,7 +819,11 @@ class Owner(models.Model):
if self.owner_type.name == 'user' and get_global_setting(
'DISPLAY_FULL_NAMES', cache=True
):
return self.owner.get_full_name() or str(self.owner)
if self.owner and hasattr(self.owner, 'get_full_name'):
# Use the get_full_name method if available
return self.owner.get_full_name() or str(self.owner)
else:
return str(self.owner)
return str(self.owner)
def label(self):

View File

@@ -1,5 +1,6 @@
# Please keep this list sorted - if you pin a version provide a reason
Django<5.0 # Django package
blessed # CLI for Q Monitor
coreapi # API documentation for djangorestframework
cryptography>=40.0.0,!=40.0.2 # Core cryptographic functionality
django-allauth[openid,saml] # SSO for external providers via OpenID

View File

@@ -26,6 +26,10 @@ bleach[css]==6.2.0 \
--hash=sha256:117d9c6097a7c3d22fd578fcd8d35ff1e125df6736f554da4e432fdd63f31e5e \
--hash=sha256:123e894118b8a599fd80d3ec1a6d4cc7ce4e5882b1317a7e1ba69b56e95f991f
# via django-markdownify
blessed==1.21.0 \
--hash=sha256:ece8bbc4758ab9176452f4e3a719d70088eb5739798cd5582c9e05f2a28337ec \
--hash=sha256:f831e847396f5a2eac6c106f4dfadedf46c4f804733574b15fe86d2ed45a9588
# via -r src/backend/requirements.in
brotli==1.1.0 \
--hash=sha256:03d20af184290887bdea3f0f78c4f737d126c74dc2f3ccadf07e54ceca3bf208 \
--hash=sha256:0541e747cce78e24ea12d69176f6a7ddb690e62c425e01d31cc065e69ce55b48 \
@@ -1639,7 +1643,9 @@ urllib3==2.2.3 \
wcwidth==0.2.13 \
--hash=sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859 \
--hash=sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5
# via prettytable
# via
# blessed
# prettytable
weasyprint==62.3 \
--hash=sha256:8d8680d732f7fa0fcbc587692a5a5cb095c3525627066918d6e203cbf42b7fcd \
--hash=sha256:d31048646ce15084e135b33e334a61f526aa68d2f679fcc109ed0e0f5edaed21

View File

@@ -713,22 +713,22 @@ def export_records(
data_out = []
if include_permissions is False:
for entry in data:
model_name = entry.get('model', None)
for entry in data:
model_name = entry.get('model', None)
# Ignore any temporary settings (start with underscore)
if model_name in ['common.inventreesetting', 'common.inventreeusersetting']:
if entry['fields'].get('key', '').startswith('_'):
continue
# Ignore any temporary settings (start with underscore)
if model_name in ['common.inventreesetting', 'common.inventreeusersetting']:
if entry['fields'].get('key', '').startswith('_'):
continue
if include_permissions is False:
if model_name == 'auth.group':
entry['fields']['permissions'] = []
if model_name == 'auth.user':
entry['fields']['user_permissions'] = []
data_out.append(entry)
data_out.append(entry)
# Write the processed data to file
with open(target, 'w', encoding='utf-8') as f_out:
@@ -1360,7 +1360,7 @@ def frontend_download(
# if clean, delete static/web directory
if clean:
shutil.rmtree(dest_path, ignore_errors=True)
dest_path.mkdir()
dest_path.mkdir(parents=True, exist_ok=True)
info(f'Cleaned directory: {dest_path}')
# unzip build to static folder
@@ -1385,6 +1385,7 @@ def frontend_download(
info(f'Downloaded frontend build to temporary file: {dst.name}')
handle_extract(dst.name)
static(c)
def check_already_current(tag=None, sha=None):
"""Check if the currently available frontend is already the requested one."""
@@ -1548,6 +1549,12 @@ def clear_generated(c):
run(c, 'find src -name "messages.mo" -exec rm -f {} +')
@task(pre=[wait])
def monitor(c):
"""Monitor the worker performance."""
manage(c, 'qmonitor', pty=True)
# Collection sorting
development = Collection(
delete_data,
@@ -1596,6 +1603,7 @@ ns = Collection(
version,
wait,
worker,
monitor,
)
ns.add_collection(development, 'dev')