Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019
本文介绍如何在 Azure DevOps 中为组织的自定义生成或发布任务安装扩展。 有关详细信息,请参阅什么是 Azure Pipelines?
注意
本文介绍基于代理的扩展中的代理任务。 有关服务器任务和基于服务器的扩展的详细信息,请参阅 服务器任务创作。
先决条件
Azure DevOps 中的组织。 创建一个组织。
文本编辑器。 对于许多教程,我们使用 Visual Studio Code,它提供 Intellisense 和调试支持。
最新版本的 Node.js。
npmjs.com 4.0.2 或更高版本。 安装此 TypeScript 编译器的 最新版本 。
用于打包扩展的 Azure DevOps 跨平台 CLI(tfx-cli)。
- 可以使用
npm
(Node.js 的组件)通过运行npm i -g tfx-cli
安装 tfx-cli。
- 可以使用
Azure DevOps 扩展 SDK。 安装 azure-devops-extension-sdk 包。
项目的
home
目录。 完成home
本文中的步骤后,生成或发布任务扩展的目录应具有以下结构:|--- README.md |--- images |--- extension-icon.png |--- buildandreleasetask // where your task scripts are placed |--- vss-extension.json // extension's manifest
重要
开发计算机必须运行 最新版本的 Node ,以确保编写的代码与代理上的生产环境和最新的非预览版 azure-pipelines-task-lib
兼容。 请根据以下命令更新您的task.json
文件。
"execution": {
"Node20_1": {
"target": "index.js"
}
}
1.创建自定义任务
在buildandreleasetask
目录内的home
文件夹中执行此过程的每个部分。
注意
此示例演练将 Windows 与 PowerShell 配合使用。 这些步骤适用于所有平台,但用于获取环境变量的语法不同。 如果使用 Mac 或 Linux,请将任何实例 $env:<var>=<val>
替换为 export <var>=<val>
。
创建任务基架
为任务创建文件夹结构,并安装所需的库和依赖项。
打开 PowerShell 命令窗口,转到文件夹
buildandreleasetask
,然后运行以下命令。npm init --yes
npm init
创建package.json
文件。 添加了参数--yes
以接受所有默认npm init
选项。提示
代理不会自动安装所需的模块,因为任务文件夹需要包含节点模块。 若要缓解此问题,请将
node_modules
复制到buildandreleasetask
。 随着任务变大,很容易超过 VSIX 文件的大小限制(50 MB)。 在复制节点文件夹之前,可能需要运行npm install --production
或npm prune --production
,也可以编写脚本来生成和打包所有内容。将
azure-pipelines-task-lib
添加到您的库中。npm install azure-pipelines-task-lib --save
确保为外部依赖项安装了 TypeScript typing。
npm install @types/node --save-dev npm install @types/q --save-dev
创建文件
.gitignore
并向其添加node_modules。 你的构建过程应该执行npm install
和typings install
,以便每次构建 node_modules 并且不需要签入。echo node_modules > .gitignore
将 Mocha 安装为开发依赖项。
npm install mocha --save-dev -g npm install sync-request --save-dev npm install @types/mocha --save-dev
选择 TypeScript 版本 2.3.4 或 4.6.3。
npm install typescript@4.6.3 -g --save-dev
注意
请确保在开发环境中通过全局方式使用
npm
安装 TypeScript,以保证tsc
命令可用。 如果跳过此步骤,则默认情况下使用 TypeScript 版本 2.3.4,并且仍需全局安装包,才能让tsc
命令可用。创建
tsconfig.json
编译器选项。 此文件可确保 TypeScript 文件编译为 JavaScript 文件。tsc --init --target es2022
创建任务
现在基架已完成,可以创建自定义任务。
在
task.json
文件夹中创建buildandreleasetask
文件。 该task.json
文件描述了构建/发布任务,并且构建/发布系统使用它来向用户显示配置选项,以及在构建/发布时确定要运行哪些脚本。复制以下代码,并用您的任务信息替换
{{placeholders}}
。 最重要的占位符是taskguid
,它必须是唯一的。{ "$schema": "https://raw.githubusercontent.com/Microsoft/azure-pipelines-task-lib/master/tasks.schema.json", "id": "{{taskguid}}", "name": "{{taskname}}", "friendlyName": "{{taskfriendlyname}}", "description": "{{taskdescription}}", "helpMarkDown": "", "category": "Utility", "author": "{{taskauthor}}", "version": { "Major": 0, "Minor": 1, "Patch": 0 }, "instanceNameFormat": "Echo $(samplestring)", "inputs": [ { "name": "samplestring", "type": "string", "label": "Sample String", "defaultValue": "", "required": true, "helpMarkDown": "A sample string" } ], "execution": { "Node20_1": { "target": "index.js" } } }
使用以下代码作为参考来创建
index.ts
文件。 此代码在调用任务时运行。import tl = require('azure-pipelines-task-lib/task'); async function run() { try { const inputString: string | undefined = tl.getInput('samplestring', true); if (inputString == 'bad') { tl.setResult(tl.TaskResult.Failed, 'Bad input was given'); return; } console.log('Hello', inputString); } catch (err:any) { tl.setResult(tl.TaskResult.Failed, err.message); } } run();
若要从
index.js
编译index.ts
文件,请从tsc
文件夹中输入buildandreleasetask
。
task.json 组件
请查看关于文件 task.json
的一些组件的以下说明。
属性 | 说明 |
---|---|
id |
任务的唯一 GUID。 |
name |
不带空格的名称。 |
friendlyName |
描述性名称(允许空格)。 |
description |
您的任务执行内容的详细说明。 |
author |
描述开发生成或发布任务的实体的简短字符串,例如: Microsoft Corporation |
instanceNameFormat |
任务在生成/发布步骤列表中显示的方式。 可以使用 $(variablename)来使用变量值。 |
groups |
描述 UI 中任务属性的逻辑分组。 |
inputs |
生成或发布任务运行时要使用的输入。 此任务需要具有名称 samplestring 的输入。 |
execution |
此任务有多个执行选项,包括脚本,例如 Node 、PowerShell 、PowerShell3 或 Process 。 |
restrictions |
对任务可以调用的 GitHub Codespaces 命令 以及任务可设置的变量应用的限制。 建议为新任务指定限制模式。 |
运行任务
从 PowerShell 中使用 node index.js
来运行任务。
在以下示例中,任务失败,因为未提供输入(samplestring
是所需的输入)。
node index.js
##vso[task.debug]agent.workFolder=undefined
##vso[task.debug]loading inputs and endpoints
##vso[task.debug]loaded 0
##vso[task.debug]task result: Failed
##vso[task.issue type=error;]Input required: samplestring
##vso[task.complete result=Failed;]Input required: samplestring
作为解决方案,请设置 samplestring
输入并再次运行任务。
$env:INPUT_SAMPLESTRING="Human"
node index.js
##vso[task.debug]agent.workFolder=undefined
##vso[task.debug]loading inputs and endpoints
##vso[task.debug]loading INPUT_SAMPLESTRING
##vso[task.debug]loaded 1
##vso[task.debug]Agent.ProxyUrl=undefined
##vso[task.debug]Agent.CAInfo=undefined
##vso[task.debug]Agent.ClientCert=undefined
##vso[task.debug]Agent.SkipCertValidation=undefined
##vso[task.debug]samplestring=Human
Hello Human
这次任务成功了,因为提供了 samplestring
,并且它正确输出了 Hello Human!
提示
有关各种任务运行程序以及如何在 task.json
中包括最新节点版本的信息,请参阅面向 Azure Pipelines 任务作者的 Node 运行器更新指南。
2.对任务脚本进行单元测试
执行单元测试以快速测试任务脚本,而不是它调用的外部工具。 测试成功路径和失败路径的各个方面。
安装测试工具。 在此过程中,我们使用 Mocha 作为测试驱动程序。
npm install mocha --save-dev -g npm install sync-request --save-dev npm install @types/mocha --save-dev
创建一个
tests
文件夹,其中包含一个_suite.ts
文件,文件内容如下:import * as path from 'path'; import * as assert from 'assert'; import * as ttm from 'azure-pipelines-task-lib/mock-test'; describe('Sample task tests', function () { before( function() { }); after(() => { }); it('should succeed with simple inputs', function(done: Mocha.Done) { // Add success test here }); it('it should fail if tool returns 1', function(done: Mocha.Done) { // Add failure test here }); });
提示
测试文件夹应位于
buildandreleasetask
该文件夹中。 如果收到同步请求错误,可以通过使用命令buildandreleasetask
将同步请求添加到npm i --save-dev sync-request
文件夹来解决此问题。success.ts
在测试目录中创建包含以下内容的文件。 此文件创建模拟运行任务并模拟对外部方法的所有调用。import ma = require('azure-pipelines-task-lib/mock-answer'); import tmrm = require('azure-pipelines-task-lib/mock-run'); import path = require('path'); let taskPath = path.join(__dirname, '..', 'index.js'); let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); tmr.setInput('samplestring', 'human'); tmr.run();
成功测试验证了在适当的输入下,测试是否成功且没有错误或警告并返回正确的输出。
若要运行任务模拟运行程序,请将以下示例成功测试添加到
_suite.ts
文件。it('should succeed with simple inputs', function(done: Mocha.Done) { this.timeout(1000); let tp: string = path.join(__dirname, 'success.js'); let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); // tr.run(); //current, old function. tr.runAsync().then(() => { console.log(tr.succeeded); assert.equal(tr.succeeded, true, 'should have succeeded'); assert.equal(tr.warningIssues.length, 0, "should have no warnings"); assert.equal(tr.errorIssues.length, 0, "should have no errors"); console.log(tr.stdout); assert.equal(tr.stdout.indexOf('Hello human') >= 0, true, "should display Hello human"); done(); }).catch((error) => { done(error); // Ensure the test case fails if there's an error }); });
在测试目录中创建一个
failure.ts
文件作为任务模拟运行程序,其中包含以下内容:import ma = require('azure-pipelines-task-lib/mock-answer'); import tmrm = require('azure-pipelines-task-lib/mock-run'); import path = require('path'); let taskPath = path.join(__dirname, '..', 'index.js'); let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); tmr.setInput('samplestring', 'bad'); tmr.run();
失败测试验证当工具输入不正确或不完整时,它会以预期方式失败,并得到有用的输出。
若要运行任务模拟运行程序,请将以下代码添加到
_suite.ts
文件。it('should fail if tool returns 1', function(done: Mocha.Done) { this.timeout(1000); const tp = path.join(__dirname, 'failure.js'); const tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); tr.runAsync().then(() => { console.log(tr.succeeded); assert.equal(tr.succeeded, false, 'should have failed'); assert.equal(tr.warningIssues.length, 0, 'should have no warnings'); assert.equal(tr.errorIssues.length, 1, 'should have 1 error issue'); assert.equal(tr.errorIssues[0], 'Bad input was given', 'error issue output'); assert.equal(tr.stdout.indexOf('Hello bad'), -1, 'Should not display Hello bad'); done(); }); });
运行测试。
tsc mocha tests/_suite.js
这两个测试都应通过。 如果要使用更详细的输出(在生成控制台中看到的内容)运行测试,请设置环境变量:
TASK_TEST_TRACE=1
$env:TASK_TEST_TRACE=1
3. 创建扩展清单文件
扩展清单包含有关扩展的所有信息。 它包括文件的链接,其中包括任务文件夹和图像文件夹。 确保已创建一个包含extension-icon.png
的图片文件夹。 以下示例是包含生成或发布任务的扩展清单。
将以下 .json 代码复制并保存为 vss-extension.json
目录中的 home
文件。
请勿在 buildandreleasetask 文件夹中创建此文件。
{
"manifestVersion": 1,
"id": "build-release-task",
"name": "Fabrikam Build and Release Tools",
"version": "0.0.1",
"publisher": "fabrikam",
"targets": [
{
"id": "Microsoft.VisualStudio.Services"
}
],
"description": "Tools for building/releasing with Fabrikam. Includes one build/release task.",
"categories": [
"Azure Pipelines"
],
"icons": {
"default": "images/extension-icon.png"
},
"files": [
{
"path": "buildandreleasetask"
}
],
"contributions": [
{
"id": "custom-build-release-task",
"type": "ms.vss-distributed-task.task",
"targets": [
"ms.vss-distributed-task.tasks"
],
"properties": {
"name": "buildandreleasetask"
}
}
]
}
注意
请将发布者更改为你的发布者名称。 有关详细信息,请参阅 “创建发布者”。
贡献
属性 | 说明 |
---|---|
id |
贡献的标识符。 在扩展中必须唯一。 不需要与生成或发布任务的名称匹配。 通常,生成或发布任务名称位于贡献项的 ID 中。 |
type |
贡献的类型。 应为 ms.vss-distributed-task.task 。 |
targets |
该贡献所针对的贡献。 应为 ms.vss-distributed-task.tasks 。 |
properties.name |
任务的名称。 此名称必须与相应的自包含生成或发布管道任务的文件夹名称匹配。 |
文件
属性 | 说明 |
---|---|
path |
相对于 home 目录的文件或文件夹的路径。 |
有关扩展清单文件(例如其属性及其用途)的详细信息,请参阅 扩展清单参考。
4.打包扩展
将所有文件打包在一起,将扩展引入 Visual Studio 市场。 所有扩展都打包为 VSIX 2.0 兼容的 .vsix 文件。 Microsoft提供了用于打包扩展的跨平台命令行接口(CLI)。
获取 tfx-cli 后,转到扩展的主目录,并运行以下命令:
tfx extension create --manifest-globs vss-extension.json
注意
每次更新时,都必须递增扩展或集成版本。
更新现有扩展时,请更新清单中的版本或传递 --rev-version
命令行开关。 这会递增你的扩展的补丁版本号,并将新版本保存到清单中。
必须同时更新任务版本和扩展版本才能进行更新。
tfx extension create --manifest-globs vss-extension.json --rev-version
仅更新扩展版本,而不是任务版本。 有关详细信息,请参阅 GitHub 中的生成任务。
打包的扩展名位于 .vsix 文件中后,即可将扩展发布到市场。
5.发布扩展
若要发布扩展,请先 创建发布者,然后 上传扩展,最后 共享该扩展。
创建发布者
所有扩展(包括 Microsoft 的扩展)都标识为由发布者提供。 如果你还不是现有发布方的成员,你应该创建一个新的发布方。
如果还没有现有发布者的成员,系统会提示你创建发布者。 如果未提示创建发布者,请向下滚动到页面底部,然后在“相关网站”下选择“发布扩展”。
- 为发布者指定标识符,例如:
mycompany-myteam
- 此标识符用作扩展清单文件中
publisher
属性的值。
- 此标识符用作扩展清单文件中
- 为发布者指定显示名称,例如:
My Team
- 为发布者指定标识符,例如:
查看市场发布者协议,然后选择“创建”。
你的发布者已定义。 在将来的版本中,可以授予查看和管理发布者扩展的权限。 在通用发布者下发布扩展更容易且更安全,无需跨用户共享一组凭据。
上传扩展
找到“上传新扩展”按钮,转到打包的 .vsix 文件,然后选择“上传”。
可以通过命令行接口(CLI)使用 tfx extension publish
命令,而不是使用 tfx extension create
,一步完成扩展的打包和发布。 可以选择使用 --share-with
在扩展发布之后与一个或多个帐户共享你的扩展。
tfx extension publish --manifest-globs your-manifest.json --share-with yourOrganization
分享扩展
上传扩展后,扩展将位于市场中,但没有人可以看到它。 与组织共享它,以便你可以安装和测试它。
右键单击扩展并选择“共享”,然后输入组织信息。 你也可以与想要访问你扩展的其他帐户共享它。
重要
必须验证发布者才能公开共享扩展。 有关详细信息,请参阅 包/发布/安装。
在市场中共享扩展后,任何想要使用它的人都必须安装它。
6. 创建生成和发布管道以将扩展发布到市场
若要在市场中维护自定义任务,请在 Azure DevOps 上创建生成和发布管道。
发布先决条件
Azure DevOps 项目。 创建项目。
Azure DevOps 扩展任务插件。 在组织中免费安装它 。
管道库变量组。 创建管道库变量组以保存管道使用的变量。 有关详细信息,请参阅 “添加和使用变量组”。 可以从 Azure DevOps 库选项卡或通过 CLI 生成变量组。 在管道中使用此组中的变量 。 此外,在变量组中声明以下变量:
-
publisherId
:市场发布者的 ID -
extensionId
:扩展的 ID,如 vss-extension.json 文件中声明的那样 -
extensionName
:扩展的名称,如 vss-extension.json 文件中声明的那样 -
artifactName
:为 VSIX 文件创建的项目的名称
-
服务连接。 创建新的市场服务连接并为所有管道授予访问权限。
YAML 管道。 使用以下示例通过 YAML 创建新管道。 有关详细信息,请参阅 创建第一个管道 和 YAML 架构。
trigger: - main pool: vmImage: "ubuntu-latest" variables: - group: variable-group # Rename to whatever you named your variable group in the prerequisite stage of step 6 stages: - stage: Run_and_publish_unit_tests jobs: - job: steps: - task: TfxInstaller@4 inputs: version: "v0.x" - task: Npm@1 inputs: command: 'install' workingDir: '/TaskDirectory' # Update to the name of the directory of your task - task: Bash@3 displayName: Compile Javascript inputs: targetType: "inline" script: | cd TaskDirectory # Update to the name of the directory of your task tsc - task: Npm@1 inputs: command: 'custom' workingDir: '/TestsDirectory' # Update to the name of the directory of your task's tests customCommand: 'testScript' # See the definition in the explanation section below - it may be called test - task: PublishTestResults@2 inputs: testResultsFormat: 'JUnit' testResultsFiles: '**/ResultsFile.xml' - stage: Package_extension_and_publish_build_artifacts jobs: - job: steps: - task: TfxInstaller@4 inputs: version: "0.x" - task: Npm@1 inputs: command: 'install' workingDir: '/TaskDirectory' # Update to the name of the directory of your task - task: Bash@3 displayName: Compile Javascript inputs: targetType: "inline" script: | cd TaskDirectory # Update to the name of the directory of your task tsc - task: QueryAzureDevOpsExtensionVersion@4 name: QueryVersion inputs: connectTo: 'VsTeam' connectedServiceName: 'ServiceConnection' # Change to whatever you named the service connection publisherId: '$(PublisherID)' extensionId: '$(ExtensionID)' versionAction: 'Patch' - task: PackageAzureDevOpsExtension@4 inputs: rootFolder: '$(System.DefaultWorkingDirectory)' publisherId: '$(PublisherID)' extensionId: '$(ExtensionID)' extensionName: '$(ExtensionName)' extensionVersion: '$(QueryVersion.Extension.Version)' updateTasksVersion: true updateTasksVersionType: 'patch' extensionVisibility: 'private' # Change to public if you're publishing to the marketplace extensionPricing: 'free' - task: CopyFiles@2 displayName: "Copy Files to: $(Build.ArtifactStagingDirectory)" inputs: Contents: "**/*.vsix" TargetFolder: "$(Build.ArtifactStagingDirectory)" - task: PublishBuildArtifacts@1 inputs: PathtoPublish: '$(Build.ArtifactStagingDirectory)' ArtifactName: '$(ArtifactName)' publishLocation: 'Container' - stage: Download_build_artifacts_and_publish_the_extension jobs: - job: steps: - task: TfxInstaller@4 inputs: version: "v0.x" - task: DownloadBuildArtifacts@0 inputs: buildType: "current" downloadType: "single" artifactName: "$(ArtifactName)" downloadPath: "$(System.DefaultWorkingDirectory)" - task: PublishAzureDevOpsExtension@4 inputs: connectTo: 'VsTeam' connectedServiceName: 'ServiceConnection' # Change to whatever you named the service connection fileType: 'vsix' vsixFile: '$(PublisherID).$(ExtensionName)/$(PublisherID)..vsix' publisherId: '$(PublisherID)' extensionId: '$(ExtensionID)' extensionName: '$(ExtensionName)' updateTasksVersion: false extensionVisibility: 'private' # Change to public if you're publishing to the marketplace extensionPricing: 'free'
有关详细信息,请参阅 指定会触发管道的事件。
注意
每个作业都使用新的用户代理,并要求安装依赖项。
管道阶段
以下部分可帮助你了解管道阶段的工作原理。
阶段 1:运行和发布单元测试
此阶段运行单元测试并将测试结果发布到 Azure DevOps。
若要运行单元测试,请将自定义脚本添加到 package.json
文件,如以下示例所示。
"scripts": {
"testScript": "mocha ./TestFile --reporter xunit --reporter-option output=ResultsFile.xml"
},
添加将 Node CLI 用于 Azure DevOps (tfx-cli) 以将 tfx-cli 安装到生成代理上。
使用
npm
命令添加install
任务,并将目标指向包含package.json
的文件夹。添加
Bash
任务以将 TypeScript 编译到 JavaScript 中。使用
npm
custom
命令添加任务,将包含单元测试的文件夹作为目标,并将输入testScript
作为命令。 使用以下输入:- 命令:
custom
- 包含 package.json的工作文件夹:
/TestsDirectory
- 命令和参数:
testScript
- 命令:
添加 “发布测试结果 ”任务。 如果使用的是 Mocha XUnit 报告器,请确保结果格式是
JUnit
而不是XUnit
。 将搜索文件夹设置为根目录。 使用以下输入:- 测试结果格式:
JUnit
- 测试结果文件:
**/ResultsFile.xml
- 搜索文件夹:
$(System.DefaultWorkingDirectory)
发布测试结果后,“测试”选项卡下的输出应如以下示例所示。
- 测试结果格式:
阶段 2:打包扩展并发布生成项目
添加将 Node CLI 用于 Azure DevOps (tfx-cli) 以将 tfx-cli 安装到生成代理上。
使用
npm
命令添加install
任务,并将目标指向包含package.json
的文件夹。添加
Bash
任务以将 TypeScript 编译到 JavaScript 中。若要查询现有版本,请使用以下输入添加 查询扩展版本 任务:
- 连接到:Visual Studio Marketplace
- Visual Studio Marketplace(服务连接):服务连接
- 发布者 ID:Visual Studio Marketplace 发布者的 ID
- 扩展 ID:
vss-extension.json
文件中扩展的 ID - 版本升级:补丁
- 输出变量:
Task.Extension.Version
若要基于清单 Json 打包扩展,请使用以下输入添加 包扩展 任务:
- 根清单文件夹:指向包含清单文件的根目录。 例如,
$(System.DefaultWorkingDirectory)
是根目录。 - 清单文件:
vss-extension.json
- 发布者 ID:Visual Studio Marketplace 发布者的 ID
- 扩展 ID:
vss-extension.json
文件中扩展的 ID - 扩展名:
vss-extension.json
文件中扩展的名称 - 扩展版本:
$(Task.Extension.Version)
- 替代任务版本:已选中 (true)
- 替代类型:仅替换补丁 (1.0.r)
- 扩展可见性:如果扩展仍在开发中,请将该值设置为 私有。 若要将扩展发布到公共,请将值设置为 公共。
- 根清单文件夹:指向包含清单文件的根目录。 例如,
若要复制到已发布的文件,请使用以下输入添加 “复制文件 ”任务:
- 内容:所有要复制以便发布为工件的文件。
- 目标文件夹:文件复制到的文件夹
- 例如:
$(Build.ArtifactStagingDirectory)
- 例如:
添加发布生成项目以发布要在其他作业或管道中使用的项目。 使用以下输入:
- 发布路径:包含要发布的文件的文件夹的路径
- 例如:
$(Build.ArtifactStagingDirectory)
- 例如:
- 文物名称:分配给该文物的名称
- 工件发布路径:选择 Azure Pipelines 以便在后续作业中使用该工件。
- 发布路径:包含要发布的文件的文件夹的路径
阶段 3:下载生成产物并发布扩展程序
要将 tfx-cli 安装到生成代理上,请添加将 Node CLI 用于 Azure DevOps (tfx-cli)。
若要将项目下载到新作业,请使用以下输入添加 “下载生成项目 ”任务:
- 下载以下作业生成的工件:如果要在新作业中从同一管道下载工件,请选择当前生成。 如果要在新管道上下载,请选择特定生成
- 下载类型:选择 特定项目 以下载已发布的所有文件。
- 项目名称:已发布的项目名称
- 目标目录:应下载文件的文件夹
若要获取 发布扩展 任务,请使用以下输入:
- 连接到:Visual Studio Marketplace
- Visual Studio Marketplace 连接:ServiceConnection
- 输入文件类型:VSIX 文件
- VSIX 文件:
/Publisher.*.vsix
- 发布者 ID:Visual Studio Marketplace 发布者的 ID
- 扩展 ID:
vss-extension.json
文件中扩展的 ID - 扩展名:
vss-extension.json
文件中扩展的名称 - 扩展可见性:私有或公共
可选:安装和测试扩展
只需执行几个步骤即可安装与你共享的扩展:
- 从组织控制面板(
https://dev.azure.com/{organization}/_admin
)转到项目集合管理页面。 - 在“ 扩展 ”选项卡中,在“ 与我共享的扩展 ”组中找到扩展,然后选择扩展链接。
- 安装扩展。
如果看不到“ 扩展 ”选项卡,请确保位于控制面板(项目集合级别的管理页), https://dev.azure.com/{organization}/_admin
而不是项目的管理页。
如果未看到“ 扩展 ”选项卡,则不会为组织启用扩展。 可以通过加入 Visual Studio 合作伙伴计划来提前访问扩展功能。
若要打包 Azure DevOps Extensions 并将其发布到 Visual Studio Marketplace,可以下载 Azure DevOps 扩展任务。
常见问题
有关在 Azure DevOps 的扩展中添加自定义生成或发布任务,请参阅以下常见问题。
问:如何限制在任务中使用 Azure Pipelines 命令的权限?
可以限制按任务设置的 Azure Pipelines 命令使用情况和变量。
此操作可能有助于防止任务执行过程中自定义脚本对变量或 vso 命令的无限制访问。 建议你为新任务进行设置
若要应用,可能需要将以下语句添加到 task.json
文件:
"restrictions": {
"commands": {
"mode": "restricted"
},
"settableVariables": {
"allowed": ["variable1", "test*"]
}
}
如果为 restricted
指定了 mode
值,则只能通过任务执行以下命令:
logdetail
logissue
complete
setprogress
setsecret
setvariable
debug
settaskvariable
prependpath
publish
settableVariables
限制允许你传入由 setvariable
或 prependpath
命令设置的变量的允许列表。 它还允许基本正则表达式。 例如,如果允许列表是:['abc', 'test*']
,那么将abc
、test
或test1
设置为具有任何值的变量,或者将它们添加到路径前面都会成功,但如果您尝试设置一个变量代理,则会发出警告。 空列表意味着任务不会更改任何变量。
如果settableVariables
密钥或commands
密钥被省略,则不会应用相关限制。
限制功能可从 代理版本 2.182.1 获取。
问:如何通过任务来处理取消信号?
管道代理向相关子进程发送 SIGINT
和 SIGTERM
信号。 任务库中没有显式的方法来处理。 有关详细信息,请参阅 代理作业取消。
问:如何从项目集合中删除任务?
我们不支持自动删除任务。 自动删除不安全,会中断已使用此类任务的现有管道。 但是,可以将任务标记为已弃用。 为此,更新任务版本 并 将任务标记为弃用。
问:如何将自定义任务升级到最新的节点?
建议升级到 最新的 Node 版本。 有关示例信息,请参阅 将任务升级到 Node 20。
Microsoft 托管代理和各种 Azure DevOps Server 版本的生命周期不同,这导致在不同的任务运行位置会安装不同版本的 Node.js 运行程序。 为了确保与不同节点运行程序版本的代理之间的兼容性, task.json
该文件可以包含多个执行部分。 在以下示例中,使用 Node 20 运行程序的 Azure Pipeline 代理默认使用 Node 20,而没有它的代理将回退到 Node 10 实现。
"execution": {
"Node10": {
"target": "bash.js",
"argumentFormat": ""
},
"Node20_1": {
"target": "bash.js",
"argumentFormat": ""
}
}
要升级你的任务,请执行以下操作:
若要确保代码按预期方式运行,请在各种 Node 运行程序版本上测试任务。
在任务的执行部分中,将
Node
或Node10
更新为Node16
或Node20
。若要支持较旧的服务器版本,应保留目标
Node
/Node10
。 旧版 Azure DevOps Server 可能不包含最新的 Node 运行程序版本。可以选择共享目标中定义的入口点,或者将目标优化到使用的 Node 版本。
"execution": { "Node10": { "target": "bash10.js", "argumentFormat": "" }, "Node16": { "target": "bash16.js", "argumentFormat": "" }, "Node20_1": { "target": "bash20.js", "argumentFormat": "" } }
重要
如果你没有在自定义任务中添加对 Node 20 运行器的支持,则任务会在从 pipelines-agent-*
发布源安装的代理上失败。