Как правильно использовать сборку и развертывание функций Azure в Azure DevOps с несколькими проектами.C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Как правильно использовать сборку и развертывание функций Azure в Azure DevOps с несколькими проектами.

Сообщение Anonymous »

Я работаю с Azure и приложением на основе C#. У меня есть 2 службы приложений: веб-приложение и приложение-функция. Мое веб-приложение использует dotnet 9.0, и мое приложение-функция тоже использует dotnet 9.0. Я выбрал триггер таймера с изолированным работником и использовал план, основанный на потреблении. Кроме того, мое веб-приложение имеет 4 слота развертывания: разработка, UAT, промежуточный этап, производство. Приложение «Моя функция» имеет два слота развертывания: разработка, производство.
Я разделил свое веб-приложение на два проекта: веб-приложение и общую библиотеку. Мои миграции, контекст базы данных, модели и функция, на которую можно ссылаться и которая будет выполняться в функции Azure, — все это находится в общей библиотеке. Третий проект — моя функция Azure. Все они хранятся в одном репозитории в Azure DevOps. Когда я запускаю приведенный ниже сценарий конвейера, все работает отлично и проходит. Однако похоже, что конвейер неправильно создает или развертывает функцию Azure.
Когда я загружаю консоль Kudu, я вижу, что заархивированная папка загружается в каталог ~/wwwroot. Однако имя этой заархивированной папки — это заархивированный проект веб-приложения, а не заархивированный проект функции Azure. Как я могу это исправить? Мой azure-pipelines.yml приведен ниже.
Изменить: обновлен .yml до фактической используемой версии.

Код: Выделить всё

trigger:
branches:
include:
- development-cs
- main
- uat

variables:
buildConfiguration: 'Release'
azureSubscription: 'RandomAzureConnection'        # Name of your Azure Service Connection
appName: 'RandomWebApp'                             # Name of your Azure Web App
functionAppName: 'RandomFunctionApp'                # Name of your Azure Function App
resourceGroupName: 'Random_ResourceGroup'           # Name of your Resource Group
sqlServerName: 'randomsqlserver.database.windows.net'  # Azure SQL Server FQDN
runtimeStack: 'DOTNETCORE|9.0'
ResourceGroupLocation: 'East US'

# Database names
devSqlDatabaseName: 'randomdevdb'
uatSqlDatabaseName: 'randomuatdb'
mainSqlDatabaseName: 'RandomMainDB'

# Deployment Slots for Web App
devSlotName: 'devSlot'
uatSlotName: 'uatSlot'
stagingSlotName: 'stagingSlot'
productionSlotName: 'productionSlot'

stages:
- stage: BuildAndDeploy
displayName: 'Build and Deploy Stage'
jobs:

- job: Build
displayName: 'Build Job'
pool:
vmImage: 'ubuntu-latest'
steps:
# Checkout code and set up environment
- 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'

# Restore and Build all projects
- 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 the Web App package
- task: DotNetCoreCLI@2
displayName: 'Publish Web App'
inputs:
command: 'publish'
projects: 'RandomApp/WebApp.csproj'
arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/web --no-restore'

# Publish the Function App package into its own folder
- task: DotNetCoreCLI@2
displayName: 'Publish Function App'
inputs:
command: 'publish'
projects: 'RandomApp/RandomFunctions.csproj'
arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/functions --no-restore'

# Archive the Function App folder into a zip file
- task: ArchiveFiles@2
displayName: 'Archive Function App Package'
inputs:
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/functions'
includeRootFolder: false
archiveFile: '$(Build.ArtifactStagingDirectory)/functionapp.zip'
replaceExistingArchive: true

# (Optional) Cleanup the unzipped Function App folder so only the zip remains
- script: |
echo "Cleaning up unzipped Function App folder..."
rm -rf "$(Build.ArtifactStagingDirectory)/functions"
displayName: 'Cleanup Function App Folder'

# (Optional) Generate EF Core migration SQL script
- script: |
echo "Generating EF Core migration script..."
dotnet ef migrations script --idempotent \
--project "RandomApp/RandomShared.csproj" \
--startup-project "RandomApp/WebApp.csproj"  \
--output $(Build.ArtifactStagingDirectory)/migration.sql
displayName: 'Generate EF Core Migration Script'

# List files for debugging purposes
- script: |
echo "Listing contents of the Artifact Staging Directory:"
ls -la "$(Build.ArtifactStagingDirectory)"
displayName: 'List Artifact Files'

# Publish build artifacts (both the web folder and the Function App zip)
- task: PublishBuildArtifacts@1
displayName: 'Publish Build Artifacts'
inputs:
# Change the path to publish both the web folder and the functionapp.zip file
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

