Azure DevOps Services |Azure DevOps Server 2022 および Azure DevOps Server 2019
この記事では、Azure DevOps でカスタム ビルドタスクまたはリリース タスク用の拡張機能を組織にインストールする方法について説明します。 詳細については、「Azure Pipelines とは」を参照してください。
注
この記事では、エージェント ベースの拡張機能のエージェント タスクについて説明します。 サーバー タスクとサーバー ベースの拡張機能の詳細については、「 サーバー タスクの作成」を参照してください。
前提条件
Azure DevOps の組織。 組織の作成。
テキスト エディター。 多くのチュートリアルでは、IntelliSense とデバッグのサポートを提供する Visual Studio Code を使用します。
Node.jsの最新バージョン。
npmjs.com 4.0.2 以降。 この TypeScript コンパイラの 最新バージョン をインストールします。
拡張機能をパッケージ化するための Azure DevOps (tfx-cli) 用のクロスプラットフォーム 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
フォルダー内で、この手順のすべての部分を実行します。
注
このチュートリアルの例では、PowerShell で Windows を使用します。 手順はすべてのプラットフォームで一般的ですが、環境変数を取得するための構文は異なります。 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 型指定がインストールされていることを確認します。
npm install @types/node --save-dev npm install @types/q --save-dev
.gitignore
ファイルを作成し、node_modulesを追加します。 ビルド プロセスでは、毎回node_modulesがビルドされ、チェックインする必要がないように、npm install
とtypings install
を実行する必要があります。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 |
ビルドまたはリリース タスクの実行時に使用する入力。 このタスクでは、 amplestring という名前の入力が必要です。 |
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 タスク作成者向けのノード ランナー更新ガイダンスを参照してください。
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
フォルダーに 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"
}
}
]
}
注
publisherを発行元名に変更します。 詳細については、「 パブリッシャーの作成」を参照してください。
貢献
プロパティ | 説明 |
---|---|
id |
コントリビューションの識別子。 拡張機能内で一意である必要があります。 ビルド タスクまたはリリース タスクの名前と一致する必要はありません。 通常、ビルドまたはリリース タスク名はコントリビューションの ID にあります。 |
type |
コントリビューションの種類。
ms.vss-distributed-task.task でなければなりません。 |
targets |
このコントリビューションの対象となるコントリビューション。
ms.vss-distributed-task.tasks でなければなりません。 |
properties.name |
タスクの名前。 この名前は、対応する自己完結型ビルドまたはリリース パイプライン タスクのフォルダー名と一致する必要があります。 |
ファイル
プロパティ | 説明 |
---|---|
path |
home ディレクトリを基準としたファイルまたはフォルダーのパス。 |
拡張マニフェスト ファイルのプロパティや実行内容など、拡張マニフェスト ファイルの詳細については、 extension マニフェスト リファレンスを参照してください。
4. 拡張機能をパッケージ化する
すべてのファイルをパッケージ化して、拡張機能を Visual Studio Marketplace に取り込みます。 すべての拡張機能は、VSIX 2.0 と互換性のある .vsix ファイルとしてパッケージ化されています。 Microsoft では、拡張機能をパッケージ化するためのクロスプラットフォーム コマンド ライン インターフェイス (CLI) を提供しています。
tfx-cliを取得したら、拡張機能のホーム ディレクトリに移動し、次のコマンドを実行します。
tfx extension create --manifest-globs vss-extension.json
注
拡張機能または統合のバージョンは、更新ごとにインクリメントする必要があります。
既存の拡張機能を更新する場合は、マニフェストのバージョンを更新するか、 --rev-version
コマンド ライン スイッチを渡します。 これにより、拡張機能の patch バージョン番号がインクリメントされ、新しいバージョンがマニフェストに保存されます。
更新を行うには、タスクのバージョンと拡張機能のバージョンの両方を変更する必要があります。
tfx extension create --manifest-globs vss-extension.json --rev-version
は、タスクのバージョンではなく、拡張機能のバージョンのみを更新します。 詳細については、GitHub の Build タスクを参照してください。
パッケージ化された拡張機能が .vsix ファイルに含まれると、Marketplace に拡張機能を発行する準備が整います。
5. 拡張機能を公開する
拡張機能を発行するには、最初 に発行元を作成し、次 に拡張機能をアップロードして、最後に 共有します。
発行元を作成する
Microsoft の拡張機能を含むすべての拡張機能は、発行元によって提供されていると識別されます。 既存のパブリッシャーのメンバーでない場合は、作成します。
Visual Studio Marketplace 発行ポータルにサインインします。
既存のパブリッシャーのメンバーでない場合は、パブリッシャーの作成を求められます。 発行元の作成を求めるメッセージが表示されない場合は、ページの下部まで下にスクロールし、関連サイト [拡張機能の公開] を選択。
- 発行元の識別子を指定します (例:
mycompany-myteam
)。- この識別子は、拡張機能のマニフェスト ファイルの
publisher
属性の値として使用されます。
- この識別子は、拡張機能のマニフェスト ファイルの
- 発行元の表示名を指定します (例:
My Team
)。
- 発行元の識別子を指定します (例:
Marketplace パブリッシャー契約を確認し作成を選択します。
発行元が定義されています。 今後のリリースでは、発行元の拡張機能を表示および管理するためのアクセス許可を付与できます。 ユーザー間で資格情報のセットを共有する必要なく、共通の発行元の下で拡張機能を公開する方が簡単で安全です。
拡張機能をアップロードする
新しい拡張機能のアップロード ボタンを見つけて、パッケージ化された .vsix ファイルに移動し、アップロードを選択します。
また、tfx extension publish
ではなく、tfx extension create
コマンドを使用してコマンド ライン インターフェイス (CLI) を使用して拡張機能をアップロードし、1 つの手順で拡張機能をパッケージ化して発行することもできます。 必要に応じて、 --share-with
を使用して、公開後に 1 つ以上のアカウントと拡張機能を共有できます。
tfx extension publish --manifest-globs your-manifest.json --share-with yourOrganization
拡張機能を共有する
お使いの拡張機能をアップロードした今、その拡張機能は Marketplace にありますが、誰にも見られていません。 インストールしてテストできるように、組織と共有します。
拡張機能を右選択し、 Share を選択し、組織の情報を入力します。 拡張機能にアクセスする他のアカウントと共有することもできます。
重要
公開されている拡張機能を共有するには、発行元を確認する必要があります。 詳細については、「 Package/Publish/Install」を参照してください。
拡張機能を Marketplace で共有したら、その拡張機能を使用するすべてのユーザーがインストールする必要があります。
6.拡張機能を Marketplace に発行するビルドおよびリリース パイプラインを作成する
Marketplace でカスタム タスクを維持するには、Azure DevOps でビルドおよびリリース パイプラインを作成します。
発行の前提条件
Azure DevOps プロジェクト。 プロジェクトを作成します。
Azure DevOps Extension Tasks 拡張機能。 組織で無料でインストールします。
パイプライン ライブラリ変数グループ。 パイプラインで使用される変数を保持するパイプライン ライブラリ変数グループを作成します。 詳細については、「 変数グループの追加と使用を参照してください。 変数グループは、Azure DevOps ライブラリ タブまたは CLI から作成できます。 パイプライン内のこのグループ内で 変数を使用します。 また、変数グループで次の変数を宣言します。
-
publisherId
: あなたの市場パブリッシャーのID -
extensionId
: vss-extension.json ファイルで宣言されている拡張機能の ID -
extensionName
: vss-extension.json ファイルで宣言されている拡張機能の名前 -
artifactName
: VSIX ファイル用に作成される成果物の名前
-
サービス接続。 新しい Marketplace サービス接続を作成し、すべてのパイプラインにアクセス許可を付与します。
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"
},
Azure DevOps 用の Node CLI (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: 拡張機能をパッケージ化し、ビルド成果物を発行する
Azure DevOps 用の Node CLI (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 に基づいて拡張機能をパッケージ化するには、次の入力を使用して Package Extension タスクを追加します。
- ルート マニフェスト フォルダー: マニフェスト ファイルを含むルート ディレクトリを指します。 たとえば、ルート ディレクトリ
$(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)
- 拡張機能の可視性: 拡張機能がまだ開発中の場合は、値を private に設定します。 拡張機能をパブリックにリリースするには、値を public に設定します。
- ルート マニフェスト フォルダー: マニフェスト ファイルを含むルート ディレクトリを指します。 たとえば、ルート ディレクトリ
パブリッシュされたファイルにコピーするには、次の入力を使用して ファイルのコピー タスクを追加します。
- 内容: 成果物として発行するためにコピーされるすべてのファイル
- ターゲット フォルダー: ファイルのコピー先フォルダー
- 例:
$(Build.ArtifactStagingDirectory)
- 例:
ビルド成果物の発行を追加して、他のジョブまたはパイプラインで使用する成果物を発行します。 次の入力を使用します。
- 発行するパス: 発行されるファイルを含むフォルダーへのパス
- 例:
$(Build.ArtifactStagingDirectory)
- 例:
- 成果物名: 成果物に指定された名前
- 成果物の発行場所: 将来のジョブで成果物を使用する Azure Pipelines を選択する
- 発行するパス: 発行されるファイルを含むフォルダーへのパス
ステージ 3: ビルド成果物をダウンロードして拡張機能を発行する
ビルド エージェントに tfx-cli をインストールするには、 Azure DevOps に Node CLI を使用する (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
) から、プロジェクト コレクションの管理ページに移動します。 - [ 拡張機能 ] タブで、[ 自分と共有されている拡張機能 ] グループで拡張機能を見つけて、拡張機能のリンクを選択します。
- 拡張機能をインストールします。
[ Extensions タブが表示されない場合は、プロジェクトの管理ページではなく、コントロール パネル (プロジェクト コレクション レベルの管理ページ https://dev.azure.com/{organization}/_admin
) にいることを確認してください。
[ Extensions ] タブが表示されない場合、拡張機能は組織で有効になりません。 Visual Studio パートナー プログラムに参加することで、拡張機能機能に早期にアクセスできます。
Azure DevOps 拡張機能をパッケージ化して Visual Studio Marketplace に発行するには、 Azure DevOps 拡張機能タスクをダウンロードできます。
よくあるご質問
Azure DevOps の拡張機能にカスタム ビルドタスクまたはリリース タスクを追加する方法については、次のよく寄せられる質問を参照してください。
Q: タスクの 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 から入手できます。
Q: キャンセルシグナルはタスクによってどのように処理されますか?
パイプライン エージェントは、関連する子プロセスに SIGINT
および SIGTERM
シグナルを送信します。
task ライブラリには、処理する明示的な手段はありません。 詳細については、「エージェントジョブのキャンセル」を参照してください。
Q: プロジェクト コレクションからタスクを削除するにはどうすればよいですか?
タスクの自動削除はサポートされていません。 自動削除は安全ではなく、そのようなタスクを既に使用している既存のパイプラインを中断します。 ただし、タスクは非推奨としてマークできます。 これを行うには、タスクのバージョンを更新し、タスクを非推奨としてマークします。
Q: カスタム タスクを最新のノードにアップグレードするにはどうすればよいですか?
最新の Node バージョンにアップグレードすることをお勧めします。 例については、「 ノード 20 へのタスクのアップグレード」を参照してください。
Microsoft ホステッド エージェントとさまざまな Azure DevOps Server バージョンでは、ライフ サイクルが異なり、タスクの実行場所に応じて異なる Node ランナー バージョンがインストールされます。 ノード ランナーのバージョンが異なるエージェント間の互換性を確保するために、 task.json
ファイルには複数の実行セクションを含めることができます。 次の例では、Node 20 ランナーを持つ Azure Pipeline エージェントでは既定で使用されますが、使用されていないエージェントは 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-*
リリース フィードからインストールされたエージェントで失敗します。