Mukil Deepthi
Mukil Deepthi

Reputation: 6452

Azure Devops how to deploy static angular app to azure blob storage

I am completely new to deploy azure static webapp to azure. I have a very simple angular app and azure devops account.

I want to setup the azure devops pipeline to build and upload the angular app files to blob container. Note: i dont have azure subscription and only having storage account connection string details.

my yml file so far is. not sure how to proceed further.

trigger:
- main

pool:
  vmImage: ubuntu-latest

steps:
- task: NodeTool@0
  inputs:
    versionSpec: '12.x'
  displayName: 'Install Node.js'

- script: |
    npm install -g @angular/cli
    npm install
    ng build --prod
  displayName: 'npm install and build'

Can anyone please help me how to do this.

i see some script available to upload but not sure how to add to the pipeline

az storage blob upload --account-name mystorageaccount --account-key 0000-0000 --container-name mycontainer --file /path/to/file --name myblob

Upvotes: 2

Views: 2519

Answers (2)

Doug
Doug

Reputation: 7067

This is the YAML I utilize for deploying an Angular App to Blob Storage. Under "capabilities" of the Storage Account, you will need to enable "Static Website" which will create the $web container, beyond that, update the variables in the following YAML and it should work as-is.

Here is the entire YAML, and then I will explain it section by section to give more context:

variables:
- name: storageContainer
  value: myStorageaccount
- name: subscription
  value: Subscription (8217a062-4d59-45f6-bc03-b6f559a1e58a)
trigger:
  branches:
    include:
    - master
stages:
- stage: __default
  jobs:
  - job: Job
    pool:
      vmImage: windows-latest
    steps:
    - task: NodeTool@0
      inputs:
        versionSpec: '14.17.4'
        force32bit: true
    - task: CmdLine@2
      displayName: npm install
      inputs:
        script: |
          npm install
    - task: CmdLine@2
      displayName: ng build
      inputs:
        script: |
          set PATH=%PATH%;%CD%\node_modules\.bin;C:\npm\prefix
          ng build --subresource-integrity --output-hashing none
    - task: AzureFileCopy@2
      displayName: Deploy Files
      inputs:
        SourcePath: '$(System.DefaultWorkingDirectory)\dist\$(Build.Repository.Name)'
        azureSubscription: $(subscription)
        Destination: 'AzureBlob'
        storage: $(storageContainer)
        ContainerName: '$web'
        BlobPrefix: ''
    - task: AzureCLI@2
      displayName: Delete Old Files
      inputs:
        azureSubscription: $(subscription)
        scriptType: 'pscore'
        scriptLocation: 'inlineScript'
        inlineScript: 'az storage blob delete-batch -s `$web --account-name $(storageContainer) --if-unmodified-since $(Get-Date ((Get-Date).addMinutes(-5)) -UFORMAT +%Y-%m-%dT%H:%MZ)'

Okay, here it is section by section:

The following sets the values for the variables storageContainer and subscription to be used in the rest of the commands. Variables are replaced when you use $(storageContainer) type syntax.

variables:
- name: storageContainer
  value: myStorageaccount
- name: subscription
  value: Subscription (8217a062-4d59-45f6-bc03-b6f559a1e58a)

The following sets continuous build / delivery when code is returned to the master branch, and tells everything to deploy to a vm with the latest build of Windows. Windows is needed for some of the azure cli commands later on:

trigger:
  branches:
    include:
    - master
stages:
- stage: __default
  jobs:
  - job: Job
    pool:
      vmImage: windows-latest

The following task installs node version 14.17.4 onto the system in order to utilize it. I had it utilize the 32-bit version of node, but that really shouldn't matter.

steps:
- task: NodeTool@0
  inputs:
    versionSpec: '14.17.4'
    force32bit: true

The following executes the npm install and installs everything from packages.json. I added the angular/cli to my dev dependencies, and therefore its installed with this. If you don't want to do that, you'll need a command that installs the angular cli. Please keep in mind, Azure DevOps doesn't seem to like it when there is more than one node install within a CmdLine block, so you'll need another block.

- task: CmdLine@2
  displayName: npm install
  inputs:
    script: |
      npm install

The following does the Angular build (ng build). The first thing I do is set the path appropriately so that it can find the Angular cli in the dev dependencies. I also have it add c:\npm\prefix to the path, which is apparently where the global npm installs are put. That was hard to find / figure out; so I left it in the path when I found it. In my Angular build I have two flags. The --subresource-integrity flag makes it so that the script tags have an integrity attribute that has the hash of the JavaScript file. This is considered a security best practice. I also have the --output-hashing none set. This makes it so that files are just main.js rather than the longer names with the hash in the JS file. This is just a preference of mine.

