Skip to content
Extraits de code Groupes Projets

Check availability of Odoo modules

  • Cloner avec SSH
  • Cloner avec HTTPS
  • Intégrer
  • Partager
    L'extrait de code peut être consulté sans aucune authentification.
    Rédigé par Théo - Le Filament
    Modifié
    check_modules.py 6,44 Kio
    #!/usr/bin/python3
    
    import urllib.request, urllib.error
    import re
    import sys
    import yaml
    
    
    repos = {
        "https://github.com/OCA/account-financial-reporting": [
            "account_tax_balance"
        ],
        "https://github.com/OCA/account-financial-tools": [
            "account_lock_date_update",
            "account_move_name_sequence",
            "account_reconcile_show_boolean"
        ],
        "https://github.com/OCA/account-invoicing": [
            "sale_timesheet_invoice_description"
        ],
        "https://github.com/OCA/account-reconcile": [
            "account_reconciliation_widget"
        ],
        "https://github.com/OCA/bank-statement-import": [
            "account_statement_import",
            "account_statement_import_ofx"
        ],
        "https://github.com/OCA/crm": [
            "crm_stage_probability"
        ],
        "https://github.com/OCA/partner-contact": [
            "partner_disable_gravatar",
            "partner_firstname"
        ],
        "https://github.com/OCA/project": [
            "project_category",
            "project_status",
            "project_task_default_stage",
            "project_template",
            "project_timeline"
        ],
        "https://github.com/OCA/server-auth": [
            "password_security"
        ],
        "https://github.com/OCA/server-brand": [
            "disable_odoo_online",
            "remove_odoo_enterprise"
        ],
        "https://github.com/OCA/server-tools": [
            "base_search_fuzzy",
            "module_change_auto_install"
        ],
        "https://github.com/OCA/server-ux": [
            "base_technical_features",
            "date_range",
            "mass_editing"
        ],
        "https://github.com/OCA/social": [
            "base_search_mail_content",
            "mail_debrand",
            "mail_tracking"
        ],
        "https://github.com/OCA/web": [
            "web_environment_ribbon",
            "web_responsive",
            "web_no_bubble",
            "web_timeline"
        ]
    }
    
    
    class Style:
        """Set of console display styles.
    
        """
        black = '\033[30m'
        red = '\033[31m'
        green = '\033[32m'
        yellow = '\033[33m'
        blue = '\033[34m'
        magenta = '\033[35m'
        cyan = '\033[36m'
        lightgray = '\033[37m'
        default = '\033[39m'
        bold = '\033[1m'
        normal = '\033[0m'
    
    
    def print_err(message):
        print(f"{Style.red}{Style.bold}err: {message}{Style.normal}"
              f"{Style.default}", file=sys.stderr)
    
    
    def check_pr(repo, module):
        conn = urllib.request.urlopen(
            f"{repo}/pulls?q=is%3Apr+is%3Aopen+%5B{version}%5D+mig+{module}")
        html = conn.read().decode('utf-8')
        result = re.search(rf"{repo[18:]}/pull/\d+", html)
        if result:
            return f"https://github.com{result.group()}"
        return None
    
    def load_repos(host_file):
        with open(host_file, 'r', encoding='utf8') as file:
            host = yaml.safe_load(file)
            for instance in host['odoo_nonprod_instances']:
                for repo in instance['custom_modules_oca']:
                    repo_url = f"https://github.com/OCA/{repo['repo']}"
                    if repos.get(repo_url):
                        repos[repo_url].extend(repo['modules'])
                    else:
                        repos[repo_url] = repo['modules']
                for repo in instance['custom_modules']:
                    repos[f"https://sources.le-filament.com/lefilament/{repo}"] = None
    
    def print_help():
        print(f"usage:\n  {sys.argv[0]} <version> [hostvars file]\n"
              "options:\n  <version>        Odoo version\n"
              "  [hostvars file]  Ansible hostvars file to also check modules of"
              " this host")
    
    
    def main():
        if len(sys.argv) >= 2:
            version = sys.argv[1]
        else:
            print_err("missing version argument (e.g.: '16.0')")
            sys.exit(1)
        if sys.argv[1] == '-h' or sys.argv[1] == '--help':
            print_help()
            sys.exit(0)
        if len(sys.argv) == 3:
            load_repos(sys.argv[2])
    
        print(f"{Style.blue}💡 Checking availability Odoo v{version} "
              f"modules...{Style.default}\n")
    
        module_count = 0
        available_module_count = 0
        pr_count = 0
        for repo, modules in repos.items():
            tree = "tree"
            if 'github.com' not in repo:
                tree = '-/tree'
            repo_name = repo.split('/')[-1]
    
            for module in modules or []:
                module_count += 1
                try:
                    conn = urllib.request.urlopen(f"{repo}/{tree}/"
                                                  f"{version}/{module}")
                except urllib.error.HTTPError as err:
                    if err.code == 404:
                        pr_url = check_pr(repo, module)
                        if pr_url:
                            pr_count += 1
                            print(f"{Style.red}❌ Not ready: {module} "
                                  f"(in {repo_name}){Style.default} "
                                  f"PR at {pr_url}")
                        else:
                            print(f"{Style.red}❌ Not ready: {module} "
                                  f"(in {repo_name}){Style.default}")
                    else:
                        print_err(f"HTTP error code {err.code} "
                                  f"for {module} (in {repo})")
                except urllib.error.URLError as err:
                    print_err(f"HTTP error '{err.reason}' for {module} "
                              f"(in {repo_name})")
                else:
                    available_module_count += 1
                    print(f"{Style.green}✅ Available: {module} "
                          f"(in {repo_name}){Style.default}")
    
            if not modules:
                module_count += 1
                try:
                    conn = urllib.request.urlopen(f"{repo}/{tree}/{version}/")
                except urllib.error.HTTPError as err:
                    if err.code == 404:
                        print(f"{Style.red}❌ Not already: {repo_name}"
                              f"{Style.default}")
                    else:
                        print_err(f"HTTP error code {err.code} for {repo_name}")
                except urllib.error.URLError as err:
                    print_err(f"HTTP error '{err.reason}' for {repo_name}")
                else:
                    available_module_count += 1
                    print(f"{Style.green}✅ Available:  {repo_name}"
                          f"{Style.default}")
    
    
        if available_module_count < module_count:
            print(f"\n{Style.bold}Result: {Style.green}{available_module_count}"
                  f"{Style.default} / {module_count} modules are available. "
                  f"There are {pr_count} opened pull requests.{Style.normal}")
        else:
            print(f"\n{Style.green}{Style.bold}Result: all {module_count} modules "
                  f"are available. It's ready to go!{Style.normal}{Style.default}")
    
    
    if __name__ == '__main__':
        main()
    • Cool, merci Theo ! C'est cool pour les modules pour la v16 qu'on met par défaut dans l'image. Ce qui serait top serait de pouvoir lui donner en entrée un fichier yaml comme celui qu'on pousse sur les serveurs avec la liste des modules d'un client pour qu'il vérifie lesquels existent ou pas (et la version à vérifier en paramètre) - si pas de fichier yaml en entrée il affiche comme aujourd'hui avec les modules de base de notre image.

    • Théo, il faudrait modifier la fonction load_file() avec nouvelle architecture fichier host_vars :

      def load_repos(host_file):
          with open(host_file, 'r', encoding='utf8') as file:
              host = yaml.safe_load(file)
              for instance in host['odoo_instances']:
                  for repo in host['odoo_instances'][instance].get('custom_modules_oca', []):
                      repo_url = f"https://github.com/OCA/{repo['repo']}"
                      if repos.get(repo_url):
                          repos[repo_url].extend(repo['modules'])
                      else:
                          repos[repo_url] = repo['modules']
                  for repo in host['odoo_instances'][instance].get('custom_modules', []):
                      repos[f"https://sources.le-filament.com/lefilament/{repo['repo']}"] = None

      ça pourrait aussi être intéressant d'aller chercher des valeurs uniques dans la variable repos (par exemple pour les hôtes où tu as plusieurs instances build avec différentes conf) ou passer en paramètre l'instance à utiliser ?

    • Il faudrait aussi mettre à jour la liste des modules par défaut (ou la récupérer du fichier https://sources.le-filament.com/lefilament/odoo_docker/-/blob/{version}/{version}.Dockerfile ?)

    0% Chargement en cours ou .
    You are about to add 0 people to the discussion. Proceed with caution.
    Veuillez vous inscrire ou vous pour commenter