Problem
A user has a content bundle (.tar.gz) downloaded from one Connect instance and wants to publish it to another. Today there is no single command that takes a downloaded bundle and re-deploys it.
The current workaround is to unpack the bundle and use deploy manifest:
mkdir mycontent && tar -xzf bundle.tar.gz -C mycontent
rsconnect deploy manifest mycontent/manifest.json --server ... --api-key ...
Proposal
Add a command (e.g. rsconnect deploy bundle <bundle.tar.gz>) that deploys a downloaded bundle directly.
Importantly, this should not extract and re-bundle. A downloaded bundle is already exactly the tarball that the deploy machinery uploads, so the extract → deploy manifest → make_manifest_bundle round trip is wasted work (and risks producing a slightly different bundle than the one downloaded).
Looking at RSConnectExecutor in rsconnect/api.py:
make_bundle(func, ...) (api.py:1317) just sets self.bundle to a file-like tarball.
deploy_bundle() (api.py:1358) uploads exactly self.bundle.
So for a downloaded bundle we can skip make_bundle entirely and set self.bundle to the opened tarball directly. The deploy chain is then identical to deploy manifest:
ce.validate_server()
.validate_app_mode(app_mode=app_mode)
# instead of .make_bundle(make_manifest_bundle, ...):
# ce.bundle = open(bundle_path, "rb") (or a small helper)
.deploy_bundle(activate=not draft)
.save_deployed_info()
.emit_task_log()
The only thing needed from inside the tarball is the app mode for validate_app_mode (api.py:1485). That can be read by pulling just the manifest.json member out of the tar (reusing the parsing in read_manifest_app_mode / read_manifest_file, bundle.py:818) — no full extraction required. make_bundle also sets self.deployment_name, so that one line would need to be factored out / called separately.
Suggested refactor
- Factor the
deployment_name assignment out of make_bundle (or add an open_bundle(path) executor method that sets self.bundle and the deployment name without re-bundling).
- Add a helper to read
manifest.json (and thus app mode + default title) directly from a tarball.
- Wire up
deploy bundle reusing the existing executor chain.
Caveats worth documenting / handling
- Environment variables and secrets are not in the bundle — the target server must have them set (could be passed via
-E KEY=value).
- Dependencies are pinned in the manifest, so the target server needs a compatible Python/R version available.
- Creates new content by default; updating existing content would still use
--app-id.
Acceptance
rsconnect deploy bundle path/to/bundle.tar.gz --server ... --api-key ... deploys the bundle's content to the target server, uploading the downloaded tarball as-is (no re-bundling).
- Standard deploy options (
--name, --app-id, --title, -E, --new, etc.) are supported.
Problem
A user has a content bundle (
.tar.gz) downloaded from one Connect instance and wants to publish it to another. Today there is no single command that takes a downloaded bundle and re-deploys it.The current workaround is to unpack the bundle and use
deploy manifest:mkdir mycontent && tar -xzf bundle.tar.gz -C mycontent rsconnect deploy manifest mycontent/manifest.json --server ... --api-key ...Proposal
Add a command (e.g.
rsconnect deploy bundle <bundle.tar.gz>) that deploys a downloaded bundle directly.Importantly, this should not extract and re-bundle. A downloaded bundle is already exactly the tarball that the deploy machinery uploads, so the extract →
deploy manifest→make_manifest_bundleround trip is wasted work (and risks producing a slightly different bundle than the one downloaded).Looking at
RSConnectExecutorinrsconnect/api.py:make_bundle(func, ...)(api.py:1317) just setsself.bundleto a file-like tarball.deploy_bundle()(api.py:1358) uploads exactlyself.bundle.So for a downloaded bundle we can skip
make_bundleentirely and setself.bundleto the opened tarball directly. The deploy chain is then identical todeploy manifest:The only thing needed from inside the tarball is the app mode for
validate_app_mode(api.py:1485). That can be read by pulling just themanifest.jsonmember out of the tar (reusing the parsing inread_manifest_app_mode/read_manifest_file,bundle.py:818) — no full extraction required.make_bundlealso setsself.deployment_name, so that one line would need to be factored out / called separately.Suggested refactor
deployment_nameassignment out ofmake_bundle(or add anopen_bundle(path)executor method that setsself.bundleand the deployment name without re-bundling).manifest.json(and thus app mode + default title) directly from a tarball.deploy bundlereusing the existing executor chain.Caveats worth documenting / handling
-E KEY=value).--app-id.Acceptance
rsconnect deploy bundle path/to/bundle.tar.gz --server ... --api-key ...deploys the bundle's content to the target server, uploading the downloaded tarball as-is (no re-bundling).--name,--app-id,--title,-E,--new, etc.) are supported.