How do I configure Azure DevOps to publish binaries in a web downloadable form, and automatically update my readme.md or wiki page to reflect the latest released artifacts?
I know how to build release pipelines for artifacts I publish to Azure, e.g. I can publish webapps and functions.
But I can't figure out how to publish and release dowloadable content.
I'd like the result to be similar to GitHub releases, where my users can browse releases, and click and download the files.
I'd like the project page (readme.md or wiki) to automatically be updated with the release data, similar to how I would create a build state link.
If you want to upload the artifacts to your shared path. I recommend that you could add the script task to upload the released artifacts to the shared path or ftp server.
For example, if azure storage is acceptable, then you could publish your build artifacts to the Azure storage with following scripts
$source = "build file"
$azureStorageKey = "xxxxx"
$storage_context = New-AzureStorageContext -StorageAccountName "yourstorageAccount" -StorageAccountKey "$azureStorageKey"
Set-AzureStorageBlobContent -Context $storage_context -Container "containerName" -File $source -Blob "drop.zip" -Force
I'd like the project page (readme.md or wiki) to automatically be updated with the release data, similar to how I would create a build state link.
Yes, you could to do that with Azure pipeline build state badge. You could copy the markdown link into your readme file
Update :
I do a demo upload the build to azure storage with following YAML file.
queue:
name: Hosted VS2017
demands:
- msbuild
- visualstudio
- azureps
steps:
- task: NuGetCommand#2
displayName: 'NuGet restore'
- task: VSBuild#1
displayName: 'Build solution **\*.sln'
- task: CopyFiles#2
displayName: 'Copy Files'
inputs:
SourceFolder: '$(build.sourcesdirectory)'
TargetFolder: '$(build.artifactstagingdirectory)'
- task: PublishBuildArtifacts#1
displayName: 'Publish Artifact: drop'
- task: ArchiveFiles#2
displayName: 'Archive $(Build.ArtifactStagingDirectory)'
inputs:
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)'
- task: AzureFileCopy#1
displayName: 'AzureBlob File Copy'
inputs:
SourcePath: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip'
azureSubscription: xxxxx
Destination: AzureBlob
storage: $(storageAccountName)
ContainerName: $(containerName)
UI design:
what I'd like is for the page to have a download link that points to the latest build that passed.
We could use AzureBlob File Copy task to copy the build easily to the Azure blob storage.
If Azure function is possible, you could use the blob trigger to create your customized page with your script.
Related
When I deploy my function app with the command
func azure functionapp publish '<name>' --dotnet it successfully packages my code and publishes it to the function app, and everything works.
I'm now working on building out automation pipelines, and I created a pipeline with the following stages
- stage: Build
displayName: Build stage
jobs:
- job: Build
displayName: Build
pool:
vmImage: $(vmImageName)
steps:
- task: UseDotNet#2
displayName: 'Use .NET 6 Core sdk'
inputs:
packageType: 'sdk'
version: '6.0.402'
- task: DotNetCoreCLI#2
displayName: Build
inputs:
command: 'build'
projects: |
$(workingDirectory)/*.csproj
arguments: --output $(System.DefaultWorkingDirectory)/publish_output --configuration Release
- task: ArchiveFiles#2
displayName: 'Archive files'
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)/publish_output'
includeRootFolder: false
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
replaceExistingArchive: true
- publish: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
artifact: drop
which packages the app and
- stage: Deploy
displayName: Deploy stage
dependsOn: Build
condition: succeeded()
jobs:
- deployment: Deploy
displayName: Deploy
environment: 'development'
pool:
vmImage: $(vmImageName)
strategy:
runOnce:
deploy:
steps:
- task: AzureFunctionApp#1
displayName: 'Azure functions app deploy'
inputs:
azureSubscription: $(azureSubscription)
appType: functionApp
appName: $(functionAppName)
slotName: $(slotName)
package: '$(Pipeline.Workspace)/drop/$(Build.BuildId).zip'
- task: AzureAppServiceManage#0
inputs:
azureSubscription: $(azureSubscription)
Action: 'Swap Slots'
WebAppName: $(functionAppName)
ResourceGroupName: 'group-name'
SourceSlot: $(slotName)
SwapWithProduction: true
It builds perfectly fine and then it also deploys and swaps the function app slots without any error.
The issue is that after it does this, everything is broken when making requests the function endpoints. I either get 404 errors saying my function endpoints don't exist, or I get 500 dependency injection errors. To escape this chaos I locally run func azure functionapp publish '<name>' --dotnet again on the exact same code that was deployed through the pipeline and then everything works fine.
I also tried deploying straight to the production slot instead of swapping, and the result is the same through the pipeline.
I am using the exact same version of dotnet locally as I am in the pipeline. Without any good errors to help me understand why it says it deployed without issue but everything is broken, it's hard for me to figure out what's going on.
Does anyone have any idea what's going on?
Here is the dependency Injection error:
System.InvalidOperationException : Unable to resolve service for type
'Api.Request.Services.User' while attempting to activate
'Api.Request.Functions.Create'.at
Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider
sp,Type type,Type requiredBy,Boolean isDefaultParameterRequired)at
lambda_method331(Closure ,IServiceProvider ,Object[] )at
Microsoft.Azure.WebJobs.Host.Executors.DefaultJobActivator.CreateInstance[T](IServiceProvider
serviceProvider) at
C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultJobActivator.cs
: 42at
Microsoft.Azure.WebJobs.Host.Executors.DefaultJobActivator.CreateInstance[T](IFunctionInstanceEx
functionInstance) at
C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultJobActivator.cs
: 31at
Microsoft.Azure.WebJobs.Host.Executors.ActivatorInstanceFactory1.<>c__DisplayClass1_1.<.ctor>b__0(IFunctionInstanceEx i) at C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\ActivatorInstanceFactory.cs : 20at Microsoft.Azure.WebJobs.Host.Executors.ActivatorInstanceFactory1.Create(IFunctionInstanceEx
functionInstance) at
C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\ActivatorInstanceFactory.cs
: 26at
Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`2.CreateInstance(IFunctionInstanceEx
functionInstance) at
C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionInvoker.cs
: 44at
Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ParameterHelper.Initialize()
at
C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs
: 791at async
Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.TryExecuteAsync(IFunctionInstance
functionInstance,CancellationToken cancellationToken) at
C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs
: 104
but I am including it in Startup.cs
services.AddScoped<Services.User>();
Also, I am using in-process function apps, could that be why everything is breaking in the pipeline? I just don't get why it works perfect if I use the func command and doesn't work at all when I use the function azure provides in the pipeline. Isn't this all MS, so shouldn't the underlying publish mechanisms be the same?
EDIT
One thing I've just found is that the files in /home/wwwroot are different when deploying through the pipeline and through the func azure functionapp command. When deploying through the pipeline it has a lot more files in it. I'm wondering if it's building the project incorrectly..
The issue was that I had thought I was building/zipping and deploying my code correctly, but it wasn't being packaged the same way that it was locally.
Using Kudu to view the deployed files showed me that everything was being placed in the /home/wwwroot directory instead of having most of the built files being placed in the /bin directory. This explained why I was getting the unexpected behavior. After I altered my build script, I was able to get it to properly build and deploy my code changes.
I'm trying to deploy a c# MVC app to windows server running IIS where I have deployed another app as default site but this app which I want to build and deploy is only to a specific virtual folder
so for build steps I have used below steps :
paths:
exclude:
- gitignore
pool:
name: 'Hosted Windows 2019 with VS2019'
variables:
SolutionPath: '**/*.sln'
buildConfiguration: 'Release'
buildPlatform: 'Any CPU'
stages:
- stage: Build
displayName: Build app
jobs:
- job: Build
workspace:
clean: all
displayName: Build app
steps:
- task: NuGetToolInstaller#1
- task: NuGetCommand#2
inputs:
restoreSolution: '$(SolutionPath)'
- task: VSBuild#1
displayName: 'Build solution'
inputs:
solution: '$(SolutionPath)'
msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=FileSystem /p:PackageAsSingleFile=false /p:SkipInvalidConfigurations=true /p:PackageLocation="$(Build.stagingdirectory)"'
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
- task: PublishBuildArtifacts#1
inputs:
PathtoPublish: $(Build.artifactstagingdirectory)
ArtifactName: 'drop' ```
As you can see I have set the msbuildArgs specially /p:WebPublishMethod=FileSystem to drop the files under virtual specific path.
as a outcome the build artifacts are coming out as a long path,not sure if I am missing something in terms of setting any argument for path to publish-
\drop\Archive\Content\D_C\a\1\s\temp\obj\Release\Package\PackageTmp\<app files>
Now in release pipeline I have used below IIS web app deploy task
[![Release pipeline][1]][1]
[1]: https://i.stack.imgur.com/Dkp7m.png
can someone explain me how do I should build it a specific virtual path so I can deploy it without interfering the default site
My solution(.sln) contains contains 21 projects and the nuget restore takes a lot of time(4m and 56s).
I am trying to cache the nuget packages for faster restore.
I've successfully cached the /.nuget/packages and it caches correctly but when the build runs it tries to access the project.assets.json for every project in solution and I get the following error:
error NETSDK1004: Assets file 'd:\a\1\s\src\Project\obj\project.assets.json' not found. Run a NuGet package restore to generate this file. [d:\a\1\s\src\Project\Project.csproj]
I've found from the Microsoft community support forums that I need to cache also the project.assets.json for every project... But how? The cache task doesn't support wildcards to recursively search through each project's project.assets.json.
Another solution would be to write 21 cache tasks with the exact path for each project, but this doesn't look right... maybe I'm doing something wrong?
I really appreciate any help you can provide!
Thanks!
EDIT here is my auzre-pipelines.yml:
trigger: none
pool:
vmImage: 'windows-latest'
variables:
solution: '**/*.sln'
buildPlatform: 'Any CPU'
configuration: Release
NUGET_PACKAGES: $(Pipeline.Workspace)/.nuget/packages
CACHE_RESTORED: 'false'
- task: UseGitVersion#5
displayName: 'Install GitVersion5'
inputs:
versionSpec: '5.x'
additionalArguments: '/output buildserver -config .\GitVersion.yml'
- task: NuGetToolInstaller#1
displayName: 'Install NuGet 5.3.x'
inputs:
versionSpec: '5.3.x'
- task: Cache#2
inputs:
key: 'v1 | nuget | "$(Agent.OS)"'
path: $(NUGET_PACKAGES)
cacheHitVar: CACHE_RESTORED
- task: NuGetCommand#2
inputs:
command: 'restore'
condition: ne(variables.CACHE_RESTORED, 'true')
restoreSolution: '**/*.sln'
feedsToUse: 'select'
vstsFeed: 'a-dummy-feed'
- task: VSBuild#1
inputs:
solution: '**\*.sln'
msbuildArgs: '/t:Restore'
platform: 'any cpu'
configuration: 'Release'
clean: true
logProjectEvents: false
- task: NuGetCommand#2
displayName: 'Generate .nupkg'
inputs:
command: 'pack'
packagesToPack: '**/*.csproj'
configuration: '$(configuration)'
versioningScheme: 'byEnvVar'
versionEnvVar: 'UseGitVersion.GitVersion.NuGetVersion
- task: NuGetCommand#2
displayName: 'Push .nupkg to AzureArtifacts Feed'
inputs:
command: 'push'
packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg'
nuGetFeedType: 'internal'
publishVstsFeed: 'a-dummy-feed'
publishPackageMetadata: false
allowPackageConflicts: true
According to the error message, the project.assets.json file doesn’t exist in the path.
You could try to add the /t:Restore in the MSBuild Arguments.
Then the project.assets.json file will be automatically added during the build process.
Hope this helps.
I ran into a similar problem showing the same error message. The root cause in my case was that not all the projects in my solution were set up to generate a packages.lock.json file.
It was in the projects where the packages.lock.json file was not present that dotnet build was complaining of not being able to find the project.assets.json file.
The solution to my problem was to enable the generation of a nuget lock file across all projects in my solution. Here's what I did, step by step.
Placed a Directory.Build.props file at the root folder for my solution, containing this:
<Project>
<PropertyGroup>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
</PropertyGroup>
</Project>
Cleaned my solution and rebuilt it to generate all the individual packages.lock.json files. If you try this but files are not generated for some projects, try closing Visual Studio and re-opening it before rebuilding.
Added the Build.Directory.props file and all packages.lock.json files to git and committed them.
PS - I have a slightly different key in my cache task inputs:
key: 'nuget | "$(Agent.OS)" | **/packages.lock.json,!**/bin/**'
This makes the task generate a cache for every project in my solution.
- job: buildAndTestJob
steps:
- task: DotNetCoreCLI#2
displayName: dotnet restore
inputs:
command: restore
vstsFeed: $(vstsFeed)
- task: DotNetCoreCLI#2
displayName: 'dotnet build'
inputs:
arguments: '--configuration ${{ parameters.buildConfiguration }}'
- task: DotNetCoreCLI#2
displayName: 'dotnet test'
inputs:
command: test
arguments: '--configuration ${{ parameters.buildConfiguration }}'
- task: CopyFiles#2
displayName: copy bin files
inputs:
sourceFolder: '$(Build.SourcesDirectory)'
contents: '**/bin/**/*'
TargetFolder: '$(Build.ArtifactStagingDirectory)'
- task: CopyFiles#2
displayName: copy obj files
inputs:
sourceFolder: '$(Build.SourcesDirectory)'
contents: '**/obj/**/*'
TargetFolder: '$(Build.ArtifactStagingDirectory)'
- task: PublishBuildArtifacts#1
displayName: publish build artifacts
inputs:
pathtoPublish: '$(Build.ArtifactStagingDirectory)'
artifactName: buildeffect
publishLocation: 'Container'
-job: packAndPushJob
steps:
- task: DownloadBuildArtifacts#0
displayName: download build artifacts
inputs:
buildType: 'current'
downloadType: 'single'
artifactName: 'buildeffect'
downloadPath: '$(Build.ArtifactStagingDirectory)'
- task: CopyFiles#2
displayName: copy files to source directory
inputs:
sourceFolder: '$(Build.ArtifactStagingDirectory)/buildeffect'
contents: '**/*'
TargetFolder: '$(Build.SourcesDirectory)'
allowPackageConflicts: true
- task: DotNetCoreCLI#2
displayName: 'dotnet pack'
inputs:
arguments: '--no-restore'
nobuild: true
command: pack
projects: '$(Build.SourcesDirectory)'
publishWebProjects: true
publishVstsFeed: $(vstsFeed)
includeNuGetOrg: true
- task: NuGetCommand#2
displayName: 'nuGet push'
inputs:
command: push
projects: '$(Build.SourcesDirectory)'
publishVstsFeed: $(vstsFeed)
allowPackageConflicts: true
I have 2 jobs. First, to restore, test, build and share build files in a build artifact. Second to pack and push nuget packages. First job finished their job with success, but second job failed during pack task. It have a problem with nuget packages, for example:
/usr/share/dotnet/sdk/3.0.100/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(234,5): error NETSDK1064: Package Microsoft.CSharp, version 4.6.0 was not found. It might have been deleted since NuGet restore. Otherwise, NuGet restore might have only partially completed, which might have been due to maximum path length restrictions. [/home/vsts/work/1/s/src/Spotio.Leads.Client/Spotio.Leads.Client.csproj]
So, maybe should we share builded project in another way? Or maybe add some parameters with feeds to restore? I don't have any idea, so please, if you have any suggestions, help us :)
How can I share a built .NET Core project between many jobs in Azure
pipelines?
1.See this : Projects using the PackageReference format always use packages directly from this folder(%userprofile%\.nuget\packages).
2.Project that targets .net core uses PackageReference format, so the restored packages are stored in %userprofile%\.nuget\packages in first agent.
3.For your second agent job, devops actually start another hosted agent to run your tasks. It means for second agent, it doesn't have the referenced packages in %userprofile%\.nuget\packages.
4.Something we should know is that: Though we've copied all files of bin and obj to second agent, dotnet pack xx.csproj will still try to confirm the referenced packages exist, then the issue occurs.
So I suggest you can add a dotnet restore task before that dotnet pack task in second agent job to make sure the missing packages can be found in second agent.
Note:
1.In one build pipeline with two agent jobs, though these two agent jobs all use hosted agent, these two agent is not the same instance.
2.Make sure the configuration you use to build is the same configuration you use to pack.
Hope it helps. If i misunderstand anything, feel free to let me know :)
I am Building C# Application using Visual Studio Build In Azure Pipeline.
My solution Contains multiple project (ManagerWeb & WebAPI).
I want to Publish Two Separate Artifact ManagerWeb & WebAPI respectively.
All the required File's are present in Build.ArtifactStagingDirectory.
How I can specify a pattern using which I can get Two Separate Artifact ?
Example All the File name with WebAPI in 1st Artifact & ManagerWeb in another.
The File name from ArtifactStaging Directory are as Below
Something.Manager.WebAPI.deploy.cmd
Something.Manager.WebAPI.deploy-readme.txt
Something.Manager.WebAPI.SetParameters.xml
Something.Manager.WebAPI.SourceManifest.xml
Something.Manager.WebAPI.zip
Something.ManagerWeb.deploy.cmd
Something.ManagerWeb.deploy-readme.txt
Something.ManagerWeb.SetParameters.xml
Something.ManagerWeb.SourceManifest.xml
Something.ManagerWeb.zip
Any Help will be appreciable.
Thanks in Advance.
Add two Copy Files steps which copy;
ManagerWeb files to $(Build.ArtifactStagingDirectory)\ManagerWeb
WebAPI files to $(Build.ArtifactStagingDirectory)\WebAPI
Then have two Publish Artifact steps to;
Publish $(Build.ArtifactStagingDirectory)\ManagerWeb as ManagerWeb
Publish $(Build.ArtifactStagingDirectory)\WebAPI as WebAPI
I've mocked this up and exported the YAML as follows;
pool:
name: Hosted VS2017
steps:
- task: CopyFiles#2
displayName: 'Copy Files to: $(Build.ArtifactStagingDirectory)\ManagerWeb'
inputs:
SourceFolder: 'your/path/here/ManagerWeb'
TargetFolder: '$(Build.ArtifactStagingDirectory)\ManagerWeb'
- task: CopyFiles#2
displayName: 'Copy Files to: $(Build.ArtifactStagingDirectory)\WebAPI'
inputs:
SourceFolder: 'your/path/here/WebAPI'
TargetFolder: '$(Build.ArtifactStagingDirectory)\WebAPI'
- task: PublishBuildArtifacts#1
displayName: 'Publish Artifact: ManagerWeb'
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)\ManagerWeb'
- task: PublishBuildArtifacts#1
displayName: 'Publish Artifact: WebAPI'
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)\WebAPI'
Add a PowerShell task to create two folders and move the files to there:
cd $(Build.ArtifactStagingDirectory)
$files = dir
mkdir WebAPI
mkdir ManagerWeb
ForEach($file in $files)
{
if($file.FullName.Contains("WebAPI"))
{
mv $file.FullName -Destination WebAPI
}
else
{
mv $file.FullName -Destination ManagerWeb
}
}
Then in the "Path to publish" field add the folders:
For WebApi artifacts:
$(Build.ArtifactStagingDirectory)/WebAPI
And for ManagerWeb artifacts:
$(Build.ArtifactStagingDirectory)/ManagerWeb