-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SNOW-1039218] feat: add hidden app list-templates command #887
Changes from 7 commits
73d7c32
761abaf
6e8aa60
eb1c588
6482d3c
37c6e78
b038622
6c7e108
a108901
4d2f2ad
628ecf5
34f4126
3ef5408
5433c9f
f468f39
8147cd1
1f475c6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,9 +7,17 @@ | |
with_project_definition, | ||
) | ||
from snowflake.cli.api.commands.snow_typer import SnowTyper | ||
from snowflake.cli.api.output.types import CommandResult, MessageResult | ||
from snowflake.cli.api.output.types import ( | ||
CollectionResult, | ||
CommandResult, | ||
MessageResult, | ||
) | ||
from snowflake.cli.api.secure_path import SecurePath | ||
from snowflake.cli.plugins.nativeapp.common_flags import ForceOption, InteractiveOption | ||
from snowflake.cli.plugins.nativeapp.init import nativeapp_init | ||
from snowflake.cli.plugins.nativeapp.init import ( | ||
OFFICIAL_TEMPLATES_GITHUB_URL, | ||
nativeapp_init, | ||
) | ||
from snowflake.cli.plugins.nativeapp.manager import NativeAppManager | ||
from snowflake.cli.plugins.nativeapp.policy import ( | ||
AllowAlwaysPolicy, | ||
|
@@ -20,7 +28,11 @@ | |
from snowflake.cli.plugins.nativeapp.teardown_processor import ( | ||
NativeAppTeardownProcessor, | ||
) | ||
from snowflake.cli.plugins.nativeapp.utils import is_tty_interactive | ||
from snowflake.cli.plugins.nativeapp.utils import ( | ||
get_first_paragraph_from_markdown_file, | ||
is_tty_interactive, | ||
shallow_git_clone, | ||
) | ||
from snowflake.cli.plugins.nativeapp.version.commands import app as versions_app | ||
|
||
app = SnowTyper( | ||
|
@@ -69,6 +81,39 @@ def app_init( | |
) | ||
|
||
|
||
@app.command("list-templates", hidden=True) | ||
def app_list_templates(**options) -> CommandResult: | ||
""" | ||
Prints information regarding templates that can be used with snow app init. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: "... regarding the official templates ...", so it is clear that only our Github templates are listed in this command. |
||
""" | ||
with SecurePath.temporary_directory() as temp_path: | ||
repo = shallow_git_clone(OFFICIAL_TEMPLATES_GITHUB_URL, temp_path.path) | ||
|
||
# Mark a directory as a template if a project definition jinja template is inside | ||
template_directories = [ | ||
entry.name | ||
for entry in repo.head.commit.tree | ||
if (temp_path / entry.name / "snowflake.yml.jinja").exists() | ||
] | ||
|
||
# get the template descriptions from the README.md in its directory | ||
template_descriptions = [ | ||
get_first_paragraph_from_markdown_file( | ||
(temp_path / directory / "README.md").path | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right now, this will fail if any templates are created that don't have top-level There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good callout - added a test for it as well, thanks! |
||
) | ||
for directory in template_directories | ||
] | ||
|
||
result = ( | ||
{"template": directory, "description": description} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really like the idea of a little description along with template names! |
||
for directory, description in zip( | ||
template_directories, template_descriptions | ||
) | ||
) | ||
|
||
return CollectionResult(result) | ||
|
||
|
||
@app.command("bundle", hidden=True) | ||
@with_project_definition("native_app") | ||
def app_bundle( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
from textwrap import dedent | ||
|
||
import pytest | ||
from snowflake.cli.api.secure_path import SecurePath | ||
from snowflake.cli.plugins.nativeapp.utils import get_first_paragraph_from_markdown_file | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"file_content, expected_paragraph", | ||
[ | ||
( | ||
dedent( | ||
""" | ||
## Introduction | ||
|
||
This is an example template for a Snowflake Native App project which demonstrates the use of Python extension code and adding Streamlit code. This template is meant to guide developers towards a possible project structure on the basis of functionality, as well as to indicate the contents of some common and useful files. | ||
|
||
Since this template contains Python files only, you do not need to perform any additional steps to build the source code. You can directly go to the next section. However, if there were any source code that needed to be built, you must manually perform the build steps here before proceeding to the next section. | ||
|
||
Similarly, you can also use your own build steps for any other languages supported by Snowflake that you wish to write your code in. For more information on supported languages, visit [docs](https://docs.snowflake.com/en/developer-guide/stored-procedures-vs-udfs#label-sp-udf-languages). | ||
""" | ||
), | ||
"This is an example template for a Snowflake Native App project which demonstrates the use of Python extension code and adding Streamlit code. This template is meant to guide developers towards a possible project structure on the basis of functionality, as well as to indicate the contents of some common and useful files.", | ||
), | ||
( | ||
dedent( | ||
""" | ||
# Just a Heading | ||
|
||
## And some whitespace. | ||
""" | ||
), | ||
None, | ||
), | ||
], | ||
) | ||
def test_get_first_paragraph_from_markdown_file_with_valid_path( | ||
file_content, expected_paragraph | ||
): | ||
with SecurePath.temporary_directory() as temp_path: | ||
temp_readme_path = (temp_path / "README.md").path | ||
|
||
with open(temp_readme_path, "w+") as temp_readme_file: | ||
temp_readme_file.write(file_content) | ||
|
||
actual_paragraph = get_first_paragraph_from_markdown_file(temp_readme_path) | ||
sfc-gh-cgorrie marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
assert actual_paragraph == expected_paragraph | ||
|
||
|
||
def test_get_first_paragraph_from_markdown_file_with_invalid_path(): | ||
with SecurePath.temporary_directory() as temp_path: | ||
temp_readme_path = (temp_path / "README.md").path | ||
|
||
actual_paragraph = get_first_paragraph_from_markdown_file(temp_readme_path) | ||
|
||
assert actual_paragraph is None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Today we have feature flags. Have you consider using them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this was clarified offline, please see the slack thread of the PR for the full discussion, but to summarize:
Please let me know if this works for you :)