Commit 206021bc authored by Pierre Smeyers's avatar Pierre Smeyers
Browse files

fix: template schema

parent 0f13294a
Loading
Loading
Loading
Loading
+57 −17
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@ import json
from enum import Enum
from logging import Logger
from pathlib import Path
from typing import Optional
from typing import Optional, Union

import yaml
from pydantic import BaseModel
@@ -45,7 +45,7 @@ class TbcVarType(str, Enum):
        return GlInputType.string


NullValue = "null"
_UNDEF = "!undef!"


class GlInput(BaseModel):
@@ -53,7 +53,7 @@ class GlInput(BaseModel):
    description: Optional[str] = None
    type: GlInputType = GlInputType.string
    options: Optional[list[str]] = None
    default: Optional[str] = None
    default: Optional[Union[str, bool]] = None

    def to_json(self) -> dict[str, any]:
        ret = {}
@@ -63,8 +63,10 @@ class GlInput(BaseModel):
            ret["type"] = self.type.value
        if self.options:
            ret["options"] = self.options
        if self.default:
            ret["default"] = None if self.default == NullValue else self.default
        if self.default != _UNDEF:
            # TODO: ci-lint doesn't allow default: null (500 error)
            # ret["default"] = self.default
            ret["default"] = "" if self.default == None else self.default
        return ret


@@ -84,14 +86,52 @@ class TbcVar(BaseModel):
            # TODO: remove Markdown formatting?
            description=self.description,
            type=self.type.to_gl(),
            default=self.default if self.default else "false" if self.type == TbcVarType.boolean else NullValue,
            default=self.default if self.default else False if self.type == TbcVarType.boolean else None,
            options=self.values
        )


def _migrate_var(var: TbcVar, var_prefix: str, tpl: dict[str, any]) -> Optional[GlInput]:
def _get_var(tpl_desc: dict[str, any], name: str) -> Optional[TbcVar]:
    var = next(iter([TbcVar.parse_obj(var) for var in tpl_desc.get("variables", []) if var["name"] == name]), None)
    if var:
        return var

    # look into feature variables
    for feat in tpl_desc.get("features", []):
        if feat.get("enable_with") == name:
            return TbcVar(
                name=feat.get("enable_with"),
                description= f"Enable {feat['name']}",
                type=TbcVarType.boolean,
            )
        elif feat.get("disable_with") == name:
            return TbcVar(
                name=feat.get("disable_with"),
                description= f"Disable {feat['name']}",
                type=TbcVarType.boolean,
            )
        var = next(iter([TbcVar.parse_obj(var) for var in feat.get("variables", []) if var["name"] == name]), None)
        if var:
            return var
    
    return None


def _migrate_var(var: TbcVar, var_prefix: str, tpl: dict[str, any], main_tpl: Optional[dict[str, any]]) -> Optional[GlInput]:
    if var.secret:
        # secrets should not be inputs
        print(f"INFO: variable '{var.name}' is a secret: skip")
        print()
        return None
    if main_tpl and _get_var(main_tpl, var.name):
        # a variant is overriding a variable from the main template: skip
        print(f"INFO: variable '{var.name}' is an override: skip")
        print()
        return None
    if var.name.startswith("TBC_"):
        # global TBC variable: skip
        print(f"INFO: variable '{var.name}' is global TBC: skip")
        print()
        return None
    
    gl_inputs = var.to_gl(var_prefix)
@@ -103,7 +143,7 @@ def _migrate_var(var: TbcVar, var_prefix: str, tpl: dict[str, any]) -> Optional[
        # detailed variable form (value, options, description)
        tpl_default = tpl_default.get("value")
    if tpl_default and tpl_default != inputs_binding and var.default != tpl_default:
        print(f"WARN: variable {var.name} has different default values")
        print(f"WARN: variable '{var.name}' has different default values")
        print(f"| template: {tpl_default}")
        print(f"| kicker  : {var.default}")
        print()
@@ -118,7 +158,7 @@ def _migrate_var(var: TbcVar, var_prefix: str, tpl: dict[str, any]) -> Optional[
    return gl_inputs


def _migrate_tpl(tpl_desc, project_dir: Path, var_prefix: str):
def _migrate_tpl(tpl_desc, main_tpl_desc, project_dir: Path, var_prefix: str):
    tpl_path = tpl_desc['template_path']
    # load template
    with open(project_dir / tpl_path, "r") as tpl_file:
@@ -129,7 +169,7 @@ def _migrate_tpl(tpl_desc, project_dir: Path, var_prefix: str):

    # migrate main template variables
    for var in tpl_desc.get("variables", []):
        gl_inputs.append(_migrate_var(TbcVar.parse_obj(var), var_prefix, tpl))
        gl_inputs.append(_migrate_var(TbcVar.parse_obj(var), var_prefix, tpl, main_tpl_desc))

    # migrate feature variables
    for feat in tpl_desc.get("features", []):
@@ -137,14 +177,14 @@ def _migrate_tpl(tpl_desc, project_dir: Path, var_prefix: str):
           gl_inputs.append(_migrate_var(TbcVar(name=feat.get("enable_with"),
               description= f"Enable {feat['name']}",
               type=TbcVarType.boolean,
           ), var_prefix, tpl))
           ), var_prefix, tpl, main_tpl_desc))
       elif feat.get("disable_with"):
           gl_inputs.append(_migrate_var(TbcVar(name=feat.get("disable_with"),
               description= f"Disable {feat['name']}",
               type=TbcVarType.boolean,
           ), var_prefix, tpl))
           ), var_prefix, tpl, main_tpl_desc))
       for var in feat.get("variables", []):
            gl_inputs.append(_migrate_var(TbcVar.parse_obj(var), var_prefix, tpl))
            gl_inputs.append(_migrate_var(TbcVar.parse_obj(var), var_prefix, tpl, main_tpl_desc))
    
    tpl_spec = {"spec": {"inputs": {inputs.name: inputs.to_json() for inputs in gl_inputs if inputs}}}

@@ -199,10 +239,10 @@ def migrate():
    print(f"=== Migrating main template '{kicker['name']}' with var prefix '{var_prefix}'...")
    print()

    _migrate_tpl(kicker, project_dir, var_prefix)
    _migrate_tpl(kicker, None, project_dir, var_prefix)
    
    for variant in kicker.get("variants", []):
        var_prefix_for_variant = var_prefix+(variant["id"].upper())+"_"
        print(f"=== Migrating variant '{variant['name']}' with var prefix '{var_prefix_for_variant}'...")
        # var_prefix_for_variant = var_prefix+(variant["id"].upper())+"_"
        print(f"=== Migrating variant '{variant['name']}' with var prefix '{var_prefix}'...")
        print()
        _migrate_tpl(variant, project_dir, var_prefix_for_variant)
        _migrate_tpl(variant, kicker, project_dir, var_prefix)