fix(hoot-dom): platform shim addon to inject hoot-dom into web.assets_backend

This commit is contained in:
OdooSky v3
2026-05-08 23:26:52 +02:00
parent 96785158e7
commit 44a6972b44
2 changed files with 94 additions and 12 deletions

View File

@@ -5,7 +5,7 @@ description: |
Variation between instances is expressed via values.yaml only. Variation between instances is expressed via values.yaml only.
No chart variants. No string-templating in Tower. No chart variants. No string-templating in Tower.
type: application type: application
version: 0.1.1 version: 0.1.2
appVersion: "1.0" appVersion: "1.0"
keywords: keywords:
- odoo - odoo

View File

@@ -91,6 +91,56 @@ spec:
volumeMounts: volumeMounts:
- name: filestore - name: filestore
mountPath: /var/lib/odoo mountPath: /var/lib/odoo
# platform-shim: workaround for upstream Odoo manifest bug.
# Materializes a tiny addon (`odoosky_hoot_dom_shim`) into the
# shared addons volume; the addon injects
# `web/static/lib/hoot-dom/**/*` into the `web.assets_backend`
# bundle.
#
# Why: Odoo 18.0 nightlies (verified through 2026-05-08)
# include production source files
# (`barcodes/static/src/barcode_handlers.js`,
# `web_tour/.../tour_step_automatic.js`,
# `sale/.../tour_utils.js`) that `import '@odoo/hoot-dom'`,
# but the upstream `web/__manifest__.py` only places the
# hoot-dom library in `web.assets_unit_tests_setup` (the test
# bundle). Production bundle ends up with dangling references
# and the browser fails to bootstrap. erp18 incident
# 2026-05-08 — surfaced after a heavy addon install pulled
# barcode_handlers.js into the active backend bundle.
#
# Remove this initContainer (and the shim install step in
# db-init) once upstream patches the manifest.
- name: platform-shim
image: {{ include "instance.odooImage" . | quote }}
imagePullPolicy: IfNotPresent
command: ["/bin/sh", "-c"]
args:
- |
set -eu
mkdir -p /target/odoosky_hoot_dom_shim
: > /target/odoosky_hoot_dom_shim/__init__.py
cat > /target/odoosky_hoot_dom_shim/__manifest__.py <<'PYEOF'
{
'name': 'OdooSky hoot-dom backend shim',
'version': '18.0.1.0.0',
'category': 'Hidden',
'summary': 'Inject web/static/lib/hoot-dom/**/* into web.assets_backend (workaround for upstream manifest bug)',
'depends': ['web'],
'assets': {
'web.assets_backend': [
'web/static/lib/hoot-dom/**/*',
],
},
'installable': True,
'auto_install': True,
'license': 'LGPL-3',
}
PYEOF
echo "── platform shim materialized at /target/odoosky_hoot_dom_shim ──"
volumeMounts:
- name: addons
mountPath: /target
# db-init: idempotent on every pod boot. # db-init: idempotent on every pod boot.
# 1. createdb if missing (PG-level) # 1. createdb if missing (PG-level)
# 2. odoo -i base --stop-after-init to install base module # 2. odoo -i base --stop-after-init to install base module
@@ -182,6 +232,30 @@ spec:
--db_host="$HOST" --db_port="$PORT" --db_user="$USER" --db_password="$PASSWORD" \ --db_host="$HOST" --db_port="$PORT" --db_user="$USER" --db_password="$PASSWORD" \
--workers=0 --workers=0
fi fi
# Install the platform-shim addon if not already
# installed. The shim's files were materialized into
# the addons volume by the platform-shim initContainer
# above; here we just register them in this DB. Once
# registered, Odoo's asset machinery emits an ir.asset
# row that adds web/static/lib/hoot-dom/**/* to the
# web.assets_backend bundle on next regeneration. See
# platform-shim initContainer for the why.
SHIM_INSTALLED=""
IS_INIT_AFTER=$(PGPASSWORD="$PASSWORD" psql -h "$HOST" -p "$PORT" -U "$USER" -d "$DBNAME" -tAc \
"SELECT 1 FROM information_schema.tables WHERE table_schema='public' AND table_name='ir_module_module'" 2>/dev/null || true)
if [ "$IS_INIT_AFTER" = "1" ]; then
SHIM_INSTALLED=$(PGPASSWORD="$PASSWORD" psql -h "$HOST" -p "$PORT" -U "$USER" -d "$DBNAME" -tAc \
"SELECT 1 FROM ir_module_module WHERE name='odoosky_hoot_dom_shim' AND state='installed'" 2>/dev/null || true)
fi
if [ "$SHIM_INSTALLED" = "1" ]; then
echo "── odoosky_hoot_dom_shim already installed — skipping ──"
else
echo "── installing odoosky_hoot_dom_shim (hoot-dom workaround) ──"
odoo -i odoosky_hoot_dom_shim -d "$DBNAME" --stop-after-init --no-http \
--db_host="$HOST" --db_port="$PORT" --db_user="$USER" --db_password="$PASSWORD" \
--workers=0 \
--addons-path="/usr/lib/python3/dist-packages/odoo/addons,{{ .Values.addonsMountPath }}"
fi
echo "── db-init done ──" echo "── db-init done ──"
env: env:
- name: HOST - name: HOST
@@ -198,6 +272,14 @@ spec:
secretKeyRef: secretKeyRef:
name: {{ include "instance.fullname" . }}-pg name: {{ include "instance.fullname" . }}-pg
key: POSTGRES_PASSWORD key: POSTGRES_PASSWORD
volumeMounts:
# db-init reads the platform-shim addon from this mount
# to install it via `odoo -i odoosky_hoot_dom_shim`. The
# mount is unconditional because the shim is unconditional;
# any tenant addon images write here too if .Values.addons
# is non-empty.
- name: addons
mountPath: {{ .Values.addonsMountPath }}
{{- if .Values.addons }} {{- if .Values.addons }}
# One initContainer per selected addon. Each addon image's # One initContainer per selected addon. Each addon image's
# ENTRYPOINT/CMD copies its bundled content into /target/<code>, # ENTRYPOINT/CMD copies its bundled content into /target/<code>,
@@ -243,9 +325,11 @@ spec:
- "-d" - "-d"
- "{{ .Values.instance.code }}" - "{{ .Values.instance.code }}"
- "--db-filter=^{{ .Values.instance.code }}$" - "--db-filter=^{{ .Values.instance.code }}$"
{{- if .Values.addons }} # addons-path always includes the shared addons mount —
# the platform-shim addon lives there even when the
# tenant has no extra addons. See platform-shim
# initContainer.
- "--addons-path=/usr/lib/python3/dist-packages/odoo/addons,{{ .Values.addonsMountPath }}" - "--addons-path=/usr/lib/python3/dist-packages/odoo/addons,{{ .Values.addonsMountPath }}"
{{- end }}
ports: ports:
- name: http - name: http
containerPort: 8069 containerPort: 8069
@@ -278,11 +362,11 @@ spec:
volumeMounts: volumeMounts:
- name: filestore - name: filestore
mountPath: /var/lib/odoo mountPath: /var/lib/odoo
{{- if .Values.addons }} # addons mount is always present — at minimum it carries
# the platform-shim addon (see platform-shim initContainer).
- name: addons - name: addons
mountPath: {{ .Values.addonsMountPath }} mountPath: {{ .Values.addonsMountPath }}
readOnly: true readOnly: true
{{- end }}
resources: resources:
{{- include "instance.resources" (dict "Values" .Values "role" "odoo") | nindent 12 }} {{- include "instance.resources" (dict "Values" .Values "role" "odoo") | nindent 12 }}
# /web/login is the most stable health endpoint across Odoo # /web/login is the most stable health endpoint across Odoo
@@ -314,12 +398,10 @@ spec:
- name: filestore - name: filestore
persistentVolumeClaim: persistentVolumeClaim:
claimName: {{ include "instance.fullname" . }}-odoo claimName: {{ include "instance.fullname" . }}-odoo
{{- if .Values.addons }} # Shared scratch volume that init containers populate. Always
# Shared scratch volume that init containers populate with # created — at minimum the platform-shim initContainer drops
# addon content. emptyDir is fine — the source of truth is # `odoosky_hoot_dom_shim` here. emptyDir is fine — source of
# the registry's images; if the volume is wiped (pod # truth is the registry's images / hardcoded shim; if the
# recreate) the init containers re-materialize from the # volume is wiped (pod recreate) initContainers re-materialize.
# cached images.
- name: addons - name: addons
emptyDir: {} emptyDir: {}
{{- end }}