Promoting Content

This section explains how to use the Connect Server APIs to download code from content in one location and deploy to another. This workflow can help take application changes from a staging environment and deploy into production.

The bundle and content APIs are experimental and will continue to evolve in upcoming RStudio Connect releases. Please try using these APIs to build your own deployment tools. Let your Customer Success representative know about your experience!

The Connect Server API Reference contains documentation for each of the endpoints used in these recipes.

The content promotion recipe uses bash snippets and relies on curl to perform HTTP requests.

Scenario

Here is one scenario that can take advantage of this content promotion recipe; your organization may have similar separation of permissions and environments.

Your data scientists write Shiny applications and R Markdown reports. They rapidly iterate, experiment, and share updates. Content updates are deployed to an RStudio Connect staging environment. This environment lets the team share in-progress work without altering your business critical production content.

The RStudio Connect production environment hosts content that is visible to your customers and stakeholders. Deployment into production is done by a deployment engineer - not the data scientist.

The data science team develops updates to a Shiny application, which are then peer reviewed, tested, and approved for production use. The application developers do not have permissions to update content in the production environment. They hand-off to the deployment engineer, who has production privileges. The deployment engineer downloads the exact bundle archive from the staging environment and deploys into production.

Before Starting

You will need the following pieces of information about your staging environment before attempting to download a bundle archive:

  • STAGING_SERVER - The base URL for your RStudio Connect staging environment, such as https://connect-staging.company.com/.
  • STAGING_CONTENT_GUID - The source content GUID within your staging environment.
  • STAGING_API_KEY - An RStudio Connect API Key within your staging environment. The user associated with this API Key must be a collaborator for your source staging content.

You will need the following pieces of information about your production environment before attempting to deploy a bundle archive:

  • PROD_SERVER - The base URL for your RStudio Connect production environment, such as https://connect.company.com/.
  • PROD_CONTENT_GUID - The target content GUID within your production environment. This workflow assumes the target content already exists. Use the Creating Content recipe to create a new content item.
  • PROD_API_KEY - An RStudio Connect API Key within your production environment. The user associated with this API Key must be a collaborator (or owner) of your target production content.

The STAGING_SERVER and PROD_SERVER values appear elsewhere as CONNECT_SERVER. The STAGING_API_KEY and PROD_API_KEY are CONNECT_API_KEY elsewhere. The STAGING_CONTENT_GUID and PROD_CONTENT_GUID values are CONTENT_GUID in other recipes.

These recipes use the CONNECT_SERVER and CONNECT_API_KEY environment variables introduced in the Getting Started section of this cookbook.

Do not accidentally mix-and-match your staging/production configuration. API Keys for staging will not be recognized in your production environment.

Workflow

The content promotion workflow includes three steps:

  1. Download the archive file for a source bundle from the staging environment.
  2. Upload the archive file into the production environment.
  3. Deploy the new production bundle.

Bundle Download (staging)

The GET /experimental/content/{guid} endpoint returns information about a single content item and indicates the active bundle with its bundle_id field.

curl --silent --show-error -L --max-redirs 0 --fail \
    -H "Authorization: Key ${STAGING_API_KEY}" \
    "${STAGING_SERVER}__api__/v1/experimental/content/${STAGING_CONTENT_GUID}"
# => {
# =>   "guid": "b99b9b77-a8ae-4ecd-93aa-3c23baf9cefe",
# =>   "title": "staging content",
# =>   ...
# =>   "bundle_id": "584",
# =>   ...
# => }

Extract the bundle ID from the JSON response and assign it to a STAGING_BUNDLE_ID environment variable:

export STAGING_BUNDLE_ID="584"

We will use this bundle ID to download its archive file using the GET /experimental/bundles/{id}/download bundle download endpoint.

curl --silent --show-error -L --max-redirs 0 --fail -J -O \
    -H "Authorization: Key ${STAGING_API_KEY}" \
    "${STAGING_SERVER}__api__/v1/experimental/bundles/${STAGING_BUNDLE_ID}/download"

RStudio Connect suggests the filename bundle-${STAGING_BUNDLE_ID}.tar.gz in the Content-Disposition HTTP response header. The -J -O options tell curl to save the downloaded archive file using that filename.

Let's define an environment variable named STAGING_BUNDLE_FILE containing name of the downloaded archive file.

# bundle-584.tar.gz
export STAGING_BUNDLE_FILE="bundle-${STAGING_BUNDLE_ID}.tar.gz"

Bundle Upload (production)

Given our staging bundle archive identified by the environment variable STAGING_BUNDLE_FILE, we can follow the Uploading Bundles recipe.

This is the one command where we are mixing "staging" and "production" variables. The archive file we obtained from the staging environment is being uploaded to production using the POST /experimental/content/{guid}/upload upload content bundle endpoint.

curl --silent --show-error -L --max-redirs 0 --fail -X POST \
    -H "Authorization: Key ${PROD_API_KEY}" \
    --data-binary @"${STAGING_BUNDLE_FILE}" \
    "${PROD_SERVER}__api__/v1/experimental/content/${PROD_CONTENT_GUID}/upload"
# => {"bundle_id":"242","bundle_size":162991}

Extract the bundle ID from the upload response and assign it to a PROD_BUNDLE_ID environment variable:

export PROD_BUNDLE_ID="242"

Bundle Deploy (production)

Given our target production bundle identified by the environment variable PROD_BUNDLE_ID, we can follow the Deploying a Bundle recipe. This uses the POST /experimental/content/{guid}/deploy deploy content bundle endpoint.

# Build the JSON input naming the bundle to deploy.
export DATA='{"bundle_id":"'"${PROD_BUNDLE_ID}"'"}'
# Trigger a deployment.
curl --silent --show-error -L --max-redirs 0 --fail -X POST \
    -H "Authorization: Key ${PROD_API_KEY}" \
    --data "${DATA}" \
    "${PROD_SERVER}__api__/v1/experimental/content/${PROD_CONTENT_GUID}/deploy"
# => {"task_id":"t0yiLB6bd6RKlesX"}

You can monitor the progress of this deployment by polling against the GET /experimental/tasks/{id} get task endpoint, as explained in the Task Polling recipe. Remember to poll against the PROD_SERVER URL and not your staging environment.