The $(Build.ArtifactStagingDirectory) variable's value changes when deploying a build in Azure DevOps Pipelines - azure-devops

I have a DACPAC deployment task which is failing, because for some reason the value of the $(Build.ArtifactStagingDirectory) pipeline variable is changing between the build pipeline and the release pipeline. In the build pipeline, the variable is set to C:\agent\_work\2\a, but in the release pipeline it's C:\agent\_work\r2\a. This is causing the release pipeline to fail when it tries to deploy the DACPAC artifact, because the folder it's looking in is empty; the folder where the artifact actually is is ignored. How do I make these variables consistent between the build and release pipelines so that the artifact is retrieved from the same folder it's generated in? These variables appear to be built in, so I don't see any way to change them. I could always hardcode a path, but that seems a bit kludgy...

In releases you have System.ArtifactsDirectory which is
The directory to which artifacts are downloaded during deployment of a release. The directory is cleared before every deployment if it requires artifacts to be downloaded to the agent. Same as Agent.ReleaseDirectory and System.DefaultWorkingDirectory.
Example: C:\agent_work\r1\a
and in pipelines/builds Build.ArtifactStagingDirectory
The local path on the agent where any artifacts are copied to before being pushed to their destination. For example: c:\agent_work\1\a
A typical way to use this folder is to publish your build artifacts with the Copy files and Publish build artifacts tasks.
Note: Build.ArtifactStagingDirectory and Build.StagingDirectory are interchangeable. This directory is purged before each new build, so you don't have to clean it up yourself.
See Artifacts in Azure Pipelines.
This variable is agent-scoped, and can be used as an environment variable in a script and as a parameter in a build task, but not as part of the build number or as a version control tag.
This is in line with your experience. And you cannot change it, as they are predefined. But can you clarify why this is a problem for you?

In the release pipeline, you can't directly access the files in the build pipeline, not only because the working directory is different, but also because they do not use the same agent. You need to download the artifacts first, and then use them in the release pipeline.
You can use the following ways to download artifacts:
Use the Download Build Artifacts task.
Go to the edit release pipeline page -> Select Add artifact -> Select Build -> Fill in the information related to the build pipeline (Notice the value of Source alias)-> Add it. You will find your artifacts are downloaded in $(System.ArtifactsDirectory)/${Source alias}
For more information about consuming artifacts in release pipelines, you can click this document.

Oh, I think I figured it out. Each release pipeline stage has an option called "Artifact download" which lets you specify which artifacts out of all those linked in the pipeline are actually used by that stage. I needed to check the appropriate checkboxes there in order to use the artifacts in the stage's tasks.

Related

Azure pipeline yml: publish or file copy?

At the end of my pipeline I want to copy the bin directly to a network share from which it can be used to deploy.
I see there are two possible task typed that could do this:
copy files that makes a task: CopyPublishBuildArtifacts#1; or
_ copy and publish build artefacts_ that makes a CopyPublishBuildArtifacts#1.
And this publish is different to dotnet publish?
Which one should I pick and why?
They appear to have identical parameters.
What is the # for?
Azure pipeline yml: publish or file copy?
The task CopyPublishBuildArtifacts is deprecated. If you're using Team Foundation Server 2017 or newer, we recommend that you use Pipeline Artifacts.
And if you want to know the different between publishbuildartifacts vs publishpipelineartifact, you could check below thread for the details:
What is the difference between Build Artifact and Pipeline Artifact tasks?
And this publish is different to dotnet publish?
The answer is yes. The dotnet publish task is to serve the specific project. Its function is similar to that we choose the Publish option for net core project in Visual Studio.
But we could specify the folder or files to publish for the publishbuildartifacts or publishpipelineartifact task.
Which one should I pick and why?
We recommend to use the publishpipelineartifact task if you just want to copy the bin directly to a network share.
You could check the reason from here:
For build artifacts, it's common to copy files to $(Build.ArtifactStagingDirectory) and then use the Publish Build Artifacts task to publish this folder. With the Publish Pipeline Artifact task, you can just publish directly from the path containing the files.
By default, the Download Pipeline Artifact task downloads files to $(Pipeline.Workspace). This is the default and recommended path for all types of artifacts.
File matching patterns for the Download Build Artifacts task are expected to start with (or match) the artifact name, regardless if a specific artifact was specified or not. In the Download Pipeline Artifact task, patterns should not include the artifact name when an artifact name has already been specified. For more information, see single artifact selection.
What is the # for?
The role of # is to specify the version of the task. For example, #1 is to use the version 1.0 of the task.

.NET Core WebJob Console App CI/CD using Azure DevOps Pipelines

I'm trying to build my console application through Azure DevOps. So to this I'm following this tutorial.
The follow images, are from what I already did.
Build Solution Pipeline
Build Solution Pipeline / Publish
Build Solution Pipeline / Artifact
Deploy WebJob Pipeline
Deploy WebJob Pipeline / Variables
When I run the Build Solution the zip seems to work, because I see it.
But when I run the Deploy WebJob Pipeline I get ##[error]D:\a\1\s\***.zip not found.. I tried wwwroot/App_Data/jobs/, but still the same error.
What could I be doing wrong? What's the right way to set the zippedArtifactPath?
You're following the tutorial incorrectly. The tutorial is telling you to create a release. You're using a build pipeline to try to release. Although you can do that, you shouldn't.
You have two options:
If you want to keep using the visual designer, use a release. Look at the "Release" tab for this. Releases can be tied to build artifacts and will handle downloading the build artifact automatically.
If you want to use YAML, refer to the YAML documentation and set up a multi-stage pipeline to release.
What could I be doing wrong?
Check your error messgae ##[error]D:\a\1\s\***.zip not found we can find in the second build pipeline, the PS tried to get the xx.zip in xxx\s folder while in first build pipeline you published the xx.zip to xxx\a folder.
The $(System.DefaultWorkingDirectory) for build pipeline is xx\s folder while that for release pipeline is xx\a folder. In first build pipeline we published the xx.zip to Build.ArtifactStagingDirectory which is a xx\a folder, so we can't access the xx.zip from xx\s folder in second build pipeline's PS script.
What's the right way to set the zippedArtifactPath?
It's not recommended to build and deploy one web app using two build pipelines. For normal logic, we should do this by using combination like build+release pipeline just like the Toturial and Daniel suggests above.
We can use this variable $(Release.PrimaryArtifactSourceAlias) to get the artifact directory.
In your powerShell script you can set path variable like:
$path = "$(System.DefaultWorkingDirectory)\$(Release.PrimaryArtifactSourceAlias)\webjobs_drop\[ZIP_File_Name].zip"
[your build artifact name]\webjobs_drop[your zipped files].zip
"your build artifact name" - you should get it from your release pipelines Artifacts stage from where you are selecting your build artifacts

Where are the artifacts after having built, to be used by release?

