I had an application that was on .NET 5 and was hooked up to an Azure DevOps pipeline that built and deployed fine. The relevant parts are:
- task: PublishBuildArtifacts#1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
- task: AzureRmWebAppDeployment#4
inputs:
ConnectionType: 'AzureRM'
azureSubscription: 'mySub'
appType: 'webAppLinux'
WebAppName: 'myApp'
packageForLinux: '$(Build.ArtifactStagingDirectory)/s.zip'
RuntimeStack: 'DOTNETCORE|5.0'
I when I moved to .NET 6 I recreated the project from scratch and ported the code over including the .yaml file, but when the pipeline runs, when it gets to the Deployment step it says it can't find 'D:\a\1\a\s.zip'. When i wildcard it it says more than 1 zip file exists.
- task: AzureRmWebAppDeployment#4
inputs:
ConnectionType: 'AzureRM'
azureSubscription: 'mySub'
appType: 'webAppLinux'
WebAppName: 'myApp'
packageForLinux: '$(Build.ArtifactStagingDirectory)/*.zip'
RuntimeStack: 'DOTNETCORE|6.0'
TLDR: How can I determine what the Publish step output as the zip file?
There can be three approaches.
Use artifactName while publishing the artifact, that way the artifacts would be published with your desired name.
Reference https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/utility/publish-build-artifacts?view=azure-devops
ArtifactName: Specify the name of the artifact that you want to create. It can be whatever you want.
Default value: drop
Use a bash task to list the content of the directory.
- bash: ls $(Build.ArtifactStagingDirectory)
displayName: "List the content of staging directory"
Once the artifact is published and your pipeline run is completed, navigate to Summary to explore or download your artifact.
Reference: https://learn.microsoft.com/en-us/azure/devops/pipelines/artifacts/build-artifacts?view=azure-devops&tabs=yaml#download-artifacts
Related
I have a dotnet6 project which I want to deploy on a AppService in Azure.
I am using Auzre Devops for my CICD and there I'm using a Yaml file for build and later deployment.
I have also some WebJobs that I want to deploy on the same AppService in the same slot.
The build process of my solution will provide a zip file with some files:
1- zip file
2- Parameters.xml
3- SetParameters.xml
4- readme.txt
5- and a deploy.cmd file which is a Batch file
This is the task for building a solution:
- task: VSBuild#1
inputs:
solution: 'Mydea/Mydea.sln'
msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:DesktopBuildPackageLocation="$(build.artifactstagingdirectory)\yourProject.zip" /p:DeployIisAppPath="Default Web Site"'
platform: '$(BuildPlatform)'
configuration: '$(BuildConfiguration)'
clean: true
Later in CD I use another command to deploy my zip file into the Azure like this:
- task: AzureRmWebAppDeployment#4
displayName: 'Deploy WebApp'
inputs:
ConnectionType: 'AzureRM'
azureSubscription: 'xxxx'
appType: 'webApp'
WebAppName: 'xxx'
deployToSlotOrASE: true
ResourceGroupName: 'xxxx'
SlotName: 'Test'
packageForLinux: '$(pipeline.workspace)/drop/WebApp.zip'
JSONFiles: '**/appsettings.json'
until here is everything fine.
But if I want to deploy some WebJob, it is different. I will not have a zip file with some batch, the only thing that I need here is a zip file which directing to the correct path:
App_Data/jobs/triggered/yourproject
later in the CD you need to call the same task in order to deploy your Webjobs.
Problem:
I can create 2 seperate zip file in the same artifact and later in CD, I need to call the deploy task. But the deploy task only can get one zip file.
If you calling the deploy task 2 times it will override it. that means you can have only your project deployed or your webjobs.
My idea was to combine the two zip files in the CI like this:
- task: VSBuild#1
inputs:
solution: 'xxx/xxx.sln'
msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:DesktopBuildPackageLocation="$(build.artifactstagingdirectory)\WebApp.zip" /p:DeployIisAppPath="Default Web Site"'
platform: '$(BuildPlatform)'
configuration: '$(BuildConfiguration)'
clean: true
- task: ExtractFiles#1
inputs:
archiveFilePatterns: '$(build.artifactstagingdirectory)\WebApp.zip'
destinationFolder: '$(Build.BinariesDirectory)/root'
cleanDestinationFolder: true
overwriteExistingFiles: true
- task: DotNetCoreCLI#2
displayName: 'publish Webjob Daily'
inputs:
command: 'publish'
publishWebProjects: false
projects: 'xxx/xxx.Webjob.Daily/xxx.Webjob.Daily.csproj'
arguments: '--output $(Build.BinariesDirectory)/root/App_Data/jobs/triggered/WebjobDaily'
zipAfterPublish: false
modifyOutputPath: false
- task: ArchiveFiles#2
displayName: 'Zip solution'
inputs:
rootFolderOrFile: '$(Build.BinariesDirectory)/root'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/WebApp.zip'
replaceExistingArchive: true
- task: PublishPipelineArtifact#1
displayName: Publish drop Artifact
inputs:
targetPath: '$(Build.ArtifactStagingDirectory)'
artifact: 'drop'
publishLocation: 'pipeline'
As you can see in this tasks, I combine the 2 zip files into one zip file.
notice that the zip file for the main solution has also some extra files with one batch file.
I tried to deploy this zip file in CD, the main project was successfully deployed but not the WebJobs.
If I deploy only the main project or only the WebJobs, it will be successfully done. but I need to deploy both of them togehter.
Now for me the last way is to create for my project another slot in the AppService. and deploy the main project on one Slot and the WebJobs on the other and this will work.
But this is not a clean solution.
I like to have them both in the same Slot.
I wouldn't combine the two artifacts into the same zip file. Reason being is how will platform know to split the zip file once it's extracted?
Doing a CI pipeline that builds the artifacts is certainly plausible, but why not have two different CD's that are triggered by the CI pipeline. Each separate CD will pull their respective artifact. Going this route does two things;
Doesn't overly complicate the CD pipeline with additional logic to handle two different artifacts, thereby keeping things clean and separated, and
If you ever decided to run your WebJob on a different app service (plan), you can easily change the deployment target.
I found the solution.
In the deployment you should have two separate zip files one for your WebApp and the other for your WebJobs, exactly like the code in my question.
In the deployment you should call the AzureRmWebAppDeployment#4 task two times, first for your WebApp and after that for your WebJobs.
But...
in order that the second task doesn't override the first task you should alter 2 other parameters; enableCustomDeployment to true and ExcludeFilesFromAppDataFlag to false.
- task: AzureRmWebAppDeployment#4
displayName: 'Deploy WebApp'
inputs:
ConnectionType: 'AzureRM'
azureSubscription: 'xxx'
appType: 'webApp'
WebAppName: 'xxx'
deployToSlotOrASE: true
ResourceGroupName: 'xxx'
SlotName: 'Test'
packageForLinux: '$(pipeline.workspace)/drop/WebApp.zip'
JSONFiles: '**/appsettings.json'
- task: AzureRmWebAppDeployment#4
displayName: 'Deploy Webjobs'
inputs:
ConnectionType: 'AzureRM'
azureSubscription: 'xxx'
appType: 'webApp'
WebAppName: 'xxx'
deployToSlotOrASE: true
ResourceGroupName: 'xxx'
SlotName: 'Test'
packageForLinux: '$(pipeline.workspace)/drop/Webjobs.zip'
JSONFiles: '**/appsettings.json'
enableCustomDeployment: true
ExcludeFilesFromAppDataFlag: false
I am trying to publish a Blazor net core app using Azure Pipelines, but I constantly get a 500 error on the Web Deployment stage.
Once the pipeline runs I check through Kudu console and the only two files on the server are an empty web.config and FAILED TO INITIALIZE RUN FROM PACKAGE.txt with Run From Package Initialization failed. inside.
Below is the YAML of the pipeline.
pool:
name: Azure Pipelines
#Your build pipeline references an undefined variable named ‘Parameters.RestoreBuildProjects’. Create or edit the build pipeline for this YAML file, define the variable on the Variables tab. See https://go.microsoft.com/fwlink/?linkid=865972
#Your build pipeline references the ‘BuildConfiguration’ variable, which you’ve selected to be settable at queue time. Create or edit the build pipeline for this YAML file, define the variable on the Variables tab, and then select the option to make it settable at queue time. See https://go.microsoft.com/fwlink/?linkid=865971
steps:
- task: DotNetCoreCLI#2
displayName: Restore
inputs:
command: restore
projects: '$(Parameters.RestoreBuildProjects)'
feedsToUse: config
nugetConfigPath: NuGet.Config
- task: DotNetCoreCLI#2
displayName: Publish
inputs:
command: publish
publishWebProjects: false
projects: '**/TPL/Server/TPL.Server.csproj'
arguments: '--configuration $(BuildConfiguration) --output $(build.artifactstagingdirectory)'
modifyOutputPath: false
- task: AzureRmWebAppDeployment#4
displayName: 'Azure App Service Deploy: tpl'
inputs:
azureSubscription: '**hidden**'
WebAppName: tpl
deployToSlotOrASE: true
ResourceGroupName: TPL
SlotName: test
packageForLinux: '$(build.artifactstagingdirectory)/**/*.zip'
Deleting and recreating the slot fixed this. I previously had old way CI (from portal's deployment center menu) and my hunch is that didn't get disconnected properly or something like that didn't get cleaned up.
I have the following three steps to publish a function app to artifact in Azure Pipeline:
- task: DotNetCoreCLI#2
displayName: 'dotnet publish function app'
inputs:
command: publish
arguments: '--configuration Release --output updater_publish_output'
projects: 'Service/XYZ/Hosts.FA/*.csproj'
publishWebProjects: false
modifyOutputPath: false
zipAfterPublish: false
- task: ArchiveFiles#2
displayName: 'archive function app files'
inputs:
rootFolderOrFile: "$(System.DefaultWorkingDirectory)/updater_publish_output"
includeRootFolder: false
archiveFile: "$(System.DefaultWorkingDirectory)/Hosts.FA.zip"
- task: PublishBuildArtifacts#1
displayName: 'publish function app files'
inputs:
PathtoPublish: '$(System.DefaultWorkingDirectory)/Hosts.FA.zip'
ArtifactName: '$(Build.BuildNumber)'
Here is the project structure:
I have updated the first step to:
- name: dotnet publish function app
run: dotnet publish Service/XYZ/Hosts.FA/Hosts.FA.csproj --configuration Release --output updater_publish_output
How do I convert the tasks ArchiveFiles#2 & PublishBuildArtifacts#1 to GitHub Actions?
Use the Upload-Artifact task from here: https://github.com/actions/upload-artifact. It will replace both ArchiveFiles#2 (zipping) and PublishBuildArtifacts#1 (uploading).
- uses: actions/upload-artifact#v2
with:
name: ${{github.run_number}}
path: |
updater_publish_output
As per https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context github.run_number is
A unique number for each run of a particular workflow in a repository. This number begins at 1 for the workflow's first run, and increments with each new run. This number does not change if you re-run the workflow run.
You could also use github.run_id:
A unique number for each run within a repository. This number does not change if you re-run the workflow run.
I would like to create pipeline which deploy Java Azure Function. The pipeline Job says successful (1 artifact produced.100% tests passed. 13 files uploaded) but I cannot see Functions deployed in Azure Portal.
Please advice me. I'm following tutorial as base, but I'm using Git Repo of Azure DevOps instead of GitHub. https://learn.microsoft.com/en-us/azure/devops/pipelines/ecosystems/java-function?view=azure-devops
My Visual Code project (unzipped) is located on git /MyProject/FunctionsJava/
Pom.xml is located (unzipped) /MyProject/FunctionsJava/pom.xml
My yml is followings:
trigger:
- master
pool:
vmImage: 'ubuntu-latest'
# at the top of your YAML file
# set some variables that you'll need when you deploy
variables:
# the name of the service connection that you created above
serviceConnectionToAzure: connection-to-TestRG-rg
# the name of your web app here is the same one you used above
# when you created the web app using the Azure CLI
appName: JavaFuncApp
# ...
steps:
# ...
# add these as the last steps
# to deploy to your app service
- task: CopyFiles#2
displayName: Copy Files
inputs:
SourceFolder: $(system.defaultworkingdirectory)/MyProject/FunctionsJava/
Contents: '**'
TargetFolder: $(build.artifactstagingdirectory)
- task: Maven#3
inputs:
mavenPomFile: '$(System.DefaultWorkingDirectory)/MyProject/FunctionsJava/pom.xml'
mavenOptions: '-Xmx3072m'
javaHomeOption: 'JDKVersion'
jdkVersionOption: '1.8'
jdkArchitectureOption: 'x64'
publishJUnitResults: true
testResultsFiles: '**/surefire-reports/TEST-*.xml'
goals: 'package'
- task: PublishBuildArtifacts#1
displayName: Publish Artifact
inputs:
PathtoPublish: $(build.artifactstagingdirectory)
- task: AzureWebApp#1
inputs:
azureSubscription: 'TestRG-Conn'
appType: 'webApp'
appName: '$(appName)'
package: $(build.artifactstagingdirectory)
deploymentMethod: 'auto'
The problem should be caused by appType: 'webApp' in the AzureWebApp task, appType should be functionApp. Web app is deployed to app service.
You can try Azure Function App deploy task or Azure App Service deploy task.
- task: AzureFunctionApp#1
displayName: Azure Function App deploy
inputs:
azureSubscription: $(serviceConnectionToAzure)
appType: functionApp
appName: $(appName)
package: $(build.artifactstagingdirectory)
We have a working classic build job in azure Devops with an self hosted agent pool. But when we tried to convert this build job to yaml method, while executing no agents are getting assigned and its hanging. Could you please correct me here if i am doing something task.
Error
"All eligible agents are disabled or offline"
below is the converted yaml file from classic build - agent job
pool:
name: MYpool
demands: maven
#Your build pipeline references an undefined variable named ‘Parameters.mavenPOMFile’. Create or edit the build pipeline for this YAML file, define the variable on the Variables tab. See https://go.microsoft.com/fwlink/?linkid=865972
steps:
- task: Maven#3
displayName: 'Maven pom.xml'
inputs:
mavenPomFile: '$(Parameters.mavenPOMFile)'
- task: CopyFiles#2
displayName: 'Copy Files to: $(build.artifactstagingdirectory)'
inputs:
SourceFolder: '$(system.defaultworkingdirectory)'
Contents: '**/*.war'
TargetFolder: '$(build.artifactstagingdirectory)'
condition: succeededOrFailed()
- task: PublishBuildArtifacts#1
displayName: 'Publish Artifact: Root'
inputs:
PathtoPublish: '$(build.artifactstagingdirectory)'
ArtifactName: Root
condition: succeededOrFailed()
- task: CopyFiles#2
displayName: 'Copy wars to build directory'
inputs:
SourceFolder: '$(build.artifactstagingdirectory)/target'
TargetFolder: '/home/myadmin/builds/$(build.buildnumber)'
- task: CopyFiles#2
displayName: 'copying docker file to Build Directory'
inputs:
SourceFolder: Admin
TargetFolder: '/home/myadmin/builds/$(build.buildnumber)'
- bash: |
# Write your commands here
mv /home/myadmin/builds/$(build.buildnumber)/mypack0.0.1.war /home/myadmin/builds/$(build.buildnumber)/ROOT.war
displayName: 'Name war file Root.war'
- task: Docker#2
displayName: 'Build the docker image'
inputs:
repository: 'mycontainerregistry.azurecr.io/myservice'
command: build
Dockerfile: '/home/myadmin/builds/$(build.buildnumber)/Dockerfile'
tags: '$(Build.BuildNumber)-DEV'
- bash: |
# Write your commands here
docker login mycontainerregistry.azurecr.io
docker push mycontainerregistry.azurecr.io/myservice:$(Build.BuildNumber)-DEV
displayName: 'Push Docker Image'
- task: CopyFiles#2
displayName: 'Copy Deployment file'
inputs:
SourceFolder: /home/myadmin/kubernetes
TargetFolder: '/home/myadmin/builds/$(build.buildnumber)'
- task: qetza.replacetokens.replacetokens-task.replacetokens#3
displayName: 'Replace image in deployment file'
inputs:
rootDirectory: '/home/myadmin/builds/$(build.buildnumber)'
targetFiles: '**/*.yml'
In my previous answer, I said when I wait for nearly 20-30 mins, the interface of agent will prompt below message.
In fact, this is a process which upgrade the agent to latest version automatically.
Yes, when you using YAML with private agent, the agent version must be the latest one. No matter you add the demands or not.
For our system, the agent version is a implicit demand that your agent must satisfied with the latest one when you applying it in YAML.
If it is not satisfied, it will be blocked and the agent upgrade process will be forced to be performed automatically by system after some times.
So, to execute the private agent in YAML successfully, please upgrade the agent to latest one manually.
Since what my colleague and I talked are all private to microsoft in this ticket, sorry you could not get visible on this summary. So, here I take the screenshots about it, and you can refer to it: https://imgur.com/a/4OnzHp3
We are still working on why the system prompting so confusing message like: All eligible agents are disabled or offline. And, am trying to do some contribution to let this message more clear, for example: no agents meet demands: agent version xxx.