- task: CmdLine@2
  displayName: ng build
  inputs:
    script: |
      set PATH=%PATH%;%CD%\node_modules\.bin;C:\npm\prefix
      ng build --subresource-integrity --output-hashing none

The following Azure Cli command copies all of the files to the $web container of the storage account. The Angular build command by default putss these files from whatever is listed in "outputPath" in your angular.json. By default this is a folder under the dist directory. That folder happens to be the same exact name as my Git Repository, which I think is normal. This is why I have the source to grab files from be '$(System.DefaultWorkingDirectory)\dist$(Build.Repository.Name)' . I think this should work for you out-of-the-box the way I have it, but if not, replace "dist$(Build.Repository.Name)" with whatever is set in outputPath of your angular.json .

- task: AzureFileCopy@2
  displayName: Deploy Files
  inputs:
    SourcePath: '$(System.DefaultWorkingDirectory)\dist\$(Build.Repository.Name)'
    azureSubscription: $(subscription)
    Destination: 'AzureBlob'
    storage: $(storageContainer)
    ContainerName: '$web'
    BlobPrefix: ''

When copying files to an Azure Storage Account, by default it will overwrite files with the same name. However, it won't do anything with files that are no longer used and aren't overwritten. For that reason, this last section will delete any files that haven't been modified in the last 5 minutes. This build process on average takes about 4 minutes, so I figured anything that was older than 5 minutes was from a prior build.

- task: AzureCLI@2
  displayName: Delete Old Files
  inputs:
    azureSubscription: $(subscription)
    scriptType: 'pscore'
    scriptLocation: 'inlineScript'
    inlineScript: 'az storage blob delete-batch -s `$web --account-name $(storageContainer) --if-unmodified-since $(Get-Date ((Get-Date).addMinutes(-5)) -UFORMAT +%Y-%m-%dT%H:%MZ)'

Hopefully this helps save someone some time. This took MUCH more time than I was expecting to get properly put together.

Upvotes: 1

ShrutiJoshi-MT
ShrutiJoshi-MT

Reputation: 1833

Try with following steps.

1) Enable the static website hosting in storage account. Storage Account's side-menu (Settings ⇒ Static website)

enter image description here

enter image description here

2) Configure the release pipeline for storage account. Creating a release pipeline that will use the artifacts published as part of the build pipeline for more details refer this document document

inside an Azure DevOps project, create a new Release Pipeline by selecting Pipeline ⇒ Releases ⇒ New ⇒ New Release Pipeline

enter image description here

3) choose to start with an empty job instead of selecting a preconfigured template. As Azure DevOps supports multiple stages, provide the name for the stage that's created by default, or you can keep Stage 1 as its name.

4) Add the build artifacts.

Click Add an Artifact, select the Build source type (as the artifacts are stored within the build pipeline), and select the appropriate build pipeline from the source dropdown. You can keep the default values for both the version to deploy, as we always want to deploy the latest version, and the source alias. The source alias is the folder that will be used to download the artifacts.

enter image description here

5) Add the deployment tasks.

started with an empty job(step 3), there are no tasks defined yet. add the task to deploy the artifact's files to an Azure Storage Account.click the '+' on the Agent job, search for Azure file copy, and click the add.

When adding an Azure file copy task, need to provide the required information in order for Azure DevOps to know what files have to be deployed to which destination. This includes both the Azure Subscription, and the Storage Account information.

enter image description here

6) select your Azure Subscription, select Azure Blob as the Destination Type, choose the appropriate Storage Account , and provide $web for the container name (this is the default container name used by Azure Devops when enabling static websites inside an Azure Storage Account)

enter image description here

7) Use of Environment specific configuration

to avoid rebuilding the application in order for it to use environment-specific configuration, Use the JSON file that's served as part of the assets directory, and is retrieved in our Angular application using an Http Request. You can find a detailed overview on how to configure in this document

Create a File transform task to modify the contents of the config.json file as part of release pipeline's stage (in case of multiple stages, every stage can have its own step, and can replace the contents with different values before deploying). Add the task, and configure it to target the assets/config.json file inside web-app artifact.

enter image description here

8) Execute the task before deploying the files to Azure Storage.

enter image description here

9) create release pipeline variables. The file transform task will use all the variables, and update values based on its name

enter image description here

10) Enable the Continuous deployment trigger to continuously deploy artifacts.

Click on the lightning strike symbol that's showing up on your artifact in the pipeline section, enable the Continuous deployment trigger

enter image description here

11) Once the deployment is finished, navigating to one of the Azure Storage endpoint URL's should show the Angular application.

enter image description here

For more details refer this document

Upvotes: 1

Related Questions