Commit 3c6d5af6 authored by Pierre Smeyers's avatar Pierre Smeyers
Browse files

add check default from README

parent 2c86367c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -24,6 +24,6 @@ poetry run tbc-check path/to/tbc/template
- for each variable in the `kicker.json` file (main template and variants):
    - mapped input is declared in the related template with same name, type, default, options and description (WARNING only)
    - the variable is declared in the related template with expected input mapping (`$[[ inputs.input-name ]]`)
    - the input/variable is documented in the README (WARNING only)
    - the input/variable is documented in the README with same default (WARNING only)

If any non-WARNING rule fails, `tbc-check` fails with exit code 127.
+20 −3
Original line number Diff line number Diff line
@@ -104,7 +104,20 @@ class DocVar(BaseModel):
    var_name: str
    input_name: Optional[str] = None
    description: str
    default: str
    default_cell: str

    def default(self, type: GlInputType) -> Optional[str]:
        code_expr_match = re.match(r"`([^`]*)`", self.default_cell)
        explicit_default = code_expr_match.group(1) if code_expr_match else None

        if type == GlInputType.boolean:
            # return bool(self.default) if self.default != None else False
            return explicit_default or "false"
        if type == GlInputType.number:
            # return int(self.default) if self.default != None else 0
            return explicit_default or "0"
        return explicit_default or ''



def _get_var(tpl_desc: dict[str, any], var_name: str) -> Optional[TbcVar]:
@@ -136,11 +149,16 @@ def _get_var(tpl_desc: dict[str, any], var_name: str) -> Optional[TbcVar]:
def _check_var(tbc_var: TbcVar, var_prefix: str, tpl_spec: dict[str, any], tpl_impl: dict[str, any], main_tpl_desc: Optional[dict[str, any]], doc_vars: list[DocVar]) -> int:
    has_no_input = tbc_var.secret or main_tpl_desc and _get_var(main_tpl_desc, tbc_var.name) or tbc_var.name.startswith("TBC_")
    expected_input_name = tbc_var.input_name(var_prefix)
    expected_gl_input = tbc_var.to_gl()
    # check variable is declared in doc
    doc_var = next(filter(lambda dv: dv.var_name == tbc_var.name, doc_vars), None)
    if doc_var == None:
        print(f"  {bcolors.YELLOW}⚠ <{tbc_var.name}>: not documented in README{bcolors.RESET}")
    else:
        # check default
        if doc_var.default(expected_gl_input.type) != expected_gl_input.default:
            print(f"  {bcolors.YELLOW}⚠ <{tbc_var.name}/{expected_input_name}>: README default ({doc_var.default(tbc_var.type)}) doesn't match Kicker's ({expected_gl_input.default}){bcolors.YELLOW}")

        if doc_var.lock and not tbc_var.secret:
            print(f"  {bcolors.YELLOW}⚠ <{tbc_var.name}>: is not declared as a secret but has a lock in README{bcolors.RESET}")
        elif not doc_var.lock and tbc_var.secret:
@@ -184,7 +202,6 @@ def _check_var(tbc_var: TbcVar, var_prefix: str, tpl_spec: dict[str, any], tpl_i
    err_count = 0
    # check actual input is as expected
    actual_gl_input = GlInput.parse_obj(declared_input)
    expected_gl_input = tbc_var.to_gl()

    if actual_gl_input.type != expected_gl_input.type:
        print(f"  {bcolors.RED}✕ <{tbc_var.name}/{expected_input_name}>: type ({actual_gl_input.type}) doesn't match Kicker's ({expected_gl_input.type}){bcolors.RESET}")
@@ -287,7 +304,7 @@ def _load_vars_from_doc(project_dir: Path) -> list[DocVar]:
    # group 4: <description>
    # group 5: <default>
    var_doc_regex = re.compile(r"^\| *(:lock:)? *`([a-zA-Z0-9-_]+)`(?: *\/ *`([a-zA-Z0-9-_]+)`)? *\| *([^|]*) *\| *([^|]*)\ *\|$", flags=re.MULTILINE)
    return [DocVar(lock=bool(match.group(1)), var_name=match.group(3) or match.group(2), input_name=match.group(2) if match.group(3) else None, description=match.group(4), default=match.group(5)) for match in var_doc_regex.finditer(readme_content)]
    return [DocVar(lock=bool(match.group(1)), var_name=match.group(3) or match.group(2), input_name=match.group(2) if match.group(3) else None, description=match.group(4), default_cell=match.group(5)) for match in var_doc_regex.finditer(readme_content)]


def run():