Azure FunctionApp Dependency Injection Error only if deploying through Azure Devops - c#

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.

Related

Deploy C# MVC app to a specific virtual path without overwriting default site using azure pipelines

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

Azure DevOps dotnet build doesn't have access to nuget packages

In Azure DevOps I have my company nuget repository. I have created some new nuget packages and I included them in my projects. Locally the projects are working fine.
When I run the dotnet build on DevOps there is error because there is an unauthorize access to the nuget repository.
[error]C:\Program Files\dotnet\sdk\3.1.202\NuGet.targets(124,5): Error : Unable to load the service index for source
https://vs.pkgs.visualstudio.com/Vs/_packaging/vs.com/nuget/v3/index.json.
Response status code does not indicate success: 401 (Unauthorized).
C:\Program Files\dotnet\sdk\3.1.202\NuGet.targets(124,5): error :
Unable to load the service index for source
https://vs.pkgs.visualstudio.com/Vs/_packaging/vs.com/nuget/v3/index.json.
[d:\a\1\s\Payments\Payments.csproj]
C:\Program
Files\dotnet\sdk\3.1.202\NuGet.targets(124,5): error : Response
status code does not indicate success: 401 (Unauthorized).
[d:\a\1\s\PiP.Payments.Stripe\PiP.Payments.csproj]
Build FAILED.
C:\Program Files\dotnet\sdk\3.1.202\NuGet.targets(124,5): error :
Unable to load the service index for source
https://vs.pkgs.visualstudio.com/Vs/_packaging/vs.com/nuget/v3/index.json.
[d:\a\1\s\PiP.Payments.Stripe\PiP.Payments.csproj]
C:\Program
Files\dotnet\sdk\3.1.202\NuGet.targets(124,5): error : Response
status code does not indicate success: 401 (Unauthorized).
We have had this error several times before. We were always able to fix it with an extra dotnet restore command before the dotnet build command.
There is a small hint in the documentation here:
https://learn.microsoft.com/en-us/azure/devops/artifacts/nuget/dotnet-exe?view=azure-devops#on-build-machines-and-in-non-interactive-scenarios
In Azure Pipelines, use the .NET Core step's restore command, which automatically handles authentication to Azure Artifacts feeds. Otherwise, use the Azure Artifacts Credential Provider and pass in credentials using the VSS_NUGET_EXTERNAL_FEED_ENDPOINTS environment variable.
Here is an example yaml:
- task: DotNetCoreCLI#2
displayName: 'Restore Packages'
inputs:
command: restore
projects: 'MyCsproj.csproj'
vstsFeed: 'voxspan'
- task: DotNetCoreCLI#2
displayName: 'Build'
inputs:
command: build
projects: 'MyCsproj.csproj'

Displaying NUnit tests code coverage on Azure DevOps

I've setup a new pipeline on Azure DevOps which builds and run the tests of the projects. The tests are written with NUnit.
In the pipeline I'm using the VSTest#2 task to run the unit tests and I add the codeCoverageEnabled to true.
In the end the pipeline runs and when I go in the "Code Coverage" tab of the job, it allows me to download .codecoverage file but it does not display its content in the tab. My understanding was that this should happen.
How can I fix this ?
Thanks
By default, the code coverage for the VSTest Task is output to a .codecoverage file, which Azure DevOps does not know how to interpret and only provides as a downloadable file. You'll need to use a few DotNetCoreCLI tasks and coverlet to be able to display code coverage results on the code coverage tab in azure pipelines.
So, if you are on .NET CORE, There is a way how you can do that.
Step 1
add Coverlet.collector nuget Package in your test project
Step 2
Change your azure-pipelines.yml to include the following for your code coverage:
If you have any settings from a CodeCoverage.runsettings file, you can keep them too
- task: DotNetCoreCLI#2
inputs:
command: 'test'
projects: '**/*.Tests/*.csproj'
arguments: -c $(BuildConfiguration) --collect:"XPlat Code Coverage" -- RunConfiguration.DisableAppDomain=true
testRunTitle: 'Run Test and collect Coverage'
displayName: 'Running tests'
- task: DotNetCoreCLI#2
inputs:
command: custom
custom: tool
arguments: install --tool-path . dotnet-reportgenerator-globaltool
displayName: Install ReportGenerator tool
- script: reportgenerator -reports:$(Agent.TempDirectory)/**/coverage.cobertura.xml -targetdir:$(Build.SourcesDirectory)/coverlet/reports -reporttypes:"Cobertura"
displayName: Create reports
- task: PublishCodeCoverageResults#1
displayName: 'Publish code coverage'
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: $(Build.SourcesDirectory)/coverlet/reports/Cobertura.xml
One other thing to note for the above code is the Report Generator. Depending on which version of .net core you are using it might be required to get a different version of the tool.
More information can also be found on the Microsoft Docs

Azure pipeline not running NUnit tests

Just been introduced to Azure piplelines. My project is a .NET project and is linked up with Azure but does not run my Unit Tests before integrating (therefore is integrating everything even with failing tests)
My .yaml file is:
# ASP.NET Core
# Build and test ASP.NET Core projects targeting .NET Core.
# Add steps that run tests, create a NuGet package, deploy, and more:
# https://learn.microsoft.com/azure/devops/pipelines/languages/dotnet-core
trigger:
- master
pool:
vmImage: 'ubuntu-latest'
variables:
buildConfiguration: 'Release'
steps:
- script: dotnet build --configuration $(buildConfiguration)
displayName: 'dotnet build $(buildConfiguration)'
My unit tests are in the solution under a project called MyProjectTests and in a file called ProjectTests.cs. Can anyone please advise what I need to add to my yaml file (or do in general?) to get these to run please? I have looked into this myself and can't seem to find a solution and I want to avoid clogging up my commit history with failed attempts to run the unit tests.
Thanks so much.
UPDATE:
I have fixed by adding the following:
- task: DotNetCoreCLI#2
inputs:
command: test
projects: '**/*Tests/*.csproj'
arguments: '--configuration $(buildConfiguration)'
Here you go.
- task: DotNetCoreCLI#2
displayName: Test
inputs:
command: test
projects: 'PathToTestProject/TestProject.csproj'
arguments: '--configuration Debug'
You can choose whatever configuration you like, of course. And the displayName is optional. If any of your tests fail, the Pipeline will abort subsequent steps.

How to release and publish downloadable binaries?

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.

Categories

Resources