Skip to content

feat(application): add --share-token to run commands#688

Open
dima-aignostics wants to merge 2 commits into
mainfrom
feat/PYSDK-145-read-run-with-share-token
Open

feat(application): add --share-token to run commands#688
dima-aignostics wants to merge 2 commits into
mainfrom
feat/PYSDK-145-read-run-with-share-token

Conversation

@dima-aignostics

@dima-aignostics dima-aignostics commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Add --share-token argument to next commands to the uvx aignostics application run group:

describe
dump-metadata
dump-item-metadata
result download

@dima-aignostics dima-aignostics requested a review from a team as a code owner June 22, 2026 08:46
@dima-aignostics dima-aignostics force-pushed the feat/PYSDK-145-read-run-with-share-token branch 4 times, most recently from b524be7 to 9510e92 Compare June 22, 2026 11:36
@dima-aignostics dima-aignostics force-pushed the feat/PYSDK-132-add-run-sharing-to-python-sdk branch 6 times, most recently from 6ae872e to 0bc4980 Compare June 23, 2026 21:15
Base automatically changed from feat/PYSDK-132-add-run-sharing-to-python-sdk to main June 29, 2026 08:04
@dima-aignostics dima-aignostics force-pushed the feat/PYSDK-145-read-run-with-share-token branch 3 times, most recently from 5ab4c44 to 23c6793 Compare June 30, 2026 14:04
@codecov

codecov Bot commented Jun 30, 2026

Copy link
Copy Markdown

❌ 4 Tests Failed:

Tests completed Failed Passed Skipped
972 4 968 15
View the top 3 failed test(s) by shortest run time
tests.aignostics.platform.cli_test.TestAuthTokenCLI::test_auth_token_failure_json_structure
Stack Traces | 0.022s run time
record_property = <function record_property.<locals>.append_property at 0x7f1437e81b10>
runner = <typer.testing.CliRunner object at 0x7f144078dc50>

    @pytest.mark.integration
    @staticmethod
    def test_auth_token_failure_json_structure(record_property, runner: CliRunner) -> None:
        """Gcloud-compatible error JSON is written to stdout when token retrieval fails."""
        record_property("tested-item-id", "SPEC-PLATFORM-CLI")
        with patch("aignostics.platform._cli.get_token", side_effect=RuntimeError("no credentials")):
            result = runner.invoke(cli, ["auth", "token"])
    
        json_start = result.output.find("{")
>       response = json.loads(result.output[json_start:])
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.../aignostics/platform/cli_test.py:692: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../.........../_temp/uv-python-dir/cpython-3.14.3-linux-x86_64-gnu/lib/python3.14/json/__init__.py:352: in loads
    return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
../.........../_temp/uv-python-dir/cpython-3.14.3-linux-x86_64-gnu/lib/python3.14/json/decoder.py:345: in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <json.decoder.JSONDecoder object at 0x7f153ad98d70>, s = '\n', idx = 1

    def raw_decode(self, s, idx=0):
        """Decode a JSON document from ``s`` (a ``str`` beginning with
        a JSON document) and return a 2-tuple of the Python
        representation and the index in ``s`` where the document ended.
    
        This can be used to decode a JSON document from a string that may
        have extraneous data at the end.
    
        """
        try:
            obj, end = self.scan_once(s, idx)
        except StopIteration as err:
>           raise JSONDecodeError("Expecting value", s, err.value) from None
E           json.decoder.JSONDecodeError: Expecting value: line 2 column 1 (char 1)

../.........../_temp/uv-python-dir/cpython-3.14.3-linux-x86_64-gnu/lib/python3.14/json/decoder.py:363: JSONDecodeError
tests.aignostics.platform.cli_test.TestAuthTokenCLI::test_auth_token_failure_exit_code
Stack Traces | 0.023s run time
record_property = <function record_property.<locals>.append_property at 0x7f14407b3b60>
runner = <typer.testing.CliRunner object at 0x7f14407f9cd0>

    @pytest.mark.integration
    @staticmethod
    def test_auth_token_failure_exit_code(record_property, runner: CliRunner) -> None:
        """Exit code is 1 when token retrieval fails."""
        record_property("tested-item-id", "SPEC-PLATFORM-CLI")
        with patch("aignostics.platform._cli.get_token", side_effect=RuntimeError("no credentials")):
            result = runner.invoke(cli, ["auth", "token"])
    
>       assert result.exit_code == 1
E       assert 2 == 1
E        +  where 2 = <Result SystemExit(2)>.exit_code

