diff --git a/src/google/adk/cli/cli_create.py b/src/google/adk/cli/cli_create.py index 3e5a5b0ed9..d860e9022a 100644 --- a/src/google/adk/cli/cli_create.py +++ b/src/google/adk/cli/cli_create.py @@ -72,28 +72,31 @@ """ -def _ensure_dotenv_gitignored(agent_folder: str) -> None: - """Ensures generated secrets are excluded from version control.""" +def _ensure_generated_files_gitignored(agent_folder: str) -> None: + """Ensures generated secrets and runtime data are excluded from version control.""" gitignore_file_path = os.path.join(agent_folder, ".gitignore") - dotenv_entry = ".env" + generated_entries = (".env", ".adk/") if not os.path.exists(gitignore_file_path): with open(gitignore_file_path, "w", encoding="utf-8") as f: - f.write(f"{dotenv_entry}\n") + f.write("\n".join(generated_entries) + "\n") return with open(gitignore_file_path, "r", encoding="utf-8") as f: content = f.read() existing_lines = content.splitlines() - if dotenv_entry in existing_lines: + missing_entries = tuple( + entry for entry in generated_entries if entry not in existing_lines + ) + if not missing_entries: return - # Append .env, ensuring proper newline separation. + # Append generated entries, ensuring proper newline separation. with open(gitignore_file_path, "a", encoding="utf-8") as f: if content and not content.endswith("\n"): f.write("\n") - f.write(f"{dotenv_entry}\n") + f.write("\n".join(missing_entries) + "\n") def _generate_files( @@ -126,7 +129,7 @@ def _generate_files( if google_cloud_region: lines.append(f"GOOGLE_CLOUD_LOCATION={google_cloud_region}") f.write("\n".join(lines)) - _ensure_dotenv_gitignored(agent_folder) + _ensure_generated_files_gitignored(agent_folder) if type == "config": with open(agent_config_file_path, "w", encoding="utf-8") as f: diff --git a/tests/unittests/cli/utils/test_cli_create.py b/tests/unittests/cli/utils/test_cli_create.py index 98e0a92f88..6265342ece 100644 --- a/tests/unittests/cli/utils/test_cli_create.py +++ b/tests/unittests/cli/utils/test_cli_create.py @@ -69,7 +69,7 @@ def test_generate_files_with_api_key(agent_folder: Path) -> None: env_content = (agent_folder / ".env").read_text() assert "GOOGLE_API_KEY=dummy-key" in env_content assert "GOOGLE_GENAI_USE_ENTERPRISE=0" in env_content - assert (agent_folder / ".gitignore").read_text() == ".env\n" + assert (agent_folder / ".gitignore").read_text() == ".env\n.adk/\n" assert (agent_folder / "agent.py").exists() assert (agent_folder / "__init__.py").exists() @@ -151,7 +151,7 @@ def test_generate_files_no_params(agent_folder: Path) -> None: assert key not in env_content -def test_generate_files_appends_dotenv_to_existing_gitignore( +def test_generate_files_appends_generated_entries_to_existing_gitignore( agent_folder: Path, ) -> None: """Existing .gitignore entries should be preserved.""" @@ -162,10 +162,12 @@ def test_generate_files_appends_dotenv_to_existing_gitignore( str(agent_folder), model="gemini-2.0-flash-001", type="code" ) - assert (agent_folder / ".gitignore").read_text() == "__pycache__\n.env\n" + assert ( + agent_folder / ".gitignore" + ).read_text() == "__pycache__\n.env\n.adk/\n" -def test_generate_files_appends_dotenv_to_existing_gitignore_with_newline( +def test_generate_files_appends_generated_entries_to_existing_gitignore_with_newline( agent_folder: Path, ) -> None: """Existing .gitignore entries ending in a newline should not cause extra blank lines.""" @@ -176,13 +178,31 @@ def test_generate_files_appends_dotenv_to_existing_gitignore_with_newline( str(agent_folder), model="gemini-2.0-flash-001", type="code" ) - assert (agent_folder / ".gitignore").read_text() == "__pycache__\n.env\n" + assert ( + agent_folder / ".gitignore" + ).read_text() == "__pycache__\n.env\n.adk/\n" -def test_generate_files_does_not_duplicate_dotenv_gitignore_entry( +def test_generate_files_does_not_duplicate_generated_gitignore_entries( agent_folder: Path, ) -> None: - """Existing .env ignore entries should not be duplicated.""" + """Existing generated-file entries should not be duplicated.""" + agent_folder.mkdir(parents=True, exist_ok=True) + (agent_folder / ".gitignore").write_text("__pycache__\n.env\n.adk/\n") + + cli_create._generate_files( + str(agent_folder), model="gemini-2.0-flash-001", type="code" + ) + + assert ( + agent_folder / ".gitignore" + ).read_text() == "__pycache__\n.env\n.adk/\n" + + +def test_generate_files_adds_missing_runtime_entry( + agent_folder: Path, +) -> None: + """Existing .env entries should not prevent adding the runtime directory.""" agent_folder.mkdir(parents=True, exist_ok=True) (agent_folder / ".gitignore").write_text("__pycache__\n.env\n") @@ -190,7 +210,9 @@ def test_generate_files_does_not_duplicate_dotenv_gitignore_entry( str(agent_folder), model="gemini-2.0-flash-001", type="code" ) - assert (agent_folder / ".gitignore").read_text() == "__pycache__\n.env\n" + assert ( + agent_folder / ".gitignore" + ).read_text() == "__pycache__\n.env\n.adk/\n" # run_cmd @@ -274,7 +296,7 @@ def test_run_cmd_with_type_config( env_file = agent_dir / ".env" assert env_file.exists() assert "GOOGLE_API_KEY=test-key" in env_file.read_text() - assert (agent_dir / ".gitignore").read_text() == ".env\n" + assert (agent_dir / ".gitignore").read_text() == ".env\n.adk/\n" # Prompt helpers