Loading tbc/template_to_component.py +66 −17 Original line number Diff line number Diff line Loading @@ -132,17 +132,14 @@ def _migrate_var(var: TbcVar, var_prefix: str, tpl: dict[str, any], main_tpl: Op 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) Loading @@ -157,7 +154,6 @@ def _migrate_var(var: TbcVar, var_prefix: str, tpl: dict[str, any], main_tpl: Op print(f"WARN: variable '{var.name}' has different default values") print(f"| template: {tpl_default}") print(f"| kicker : {var.default}") print() # apply template default instead var.default = tpl_default # update input Loading @@ -171,10 +167,10 @@ def _migrate_var(var: TbcVar, var_prefix: str, tpl: dict[str, any], main_tpl: Op def _migrate_tpl(tpl_desc, main_tpl_desc, project_dir: Path, var_prefix: str) -> list[tuple[TbcVar, Optional[GlInput]]]: ret: list[tuple[TbcVar, Optional[GlInput]]] = [] tpl_path = tpl_desc['template_path'] tpl_path = project_dir / tpl_desc['template_path'] # load template with open(project_dir / tpl_path, "r") as tpl_file: all_tpl = list(yaml.load_all(tpl_file, Loader=yaml.BaseLoader)) with open(tpl_path, "r") as tpl_reader: all_tpl = list(yaml.load_all(tpl_reader, Loader=yaml.BaseLoader)) tpl = all_tpl[-1] # migrate main template variables Loading Loading @@ -202,15 +198,26 @@ def _migrate_tpl(tpl_desc, main_tpl_desc, project_dir: Path, var_prefix: str) -> tpl_spec = {"spec": {"inputs": {inputs.name: inputs.to_json() for _, inputs in ret if inputs}}} # rewrite template with inputs section # print(">> Rewrite template") # migrate template print(">> Migrate template") with open(tpl_path, "r") as tpl_reader: tpl_content = tpl_reader.read() # insert specs # print(">> Template spec:") # print(yaml.dump(tpl_spec, width=1000, default_flow_style=False, sort_keys=False)) # print() # with open(project_dir / template_path, "w") as tpl_file: # yaml.dump_all((tpl_specs, tpl), tpl_file) first_non_comment_line: re.Match = next(re.finditer(r"^[^#]", tpl_content, flags=re.MULTILINE)) print(f"first non-comment line: {first_non_comment_line}") tpl_content = tpl_content[0:first_non_comment_line.start(0)]+yaml.dump(tpl_spec, width=1000, default_flow_style=False, sort_keys=False)+"---\n"+tpl_content[first_non_comment_line.start(0):] print(">> Template spec:") print(yaml.dump(tpl_spec, width=1000, default_flow_style=False, sort_keys=False)) print() # overwrite variables # for var in tpl["variables"]: # tpl_content = re.sub(f"^ {var['name']}:.*$", yaml.dump(var, default_flow_style=False, sort_keys=False), tpl_content) # write with open(tpl_path, "w") as writer: writer.write(tpl_content) print(">> Variables sections:") print(yaml.dump({"variables": tpl["variables"]}, default_flow_style=False, sort_keys=False)) Loading @@ -219,11 +226,52 @@ def _migrate_tpl(tpl_desc, main_tpl_desc, project_dir: Path, var_prefix: str) -> return ret def _migrate_readme(readme_file: Path, var_input: list[tuple[TbcVar, Optional[GlInput]]]): def _migrate_readme(tpl_desc, project_dir: Path, var_input: list[tuple[TbcVar, Optional[GlInput]]]): # read file readme_file = project_dir / "README.md" with open(readme_file, "r") as reader: readme_content = reader.read() project_name = project_dir.name project_version = "TODO" # insert new usage chapter readme_content = readme_content.replace("## Usage", f"""## Usage This template can be used both as a [CI/CD component](https://docs.gitlab.com/ee/ci/components/#use-a-component-in-a-cicd-configuration) or using the legacy [`include:project`](https://docs.gitlab.com/ee/ci/yaml/index.html#includeproject) syntax. ### Use as a CI/CD component Add the following to your `gitlab-ci.yml`: ```yaml include: # 1: include the component - component: gitlab.com/to-be-continuous/{project_name}/{tpl_desc['template_path'].split('/')[-1]}@{project_version} # 2: set/override component inputs inputs: example-input: "TODO" # ⚠ this is only an example ``` ### Use as a CI/CD template (legacy) Add the following to your `gitlab-ci.yml`: ```yaml include: # 1: include the template - project: 'to-be-continuous/{project_name}' ref: '{project_version}' file: '{tpl_desc['template_path']}' variables: # 2: set/override template variables EXAMPLE_VAR: "TODO" # ⚠ this is only an example ``` ## Usage (previous)""") # replace "Name" header in tables by "Input / Variable" readme_content = re.sub(r"\| *Name *\|", "| Input / Variable |", readme_content) # readme_content = re.sub(r"\| *description", "| Description", readme_content) Loading Loading @@ -255,7 +303,8 @@ def migrate(): with open(project_dir / "kicker.json", "r") as kicker_file: kicker = json.load(kicker_file) var_prefix = (args.var_prefix or kicker["name"].upper()) + "_" # guess prefix var_prefix = (args.var_prefix or next(map(lambda var: var["name"].split("_")[0], filter(lambda var: var["name"].endswith("_IMAGE"), kicker.get("variables", []))), None) or kicker["name"].upper()) + "_" var_input: list[tuple[TbcVar, Optional[GlInput]]] = [] Loading @@ -271,7 +320,7 @@ def migrate(): print("=== Migrating README...") print() _migrate_readme(project_dir / "README.md", var_input) _migrate_readme(kicker, project_dir, var_input) print("=== Copying bumpversion.sh...") print() Loading Loading
tbc/template_to_component.py +66 −17 Original line number Diff line number Diff line Loading @@ -132,17 +132,14 @@ def _migrate_var(var: TbcVar, var_prefix: str, tpl: dict[str, any], main_tpl: Op 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) Loading @@ -157,7 +154,6 @@ def _migrate_var(var: TbcVar, var_prefix: str, tpl: dict[str, any], main_tpl: Op print(f"WARN: variable '{var.name}' has different default values") print(f"| template: {tpl_default}") print(f"| kicker : {var.default}") print() # apply template default instead var.default = tpl_default # update input Loading @@ -171,10 +167,10 @@ def _migrate_var(var: TbcVar, var_prefix: str, tpl: dict[str, any], main_tpl: Op def _migrate_tpl(tpl_desc, main_tpl_desc, project_dir: Path, var_prefix: str) -> list[tuple[TbcVar, Optional[GlInput]]]: ret: list[tuple[TbcVar, Optional[GlInput]]] = [] tpl_path = tpl_desc['template_path'] tpl_path = project_dir / tpl_desc['template_path'] # load template with open(project_dir / tpl_path, "r") as tpl_file: all_tpl = list(yaml.load_all(tpl_file, Loader=yaml.BaseLoader)) with open(tpl_path, "r") as tpl_reader: all_tpl = list(yaml.load_all(tpl_reader, Loader=yaml.BaseLoader)) tpl = all_tpl[-1] # migrate main template variables Loading Loading @@ -202,15 +198,26 @@ def _migrate_tpl(tpl_desc, main_tpl_desc, project_dir: Path, var_prefix: str) -> tpl_spec = {"spec": {"inputs": {inputs.name: inputs.to_json() for _, inputs in ret if inputs}}} # rewrite template with inputs section # print(">> Rewrite template") # migrate template print(">> Migrate template") with open(tpl_path, "r") as tpl_reader: tpl_content = tpl_reader.read() # insert specs # print(">> Template spec:") # print(yaml.dump(tpl_spec, width=1000, default_flow_style=False, sort_keys=False)) # print() # with open(project_dir / template_path, "w") as tpl_file: # yaml.dump_all((tpl_specs, tpl), tpl_file) first_non_comment_line: re.Match = next(re.finditer(r"^[^#]", tpl_content, flags=re.MULTILINE)) print(f"first non-comment line: {first_non_comment_line}") tpl_content = tpl_content[0:first_non_comment_line.start(0)]+yaml.dump(tpl_spec, width=1000, default_flow_style=False, sort_keys=False)+"---\n"+tpl_content[first_non_comment_line.start(0):] print(">> Template spec:") print(yaml.dump(tpl_spec, width=1000, default_flow_style=False, sort_keys=False)) print() # overwrite variables # for var in tpl["variables"]: # tpl_content = re.sub(f"^ {var['name']}:.*$", yaml.dump(var, default_flow_style=False, sort_keys=False), tpl_content) # write with open(tpl_path, "w") as writer: writer.write(tpl_content) print(">> Variables sections:") print(yaml.dump({"variables": tpl["variables"]}, default_flow_style=False, sort_keys=False)) Loading @@ -219,11 +226,52 @@ def _migrate_tpl(tpl_desc, main_tpl_desc, project_dir: Path, var_prefix: str) -> return ret def _migrate_readme(readme_file: Path, var_input: list[tuple[TbcVar, Optional[GlInput]]]): def _migrate_readme(tpl_desc, project_dir: Path, var_input: list[tuple[TbcVar, Optional[GlInput]]]): # read file readme_file = project_dir / "README.md" with open(readme_file, "r") as reader: readme_content = reader.read() project_name = project_dir.name project_version = "TODO" # insert new usage chapter readme_content = readme_content.replace("## Usage", f"""## Usage This template can be used both as a [CI/CD component](https://docs.gitlab.com/ee/ci/components/#use-a-component-in-a-cicd-configuration) or using the legacy [`include:project`](https://docs.gitlab.com/ee/ci/yaml/index.html#includeproject) syntax. ### Use as a CI/CD component Add the following to your `gitlab-ci.yml`: ```yaml include: # 1: include the component - component: gitlab.com/to-be-continuous/{project_name}/{tpl_desc['template_path'].split('/')[-1]}@{project_version} # 2: set/override component inputs inputs: example-input: "TODO" # ⚠ this is only an example ``` ### Use as a CI/CD template (legacy) Add the following to your `gitlab-ci.yml`: ```yaml include: # 1: include the template - project: 'to-be-continuous/{project_name}' ref: '{project_version}' file: '{tpl_desc['template_path']}' variables: # 2: set/override template variables EXAMPLE_VAR: "TODO" # ⚠ this is only an example ``` ## Usage (previous)""") # replace "Name" header in tables by "Input / Variable" readme_content = re.sub(r"\| *Name *\|", "| Input / Variable |", readme_content) # readme_content = re.sub(r"\| *description", "| Description", readme_content) Loading Loading @@ -255,7 +303,8 @@ def migrate(): with open(project_dir / "kicker.json", "r") as kicker_file: kicker = json.load(kicker_file) var_prefix = (args.var_prefix or kicker["name"].upper()) + "_" # guess prefix var_prefix = (args.var_prefix or next(map(lambda var: var["name"].split("_")[0], filter(lambda var: var["name"].endswith("_IMAGE"), kicker.get("variables", []))), None) or kicker["name"].upper()) + "_" var_input: list[tuple[TbcVar, Optional[GlInput]]] = [] Loading @@ -271,7 +320,7 @@ def migrate(): print("=== Migrating README...") print() _migrate_readme(project_dir / "README.md", var_input) _migrate_readme(kicker, project_dir, var_input) print("=== Copying bumpversion.sh...") print() Loading