How to use pnpm on Azure Pipelines? - azure

In my Nextjs project, I want to create a pipeline using Azure Pipelines. But my project uses pnpm package manager. I have read pnpm doc that only Travis, Semaphore, AppVeyor, GitHub Actions, Gitlab CI, and Bitbucket Pipelines. No Azure Pipelines documentation.
Does anyone know how to implement this?

I have created my own recipe for my pipelines in Azure pipelines.
Any feedback will be useful
For Nextjs
azure-pipelines.yml
variables:
pnpm_config_cache: $(Pipeline.Workspace)/.pnpm-store
trigger:
- main
pool:
vmImage: ubuntu-latest
steps:
- task: Cache#2
inputs:
key: 'pnpm | "$(Agent.OS)" | pnpm-lock.yaml'
path: $(pnpm_config_cache)
displayName: Cache pnpm
- task: Cache#2
inputs:
key: next | $(Agent.OS) | pnpm-lock.yaml
path: "$(System.DefaultWorkingDirectory)/.next/cache"
displayName: "Cache .next/cache"
- script: |
curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm#7
pnpm config set store-dir $(pnpm_config_cache)
displayName: "Setup pnpm"
- script: |
pnpm install
pnpm run build
displayName: "pnpm install and build"
- task: ArchiveFiles#2
inputs:
rootFolderOrFile: "."
includeRootFolder: false
archiveType: "zip"
archiveFile: "$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip"
replaceExistingArchive: true
- task: PublishBuildArtifacts#1
inputs:
PathtoPublish: "$(Build.ArtifactStagingDirectory)"
ArtifactName: "drop"
publishLocation: "Container"
For other build (removed version of Nextjs part)
azure-pipelines.yml
variables:
pnpm_config_cache: $(Pipeline.Workspace)/.pnpm-store
trigger:
- main
pool:
vmImage: ubuntu-latest
steps:
- task: Cache#2
inputs:
key: 'pnpm | "$(Agent.OS)" | pnpm-lock.yaml'
path: $(pnpm_config_cache)
displayName: Cache pnpm
- script: |
curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm#7
pnpm config set store-dir $(pnpm_config_cache)
displayName: "Setup pnpm"
- script: |
pnpm install
pnpm run build
displayName: "pnpm install and build"
- task: ArchiveFiles#2
inputs:
rootFolderOrFile: "."
includeRootFolder: false
archiveType: "zip"
archiveFile: "$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip"
replaceExistingArchive: true
- task: PublishBuildArtifacts#1
inputs:
PathtoPublish: "$(Build.ArtifactStagingDirectory)"
ArtifactName: "drop"
publishLocation: "Container"

Related

How to deploy two zipped Functions to the same Azure Function App?

