Skip to content

Commit 22dac9c

Browse files
authored
Redeploy to Posit Cloud from a project associates the content with project (#452)
* Redeploy to Posit Cloud from a project associates the content with that project * attempt to fix test * move up the call to get the current project * merge
1 parent ca1bff6 commit 22dac9c

File tree

4 files changed

+32
-9
lines changed

4 files changed

+32
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88

99
### Added
1010
- Failed deploys to shinyapps.io will now output build logs. Posit Cloud application deploys will also output build logs once supported server-side.
11+
- Redeploy to Posit Cloud from a project now correctly associates the content with that project.
1112

1213
## [1.19.0] - 2023-07-12
1314

rsconnect/api.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,6 +1319,12 @@ def __init__(self, cloud_client: PositClient, server: CloudServer, project_appli
13191319
self._server = server
13201320
self._project_application_id = project_application_id
13211321

1322+
def _get_current_project_id(self):
1323+
if self._project_application_id is not None:
1324+
project_application = self._rstudio_client.get_application(self._project_application_id)
1325+
return project_application["content_id"]
1326+
return None
1327+
13221328
def prepare_deploy(
13231329
self,
13241330
app_id: typing.Optional[typing.Union[str, int]],
@@ -1330,24 +1336,24 @@ def prepare_deploy(
13301336
) -> PrepareDeployOutputResult:
13311337
application_type = "static" if app_mode == AppModes.STATIC else "connect"
13321338

1339+
project_id = self._get_current_project_id()
1340+
13331341
if app_id is None:
1334-
# this is a new deployment.
1335-
# get the Posit Cloud project so that we can associate the deployment with it
1336-
if self._project_application_id is not None:
1337-
project_application = self._rstudio_client.get_application(self._project_application_id)
1338-
project_id = project_application["content_id"]
1342+
# this is a deployment of a new output
1343+
if project_id is not None:
13391344
project = self._rstudio_client.get_content(project_id)
13401345
space_id = project["space_id"]
13411346
else:
13421347
project_id = None
13431348
space_id = None
13441349

1350+
# create the new output and associate it with the current Posit Cloud project and space
13451351
output = self._rstudio_client.create_output(
13461352
name=app_name, application_type=application_type, project_id=project_id, space_id=space_id
13471353
)
13481354
app_id_int = output["source_id"]
13491355
else:
1350-
# this is a redeployment
1356+
# this is a redeployment of an existing output
13511357
if app_store_version is not None:
13521358
# versioned app store files store content id in app_id
13531359
output = self._rstudio_client.get_content(app_id)
@@ -1359,13 +1365,16 @@ def prepare_deploy(
13591365
# content_id will appear on static applications as output_id
13601366
content_id = application.get("content_id") or application.get("output_id")
13611367
app_id_int = application["id"]
1362-
13631368
output = self._rstudio_client.get_content(content_id)
13641369

13651370
if application_type == "static":
13661371
revision = self._rstudio_client.create_revision(content_id)
13671372
app_id_int = revision["application_id"]
13681373

1374+
# associate the output with the current Posit Cloud project (if any)
1375+
if project_id is not None:
1376+
self._rstudio_client.update_output(output["id"], {"project": project_id})
1377+
13691378
app_url = output["url"]
13701379
output_id = output["id"]
13711380

tests/test_api.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from unittest import TestCase
2-
from unittest.mock import Mock, patch
2+
from unittest.mock import Mock, patch, call
33
import json
44

55
import httpretty
@@ -332,6 +332,7 @@ def test_prepare_redeploy(self):
332332
app_mode = AppModes.PYTHON_SHINY
333333

334334
self.cloud_client.get_content.return_value = {"id": 1, "source_id": 10, "url": "https://posit.cloud/content/1"}
335+
self.cloud_client.get_application.return_value = {"id": 10, "content_id": 200}
335336
self.cloud_client.create_bundle.return_value = {
336337
"id": 100,
337338
"presigned_url": "https://presigned.url",
@@ -348,6 +349,7 @@ def test_prepare_redeploy(self):
348349
)
349350
self.cloud_client.get_content.assert_called_with(1)
350351
self.cloud_client.create_bundle.assert_called_with(10, "application/x-tar", bundle_size, bundle_hash)
352+
self.cloud_client.update_output.assert_called_with(1, {"project": 200})
351353

352354
assert prepare_deploy_result.app_id == 1
353355
assert prepare_deploy_result.application_id == 10
@@ -364,6 +366,7 @@ def test_prepare_redeploy_static(self):
364366
app_mode = AppModes.STATIC
365367

366368
self.cloud_client.get_content.return_value = {"id": 1, "source_id": 10, "url": "https://posit.cloud/content/1"}
369+
self.cloud_client.get_application.return_value = {"id": 10, "content_id": 200}
367370
self.cloud_client.create_revision.return_value = {
368371
"application_id": 11,
369372
}
@@ -384,6 +387,7 @@ def test_prepare_redeploy_static(self):
384387
self.cloud_client.get_content.assert_called_with(1)
385388
self.cloud_client.create_revision.assert_called_with(1)
386389
self.cloud_client.create_bundle.assert_called_with(11, "application/x-tar", bundle_size, bundle_hash)
390+
self.cloud_client.update_output.assert_called_with(1, {"project": 200})
387391

388392
assert prepare_deploy_result.app_id == 1
389393
assert prepare_deploy_result.application_id == 11
@@ -418,9 +422,11 @@ def test_prepare_redeploy_preversioned_app_store(self):
418422
app_mode=app_mode,
419423
app_store_version=None,
420424
)
421-
self.cloud_client.get_application.assert_called_with(10)
425+
# first call is to get the current project id, second call is to get the application
426+
self.cloud_client.get_application.assert_has_calls([call(self.project_application_id), call(app_id)])
422427
self.cloud_client.get_content.assert_called_with(1)
423428
self.cloud_client.create_bundle.assert_called_with(10, "application/x-tar", bundle_size, bundle_hash)
429+
self.cloud_client.update_output.assert_called_with(1, {"project": 1})
424430

425431
assert prepare_deploy_result.app_id == 1
426432
assert prepare_deploy_result.application_id == 10

tests/test_main.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,13 @@ def post_output_callback(request, uri, response_headers):
350350
body=post_output_callback,
351351
)
352352

353+
httpretty.register_uri(
354+
httpretty.PATCH,
355+
"https://api.posit.cloud/v1/outputs/1",
356+
body=open("tests/testdata/rstudio-responses/create-output.json", "r").read(),
357+
status=200,
358+
)
359+
353360
def post_bundle_callback(request, uri, response_headers):
354361
parsed_request = _load_json(request.body)
355362
del parsed_request["checksum"]

0 commit comments

Comments
 (0)