.../aignostics/platform/cli_test.py:681: AssertionError
tests.aignostics.platform.cli_test.TestAuthTokenCLI::test_auth_token_success_json_structure
Stack Traces | 0.032s run time
record_property = <function record_property.<locals>.append_property at 0x7f144081a090>
runner = <typer.testing.CliRunner object at 0x7f1444d53cd0>

    @pytest.mark.integration
    @staticmethod
    def test_auth_token_success_json_structure(record_property, runner: CliRunner) -> None:
        """Valid gcloud external-credential-helper JSON is written to stdout on success."""
        record_property("tested-item-id", "SPEC-PLATFORM-CLI")
        stored = f"{TestAuthTokenCLI._MOCK_TOKEN}:{TestAuthTokenCLI._MOCK_EXPIRY}"
        mock_settings = MagicMock()
        mock_settings.return_value.token_file.read_text.return_value = stored
    
        with (
            patch("aignostics.platform._cli.get_token", return_value=TestAuthTokenCLI._MOCK_TOKEN),
            patch("aignostics.platform._cli.settings", mock_settings),
        ):
            result = runner.invoke(cli, ["auth", "token"])
    
        json_start = result.output.find("{")
>       response = json.loads(result.output[json_start:])
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.../aignostics/platform/cli_test.py:665: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../.........../_temp/uv-python-dir/cpython-3.14.3-linux-x86_64-gnu/lib/python3.14/json/__init__.py:352: in loads
    return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
../.........../_temp/uv-python-dir/cpython-3.14.3-linux-x86_64-gnu/lib/python3.14/json/decoder.py:345: in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <json.decoder.JSONDecoder object at 0x7f153ad98d70>, s = '\n', idx = 1

    def raw_decode(self, s, idx=0):
        """Decode a JSON document from ``s`` (a ``str`` beginning with
        a JSON document) and return a 2-tuple of the Python
        representation and the index in ``s`` where the document ended.
    
        This can be used to decode a JSON document from a string that may
        have extraneous data at the end.
    
        """
        try:
            obj, end = self.scan_once(s, idx)
        except StopIteration as err:
>           raise JSONDecodeError("Expecting value", s, err.value) from None
E           json.decoder.JSONDecodeError: Expecting value: line 2 column 1 (char 1)

../.........../_temp/uv-python-dir/cpython-3.14.3-linux-x86_64-gnu/lib/python3.14/json/decoder.py:363: JSONDecodeError
tests.aignostics.platform.cli_test.TestAuthTokenCLI::test_auth_token_success_exit_code
Stack Traces | 0.071s run time
record_property = <function record_property.<locals>.append_property at 0x7f1444d5a350>
runner = <typer.testing.CliRunner object at 0x7f145d8df650>

    @pytest.mark.integration
    @staticmethod
    def test_auth_token_success_exit_code(record_property, runner: CliRunner) -> None:
        """Exit code is 0 when a cached token is available."""
        record_property("tested-item-id", "SPEC-PLATFORM-CLI")
        stored = f"{TestAuthTokenCLI._MOCK_TOKEN}:{TestAuthTokenCLI._MOCK_EXPIRY}"
        mock_settings = MagicMock()
        mock_settings.return_value.token_file.read_text.return_value = stored
    
        with (
            patch("aignostics.platform._cli.get_token", return_value=TestAuthTokenCLI._MOCK_TOKEN),
            patch("aignostics.platform._cli.settings", mock_settings),
        ):
            result = runner.invoke(cli, ["auth", "token"])
    
>       assert result.exit_code == 0
E       assert 2 == 0
E        +  where 2 = <Result SystemExit(2)>.exit_code

.../aignostics/platform/cli_test.py:647: AssertionError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

…DK-145)

Recipients holding a share token secret can now describe a run without
OAuth login by passing --share-token <secret> to `application run describe`.
The token is used directly as the Bearer token for platform API requests.

- Adds `--share-token` option to `run describe`; when set, creates a
  `Client(token_provider=…)` bypassing OAuth, with `hide_platform_queue_position=True`
- Catches `UnauthorizedException` and `ForbiddenException` when using a share
  token and surfaces a clear "Access denied" message with exit code 1
- Adds 5 integration tests covering success (text + JSON), not-found,
  unauthorized, and forbidden paths

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dima-aignostics dima-aignostics force-pushed the feat/PYSDK-145-read-run-with-share-token branch from 23c6793 to c3c99ef Compare June 30, 2026 15:38
@dima-aignostics dima-aignostics changed the title feat(application): add --share-token to run describe CLI command (PYS… feat(application): add --share-token to run commands Jul 1, 2026
@dima-aignostics dima-aignostics force-pushed the feat/PYSDK-145-read-run-with-share-token branch from 01154f0 to 8bad631 Compare July 1, 2026 11:23
@sonarqubecloud

sonarqubecloud Bot commented Jul 1, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant