Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

send content category to Posit Cloud API #478

Open
wants to merge 12 commits into
base: refactor-manifest
Choose a base branch
from
Open
12 changes: 6 additions & 6 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- os: macos-latest
python-version: '3.9'
- os: windows-latest
python-version: '3.9'
python-version: '3.9'
runs-on: ${{ matrix.os }}
name: test (py${{ matrix.python-version }} ${{ matrix.os }})
steps:
Expand Down Expand Up @@ -108,7 +108,7 @@ jobs:
- if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
run: make sync-to-s3
- if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@master
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_TOKEN }}
Expand Down Expand Up @@ -190,10 +190,10 @@ jobs:
run: |
pytest tests/test_main_system_caches.py
pytest -m 'vetiver'

test-jupyter:
runs-on: ubuntu-latest
env:
env:
CONNECT_LICENSE: ${{ secrets.RSC_LICENSE }}
ADMIN_API_KEY: ${{ secrets.ADMIN_API_KEY }}
steps:
Expand All @@ -209,7 +209,7 @@ jobs:
- name: Start Connect + rsconnect-jupyter
run: |
just integration-testing/up

- name: Run Cypress Tests
run: |
export ADMIN_API_KEY="${{ secrets.ADMIN_API_KEY }}"
Expand All @@ -219,7 +219,7 @@ jobs:
- name: Save videos
uses: actions/upload-artifact@v3
if: success() || failure()
with:
with:
name: cypress-videos
path: integration-testing/cypress/videos
if-no-files-found: ignore
Expand Down
17 changes: 10 additions & 7 deletions rsconnect/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@

try:
import typing
if typing.TYPE_CHECKING:
from rsconnect import bundle

except ImportError:
typing = None

Expand Down Expand Up @@ -546,7 +549,7 @@ def write_quarto_manifest_json(
"""
warn("This method has been moved and will be deprecated.", DeprecationWarning, stacklevel=2)

manifest, _ = make_quarto_manifest(
quarto_manifest_info = make_quarto_manifest(
file_or_directory,
inspect,
app_mode,
Expand All @@ -562,7 +565,7 @@ def write_quarto_manifest_json(
if not isdir(file_or_directory):
base_dir = dirname(file_or_directory)
manifest_path = join(base_dir, "manifest.json")
write_manifest_json(manifest_path, manifest)
write_manifest_json(manifest_path, quarto_manifest_info.manifest.data)


def write_manifest_json(manifest_path, manifest):
Expand Down Expand Up @@ -1236,7 +1239,7 @@ def create_notebook_deployment_bundle(
image=image,
env_management_py=env_management_py,
env_management_r=env_management_r,
)
).bundle
except subprocess.CalledProcessError as exc:
# Jupyter rendering failures are often due to
# user code failing, vs. an internal failure of rsconnect-python.
Expand All @@ -1251,7 +1254,7 @@ def create_notebook_deployment_bundle(
image=image,
env_management_py=env_management_py,
env_management_r=env_management_r,
)
).bundle


def create_api_deployment_bundle(
Expand Down Expand Up @@ -1296,7 +1299,7 @@ def create_api_deployment_bundle(

return make_api_bundle(
directory, entry_point, app_mode, environment, extra_files, excludes, image, env_management_py, env_management_r
)
).bundle


def create_quarto_deployment_bundle(
Expand All @@ -1309,7 +1312,7 @@ def create_quarto_deployment_bundle(
image: str = None,
env_management_py: bool = None,
env_management_r: bool = None,
) -> typing.IO[bytes]:
) -> 'bundle.ManifestBundle':
"""
Create an in-memory bundle, ready to deploy.

Expand Down Expand Up @@ -1621,7 +1624,7 @@ def write_api_manifest_json(
)
manifest_path = join(directory, "manifest.json")

write_manifest_json(manifest_path, manifest)
write_manifest_json(manifest_path, manifest.data)

return exists(join(directory, environment.filename))

Expand Down
40 changes: 33 additions & 7 deletions rsconnect/api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""
Posit Connect API client and utility functions
"""
from __future__ import annotations

import binascii
import os
from os.path import abspath
Expand Down Expand Up @@ -30,6 +32,10 @@
from .bundle import _default_title, fake_module_file_from_directory
from .timeouts import get_task_timeout, get_task_timeout_help_message

if typing.TYPE_CHECKING:
from .bundle import ManifestBundle
from .bundle import Manifest


class AbstractRemoteServer:
def __init__(self, url: str, remote_name: str):
Expand Down Expand Up @@ -626,7 +632,7 @@ def validate_rstudio_server(
raise RSConnectException("Failed to verify with {} ({}).".format(server.remote_name, exc))

@cls_logged("Making bundle ...")
def make_bundle(self, func: Callable, *args, **kwargs):
def make_bundle(self, func: Callable[..., ManifestBundle], *args, **kwargs):
path = (
self.get("path", **kwargs)
or self.get("file", **kwargs)
Expand Down Expand Up @@ -656,7 +662,8 @@ def make_bundle(self, func: Callable, *args, **kwargs):
)
raise RSConnectException(msg)

d["bundle"] = bundle
d["bundle"] = bundle.bundle
d["manifest"] = bundle.manifest

return self

Expand All @@ -680,6 +687,7 @@ def deploy_bundle(
title: str = None,
title_is_default: bool = False,
bundle: IO = None,
manifest: Manifest = None,
env_vars=None,
app_mode=None,
visibility=None,
Expand All @@ -689,6 +697,7 @@ def deploy_bundle(
title = title or self.get("title")
title_is_default = title_is_default or self.get("title_is_default")
bundle = bundle or self.get("bundle")
manifest = manifest or self.get("manifest")
env_vars = env_vars or self.get("env_vars")
app_mode = app_mode or self.get("app_mode")
visibility = visibility or self.get("visibility")
Expand Down Expand Up @@ -725,7 +734,7 @@ def deploy_bundle(
cloud_service = CloudService(self.client, self.remote_server, os.getenv("LUCID_APPLICATION_ID"))
app_store_version = self.get("app_store_version")
prepare_deploy_result = cloud_service.prepare_deploy(
app_id, deployment_name, bundle_size, bundle_hash, app_mode, app_store_version
app_id, deployment_name, bundle_size, bundle_hash, app_mode, manifest, app_store_version
)
self.upload_rstudio_bundle(prepare_deploy_result, bundle_size, contents)
cloud_service.do_deploy(prepare_deploy_result.bundle_id, prepare_deploy_result.application_id)
Expand Down Expand Up @@ -1120,16 +1129,29 @@ def create_application(self, account_id, application_name):
self._server.handle_bad_response(response)
return response

def create_output(self, name: str, application_type: str, project_id=None, space_id=None, render_by=None):
def create_output(
self,
name: str,
application_type: str,
project_id: typing.Optional[int],
space_id: typing.Optional[int],
render_by: typing.Optional[str],
content_category: typing.Optional[str],
):
data = {"name": name, "space": space_id, "project": project_id, "application_type": application_type}
if render_by:
data["render_by"] = render_by
if content_category:
data["content_category"] = content_category
response = self.post("/v1/outputs/", body=data)
self._server.handle_bad_response(response)
return response

def create_revision(self, content_id):
response = self.post("/v1/outputs/{}/revisions".format(content_id), body={})
def create_revision(self, content_id: int, content_category: typing.Optional[str]):
body = {}
if content_category:
body["content_category"] = content_category
response = self.post("/v1/outputs/{}/revisions".format(content_id), body=body)
self._server.handle_bad_response(response)
return response

Expand Down Expand Up @@ -1334,6 +1356,7 @@ def prepare_deploy(
bundle_size: int,
bundle_hash: str,
app_mode: AppMode,
manifest: Manifest,
app_store_version: typing.Optional[int],
) -> PrepareDeployOutputResult:

Expand All @@ -1345,6 +1368,8 @@ def prepare_deploy(

project_id = self._get_current_project_id()

content_category = manifest.data["metadata"].get("content_category")

if app_id is None:
# this is a deployment of a new output
if project_id is not None:
Expand All @@ -1361,6 +1386,7 @@ def prepare_deploy(
project_id=project_id,
space_id=space_id,
render_by=render_by,
content_category=content_category,
)
app_id_int = output["source_id"]
else:
Expand All @@ -1379,7 +1405,7 @@ def prepare_deploy(
output = self._rstudio_client.get_content(content_id)

if application_type == "static":
revision = self._rstudio_client.create_revision(content_id)
revision = self._rstudio_client.create_revision(content_id, content_category)
app_id_int = revision["application_id"]

# associate the output with the current Posit Cloud project (if any)
Expand Down
Loading