@bluedynamics/cdk8s-plone 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/.jsii +26 -7
  2. package/API.md +16 -0
  3. package/CLAUDE.md +352 -0
  4. package/README.md +55 -178
  5. package/documentation/Makefile +357 -0
  6. package/documentation/README.md +284 -0
  7. package/documentation/mx.ini +3 -0
  8. package/documentation/sources/_static/brand-theme.css +685 -0
  9. package/documentation/sources/_static/custom-icons.css +123 -0
  10. package/documentation/sources/_static/fonts/hack/Hack-Regular.woff2 +0 -0
  11. package/documentation/sources/_static/fonts/orbitron/Orbitron-Black.woff2 +11 -0
  12. package/documentation/sources/_static/fonts/orbitron/Orbitron-Bold.woff2 +11 -0
  13. package/documentation/sources/_static/fonts/orbitron/Orbitron-Regular.woff2 +0 -0
  14. package/documentation/sources/_static/fonts/rajdhani/Rajdhani-Bold.woff2 +11 -0
  15. package/documentation/sources/_static/fonts/rajdhani/Rajdhani-Medium.woff2 +11 -0
  16. package/documentation/sources/_static/fonts/rajdhani/Rajdhani-Regular.woff2 +11 -0
  17. package/documentation/sources/_static/fonts/rajdhani/Rajdhani-SemiBold.woff2 +11 -0
  18. package/documentation/sources/_static/kup6s-icon-explanation.svg +32 -0
  19. package/documentation/sources/_static/kup6s-icon-howto.svg +34 -0
  20. package/documentation/sources/_static/kup6s-icon-plone.svg +79 -0
  21. package/documentation/sources/_static/kup6s-icon-reference.svg +34 -0
  22. package/documentation/sources/_static/kup6s-icon-tutorials.svg +30 -0
  23. package/documentation/sources/_static/logo-fix.js +12 -0
  24. package/documentation/sources/conf.py +105 -0
  25. package/documentation/sources/explanation/architecture.md +311 -0
  26. package/documentation/sources/explanation/features.md +353 -0
  27. package/documentation/sources/explanation/index.md +51 -0
  28. package/documentation/sources/how-to/index.md +56 -0
  29. package/documentation/sources/how-to/setup-prerequisites.md +354 -0
  30. package/documentation/sources/index.md +108 -0
  31. package/documentation/sources/reference/api/.gitkeep +1 -0
  32. package/documentation/sources/reference/configuration-options.md +370 -0
  33. package/documentation/sources/reference/index.md +59 -0
  34. package/documentation/sources/tutorials/01-quick-start.md +157 -0
  35. package/documentation/sources/tutorials/index.md +48 -0
  36. package/lib/httpcache.d.ts +6 -0
  37. package/lib/httpcache.js +4 -2
  38. package/lib/plone.js +1 -1
  39. package/package.json +1 -1
package/README.md CHANGED
@@ -1,56 +1,38 @@
1
1
  # CDK8S Plone
2
2
 
3
- A CDK8S library for deploying Plone CMS to Kubernetes.
3
+ > TypeScript and Python library for deploying Plone CMS to Kubernetes using CDK8S
4
4
 
