Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions lib/python/base_cli/_lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from ._runtime import refresh_run_bundle_index
from .context import Context
from .exit_codes import ExitCode
from .history import format_timestamp
from .history import compact_optional_path, format_timestamp


@dataclass(frozen=True)
Expand Down Expand Up @@ -104,9 +104,9 @@ def _metadata(self, *, status: str) -> dict[str, Any]:
"status": status,
"started_at": format_timestamp(self.started_at),
"project": context.project_name,
"project_root": str(context.project_root) if context.project_root else None,
"manifest": str(context.manifest_path) if context.manifest_path else None,
"workspace_root": str(context.workspace_root) if context.workspace_root else None,
"project_root": compact_optional_path(context.project_root),
"manifest": compact_optional_path(context.manifest_path),
"workspace_root": compact_optional_path(context.workspace_root),
# ``--keep-temp`` is an explicit request to retain diagnostics;
# retention therefore protects the complete invocation bundle,
# not only its temporary directory.
Expand Down
6 changes: 3 additions & 3 deletions lib/python/base_cli/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
from .context import Context, recover_current_context, reset_current_context, set_current_context
from .errors import ConfigurationError
from .exit_codes import ExitCode
from .history import utc_now
from .history import compact_optional_path, utc_now
from .integrations import TelemetryOptions, TelemetrySession, finish_telemetry, start_telemetry
from .json_contracts import dumps_envelope, error_envelope, success_envelope
from .lifecycle_options import (
Expand Down Expand Up @@ -1291,8 +1291,8 @@ def _create_context(
{
"schema_version": 1,
"project": selected_project_name,
"project_root": str(selected_project_root),
"manifest": str(manifest_path) if manifest_path is not None else None,
"project_root": compact_optional_path(selected_project_root),
"manifest": compact_optional_path(manifest_path),
"checkout_id": layout.owner_root.name,
},
)
Expand Down
44 changes: 44 additions & 0 deletions tests/test_app_run_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,50 @@ def main(ctx: base_cli.Context) -> None:
self.assertEqual(metadata["project_root"], str(Path("/tmp/bound-project").resolve()))
self.assertEqual(metadata["manifest"], str(Path("/tmp/bound-project/project.yml").resolve()))

def test_metadata_and_identity_compact_home_paths(self) -> None:
with tempfile.TemporaryDirectory() as tmpdir:
home = Path(tmpdir)
project = home / "project"
manifest = project / "project.yml"
project.mkdir()
manifest.write_text("name: demo\n", encoding="utf-8")

def discover(_cwd: Path) -> base_cli.ProjectInfo:
return base_cli.ProjectInfo(root=project, manifest=manifest, name="demo")

base_profile = base_cli.CliProfile.generic(
cache_root=home / "cache",
discover_project=discover,
)

def resolve_runtime(
cli_name: str,
project_info: base_cli.ProjectInfo | None,
) -> base_cli.RuntimeBinding:
binding = base_profile.resolve_runtime(cli_name, project_info)
return replace(binding, write_identity=True)

profile = replace(base_profile, resolve_runtime=resolve_runtime)
app = base_cli.App(name="metadata-path-compaction", profile=profile)

@app.command()
def main(ctx: base_cli.Context) -> None:
del ctx

status, _ = _run(app, home)
metadata_path, metadata = _load_only_metadata(self, home)
identity_paths = sorted((home / "cache").glob("**/identity.json"))
self.assertEqual(status, 0)
self.assertEqual(len(identity_paths), 1, identity_paths)
identity = json.loads(identity_paths[0].read_text(encoding="utf-8"))
metadata_text = metadata_path.read_text(encoding="utf-8")

self.assertEqual(metadata["project_root"], "~/project")
self.assertEqual(metadata["manifest"], "~/project/project.yml")
self.assertEqual(identity["project_root"], "~/project")
self.assertEqual(identity["manifest"], "~/project/project.yml")
self.assertNotIn(str(home), metadata_text)

def test_parse_error_and_no_file_modes_do_not_own_run_metadata(self) -> None:
with tempfile.TemporaryDirectory() as tmpdir:
home = Path(tmpdir)
Expand Down
Loading