Skip to content
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

[App] Enable running an app from the Gallery #15941

Merged
merged 45 commits into from Dec 8, 2022
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
19f5f92
update
Dec 7, 2022
907863e
update
Dec 7, 2022
ded1875
update
Dec 7, 2022
779ca61
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 7, 2022
5ac904f
update
Dec 7, 2022
4d98009
Merge branch 'add_support_for_running_app' of https://github.com/Ligh…
Dec 7, 2022
47c71f3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 7, 2022
b2bcd8f
update
Dec 8, 2022
7fb58ea
Merge branch 'add_support_for_running_app' of https://github.com/Ligh…
Dec 8, 2022
26e74c8
update
Dec 8, 2022
433d541
Merge branch 'master' into add_support_for_running_app
tchaton Dec 8, 2022
2144412
updarte
Dec 8, 2022
6db4ab5
Merge branch 'add_support_for_running_app' of https://github.com/Ligh…
Dec 8, 2022
d7bac7d
update
Dec 8, 2022
4bfc36c
update
Dec 8, 2022
6416c05
update
Dec 8, 2022
536f581
update
Dec 8, 2022
ace5aa1
update
Dec 8, 2022
30fc0b9
update
Dec 8, 2022
0866b86
update
Dec 8, 2022
981c1a0
update
Dec 8, 2022
256dc4f
Merge branch 'master' into add_support_for_running_app
tchaton Dec 8, 2022
d3adc85
update
Dec 8, 2022
e3565f2
Merge branch 'add_support_for_running_app' of https://github.com/Ligh…
Dec 8, 2022
617468e
update
Dec 8, 2022
67ad41f
Update src/lightning_app/cli/cmd_install.py
tchaton Dec 8, 2022
100e4c1
Update src/lightning_app/cli/cmd_install.py
tchaton Dec 8, 2022
aada8fb
update
Dec 8, 2022
6bb5fb0
Merge branch 'add_support_for_running_app' of https://github.com/Ligh…
Dec 8, 2022
d88cb81
update
Dec 8, 2022
62bd1ca
mypy
Borda Dec 8, 2022
d01deed
update
Dec 8, 2022
b9b441a
Merge branch 'master' into add_support_for_running_app
tchaton Dec 8, 2022
60d3f28
Merge branch 'add_support_for_running_app' of https://github.com/PyTo…
Borda Dec 8, 2022
c3a0ec8
ex
Borda Dec 8, 2022
b2f5be4
update
Dec 8, 2022
1d4b01a
update
Dec 8, 2022
ec6e66b
ex2
Borda Dec 8, 2022
e33eac7
Merge branch 'add_support_for_running_app' of https://github.com/PyTo…
Borda Dec 8, 2022
569bc10
ex2
Borda Dec 8, 2022
daf4390
try *
Borda Dec 8, 2022
dec5843
folders
Borda Dec 8, 2022
e95410d
Merge branch 'master' into add_support_for_running_app
tchaton Dec 8, 2022
87f11e4
Merge branch 'master' into add_support_for_running_app
tchaton Dec 8, 2022
6a0e986
Merge branch 'master' into add_support_for_running_app
tchaton Dec 8, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/lightning_app/CHANGELOG.md
Expand Up @@ -28,6 +28,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).

