Compare commits

..

15 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
Matthias Mair
9b759d2689 backport reqres token fix to 0.17.x (#9685)
backports the fix from https://github.com/inventree/InvenTree/pull/9585
2025-05-21 07:43:59 +02:00
github-actions[bot]
7959b6e597 Update 0111_auto_20230521_1350.py (#9659) (#9660)
Make data migration non atomic

(cherry picked from commit aec1de6eb3)

Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
2025-05-14 12:59:26 +01:00
Oliver
d8b1ac5962 Update version.py (#9658)
Bump version to 0.17.12
2025-05-14 11:30:02 +01:00
github-actions[bot]
b705deaf54 Update config.md (#9638) (#9640)
Added clarification on how to change the timezone correctly. The documentation -- if carefully read -- explains how to change the timezone but it can be easily missed. I also explicitly mentioned the specific variable that must be set to change the timezone from UTC

(cherry picked from commit 34db1a2a49)

Co-authored-by: aluminum-ice <12374267+aluminum-ice@users.noreply.github.com>
2025-05-07 07:51:48 +01:00
Matthias Mair
807694d840 [0.17.x] bump docs deps (#9581) (#9590)
* bump docs deps (#9581)

* bumpd docs deps

* fix https://github.com/inventree/InvenTree/security/dependabot/196

(cherry picked from commit cbac1f736c)

# Conflicts:
#	docs/requirements.txt

* fix req
2025-04-29 19:14:24 +01:00
github-actions[bot]
af8a2f14a5 fix(backend): Make task registering more robust (#9586) (#9605)
* Make task registering more robust
See https://github.com/inventree/InvenTree/issues/9579

* add unit test

(cherry picked from commit 9f0354b315)

Co-authored-by: Matthias Mair <code@mjmair.com>
2025-04-29 12:36:55 +01:00
Matthias Mair
7090950066 feat(docs): include docs in release (#9524) (#9578)
* add build step for docs

* various fixes after live-testing  (#349)

(cherry picked from commit 40ded29b35)
2025-04-25 07:17:27 +10:00
19 changed files with 199 additions and 85 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

@@ -6,10 +6,12 @@ on:
types: [published]
permissions:
contents: read
env:
python_version: 3.9
jobs:
stable:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
name: Write release to stable branch
permissions:
contents: write
@@ -32,7 +34,7 @@ jobs:
force: true
build:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
name: Build and attest frontend
permissions:
id-token: write
@@ -83,3 +85,50 @@ jobs:
file: ${{ steps.attest.outputs.bundle-path}}
tag: ${{ github.ref }}
overwrite: true
docs:
runs-on: ubuntu-24.04
name: Build and publish documentation
permissions:
contents: write
env:
INVENTREE_DB_ENGINE: sqlite3
INVENTREE_DB_NAME: inventree
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_DEBUG: true
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
with:
persist-credentials: false
- name: Environment Setup
uses: ./.github/actions/setup
with:
install: true
npm: true
- name: Install dependencies
run: |
pip install --require-hashes -r contrib/dev_reqs/requirements.txt
pip install --require-hashes -r docs/requirements.txt
- name: Build documentation
run: |
invoke migrate
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
- name: Zip build docs
run: |
cd docs/site
zip -r docs-html.zip *
- name: Publish documentation
uses: svenstaro/upload-release-action@04733e069f2d7f7f0b4aebc4fbdbce8613b03ccd # pin@2.9.0
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: docs/site/docs-html.zip
asset_name: docs-html.zip
tag: ${{ github.ref }}
overwrite: true

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

@@ -75,7 +75,7 @@ The site URL is the URL that users will use to access the InvenTree server. For
### Timezone
By default, the InvenTree server is configured to use the UTC timezone. This can be adjusted to your desired local timezone. You can refer to [Wikipedia](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for a list of available timezones. Use the values specified in the *TZ Identifier* column in the linked page.
By default, the InvenTree server is configured to use the UTC timezone. This can be adjusted to your desired local timezone. You can refer to [Wikipedia](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for a list of available timezones. Use the values specified in the *TZ Identifier* column in the linked page. For example, to change to the United States Pacific timezone, set `INVENTREE_TIMEZONE='America/Los_Angeles'`.
Date and time values are stored in the database in UTC format, and are converted to the selected timezone for display in the user interface or API.

View File

@@ -1,8 +1,8 @@
# This file was autogenerated by uv via the following command:
# uv pip compile docs/requirements.in -o docs/requirements.txt --no-strip-extras --generate-hashes
anyio==4.3.0 \
--hash=sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8 \
--hash=sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6
anyio==4.9.0 \
--hash=sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028 \
--hash=sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c
# via httpx
babel==2.15.0 \
--hash=sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb \
@@ -126,9 +126,9 @@ colorama==0.4.6 \
# via
# griffe
# mkdocs-material
essentials==1.1.5 \
--hash=sha256:8736f738bb2c51d5069b2de2cf9146f7d402f25f9f95636781e59a422c908c46 \
--hash=sha256:905fa4a69fcd2b2cf41ecc6cc65827e30c87ef91f3f5c71540bcc5e984fa8360
essentials==1.1.6 \
--hash=sha256:3fd26923f5f2ece51a219dbb17b1fb22c9190d70fa2104919be92a6419521877 \
--hash=sha256:a470e693d83c13369ebf1f488d60236b4ea99400f38db6b7224e2808c1369256
# via essentials-openapi
essentials-openapi==1.0.9 \
--hash=sha256:1431e98ef0a442f1919fd9833385bf44d832c355fd05919dc06d43d4da0f8ef4 \
@@ -150,13 +150,13 @@ gitpython==3.1.43 \
--hash=sha256:35f314a9f878467f5453cc1fee295c3e18e52f1b99f10f6cf5b1682e968a9e7c \
--hash=sha256:eec7ec56b92aad751f9912a73404bc02ba212a23adb2c7098ee668417051a1ff
# via mkdocs-git-revision-date-localized-plugin
griffe==0.45.1 \
--hash=sha256:12194c10ae07a7f46708741ad78419362cf8e5c883f449c7c48de1686611b853 \
--hash=sha256:84ce9243a9e63c07d55563a735a0d07ef70b46c455616c174010e7fc816f4648
griffe==1.7.3 \
--hash=sha256:52ee893c6a3a968b639ace8015bec9d36594961e156e23315c8e8e51401fa50b \
--hash=sha256:c6b3ee30c2f0f17f30bcdef5068d6ab7a2a4f1b8bf1a3e74b56fffd21e1c5f75
# via mkdocstrings-python
h11==0.14.0 \
--hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \
--hash=sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761
h11==0.16.0 \
--hash=sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1 \
--hash=sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86
# via httpcore
hjson==3.1.0 \
--hash=sha256:55af475a27cf83a7969c808399d7bccdec8fb836a07ddbd574587593b9cdcf75 \
@@ -164,9 +164,9 @@ hjson==3.1.0 \
# via
# mkdocs-macros-plugin
# super-collections
httpcore==1.0.5 \
--hash=sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61 \
--hash=sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5
httpcore==1.0.9 \
--hash=sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55 \
--hash=sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8
# via httpx
httpx==0.27.0 \
--hash=sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5 \
@@ -196,9 +196,9 @@ jinja2==3.1.4 \
# mkdocs-material
# mkdocstrings
# neoteroi-mkdocs
markdown==3.6 \
--hash=sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f \
--hash=sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224
markdown==3.8 \
--hash=sha256:794a929b79c5af141ef5ab0f2f642d0f7b1872981250230e72682346f7cc90dc \
--hash=sha256:7df81e63f0df5c4b24b7d156eb81e4690595239b7d70937d0409f1b0de319c6f
# via
# mkdocs
# mkdocs-autorefs
@@ -302,7 +302,9 @@ mkdocs==1.6.1 \
mkdocs-autorefs==1.2.0 \
--hash=sha256:a86b93abff653521bda71cf3fc5596342b7a23982093915cb74273f67522190f \
--hash=sha256:d588754ae89bd0ced0c70c06f58566a4ee43471eeeee5202427da7de9ef85a2f
# via mkdocstrings
# via
# mkdocstrings
# mkdocstrings-python
mkdocs-get-deps==0.2.0 \
--hash=sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c \
--hash=sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134
@@ -337,17 +339,17 @@ mkdocstrings[python]==0.27.0 \
# via
# -r docs/requirements.in
# mkdocstrings-python
mkdocstrings-python==1.10.2 \
--hash=sha256:38a4fd41953defb458a107033440c229c7e9f98f35a24e84d888789c97da5a63 \
--hash=sha256:e8e596b37f45c09b67bec253e035fe18988af5bbbbf44e0ccd711742eed750e5
mkdocstrings-python==1.13.0 \
--hash=sha256:2dbd5757e8375b9720e81db16f52f1856bf59905428fd7ef88005d1370e2f64c \
--hash=sha256:b88bbb207bab4086434743849f8e796788b373bd32e7bfefbf8560ac45d88f97
# via mkdocstrings
neoteroi-mkdocs==1.1.0 \
--hash=sha256:609aae655e781c7aec517ab14759c34ce896b8132d1df4b9c2e504779c2e48ef \
--hash=sha256:9c59aebf83ca09d1d486bf8c0351e6ddfa912f09413d153ecabc5cd268a3155a
neoteroi-mkdocs==1.1.2 \
--hash=sha256:95a8b8e6b89a54a6a731e68329c7bb03e86f46deb74fe2a95de307c9702e7af9 \
--hash=sha256:a40475142b7067f5b88108d2e164a6c3d6ed98af311402bd0833417bdb0dd6bc
# via -r docs/requirements.in
packaging==24.0 \
--hash=sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5 \
--hash=sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9
packaging==25.0 \
--hash=sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484 \
--hash=sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f
# via
# mkdocs
# mkdocs-macros-plugin
@@ -360,15 +362,15 @@ pathspec==0.12.1 \
# via
# mkdocs
# mkdocs-macros-plugin
platformdirs==4.2.2 \
--hash=sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee \
--hash=sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3
platformdirs==4.3.7 \
--hash=sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94 \
--hash=sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351
# via
# mkdocs-get-deps
# mkdocstrings
pygments==2.18.0 \
--hash=sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199 \
--hash=sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a
pygments==2.19.1 \
--hash=sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f \
--hash=sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c
# via
# mkdocs-material
# rich
@@ -384,9 +386,9 @@ python-dateutil==2.9.0.post0 \
# via
# ghp-import
# mkdocs-macros-plugin
pytz==2024.1 \
--hash=sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812 \
--hash=sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319
pytz==2025.2 \
--hash=sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3 \
--hash=sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00
# via mkdocs-git-revision-date-localized-plugin
pyyaml==6.0.2 \
--hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \
@@ -553,9 +555,9 @@ requests==2.32.3 \
--hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \
--hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6
# via mkdocs-material
rich==13.7.1 \
--hash=sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222 \
--hash=sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432
rich==14.0.0 \
--hash=sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0 \
--hash=sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725
# via neoteroi-mkdocs
six==1.16.0 \
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
@@ -575,19 +577,20 @@ super-collections==0.5.3 \
--hash=sha256:907d35b25dc4070910e8254bf2f5c928348af1cf8a1f1e8259e06c666e902cff \
--hash=sha256:94c1ec96c0a0d5e8e7d389ed8cde6882ac246940507c5e6b86e91945c2968d46
# via mkdocs-macros-plugin
termcolor==2.4.0 \
--hash=sha256:9297c0df9c99445c2412e832e882a7884038a25617c60cea2ad69488d4040d63 \
--hash=sha256:aab9e56047c8ac41ed798fa36d892a37aca6b3e9159f3e0c24bc64a9b3ac7b7a
termcolor==3.0.1 \
--hash=sha256:a6abd5c6e1284cea2934443ba806e70e5ec8fd2449021be55c280f8a3731b611 \
--hash=sha256:da1ed4ec8a5dc5b2e17476d859febdb3cccb612be1c36e64511a6f2485c10c69
# via mkdocs-macros-plugin
typing-extensions==4.12.2 \
--hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
--hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8
typing-extensions==4.13.2 \
--hash=sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c \
--hash=sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef
# via
# anyio
# mkdocstrings
urllib3==2.2.2 \
--hash=sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472 \
--hash=sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168
# rich
urllib3==2.4.0 \
--hash=sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466 \
--hash=sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813
# via requests
watchdog==4.0.0 \
--hash=sha256:11e12fafb13372e18ca1bbf12d50f593e7280646687463dd47730fd4f4d5d257 \

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.11'
INVENTREE_SW_VERSION = '0.17.14'
logger = logging.getLogger('inventree')

View File

@@ -84,6 +84,8 @@ def migrate_part_units(apps, schema_editor):
class Migration(migrations.Migration):
atomic = False
dependencies = [
('part', '0110_alter_part_units'),
]

View File

@@ -179,7 +179,15 @@ class ScheduleMixin:
obj['func'] = 'plugin.registry.call_plugin_function'
obj['args'] = f"'{slug}', '{func_name}'"
if Schedule.objects.filter(name=task_name).exists():
tasks = Schedule.objects.filter(name=task_name)
if len(tasks) > 1:
logger.info(
"Found multiple tasks; Adding a new scheduled task '%s'",
task_name,
)
tasks.delete()
Schedule.objects.create(**obj)
elif len(tasks) == 1:
# Scheduled task already exists - update it!
logger.info("Updating scheduled task '%s'", task_name)
instance = Schedule.objects.get(name=task_name)

View File

@@ -209,7 +209,11 @@ class APICallMixinTest(BaseMixinDefinition, TestCase):
NAME = 'Sample API Caller'
SETTINGS = {
'API_TOKEN': {'name': 'API Token', 'protected': True},
'API_TOKEN': {
'name': 'API Token',
'protected': True,
'default': 'reqres-free-v1',
},
'API_URL': {
'name': 'External URL',
'description': 'Where is your API located?',
@@ -219,6 +223,7 @@ class APICallMixinTest(BaseMixinDefinition, TestCase):
API_URL_SETTING = 'API_URL'
API_TOKEN_SETTING = 'API_TOKEN'
API_TOKEN = 'x-api-key'
@property
def api_url(self):
@@ -289,6 +294,8 @@ class APICallMixinTest(BaseMixinDefinition, TestCase):
self.assertTrue(result)
self.assertEqual(result.reason, 'OK')
# Set API TOKEN
self.mixin.set_setting('API_TOKEN', 'reqres-free-v1')
# api_call with post and data
result = self.mixin.api_call(
'https://reqres.in/api/users/',
@@ -298,6 +305,7 @@ class APICallMixinTest(BaseMixinDefinition, TestCase):
)
self.assertTrue(result)
self.assertNotIn('error', result)
self.assertEqual(result['name'], 'morpheus')
# api_call with endpoint with leading slash

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

@@ -10,7 +10,11 @@ class SampleApiCallerPlugin(APICallMixin, SettingsMixin, InvenTreePlugin):
NAME = 'Sample API Caller'
SETTINGS = {
'API_TOKEN': {'name': 'API Token', 'protected': True},
'API_TOKEN': {
'name': 'API Token',
'protected': True,
'default': 'reqres-free-v1',
},
'API_URL': {
'name': 'External URL',
'description': 'Where is your API located?',
@@ -19,6 +23,7 @@ class SampleApiCallerPlugin(APICallMixin, SettingsMixin, InvenTreePlugin):
}
API_URL_SETTING = 'API_URL'
API_TOKEN_SETTING = 'API_TOKEN'
API_TOKEN = 'x-api-key'
def get_external_url(self):
"""Returns data from the sample endpoint."""

View File

@@ -2,10 +2,10 @@
from django.test import TestCase
from plugin import InvenTreePlugin, registry
from plugin import InvenTreePlugin
from plugin.helpers import MixinImplementationError
from plugin.mixins import ScheduleMixin
from plugin.registry import call_plugin_function
from plugin.registry import call_plugin_function, registry
class ExampleScheduledTaskPluginTests(TestCase):
@@ -42,9 +42,19 @@ class ExampleScheduledTaskPluginTests(TestCase):
# test updating the schedule
hello_schedule = Schedule.objects.get(name='plugin.schedule.hello')
self.assertEqual(hello_schedule.minutes, 45)
# change the schedule and reregister
# change the schedule and reregister -> the interval should be preserved
plg.scheduled_tasks['hello']['minutes'] = 15
# add a doubly scheduled task - this should be removed
Schedule.objects.create(name='plugin.schedule.hello')
self.assertEqual(
Schedule.objects.filter(name='plugin.schedule.hello').count(), 2
)
plg.register_tasks()
# The duplicate task should be removed
self.assertEqual(
Schedule.objects.filter(name='plugin.schedule.hello').count(), 1
)
# Check that the schedule was updated
hello_schedule = Schedule.objects.get(name='plugin.schedule.hello')

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')