5
- This library provides constructs to bootstrap a Plone deployment on a Kubernetes cluster using the [CDK8S](https://cdk8s.io) framework.
5
+ [![npm version](https://badge.fury.io/js/%40bluedynamics%2Fcdk8s-plone.svg)](https://www.npmjs.com/package/@bluedynamics/cdk8s-plone)
6
+ [![PyPI version](https://badge.fury.io/py/cdk8s-plone.svg)](https://pypi.org/project/cdk8s-plone/)
7
+ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
6
8
 
7
- ## Features
9
+ ## Overview
8
10
 
9
- - **Backend**: Plone backend (API with `plone.volto` or Classic-UI)
10
- - **Frontend**: Plone Volto (modern React-based user interface)
11
- - **Varnish Caching**: Optional HTTP caching layer using [kube-httpcache](https://github.com/mittwald/kube-httpcache) with cluster-wide cache invalidation
12
- - **High Availability**: Configurable replicas with PodDisruptionBudgets
13
- - **Multi-language Support**: Published to npm (TypeScript/JavaScript) and PyPI (Python)
11
+ cdk8s-plone provides CDK8S constructs for deploying [Plone CMS](https://plone.org/) on Kubernetes. Define your infrastructure using TypeScript or Python and generate Kubernetes manifests automatically.
14
12
 
13
+ **Key Features:**
14
+ - 🚀 Supports Volto (modern React frontend) and Classic UI
15
+ - 📦 High availability with configurable replicas
16
+ - ⚡ Optional Varnish HTTP caching layer
17
+ - 🔧 Fine-grained resource and probe configuration
18
+ - 🌍 Multi-language support (TypeScript/JavaScript and Python)
19
+ - ✅ Type-safe infrastructure as code
15
20
 
16
- ## Installation
17
-
18
- ### TypeScript/JavaScript
19
-
20
- Create a new CDK8S project (or use an existing one):
21
-
22
- ```bash
23
- cdk8s init typescript-app
24
- ```
21
+ ## Quick Start
25
22
 
26
- Install the library:
23
+ ### Installation
27
24
 
25
+ **TypeScript/JavaScript:**
28
26
  ```bash
29
27
  npm install @bluedynamics/cdk8s-plone
30
28
  ```
31
29
 
32
- Package: [@bluedynamics/cdk8s-plone](https://www.npmjs.com/package/@bluedynamics/cdk8s-plone)
33
-
34
- ### Python
35
-
36
- Create a new CDK8S project:
37
-
38
- ```bash
39
- cdk8s init python-app
40
- ```
41
-
42
- Install the library:
43
-
30
+ **Python:**
44
31
  ```bash
45
32
  pip install cdk8s-plone
46
33
  ```
47
34
 
48
- Package: [cdk8s-plone](https://pypi.org/project/cdk8s-plone/)
49
-
50
-
51
- ## Quick Start
52
-
53
- ### Basic Plone Deployment
35
+ ### Basic Example
54
36
 
55
37
  ```typescript
56
38
  import { App, Chart } from 'cdk8s';
@@ -62,7 +44,7 @@ const chart = new Chart(app, 'PloneDeployment');
62
44
  new Plone(chart, 'my-plone', {
63
45
  variant: PloneVariant.VOLTO,
64
46
  backend: {
65
- image: 'plone/plone-backend:6.0.10',
47
+ image: 'plone/plone-backend:6.1.3',
66
48
  replicas: 3,
67
49
  },
68
50
  frontend: {
@@ -74,173 +56,68 @@ new Plone(chart, 'my-plone', {
74
56
  app.synth();
75
57
  ```
76
58
 
77
- ### With Varnish HTTP Cache
78
-
79
- ```typescript
80
- import { PloneHttpcache } from '@bluedynamics/cdk8s-plone';
81
-
82
- const plone = new Plone(chart, 'my-plone', {
83
- variant: PloneVariant.VOLTO,
84
- backend: { image: 'plone/plone-backend:6.0.10' },
85
- frontend: { image: 'plone/plone-frontend:16.0.0' },
86
- });
87
-
88
- new PloneHttpcache(chart, 'cache', {
89
- plone: plone,
90
- existingSecret: 'varnish-secret',
91
- replicas: 2,
92
- });
93
- ```
94
-
95
- ### Generate Kubernetes Manifests
96
-
59
+ Generate Kubernetes manifests:
97
60
  ```bash
98
61
  cdk8s synth
62
+ kubectl apply -f dist/
99
63
  ```
100
64
 
101
- The manifests are stored in the `dist/` directory.
102
-
103
- For a complete example, see the [example project](https://github.com/bluedynamics/cdk8s-plone-example).
104
-
105
- ## Prerequisites
106
-
107
- - **kubectl** - Command-line tool for deploying Kubernetes manifests. [Install kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl)
108
- - **Helm** (optional) - Only needed if generating Helm charts. [Install Helm](https://helm.sh/docs/intro/install/)
109
- - **Node.js** - For TypeScript/JavaScript development
110
- - **Python 3.8+** - For Python development
65
+ ## Documentation
111
66
 
67
+ **📚 Full documentation:** https://bluedynamics.github.io/cdk8s-plone/
112
68
 
113
- ## API Documentation
69
+ - [Quick Start Tutorial](https://bluedynamics.github.io/cdk8s-plone/tutorials/01-quick-start.html)
70
+ - [Configuration Reference](https://bluedynamics.github.io/cdk8s-plone/reference/configuration-options.html)
71
+ - [Architecture Overview](https://bluedynamics.github.io/cdk8s-plone/explanation/architecture.html)
72
+ - [Complete API Documentation](./API.md)
114
73
 
115
- For complete API documentation, see [API.md](./API.md).
74
+ ## Examples
116
75
 
117
- ### Key Constructs
76
+ See the [cdk8s-plone-example](https://github.com/bluedynamics/cdk8s-plone-example) repository for complete working examples.
118
77
 
119
- #### `Plone`
78
+ ## Requirements
120
79
 
121
- Main construct for deploying Plone CMS. Supports two variants:
122
- - **VOLTO**: Modern React frontend with REST API backend (default)
123
- - **CLASSICUI**: Traditional server-side rendered Plone
124
-
125
- Properties:
126
- - `backendServiceName` - Name of the backend Kubernetes service
127
- - `frontendServiceName` - Name of the frontend service (VOLTO only)
128
- - `variant` - Deployment variant (VOLTO or CLASSICUI)
129
- - `siteId` - Plone site ID in ZODB (default: 'Plone')
130
-
131
- #### `PloneHttpcache`
132
-
133
- Varnish HTTP caching layer using the [kube-httpcache](https://github.com/mittwald/kube-httpcache) Helm chart.
134
-
135
- Properties:
136
- - `httpcacheServiceName` - Name of the Varnish service
137
-
138
- ### Configuration Options
139
-
140
- #### `PloneOptions`
141
-
142
- - `version` - Version of your project
143
- - `siteId` - Plone site ID (default: 'Plone')
144
- - `variant` - PloneVariant.VOLTO or PloneVariant.CLASSICUI (default: VOLTO)
145
- - `backend` - Backend configuration (PloneBaseOptions)
146
- - `frontend` - Frontend configuration (PloneBaseOptions, required for VOLTO)
147
- - `imagePullSecrets` - Image pull secrets for private registries
148
-
149
- #### `PloneBaseOptions`
150
-
151
- Configuration for backend or frontend:
152
-
153
- **Container:**
154
- - `image` - Container image (e.g., 'plone/plone-backend:6.0.10')
155
- - `imagePullPolicy` - Pull policy (default: 'IfNotPresent')
156
- - `replicas` - Number of replicas (default: 2)
157
- - `environment` - Environment variables (cdk8s-plus-30.Env)
158
-
159
- **Resources:**
160
- - `requestCpu` / `limitCpu` - CPU requests/limits
161
- - `requestMemory` / `limitMemory` - Memory requests/limits
162
-
163
- **High Availability:**
164
- - `minAvailable` - Min pods during updates (for PodDisruptionBudget)
165
- - `maxUnavailable` - Max unavailable pods during updates
166
-
167
- **Health Probes:**
168
- - `readinessEnabled` - Enable readiness probe (default: true)
169
- - `readinessInitialDelaySeconds` / `readinessTimeoutSeconds` / `readinessPeriodSeconds`
170
- - `readinessSuccessThreshold` / `readinessFailureThreshold`
171
- - `livenessEnabled` - Enable liveness probe (default: false, recommended true for frontend)
172
- - `livenessInitialDelaySeconds` / `livenessTimeoutSeconds` / `livenessPeriodSeconds`
173
- - `livenessSuccessThreshold` / `livenessFailureThreshold`
174
-
175
- **Annotations:**
176
- - `annotations` - Deployment metadata annotations
177
- - `podAnnotations` - Pod template annotations (e.g., for Prometheus)
178
- - `serviceAnnotations` - Service annotations (e.g., for external-dns)
179
-
180
- #### `PloneHttpcacheOptions`
181
-
182
- - `plone` - Plone construct to attach cache to (required)
183
- - `varnishVcl` - VCL configuration as string
184
- - `varnishVclFile` - Path to VCL configuration file
185
- - `existingSecret` - Kubernetes secret for Varnish admin credentials
186
- - `replicas` - Number of Varnish replicas (default: 2)
187
- - `requestCpu` / `limitCpu` - CPU resources
188
- - `requestMemory` / `limitMemory` - Memory resources
189
- - `servicemonitor` - Enable Prometheus ServiceMonitor (default: false)
190
- - `exporterEnabled` - Enable Prometheus exporter sidecar (default: true)
191
- - `chartVersion` - kube-httpcache Helm chart version (default: latest)
80
+ - **kubectl** - [Install kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl)
81
+ - **Node.js 16+** (for TypeScript/JavaScript) - [Install Node.js](https://nodejs.org/)
82
+ - **Python 3.8+** (for Python) - [Install Python](https://www.python.org/)
83
+ - **Kubernetes cluster** (local or cloud)
192
84
 
85
+ For detailed setup instructions, see [Setup Prerequisites](https://bluedynamics.github.io/cdk8s-plone/how-to/setup-prerequisites.html).
193
86
 
194
87
  ## Development
195
88
 
196
- This project uses [Projen](https://projen.io/) to manage project configuration. **Do not edit generated files directly.**
197
-
198
- ### Setup
199
-
200
- Clone the repository and install dependencies:
89
+ This project uses [Projen](https://projen.io/) for project management.
201
90
 
202
91
  ```bash
203
- nvm use lts/*
204
- corepack enable
205
- npx projen
206
- ```
207
-
208
- ### Common Commands
92
+ # Install dependencies
93
+ npm install
209
94
 
210
- ```bash
211
95
  # Run tests
212
- npx projen test
213
-
214
- # Run tests in watch mode
215
- npx projen test:watch
96
+ npm test
216
97
 
217
- # Build (compile TypeScript + generate JSII bindings)
218
- npx projen build
98
+ # Build
99
+ npm run build
219
100
 
220
- # Lint
221
- npx projen eslint
222
-
223
- # Generate API documentation
224
- npx projen docgen
225
-
226
- # Package for distribution
227
- npx projen package-all
101
+ # Update project configuration
102
+ # Edit .projenrc.ts, then run:
103
+ npx projen
228
104
  ```
229
105
 
230
- ### Making Changes
231
-
232
- 1. Edit `.projenrc.ts` for project configuration changes
233
- 2. Run `npx projen` to regenerate project files
234
- 3. Make code changes in `src/`
235
- 4. Run tests and update snapshots if needed: `npx projen test -- -u`
106
+ For detailed development instructions, see [CONTRIBUTING.md](./CONTRIBUTING.md) (if available).
236
107
 
237
- ## References
108
+ ## Resources
238
109
 
239
110
  - [CDK8S Documentation](https://cdk8s.io/)
240
- - [Kubernetes Probes Documentation](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/)
241
- - [kube-httpcache Helm Chart](https://github.com/mittwald/kube-httpcache)
111
+ - [Plone CMS](https://plone.org/)
112
+ - [kube-httpcache](https://github.com/mittwald/kube-httpcache) (for HTTP caching)
242
113
  - [Example Project](https://github.com/bluedynamics/cdk8s-plone-example)
243
114
 
244
115
  ## License
245
116
 
246
- See [LICENSE](./LICENSE) file.
117
+ [Apache 2.0](LICENSE)
118
+
119
+ ## Maintainers
120
+
121
+ Maintained by [Blue Dynamics Alliance](https://github.com/bluedynamics)
122
+
123
+ **Author:** Jens W. Klein (jk@kleinundpartner.at)
@@ -0,0 +1,357 @@
1
+ ##############################################################################
2
+ # THIS FILE IS GENERATED BY MXMAKE
3
+ #
4
+ # DOMAINS:
5
+ #: core.base
6
+ #: core.mxenv
7
+ #: docs.sphinx
8
+ #
9
+ # SETTINGS (ALL CHANGES MADE BELOW SETTINGS WILL BE LOST)
10
+ ##############################################################################
11
+
12
+ ## core.base
13
+
14
+ # `deploy` target dependencies.
15
+ # No default value.
16
+ DEPLOY_TARGETS?=
17
+
18
+ # target to be executed when calling `make run`
19
+ # No default value.
20
+ RUN_TARGET?=
21
+
22
+ # Additional files and folders to remove when running clean target
23
+ # No default value.
24
+ CLEAN_FS?=
25
+
26
+ # Optional makefile to include before default targets. This can
27
+ # be used to provide custom targets or hook up to existing targets.
28
+ # Default: include.mk
29
+ INCLUDE_MAKEFILE?=include.mk
30
+
31
+ # Optional additional directories to be added to PATH in format
32
+ # `/path/to/dir/:/path/to/other/dir`. Gets inserted first, thus gets searched
33
+ # first.
34
+ # No default value.
35
+ EXTRA_PATH?=
36
+
37
+ # Path to Python project relative to Makefile (repository root).
38
+ # Leave empty if Python project is in the same directory as Makefile.
39
+ # For monorepo setups, set to subdirectory name (e.g., `backend`).
40
+ # Future-proofed for multi-language monorepos (e.g., PROJECT_PATH_NODEJS).
41
+ # No default value.
42
+ PROJECT_PATH_PYTHON?=
43
+
44
+ ## core.mxenv
45
+
46
+ # Primary Python interpreter to use. It is used to create the
47
+ # virtual environment if `VENV_ENABLED` and `VENV_CREATE` are set to `true`.
48
+ # If global `uv` is used, this value is passed as `--python VALUE` to the venv creation.
49
+ # uv then downloads the Python interpreter if it is not available.
50
+ # for more on this feature read the [uv python documentation](https://docs.astral.sh/uv/concepts/python-versions/)
51
+ # Default: python3
52
+ PRIMARY_PYTHON?=3.13
53
+
54
+ # Minimum required Python version.
55
+ # Default: 3.10
56
+ PYTHON_MIN_VERSION?=3.13
57
+
58
+ # Install packages using the given package installer method.
59
+ # Supported are `pip` and `uv`. When `uv` is selected, a global installation
60
+ # is auto-detected and used if available. Otherwise, uv is installed in the
61
+ # virtual environment or using `PRIMARY_PYTHON`, depending on the
62
+ # `VENV_ENABLED` setting.
63
+ # Default: pip
64
+ PYTHON_PACKAGE_INSTALLER?=uv
65
+
66
+ # Python version for UV to install/use when creating virtual
67
+ # environments with global UV. Passed to `uv venv -p VALUE`. Supports version
68
+ # specs like `3.11`, `3.14`, `cpython@3.14`. Defaults to PRIMARY_PYTHON value
69
+ # for backward compatibility.
70
+ # Default: $(PRIMARY_PYTHON)
71
+ UV_PYTHON?=$(PRIMARY_PYTHON)
72
+
73
+ # Flag whether to use virtual environment. If `false`, the
74
+ # interpreter according to `PRIMARY_PYTHON` found in `PATH` is used.
75
+ # Default: true
76
+ VENV_ENABLED?=true
77
+
78
+ # Flag whether to create a virtual environment. If set to `false`
79
+ # and `VENV_ENABLED` is `true`, `VENV_FOLDER` is expected to point to an
80
+ # existing virtual environment.
81
+ # Default: true
82
+ VENV_CREATE?=true
83
+
84
+ # The folder of the virtual environment.
85
+ # If `VENV_ENABLED` is `true` and `VENV_CREATE` is true it is used as the
86
+ # target folder for the virtual environment. If `VENV_ENABLED` is `true` and
87
+ # `VENV_CREATE` is false it is expected to point to an existing virtual
88
+ # environment. If `VENV_ENABLED` is `false` it is ignored.
89
+ # Default: .venv
90
+ VENV_FOLDER?=.venv
91
+
92
+ # mxdev to install in virtual environment.
93
+ # Default: mxdev
94
+ MXDEV?=mxdev
95
+
96
+ # mxmake to install in virtual environment.
97
+ # Default: mxmake
98
+ MXMAKE?=mxmake
99
+
100
+ ## docs.sphinx
101
+
102
+ # Documentation source folder.
103
+ # Default: docs/source
104
+ DOCS_SOURCE_FOLDER?=sources
105
+
106
+ # Documentation generation target folder.
107
+ # Default: docs/html
108
+ DOCS_TARGET_FOLDER?=html
109
+
110
+ # Documentation linkcheck output folder.
111
+ # Default: docs/linkcheck
112
+ DOCS_LINKCHECK_FOLDER?=docs/linkcheck
113
+
114
+ # Documentation Python requirements to be installed (via pip).
115
+ # No default value.
116
+ DOCS_REQUIREMENTS?=myst_parser sphinxcontrib.mermaid shibuya sphinx-design sphinx-copybutton
117
+
118
+ ##############################################################################
119
+ # END SETTINGS - DO NOT EDIT BELOW THIS LINE
120
+ ##############################################################################
121
+
122
+ INSTALL_TARGETS?=
123
+ DIRTY_TARGETS?=
124
+ CLEAN_TARGETS?=
125
+ PURGE_TARGETS?=
126
+
127
+ export PATH:=$(if $(EXTRA_PATH),$(EXTRA_PATH):,)$(PATH)
128
+
129
+ # Helper variable: adds trailing slash to PROJECT_PATH_PYTHON only if non-empty
130
+ PYTHON_PROJECT_PREFIX=$(if $(PROJECT_PATH_PYTHON),$(PROJECT_PATH_PYTHON)/,)
131
+
132
+ # Defensive settings for make: https://tech.davis-hansson.com/p/make/
133
+ SHELL:=bash
134
+ .ONESHELL:
135
+ # for Makefile debugging purposes add -x to the .SHELLFLAGS
136
+ .SHELLFLAGS:=-eu -o pipefail -O inherit_errexit -c
137
+ .SILENT:
138
+ .DELETE_ON_ERROR:
139
+ MAKEFLAGS+=--warn-undefined-variables
140
+ MAKEFLAGS+=--no-builtin-rules
141
+
142
+ # mxmake folder
143
+ MXMAKE_FOLDER?=.mxmake
144
+
145
+ # Sentinel files
146
+ SENTINEL_FOLDER?=$(MXMAKE_FOLDER)/sentinels
147
+ SENTINEL?=$(SENTINEL_FOLDER)/about.txt
148
+ $(SENTINEL): $(firstword $(MAKEFILE_LIST))
149
+ @mkdir -p $(SENTINEL_FOLDER)
150
+ @echo "Sentinels for the Makefile process." > $(SENTINEL)
151
+
152
+ ##############################################################################
153
+ # mxenv
154
+ ##############################################################################
155
+
156
+ OS?=
157
+
158
+ # Determine the executable path
159
+ ifeq ("$(VENV_ENABLED)", "true")
160
+ export VIRTUAL_ENV=$(abspath $(VENV_FOLDER))
161
+ ifeq ("$(OS)", "Windows_NT")
162
+ VENV_EXECUTABLE_FOLDER=$(VIRTUAL_ENV)/Scripts
163
+ else
164
+ VENV_EXECUTABLE_FOLDER=$(VIRTUAL_ENV)/bin
165
+ endif
166
+ export PATH:=$(VENV_EXECUTABLE_FOLDER):$(PATH)
167
+ MXENV_PYTHON=python
168
+ else
169
+ MXENV_PYTHON=$(PRIMARY_PYTHON)
170
+ endif
171
+
172
+ # Determine the package installer with non-interactive flags
173
+ ifeq ("$(PYTHON_PACKAGE_INSTALLER)","uv")
174
+ PYTHON_PACKAGE_COMMAND=uv pip --no-progress
175
+ else
176
+ PYTHON_PACKAGE_COMMAND=$(MXENV_PYTHON) -m pip
177
+ endif
178
+
179
+ # Auto-detect global uv availability (simple existence check)
180
+ ifeq ("$(PYTHON_PACKAGE_INSTALLER)","uv")
181
+ UV_AVAILABLE:=$(shell command -v uv >/dev/null 2>&1 && echo "true" || echo "false")
182
+ else
183
+ UV_AVAILABLE:=false
184
+ endif
185
+
186
+ # Determine installation strategy
187
+ # depending on the PYTHON_PACKAGE_INSTALLER and UV_AVAILABLE
188
+ # - both vars can be false or
189
+ # - one of them can be true,
190
+ # - but never boths.
191
+ USE_GLOBAL_UV:=$(shell [[ "$(PYTHON_PACKAGE_INSTALLER)" == "uv" && "$(UV_AVAILABLE)" == "true" ]] && echo "true" || echo "false")
192
+ USE_LOCAL_UV:=$(shell [[ "$(PYTHON_PACKAGE_INSTALLER)" == "uv" && "$(UV_AVAILABLE)" == "false" ]] && echo "true" || echo "false")
193
+
194
+ # Check if global UV is outdated (non-blocking warning)
195
+ ifeq ("$(USE_GLOBAL_UV)","true")
196
+ UV_OUTDATED:=$(shell uv self update --dry-run 2>&1 | grep -q "Would update" && echo "true" || echo "false")
197
+ else
198
+ UV_OUTDATED:=false
199
+ endif
200
+
201
+ MXENV_TARGET:=$(SENTINEL_FOLDER)/mxenv.sentinel
202
+ $(MXENV_TARGET): $(SENTINEL)
203
+ # Validation: Check Python version if not using global uv
204
+ ifneq ("$(USE_GLOBAL_UV)","true")
205
+ @$(PRIMARY_PYTHON) -c "import sys; vi = sys.version_info; sys.exit(1 if (int(vi[0]), int(vi[1])) >= tuple(map(int, '$(PYTHON_MIN_VERSION)'.split('.'))) else 0)" \
206
+ && echo "Need Python >= $(PYTHON_MIN_VERSION)" && exit 1 || :
207
+ else
208
+ @echo "Using global uv for Python $(UV_PYTHON)"
209
+ endif
210
+ # Validation: Check VENV_FOLDER is set if venv enabled
211
+ @[[ "$(VENV_ENABLED)" == "true" && "$(VENV_FOLDER)" == "" ]] \
212
+ && echo "VENV_FOLDER must be configured if VENV_ENABLED is true" && exit 1 || :
213
+ # Validation: Check uv not used with system Python
214
+ @[[ "$(VENV_ENABLED)" == "false" && "$(PYTHON_PACKAGE_INSTALLER)" == "uv" ]] \
215
+ && echo "Package installer uv does not work with a global Python interpreter." && exit 1 || :
216
+ # Warning: Notify if global UV is outdated
217
+ ifeq ("$(UV_OUTDATED)","true")
218
+ @echo "WARNING: A newer version of uv is available. Run 'uv self update' to upgrade."
219
+ endif
220
+
221
+ # Create virtual environment
222
+ ifeq ("$(VENV_ENABLED)", "true")
223
+ ifeq ("$(VENV_CREATE)", "true")
224
+ ifeq ("$(USE_GLOBAL_UV)","true")
225
+ @echo "Setup Python Virtual Environment using global uv at '$(VENV_FOLDER)'"
226
+ @uv venv --allow-existing --no-progress -p $(UV_PYTHON) --seed $(VENV_FOLDER)
227
+ else
228
+ @echo "Setup Python Virtual Environment using module 'venv' at '$(VENV_FOLDER)'"
229
+ @$(PRIMARY_PYTHON) -m venv $(VENV_FOLDER)
230
+ @$(MXENV_PYTHON) -m ensurepip -U
231
+ endif
232
+ endif
233
+ else
234
+ @echo "Using system Python interpreter"
235
+ endif
236
+
237
+ # Install uv locally if needed
238
+ ifeq ("$(USE_LOCAL_UV)","true")
239
+ @echo "Install uv in virtual environment"
240
+ @$(MXENV_PYTHON) -m pip install uv
241
+ endif
242
+
243
+ # Install/upgrade core packages
244
+ @$(PYTHON_PACKAGE_COMMAND) install -U pip setuptools wheel
245
+ @echo "Install/Update MXStack Python packages"
246
+ @$(PYTHON_PACKAGE_COMMAND) install -U $(MXDEV) $(MXMAKE)
247
+ @touch $(MXENV_TARGET)
248
+
249
+ .PHONY: mxenv
250
+ mxenv: $(MXENV_TARGET)
251
+
252
+ .PHONY: mxenv-dirty
253
+ mxenv-dirty:
254
+ @rm -f $(MXENV_TARGET)
255
+
256
+ .PHONY: mxenv-clean
257
+ mxenv-clean: mxenv-dirty
258
+ ifeq ("$(VENV_ENABLED)", "true")
259
+ ifeq ("$(VENV_CREATE)", "true")
260
+ @rm -rf $(VENV_FOLDER)
261
+ endif
262
+ else
263
+ @$(PYTHON_PACKAGE_COMMAND) uninstall -y $(MXDEV)
264
+ @$(PYTHON_PACKAGE_COMMAND) uninstall -y $(MXMAKE)
265
+ endif
266
+
267
+ INSTALL_TARGETS+=mxenv
268
+ DIRTY_TARGETS+=mxenv-dirty
269
+ CLEAN_TARGETS+=mxenv-clean
270
+
271
+ ##############################################################################
272
+ # sphinx
273
+ ##############################################################################
274
+
275
+ # additional targets required for building docs.
276
+ DOCS_TARGETS+=
277
+
278
+ SPHINX_BIN=sphinx-build
279
+ SPHINX_AUTOBUILD_BIN=sphinx-autobuild
280
+
281
+ DOCS_TARGET:=$(SENTINEL_FOLDER)/sphinx.sentinel
282
+ $(DOCS_TARGET): $(MXENV_TARGET)
283
+ @echo "Install Sphinx"
284
+ @$(PYTHON_PACKAGE_COMMAND) install -U sphinx sphinx-autobuild $(DOCS_REQUIREMENTS)
285
+ @touch $(DOCS_TARGET)
286
+
287
+ .PHONY: docs
288
+ docs: $(DOCS_TARGET) $(DOCS_TARGETS)
289
+ @echo "Build sphinx docs"
290
+ @$(SPHINX_BIN) $(DOCS_SOURCE_FOLDER) $(DOCS_TARGET_FOLDER)
291
+
292
+ .PHONY: docs-live
293
+ docs-live: $(DOCS_TARGET) $(DOCS_TARGETS)
294
+ @echo "Rebuild Sphinx documentation on changes, with live-reload in the browser"
295
+ @$(SPHINX_AUTOBUILD_BIN) $(DOCS_SOURCE_FOLDER) $(DOCS_TARGET_FOLDER)
296
+
297
+ .PHONY: docs-linkcheck
298
+ docs-linkcheck: $(DOCS_TARGET) $(DOCS_TARGETS)
299
+ @echo "Run Sphinx linkcheck"
300
+ @$(SPHINX_BIN) -b linkcheck $(DOCS_SOURCE_FOLDER) $(DOCS_LINKCHECK_FOLDER)
301
+
302
+ .PHONY: docs-dirty
303
+ docs-dirty:
304
+ @rm -f $(DOCS_TARGET)
305
+
306
+ .PHONY: docs-clean
307
+ docs-clean: docs-dirty
308
+ @test -e $(MXENV_PYTHON) && $(MXENV_PYTHON) -m pip uninstall -y \
309
+ sphinx sphinx-autobuild $(DOCS_REQUIREMENTS) || :
310
+ @rm -rf $(DOCS_TARGET_FOLDER)
311
+
312
+ INSTALL_TARGETS+=$(DOCS_TARGET)
313
+ DIRTY_TARGETS+=docs-dirty
314
+ CLEAN_TARGETS+=docs-clean
315
+
316
+ ##############################################################################
317
+ # Custom includes
318
+ ##############################################################################
319
+
320
+ -include $(INCLUDE_MAKEFILE)
321
+
322
+ ##############################################################################
323
+ # Default targets
324
+ ##############################################################################
325
+
326
+ INSTALL_TARGET:=$(SENTINEL_FOLDER)/install.sentinel
327
+ $(INSTALL_TARGET): $(INSTALL_TARGETS)
328
+ @touch $(INSTALL_TARGET)
329
+
330
+ .PHONY: install
331
+ install: $(INSTALL_TARGET)
332
+ @touch $(INSTALL_TARGET)
333
+
334
+ .PHONY: run
335
+ run: $(RUN_TARGET)
336
+
337
+ .PHONY: deploy
338
+ deploy: $(DEPLOY_TARGETS)
339
+
340
+ .PHONY: dirty
341
+ dirty: $(DIRTY_TARGETS)
342
+ @rm -f $(INSTALL_TARGET)
343
+
344
+ .PHONY: clean
345
+ clean: dirty $(CLEAN_TARGETS)
346
+ @rm -rf $(CLEAN_TARGETS) $(MXMAKE_FOLDER) $(CLEAN_FS)
347
+
348
+ .PHONY: purge
349
+ purge: clean $(PURGE_TARGETS)
350
+
351
+ .PHONY: runtime-clean
352
+ runtime-clean:
353
+ @echo "Remove runtime artifacts, like byte-code and caches."
354
+ @find . -name '*.py[c|o]' -delete
355
+ @find . -name '*~' -exec rm -f {} +
356
+ @find . -name '__pycache__' -exec rm -fr {} +
357
+