Skip to content

Commit

Permalink
feat(cli): allow ignoring template rendering errors (#3697)
Browse files Browse the repository at this point in the history
  • Loading branch information
m-alisafaee committed Feb 5, 2024
1 parent ae3618c commit 088ce15
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 11 deletions.
4 changes: 2 additions & 2 deletions renku/core/errors.py
Expand Up @@ -485,11 +485,11 @@ class TemplateError(RenkuException):


class InvalidTemplateError(TemplateError):
"""Raised when using a non-valid template."""
"""Raised when using an invalid template."""


class TemplateMissingReferenceError(TemplateError):
"""Raised when using a non-valid template."""
"""Raised when a reference cannot be found in the template's repository."""


class TemplateUpdateError(TemplateError):
Expand Down
4 changes: 3 additions & 1 deletion renku/core/init.py
Expand Up @@ -110,6 +110,7 @@ def init_project(
input_parameters: Dict[str, str],
custom_metadata: Optional[Dict[str, Any]],
force: bool,
ignore_template_errors: bool,
data_dir: Optional[Path],
initial_branch: Optional[str],
install_mergetool: bool,
Expand All @@ -129,6 +130,7 @@ def init_project(
input_parameters: Template parameters.
custom_metadata: Custom JSON-LD metadata for project.
force: Whether to overwrite existing files and delete existing metadata.
ignore_template_errors: Create project anyway even if template rendering fails.
data_dir: Where to store dataset data.
initial_branch: Default git branch.
install_mergetool(bool): Whether to set up the renku metadata mergetool in the created project.
Expand Down Expand Up @@ -181,7 +183,7 @@ def init_project(
# TODO: Validate input_parameters to make sure they don't contain __\w+__ keys
set_template_parameters(template=template, template_metadata=template_metadata, input_parameters=input_parameters)

rendered_template = template.render(metadata=template_metadata)
rendered_template = template.render(metadata=template_metadata, ignore_template_errors=ignore_template_errors)
actions = get_file_actions(
rendered_template=rendered_template, template_action=TemplateAction.INITIALIZE, interactive=False
)
Expand Down
35 changes: 27 additions & 8 deletions renku/domain_model/template.py
Expand Up @@ -28,6 +28,7 @@

from renku.core import errors
from renku.core.constant import RENKU_HOME
from renku.core.util import communication
from renku.core.util.os import get_safe_relative_path, hash_file, hash_string
from renku.core.util.util import to_string

Expand Down Expand Up @@ -343,16 +344,23 @@ def get_files(self) -> Generator[str, None, None]:
if subpath.is_file():
yield str(subpath.relative_to(self.path))

def render(self, metadata: "TemplateMetadata") -> "RenderedTemplate":
def render(self, metadata: "TemplateMetadata", ignore_template_errors: bool = False) -> "RenderedTemplate":
"""Render template files in a new directory."""
if self.path is None:
raise ValueError("Template path not set")

render_base = Path(tempfile.mkdtemp())

for relative_path in self.get_files():
# NOTE: The path could contain template variables, we need to template it
rendered_relative_path = jinja2.Template(relative_path).render(metadata.metadata)
try:
# NOTE: The path could contain template variables, we need to template it
rendered_relative_path = jinja2.Template(relative_path).render(metadata.metadata)
except jinja2.TemplateError as e:
if ignore_template_errors:
rendered_relative_path = relative_path
communication.warn(f"Ignoring template error when rendering path '{relative_path}'")
else:
raise errors.InvalidTemplateError(f"Cannot render template file path '{relative_path}': {e}")

destination = render_base / rendered_relative_path
destination.parent.mkdir(parents=True, exist_ok=True)
Expand All @@ -365,9 +373,20 @@ def render(self, metadata: "TemplateMetadata") -> "RenderedTemplate":
content_bytes = source.read_bytes()
destination.write_bytes(content_bytes)
else:
template = jinja2.Template(content, keep_trailing_newline=True)
rendered_content = template.render(metadata.metadata)
destination.write_text(rendered_content)
try:
rendered_content = jinja2.Template(content, keep_trailing_newline=True).render(metadata.metadata)
except jinja2.TemplateError as e:
if ignore_template_errors:
destination.write_text(content)
communication.warn(
f"Ignoring template rendering error when creating '{rendered_relative_path}'"
)
else:
raise errors.InvalidTemplateError(
f"Cannot render template file '{rendered_relative_path}': {e}"
)
else:
destination.write_text(rendered_content)

return RenderedTemplate(path=render_base, template=self, metadata=metadata.metadata)

Expand Down Expand Up @@ -432,8 +451,8 @@ def from_dict(cls, name: str, value: Dict[str, Any]):
@property
def has_default(self) -> bool:
"""Return True if a default value is set."""
# NOTE: ``None`` cannot be used as the default value but it's ok since no variable type accepts it and it's not
# a valid value anyways
# NOTE: ``None`` cannot be used as the default value, but it's ok since no variable type accepts it, and it's
# not a valid value anyway
return self.default is not None

def validate(self, raise_errors: bool = True) -> List[str]:
Expand Down
7 changes: 7 additions & 0 deletions renku/ui/cli/init.py
Expand Up @@ -53,6 +53,10 @@
source ``--template-source`` (both local path and remote url are supported) and
the reference ``--template-ref`` (branch, tag or commit).
If the template contains an error that prevents it from being rendered, you can
ignore this error by passing ``--ignore-template-errors`` to the ``init``
command.
You can take inspiration from the
`official Renku template repository
<https://github.com/SwissDataScienceCenter/renku-project-template>`_
Expand Down Expand Up @@ -259,6 +263,7 @@ def resolve_data_directory(data_dir, path):
@click.option("-l", "--list-templates", is_flag=True, help="List templates available in the template-source.")
@click.option("-d", "--describe", is_flag=True, help="Show description for templates and parameters")
@click.option("--force", is_flag=True, help="Override target path.")
@click.option("--ignore-template-errors", is_flag=True, help="Ignore template rendering errors.")
@click.option("--initial-branch", help="Initial git branch to create.")
@option_external_storage_requested
@click.pass_context
Expand All @@ -277,6 +282,7 @@ def init(
metadata,
list_templates,
force,
ignore_template_errors,
describe,
datadir,
initial_branch,
Expand Down Expand Up @@ -319,6 +325,7 @@ def init(
input_parameters=parameters,
custom_metadata=custom_metadata,
force=force,
ignore_template_errors=ignore_template_errors,
data_dir=datadir,
initial_branch=initial_branch,
install_mergetool=True,
Expand Down

0 comments on commit 088ce15

Please sign in to comment.