diff --git a/roar/application/publish/service.py b/roar/application/publish/service.py index 05ed555..829c523 100644 --- a/roar/application/publish/service.py +++ b/roar/application/publish/service.py @@ -365,112 +365,118 @@ def _run_git(path: Path, *args: str) -> str | None: def register_lineage_target(request: RegisterLineageRequest) -> RegisterLineageResponse: """Run the `roar register` application workflow.""" + from ...publish_auth import PublishAuthError + if not request.dry_run: bootstrap(request.roar_dir) logger = get_logger() - resolved_target = resolve_register_lineage_target( - request.target, - cwd=request.cwd, - roar_dir=request.roar_dir, - ) - runtime = ( - build_register_preview_runtime( - start_dir=str(request.cwd), - allow_public_without_binding=request.public, + + try: + resolved_target = resolve_register_lineage_target( + request.target, + cwd=request.cwd, + roar_dir=request.roar_dir, ) - if request.dry_run - else build_publish_runtime( - glaas_url=get_glaas_url(), - start_dir=str(request.cwd), - allow_public_without_binding=request.public, + runtime = ( + build_register_preview_runtime( + start_dir=str(request.cwd), + allow_public_without_binding=request.public, + ) + if request.dry_run + else build_publish_runtime( + glaas_url=get_glaas_url(), + start_dir=str(request.cwd), + allow_public_without_binding=request.public, + ) ) - ) - collected_lineage, error = collect_register_lineage( - target=resolved_target, - roar_dir=request.roar_dir, - cwd=request.cwd, - lineage_collector=runtime.lineage_collector, - session_service=runtime.session_service, - logger=logger, - dry_run=request.dry_run, - ) - if collected_lineage is None: - return RegisterLineageResponse(success=False, error=error) + collected_lineage, error = collect_register_lineage( + target=resolved_target, + roar_dir=request.roar_dir, + cwd=request.cwd, + lineage_collector=runtime.lineage_collector, + session_service=runtime.session_service, + logger=logger, + dry_run=request.dry_run, + ) + if collected_lineage is None: + return RegisterLineageResponse(success=False, error=error) + + try: + if request.dry_run: + prepared = prepare_register_preview_execution( + runtime=runtime, + roar_dir=request.roar_dir, + cwd=request.cwd, + session_id=collected_lineage.session_id, + session_hash_override=collected_lineage.session_hash_override, + logger=logger, + lineage=collected_lineage.lineage, + ) + else: + prepared = prepare_register_execution( + runtime=runtime, + roar_dir=request.roar_dir, + cwd=request.cwd, + session_id=collected_lineage.session_id, + dry_run=False, + session_hash_override=collected_lineage.session_hash_override, + logger=logger, + lineage=collected_lineage.lineage, + ) + except ValueError as exc: + return RegisterLineageResponse( + success=False, + artifact_hash=collected_lineage.artifact_hash, + error=str(exc), + ) - try: if request.dry_run: - prepared = prepare_register_preview_execution( - runtime=runtime, - roar_dir=request.roar_dir, - cwd=request.cwd, - session_id=collected_lineage.session_id, - session_hash_override=collected_lineage.session_hash_override, - logger=logger, + return preview_register_lineage( lineage=collected_lineage.lineage, - ) - else: - prepared = prepare_register_execution( - runtime=runtime, - roar_dir=request.roar_dir, + artifact_hash=collected_lineage.artifact_hash, + prepared=prepared, cwd=request.cwd, - session_id=collected_lineage.session_id, - dry_run=False, - session_hash_override=collected_lineage.session_hash_override, - logger=logger, - lineage=collected_lineage.lineage, + skip_confirmation=request.skip_confirmation, + confirm_callback=request.confirm_callback, ) - except ValueError as exc: - return RegisterLineageResponse( - success=False, - artifact_hash=collected_lineage.artifact_hash, - error=str(exc), - ) - if request.dry_run: - return preview_register_lineage( + service = RegisterService( + glaas_client=runtime.glaas_client, + coordinator=runtime.registration_coordinator, + ) + result = service.register_prepared_lineage( lineage=collected_lineage.lineage, + roar_dir=request.roar_dir, artifact_hash=collected_lineage.artifact_hash, - prepared=prepared, - cwd=request.cwd, + dry_run=request.dry_run, + as_blake3=request.as_blake3, skip_confirmation=request.skip_confirmation, confirm_callback=request.confirm_callback, + prepared=prepared, ) - service = RegisterService( - glaas_client=runtime.glaas_client, - coordinator=runtime.registration_coordinator, - ) - result = service.register_prepared_lineage( - lineage=collected_lineage.lineage, - roar_dir=request.roar_dir, - artifact_hash=collected_lineage.artifact_hash, - dry_run=request.dry_run, - as_blake3=request.as_blake3, - skip_confirmation=request.skip_confirmation, - confirm_callback=request.confirm_callback, - prepared=prepared, - ) - - finalize_register_git( - result_success=result.success, - dry_run=request.dry_run, - git_tag_name=prepared.git_tag_name, - git_tag_repo_root=prepared.git_tag_repo_root, - logger=logger, - ) + finalize_register_git( + result_success=result.success, + dry_run=request.dry_run, + git_tag_name=prepared.git_tag_name, + git_tag_repo_root=prepared.git_tag_repo_root, + logger=logger, + ) - return RegisterLineageResponse( - success=result.success, - session_hash=result.session_hash, - artifact_hash=result.artifact_hash, - jobs_registered=result.jobs_registered, - artifacts_registered=result.artifacts_registered, - links_created=result.links_created, - error=result.error, - secrets_detected=list(result.secrets_detected), - secrets_redacted=result.secrets_redacted, - aborted_by_user=result.aborted_by_user, - ) + return RegisterLineageResponse( + success=result.success, + session_hash=result.session_hash, + artifact_hash=result.artifact_hash, + jobs_registered=result.jobs_registered, + artifacts_registered=result.artifacts_registered, + links_created=result.links_created, + error=result.error, + secrets_detected=list(result.secrets_detected), + secrets_redacted=result.secrets_redacted, + aborted_by_user=result.aborted_by_user, + ) + except PublishAuthError as exc: + return RegisterLineageResponse(success=False, error=str(exc)) def put_artifacts(request: PutRequest) -> PutResponse: diff --git a/roar/publish_auth.py b/roar/publish_auth.py index 0a25192..77fecc4 100644 --- a/roar/publish_auth.py +++ b/roar/publish_auth.py @@ -11,6 +11,10 @@ from .auth_store import load_auth_state +class PublishAuthError(RuntimeError): + """Raised when publish auth or repo binding requirements are not satisfied.""" + + @dataclass(frozen=True) class PublishAuthContext: access_token: str | None @@ -38,11 +42,11 @@ def load_publish_auth_context( binding = _load_repo_binding(start_dir) if binding and not access_token: - raise RuntimeError( + raise PublishAuthError( "Repo is linked to GLaaS but no global auth state is available. Run `roar login`." ) if not binding and not allow_public_without_binding: - raise RuntimeError( + raise PublishAuthError( "No GLaaS repo binding found for this publish. Link the repo to a TReqs owner/project first, or rerun with --public to publish publicly." ) diff --git a/tests/integration/test_public_publish_intent_cli.py b/tests/integration/test_public_publish_intent_cli.py index 3b82c58..4a50f10 100644 --- a/tests/integration/test_public_publish_intent_cli.py +++ b/tests/integration/test_public_publish_intent_cli.py @@ -101,8 +101,10 @@ def test_register_requires_explicit_public_flag_when_repo_has_no_binding( assert result.returncode != 0 combined = f"{result.stdout}\n{result.stderr}" - assert "No GLaaS repo binding found" in combined + assert "Error: No GLaaS repo binding found" in combined assert "--public" in combined + assert "Traceback (most recent call last)" not in combined + assert "RuntimeError:" not in combined assert fake_glaas_publish_server.session_registrations == []