Skip to main content
Updating Codelabs via API

Want to publish your Codelab automatically every time you commit? Read on!

Chris Ramlow avatar
Written by Chris Ramlow
Updated over 3 months ago

Watch this video demo building a CI system with Github Workflows to publish Codelabs automatically!

PlusPlus has a rich read-only API via GraphQL.

However, our Guides feature supports Google’s Codelab product. These are heavily used by technical teams who value automation and so we support updating the Codelab version of your published Guide via an API call.

You will need to publish a Codelab manually to get started. See this helpdesk article for instructions but note that the API for updating Codelabs only supports Codelabs authored with Markdown at this time.

Without specific knowledge about how your Codelabs are laid out and updated we can’t provide a fully automatic solution for you. However the API documented below allows you to create your own automation and we have a sample Github Action in our example Github repo for you to copy if helpful. Feel free to copy the Github Action or publishing script and re-use to fit your own configuration.

If you are stuck building your automation or using the API please reach out to support!

Information Required

To get started using the Update API you'll need four pieces of information.

1. Your PlusPlus App Domain

You’ll need to know the domain at which you access your PlusPlus instance.

2. Developer Token

To use this API you will need to obtain a developer token - as an admin user visit the PlusPlus app and navigate to Menu > Settings > Developers. Copy the GraphQL API Token value you find there - it is tied to your user account and is valid as long as you are an active user.

3. Codelab UUID

You’ll need the UUID value that uniquely identifies your published Coc - this appears in your url when viewing it. For instance, when viewing the Codelab at https://demo.plusplus.app/a/codelabs/501a39e1-aaf8-4581-889c-5d6023824ee2_your-first-progressive-web-app the UUID is the value 501a39e1-aaf8-4581-889c-5d6023824ee2

4. Your Codelab File

Markdown-based Codelabs are published by zipping up the directory that your .md files live in along with (optionally) any assets required. You’ll need to create this file yourself.

We’ll call these four pieces of information $DOMAIN, $TOKEN, $UUID, and $FILE.

API Calls

To update the version of your Codelab you must zip up your directory of markdown and optionally any static resources and produce a single zip file with at least an index.md file in it. That is the $FILE above and it represents the current content for your Codelab.

To publish this update you must make three API calls. But don’t panic - we have a sample Python client written for you already which will make the calls for you. Skip to the bottom to see the sample code.

The three steps necessary are:

Step #1 - Request a Pre-Signed POST

This step retrieves the necessary information to make a POST call to our file storage system. You will need to POST to a url that looks like https://{domain}/endpoints/codelabs/upload/api/{codelab_id}/pre-sign/

In order for your API call to be authorized you must include a custom header that includes your developer token $TOKEN. You will receive back a JSON dictionary. For instance, via curl this call and response looks like (with some encryption details sanitized):

$ curl --header "authorization: $TOKEN" -X POST \   
'https://$DOMAIN/endpoints/codelabs/upload/api/$UUID/pre-sign/'

{"upload_data":{"url":"http://sanitized-url-from-server",
"fields":{"key":"1/uploads/default/e2e5796cdf484ba69bf059568d0be1a8",
"x-amz-algorithm":"AWS4-HMAC-SHA256",
"x-amz-credential":"sanitized…",
"x-amz-date":"20240423T162357Z",
"Policy":"sanitized",
"X-amz-signature":"sanitized}},
"read_url":"sanitized"}

Step #2 - Upload Your File

As you can see above the result of the Pre-Signed POST call is … data to make another call!

You’ll want to POST to the upload_data.url returned by the previous endpoint and send your $FILE. To authenticate to this endpoint you’ll have to pass all the upload_data.fields as headers to the request. With recent versions of curl you can save those to a text file and pull them into your curl POST request by prefacing the name of your text file containing your headers with an @ sign. This might look like:

$ curl \
--header "Content-Disposition: form-data; name="file";filename='$FILE'" \
-X POST $UPLOAD_URL \
-H @headers.txt \
--data-binary @$FILE

Because this call is pointed at our file storage system you do not need your authorization token - the authorization for this request is in the provided headers.

Step #3 - Updating the Codelab Version

Finally you can pass the read_url value you got back in the first step to PlusPlus in order to update your Codelab:

$ curl --header "authorization: $TOKEN" \
-X POST https://$DOMAIN/endpoints/codelabs/upload/api/$TOKEN/ \
–data-raw "{'read_url': '$READ_URL'}"

Success!

When you reload a Codelab that has been updated since your last visit you may initially see the original version you started with. Look for a banner message at the top indicating that a newer version is available.

Click the button on this banner to reload and access the latest published version to see your published changes. New assignments to this codelab will automatically be made against the latest version.

Sample Client

If all this feels like a lot to manage - try using a short Python script!

The following Python code has been tested with Python 3 and the requests library installed. Be sure to replace the four $VALUEs in the script to use your own token, on your app, against your Codelab with your supplied zip file.

Save this file as client.py and run it. A successful run looks like:

$ python client.py
Success! See <url-to-your-codelab>

Any errors in any of the three API calls will result in error messages printed to stdout.

Sample Client


import requests

token = $TOKEN # REPLACE
domain = $DOMAIN # REPLACE
codelab_id = $UUID # REPLACE
codelab_file = $FILE # REPLACE

url = f"https://{domain}/endpoints/codelabs/upload/api/{codelab_id}/pre-sign/"

# Get the pre-signed post details
response = requests.post(url, headers={'authorization': token})
if response.status_code != 200:
print(response)
raise SystemExit("Failed to generate pre-signed post")

# Upload the zip file representing the codelab version with the presigned post
data = response.json()
upload_data = data['upload_data']
response = requests.post(upload_data['url'],
data=upload_data['fields'],
files={'file': open(codelab_file, "rb")})

if response.status_code != 204:
print(response)
raise SystemExit("Failed to upload file")

# Try to update the version by pointing to the uploaded file
url = f"https://{domain}/endpoints/codelabs/upload/api/{codelab_id}/version/"
response = requests.post(url,
headers={'authorization': token},
data={'read_url': data['read_url']})


if response.status_code != 200:
print(response)
raise SystemExit("Failed to update version")

url = f"https://{domain}/a/codelabs/{codelab_id}/"
print(f"Success! See {url}")

See also

Did this answer your question?