I'm new to Aure DevOps. Trying to create build and release pipelines there's one thing I don't understand:
Commonly, every kind of build finally results in some output, called artifacts.
With Azure DevOps it seems like there is always a final copy or publish task necessary to copy the created artifact from A to B, so the release task may then access the compiled artifacts.
Why aren't these artifacts plain accessible to a release pipeline right from the location where they have been built? Why don't the build tasks automatically set a variable pointing to the right folder, so the release pipeline may access the files right from there?
Or is this already happening and I'm just missing something from the tutorials I watched?
There are so many reasons.
Two easy ones:
There is no guarantee that the agent's working folder still contains the files. Agents are reused from build to build and release to release, and a given build or release will always use the same working folder. The working folder is cleaned up between builds.
Releases may run on different agents. On different machines. In different domains. Or any combination. There's no guarantee that the agent where the build ran is accessible by the agent where the release is running. Publishing the artifact allows a guarantee: As long as the machine the release is running on has the ability to talk to Azure DevOps (which is a requirement for the agent to function in the first place), it can get the artifacts it needs.
Why aren't these artifacts plain accessible to a release pipeline
right from the location where they have been built?
Agree with Daniel.
The main reason for me is because we can't hold the hosted agent all the time. Since MS wants to protect resources efficiently, it is not occupied for a long time.
When we queue a build, MS will assign us a brand new clean agent to execute our task, and after the build is complete, the MS will reclaim the agent assigned to our build and restore the agent to its initial state in preparation for accepting the assignment of the next task.
So, we could not keep hold the hosted agent to use it in next release pipeline. We have to store the artifacts in the cloud/server, then we could download it in the release pipeline. Otherwise, we could not get the artifact we need from an agent that has been restored.
Besides, MS is randomly assigned to the agent, and we cannot guarantee that the same agent will be allocated and built during the release pipeline.
That is the main reason why we need to copy or publish the artifacts.
If you do not want to copy or publish the artifacts, you could setup your own private agent, and do not clean the agent before you execute the release pipeline.
Update:
why is the user, well, bothered to find a place for the artifacts
manually? I would have expected every build pipeline to come with a
personal space to store the latest build artifacts. A space where
Azure DevOps automatically copies the build artifacts to. To me it
looks like things have to be manually copied from A to B and then
later from B to C.
That because not all output is needed, for example, the test project, what we need is test result/Code coverage for the test project, not the output for the solution. In this case, we do not need to copy the output to the artifacts. On the other hand, we need to copy some special files to artfacts, then automatically copy the build artifacts will not meet your requirements.
That is also the reason why we provide the task to copy files to artifacts, so that we could customize our personality needs.
Of course, if you think that manual copying is superfluous, you can use the MSBuild parameter /p:output=$(build.artifactstagingdirectory) to set the output directly to artifacts.
If I need to copy things from A to B in the Build pipeline, then what
should keep me from copying it to C right away? Then a separate
Release pipeline would be, well, rather optional, if not redundant.
If you are in the build pipeline, there is another task Download build artifacts, which could download the build artifacts.
if you are in the release pipeline, you just need select the build artifacts as source, release pipeline will download that artifact automatically:
Check this document for some more details.
Hope this helps.

Is there a way in an ADO Build Pipeline to only build one of the artifacts?

I have an ADO build pipeline that builds three artifacts. However, while I am developing, I only want one of the artifacts to be built since that is the artifact on which I am working and it takes longer for all of them to build and I don't want to wait. Can I disable the other artifacts from building?
As I know, you could not use UI to disable some of artifacts which build from one build pipeline. Because we does not provide this feature in VSTS now.
But as workaround, you can use Copy File task in your release to achieve this.
Specify the artifact what you want to work with in release pipeline, and copy it from File A(the source file where these build artifacts is) to File B(any file you want). And then, you can do other thing with this specific build.
Hope this could help -)

Unique Need - Perform Team Services releases using artifacts created in an external build

I have a unique need where I need to perform releases from Team Services using a Release Pipeline and artifacts that have been created in a previous external build. I have the artifacts that were created, dacpacs and websites ect.
I would like to deploy these items using the features in release Pipelines but artifact sources only come from a build or some other version control.
My approach (hack) was to use a build to copy the external files and publish them into the artifact container for the build. I could then use the release pipelines to do my releases. But .. Build copy tasks only seem to work with paths into a repo.
My fall back will be to use the release pipeline and powershell to do the releases with these externally created artifacts. I would sure like to avoid this since there is nice capability in the release pipeline tasks.
This is a compliance requirement my firm has which results in the rather crazy post.
Any help would really be appreciated.
You can use Copy Files task and Publish Build Artifacts task for your build definition.
Copy Files task
Source Folder: you can specify the folder which has your external build artifacts. Such as C:\project\a.
Contents: you can use wildcards to specify which files to copy. Such as **\*.dll, this will copy all *.dll files in C:\project\a and it’s subfilder.
Target Folder: where you want to copy these files. Usually it’s $(build.artifactstagingdirectory).
Publish Build Artifacts task
Path to Publish: set as the same with Target folder in Copy files task. Such as $(build.artifactstagingdirectory).
Note: Copy files task will find the source folder in the machine where the private agent is located.