I trying to deploy two zipped Functions to the same Azure Function App called http-trigger-api-test and the result is that the first one gets deployed but then it is replaced by the second function.
I have the tasks in the following yaml file:
- stage: Build
displayName: Build stage for Azure Function
jobs:
- job: Build
steps:
- task: ArchiveFiles#2
displayName: 'Archive HttpTriggerApi Azure Function'
inputs:
rootFolderOrFile: 'azure/azure_functions/HttpTriggerApi/function_code'
includeRootFolder: false
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
replaceExistingArchive: true
- task: ArchiveFiles#2
displayName: 'Archive HttpTriggerApiWeb Azure Function'
inputs:
rootFolderOrFile: 'azure/azure_functions/HttpTriggerApi/function_code_web'
includeRootFolder: false
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId)2.zip
replaceExistingArchive: true
- upload: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
displayName: 'Upload Azure Function Full Stack'
artifact: full_stack_deploy
- upload: $(Build.ArtifactStagingDirectory)/$(Build.BuildId)2.zip
displayName: 'Upload Azure Function Web Stack'
artifact: web_deploy
- stage: TEST
displayName: Deploy stage Test
variables:
- group: optimizelyeventconnector-test-group
jobs:
- deployment: Deploy
displayName: Deploy
environment: optimizelyeventconnector-test
pool:
vmImage: $(vmImageName)
strategy:
runOnce:
deploy:
steps:
- task: AzureCLI#1
displayName: 'Deploy Azure Function Full Stack'
inputs:
azureSubscription: 'test-group-SPN'
scriptType: 'ps'
scriptLocation: 'inlineScript'
inlineScript: |
az functionapp deployment source config-zip -g test-group -n http-trigger-api-test --src $(Pipeline.Workspace)/full_stack_deploy/$(Build.BuildId).zip
- task: AzureCLI#1
displayName: 'Deploy Azure Function Web Stack'
inputs:
azureSubscription: 'test-group-SPN'
scriptType: 'ps'
scriptLocation: 'inlineScript'
inlineScript: |
az functionapp deployment source config-zip -g test-group -n http-trigger-api-test --src $(Pipeline.Workspace)/web_deploy/$(Build.BuildId)2.zip
I have read some questions where it is suggested not to pack several functions into one function app unless they are related. In my case, both functions are related.
Any suggestion, comment or improvement to this questions is welcome.
After some research I found the solution.
I had to structure my function app in the following way:
- main_function_app
- functions
- Full_Stack
- configAPI.json
- configAPITest.json
- function.json
- index.js
- Web
- configAPI.json
- configAPITest.json
- function.json
- index.js
- host.json
- local.settings.json
- package-lock.json
- package.json
- proxies.json
- utils.js
When deploying to azure, you need to install node, dependencies, zip the files and publish them.
- stage: Build
displayName: Build stage for Azure Function
jobs:
- job: Build
displayName: Build
pool:
vmImage: $(vmImageName)
steps:
- task: NodeTool#0
inputs:
versionSpec: '14.x'
displayName: 'Install Node.js'
- task: Bash#3
inputs:
targetType: 'inline'
script: 'npm install --prefix azure/azure_functions/HttpTriggerApi/main_function_app/functions'
- task: ArchiveFiles#2
displayName: 'Build Azure Functions and Dependencies'
inputs:
rootFolderOrFile: 'azure/azure_functions/HttpTriggerApi/main_function_app/functions'
includeRootFolder: false
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
replaceExistingArchive: true
- upload: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
displayName: 'Publish Azure Functions Artifact'
artifact: functions

CI-CD Azure devops for function app deployment

