Skip to content

Commit 0662c00

Browse files
author
Dylan Huang
committed
Add support for uploading secrets from .env file in CLI
- Introduced `--env-file` argument in the CLI for specifying the path to the .env file containing secrets. - Refactored the upload process to include a new function `upload_secrets_to_fireworks` that handles the uploading of secrets. - Updated the `upload_command` to optionally skip secret uploads if already handled. - Enhanced the evaluator upload process to ensure secrets are uploaded before ensuring evaluator existence.
1 parent 8e2686b commit 0662c00

File tree

3 files changed

+67
-24
lines changed

3 files changed

+67
-24
lines changed

eval_protocol/cli.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ def _configure_parser(parser: argparse.ArgumentParser) -> argparse.ArgumentParse
156156
metavar="",
157157
help="Extra flags to pass to 'docker run' when validating evaluator (quoted string, e.g. \"--env-file .env --memory=8g\")",
158158
)
159+
rft_parser.add_argument(
160+
"--env-file",
161+
metavar="",
162+
help="Path to .env file containing secrets to upload to Fireworks (default: .env in project root)",
163+
)
159164

160165
# The flags below are Eval Protocol CLI workflow controls (not part of the Fireworks SDK `create()` signature),
161166
# so they can’t be auto-generated via signature introspection and must be maintained here.

