dotnet-ado-unique
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesedotnet-ado-unique
dotnet-ado-unique
Azure DevOps-exclusive features not available in GitHub Actions: Environments with approvals and gates (pre-deployment checks, business hours restrictions), deployment groups vs environments (when to use each), service connections (Azure Resource Manager, Docker Registry, NuGet), classic release pipelines (legacy migration guidance to YAML), variable groups and library (linked to Azure Key Vault), pipeline decorators for organization-wide policy, and Azure Artifacts universal packages.
Version assumptions: Azure DevOps Services (cloud). YAML pipelines with multi-stage support. Classic release pipelines for legacy migration context only.
Scope boundary: This skill owns ADO-exclusive platform features that have no direct GitHub Actions equivalent. Composable YAML pipeline patterns (templates, triggers, multi-stage) are in [skill:dotnet-ado-patterns]. Build/test pipeline configuration is in [skill:dotnet-ado-build-test]. Publishing pipelines are in [skill:dotnet-ado-publish]. Starter CI templates are owned by [skill:dotnet-add-ci].
Out of scope: Composable pipeline patterns (templates, triggers) -- see [skill:dotnet-ado-patterns]. Build/test pipeline configuration -- see [skill:dotnet-ado-build-test]. Publishing pipelines -- see [skill:dotnet-ado-publish]. Starter CI templates -- see [skill:dotnet-add-ci]. GitHub Actions equivalents -- see [skill:dotnet-gha-patterns], [skill:dotnet-gha-build-test], [skill:dotnet-gha-publish], [skill:dotnet-gha-deploy]. CLI release pipelines -- see [skill:dotnet-cli-release-pipeline].
Cross-references: [skill:dotnet-add-ci] for starter CI templates, [skill:dotnet-cli-release-pipeline] for CLI-specific release automation.
GitHub Actions中没有的Azure DevOps专属功能:带审批与闸门的环境(部署前检查、营业时间限制)、部署组与环境的对比(各自适用场景)、服务连接(Azure Resource Manager、Docker Registry、NuGet)、经典发布管道(向YAML迁移的指南)、与Azure Key Vault关联的变量组和库、用于组织级策略的管道装饰器,以及Azure Artifacts通用包。
版本说明:Azure DevOps Services(云端版本)。支持多阶段的YAML管道。经典发布管道仅用于遗留系统迁移场景。
范围界定:本技能涵盖无直接GitHub Actions等效功能的ADO专属平台特性。可组合的YAML管道模式(模板、触发器、多阶段)属于[skill:dotnet-ado-patterns]。构建/测试管道配置属于[skill:dotnet-ado-build-test]。发布管道属于[skill:dotnet-ado-publish]。入门级CI模板由[skill:dotnet-add-ci]负责。
超出范围:可组合管道模式(模板、触发器)——详见[skill:dotnet-ado-patterns]。构建/测试管道配置——详见[skill:dotnet-ado-build-test]。发布管道——详见[skill:dotnet-ado-publish]。入门级CI模板——详见[skill:dotnet-add-ci]。GitHub Actions等效功能——详见[skill:dotnet-gha-patterns]、[skill:dotnet-gha-build-test]、[skill:dotnet-gha-publish]、[skill:dotnet-gha-deploy]。CLI发布管道——详见[skill:dotnet-cli-release-pipeline]。
交叉引用:入门级CI模板详见[skill:dotnet-add-ci],CLI专属发布自动化详见[skill:dotnet-cli-release-pipeline]。
Environments with Approvals and Gates
带审批与闸门的环境
Defining Environments in YAML
在YAML中定义环境
Environments are first-class Azure DevOps resources that provide deployment targeting, approval gates, and deployment history:
yaml
stages:
- stage: DeployStaging
jobs:
- deployment: DeployToStaging
pool:
vmImage: 'ubuntu-latest'
environment: 'staging'
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: app
- script: echo "Deploying to staging"
- stage: DeployProduction
dependsOn: DeployStaging
jobs:
- deployment: DeployToProduction
pool:
vmImage: 'ubuntu-latest'
environment: 'production'
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: app
- script: echo "Deploying to production"Environments are created automatically on first reference. Configure approvals and gates in Azure DevOps > Pipelines > Environments > (select environment) > Approvals and checks.
环境是Azure DevOps的一等资源,可实现部署目标定位、审批闸门和部署历史追踪:
yaml
stages:
- stage: DeployStaging
jobs:
- deployment: DeployToStaging
pool:
vmImage: 'ubuntu-latest'
environment: 'staging'
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: app
- script: echo "Deploying to staging"
- stage: DeployProduction
dependsOn: DeployStaging
jobs:
- deployment: DeployToProduction
pool:
vmImage: 'ubuntu-latest'
environment: 'production'
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: app
- script: echo "Deploying to production"首次引用环境时会自动创建。可在Azure DevOps > 管道 > 环境 >(选择对应环境)> 审批与检查中配置审批和闸门。
Approval Checks
审批检查
| Check Type | Purpose | Configuration |
|---|---|---|
| Approvals | Manual sign-off before deployment | Assign approver users/groups |
| Branch control | Restrict deployments to specific branches | Allow only |
| Business hours | Deploy only during allowed time windows | Define hours and timezone |
| Template validation | Require pipeline to extend a specific template | Specify required template path |
| Invoke Azure Function | Custom validation via Azure Function | Provide function URL and key |
| Invoke REST API | Custom validation via HTTP endpoint | Provide URL and success criteria |
| Required template | Enforce pipeline structure | Specify required extends template |
| 检查类型 | 用途 | 配置方式 |
|---|---|---|
| 审批 | 部署前需人工签字确认 | 分配审批用户/组 |
| 分支控制 | 限制仅特定分支可触发部署 | 仅允许 |
| 营业时间 | 仅在允许的时间段内部署 | 定义时间窗口及时区 |
| 模板验证 | 要求管道必须继承特定模板 | 指定必填模板路径 |
| 调用Azure Function | 通过Azure Function实现自定义验证 | 提供函数URL和密钥 |
| 调用REST API | 通过HTTP端点实现自定义验证 | 提供URL和成功判定条件 |
| 必填模板 | 强制管道结构规范 | 指定必须继承的模板 |
Configuring Approval Checks
配置审批检查
Approval checks are configured in the Azure DevOps UI, not in YAML. The YAML pipeline references the environment, and the checks are applied:
yaml
undefined审批检查需在Azure DevOps UI中配置,而非YAML。YAML管道仅需引用环境名称,检查规则会自动生效:
yaml
undefinedPipeline YAML -- environment reference triggers checks
管道YAML——环境引用会触发检查
- deployment: DeployToProduction environment: 'production' # checks configured in UI strategy: runOnce: deploy: steps: - script: echo "This runs only after all checks pass"
**Approval configuration (UI):**
- Navigate to Pipelines > Environments > production > Approvals and checks
- Add "Approvals" check: assign individuals or groups
- Set minimum number of approvers (e.g., 2 for production)
- Enable "allow approvers to approve their own runs" only if appropriate- deployment: DeployToProduction environment: 'production' # 检查规则在UI中配置 strategy: runOnce: deploy: steps: - script: echo "This runs only after all checks pass"
**审批配置(UI操作):**
- 导航至管道 > 环境 > production > 审批与检查
- 添加「审批」检查:指定个人或组作为审批者
- 设置最小审批人数(例如生产环境需2人)
- 仅在必要时启用「允许审批者批准自己触发的运行」Business Hours Gate
营业时间闸门
Restrict deployments to specific time windows to reduce risk:
- Navigate to Pipelines > Environments > production > Approvals and checks
- Add "Business Hours" check
- Configure: Monday-Friday, 09:00-17:00 (team timezone)
- Pipelines will queue and wait until the window opens
将部署限制在特定时间窗口内以降低风险:
- 导航至管道 > 环境 > production > 审批与检查
- 添加「营业时间」检查
- 配置:周一至周五,09:00-17:00(团队时区)
- 管道将进入排队状态,直到时间窗口开启
Pre-Deployment Validation with Azure Functions
借助Azure Function实现部署前验证
yaml
undefinedyaml
undefinedThe environment's "Invoke Azure Function" check calls:
环境的「调用Azure Function」检查会调用:
with the pipeline context as payload.
并将管道上下文作为请求体。
Returns 200 to approve, non-200 to reject.
返回200表示批准,非200表示拒绝。
- deployment: DeployToProduction environment: 'production' # Azure Function check configured in UI strategy: runOnce: preDeploy: steps: - script: echo "Pre-deploy hook (in-pipeline)" deploy: steps: - script: echo "Deploying" routeTraffic: steps: - script: echo "Routing traffic" postRouteTraffic: steps: - script: echo "Post-route validation"
The `preDeploy`, `routeTraffic`, and `postRouteTraffic` lifecycle hooks execute within the pipeline. Environment checks (approvals, Azure Function gates) execute before the deployment job starts.
---- deployment: DeployToProduction environment: 'production' # Azure Function检查在UI中配置 strategy: runOnce: preDeploy: steps: - script: echo "Pre-deploy hook (in-pipeline)" deploy: steps: - script: echo "Deploying" routeTraffic: steps: - script: echo "Routing traffic" postRouteTraffic: steps: - script: echo "Post-route validation"
`preDeploy`、`routeTraffic`和`postRouteTraffic`生命周期钩子在管道内部执行。环境检查(审批、Azure Function闸门)则在部署作业启动前执行。
---Deployment Groups vs Environments
部署组与环境的对比
When to Use Each
各自适用场景
| Feature | Deployment Groups | Environments |
|---|---|---|
| Target | Physical/virtual machines with agents | Any target (VMs, Kubernetes, cloud services) |
| Agent model | Self-hosted agents on target machines | Pool agents or target-specific resources |
| Pipeline type | Classic release pipelines (legacy) | YAML multi-stage pipelines (modern) |
| Approvals | Per-stage in classic UI | Checks and approvals on environment |
| Rolling deployment | Built-in rolling strategy | |
| Recommendation | Legacy workloads only | All new projects |
| 特性 | 部署组 | 环境 |
|---|---|---|
| 目标对象 | 安装了Agent的物理/虚拟机 | 任意目标(虚拟机、Kubernetes、云服务) |
| Agent模式 | 目标机器上的自托管Agent | 池化Agent或目标专属资源 |
| 管道类型 | 经典发布管道(遗留) | 多阶段YAML管道(现代) |
| 审批方式 | 经典UI中按阶段配置 | 环境层面的检查与审批 |
| 滚动部署 | 内置滚动策略 | YAML中使用 |
| 推荐场景 | 仅遗留工作负载 | 所有新项目 |
Deployment Group Example (Legacy)
部署组示例(遗留)
Deployment groups install an agent on each target machine. Use only for existing on-premises deployments:
yaml
undefined部署组会在每台目标机器上安装Agent。仅适用于现有本地部署场景:
yaml
undefinedClassic release pipeline (not YAML) -- for reference only
经典发布管道(非YAML)——仅作参考
Deployment groups are configured in Project Settings > Deployment Groups
部署组在项目设置 > 部署组中配置
Each target server runs the ADO agent registered to the group
每台目标服务器运行已注册到该组的ADO Agent
undefinedundefinedEnvironment with Kubernetes Resource
关联Kubernetes资源的环境
yaml
- deployment: DeployToK8s
environment: 'production.my-k8s-namespace'
strategy:
runOnce:
deploy:
steps:
- task: KubernetesManifest@1
inputs:
action: 'deploy'
manifests: 'k8s/*.yml'
containers: '$(ACR_LOGIN_SERVER)/myapp:$(Build.BuildId)'Environments can target Kubernetes clusters and namespaces. Register the cluster as a resource under the environment in the Azure DevOps UI.
yaml
- deployment: DeployToK8s
environment: 'production.my-k8s-namespace'
strategy:
runOnce:
deploy:
steps:
- task: KubernetesManifest@1
inputs:
action: 'deploy'
manifests: 'k8s/*.yml'
containers: '$(ACR_LOGIN_SERVER)/myapp:$(Build.BuildId)'环境可定位Kubernetes集群和命名空间。需在Azure DevOps UI中将集群注册为环境下的资源。
Migration from Deployment Groups to Environments
从部署组迁移到环境
- Create environments matching existing deployment group names
- Configure the same approval gates in the environment's Approvals and checks
- Convert classic release pipeline stages to YAML jobs targeting the new environments
deployment - Use for incremental deployments equivalent to deployment group behavior
strategy: rolling
- 创建与现有部署组名称匹配的环境
- 在环境的审批与检查中配置相同的审批闸门
- 将经典发布管道阶段转换为指向新环境的YAML 作业
deployment - 使用实现与部署组等效的增量部署
strategy: rolling
Service Connections
服务连接
Azure Resource Manager (ARM)
Azure Resource Manager (ARM)
Service connections provide authenticated access to external services. ARM connections enable Azure resource deployments:
yaml
- task: AzureWebApp@1
displayName: 'Deploy to Azure App Service'
inputs:
azureSubscription: 'MyAzureServiceConnection'
appType: 'webAppLinux'
appName: 'myapp-staging'
package: '$(Pipeline.Workspace)/app'Creating an ARM service connection:
- Navigate to Project Settings > Service Connections > New service connection > Azure Resource Manager
- Choose "Service principal (automatic)" for automatic credential management
- Select the subscription and resource group scope
- ADO creates an app registration and assigns Contributor role
服务连接提供对外部服务的认证访问。ARM连接可实现Azure资源部署:
yaml
- task: AzureWebApp@1
displayName: 'Deploy to Azure App Service'
inputs:
azureSubscription: 'MyAzureServiceConnection'
appType: 'webAppLinux'
appName: 'myapp-staging'
package: '$(Pipeline.Workspace)/app'创建ARM服务连接:
- 导航至项目设置 > 服务连接 > 新建服务连接 > Azure Resource Manager
- 选择「服务主体(自动)」以实现凭证自动管理
- 选择订阅和资源组范围
- ADO会自动创建应用注册并分配参与者角色
Workload Identity Federation (Recommended)
工作负载身份联合(推荐)
Use workload identity federation for passwordless Azure authentication (no client secret):
- Navigate to Project Settings > Service Connections > New service connection > Azure Resource Manager
- Choose "Workload Identity federation (automatic)"
- This creates a federated credential that trusts Azure DevOps pipeline tokens
- No secret rotation required -- the credential uses short-lived pipeline tokens
使用工作负载身份联合实现无密码Azure认证(无需客户端密钥):
- 导航至项目设置 > 服务连接 > 新建服务连接 > Azure Resource Manager
- 选择「工作负载身份联合(自动)」
- 系统会创建一个联合凭证,信任Azure DevOps管道令牌
- 无需密钥轮换——凭证使用短期管道令牌
Docker Registry Service Connection
Docker Registry服务连接
yaml
- task: Docker@2
displayName: 'Login to ACR'
inputs:
command: 'login'
containerRegistry: 'MyACRServiceConnection'
- task: Docker@2
displayName: 'Build and push'
inputs:
command: 'buildAndPush'
containerRegistry: 'MyACRServiceConnection'
repository: 'myapp'
dockerfile: 'src/MyApp/Dockerfile'Creating a Docker registry connection:
- Project Settings > Service Connections > New service connection > Docker Registry
- For ACR: select "Azure Container Registry" and choose the registry
- For DockerHub: provide username and access token
yaml
- task: Docker@2
displayName: 'Login to ACR'
inputs:
command: 'login'
containerRegistry: 'MyACRServiceConnection'
- task: Docker@2
displayName: 'Build and push'
inputs:
command: 'buildAndPush'
containerRegistry: 'MyACRServiceConnection'
repository: 'myapp'
dockerfile: 'src/MyApp/Dockerfile'创建Docker Registry连接:
- 项目设置 > 服务连接 > 新建服务连接 > Docker Registry
- 对于ACR:选择「Azure容器注册表」并选择对应注册表
- 对于DockerHub:提供用户名和访问令牌
NuGet Service Connection
NuGet服务连接
For pushing to external NuGet feeds (e.g., nuget.org):
yaml
- task: NuGetCommand@2
displayName: 'Push to nuget.org'
inputs:
command: 'push'
packagesToPush: '$(Pipeline.Workspace)/nupkgs/*.nupkg'
nuGetFeedType: 'external'
publishFeedCredentials: 'NuGetOrgServiceConnection'Creating a NuGet connection:
- Project Settings > Service Connections > New service connection > NuGet
- Provide the feed URL () and API key
https://api.nuget.org/v3/index.json
用于推送包至外部NuGet源(如nuget.org):
yaml
- task: NuGetCommand@2
displayName: 'Push to nuget.org'
inputs:
command: 'push'
packagesToPush: '$(Pipeline.Workspace)/nupkgs/*.nupkg'
nuGetFeedType: 'external'
publishFeedCredentials: 'NuGetOrgServiceConnection'创建NuGet连接:
- 项目设置 > 服务连接 > 新建服务连接 > NuGet
- 提供源URL()和API密钥
https://api.nuget.org/v3/index.json
Classic Release Pipelines (Legacy Migration)
经典发布管道(遗留系统迁移)
Why Migrate to YAML
为何迁移至YAML
Classic release pipelines use a visual designer and are not stored in source control. Migrate to YAML multi-stage pipelines for:
- Source control: Pipeline definitions live alongside code
- Code review: Pipeline changes go through PR review
- Branch-specific pipelines: YAML pipelines can vary by branch
- Reusability: Templates and extends for composable pipelines
- Modern features: Environments, deployment strategies, pipeline decorators
经典发布管道使用可视化设计器,且定义不存储在源代码控制中。迁移至多阶段YAML管道可获得以下优势:
- 源代码控制:管道定义与代码存储在一起
- 代码评审:管道变更需经过PR评审
- 分支专属管道:YAML管道可根据分支自定义
- 可复用性:通过模板和继承实现可组合管道
- 现代特性:环境、部署策略、管道装饰器
Migration Pattern
迁移模式
Classic release structure:
Build Pipeline -> Release Pipeline
Stage 1: Dev (auto-deploy)
Stage 2: Staging (manual approval)
Stage 3: Production (scheduled + approval)Equivalent YAML multi-stage pipeline:
yaml
trigger:
branches:
include:
- main
stages:
- stage: Build
jobs:
- job: BuildJob
pool:
vmImage: 'ubuntu-latest'
steps:
- task: DotNetCoreCLI@2
inputs:
command: 'publish'
projects: 'src/MyApp/MyApp.csproj'
arguments: '-c Release -o $(Build.ArtifactStagingDirectory)/app'
- task: PublishPipelineArtifact@1
inputs:
targetPath: '$(Build.ArtifactStagingDirectory)/app'
artifactName: 'app'
- stage: DeployDev
dependsOn: Build
jobs:
- deployment: DeployDev
environment: 'development'
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: app
- script: echo "Deploy to dev"
- stage: DeployStaging
dependsOn: DeployDev
jobs:
- deployment: DeployStaging
environment: 'staging' # approvals configured in UI
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: app
- script: echo "Deploy to staging"
- stage: DeployProduction
dependsOn: DeployStaging
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- deployment: DeployProduction
environment: 'production' # approvals + business hours in UI
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: app
- script: echo "Deploy to production"经典发布结构:
构建管道 -> 发布管道
阶段1:Dev(自动部署)
阶段2:Staging(人工审批)
阶段3:Production(定时触发+审批)等效的多阶段YAML管道:
yaml
trigger:
branches:
include:
- main
stages:
- stage: Build
jobs:
- job: BuildJob
pool:
vmImage: 'ubuntu-latest'
steps:
- task: DotNetCoreCLI@2
inputs:
command: 'publish'
projects: 'src/MyApp/MyApp.csproj'
arguments: '-c Release -o $(Build.ArtifactStagingDirectory)/app'
- task: PublishPipelineArtifact@1
inputs:
targetPath: '$(Build.ArtifactStagingDirectory)/app'
artifactName: 'app'
- stage: DeployDev
dependsOn: Build
jobs:
- deployment: DeployDev
environment: 'development'
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: app
- script: echo "Deploy to dev"
- stage: DeployStaging
dependsOn: DeployDev
jobs:
- deployment: DeployStaging
environment: 'staging' # 审批在UI中配置
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: app
- script: echo "Deploy to staging"
- stage: DeployProduction
dependsOn: DeployStaging
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- deployment: DeployProduction
environment: 'production' # 审批+营业时间限制在UI中配置
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: app
- script: echo "Deploy to production"Migration Checklist
迁移检查清单
- Identify all classic release stages and map to YAML stages
- Convert environment variables to YAML variable groups or templates
- Replace classic approval gates with environment checks
- Convert artifact sources to or pipeline resources
download: current - Replace task groups with YAML step or job templates
- Test the YAML pipeline on a non-production branch before decommissioning the classic release
- 识别所有经典发布阶段并映射为YAML阶段
- 转换环境变量为YAML变量组或模板
- 替换经典审批闸门为环境检查
- 转换制品源为或管道资源
download: current - 替换任务组为YAML步骤或作业模板
- 在非生产分支测试YAML管道,之后再停用经典发布管道
Variable Groups and Library
变量组与库
Variable Groups Linked to Azure Key Vault
关联Azure Key Vault的变量组
Variable groups can pull secrets directly from Azure Key Vault at pipeline runtime:
yaml
variables:
- group: 'kv-production-secrets'
- group: 'build-settings'
- name: buildConfiguration
value: 'Release'
steps:
- script: |
echo "Building with configuration $(buildConfiguration)"
displayName: 'Build'
env:
SQL_CONNECTION: $(sql-connection-string) # from Key Vault
API_KEY: $(api-key) # from Key VaultSetting up Key Vault-linked variable groups:
- Navigate to Pipelines > Library > Variable Groups > New variable group
- Enable "Link secrets from an Azure key vault as variables"
- Select the Azure subscription (service connection) and Key Vault
- Choose which secrets to include
- Secrets are fetched at pipeline runtime and available as
$(secret-name)
变量组可在管道运行时直接从Azure Key Vault拉取机密:
yaml
variables:
- group: 'kv-production-secrets'
- group: 'build-settings'
- name: buildConfiguration
value: 'Release'
steps:
- script: |
echo "Building with configuration $(buildConfiguration)"
displayName: 'Build'
env:
SQL_CONNECTION: $(sql-connection-string) # 来自Key Vault
API_KEY: $(api-key) # 来自Key Vault配置Key Vault关联变量组:
- 导航至管道 > 库 > 变量组 > 新建变量组
- 启用「将Azure密钥保管库中的机密链接为变量」
- 选择Azure订阅(服务连接)和Key Vault
- 选择需要包含的机密
- 机密会在管道运行时拉取,可通过引用
$(secret-name)
Scoping Variable Groups to Environments
按环境作用域划分变量组
Use conditional variable group references based on pipeline stage:
yaml
stages:
- stage: DeployStaging
variables:
- group: 'staging-config'
- group: 'kv-staging-secrets'
jobs:
- deployment: Deploy
environment: 'staging'
strategy:
runOnce:
deploy:
steps:
- script: echo "Deploying with staging config"
env:
CONNECTION_STRING: $(sql-connection-string)
- stage: DeployProduction
variables:
- group: 'production-config'
- group: 'kv-production-secrets'
jobs:
- deployment: Deploy
environment: 'production'
strategy:
runOnce:
deploy:
steps:
- script: echo "Deploying with production config"
env:
CONNECTION_STRING: $(sql-connection-string)可根据管道阶段条件引用不同变量组:
yaml
stages:
- stage: DeployStaging
variables:
- group: 'staging-config'
- group: 'kv-staging-secrets'
jobs:
- deployment: Deploy
environment: 'staging'
strategy:
runOnce:
deploy:
steps:
- script: echo "Deploying with staging config"
env:
CONNECTION_STRING: $(sql-connection-string)
- stage: DeployProduction
variables:
- group: 'production-config'
- group: 'kv-production-secrets'
jobs:
- deployment: Deploy
environment: 'production'
strategy:
runOnce:
deploy:
steps:
- script: echo "Deploying with production config"
env:
CONNECTION_STRING: $(sql-connection-string)Secure Files in Library
库中的安全文件
Store certificates, SSH keys, and other binary secrets in the Pipelines Library:
yaml
- task: DownloadSecureFile@1
displayName: 'Download signing certificate'
name: signingCert
inputs:
secureFile: 'code-signing.pfx'
- script: |
dotnet nuget sign ./nupkgs/*.nupkg \
--certificate-path $(signingCert.secureFilePath) \
--certificate-password $(CERT_PASSWORD) \
--timestamper http://timestamp.digicert.com
displayName: 'Sign NuGet packages'可在管道库中存储证书、SSH密钥和其他二进制机密:
yaml
- task: DownloadSecureFile@1
displayName: 'Download signing certificate'
name: signingCert
inputs:
secureFile: 'code-signing.pfx'
- script: |
dotnet nuget sign ./nupkgs/*.nupkg \
--certificate-path $(signingCert.secureFilePath) \
--certificate-password $(CERT_PASSWORD) \
--timestamper http://timestamp.digicert.com
displayName: 'Sign NuGet packages'Pipeline Decorators
管道装饰器
Pipeline decorators inject steps into every pipeline in an organization or project without modifying individual pipeline files. They enforce organizational policies:
管道装饰器可在无需修改单个管道文件的情况下,将步骤注入组织或项目中的所有管道,用于强制实施组织级策略:
Decorator Use Cases
装饰器适用场景
| Use Case | Implementation |
|---|---|
| Mandatory security scanning | Inject credential scanner before every job |
| Compliance audit logging | Inject telemetry step after every job |
| Required code analysis | Inject SonarQube analysis on main branch builds |
| License compliance | Inject dependency license scanner |
| 场景 | 实现方式 |
|---|---|
| 强制安全扫描 | 在每个作业前注入凭证扫描步骤 |
| 合规审计日志 | 在每个作业后注入遥测步骤 |
| 强制代码分析 | 在主分支构建时注入SonarQube分析 |
| 许可证合规 | 注入依赖许可证扫描步骤 |
Decorator Definition
装饰器定义
Decorators are packaged as Azure DevOps extensions:
yaml
undefined装饰器需打包为Azure DevOps扩展:
yaml
undefinedvss-extension.json (extension manifest)
vss-extension.json(扩展清单)
{
"contributions": [
{
"id": "required-security-scan",
"type": "ms.azure-pipelines.pipeline-decorator",
"targets": ["ms.azure-pipelines-agent-job"],
"properties": {
"template": "decorator.yml",
"targetsExecutionOrder": "PreJob"
}
}
]
}
```yaml{
"contributions": [
{
"id": "required-security-scan",
"type": "ms.azure-pipelines.pipeline-decorator",
"targets": ["ms.azure-pipelines-agent-job"],
"properties": {
"template": "decorator.yml",
"targetsExecutionOrder": "PreJob"
}
}
]
}
```yamldecorator.yml
decorator.yml
steps:
- task: CredentialScanner@1 displayName: '[Policy] Credential scan' condition: always()
undefinedsteps:
- task: CredentialScanner@1 displayName: '[Policy] Credential scan' condition: always()
undefinedDeployment Limitations
部署限制
- Decorators require Azure DevOps organization admin permissions to install
- They apply to all pipelines in the organization (or selected projects)
- Pipeline authors cannot override or skip decorator steps
- Decorator steps run under the pipeline's agent pool and service connection context
- 装饰器需要Azure DevOps组织管理员权限才能安装
- 会应用于组织内所有管道(或选定项目)
- 管道作者无法覆盖或跳过装饰器步骤
- 装饰器步骤在管道的Agent池和服务连接上下文中运行
Azure Artifacts Universal Packages
Azure Artifacts通用包
Universal packages store arbitrary files (binaries, tools, datasets) in Azure Artifacts feeds, not limited to NuGet/npm/Maven formats:
通用包可在Azure Artifacts源中存储任意文件(二进制文件、工具、数据集),不限于NuGet/npm/Maven格式:
Publish a Universal Package
发布通用包
yaml
- task: UniversalPackages@0
displayName: 'Publish universal package'
inputs:
command: 'publish'
publishDirectory: '$(Build.ArtifactStagingDirectory)/tools'
feedsToUsePublish: 'internal'
vstsFeedPublish: 'MyProject/MyFeed'
vstsFeedPackagePublish: 'my-dotnet-tool'
versionOption: 'custom'
versionPublish: '$(Build.BuildNumber)'
packagePublishDescription: '.NET CLI tool binaries'yaml
- task: UniversalPackages@0
displayName: 'Publish universal package'
inputs:
command: 'publish'
publishDirectory: '$(Build.ArtifactStagingDirectory)/tools'
feedsToUsePublish: 'internal'
vstsFeedPublish: 'MyProject/MyFeed'
vstsFeedPackagePublish: 'my-dotnet-tool'
versionOption: 'custom'
versionPublish: '$(Build.BuildNumber)'
packagePublishDescription: '.NET CLI tool binaries'Download a Universal Package
下载通用包
yaml
- task: UniversalPackages@0
displayName: 'Download universal package'
inputs:
command: 'download'
feedsToUse: 'internal'
vstsFeed: 'MyProject/MyFeed'
vstsFeedPackage: 'my-dotnet-tool'
vstsPackageVersion: '*'
downloadDirectory: '$(Pipeline.Workspace)/tools'yaml
- task: UniversalPackages@0
displayName: 'Download universal package'
inputs:
command: 'download'
feedsToUse: 'internal'
vstsFeed: 'MyProject/MyFeed'
vstsFeedPackage: 'my-dotnet-tool'
vstsPackageVersion: '*'
downloadDirectory: '$(Pipeline.Workspace)/tools'Use Cases for .NET Projects
.NET项目适用场景
- CLI tool distribution: Publish self-contained .NET CLI tool binaries for cross-team consumption
- Build tool caching: Store custom MSBuild tasks or analyzers used across repositories
- Test fixture data: Publish large test datasets that should not be stored in Git
- AOT binaries: Distribute pre-built Native AOT binaries for platforms where on-demand compilation is impractical
- CLI工具分发:发布自包含的.NET CLI工具二进制文件供跨团队使用
- 构建工具缓存:存储跨仓库使用的自定义MSBuild任务或分析器
- 测试数据集:发布不适合存储在Git中的大型测试数据
- AOT二进制文件:分发预编译的Native AOT二进制文件,适用于无法按需编译的平台
Agent Gotchas
Agent注意事项
- Environment checks (approvals, gates) are configured in the UI, not YAML -- the YAML pipeline references the environment name; all checks are managed through the Azure DevOps web UI.
- Deployment groups are legacy -- use environments for all new projects; deployment groups exist only for backward compatibility with classic release pipelines.
- Service connection scope matters -- ARM connections scoped to a resource group cannot deploy to resources outside that group; use subscription-level scope for cross-resource-group deployments.
- Workload identity federation is preferred over service principal secrets -- federated credentials eliminate secret rotation; use automatic federation for new connections.
- Key Vault-linked variable groups fetch secrets at runtime -- template expressions () cannot access Key Vault secrets because they resolve at compile time; use runtime expressions (
${{ }}) instead.$() - Classic release pipelines are not stored in source control -- this is a primary motivation for migration; YAML pipelines enable PR review and branch-specific definitions.
- Pipeline decorators cannot be bypassed by pipeline authors -- this is intentional for policy enforcement; test decorator changes in a separate organization or project to avoid breaking all pipelines.
- Universal packages have a 4 GiB size limit per file -- for larger artifacts, split files or use Azure Blob Storage with a SAS token instead.
- 环境检查(审批、闸门)需在UI中配置,而非YAML——YAML管道仅引用环境名称;所有检查规则通过Azure DevOps网页UI管理。
- 部署组属于遗留功能——所有新项目应使用环境;部署组仅为兼容经典发布管道而保留。
- 服务连接的作用域很重要——限定为资源组的ARM连接无法部署到组外资源;跨资源组部署需使用订阅级作用域。
- 工作负载身份联合优于服务主体密钥——联合凭证无需密钥轮换;新建连接时优先使用自动联合方式。
- 关联Key Vault的变量组在运行时拉取机密——模板表达式()无法访问Key Vault机密(因为在编译时解析);需使用运行时表达式(
${{ }})。$() - 经典发布管道不存储在源代码控制中——这是迁移的主要原因;YAML管道支持PR评审和分支专属定义。
- 管道装饰器无法被管道作者绕过——这是为了确保策略强制实施;需在单独的组织或项目中测试装饰器变更,避免影响所有管道。
- 通用包单文件大小限制为4 GiB——对于更大的制品,可拆分文件或使用带SAS令牌的Azure Blob存储。