Self-hosted Live Updates with Azure DevOps
Overview
Self-hosted Live Updates allows customers to build and host their web artifacts then deploy them as Live Updates to app users. To help ensure secure end-to-end delivery, code signing and signature verification steps are included as well.
This example walks through setting up Self-hosted live updates in a Capacitor app using Azure DevOps.
Requirements
For this example, we've already followed the Self-hosted live update App Setup instructions. This includes creating an Appflow app, a personal access token (PAT), a public/private key, and configuring the Capacitor app.
Azure DevOps Setup
With your Capacitor app configured to use self-hosted live updates, we can configure Azure DevOps next.
Store the Private Key Securely
To store the private key securely in Azure, upload it to "Secure Files", found under Pipelines -> Library -> Secure files. This also makes it available to the pipeline we'll write shortly.
Store a Personal Access Token Securely
The personal access token is used to authenticate access to your Appflow account via the Ionic Cloud CLI, so it also needs to be made available to the pipeline. Under Pipelines -> Library -> Variable groups, create a new variable group ("Ionic Tokens" for example), then create a variable named APPFLOW_PAT (or similar). Click the lock icon to mark the variable as secret.
Create an Azure Storage Blob
The final Azure setup step involves creating an Azure storage blob to host the live updates. From the Azure Portal, navigate to Storage Accounts and create a new one. You may need to create a new Resource group (such as "liveupdates"),
On the next screen, Advanced, turn on "Allow enabling public access on containers." Public access is required for the Capacitor Live Updates plugin to download live updates onto your app user's devices. It's worth noting that by default, Azure encrypts storage account data at rest. Turn on "Require secure transfer for REST API operations" and set Access tier to "Hot", ideal for frequently access data such as live updates.
Once the Storage Account has been created, navigate into it and under Data Storage -> Containers, create a new container ("liveupdates"). This is where the live update artifacts will be stored. Set the Public access level to "Blob (anonymous read access for blobs only)."
Once the container has been created, click into it and navigate to Properties. Note the URL - this is the public URL that we'll register with Appflow. An example URL looks like: https://ionicselfhosted.blob.core.windows.net/liveupdates.
Write a Pipeline
Now, we're ready to write an Azure pipeline that creates and registers a live update. Here's the complete YAML script:
Complete YAML Script
# Self-hosted Live Updates pipeline example
trigger:
- main
pool:
vmImage: ubuntu-latest
variables:
- group: "Ionic Tokens"
- name: liveUpdateZipFilename
value: "live-update-bundle-$(Build.SourceVersion).zip"
- name: newLiveUpdateArtifactPath
value: LIVE_UPDATE_CONTAINER/$(liveUpdateZipFilename)
steps:
- task: Npm@1
inputs:
command: 'install'
workingDir: '$(Build.SourcesDirectory)'
displayName: 'npm Install'
- script: |
npm run build
workingDirectory: $(Build.SourcesDirectory)
displayName: 'Build Web'
- script: curl -sL https://ionic.io/get-ionic-cloud-cli | bash
displayName: 'Install Ionic Cloud CLI'
# Download a secure file to the agent machine
- task: DownloadSecureFile@1
name: ionicSigningKey
inputs:
secureFile: 'PEM_FILE'
# Bundle the web artifact
- script: |
ionic-cloud live-update bundle-artifact
--build-dir=DIR
--token=$(APPFLOW_PAT)
--signing-key=$(ionicSigningKey.secureFilePath)
--output-path=./$(liveUpdateZipFilename)
displayName: 'Bundle web artifact'
# Upload the live update to Azure Storage
- task: AzureCLI@2
inputs:
azureSubscription: 'SUBSCRIPTION'
scriptType: pscore
scriptLocation: 'inlineScript'
inlineScript: |
az storage blob upload
-c CONTAINER_NAME
--account-name ACCOUNT_NAME
-f ./$(liveUpdateZipFilename)
displayName: 'Upload web artifact to Azure blob storage'
# Register the signed live update with Appflow
- script: |
ionic-cloud live-update register-artifact
--app-id=APP_ID
--artifact-url='$(newLiveUpdateArtifactPath)'
--commit-ref=$(Build.SourceBranchName)
--commit-sha=$(Build.SourceVersion)
--commit-message='$(Build.SourceVersionMessage)'
--token=$(APPFLOW_PAT)
displayName: 'Register live update with Appflow'
Let's walk through this pipeline step by step.
Pipeline Trigger and VM
This pipeline will run every time there is a commit to the "production" branch. We recommend running on a Linux VM, so ubuntu-latest
is used.
# Self-hosted Live Updates pipeline example
trigger:
- production
pool:
vmImage: ubuntu-latest
Create Variables
Next, we'll prepare some variables.
group
: Including the "Ionic Tokens" group makes the personal access token we stored earlier (APPFLOW_PAT
) accessible to this pipeline.liveUpdateZipFilename
: The filename for the live update that will be created in this pipeline. Adding the Git commit SHA to the end (Build.SourceVersion
) will make each live update filename unique.newLiveUpdateArtifactPath
: The URL to the Azure storage blog we created earlier, such ashttps://ionicselfhosted.blob.core.windows.net/liveupdates/$(liveUpdateZipFilename)
.
variables:
- group: "Ionic Tokens"
- name: liveUpdateZipFilename
value: "live-update-bundle-$(Build.SourceVersion).zip"
- name: newLiveUpdateArtifactPath
value: LIVE_UPDATE_CONTAINER/$(liveUpdateZipFilename)
Build the Web App
Next, we build the web app. Make any changes needed to build your app.
steps:
- task: Npm@1
inputs:
command: 'install'
workingDir: '$(Build.SourcesDirectory)'
displayName: 'npm Install'
- script: |
npm run build
workingDirectory: $(Build.SourcesDirectory)
displayName: 'Build Web'
Install Ionic Cloud CLI
Next, install the Ionic Cloud CLI so we can use Self-hosted live update features:
- script: curl -sL https://ionic.io/get-ionic-cloud-cli | bash
displayName: 'Install Ionic Cloud CLI'
Download Private Key to VM
Next, we download the private key file we stored earlier to make it accessible to this pipeline.
secureFile
: The private key pem file, such asionic_cloud_private.pem
.
# Download a secure file to the agent machine
- task: DownloadSecureFile@1
name: ionicSigningKey # The name with which to reference the secure file's path on the agent
inputs:
secureFile: 'PEM_FILE'
Create a Signed Live Update
Now that the web app has been built, we can use the Cloud CLI bundle-artifact
command to turn the web artifact into a live update.
build-dir
: The top-level build directory containing the compiled web app, such aswww
for an Angular app.signing-key
: The private key we retrieved above, used to sign the live update.output-path
: The location and filename to store the live update. In this example, the$(liveUpdateZipFilename)
variable resolves to something likelive-update-bundle-0cd14bb0.zip
at the root of the VM.token
: The personal access token pulled in from the "Ionic Tokens" variable group above.
# Bundle the web artifact
- script: |
ionic-cloud live-update bundle-artifact
--build-dir=DIR
--token=$(APPFLOW_PAT)
--signing-key=$(ionicSigningKey.secureFilePath)
--output-path=./$(liveUpdateZipFilename)
displayName: 'Bundle web artifact'
Upload Live Update to Azure Blob Storage
With the new live update created, we can upload it to Azure blob storage. There are several ways to do so; in this case, we can use the Azure CLI task. We recommend adding this step using the Assistant (search for the "azure cli" task).
azureSubscription
: The subscription name and GUID (will look similar to'Azure subscription 1(cdc3c210-xxxxxx)'
).scriptType
: Set topscore
(PowerShell Core) and location toinlineScript
.inlineScript
: Configure the inline script with your container and account names. In this example, they areliveupdates
andionicselfhosted
.
# Upload the live update to Azure Storage
- task: AzureCLI@2
inputs:
azureSubscription: 'SUBSCRIPTION'
scriptType: pscore
scriptLocation: 'inlineScript'
inlineScript: |
az storage blob upload
-c CONTAINER_NAME
--account-name ACCOUNT_NAME
-f ./$(liveUpdateZipFilename)
displayName: 'Upload web artifact to Azure blob storage'
Register Signed Live Update with Appflow
In this last step, inform Appflow that a new live update is available with the Cloud CLI register-artifact
command.
app-id
: The Appflow app id, like042a1261
. Find this value under the app's name in Appflow or the URL (https://dashboard.ionicframework.com/app/042a1261/getting-started
).artifact-url
: The URL where the new live update artifact is stored. The Capacitor live update plugin will download the live update from this location. In this example, it resolves to a URL likehttps://ionicselfhosted.blob.core.windows.net/liveupdates/live-update-bundle-adf9137y45.zip
.token
: The Appflow personal access token.commit-ref
: The branch name of the commit, such as "main" or "production."commit-sha
: The Git commit SHA, such as "adf9137y45".commit-message
: The Git commit message, such as "Fix login bug."
# Register the signed live update with Appflow
- script: |
ionic-cloud live-update register-artifact
--app-id=APP_ID
--artifact-url='$(newLiveUpdateArtifactPath)'
--commit-ref=$(Build.SourceBranchName)
--commit-sha=$(Build.SourceVersion)
--commit-message='$(Build.SourceVersionMessage)'
--token=$(APPFLOW_PAT)
displayName: 'Register live update with Appflow'
Save and run the pipeline. A Self-hosted live update hosted in Azure is now available!
Deploy a Live Update
Once the pipeline has finished running, you'll find the new Self-hosted live update in your App's Builds list in Appflow. From there, you can follow the standard Live Update flow of assigning the build to a Live Update Channel.