From d6e3d37d34cdbda4f28c00836bc7c9991ae9b004 Mon Sep 17 00:00:00 2001 From: Don Kendall Date: Wed, 13 May 2026 16:38:20 -0400 Subject: [PATCH 1/2] ci(test-migration): fetch test DBs from OCA upstream releases The test-migration workflow uses ${{github.repository}}/releases/download/databases to fetch the 18.0.psql test fixture, which means forks have to mirror the multi-GB DB dumps from OCA into their own releases just to run CI. Pin the download URL to OCA/OpenUpgrade's releases regardless of where the workflow runs. Forks can keep using the OCA-provided fixtures and contributions can be tested without preparation. --- .github/workflows/test-migration.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-migration.yml b/.github/workflows/test-migration.yml index bc425add5de4..e73dc53db842 100644 --- a/.github/workflows/test-migration.yml +++ b/.github/workflows/test-migration.yml @@ -23,7 +23,9 @@ jobs: DB_PASSWORD: "odoo" DB_PORT: 5432 DB_USERNAME: "odoo" - DOWNLOADS: https://github.com/${{github.repository}}/releases/download/databases + # Test databases live only on OCA upstream; forks reuse them so we + # don't have to mirror multi-GB psql dumps. + DOWNLOADS: https://github.com/OCA/OpenUpgrade/releases/download/databases ODOO: "./odoo/odoo-bin" PGHOST: "localhost" PGPASSWORD: "odoo" From 08c7b526e10650944320ff6763fa180bc1612b88 Mon Sep 17 00:00:00 2001 From: Don Kendall Date: Wed, 13 May 2026 16:22:46 -0400 Subject: [PATCH 2/2] [19.0][FIX] base: rename user.groups_id references in domain/code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `rename_fields()` (via `rename_field_references` in openupgradelib) renames the field column and quoted occurrences in ir.filters.domain, but it doesn't process: * ir.rule.domain_force (not touched at all) * unquoted dotted references like `user.groups_id.ids` in Python expressions inside domain_force / ir.filters.domain / ir.act_server.code Concretely, an ir.rule with domain_force = "[('groups_id', 'in', user.groups_id.ids)]" has its LHS migrated to `'group_ids'` but the RHS is left untouched, which then crashes any view that triggers the rule with AttributeError: 'res.users' object has no attribute 'groups_id' Add a post-step in base/19.0.1.3 pre-migration that does a word-boundary regex_replace of `user.groups_id` → `user.group_ids` in: * ir_rule.domain_force * ir_filters.domain * ir_act_server.code Reproduced migrating a real prod 18.0 database (Ledo Enterprises) to 19.0: the login page returned HTTP 500 with the AttributeError until the ir.rule for `Website menu: group_ids` was patched manually. --- .../scripts/base/19.0.1.3/pre-migration.py | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/openupgrade_scripts/scripts/base/19.0.1.3/pre-migration.py b/openupgrade_scripts/scripts/base/19.0.1.3/pre-migration.py index 39b145615b4b..699de5d46ed7 100644 --- a/openupgrade_scripts/scripts/base/19.0.1.3/pre-migration.py +++ b/openupgrade_scripts/scripts/base/19.0.1.3/pre-migration.py @@ -176,3 +176,48 @@ def migrate(env, version): openupgrade.rename_xmlids(env.cr, _renamed_xmlids) openupgrade.rename_xmlids(env.cr, _merged_xmlids, allow_merge=True) openupgrade.rename_fields(env, _renamed_fields) + _fix_user_groups_id_references(env) + + +def _fix_user_groups_id_references(env): + """rename_fields() renames the field column on res_users and quoted + references in ir.filters.domain, but it does not process ir.rule + domain_force, nor does it match unquoted dotted references like + ``user.groups_id.ids`` in Python-evaluated domain expressions. + + Concretely, an ir.rule with + domain_force = "[('groups_id', 'in', user.groups_id.ids)]" + has its LHS migrated to 'group_ids' but the RHS is left untouched, + so any view referencing the rule crashes at runtime with + ``AttributeError: 'res.users' object has no attribute 'groups_id'``. + """ + openupgrade.logged_query( + env.cr, + r""" + UPDATE ir_rule + SET domain_force = regexp_replace( + domain_force, '\muser\.groups_id\M', 'user.group_ids', 'g' + ) + WHERE domain_force ~ '\muser\.groups_id\M' + """, + ) + openupgrade.logged_query( + env.cr, + r""" + UPDATE ir_filters + SET domain = regexp_replace( + domain, '\muser\.groups_id\M', 'user.group_ids', 'g' + ) + WHERE domain ~ '\muser\.groups_id\M' + """, + ) + openupgrade.logged_query( + env.cr, + r""" + UPDATE ir_act_server + SET code = regexp_replace( + code, '\muser\.groups_id\M', 'user.group_ids', 'g' + ) + WHERE code ~ '\muser\.groups_id\M' + """, + )