我正在使用 Azure 和基于 C# 的应用程序。我有 2 个应用程序服务、一个 Web 应用程序和一个函数应用程序。我的网络应用程序使用 dotnet 9.0,我的函数应用程序也使用 dotnet 9.0。我选择了带有隔离工作人员的计时器触发器,并使用了基于消耗的计划。此外,我的 Web 应用程序有 4 个部署槽:开发、uat、登台、生产。我的 Function 应用程序有 2 个部署槽:开发、生产。
我将我的 Web 应用程序分成 2 个项目,一个 Web 应用程序和一个共享库。我的迁移、dbcontext、模型以及在 Azure Function 中引用和运行的函数都在共享库中。第三个项目是我的 Azure 函数。所有这些都存储在 Azure DevOps 中的单个存储库中。当我运行下面的管道脚本时,一切正常并通过。但是,管道似乎无法正确构建或部署 Azure 函数。
当我加载 Kudu 控制台时,我看到压缩文件夹已上传到 ~/wwwroot 目录。但是,此压缩文件夹的名称是压缩的 webapp 项目,而不是压缩的 azure function 项目。我该如何解决这个问题?我的 azure-pipelines.yml 如下。
trigger:
branches:
include:
- development-cs
- main
- uat
variables:
buildConfiguration: 'Release'
azureSubscription: 'MyAzureServiceConnection' # Name of your Azure Service Connection
appName: 'MyWebApp' # Name of your Azure Web App
resourceGroupName: 'MyResourceGroup' # Name of your Resource Group
sqlServerName: 'myserver.database.windows.net' # Azure SQL Server FQDN
runtimeStack: 'DOTNETCORE|9.0'
ResourceGroupLocation: 'East US'
# Database names
devSqlDatabaseName: 'mydevdatabase'
uatSqlDatabaseName: 'myuatdatabase'
mainSqlDatabaseName: 'mymaindatabase'
# Deployment Slots for Web App
devSlotName: 'development'
uatSlotName: 'uat'
stagingSlotName: 'staging'
productionSlotName: 'production'
stages:
- stage: BuildAndDeploy
displayName: 'Build and Deploy Stage'
jobs:
- job: Build
displayName: 'Build Job'
pool:
vmImage: 'ubuntu-latest'
steps:
- checkout: self
fetchDepth: 0
persistCredentials: true
clean: true
- script: |
echo "Build Sources Directory: $(Build.SourcesDirectory)"
displayName: 'Print Build Sources Directory'
- script: |
echo '{ "sdk": { "version": "9.0.100" } }' > global.json
displayName: 'Create global.json'
- task: UseDotNet@2
displayName: 'Install .NET 9.0.100 SDK in Build Job'
inputs:
packageType: 'sdk'
version: '9.0.100'
- script: |
echo "Installing necessary tools..."
sudo apt-get update
sudo apt-get install -y azure-cli powershell
displayName: 'Install Azure CLI and PowerShell'
- script: |
echo "Installing dotnet-ef tool..."
dotnet tool install --global dotnet-ef --version 9.0.0-preview.6.24327.4
echo '##vso[task.prependpath]$HOME/.dotnet/tools'
displayName: 'Install dotnet-ef Tool in Build Job'
- task: DotNetCoreCLI@2
displayName: 'Restore NuGet Packages'
inputs:
command: 'restore'
projects: '**/*.csproj'
- task: DotNetCoreCLI@2
displayName: 'Build Projects'
inputs:
command: 'build'
projects: '**/*.csproj'
arguments: '--configuration $(buildConfiguration) --no-restore'
# Publish Web App package
- task: DotNetCoreCLI@2
displayName: 'Publish Web App'
inputs:
command: 'publish'
projects: 'MyProject.WebApp/MyProject.WebApp.csproj'
arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/web --no-restore'
# (Optional) Generate EF Core migration SQL script
- script: |
echo "Generating EF Core migration script..."
dotnet ef migrations script --idempotent \
--project "MyProject.Shared/MyProject.Shared.csproj" \
--startup-project "MyProject.WebApp/MyProject.WebApp.csproj" \
--output $(Build.ArtifactStagingDirectory)/migration.sql
displayName: 'Generate EF Core Migration Script'
- task: PublishBuildArtifacts@1
displayName: 'Publish Build Artifacts'
inputs:
pathToPublish: '$(Build.ArtifactStagingDirectory)'
artifactName: 'drop'
publishLocation: 'Container'
- job: Deploy
displayName: 'Deploy Job'
dependsOn: Build
pool:
vmImage: 'ubuntu-latest'
steps:
- checkout: self
fetchDepth: 0
persistCredentials: true
clean: true
- download: current
artifact: drop
- task: UseDotNet@2
displayName: 'Install .NET 9.0.100 SDK in Deploy Job'
inputs:
packageType: 'sdk'
version: '9.0.100'
- script: |
echo "Installing Azure CLI..."
sudo apt-get update
sudo apt-get install -y azure-cli
displayName: 'Install Azure CLI'
- script: |
echo "Installing dotnet-ef tool..."
dotnet tool install --global dotnet-ef --version 9.0.0-preview.6.24327.4
echo '##vso[task.prependpath]$HOME/.dotnet/tools'
displayName: 'Install dotnet-ef Tool in Deploy Job'
- script: |
echo "Verifying dotnet-ef installation..."
dotnet ef --version
displayName: 'Verify dotnet-ef Installation in Deploy Job'
- script: |
echo "Testing connectivity to SQL Server..."
sudo apt-get install -y netcat
nc -zv $(sqlServerName) 1433
displayName: 'Test SQL Server Connectivity'
# Set Web App slot and SQL database name based on branch
- script: |
branchName=$(Build.SourceBranchName)
if [ "$branchName" == "main" ]; then
echo "##vso[task.setvariable variable=slotName]$(stagingSlotName)"
echo "##vso[task.setvariable variable=sqlDatabaseName]$(mainSqlDatabaseName)"
elif [ "$branchName" == "uat" ]; then
echo "##vso[task.setvariable variable=slotName]$(uatSlotName)"
echo "##vso[task.setvariable variable=sqlDatabaseName]$(uatSqlDatabaseName)"
elif [ "$branchName" == "development-cs" ]; then
echo "##vso[task.setvariable variable=slotName]$(devSlotName)"
echo "##vso[task.setvariable variable=sqlDatabaseName]$(devSqlDatabaseName)"
else
echo "##vso[task.setvariable variable=slotName]$(devSlotName)"
echo "##vso[task.setvariable variable=sqlDatabaseName]$(devSqlDatabaseName)"
fi
echo "Branch: $branchName"
echo "Web App Slot Name: $(slotName)"
echo "SQL Server Name: $(sqlServerName)"
echo "SQL Database Name: $(sqlDatabaseName)"
displayName: 'Set Web App Slot and DB Based on Branch'
# Apply EF Core migrations (only for main and uat branches)
- script: |
echo "Applying EF Core Migrations using Service Principal..."
dotnet ef database update \
--project "MyProject.Shared/MyProject.Shared.csproj" \
--startup-project "MyProject.WebApp/MyProject.WebApp.csproj" \
--connection "Server=tcp:$(sqlServerName),1433;Database=$(sqlDatabaseName);Authentication=Active Directory Service Principal;User ID=$(sqlClientId);Password=$(sqlClientSecret);Encrypt=True;TrustServerCertificate=False;MultipleActiveResultSets=True;Connection Timeout=30;"
displayName: 'Apply EF Core Migrations'
condition: or(eq(variables['Build.SourceBranchName'], 'main'), eq(variables['Build.SourceBranchName'], 'uat'))
- task: AzureWebApp@1
displayName: 'Deploy to Azure Web App'
inputs:
azureSubscription: '$(azureSubscription)'
appName: '$(appName)'
package: '$(Pipeline.Workspace)/drop/web/**/*.zip'
appType: 'webApp'
slotName: '$(slotName)'
- task: AzureCLI@2
displayName: 'Update Web App Settings'
inputs:
azureSubscription: '$(azureSubscription)'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
echo "Updating Web App settings..."
az webapp config appsettings set \
--name "$(appName)" \
--resource-group "$(resourceGroupName)" \
--slot "$(slotName)" \
--settings ConnectionStrings__DefaultConnection="Server=tcp:$(sqlServerName),1433;Initial Catalog=$(sqlDatabaseName);Authentication=Active Directory Managed Identity;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" \
AzureAd__Instance="https://login.microsoftonline.com/" \
AzureAd__Domain="mydomain.com" \
AzureAd__TenantId="$(tenantId)" \
AzureAd__ClientId="$(clientId)" \
AzureAd__ClientSecret="$(clientSecret)"
上面的脚本是我尝试过的。此外,我尝试使用 VS Community 中的发布功能,效果非常好。完全没有问题。似乎只有在尝试将 CI/CD 与 DevOps 结合使用时才会出现问题。
编辑:我还注意到Web应用程序将在azure功能应用程序服务中发布,并且我的Web应用程序应用程序服务将不再发布并显示一个页面,表示它已准备好部署到。
您的 Web 应用程序和函数应用程序是单独的 Azure 资源。他们可以共享相同的应用程序服务计划,但在过去,我通常将它们分开以管理自己的扩展和成本。
提供的管道只是为 Web 应用程序创建可部署的工件并部署它。
dotnet publish
任务仅为单个项目创建输出。
要包含您的函数应用程序,请在与 Web 应用程序不同的文件夹中创建适当的可发布工件:
# Publish Function App package
- task: DotNetCoreCLI@2
displayName: 'Publish Function App'
inputs:
command: 'publish'
projects: 'MyProject.WebApp/MyProject.FunctionApp.csproj'
arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/functionapp --no-restore'
AzureFunctionApp@2
- task: AzureFunctionApp@2
inputs:
azureSubscription: '$(azureSubscription)'
appName: 'MyFunctionApp'
package: '$(Pipeline.Workspace)/drop/functionapp/**/*.zip'
appType: 'functionApp' # or 'functionAppLinux'
slotName: '$(functionAppslotName)'