eval_protocol/cli_commands/create_rft.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
materialize_dataset_via_builder,
2020
)
2121
from ..models import EvaluationRow
22-
from .upload import upload_command
22+
from .upload import upload_command, upload_secrets_to_fireworks
2323
from .utils import (
2424
_build_entry_point,
2525
_build_trimmed_dataset_id,
@@ -569,6 +569,8 @@ def _upload_and_ensure_evaluator(
569569
api_key: str,
570570
api_base: str,
571571
force: bool,
572+
env_file: Optional[str] = None,
573+
non_interactive: bool = False,
572574
) -> bool:
573575
"""Ensure the evaluator exists and is ACTIVE, uploading it if needed."""
574576
# Optional short-circuit: if evaluator already exists and not forcing, skip upload path
@@ -600,6 +602,13 @@ def _upload_and_ensure_evaluator(
600602
except requests.exceptions.RequestException:
601603
pass
602604

605+
# Upload secrets before ensuring evaluator exists
606+
upload_secrets_to_fireworks(
607+
root=project_root,
608+
env_file=env_file,
609+
non_interactive=non_interactive,
610+
)
611+
603612
# Ensure evaluator exists by invoking the upload flow programmatically
604613
try:
605614
tests = _discover_tests(project_root)
@@ -625,13 +634,13 @@ def _upload_and_ensure_evaluator(
625634
description=None,
626635
force=force, # Pass through the --force flag
627636
yes=True,
628-
env_file=None, # Add the new env_file parameter
637+
env_file=None, # Secrets already handled above via upload_secrets_to_fireworks
629638
)
630639

631640
if force:
632641
print(f"🔄 Force flag enabled - will overwrite existing evaluator '{evaluator_id}'")
633642

634-
rc = upload_command(upload_args)
643+
rc = upload_command(upload_args, skip_secrets=True) # Secrets already handled above
635644
if rc == 0:
636645
print(f"✓ Uploaded/ensured evaluator: {evaluator_id}")
637646

@@ -811,13 +820,16 @@ def create_rft_command(args) -> int:
811820
return 1
812821

813822
# 5) Ensure evaluator exists and is ACTIVE (upload + poll if needed)
823+
env_file: Optional[str] = getattr(args, "env_file", None)
814824
if not _upload_and_ensure_evaluator(
815825
project_root=project_root,
816826
evaluator_id=evaluator_id,
817827
evaluator_resource_name=evaluator_resource_name,
818828
api_key=api_key,
819829
api_base=api_base,
820830
force=force,
831+
env_file=env_file,
832+
non_interactive=non_interactive,
821833
):
822834
return 1
823835

eval_protocol/cli_commands/upload.py

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -270,29 +270,24 @@ def _prompt_select_secrets_fallback(
270270
return {}
271271

272272

273-
def upload_command(args: argparse.Namespace) -> int:
274-
root = os.path.abspath(getattr(args, "path", "."))
275-
entries_arg = getattr(args, "entry", None)
276-
non_interactive: bool = bool(getattr(args, "yes", False))
277-
if entries_arg:
278-
entries = [e.strip() for e in re.split(r"[,\s]+", entries_arg) if e.strip()]
279-
selected_specs: list[tuple[str, str]] = []
280-
for e in entries:
281-
qualname, resolved_path = _resolve_entry_to_qual_and_source(e, root)
282-
selected_specs.append((qualname, resolved_path))
283-
else:
284-
selected_tests: list[DiscoveredTest] | None = _discover_and_select_tests(root, non_interactive=non_interactive)
285-
if not selected_tests:
286-
return 1
287-
selected_specs = [(t.qualname, t.file_path) for t in selected_tests]
273+
def upload_secrets_to_fireworks(
274+
root: str,
275+
env_file: str | None = None,
276+
non_interactive: bool = False,
277+
) -> None:
278+
"""
279+
Upload secrets from .env file and environment to Fireworks.
288280
289-
base_id = getattr(args, "id", None)
290-
display_name = getattr(args, "display_name", None)
291-
description = getattr(args, "description", None)
292-
force = bool(getattr(args, "force", False))
293-
env_file = getattr(args, "env_file", None)
281+
This function:
282+
1. Loads secrets from the specified .env file (or default .env in root)
283+
2. Prompts user to select which secrets to upload (unless non_interactive)
284+
3. Creates/updates the selected secrets on Fireworks
294285
295-
# Load secrets from .env file and ensure they're available on Fireworks
286+
Args:
287+
root: The project root directory
288+
env_file: Optional path to a .env file. If None, uses {root}/.env
289+
non_interactive: If True, skip interactive prompts and upload all secrets
290+
"""
296291
try:
297292
fw_account_id = _ensure_account_id()
298293

@@ -350,6 +345,37 @@ def upload_command(args: argparse.Namespace) -> int:
350345
except Exception as e:
351346
print(f"Warning: Skipped Fireworks secret registration due to error: {e}")
352347

348+
349+
def upload_command(args: argparse.Namespace, skip_secrets: bool = False) -> int:
350+
root = os.path.abspath(getattr(args, "path", "."))
351+
entries_arg = getattr(args, "entry", None)
352+
non_interactive: bool = bool(getattr(args, "yes", False))
353+
if entries_arg:
354+
entries = [e.strip() for e in re.split(r"[,\s]+", entries_arg) if e.strip()]
355+
selected_specs: list[tuple[str, str]] = []
356+
for e in entries:
357+
qualname, resolved_path = _resolve_entry_to_qual_and_source(e, root)
358+
selected_specs.append((qualname, resolved_path))
359+
else:
360+
selected_tests: list[DiscoveredTest] | None = _discover_and_select_tests(root, non_interactive=non_interactive)
361+
if not selected_tests:
362+
return 1
363+
selected_specs = [(t.qualname, t.file_path) for t in selected_tests]
364+
365+
base_id = getattr(args, "id", None)
366+
display_name = getattr(args, "display_name", None)
367+
description = getattr(args, "description", None)
368+
force = bool(getattr(args, "force", False))
369+
env_file = getattr(args, "env_file", None)
370+
371+
# Upload secrets from .env file and environment to Fireworks
372+
if not skip_secrets:
373+
upload_secrets_to_fireworks(
374+
root=root,
375+
env_file=env_file,
376+
non_interactive=non_interactive,
377+
)
378+
353379
exit_code = 0
354380
for i, (qualname, source_file_path) in enumerate(selected_specs):
355381
# Generate a short default ID from just the test function name

0 commit comments

Comments
 (0)