Azure Devops - How to prevent artifacts from being deleted after every agent phase? - azure-devops

I have a release pipeline that is specifically for running automated tests, that has multiple agent phases.
Most of the phases require use of the same artifacts in the same location on the build machine.
If I had an artifact set for download on a previous agent phase like so....
I used to be able to use that artifact again in subsequent agent phases, without downloading it again.
Now it appears to wipe the artifact folder contents when moving into a new agent phase. So if I have the following that follows the above....
The folder is wiped and the tasks that depend on that artifact existing fail.
Is there any way to prevent the build agent artifact folder from being deleted after an agent phase has finished and a new one starts?

Since phases can run in parallel and can go from one agent to another and since it's unknown what job will be next on that agent, the jobs clean up once they finish.
The trick is to end each phase with a "Publish Pipeline Artifact" task and then download that artifact in the next phase.

Related

Download only artifacts I need in release pipeline and run tasks conditionnally

I have created a release pipeline that has multiple artifacts to be downloaded from multiple repositories.
Now, when I want to start the release I want to introduce a condition so that when the condition is met I download only the artifact I need and then run the task to deploy it otherwise when there is no condition all of the artifacts are downloaded thus all tasks are run.
How can I achieve that with azure DevOps ?
For conditions, I tried to look into
but for downloading only an artifact from multiple one I can't unless I specify a release pipeline for every project I have.
By default, build artifacts are downloaded to the agent. You can configure an option in the stage to skip the download of artifacts. https://learn.microsoft.com/en-us/azure/devops/pipelines/release/artifacts?view=azure-devops#artifact-sources---azure-pipelines
And use "Download Pipeline Artifact" task to specify your target Artifact. Set "Custom condition" within this task: https://learn.microsoft.com/en-us/azure/devops/pipelines/process/conditions?view=azure-devops&tabs=classic
You can customize this behavior by forcing a stage to run by specifying a custom condition.

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

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.

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.

Release is triggered even though build does not publish artifact

Last week, our team decided to move all separate .NET projects into a single solution. Because we were already using Azure DevOps with separate build pipelines for each project, we looked into the possibility to only trigger builds whenever there are changes to a specific project. This, to prevent the build agents from rebuilding the entire solution on every commit.
Because our source repository is a locally hosted Git one, we do not have the niceties of using path filters, so we resorted to using a Powershell task to determine if all upcoming tasks should be skipped, using a custom condition (explained in this SO question).
Now, on every commit, all builds are triggered, but the builds resolve for themselves if they should continue to build and (more importantly) if they should publish a build artifact at the end. An example of such a skipped build is below:
However, every time such a build 'succeeds', a new artifact is created, even though the publish artifact task is skipped. The problem is that all our release pipelines are triggered when a build pipeline creates an artifact. So every time a build is skipped like shown above, the release pipeline triggers and tries to deploy the artifact. But it fails, because the artifact it uses to deploy does not really exist (it seems like it is empty, and the build pipeline actually doesn't mention an artifact on the Summary tab), so any operations on the artifact fail in the release pipeline.
Our release pipelines are set to trigger on source type build artifact, for the corresponding build pipeline, with the default version parameter set to latest.
How is it possible that, even though the publish artifact task is skipped, the release pipeline still triggers and tries to deploy an empty artifact?
I assuming you enable the Continues Delivery in the Releases pipelines, this option is not related to build artifacts. this option means that Release will be triggered when the build succeeded (not matter if he has artifacts or no).
So this is the reason why after each build a new release started.
As workaround, you can add a task in the build that add "build tag" only when there is a artifacts, and in the release artifacts options, instead of choose Latest you can choose Latest from the build pipeline default branch with tags and specify the tag you put in the build.
Another option is in the "Stages" click on the triggers and then it's configured to "After release" so enable the "Artifact filters" and specify there the build tag.
How do you add a build tag? add a PowerShell task with this command:
Write-Host "##vso[build.addbuildtag]test-tag"

Share Single Downloaded Artifact for multiple deployment stage in Release

Using Azure Devops.
During Build Process artifact get published
During Release it get downloaded. Now I have multiple stage and each stage has different no of steps.
Now when Stage get change it download artifact again.
Also within stage there are different no of deployment task and some of them download it again.
I want to make it such a process so possibly single stage can download artifact only once.
I want if there is already such task present.
You can't. Each phase has to download the artifacts that it needs to use for one very simple reason:
They can run on different agents. Each agent definitely has a different working folder. Some agents may be on totally different machines. Some agents may be a totally different operating system. The release has no way of anticipating any of that.
There is no guarantee that Stage A-Phase 1 and Stage A-Phase 2 and Stage B will run on the same agent. They can run in parallel on different agents, or they can run sequentially on different agents. Or they can all run sequentially on the same agent.
Thus, if a phase needs an artifact, it has to download it.
If a given phase doesn't need certain artifacts, you can configure which artifacts it will download by clicking on the phase and unchecking the artifacts that are unnecessary.