|
| 1 | +# Cloud API For CI/CD Flow v2 |
| 2 | + |
| 3 | +For the v2 endpoints we want to give you even more control over the process. You can target more environments and you have more options when starting a deployment. |
| 4 | +We have tried to simplified the api calling process: Upload your artifact, and when you're ready to run the deployment you now need to reference the uploaded artifact. |
| 5 | +The big change here is that the artifact is not connected to a deployment before the api is invoked with a reference to an artifact to deploy. |
| 6 | + |
| 7 | +## Getting started |
| 8 | + |
| 9 | +To integrate Umbraco Cloud into your CI/CD pipeline, you'll need to make API calls to the following endpoint [`https://api.cloud.umbraco.com`](https://api.cloud.umbraco.com): |
| 10 | + |
| 11 | +Path for artifacts |
| 12 | +* `/v2/projects/$projectId/deployments/artifacts` |
| 13 | + |
| 14 | +Path for deployments |
| 15 | +* `/v2/projects/$projectId/deployments` |
| 16 | +* `/v2/projects/$projectId/deployments/$deploymentId` |
| 17 | +* `/v2/projects/$projectId/deployments/$latestCompletedDeploymentId/diff` |
| 18 | + |
| 19 | +You will find relevant examples using `HTTP Request Syntax` in the sections below. |
| 20 | + |
| 21 | +### How to enable CI/CD Integrator in the Umbraco Cloud Portal |
| 22 | + |
| 23 | +To authenticate with the Umbraco Cloud API, you'll need your Project ID and API Key. These credentials can be found under **Configuration > Advanced** in the Umbraco Cloud portal. |
| 24 | + |
| 25 | + |
| 26 | + |
| 27 | +The two elements to be used for the authentication are: |
| 28 | + |
| 29 | +* **Cloud Project ID**: The ID of your Umbraco project. |
| 30 | +* **CI/CD API Key**: Your unique identifier. |
| 31 | + |
| 32 | +By including the API key header in your HTTP requests, you ensure secure access to your Umbraco Cloud project's resources. |
| 33 | + |
| 34 | +For enhanced security, it's crucial to store the provided API key in a secure location. Options include a variable group in Azure DevOps or using the Secrets feature in GitHub Actions. |
| 35 | +It's important to note that each API key is tightly coupled with a specific Umbraco Cloud project and can only be used for deployments related to that project. |
| 36 | + |
| 37 | +### How to authenticate your requests |
| 38 | + |
| 39 | +To authenticate your API requests you'll need to include your API key in a custom HTTP header named Umbraco-Cloud-Api-Key. |
| 40 | + |
| 41 | +{% tabs %} |
| 42 | +{% tab title="HTTP Request Syntax" %} |
| 43 | +```http |
| 44 | +GET https://api.cloud.umbraco.com/v2/projects/{{projectId}}/deployments |
| 45 | +Umbraco-Cloud-Api-Key = {{apiKey}} |
| 46 | +``` |
| 47 | +{% endtab %} |
| 48 | +{% tab title="Powershell" %} |
| 49 | +```powershell |
| 50 | +Invoke-RestMethod -Uri https://api.cloud.umbraco.com/v2/projects/$projectId/deployments -Headers @{ "Umbraco-Cloud-Api-Key" = $apiKey } -Method Get |
| 51 | +``` |
| 52 | +{% endtab %} |
| 53 | + |
| 54 | +{% tab title="Curl" %} |
| 55 | +``` |
| 56 | +curl -s -X GET https://api.cloud.umbraco.com/v2/projects/$projectId/deployments -H "Umbraco-Cloud-Api-Key: $apiKey" |
| 57 | +``` |
| 58 | +{% endtab %} |
| 59 | +{% endtabs %} |
| 60 | + |
| 61 | +## How to upload artifacts |
| 62 | + |
| 63 | +### Upload artifact |
| 64 | + |
| 65 | +The process of uploading an artifact is tied to a project. The uploaded artifact is will be available to use in any deployment. |
| 66 | +The artifact need to be a zip-file with source code needed to build your website. |
| 67 | +TODO link to best practice for packing artifacts. |
| 68 | + |
| 69 | +{% tabs %} |
| 70 | +{% tab title="HTTP Request Syntax" %} |
| 71 | +```http |
| 72 | +@projectId = Get this value from the portal |
| 73 | +@apiKey = Get this value from the portal |
| 74 | +@description = my awesome optional description text |
| 75 | +@version = my awesome optional version text |
| 76 | +@file = path to file + filename |
| 77 | +
|
| 78 | +POST https://api.cloud.umbraco.com/v2/projects/{{projectId}}/deployments/artifacts |
| 79 | +Umbraco-Cloud-Api-Key: {{apiKey}} |
| 80 | +Content-Type: multipart/form-data; boundary=--TheFormDataBoundary |
| 81 | +
|
| 82 | +----TheFormDataBoundary |
| 83 | +Content-Disposition: form-data; name="file"; filename="package.zip" |
| 84 | +content-type: application/octet-stream |
| 85 | +
|
| 86 | +< {{file}} |
| 87 | +----TheFormDataBoundary |
| 88 | +Content-Disposition: form-data; name="description" |
| 89 | +
|
| 90 | +{{description}} |
| 91 | +----TheFormDataBoundary |
| 92 | +Content-Disposition: form-data; name="version" |
| 93 | +
|
| 94 | +{{version}} |
| 95 | +----TheFormDataBoundary-- |
| 96 | +``` |
| 97 | +{% endtab %} |
| 98 | +{% endtabs %} |
| 99 | + |
| 100 | +Once the file is uploaded you will get a response which follows the following JSON schema: |
| 101 | + |
| 102 | +```json |
| 103 | +{ |
| 104 | + "artifactId": string, |
| 105 | + "fileName": string, |
| 106 | + "blobUrl": string, |
| 107 | + "filesize" : number, |
| 108 | + "createdUtc": string, |
| 109 | + "description": string, |
| 110 | + "version": string |
| 111 | +} |
| 112 | +``` |
| 113 | + |
| 114 | + |
| 115 | +### List artifacts |
| 116 | +List artifacts uploaded related to a project. The endpoint is paged and accepts the options skip and take. |
| 117 | +If skip is not supplied its value will default to 0. |
| 118 | +If take is not supplied its value will default to 10. |
| 119 | + |
| 120 | +{% tabs %} |
| 121 | +{% tab title="HTTP Request Syntax" %} |
| 122 | +```http |
| 123 | +@skip = 0 |
| 124 | +@take = 10 |
| 125 | +@projectId = Get this value from the portal |
| 126 | +@apiKey = Get this value from the portal |
| 127 | +
|
| 128 | +GET https://api.cloud.umbraco.com/v2/projects/{{projectId}}/deployments/artifacts?skip={{skip}}&take={{take}} |
| 129 | +Umbraco-Cloud-Api-Key: {{apiKey}} |
| 130 | +Content-Type: application/json |
| 131 | +``` |
| 132 | +{% endtab %} |
| 133 | +{% endtabs %} |
| 134 | + |
| 135 | +## How to make a deployment to Umbraco Cloud using the Umbraco CI/CD API |
| 136 | + |
| 137 | +### Start the deployment |
| 138 | + |
| 139 | +The Create Deployment endpoint start a new deployment and returns a unique `deploymentId`. |
| 140 | + |
| 141 | +Some new options are available to use in the request payload: |
| 142 | +- `artifactId` *REQUIRED* Points to the artifact you want to deploy |
| 143 | +- `targetEnvironmentAlias` *REQUIRED* Points to the environment you want to deploy to |
| 144 | +- `commitMessage` *OPTIONAL* The commit message you want stamped in the environment repository on Umbraco Cloud. |
| 145 | +- `noBuildAndRestore` *OPTIONAL* Set to true it will skip the restore and build in the isolated instance, default to false |
| 146 | + |
| 147 | +```http |
| 148 | +POST https://api.cloud.umbraco.com/v2/projects/{{projectId}}/deployments |
| 149 | +Umbraco-Cloud-Api-Key: {{apiKey}} |
| 150 | +Content-Type: application/json |
| 151 | +
|
| 152 | +{ |
| 153 | + "commitMessage": "My awesome commit", |
| 154 | + "artifactId": "bc0ebd6f-cef8-4e92-8887-ceb862a83bf0", |
| 155 | + "targetEnvironmentAlias": "Development", |
| 156 | + "noBuildAndRestore": true |
| 157 | +} |
| 158 | +``` |
| 159 | + |
| 160 | +Part of the returned response will be the actual `deploymentId`. The response from the API should be an HTTP 201 Created response including a `deploymentId`. This ID can be stored in the pipeline variables so it can be used in later steps. |
| 161 | + |
| 162 | +```json |
| 163 | +{ |
| 164 | + "deploymentId": "bc0ebd6f-cef8-4e92-8887-ceb862a83bf0", |
| 165 | + "projectId" : "abcdef12-cef8-4e92-8887-ceb123456789", |
| 166 | + "projectAlias": "", |
| 167 | + "deploymentState": "Created", |
| 168 | + "updateMessage": "", |
| 169 | + "errorMessage": "", |
| 170 | + "created": "2023-05-02T07:16:46.4183912", |
| 171 | + "lastModified": "2023-05-02T07:16:48.8544387", |
| 172 | + "completed": null |
| 173 | +} |
| 174 | +``` |
| 175 | + |
| 176 | +### Get Deployment status |
| 177 | + |
| 178 | +To monitor the status of a deployment—whether it's completed, successful, or otherwise — you can periodically query the 'Get Deployment Status' API. This API endpoint is an HTTP GET request to the Umbraco Cloud API, and it requires both the `projectId` and the `deploymentId` obtained from previous steps to be included in the path. |
| 179 | + |
| 180 | +Deployments in Umbraco services can take varying amounts of time to complete. Therefore, it's advisable to poll this API at regular intervals to stay updated on the deployment's current state. For example, in a simple project, you might choose to poll the API every 15 seconds for a duration of 15 minutes. These figures are just a starting point; the optimal polling frequency and duration may differ for your specific pipeline. Based on initial experience, a 15-minute window generally suffices, but we welcome your feedback to fine-tune these parameters. |
| 181 | + |
| 182 | +Using a curl command, polling for the deployment status would look like this: |
| 183 | + |
| 184 | +```http |
| 185 | +... |
| 186 | +url="https://api.cloud.umbraco.com/v1/projects/$projectId/deployments/$deploymentId" |
| 187 | +
|
| 188 | +# Define a function to call API and check the status |
| 189 | +function call_api { |
| 190 | + response=$(curl -s -X GET $url \ |
| 191 | + -H "Umbraco-Cloud-Api-Key: $apiKey" \ |
| 192 | + -H "Content-Type: application/json") |
| 193 | + echo "$response" |
| 194 | + status=$(echo $response | jq -r '.deploymentState') |
| 195 | +} |
| 196 | +
|
| 197 | +# Call API and check status |
| 198 | +call_api |
| 199 | +while [[ $status == "Pending" || $status == "InProgress" || $status == "Queued" ]]; do |
| 200 | + echo "Status is $status, waiting 15 seconds..." |
| 201 | + sleep 15 |
| 202 | + call_api |
| 203 | + if [[ $SECONDS -gt 900 ]]; then |
| 204 | + echo "Timeout reached, exiting loop." |
| 205 | + break |
| 206 | + fi |
| 207 | +done |
| 208 | +
|
| 209 | +# Check final status |
| 210 | +if [[ $status == "Completed" ]]; then |
| 211 | + echo "Deployment completed successfully." |
| 212 | +elif [[ $status == "Failed" ]]; then |
| 213 | + echo "Deployment failed." |
| 214 | + exit 1 |
| 215 | +else |
| 216 | + echo "Unexpected status: $status" |
| 217 | + exit 1 |
| 218 | +fi |
| 219 | +
|
| 220 | +``` |
| 221 | + |
| 222 | +The response from this API call will return the same deployment object in JSON format as you would receive from other API interactions. Ultimately, the `deploymentState` field will indicate either 'Completed' or 'Failed'. Should the deployment fail, the 'ErrorMessage' field will provide additional details regarding the issue. |
| 223 | + |
| 224 | +```json |
| 225 | +{ |
| 226 | + "deploymentId": "bc0ebd6f-cef8-4e92-8887-ceb862a83bf0", |
| 227 | + "projectId" : "abcdef12-cef8-4e92-8887-ceb123456789", |
| 228 | + "projectAlias": "cicd-demo-site", |
| 229 | + "deploymentState": "Completed", |
| 230 | + "updateMessage":"Project information set\nDeployment pending\nDownloadUri set\nDeployment queued\nDeployment triggered\nDeployment started\nCheck blocking markers\nCreate updating marker\nGit Clone\nDownload update\nExtract Update\nChecking versions\nDeleting repository files\nCopying files to repository\nNuGet Restore\nDotnet Build\nGit Stage\nGit Commit\nGit Tag\nGit Push\nDelete updating marker\nDeployment successful", |
| 231 | + "errorMessage": "", |
| 232 | + "created": "2023-05-02T07:16:46.4183912", |
| 233 | + "lastModified": "2023-05-02T07:20:48.8544387", |
| 234 | + "completed": "2023-05-02T07:20:49.8544387" |
| 235 | +} |
| 236 | +``` |
| 237 | + |
| 238 | +### Get Deployments |
| 239 | + |
| 240 | +The endpoint lets you retrieve a list of completed deployments. It can only list deployments that has been run through the api. |
| 241 | + |
| 242 | +The API allows you to filter and limit the number of returned deployments using query parameters: |
| 243 | + |
| 244 | +* _Skip_ : optional, zero or positive integer |
| 245 | +* _Take_ : optional, zero or positive integer |
| 246 | +* _Includenulldeployments_ : optional, boolean, defaults to true |
| 247 | + |
| 248 | +The "skip" and "take" parameters, while optional, are always required to be used together. |
| 249 | + |
| 250 | +With `includenulldeployments` set to true, you will get all completed deployments, including those that did not create any new changes in the cloud repository. |
| 251 | + |
| 252 | +To fetch the list of deployments using a curl command, the syntax would be as follows: |
| 253 | + |
| 254 | +```sh |
| 255 | +... |
| 256 | +url="https://api.cloud.umbraco.com/v1/projects/$projectId/deployments?skip=0&take=1&includenulldeployments=false" |
| 257 | + |
| 258 | +response=$(curl -s -X GET $url \ |
| 259 | + -H "Umbraco-Cloud-Api-Key: $apiKey" \ |
| 260 | + -H "Content-Type: application/json") |
| 261 | +latestDeploymentId=$(echo $response | jq -r '.deployments[0].deploymentId') |
| 262 | + |
| 263 | +``` |
| 264 | + |
| 265 | +The response from this API call will return an object containing a list of deployment objects. The deployment-objects are consistent with the structure used in other API responses. Deployments are listed in descending order based on their creation timestamp. |
| 266 | + |
| 267 | +```json |
| 268 | +{ |
| 269 | + "projectId": "abcdef12-cef8-4e92-8887-ceb123456789", |
| 270 | + "deployments": |
| 271 | + [ |
| 272 | + { |
| 273 | + "deploymentId": "bc0ebd6f-cef8-4e92-8887-ceb862a83bf0", |
| 274 | + "projectId" : "abcdef12-cef8-4e92-8887-ceb123456789", |
| 275 | + "projectAlias": "cicd-demo-site", |
| 276 | + "deploymentState": "Completed", |
| 277 | + "updateMessage": "...", |
| 278 | + "errorMessage": "", |
| 279 | + "created": "2023-05-02T07:16:46.4183912", |
| 280 | + "lastModified": "2023-05-02T07:18:48.8544387", |
| 281 | + "completed": "2023-05-02T07:22:48.8544387" |
| 282 | + } |
| 283 | + ] |
| 284 | +} |
| 285 | +``` |
| 286 | + |
| 287 | +### Get Deployment diff |
| 288 | + |
| 289 | +Sometimes updates are done directly on the Umbraco Cloud repository. We encourage you to not do any actual work there, but auto-upgrades and environment changes will affect the umbraco-cloud-git-repos. To keep track of such changes, you can use the 'Get Deployment Diff' API. This API endpoint will provide you with a git-patch file detailing the changes between a specific deployment and the current state of the repository. To make this API call, you'll need to include both the `projectId` and the `deploymentId` of the deployment you want to check for differences against. This is a standard HTTP GET request. |
| 290 | + |
| 291 | +Using a curl command, fetching the potential differences would look like this: |
| 292 | + |
| 293 | +```sh |
| 294 | +url="https://api.cloud.umbraco.com/v1/projects/$projectId/deployments/$latestCompletedDeploymentId/diff" |
| 295 | +downloadFolder="tmp" |
| 296 | +mkdir -p $downloadFolder # ensure folder exists |
| 297 | + |
| 298 | +responseCode=$(curl -s -w "%{http_code}" -L -o "$downloadFolder/git-patch.diff" -X GET $url \ |
| 299 | + -H "Umbraco-Cloud-Api-Key: $apiKey" \ |
| 300 | + -H "Content-Type: application/json") |
| 301 | + |
| 302 | +if [[ 10#$responseCode -eq 204 ]]; then # Http 204 No Content means that there are no changes |
| 303 | + echo "No changes" |
| 304 | + rm -fr $downloadFolder/git-patch.diff |
| 305 | +elif [[ 10#$responseCode -eq 200 ]]; then # Http 200 downloads the file and set a few variables for pipeline |
| 306 | + echo "Changes - check file - $downloadFolder/git-patch.diff" |
| 307 | +else |
| 308 | + echo "Unexpected status: $responseCode" |
| 309 | + exit 1 |
| 310 | +fi |
| 311 | + |
| 312 | +``` |
| 313 | + |
| 314 | +The API response will vary based on whether or not there are changes to report. If no changes are detected, you'll receive an HTTP 204 No Content status. On the other hand, if there are changes, the API will return an HTTP 200 OK status along with a git-patch file as the content. This git-patch file can then be applied to your local repository to sync it with the changes. |
| 315 | + |
| 316 | +### Possible errors |
| 317 | + |
| 318 | +When interacting with the Umbraco Cloud API, you may encounter various HTTP status codes that indicate the success or failure of your API request. Below is a table summarizing the possible status codes, their corresponding errors, and basic root causes to guide your troubleshooting: |
| 319 | + |
| 320 | +| Status Code | Error | Basic Root Cause | |
| 321 | +| ----------- | ------------------- | ----------------------------------------------------------------------------------- | |
| 322 | +| 400 | BadRequest | Check the requested path, supplied headers and query-parameters | |
| 323 | +| 401 | Unauthorized | Check the Project Id and Api Key | |
| 324 | +| 404 | NotFound | Usually related to the supplied deploymentId in path not being found | |
| 325 | +| 409 | Conflict | The state of the referenced deployment is not ready for the work you are requesting | |
| 326 | +| 500 | InternalServerError | InternalServerError | |
| 327 | + |
| 328 | +Most errors have a response body that corresponds to this JSON, and the “detail” field will have a more complete error message. |
| 329 | + |
| 330 | +``` |
| 331 | +{ |
| 332 | + “title”: string, |
| 333 | + “status”: number, |
| 334 | + “detail”: string, |
| 335 | +} |
| 336 | +``` |
0 commit comments