Skip to content

Commit a6163bc

Browse files
committed
feat: adds bundles.active()
1 parent b61e2db commit a6163bc

File tree

3 files changed

+175
-0
lines changed

3 files changed

+175
-0
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import time
2+
from pathlib import Path
3+
4+
import pytest
5+
from packaging import version
6+
7+
from posit import connect
8+
9+
from . import CONNECT_VERSION
10+
11+
12+
class TestBundles:
13+
@classmethod
14+
def setup_class(cls):
15+
cls.client = connect.Client()
16+
cls.content = cls.client.content.create(
17+
name=f"test-bundles-{int(time.time())}",
18+
title="Test Bundles",
19+
access_type="all",
20+
)
21+
# Path to the test bundle
22+
bundle_path = Path(
23+
"../../../resources/connect/bundles/example-flask-minimal/bundle.tar.gz"
24+
)
25+
cls.bundle_path = (Path(__file__).parent / bundle_path).resolve()
26+
27+
@classmethod
28+
def teardown_class(cls):
29+
cls.content.delete()
30+
31+
def test_create_bundle(self):
32+
"""Test creating a bundle."""
33+
bundle = self.content.bundles.create(str(self.bundle_path))
34+
assert bundle["id"]
35+
assert bundle["content_guid"] == self.content["guid"]
36+
37+
def test_find_bundles(self):
38+
"""Test finding all bundles."""
39+
# Create a bundle first
40+
self.content.bundles.create(str(self.bundle_path))
41+
42+
# Find all bundles
43+
bundles = self.content.bundles.find()
44+
assert len(bundles) >= 1
45+
46+
def test_find_one_bundle(self):
47+
"""Test finding a single bundle."""
48+
# Create a bundle first
49+
self.content.bundles.create(str(self.bundle_path))
50+
51+
# Find one bundle
52+
bundle = self.content.bundles.find_one()
53+
assert bundle is not None
54+
assert bundle["content_guid"] == self.content["guid"]
55+
56+
def test_get_bundle(self):
57+
"""Test getting a specific bundle."""
58+
# Create a bundle first
59+
created_bundle = self.content.bundles.create(str(self.bundle_path))
60+
61+
# Get the bundle by ID
62+
bundle = self.content.bundles.get(created_bundle["id"])
63+
assert bundle["id"] == created_bundle["id"]
64+
65+
@pytest.mark.skipif(CONNECT_VERSION < version.parse("2024.02.0"))
66+
def test_active_bundle(self):
67+
"""Test retrieving the active bundle."""
68+
# Initially, no bundle should be active
69+
assert self.content.bundles.active() is None
70+
71+
# Create and deploy a bundle
72+
bundle = self.content.bundles.create(str(self.bundle_path))
73+
task = bundle.deploy()
74+
task.wait_for()
75+
76+
# Wait for the bundle to become active
77+
max_retries = 10
78+
active_bundle = None
79+
for _ in range(max_retries):
80+
active_bundle = self.content.bundles.active()
81+
if active_bundle is not None:
82+
break
83+
time.sleep(1)
84+
85+
# Verify the bundle is now active
86+
assert active_bundle is not None
87+
assert active_bundle["id"] == bundle["id"]
88+
assert active_bundle.get("active") is True
89+
90+
# Create another bundle but don't deploy it
91+
bundle2 = self.content.bundles.create(str(self.bundle_path))
92+
93+
# Verify the active bundle is still the first one
94+
active_bundle = self.content.bundles.active()
95+
assert active_bundle is not None
96+
assert active_bundle["id"] == bundle["id"]
97+
assert active_bundle["id"] != bundle2["id"]

src/posit/connect/bundles.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,23 @@ def find_one(self) -> Bundle | None:
193193
bundles = self.find()
194194
return next(iter(bundles), None)
195195

196+
def active(self) -> Bundle | None:
197+
"""Retrieve the active bundle.
198+
199+
Returns
200+
-------
201+
Bundle | None
202+
The currently active bundle, or None if no active bundle exists.
203+
204+
Examples
205+
--------
206+
>>> client = connect.Client()
207+
>>> content = client.content.get(guid)
208+
>>> bundle = content.bundles.active()
209+
"""
210+
bundles = self.find()
211+
return next((bundle for bundle in bundles if bundle.get("active", False)), None)
212+
196213
def get(self, uid: str) -> Bundle:
197214
"""Get a bundle.
198215

tests/posit/connect/test_bundles.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,3 +373,64 @@ def test(self):
373373
assert mock_content_get.call_count == 1
374374
assert mock_bundle_get.call_count == 1
375375
assert bundle["id"] == bundle_id
376+
377+
378+
class TestBundlesActive:
379+
@responses.activate
380+
def test_active_bundle_exists(self):
381+
content_guid = "f2f37341-e21d-3d80-c698-a935ad614066"
382+
383+
# Create a modified copy of bundles.json with one bundle as active
384+
bundles_data = load_mock(f"v1/content/{content_guid}/bundles.json")
385+
active_bundles_data = bundles_data.copy()
386+
active_bundles_data[0]["active"] = True
387+
388+
# behavior
389+
mock_content_get = responses.get(
390+
f"https://connect.example/__api__/v1/content/{content_guid}",
391+
json=load_mock(f"v1/content/{content_guid}.json"),
392+
)
393+
394+
mock_bundles_get = responses.get(
395+
f"https://connect.example/__api__/v1/content/{content_guid}/bundles",
396+
json=active_bundles_data,
397+
)
398+
399+
# setup
400+
c = Client("https://connect.example", "12345")
401+
402+
# invoke
403+
bundle = c.content.get(content_guid).bundles.active()
404+
405+
# assert
406+
assert mock_content_get.call_count == 1
407+
assert mock_bundles_get.call_count == 1
408+
assert bundle is not None
409+
assert bundle["id"] == "101"
410+
assert bundle["active"] is True
411+
412+
@responses.activate
413+
def test_no_active_bundle(self):
414+
content_guid = "f2f37341-e21d-3d80-c698-a935ad614066"
415+
416+
# behavior
417+
mock_content_get = responses.get(
418+
f"https://connect.example/__api__/v1/content/{content_guid}",
419+
json=load_mock(f"v1/content/{content_guid}.json"),
420+
)
421+
422+
mock_bundles_get = responses.get(
423+
f"https://connect.example/__api__/v1/content/{content_guid}/bundles",
424+
json=load_mock(f"v1/content/{content_guid}/bundles.json"),
425+
)
426+
427+
# setup
428+
c = Client("https://connect.example", "12345")
429+
430+
# invoke
431+
bundle = c.content.get(content_guid).bundles.active()
432+
433+
# assert
434+
assert mock_content_get.call_count == 1
435+
assert mock_bundles_get.call_count == 1
436+
assert bundle is None

0 commit comments

Comments
 (0)