My Function app Name:
my_func_dev_app
Functions I have in my project
func_dev
func_prd
Push func_dev to my_func_dev_app
Push func_prd to my_func_prd_app
But It is pushing both func_dev and func_prd to my_func_de_app
My app folder structure
(folder)myapp_function
(folder)func_dev --__init__.py
-- function.json
(folder)func_prd --__init__.py
-- function.json
task.py
Multi stage Pipeline:
#pipelines1
trigger:
- '*'
stages:
- stage: 'Build'
displayName: 'Build the web application'
jobs:
- job: 'Build'
displayName: 'Build job'
pool:
name: 'onprem_agent'
steps:
- task: CopyFiles#2
displayName: 'Copy Files to: $(Build.ArtifactStagingDirectory)'
inputs:
SourceFolder: '$(Build.SourcesDirectory)'
Contents: |
**/*
!.git/**
OverWrite: true
CleanTargetFolder: true
TargetFolder: '$(Build.ArtifactStagingDirectory)'
- task: ArchiveFiles#2
displayName: "Archive files"
inputs:
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/myapp_function'
includeRootFolder: false
archiveFile: '$(Build.ArtifactStagingDirectory)/build$(Build.BuildId).zip'
- task: PublishBuildArtifacts#1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'myapp_function'
- stage: 'DEV_AZURE'
displayName: 'Az DEV Deploy'
dependsOn: Build
condition: |
and
(
succeeded(),
eq(variables['Build.SourceBranchName'], variables['releaseBranchName'])
)
jobs:
- deployment: Deploy
environment: dev
variables:
- group: Release
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: myapp_function
displayName: Downloading artifacts
- task: AzureFunctionApp#1
inputs:
azureSubscription: CI-CD
appType: functionAppLinux
appName: my_func_dev_app
package: '$(Pipeline.Workspace)/myapp_function/*.zip'
deployToSlotOrASE: true
resourceGroupName: my-rg
slotName: PRODUCTION
displayName: 'Deploying dev'
How to fix? Push func_dev to my_func_dev_app and ignore func_prd
How to fix? Push func_dev to my_func_dev_app and ignore func_prd
To solve this issue, you can package your two projects separately into zip.
In your ArchiveFiles task, you need to specify a specific project.
For example:
For func_dev project: $(Build.ArtifactStagingDirectory)/myapp_function/func_dev
- task: ArchiveFiles#2
displayName: "Archive files"
inputs:
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/myapp_function/func_dev'
includeRootFolder: false
archiveFile: '$(Build.ArtifactStagingDirectory)/build$(Build.BuildId)-func_dev.zip'
Then you can only package the project corresponding to the function app name.
If you want to deploy two projects to the corresponding function app in one pipeline at the same time, you could use the same method to separately package the two projects as zip.

Excluding Certain Files in Azure CI Pipeline (YAML)

I have a CI pipeline (YAML) that builds a repo that will deploy into an existing Azure Function. The CI pipeline is doing it is job. However, after it is done, and I go to Function App -> App files -> I can see the azure-pipeline.yml is included in there (or i think it was included in the build process). I have tried using paths and exclude but they dont work. My question is, how do I exclude only that azure-pipeline.yml so that after the pipeline is done building, the azure-pipeline.yml is not in App files in Function App. Below is my YAML
trigger:
branches:
include:
- master
paths:
exclude:
- README.md
- azure-pipelines.yml
variables:
# Azure Resource Manager connection created during pipeline creation
azureSubscription: 'DevOps-Test'
# Function app name
functionAppName: 'test'
# Agent VM image name
vmImageName: 'vs2017-win2016'
# Working Directory
workingDirectory: '$(System.DefaultWorkingDirectory)/'
stages:
- stage: Build
displayName: Build stage
jobs:
- job: Build
displayName: Build
pool:
vmImage: $(vmImageName)
steps:
- powershell: |
if (Test-Path "extensions.csproj") {
dotnet build extensions.csproj --output ./$(workingDirectory)/bin
}
displayName: 'Build extensions'
- task: ArchiveFiles#2
displayName: 'Archive files'
inputs:
rootFolderOrFile: $(workingDirectory)
includeRootFolder: false
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
replaceExistingArchive: true
- publish: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
artifact: drop
- task: DownloadBuildArtifacts#0
inputs:
buildType: 'current'
downloadType: 'single'
artifactName: 'drop'
downloadPath: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip'
- task: AzureFunctionApp#1
displayName: 'Azure functions app deploy'
inputs:
azureSubscription: '$(azureSubscription)'
appType: functionApp
appName: $(functionAppName)
package: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip'
The following syntax means file README.md or azure-pipelines.yml won't trigger the build. It doesn't mean file README.md or azure-pipelines.yml are excluded in the working directory.
trigger:
branches:
include:
- master
paths:
exclude:
- README.md
- azure-pipelines.yml
I've noticed you tried archiving folder $(workingDirectory), and workingDirectory defined in variable which was actually $(System.DefaultWorkingDirectory)/. System.DefaultWorkingDirectory is the local path on the agent where your source code files are downloaded.
Obviously, file README.md and azure-pipelines.yml are in the source code, so they are archived too. You could add a CopyFiles task before ArchiveFiles task to copy files you need from a source folder to a target folder using match patterns, then archive the target folder. For example:
- task: CopyFiles#2
displayName: 'Copy Files to: $(Build.ArtifactStagingDirectory) '
inputs:
SourceFolder: '$(workingDirectory)'
Contents: |
**/*
!*.md
!*.yml
TargetFolder: '$(Build.ArtifactStagingDirectory) '
- task: ArchiveFiles#2
displayName: 'Archive files '
inputs:
rootFolderOrFile: '$(Build.ArtifactStagingDirectory) '
Take a look here
- powershell: |
if (Test-Path "extensions.csproj") {
dotnet build extensions.csproj --output ./$(workingDirectory)/bin
}
displayName: 'Build extensions'
- task: ArchiveFiles#2
displayName: 'Archive files'
inputs:
rootFolderOrFile: $(workingDirectory)
includeRootFolder: false
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
replaceExistingArchive: true
You produce your ouptut here ./$(workingDirectory)/bin but you zipped rootFolderOrFile: $(workingDirectory). Please change it to rootFolderOrFile: $(workingDirectory)/bin.
EDIT
Please add this before calling archive
- script: |
rm README.md
rm azure-pipelines.yml
workingDirectory: $(workingDirectory)
So you will remove them from folder which you later archive.