- Added a `configure_layout` method to the `LightningWork` which can be used to control how the work is handled in the layout of a parent flow ([#15926](https://github.com/Lightning-AI/lightning/pull/15926))

- Added the ability to run a Lightning App or Component directly from the Gallery using `lightning run app organization/name` ([#15941](https://github.com/Lightning-AI/lightning/pull/15941))


### Changed

Expand Down
154 changes: 146 additions & 8 deletions src/lightning_app/cli/cmd_install.py
Expand Up @@ -5,6 +5,7 @@
import sys
from typing import Dict, Optional, Tuple

import click
import requests
from packaging.version import Version

Expand All @@ -14,7 +15,116 @@
logger = Logger(__name__)


def gallery_component(name: str, yes_arg: bool, version_arg: str, cwd: str = None) -> None:
@click.group(name="install")
def install() -> None:
"""Install Lightning AI selfresources."""
pass


@install.command("app")
@click.argument("name", type=str)
@click.option(
"--yes",
"-y",
is_flag=True,
help="disables prompt to ask permission to create env and run install cmds",
)
@click.option(
"--version",
"-v",
type=str,
help="Specify the version to install. By default it uses 'latest'",
default="latest",
show_default=True,
)
@click.option(
"--overwrite",
"-f",
is_flag=True,
default=False,
help="When set, overwrite the app directory without asking if it already exists.",
)
def install_app(name: str, yes: bool, version: str, overwrite: bool = False) -> None:
_install_app_command(name, yes, version, overwrite=overwrite)


@install.command("component")
@click.argument("name", type=str)
@click.option(
"--yes",
"-y",
is_flag=True,
help="disables prompt to ask permission to create env and run install cmds",
)
@click.option(
"--version",
"-v",
type=str,
help="Specify the version to install. By default it uses 'latest'",
default="latest",
show_default=True,
)
def install_component(name: str, yes: bool, version: str) -> None:
_install_component_command(name, yes, version)


def _install_app_command(name: str, yes: bool, version: str, overwrite: bool = False) -> None:
if "github.com" in name:
if version != "latest":
logger.warn(
f"The provided version {version} isn't the officially supported one. "
f"The provided version will be ignored."
tchaton marked this conversation as resolved.
Show resolved Hide resolved
)
return non_gallery_app(name, yes, overwrite=overwrite)
else:
return gallery_app(name, yes, version, overwrite=overwrite)


def _install_component_command(name: str, yes: bool, version: str, overwrite: bool = False) -> None:
if "github.com" in name:
if version != "latest":
logger.warn(
f"The provided version {version} isn't the officially supported one. "
f"The provided version will be ignored."
tchaton marked this conversation as resolved.
Show resolved Hide resolved
)
return non_gallery_component(name, yes, overwrite=overwrite)
else:
return gallery_component(name, yes, version, overwrite=overwrite)


def gallery_apps_and_components(
name: str, yes_arg: bool, version_arg: str, cwd: str = None, overwrite: bool = False
) -> str:

# make sure org/app-name syntax is correct
org, app_or_component = _validate_name(name, resource_type="App OR Component", example="lightning/quick-start")

entry, kind = _resolve_entry(app_or_component, version_arg)

if kind == "app":
# give the user the chance to do a manual install
source_url, git_url, folder_name, git_sha = _show_install_app_prompt(
entry, app_or_component, org, yes_arg, resource_type="app"
)
# run installation if requested
_install_app_from_source(source_url, git_url, folder_name, cwd=cwd, overwrite=overwrite, git_sha=git_sha)

return os.path.join(os.getcwd(), folder_name, entry["appEntrypointFile"])

elif kind == "component":
# give the user the chance to do a manual install
git_url = _show_install_component_prompt(entry, app_or_component, org, yes_arg)

# run installation if requested
_install_component_from_source(git_url)

return os.path.join(os.getcwd(), entry["appEntrypointFile"])

else:
raise Exception(f"The provided {name} doesn't exist.")


def gallery_component(name: str, yes_arg: bool, version_arg: str, cwd: str = None) -> str:
# make sure org/component-name name is correct
org, component = _validate_name(name, resource_type="component", example="lightning/LAI-slack-component")

Expand All @@ -28,7 +138,9 @@ def gallery_component(name: str, yes_arg: bool, version_arg: str, cwd: str = Non
git_url = _show_install_component_prompt(component_entry, component, org, yes_arg)

# run installation if requested
_install_component(git_url)
_install_component_from_source(git_url)

return os.path.join(os.getcwd(), component_entry["appEntrypointFile"])


def non_gallery_component(gh_url: str, yes_arg: bool, cwd: str = None) -> None:
Expand All @@ -37,10 +149,10 @@ def non_gallery_component(gh_url: str, yes_arg: bool, cwd: str = None) -> None:
git_url = _show_non_gallery_install_component_prompt(gh_url, yes_arg)

# run installation if requested
_install_component(git_url)
_install_component_from_source(git_url)


def gallery_app(name: str, yes_arg: bool, version_arg: str, cwd: str = None, overwrite: bool = False) -> None:
def gallery_app(name: str, yes_arg: bool, version_arg: str, cwd: str = None, overwrite: bool = False) -> str:

# make sure org/app-name syntax is correct
org, app = _validate_name(name, resource_type="app", example="lightning/quick-start")
Expand All @@ -57,7 +169,9 @@ def gallery_app(name: str, yes_arg: bool, version_arg: str, cwd: str = None, ove
)

# run installation if requested
_install_app(source_url, git_url, folder_name, cwd=cwd, overwrite=overwrite, git_sha=git_sha)
_install_app_from_source(source_url, git_url, folder_name, cwd=cwd, overwrite=overwrite, git_sha=git_sha)

return os.path.join(os.getcwd(), folder_name, app_entry["appEntrypointFile"])


def non_gallery_app(gh_url: str, yes_arg: bool, cwd: str = None, overwrite: bool = False) -> None:
Expand All @@ -66,7 +180,7 @@ def non_gallery_app(gh_url: str, yes_arg: bool, cwd: str = None, overwrite: bool
repo_url, folder_name = _show_non_gallery_install_app_prompt(gh_url, yes_arg)

# run installation if requested
_install_app(repo_url, repo_url, folder_name, cwd=cwd, overwrite=overwrite)
_install_app_from_source(repo_url, repo_url, folder_name, cwd=cwd, overwrite=overwrite)


def _show_install_component_prompt(entry: Dict[str, str], component: str, org: str, yes_arg: bool) -> str:
Expand Down Expand Up @@ -299,6 +413,30 @@ def _validate_name(name: str, resource_type: str, example: str) -> Tuple[str, st
return org, resource


def _resolve_entry(name, version_arg) -> Tuple[Optional[Dict], Optional[str]]:
entry = None
kind = None

# resolve registry (orgs can have a private registry through their environment variables)
registry_url = _resolve_app_registry()

# load the app resource
entry = _resolve_resource(registry_url, name=name, version_arg=version_arg, resource_type="app")

if not entry:

registry_url = _resolve_component_registry()

# load the component resource
entry = _resolve_resource(registry_url, name=name, version_arg=version_arg, resource_type="component")
kind = "component" if entry else None

else:
kind = "app"

return entry, kind


def _resolve_resource(registry_url: str, name: str, version_arg: str, resource_type: str) -> Dict[str, str]:
gallery_entries = []
try:
Expand Down Expand Up @@ -381,7 +519,7 @@ def _install_with_env(repo_url: str, folder_name: str, cwd: str = None) -> None:
logger.info(m)


def _install_app(
def _install_app_from_source(
source_url: str, git_url: str, folder_name: str, cwd: str = None, overwrite: bool = False, git_sha: str = None
) -> None:
"""Installing lighting app from the `git_url`
Expand Down Expand Up @@ -458,7 +596,7 @@ def _install_app(
logger.info(m)


def _install_component(git_url: str) -> None:
def _install_component_from_source(git_url: str) -> None:
logger.info("⚡ RUN: pip install")

out = subprocess.check_output(["pip", "install", git_url])
Expand Down
78 changes: 8 additions & 70 deletions src/lightning_app/cli/lightning_cli.py
Expand Up @@ -232,7 +232,12 @@ def _run_app(
secret: tuple,
run_app_comment_commands: bool,
) -> None:
file = _prepare_file(file)

if not os.path.exists(file):
tchaton marked this conversation as resolved.
Show resolved Hide resolved
file = cmd_install.gallery_apps_and_components(file, True, "latest", overwrite=False)
if file is None:
raise Exception(f"The provided entrypoint {file} doesn't exist.")
run_app_comment_commands = True

if not cloud and cluster_id is not None:
raise click.ClickException("Using the flag --cluster-id in local execution is not supported.")
Expand Down Expand Up @@ -288,7 +293,7 @@ def run() -> None:


@run.command("app")
@click.argument("file", type=click.Path(exists=True))
@click.argument("file", type=str)
@click.option("--cloud", type=bool, default=False, is_flag=True)
@click.option(
"--cluster-id",
Expand Down Expand Up @@ -361,6 +366,7 @@ def run_app(
_main.add_command(get_list)
_main.add_command(delete)
_main.add_command(create)
_main.add_command(cmd_install.install)


@_main.command("ssh")
Expand Down Expand Up @@ -444,74 +450,6 @@ def ssh(app_name: str = None, component_name: str = None) -> None:
os.execv(ssh_path, ["-tt", f"{component_id}@{ssh_endpoint}"])


@_main.group()
def install() -> None:
"""Install a Lightning App and/or component."""


@install.command("app")
@click.argument("name", type=str)
@click.option(
"--yes",
"-y",
is_flag=True,
help="disables prompt to ask permission to create env and run install cmds",
)
@click.option(
"--version",
"-v",
type=str,
help="Specify the version to install. By default it uses 'latest'",
default="latest",
show_default=True,
)
@click.option(
"--overwrite",
"-f",
is_flag=True,
default=False,
help="When set, overwrite the app directory without asking if it already exists.",
)
def install_app(name: str, yes: bool, version: str, overwrite: bool = False) -> None:
if "github.com" in name:
if version != "latest":
logger.warn(
f"The provided version {version} isn't the officially supported one. "
f"The provided version will be ignored."
)
cmd_install.non_gallery_app(name, yes, overwrite=overwrite)
else:
cmd_install.gallery_app(name, yes, version, overwrite=overwrite)


@install.command("component")
@click.argument("name", type=str)
@click.option(
"--yes",
"-y",
is_flag=True,
help="disables prompt to ask permission to create env and run install cmds",
)
@click.option(
"--version",
"-v",
type=str,
help="Specify the version to install. By default it uses 'latest'",
default="latest",
show_default=True,
)
def install_component(name: str, yes: bool, version: str) -> None:
if "github.com" in name:
if version != "latest":
logger.warn(
f"The provided version {version} isn't the officially supported one. "
f"The provided version will be ignored."
)
cmd_install.non_gallery_component(name, yes)
else:
cmd_install.gallery_component(name, yes, version)


@_main.group()
def init() -> None:
"""Init a Lightning App and/or component."""
Expand Down