sainture
10/13/2019 - 7:08 AM

Angular Library - Azure DevOps Feed

1:
Create Azure Artifacts Feed
Azure Artifacts supports publishing and consuming npm packages to and from Azure Artifacts feeds. So either create a new feed or select an already existing feed.
Create a Feed: 
https://docs.microsoft.com/en-us/azure/devops/artifacts/get-started-npm?view=azure-devops#create-a-feed

2:
Connecting to the Feed
All Azure Artifacts feeds require authentication. You store credentials for the feed before you can install or publish packages.

    Step 1 - Download Node.js and npm (skip this step if you already have node installed)

    Step 2 - Install authentication provider “vsts-npm-auth“
    npm install -g vsts-npm-auth --registry https://registry.npmjs.com --always-auth false 

    Step 3 - Add a .npmrc to your project, in the same directory as your package.json
    registry=https://pkgs.dev.azure.com/<project-name>/_packaging/{Name of the Feed}/npm/registry/                          
    always-auth=true

    Step 4 - Then, run vsts-npm-auth to get an Azure Artifacts token added to your user-level .npmrc file
    vsts-npm-auth -config .npmrc
    This token is valid for 90 days and we can add a script in our npm scripts to refresh the token like
    "scripts": {
         "refreshVSToken": "vsts-npm-auth -config .npmrc"
     }

3:
Publishing  a package to the feed
    Step 1 - Build Angular Library project
    ng build <library-name> --prod
    The above will build the library package and output the files into “dist/<library-name>“ folder

    Step 2 - Copy .npmrc file to “dist/<library-name>“ folder

    Step 3 - go to dist folder
    cd dist/<library-name>

    Step 4 - Publish to the feed
    npm publish

4:
Installing a package from the feed in your project
    Step 1 - Follow all steps in “Connecting to the Feed“ 

    Step 2 - npm install <package-name>


Build Pipeline steps in Azure DevOps - azure-pipelines.yml file


trigger:
- master
- release/*

pool:
  vmImage: 'ubuntu-latest'

variables:
  isMasterBranch: $[eq(variables['Build.SourceBranch'], 'refs/heads/master')]
  isReleaseBranch: $[startsWith(variables['Build.SourceBranch'], 'refs/heads/release/')]
  ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/master')}}:
    releaseEnvironment: 'Development'
  ${{ if startsWith(variables['Build.SourceBranch'], 'refs/heads/release/')}}:
    releaseEnvironment: 'Staging'
  npm_config_cache: $(Pipeline.Workspace)/.npm
  buildNumber: ''

stages:
- stage: Build
  jobs:
  - job: FrontEnd
    steps:
    - task: NodeTool@0
      inputs:
        versionSpec: '14.15.0'
      displayName: 'Install Node'

    - script: |
        npm install -g @angular/cli
      displayName: 'npm install CLI'

    - script: |
        npm ci
      displayName: 'Run npm ci'

    - task: gitversion/setup@0
      displayName: 'Setup GitVersion'
      inputs:
        versionSpec: '5.x'

    - task: gitversion/execute@0
      inputs:
        useConfigFile: true
        configFilePath: '$(Build.SourcesDirectory)/GitVersion.yml'
      displayName: 'Get build version from GitVersion'
    
    - bash: echo "##vso[task.setvariable variable=buildNumber;isOutput=true]$(GitVersion.SemVer)"
      displayName: 'Set build version from GitVersion'
      name: setBuildNumber 

    - script: |
        ng test <library-name> --browsers=ChromeHeadless --watch=false
      displayName: 'Run tests'

    - task: PublishTestResults@2
      condition: succeededOrFailed()
      inputs:
        testResultsFormat: 'JUnit'
        testResultsFiles: '**/junit.xml'
      displayName: 'Publish Test Results'

    - script: |
        npm version $(GitVersion.SemVer)
        npm version --prefix ./projects/<path-to-library-folder> $(GitVersion.SemVer)
        ng build <library-name> --prod
      displayName: 'Build Library'


    - task: PublishPipelineArtifact@1
      inputs:
        targetPath: $(Build.SourcesDirectory)/dist

    - task: Npm@1
      displayName: '[Npm] Publish'
      condition: and(succeeded(), or(eq(variables.isMasterBranch, true), eq(variables.isReleaseBranch, true)))
      inputs:
        command: 'publish'
        workingDir: '$(Build.SourcesDirectory)/dist/<path-to-library-folder>'
        verbose: true
        publishRegistry: 'useFeed'
        publishFeed: '<feedId>'