Skip to content

Commit c84f92c

Browse files
committed
misc fixes
1 parent 11290c1 commit c84f92c

File tree

9 files changed

+158
-15
lines changed

9 files changed

+158
-15
lines changed

python_modules/libraries/dagster-components/dagster_components/cli/list.py

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ def list_all_components_schema_command(entry_points: bool, extra_modules: tuple[
7070
key.name,
7171
type=(Literal[key_string], key_string),
7272
attributes=(schema_type, None),
73+
requires=(dict[str, list[str]], None),
7374
__config__=ConfigDict(extra="forbid"),
7475
)
7576
)

python_modules/libraries/dagster-dg/dagster_dg/check.py

+2-5
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,7 @@ def check_yaml(
196196
)
197197
if updated_files:
198198
click.echo(
199-
"The following component files were updated to fix environment variable requirements:\n"
200-
+ "\n".join(updated_files)
199+
f"{len(updated_files)} component files were updated to fix environment variable requirements."
201200
)
202201
return False
203202
else:
@@ -206,10 +205,8 @@ def check_yaml(
206205
) - os.environ.keys()
207206
if updated_files:
208207
click.echo(
209-
"The following component files were updated to fix environment variable requirements:\n"
210-
+ "\n".join(str(file) for file in updated_files)
208+
f"{len(updated_files)} component files were updated to fix environment variable requirements."
211209
)
212-
213210
if missing_env_vars:
214211
click.echo(
215212
"The following environment variables are used in components but not specified in the .env file or the current shell environment:\n"

python_modules/libraries/dagster-dg/dagster_dg/cli/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from dagster_dg.cache import DgCache
66
from dagster_dg.cli.check import check_group
7+
from dagster_dg.cli.deploy import deploy_command
78
from dagster_dg.cli.dev import dev_command
89
from dagster_dg.cli.docs import docs_group
910
from dagster_dg.cli.env import env_group
@@ -37,6 +38,7 @@ def create_dg_cli():
3738
"dev": dev_command,
3839
"init": init_command,
3940
"plus": plus_group,
41+
"deploy": deploy_command,
4042
},
4143
context_settings={
4244
"max_content_width": DG_CLI_MAX_OUTPUT_WIDTH,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
from pathlib import Path
2+
3+
import click
4+
from dagster_shared.plus.config import DagsterPlusCliConfig
5+
6+
from dagster_dg.cli.shared_options import dg_global_options
7+
from dagster_dg.config import normalize_cli_config
8+
from dagster_dg.context import DgContext
9+
from dagster_dg.env import ProjectEnvVars, get_project_specified_env_vars
10+
from dagster_dg.utils import DgClickCommand
11+
from dagster_dg.utils.plus import gql
12+
from dagster_dg.utils.plus.gql_client import DagsterCloudGraphQLClient
13+
from dagster_dg.utils.telemetry import cli_telemetry_wrapper
14+
15+
# ########################
16+
# ##### ENVIRONMENT
17+
# ########################
18+
19+
20+
@click.command(name="deploy", cls=DgClickCommand)
21+
@dg_global_options
22+
@cli_telemetry_wrapper
23+
def deploy_command(**global_options: object) -> None:
24+
"""Deploy a Dagster project."""
25+
cli_config = normalize_cli_config(global_options, click.get_current_context())
26+
dg_context = DgContext.for_project_environment(Path.cwd(), cli_config)
27+
28+
env_vars = get_project_specified_env_vars(dg_context)
29+
30+
env = ProjectEnvVars.from_ctx(dg_context)
31+
32+
env_var_keys = set(env.values.keys()) | set(env_vars.keys())
33+
34+
if DagsterPlusCliConfig.exists():
35+
scopes_for_key = {}
36+
config = DagsterPlusCliConfig.get()
37+
gql_client = DagsterCloudGraphQLClient.from_config(config)
38+
for key in env_var_keys:
39+
secrets_by_location = gql_client.execute(
40+
gql.GET_SECRETS_FOR_SCOPES_QUERY,
41+
{
42+
"locationName": dg_context.project_name,
43+
"scopes": {
44+
"fullDeploymentScope": True,
45+
"allBranchDeploymentsScope": True,
46+
"localDeploymentScope": True,
47+
},
48+
"secretName": key,
49+
},
50+
)["secretsForScopes"]["secrets"]
51+
scopes_for_key[key] = {
52+
"full": any(secret["fullDeploymentScope"] for secret in secrets_by_location),
53+
"branch": any(
54+
secret["allBranchDeploymentsScope"] for secret in secrets_by_location
55+
),
56+
"local": any(secret["localDeploymentScope"] for secret in secrets_by_location),
57+
}
58+
59+
if not all(scopes_for_key[key]["full"] for key in env_var_keys):
60+
click.echo(
61+
f"Missing environment variables for deployment {config.default_deployment} in full deployment scope, for location {dg_context.project_name}:"
62+
)
63+
for key in env_var_keys:
64+
if not scopes_for_key[key]["full"]:
65+
click.echo(f" {key}")
66+
import sys
67+
68+
sys.exit(1)

python_modules/libraries/dagster-dg/dagster_dg/cli/dev.py

+1
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ def dev_command(
146146
check_result = check_yaml_fn(
147147
dg_context.for_project_environment(project_dir, cli_config),
148148
[],
149+
fix_env_requirements=False,
149150
)
150151
overall_check_result = overall_check_result and check_result
151152
if not overall_check_result:

python_modules/libraries/dagster-dg/dagster_dg/cli/env.py

+55-7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import click
55
import yaml
6+
from dagster_shared.plus.config import DagsterPlusCliConfig
67
from dagster_shared.yaml_utils import parse_yaml_with_source_positions
78
from rich.console import Console
89
from rich.table import Table
@@ -12,8 +13,10 @@
1213
from dagster_dg.component import get_specified_env_var_deps, get_used_env_vars
1314
from dagster_dg.config import normalize_cli_config
1415
from dagster_dg.context import DgContext
15-
from dagster_dg.env import ProjectEnvVars
16+
from dagster_dg.env import ProjectEnvVars, get_project_specified_env_vars
1617
from dagster_dg.utils import DgClickCommand, DgClickGroup
18+
from dagster_dg.utils.plus import gql
19+
from dagster_dg.utils.plus.gql_client import DagsterCloudGraphQLClient
1720
from dagster_dg.utils.telemetry import cli_telemetry_wrapper
1821

1922

@@ -35,16 +38,61 @@ def list_env_command(**global_options: object) -> None:
3538
cli_config = normalize_cli_config(global_options, click.get_current_context())
3639
dg_context = DgContext.for_project_environment(Path.cwd(), cli_config)
3740

41+
env_vars = get_project_specified_env_vars(dg_context)
42+
3843
env = ProjectEnvVars.from_ctx(dg_context)
39-
if not env.values:
40-
click.echo("No environment variables are defined for this project.")
41-
return
4244

4345
table = Table(border_style="dim")
4446
table.add_column("Env Var")
45-
table.add_column("Value")
46-
for key, value in env.values.items():
47-
table.add_row(key, value)
47+
table.add_column("Local Value")
48+
table.add_column("Components")
49+
env_var_keys = set(env.values.keys()) | set(env_vars.keys())
50+
51+
if DagsterPlusCliConfig.exists():
52+
table.add_column("Dev")
53+
table.add_column("Branch")
54+
table.add_column("Full")
55+
scopes_for_key = {}
56+
config = DagsterPlusCliConfig.get()
57+
gql_client = DagsterCloudGraphQLClient.from_config(config)
58+
for key in env_var_keys:
59+
secrets_by_location = gql_client.execute(
60+
gql.GET_SECRETS_FOR_SCOPES_QUERY,
61+
{
62+
"locationName": dg_context.project_name,
63+
"scopes": {
64+
"fullDeploymentScope": True,
65+
"allBranchDeploymentsScope": True,
66+
"localDeploymentScope": True,
67+
},
68+
"secretName": key,
69+
},
70+
)["secretsForScopes"]["secrets"]
71+
scopes_for_key[key] = {
72+
"full": any(secret["fullDeploymentScope"] for secret in secrets_by_location),
73+
"branch": any(
74+
secret["allBranchDeploymentsScope"] for secret in secrets_by_location
75+
),
76+
"local": any(secret["localDeploymentScope"] for secret in secrets_by_location),
77+
}
78+
79+
if not env_var_keys:
80+
click.echo("No environment variables are defined for this project.")
81+
return
82+
83+
for key in env_var_keys:
84+
value = env.values.get(key)
85+
components = env_vars.get(key, [])
86+
table.add_row(
87+
key,
88+
value,
89+
", ".join(str(path) for path in components),
90+
*(
91+
["X" if scopes_for_key[key][scope] else "" for scope in ["local", "branch", "full"]]
92+
if DagsterPlusCliConfig.exists()
93+
else []
94+
),
95+
)
4896
console = Console()
4997
console.print(table)
5098

python_modules/libraries/dagster-dg/dagster_dg/cli/plus.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ def pull_env_command(**global_options: object) -> None:
141141
secrets_by_location[project_ctx.project_name]
142142
)
143143
env.write()
144-
projects_without_secrets.remove(project_ctx.project_name)
144+
if project_ctx.project_name in projects_without_secrets:
145+
projects_without_secrets.remove(project_ctx.project_name)
145146

146147
if dg_context.is_project:
147148
click.echo("Environment variables saved to .env")

python_modules/libraries/dagster-dg/dagster_dg/env.py

+26-1
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,38 @@
1-
from collections.abc import Mapping
1+
from collections import defaultdict
2+
from collections.abc import Mapping, Sequence
3+
from pathlib import Path
24
from typing import Optional
35

46
from dagster_shared import check
7+
from dagster_shared.yaml_utils import parse_yaml_with_source_positions
58
from dotenv import dotenv_values
69
from typing_extensions import Self
10+
from yaml.scanner import ScannerError
711

12+
from dagster_dg.component import get_specified_env_var_deps
813
from dagster_dg.context import DgContext
914

1015

16+
def get_project_specified_env_vars(dg_context: DgContext) -> Mapping[str, Sequence[Path]]:
17+
env_vars = defaultdict(list)
18+
for component_dir in dg_context.defs_path.iterdir():
19+
component_path = component_dir / "component.yaml"
20+
21+
if component_path.exists():
22+
text = component_path.read_text()
23+
try:
24+
component_doc_tree = parse_yaml_with_source_positions(
25+
text, filename=str(component_path)
26+
)
27+
except ScannerError:
28+
continue
29+
30+
specified_env_var_deps = get_specified_env_var_deps(component_doc_tree.value)
31+
for key in specified_env_var_deps:
32+
env_vars[key].append(component_path.relative_to(dg_context.defs_path).parent)
33+
return env_vars
34+
35+
1136
class ProjectEnvVars:
1237
"""Represents the environment for a project, stored in the .env file of a
1338
project root.

python_modules/libraries/dagster-dg/dagster_dg/utils/editor/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def install_or_update_yaml_schema_extension(
5959
template_package_json_path = Path(__file__).parent / "vscode_extension_package.json"
6060
template_package_json = json.loads(template_package_json_path.read_text())
6161
template_package_json["contributes"]["yamlValidation"] = [
62-
{"fileMatch": f"{yaml_dir}/**/*.y*ml", "url": f"{schema_path}"}
62+
{"fileMatch": f"{yaml_dir}/**/component.y*ml", "url": f"{schema_path}"}
6363
]
6464

6565
extension_working_dir.mkdir(parents=True, exist_ok=True)

0 commit comments

Comments
 (0)