Let's make sure you're set up to deploy Unison code to the Cloud and are familiar with the basic workflow. In this exercise, you'll deploy a simple, pre-made HTTP service that responds with a greeting message.
📚 What we'll cover
- Deploying an HTTP service to the Cloud
- Identifying a service by hash and by name
- Log viewing in the Cloud admin panel
🐥 Getting Started
Make sure you've done the following:
Then enter ucm
in your terminal to start Unison and authorize your account to run on the Cloud with the auth.login
command:
scratch/main> auth.login
Great! Your UCM console is set up to deploy to Unison Cloud.
Create a repository for the cloud-start
project and pull the latest release to retrieve the stubs and tests.
scratch/main> project.create-empty cloud-start
cloud-start/main> pull @unison/cloud-start/releases/latest
Editing the deploy
function
You'll implement the ex1_quickstart.deploy
function, which will deploy a service to the Cloud and return a URI to call it.
📝 Instructions
To get started, run the edit
command in the UCM:
cloud-start/main> edit exercises.ex1_quickstart.deploy
Copy the following into your scratch.u
file as the deploy
function implementation, or follow along with each step below:
exercises.ex1_quickstart.deploy : '{IO, Exception} URI
exercises.ex1_quickstart.deploy = Cloud.main do
serviceHash = deployHttp exercises.env() ex1_quickstart.helloWorld.logic
serviceName = ServiceName.named "hello-world"
ServiceName.assign serviceName serviceHash
The deploy
function does the following:
- It provides the
Cloud.main
handler for theCloud
ability, so the service can be run on the Cloud - It deploys
helloWorld.logic
as an HTTP service withdeployHttp
- It creates a static name for the service with
ServiceName.named
- It assigns the name to the deployed service with
ServiceName.assign
We'll discuss each component in detail next.
🌥️ Handling Cloud interactions
Our goal is to deploy an HTTP service to the web by running a Unison program. This interaction is expressible as a regular program because of the Cloud
ability—which is our way of describing interactions with Unison Cloud infrastructure in code.
The first lines of the deploy
function need to set us up to interact with the Cloud:
exercises.ex1_quickstart.deploy : '{IO, Exception} URI
exercises.ex1_quickstart.deploy = Cloud.main do
todo "wip"
Cloud.main
is a function from the Unison Cloud client library. It expects a delayed code block, opened with the do
keyword. Inside the code block provided to Cloud.main
, we can call other functions that create and use Unison Cloud resources.
📦 HTTP services in Unison
Unison HTTP services are functions with the basic form HttpRequest -> HttpResponse
.
We've already written the HTTP service you'll be deploying. It's called helloWorld.logic
and responds to the path /:name
. Its implementation isn't important for now, but the function looks like this:
helloWorld.logic : HttpRequest ->{Exception, Log} HttpResponse
helloWorld.logic = Route.run do
use Text ++
name = Route.route GET Parser.text
info "request for greeting" [("name", name)]
ok.text ("👋 hello " ++ name ++ "\n")
You can view it in the UCM with:
cloud-start/main> view exercises.ex1_quickstart.helloWorld.logic
Our deployment function should indicate that helloWorld.logic
is the service we want to expose. We'll do that by passing it as an argument to the deployHttp
function next:
exercises.ex1_quickstart.deploy : '{IO, Exception} URI
exercises.ex1_quickstart.deploy = Cloud.main do
serviceHash = deployHttp exercises.env() ex1_quickstart.helloWorld.logic
todo "wip"
deployHttp
takes two arguments:
- An
Environment
— a way of grouping Cloud resources into a configuration environment for basic access management. - The HTTP service to deploy — in this case,
helloWorld.logic
.
We've provided a helper function, exercises.env
, for use in this project. exercises.env
is a delayed computation, so it's forced with ()
, like exercises.env()
.
deployHttp
returns a ServiceHash
which we've assigned to a variable.
A ServiceHash
is a typed hash that uniquely identifies the service code being deployed.
If you change the implementation of the service argument, (for example, by adding another endpoint, or updating an error message) you'll get a new hash, so a ServiceHash
identifies a service deployment by its service code.
🏷️ Assigning the service a name
The final lines of the deploy
function create a name for the service with ServiceName.named
and assign the service hash to the name with ServiceName.assign
.
exercises.ex1_quickstart.deploy : '{IO, Exception} URI
exercises.ex1_quickstart.deploy = Cloud.main do
serviceHash = deployHttp exercises.env() ex1_quickstart.helloWorld.logic
serviceName = ServiceName.named "hello-world"
ServiceName.assign serviceName serviceHash
ServiceName.named
creates a human-readable, static name for a service. In this case, we're calling it "hello-world".
ServiceName.assign
links the service hash from the previous step to the name we just created. This allows the service implementation to change over time—resulting in a different hash—while the name remains stable. When run, it returns a URI where the HTTP service can be accessed.
Remember to save your scratch file and update
your codebase.
cloud-start/main> update
Deployments are kicked off with the run
command in the UCM. This will run the deploy
function and return a URI you can visit to call the service:
cloud-start/main> run exercises.ex1_quickstart.deploy
😎 Don't forget that the HTTP service expects a path parameter /:name
to return a greeting.
For validation, run the submit.ex1_quickstart
function in the UCM, which will programmatically call your service and check the response!
cloud-start/main> run submit.ex1_quickstart
Solution
Altogether, your ex1_quickstart.deploy
function should look something like this when view
ed in the UCM:
exercises.ex1_quickstart.deploy : '{IO, Exception} URI
exercises.ex1_quickstart.deploy = Cloud.main do
serviceHash = deployHttp exercises.env() ex1_quickstart.helloWorld.logic
serviceName = ServiceName.named "hello-world"
ServiceName.assign serviceName serviceHash
📋 Visit the Cloud admin panel
Once your service is deployed, you can view it on the Unison Cloud admin page at app.unison.cloud
You should see your service listed in the "Named Services" tab. Service logs are automatically collected and displayed in the activity tab for the service.
You can use a browser or CURL to call the URI returned by the deploy
function since your service is now live! ⭐️