WARN unable to find package.json for plottable

When running a build for storybook via an Azure devops pipeline I get the above mentioned error.
I've tried to completely remove this package(plottable) from my project but I keep getting this error and it causes my webpack build to get stuck.
This error doesn't occur locally.
My pipeline:
trigger:
batch: true
branches:
include:
- master
stages:
- stage: develop_build_deploy_stage
pool:
name: Default
demands:
- msbuild
- visualstudio
jobs:
- job: develop_build_deploy_job
steps:
- checkout: self
clean: true
persistCredentials: true
- task: NodeTool#0
displayName: Install Node
inputs:
versionSpec: '12.x'
- task: PowerShell#2
displayName: 'Install Dependencies'
inputs:
targetType: 'inline'
script: |
npm install
- task: PowerShell#2
displayName: 'Increment version'
inputs:
targetType: 'inline'
script: |
git checkout master
git pull origin master
git config --global user.email "d#gmail.com"
git config --global user.name "Build Agent"
npm version patch -m "Increment Version [skip ci]" --force
git push
- task: PowerShell#2
displayName: 'Build Project'
inputs:
targetType: 'inline'
script: |
npm run build-storybook
npm run build
- task: CopyFiles#2
displayName: 'Copy storybook-static Files'
inputs:
sourceFolder: '$(Build.SourcesDirectory)/storybook-static'
contents: '**'
targetFolder: '$(Build.ArtifactStagingDirectory)'
- task: PublishBuildArtifacts#1
displayName: 'Publish storybook-static Files to ArtifactStagingDirectory'
inputs:
pathToPublish: '$(Build.ArtifactStagingDirectory)'
artifactName: Storybook
- task: S3Upload#1
displayName: 'Upload storybook-static to S3'
inputs:
awsCredentials: 'my-s3'
regionName: 'us-east-1'
bucketName: 'my-s3-bucket'
sourceFolder: $(Build.ArtifactStagingDirectory)
- task: Npm#1
displayName: 'Publish to Feed'
inputs:
command: 'publish'
publishRegistry: 'useFeed'
publishFeed: '#####'
How would I go about resolving this problem?
I still don't know what caused this to be the case but for some reason the changes I had made on my branch weren't being picked up and an import that I had removed wasn't removed on the branch that was being built on.
So in the end it was trying to import a package which I had removed as a dependency.

Build and publish angular app to Azure app service results in Application Error

I'm battling with getting an angular app to build and then publish to an Azure resource. The Pipeline runs "successfully" but I am getting the ":( Application Error" when accessing the site. If I view wwwroot via Azure Portal -> Advanced Tools I ~~see the entire repo~~ see nothing:
If I look at the directory via CLI - I see the files
The downloaded artifact appears correct:
[EDIT - updated .yml file] Right now, my pipeline yml file is
variables:
System.Debug: true
trigger:
- develop
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool#0
inputs:
versionSpec: '10.x'
displayName: 'Install Node.js'
- script: |
npm install -g #angular/cli
npm install
ng build
displayName: 'npm install and build'
- task: ArchiveFiles#2
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)/dist/question-ui'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip'
replaceExistingArchive: true
- task: PublishBuildArtifacts#1
inputs:
pathtoPublish: '$(Build.ArtifactStagingDirectory)'
artifactName: app
- task: DownloadBuildArtifacts#0
inputs:
buildType: 'current'
downloadType: 'single'
artifactName: 'app'
downloadPath: '$(System.ArtifactsDirectory)'
- task: AzureRmWebAppDeployment#4
inputs:
ConnectionType: 'AzureRM'
azureSubscription: 'qt-question-ui - Azure'
appType: 'webAppLinux'
WebAppName: 'qt-question-ui'
deployToSlotOrASE: true
ResourceGroupName: 'DEV_QTv2'
SlotName: 'production'
packageForLinux: '$(System.ArtifactsDirectory)/app/$(Build.BuildId).zip'
RuntimeStack: 'NODE|10-lts'
I've updated this as I progress, thinking I'm getting closer.

Resources