From 14fe731e42f99678b8bb38ac544761fafc3dd06c Mon Sep 17 00:00:00 2001 From: Paul McGuckin Date: Fri, 30 Oct 2026 14:51:46 +0000 Subject: [PATCH 1/4] Add skills to upstream definitions --- cloudsmith_cli/cli/commands/upstream.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cloudsmith_cli/cli/commands/upstream.py b/cloudsmith_cli/cli/commands/upstream.py index 8f23e316..3178d93f 100644 --- a/cloudsmith_cli/cli/commands/upstream.py +++ b/cloudsmith_cli/cli/commands/upstream.py @@ -37,6 +37,7 @@ "python", "rpm", "ruby", + "skills", "swift", ] From 6bbb4a8da5bd9d726fa5b0dccc642b6c9ace06c3 Mon Sep 17 00:00:00 2001 From: Paul McGuckin Date: Fri, 30 Oct 2026 14:51:50 +0000 Subject: [PATCH 2/4] Bump Cloudsmith API release --- pyproject.toml | 2 +- uv.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 52229650..4501ac09 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,7 +45,7 @@ dependencies = [ "click-didyoumean>=0.0.3", "click-spinner>=0.1.7", "json5>=0.9.0", # For parsing JSONC (JSON with comments) in VS Code settings - "cloudsmith-api>=2.0.38,<3.0", # Compatible up to (but excluding) 3.0+ + "cloudsmith-api>=2.0.42,<3.0", # Compatible up to (but excluding) 3.0+ "keyring>=25.4.1", "keyrings-alt>=5.0.2", "keyrings-cryptfile>=1.3.9", diff --git a/uv.lock b/uv.lock index c31999fb..932ec251 100644 --- a/uv.lock +++ b/uv.lock @@ -454,7 +454,7 @@ wheels = [ [[package]] name = "cloudsmith-api" -version = "2.0.40" +version = "2.0.42" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -462,9 +462,9 @@ dependencies = [ { name = "six" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fb/ed/7b1bb84a48a1e1c929ad0584f6d002d7539cdf9ad6cd9cbdc2abc36f937c/cloudsmith_api-2.0.40.tar.gz", hash = "sha256:fc67e783494065487e1b7897e5e65765fc690eac915519f9497daa9f3da43f87", size = 768854, upload-time = "2026-10-22T14:09:32.189Z" } +sdist = { url = "https://files.pythonhosted.org/packages/bb/17/2d373bb70ab5ea5eed04aa43fbb12088128f985c2805530f644ec122d7db/cloudsmith_api-2.0.42.tar.gz", hash = "sha256:657a18d296d1f123135c8db06b4ca53791e8cb7f12f7346c1915c1369fb02b5d", size = 769545, upload-time = "2026-10-26T13:08:02.567Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/28/ec/a3281f442703dc29a820d89d93b565a4157bcf94e1bf3d2dbc5448c366fc/cloudsmith_api-2.0.40-py3-none-any.whl", hash = "sha256:deb101007074e1465d5133648482235d4d8ff7fd00e287e59b9adae28bab552c", size = 1206776, upload-time = "2026-10-22T14:09:30.831Z" }, + { url = "https://files.pythonhosted.org/packages/d0/92/1d9d4601faec4673f6157566959edc387458edabc3666c28a2763100a398/cloudsmith_api-2.0.42-py3-none-any.whl", hash = "sha256:e49dfea7d0da42c82b3ff5f2fa7bd96693449b1982cd3d4aa92e3ad9890801f9", size = 1207400, upload-time = "2026-10-26T13:08:01.287Z" }, ] [[package]] @@ -543,7 +543,7 @@ requires-dist = [ { name = "click-configfile", specifier = ">=0.2.3" }, { name = "click-didyoumean", specifier = ">=0.0.3" }, { name = "click-spinner", specifier = ">=0.1.7" }, - { name = "cloudsmith-api", specifier = ">=2.0.38,<3.0" }, + { name = "cloudsmith-api", specifier = ">=2.0.42,<3.0" }, { name = "cryptography", specifier = ">=50.0.0" }, { name = "google-auth", marker = "extra == 'all'", specifier = ">=2.40.0" }, { name = "google-auth", marker = "extra == 'gcp'", specifier = ">=2.40.0" }, From 1b98ea3cfb2d4ec1a1ebbf6dd6b7d34a78b5295d Mon Sep 17 00:00:00 2001 From: Paul McGuckin Date: Fri, 30 Oct 2026 15:00:15 +0000 Subject: [PATCH 3/4] Update unit test --- cloudsmith_cli/cli/tests/commands/test_upstream.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cloudsmith_cli/cli/tests/commands/test_upstream.py b/cloudsmith_cli/cli/tests/commands/test_upstream.py index 6322c445..31ee7eb2 100644 --- a/cloudsmith_cli/cli/tests/commands/test_upstream.py +++ b/cloudsmith_cli/cli/tests/commands/test_upstream.py @@ -29,6 +29,7 @@ "python": "https://pypi.org", "rpm": "https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/35/Everything/x86_64/os", "ruby": "https://rubygems.org", + "skills": "https://clawhub.ai", "swift": "https://example.org", } @@ -63,6 +64,11 @@ def test_upstream_commands( "distro_versions": ["ubuntu/xenial"], } + # Skills specific arguments + if upstream_format == "skills": + upstream_config["contents"] = "Skills" + upstream_config["mode"] = "Cache and Proxy" + upstream_config_file = tmp_path / (f"cli-test-upstream-{upstream_format}.json") upstream_config_file.write_text(str(json.dumps(upstream_config))) From d3ae402ba26cdcbbbd4efed0a9ab99686b934906 Mon Sep 17 00:00:00 2001 From: Paul McGuckin Date: Mon, 2 Nov 2026 13:06:54 +0000 Subject: [PATCH 4/4] Update unitb test to use Github URL --- .env.example | 1 + .github/workflows/test.yml | 1 + cloudsmith_cli/cli/tests/commands/test_upstream.py | 14 +++++++++----- cloudsmith_cli/cli/tests/conftest.py | 6 ++++++ 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/.env.example b/.env.example index 0555c19f..0eb51726 100644 --- a/.env.example +++ b/.env.example @@ -5,3 +5,4 @@ PYTEST_CLOUDSMITH_API_KEY= PYTEST_CLOUDSMITH_ORGANIZATION= PYTEST_CLOUDSMITH_PASSWORD= PYTEST_CLOUDSMITH_USERNAME= +PYTEST_GITHUB_TOKEN= diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6f0c3f26..f9f9d13c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -128,6 +128,7 @@ jobs: PYTEST_CLOUDSMITH_ORGANIZATION: ${{ vars.PYTEST_CLOUDSMITH_ORGANIZATION }} PYTEST_CLOUDSMITH_USERNAME: ${{ secrets.PYTEST_CLOUDSMITH_USERNAME }} PYTEST_CLOUDSMITH_PASSWORD: ${{ secrets.PYTEST_CLOUDSMITH_PASSWORD }} + PYTEST_GITHUB_TOKEN: ${{ secrets.PYTEST_GITHUB_TOKEN }} run: uv run pytest -m integration --junitxml=./reports/pytest.xml - name: Upload test results diff --git a/cloudsmith_cli/cli/tests/commands/test_upstream.py b/cloudsmith_cli/cli/tests/commands/test_upstream.py index 31ee7eb2..e3ecd976 100644 --- a/cloudsmith_cli/cli/tests/commands/test_upstream.py +++ b/cloudsmith_cli/cli/tests/commands/test_upstream.py @@ -6,7 +6,7 @@ from ..utils import random_str #: The canonical public upstream for each format. These are already indexed, -#: so the API validates them quickly, and none needs credentials. The API +#: so the API validates them quickly, and only skills (GitHub) takes a token. The API #: strips trailing slashes, so none is written with one. Formats without a #: single canonical source (generic, swift) use a small placeholder page. UPSTREAM_URLS = { @@ -29,7 +29,7 @@ "python": "https://pypi.org", "rpm": "https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/35/Everything/x86_64/os", "ruby": "https://rubygems.org", - "skills": "https://clawhub.ai", + "skills": "https://github.com/anthropics/claude-plugins-official", "swift": "https://example.org", } @@ -52,7 +52,7 @@ def assert_succeeded(result): @pytest.mark.integration @pytest.mark.parametrize("upstream_format", UPSTREAM_FORMATS) def test_upstream_commands( - runner, organization, upstream_format, tmp_repository, tmp_path + request, runner, organization, upstream_format, tmp_repository, tmp_path ): upstream_config = { # "name" and "upstream_url" are the only required properties for most formats. @@ -66,8 +66,12 @@ def test_upstream_commands( # Skills specific arguments if upstream_format == "skills": - upstream_config["contents"] = "Skills" - upstream_config["mode"] = "Cache and Proxy" + # This GitHub host only offers skills and plugins together. + upstream_config["contents"] = "Skills and plugins" + upstream_config["mode"] = "Cache Only" + # Requested here rather than as a parameter so only skills skips without it. + upstream_config["auth_mode"] = "Token" + upstream_config["auth_secret"] = request.getfixturevalue("github_token") upstream_config_file = tmp_path / (f"cli-test-upstream-{upstream_format}.json") upstream_config_file.write_text(str(json.dumps(upstream_config))) diff --git a/cloudsmith_cli/cli/tests/conftest.py b/cloudsmith_cli/cli/tests/conftest.py index 8e139130..4d65b005 100644 --- a/cloudsmith_cli/cli/tests/conftest.py +++ b/cloudsmith_cli/cli/tests/conftest.py @@ -53,6 +53,12 @@ def api_key(): return _get_env_var_or_skip("PYTEST_CLOUDSMITH_API_KEY") +@pytest.fixture() +def github_token(): + """Return the PYTEST_GITHUB_TOKEN value.""" + return _get_env_var_or_skip("PYTEST_GITHUB_TOKEN") + + @pytest.fixture() def organization(): """Return the PYTEST_CLOUDSMITH_ORGANIZATION value.