# Install required tools in the Deploy Job
- 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 slot and database variables 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)"
echo "##vso[task.setvariable variable=functionSlot]''"
elif [ "$branchName" == "uat" ]; then
echo "##vso[task.setvariable variable=slotName]$(uatSlotName)"
echo "##vso[task.setvariable variable=sqlDatabaseName]$(uatSqlDatabaseName)"
echo "##vso[task.setvariable variable=functionSlot]none"
elif [ "$branchName" == "development-cs" ]; then
echo "##vso[task.setvariable variable=slotName]$(devSlotName)"
echo "##vso[task.setvariable variable=sqlDatabaseName]$(devSqlDatabaseName)"
echo "##vso[task.setvariable variable=functionSlot]development"
else
echo "##vso[task.setvariable variable=slotName]$(devSlotName)"
echo "##vso[task.setvariable variable=sqlDatabaseName]$(devSqlDatabaseName)"
echo "##vso[task.setvariable variable=functionSlot]development"
fi
echo "Branch: $branchName"
echo "Web App Slot Name: $(slotName)"
echo "SQL Server Name: $(sqlServerName)"
echo "SQL Database Name: $(sqlDatabaseName)"
echo "Function App Slot: $(functionSlot)"
displayName: 'Set Web App Slot, Function App Slot, and DB Based on Branch'

# Apply EF Core migrations for main and uat branches only
- script: |
echo "Applying EF Core Migrations using Service Principal..."
dotnet ef database update \
--project "RandomApp/RandomShared.csproj" \
--startup-project "RandomApp/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'))

# Deploy the Web App package to Azure App Service
- task: AzureWebApp@1
displayName: 'Deploy to Azure Web App'
inputs:
azureSubscription: '$(azureSubscription)'
appName: '$(appName)'
# Adjust the package path if your web app requires a zip package or folder.
package: '$(Pipeline.Workspace)/drop/web'
appType: 'webApp'
slotName: '$(slotName)'

# Update Web App settings using Azure CLI
- 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="randomdomain.com" \
AzureAd__TenantId="$(tenantId)" \
AzureAd__ClientId="$(clientId)" \
AzureAd__ClientSecret="$(clientSecret)"

# Update Function App settings (only for main and development-cs branches)
- task: AzureCLI@2
displayName: 'Update Function App Settings'
condition: or(eq(variables['Build.SourceBranchName'], 'main'), eq(variables['Build.SourceBranchName'], 'development-cs'))
inputs:
azureSubscription: '$(azureSubscription)'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
if [ "$(functionSlot)" = "development" ]; then
echo "Updating Function App settings for development slot (RandomFunctionApp/development)..."
az functionapp config appsettings set \
--name "$(functionAppName)" \
--resource-group "$(resourceGroupName)" \
--slot "development" \
--settings MyDbConnectionString="Server=tcp:$(sqlServerName),1433;Initial Catalog=$(sqlDatabaseName);Authentication=Active Directory Managed Identity;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
else
echo "Updating Function App settings for production Function App (RandomFunctionApp)..."
az functionapp config appsettings set \
--name "$(functionAppName)" \
--resource-group "$(resourceGroupName)" \
--settings MyDbConnectionString="Server=tcp:$(sqlServerName),1433;Initial Catalog=$(sqlDatabaseName);Authentication=Active Directory Managed Identity;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
fi

# Deploy the Function App package (only for main and development-cs branches)
- task: AzureFunctionApp@2
displayName: 'Deploy Function App to Azure'
condition: or(eq(variables['Build.SourceBranchName'], 'main'), eq(variables['Build.SourceBranchName'], 'development-cs'))
inputs:
connectedServiceNameARM: 'RandomAzureConnection'
appType: 'functionApp'
appName: '$(functionAppName)'
deployToSlotOrASE: true
resourceGroupName: '$(resourceGroupName)'
slotName: 'development'
package: '$(Pipeline.Workspace)/drop/functionapp.zip'
deploymentMethod: 'zipDeploy'

Я попробовал приведенный выше сценарий. Кроме того, я попытался использовать функцию публикации в сообществе VS, и она сработала отлично. Никаких проблем вообще. Похоже, что проблемы возникают только при попытке использовать CI/CD с DevOps.
Изменить: я также заметил, что веб-приложение будет публиковаться в функции Azure. служба приложений, и моя служба приложений веб-приложений больше не будет публиковаться и отображать страницу с сообщением о том, что она готова к развертыванию.

Подробнее здесь: https://stackoverflow.com/questions/793 ... th-multipl
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»