Work in Progress

This commit is contained in:
Sylvain LE GAL 2022-03-25 21:36:17 +01:00
parent d64140487f
commit e81e22e91b
16 changed files with 1080 additions and 559 deletions

BIN
.coverage Normal file

Binary file not shown.

7
.gitignore vendored
View File

@ -1,2 +1,7 @@
env env
__pycache__ __pycache__
.tox
.coverage
.pytest_cache
/tests/output/*
log/

61
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,61 @@
---
image: python
cache:
key: one-key-to-rule-them-all
paths:
- .venv
stages:
- prepare
- linting
- tests
install_tools:
stage: prepare
script:
- python -m venv .venv
- source .venv/bin/activate
- pip install poetry
- poetry --version
- poetry install -v
- echo $PATH
- echo $PYTHONPATH
black:
stage: linting
script:
- source .venv/bin/activate
- pip install black
- black --version
- black --check .
pylint:
stage: linting
script:
- source .venv/bin/activate
- pylint --version
# - pylint --disable fixme ociedoo
# - pylint --disable fixme tests
pytest:
stage: tests
image: python
cache: {}
script:
- pip install poetry
- poetry --version
- poetry install -v
- poetry run pytest --version
- poetry run pytest --cov odoo_openupgrade_wizard -v
tox:
stage: tests
image: themattrix/tox
cache: {}
script:
- pip install poetry tox
- tox --version
- poetry --version
- tox

36
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,36 @@
---
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: debug-statements
- id: mixed-line-ending
- id: name-tests-test
- id: check-yaml
- id: check-json
- id: check-toml
- id: check-added-large-files
args: ['--maxkb=2048']
- id: check-docstring-first
- id: check-merge-conflict
- id: check-symlinks
- repo: https://github.com/pre-commit/mirrors-isort
rev: v5.7.0
hooks:
- id: isort
- repo: https://github.com/psf/black
rev: 20.8b1
hooks:
- id: black
- repo: https://github.com/PyCQA/flake8
rev: "3.9.2"
hooks:
- id: flake8
# - repo: https://gitlab.com/smop/pre-commit-hooks
# rev: v1.0.0
# hooks:
# - id: check-gitlab-ci

View File

@ -1,9 +1,82 @@
# odoo-openupgrade-wizard # odoo-openupgrade-wizard
Odoo Openupgrade Wizard is a tool that helps developpers to make major
upgrade of Odoo Community Edition. (formely OpenERP).
It works with Openupgrade OCA tools. (https://github.com/oca/openupgrade)
this tool is useful for complex migrations:
- skip several versions
- complex custom code
It will create a migration environment (with all the code available)
and provides helpers to run (and replay) migrations until it works.
## Commands
### ``odoo-openupgrade-wizard init``
```
odoo-openupgrade-wizard init\
--initial-version=10.0\
--final-version=12.0\
--extra-repository=OCA/web,OCA/server-tools
```
Initialize a folder to make a migration from a 10.0 and a 12.0 database.
This will generate the following structure :
```
config.yml
log/
2022_03_25__23_12_41__init.log
...
repos/
10.0.yml
11.0.yml
12.0.yml
requirements/
10.0_requirements.txt
11.0_requirements.txt
12.0_requirements.txt
scripts/
step_1__update__10.0/
pre-migration.sql
post-migration.py
step_2__upgrade__11.0/
pre-migration.sql
post-migration.py
step_2__upgrade__12.0/
pre-migration.sql
post-migration.py
step_4__update__12.0/
pre-migration.sql
post-migration.py
src/
```
* ``log/`` will contains all the log of the ``odoo-openupgrade-wizard``
and the logs of the odoo instance that will be executed.
* ``repos/`` contains a file per version of odoo, that enumerates the
list of the repositories to use to run each odoo instance.
The syntax should respect the ``gitaggregate`` command.
(See : https://pypi.org/project/git-aggregator/)
Repo files are pre-generated. You can update them with your custom settings.
(custom branches, extra PRs, git shallow options, etc...)
* ``requirements/`` contains a file per version of odoo, that enumerates the
list of extra python librairies required to run each odoo instance.
The syntax should respect the ``pip install -r`` command.
(See : https://pip.pypa.io/en/stable/reference/requirements-file-format/)
* ``scripts`` contains a folder per migration step. In each step folder:
- ``pre-migration.sql`` can contains extra SQL queries you want to execute
before beginning the step.
- ``post-migration.py`` can contains extra python command to execute
after the execution of the step. (the orm will be available)
# TODO # TODO
* restore ``# @click.version_option(version=ociedoo.__version__)`` when we know how * with coop it easy :
to avoid to duplicate information in ``pyproject.toml`` file and ``__init__.py`` file. - short_help of group decorator ? seems useless...
* move jinja2 templates files into dedicated files.

View File

@ -0,0 +1,5 @@
from pathlib import Path
from single_source import get_version
__version__ = get_version(__name__, Path(__file__).parent.parent)

View File

@ -1,47 +1,45 @@
import datetime import datetime
# import os
# import signal
# import subprocess
# import time
from pathlib import Path from pathlib import Path
from plumbum.cmd import mkdir
from jinja2 import Template
import time
import click import click
import yaml
from loguru import logger from loguru import logger
from plumbum.cmd import mkdir
import odoo_openupgrade_wizard import odoo_openupgrade_wizard
from odoo_openupgrade_wizard.configuration_version_dependant import ( from odoo_openupgrade_wizard.cli_build import build
_get_odoo_version_str_list, from odoo_openupgrade_wizard.cli_init import init
_get_odoo_versions,
)
from odoo_openupgrade_wizard.templates import (
_CONFIG_YML_TEMPLATE,
_REPO_YML_TEMPLATE,
_REQUIREMENTS_TXT_TEMPLATE,
_PRE_MIGRATION_SQL_TEMPLATE,
_POST_MIGRATION_PY_TEMPLATE,
)
# ############################################################################
# main() @click.group()
# ############################################################################ @click.version_option(version=odoo_openupgrade_wizard.__version__)
@click.group( @click.option(
short_help="Provide a wizard to simplify the use of OpenUpgrade.", "-ef",
"--env-folder",
default="./",
type=click.Path(
exists=True,
dir_okay=True,
file_okay=False,
writable=True,
resolve_path=True,
),
help="Folder that will contains all the configuration of the wizard"
" and all the Odoo code required to make the migrations. Let empty to"
" use current folder (./).",
)
@click.option(
"-fs",
"--filestore-folder",
type=click.Path(dir_okay=True, file_okay=False, resolve_path=True),
help="Folder that contains the Odoo filestore of the database(s)"
" to migrate. Let empty to use the subfolder 'filestore' of the"
" environment folder.",
) )
@click.option("-ef", "--env-folder", required=True,
type=click.Path(exists=True, dir_okay=True, file_okay=False, writable=True,
resolve_path=True))
@click.option("-fs", "--filestore-folder",
type=click.Path(dir_okay=True, file_okay=False,
resolve_path=True))
@click.pass_context @click.pass_context
def main(ctx, env_folder, filestore_folder): def main(ctx, env_folder, filestore_folder):
""" """
TODO Provides a command set to perform odoo Community Edition migrations.
""" """
date_begin = datetime.datetime.now() date_begin = datetime.datetime.now()
logger.debug("Beginning script '%s' ..." % (ctx.invoked_subcommand)) logger.debug("Beginning script '%s' ..." % (ctx.invoked_subcommand))
@ -72,8 +70,11 @@ def main(ctx, env_folder, filestore_folder):
mkdir(["--mode", "777", log_folder_path]) mkdir(["--mode", "777", log_folder_path])
# Create log file # Create log file
log_file_path = log_folder_path / Path("{}__{}.log".format( log_file_path = log_folder_path / Path(
date_begin.strftime("%Y_%m_%d__%H_%M_%S"), ctx.invoked_subcommand)) "{}__{}.log".format(
date_begin.strftime("%Y_%m_%d__%H_%M_%S"), ctx.invoked_subcommand
)
)
logger.add(log_file_path) logger.add(log_file_path)
ctx.obj["env_folder_path"] = env_folder_path ctx.obj["env_folder_path"] = env_folder_path
ctx.obj["src_folder_path"] = src_folder_path ctx.obj["src_folder_path"] = src_folder_path
@ -82,133 +83,18 @@ def main(ctx, env_folder, filestore_folder):
ctx.obj["filestore_folder_path"] = filestore_folder_path ctx.obj["filestore_folder_path"] = filestore_folder_path
ctx.obj["config_file_path"] = config_file_path ctx.obj["config_file_path"] = config_file_path
ctx.obj["requirement_folder_path"] = requirement_folder_path ctx.obj["requirement_folder_path"] = requirement_folder_path
# logger.info(ctx.obj)
if config_file_path.exists():
with open(config_file_path) as file:
config = yaml.safe_load(file)
for step in config["migration_steps"]:
step["local_path"] = src_folder_path / Path(
"env_%s" % step["version"]
)
ctx.obj["config"] = config
elif ctx.invoked_subcommand != "init":
raise
# ############################################################################ main.add_command(init)
# init() main.add_command(build)
# ############################################################################
@main.command(
short_help="Initialize OpenUpgrade Wizard Environment.",
)
@click.option("-iv", "--initial-version", required=True, prompt=True,
type=click.Choice(_get_odoo_version_str_list("initial")))
@click.option("-fv", "--final-version", required=True, prompt=True,
type=click.Choice(_get_odoo_version_str_list("final")))
@click.option("-er", "--extra-repository", "extra_repository_list",
# TODO, add a callback to check the quality of the argument
help="Coma separated extra repositories to use in the odoo environment."
"Ex: 'OCA/web,OCA/server-tools,GRAP/grap-odoo-incubator'")
@click.pass_context
def init(ctx, initial_version, final_version, extra_repository_list):
"""
TODO
"""
# 1. create src directory if not exists
if not ctx.obj["src_folder_path"].exists():
logger.info("Creating folder '%s' ..." % (ctx.obj["src_folder_path"]))
mkdir(["--mode", "777", ctx.obj["src_folder_path"]])
# 2. create filestore directory if not exists
if not ctx.obj["filestore_folder_path"].exists():
logger.info("Creating folder '%s' ..." % (ctx.obj["filestore_folder_path"]))
mkdir(["--mode", "777", ctx.obj["filestore_folder_path"]])
# 3. Create main config file
series = _get_odoo_versions(float(initial_version), float(final_version))
# Create initial first step
steps = [series[0].copy()]
steps[0].update({
"name": "step_1",
"action": "update",
"complete_name": "step_1__update__%s" % (steps[0]["version"]),
})
# Add all upgrade steps
count = 1
for serie in series[1:]:
steps.append(serie.copy())
steps[count].update({
"name": "step_%d" % (count+1),
"action": "upgrade",
"complete_name": "step_%d__upgrade__%s" % (count+1, serie["version"]),
})
count += 1
# add final update step
steps.append(series[-1].copy())
steps[-1].update({
"name": "step_%d" % (count + 1),
"action": "update",
"complete_name": "step_%d__update__%s" % (count+1, steps[-1]["version"]),
})
template = Template(_CONFIG_YML_TEMPLATE)
output = template.render(steps=steps)
with open(ctx.obj["config_file_path"], "w") as f:
logger.info("Creating configuration file '%s' ..." % (ctx.obj["config_file_path"]))
f.write(output)
f.close()
distinct_versions = list(set(x["version"] for x in series))
# 4. Create Repo folder and files
if not ctx.obj["repo_folder_path"].exists():
logger.info("Creating folder '%s' ..." % (ctx.obj["repo_folder_path"]))
mkdir([ctx.obj["repo_folder_path"]])
extra_repositories = extra_repository_list.split(",")
orgs = {x: [] for x in set([x.split("/")[0] for x in extra_repositories])}
for extra_repository in extra_repositories:
org, repo = extra_repository.split("/")
orgs[org].append(repo)
for version in distinct_versions:
template = Template(_REPO_YML_TEMPLATE)
output = template.render(version=version, orgs=orgs)
file_name =ctx.obj["repo_folder_path"] / Path("%s.yml" % (version))
with open(file_name, "w") as f:
logger.info("Creating Repo file '%s' ..." % (file_name))
f.write(output)
f.close()
# 5. Create Requirements folder and files
if not ctx.obj["requirement_folder_path"].exists():
logger.info("Creating folder '%s' ..." % (ctx.obj["requirement_folder_path"]))
mkdir([ctx.obj["requirement_folder_path"]])
for serie in series:
template = Template(_REQUIREMENTS_TXT_TEMPLATE)
output = template.render(python_libraries=serie["python_libraries"])
file_name =ctx.obj["requirement_folder_path"] / Path("%s_requirements.txt" % (serie["version"]))
with open(file_name, "w") as f:
logger.info("Creating Requirements file '%s' ..." % (file_name))
f.write(output)
f.close()
# 6. Create Scripts folder and files
if not ctx.obj["script_folder_path"].exists():
logger.info("Creating folder '%s' ..." % (ctx.obj["script_folder_path"]))
mkdir([ctx.obj["script_folder_path"]])
for step in steps:
step_path = ctx.obj["script_folder_path"] / step["complete_name"]
if not step_path.exists():
logger.info("Creating folder '%s' ..." % (step_path))
mkdir([step_path])
template = Template(_PRE_MIGRATION_SQL_TEMPLATE)
output = template.render()
file_name =step_path / Path("pre-migration.sql")
with open(file_name, "w") as f:
logger.info("Creating pre-migration.sql file '%s' ..." % (file_name))
f.write(output)
f.close()
template = Template(_POST_MIGRATION_PY_TEMPLATE)
output = template.render()
file_name =step_path / Path("post-migration.py")
with open(file_name, "w") as f:
logger.info("Creating post-migration.py file '%s' ..." % (file_name))
f.write(output)
f.close()

View File

@ -0,0 +1,28 @@
# from pathlib import Path
import click
from loguru import logger
from plumbum.cmd import mkdir
@click.command()
@click.pass_context
def build(ctx):
"""
Build OpenUpgrade Wizard Environment:
- gitaggregate all the repositories
- build virtualenv (TODO)
"""
# distinct_versions = list(set(x["version"] for x in series))
for step in ctx.obj["config"]["migration_steps"]:
# 1. Create main folder for the odoo version
if not step["local_path"].exists():
logger.info("Creating folder '%s' ..." % (step["local_path"]))
mkdir(["--mode", "777", step["local_path"]])
# # 2. gitaggregate source code
# repo_file = ctx.obj["repo_folder_path"] / Path(
# "%s.yml" % (step["version"])
# )

View File

@ -0,0 +1,180 @@
from pathlib import Path
import click
from jinja2 import Template
from loguru import logger
from plumbum.cmd import mkdir
from odoo_openupgrade_wizard.configuration_version_dependant import (
_get_odoo_version_str_list,
_get_odoo_versions,
)
from odoo_openupgrade_wizard.templates import (
_CONFIG_YML_TEMPLATE,
_POST_MIGRATION_PY_TEMPLATE,
_PRE_MIGRATION_SQL_TEMPLATE,
_REPO_YML_TEMPLATE,
_REQUIREMENTS_TXT_TEMPLATE,
)
@click.command()
@click.option(
"-iv",
"--initial-version",
required=True,
prompt=True,
type=click.Choice(_get_odoo_version_str_list("initial")),
)
@click.option(
"-fv",
"--final-version",
required=True,
prompt=True,
type=click.Choice(_get_odoo_version_str_list("final")),
)
@click.option(
"-er",
"--extra-repository",
"extra_repository_list",
# TODO, add a callback to check the quality of the argument
help="Coma separated extra repositories to use in the odoo environment."
"Ex: 'OCA/web,OCA/server-tools,GRAP/grap-odoo-incubator'",
)
@click.pass_context
def init(ctx, initial_version, final_version, extra_repository_list):
"""
Initialize OpenUpgrade Wizard Environment based on the initial and
the final version of Odoo you want to migrate.
"""
# 1. create src directory if not exists
if not ctx.obj["src_folder_path"].exists():
logger.info("Creating folder '%s' ..." % (ctx.obj["src_folder_path"]))
mkdir(["--mode", "777", ctx.obj["src_folder_path"]])
# 2. create filestore directory if not exists
if not ctx.obj["filestore_folder_path"].exists():
logger.info(
"Creating folder '%s' ..." % (ctx.obj["filestore_folder_path"])
)
mkdir(["--mode", "777", ctx.obj["filestore_folder_path"]])
# 3. Create main config file
series = _get_odoo_versions(float(initial_version), float(final_version))
# Create initial first step
steps = [series[0].copy()]
steps[0].update(
{
"name": "step_1",
"action": "update",
"complete_name": "step_1__update__%s" % (steps[0]["version"]),
}
)
# Add all upgrade steps
count = 1
for serie in series[1:]:
steps.append(serie.copy())
steps[count].update(
{
"name": "step_%d" % (count + 1),
"action": "upgrade",
"complete_name": "step_%d__upgrade__%s"
% (count + 1, serie["version"]),
}
)
count += 1
# add final update step
steps.append(series[-1].copy())
steps[-1].update(
{
"name": "step_%d" % (count + 1),
"action": "update",
"complete_name": "step_%d__update__%s"
% (count + 1, steps[-1]["version"]),
}
)
template = Template(_CONFIG_YML_TEMPLATE)
output = template.render(steps=steps)
with open(ctx.obj["config_file_path"], "w") as f:
logger.info(
"Creating configuration file '%s' ..."
% (ctx.obj["config_file_path"])
)
f.write(output)
f.close()
distinct_versions = list(set(x["version"] for x in series))
# 4. Create Repo folder and files
if not ctx.obj["repo_folder_path"].exists():
logger.info("Creating folder '%s' ..." % (ctx.obj["repo_folder_path"]))
mkdir([ctx.obj["repo_folder_path"]])
extra_repositories = extra_repository_list.split(",")
orgs = {x: [] for x in set([x.split("/")[0] for x in extra_repositories])}
for extra_repository in extra_repositories:
org, repo = extra_repository.split("/")
orgs[org].append(repo)
for version in distinct_versions:
template = Template(_REPO_YML_TEMPLATE)
output = template.render(version=version, orgs=orgs)
file_name = ctx.obj["repo_folder_path"] / Path("%s.yml" % (version))
with open(file_name, "w") as f:
logger.info("Creating Repo file '%s' ..." % (file_name))
f.write(output)
f.close()
# 5. Create Requirements folder and files
if not ctx.obj["requirement_folder_path"].exists():
logger.info(
"Creating folder '%s' ..." % (ctx.obj["requirement_folder_path"])
)
mkdir([ctx.obj["requirement_folder_path"]])
for serie in series:
template = Template(_REQUIREMENTS_TXT_TEMPLATE)
output = template.render(python_libraries=serie["python_libraries"])
file_name = ctx.obj["requirement_folder_path"] / Path(
"%s_requirements.txt" % (serie["version"])
)
with open(file_name, "w") as f:
logger.info("Creating Requirements file '%s' ..." % (file_name))
f.write(output)
f.close()
# 6. Create Scripts folder and files
if not ctx.obj["script_folder_path"].exists():
logger.info(
"Creating folder '%s' ..." % (ctx.obj["script_folder_path"])
)
mkdir([ctx.obj["script_folder_path"]])
for step in steps:
step_path = ctx.obj["script_folder_path"] / step["complete_name"]
if not step_path.exists():
logger.info("Creating folder '%s' ..." % (step_path))
mkdir([step_path])
template = Template(_PRE_MIGRATION_SQL_TEMPLATE)
output = template.render()
file_name = step_path / Path("pre-migration.sql")
with open(file_name, "w") as f:
logger.info(
"Creating pre-migration.sql file '%s' ..." % (file_name)
)
f.write(output)
f.close()
template = Template(_POST_MIGRATION_PY_TEMPLATE)
output = template.render()
file_name = step_path / Path("post-migration.py")
with open(file_name, "w") as f:
logger.info(
"Creating post-migration.py file '%s' ..." % (file_name)
)
f.write(output)
f.close()

View File

@ -2,19 +2,64 @@
# python version is defined, based on the OCA CI. # python version is defined, based on the OCA CI.
# https://github.com/OCA/oca-addons-repo-template/blob/master/src/.github/workflows/%7B%25%20if%20ci%20%3D%3D%20'GitHub'%20%25%7Dtest.yml%7B%25%20endif%20%25%7D.jinja # https://github.com/OCA/oca-addons-repo-template/blob/master/src/.github/workflows/%7B%25%20if%20ci%20%3D%3D%20'GitHub'%20%25%7Dtest.yml%7B%25%20endif%20%25%7D.jinja
_ODOO_SERIES = [ _ODOO_SERIES = [
{"version": 6.0, "python": "python2.7", "python_libraries": ["openupgradelib"]}, {
{"version": 6.1, "python": "python2.7", "python_libraries": ["openupgradelib"]}, "version": 6.0,
{"version": 7.0, "python": "python2.7", "python_libraries": ["openupgradelib"]}, "python": "python2.7",
{"version": 8.0, "python": "python2.7", "python_libraries": ["openupgradelib"]}, "python_libraries": ["openupgradelib"],
{"version": 9.0, "python": "python2.7", "python_libraries": ["openupgradelib"]}, },
{"version": 10.0, "python": "python2.7", "python_libraries": ["openupgradelib"]}, {
{"version": 11.0, "python": "python3.5", "python_libraries": ["openupgradelib"]}, "version": 6.1,
{"version": 12.0, "python": "python3.6", "python_libraries": ["openupgradelib"]}, "python": "python2.7",
{"version": 13.0, "python": "python3.6", "python_libraries": ["openupgradelib"]}, "python_libraries": ["openupgradelib"],
{"version": 14.0, "python": "python3.6", "python_libraries": ["openupgradelib"]}, },
{"version": 15.0, "python": "python3.8", "python_libraries": ["openupgradelib"]}, {
"version": 7.0,
"python": "python2.7",
"python_libraries": ["openupgradelib"],
},
{
"version": 8.0,
"python": "python2.7",
"python_libraries": ["openupgradelib"],
},
{
"version": 9.0,
"python": "python2.7",
"python_libraries": ["openupgradelib"],
},
{
"version": 10.0,
"python": "python2.7",
"python_libraries": ["openupgradelib"],
},
{
"version": 11.0,
"python": "python3.5",
"python_libraries": ["openupgradelib"],
},
{
"version": 12.0,
"python": "python3.6",
"python_libraries": ["openupgradelib"],
},
{
"version": 13.0,
"python": "python3.6",
"python_libraries": ["openupgradelib"],
},
{
"version": 14.0,
"python": "python3.6",
"python_libraries": ["openupgradelib"],
},
{
"version": 15.0,
"python": "python3.8",
"python_libraries": ["openupgradelib"],
},
] ]
def _get_odoo_version_str_list(mode): def _get_odoo_version_str_list(mode):
serie_list = [x["version"] for x in _ODOO_SERIES] serie_list = [x["version"] for x in _ODOO_SERIES]
if mode == "initial": if mode == "initial":
@ -23,9 +68,10 @@ def _get_odoo_version_str_list(mode):
serie_list = serie_list[1:] serie_list = serie_list[1:]
return [str(x) for x in serie_list] return [str(x) for x in serie_list]
def _get_odoo_versions(initial, final): def _get_odoo_versions(initial, final):
result = [] result = []
for serie in _ODOO_SERIES: for serie in _ODOO_SERIES:
if serie["version"] >= initial and serie["version"] <= final: if serie["version"] >= initial and serie["version"] <= final:
result.append(serie) result.append(serie)
return result return result

View File

@ -1,8 +1,7 @@
_CONFIG_YML_TEMPLATE = """ _CONFIG_YML_TEMPLATE = """migration_steps:
migration_steps:
{% for step in steps %} {% for step in steps %}
- name: {{ step['name'] }} - name: {{ step['name'] }}
- complete_name: {{ step['complete_name'] }} complete_name: {{ step['complete_name'] }}
version: {{ step['version'] }} version: {{ step['version'] }}
action: {{ step['action'] }} action: {{ step['action'] }}
python: {{ step['python'] }} python: {{ step['python'] }}
@ -59,4 +58,4 @@ _PRE_MIGRATION_SQL_TEMPLATE = ""
_POST_MIGRATION_PY_TEMPLATE = """ _POST_MIGRATION_PY_TEMPLATE = """
def main(self, step): def main(self, step):
pass pass
""" """

877
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -25,10 +25,11 @@ classifiers = [
odoo-openupgrade-wizard = "odoo_openupgrade_wizard.cli:main" odoo-openupgrade-wizard = "odoo_openupgrade_wizard.cli:main"
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.5" python = "^3.6"
click = "^7.0" click = "^7.0"
loguru = "^0.6" loguru = "^0.6"
plumbum = "^1.7" plumbum = "^1.7"
single-source = "^0.3"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
pytest = [ pytest = [
@ -59,4 +60,4 @@ line-length = 79
[tool.isort] [tool.isort]
profile = "black" profile = "black"
line_length = 79 line_length = 79

30
tests/cli_init_test.py Normal file
View File

@ -0,0 +1,30 @@
import filecmp
from pathlib import Path
from click.testing import CliRunner
from plumbum.cmd import mkdir
from odoo_openupgrade_wizard.cli import main
def test_cli_init():
output_folder_path = Path("./tests/output")
expected_folder_path = Path("./tests/output_expected")
mkdir([output_folder_path, "--parents"])
result = CliRunner().invoke(
main,
[
"--env-folder=%s" % output_folder_path,
"init",
"--initial-version=9.0",
"--final-version=12.0",
"--extra-repository="
"OCA/web,OCA/server-tools,GRAP/grap-odoo-incubator",
],
)
assert result.exit_code == 0
assert filecmp.cmp(
output_folder_path / Path("config.yml"),
expected_folder_path / Path("config.yml"),
)

View File

@ -0,0 +1,31 @@
migration_steps:
- name: step_1
complete_name: step_1__update__9.0
version: 9.0
action: update
python: python2.7
- name: step_2
complete_name: step_2__upgrade__10.0
version: 10.0
action: upgrade
python: python2.7
- name: step_3
complete_name: step_3__upgrade__11.0
version: 11.0
action: upgrade
python: python3.5
- name: step_4
complete_name: step_4__upgrade__12.0
version: 12.0
action: upgrade
python: python3.6
- name: step_5
complete_name: step_5__update__12.0
version: 12.0
action: update
python: python3.6

11
tox.ini Normal file
View File

@ -0,0 +1,11 @@
[tox]
isolated_build = true
skipsdist = True
; envlist = py35, py36, py37, py38
envlist = py36
[testenv]
whitelist_externals = poetry
commands =
poetry install -v
poetry run pytest -vv