カスタム パイプライン タスク拡張機能を追加する
Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019
Azure DevOps でカスタム ビルドまたはリリース タスク用の拡張機能を組織にインストールする方法について説明します。 詳細については、「Azure Pipelines とは」を参照してください。
Note
この記事では、エージェント ベースの拡張機能のエージェント タスクについて説明します。 サーバー タスクとサーバー ベースの拡張機能の詳細については、サーバー タスクの GitHub ドキュメントを 参照してください。
前提条件
Azure DevOps の拡張機能を作成するには、次のソフトウェアとツールが必要です。
ソフトウェア/ツール | 情報 |
---|---|
Azure DevOps 組織 | 組織の作成。 |
テキスト エディター | 多くの手順では、IntelliSense とデバッグのサポートを提供する Visual Studio Code を使用します。 最新バージョンをダウンロード します。 |
Node.js | 最新バージョンをダウンロード します。 |
npmjs.com 4.0.2 以降 | TypeScript コンパイラ。 最新バージョンをダウンロード します。 |
tfx-cli | Azure DevOps 用のクロスプラットフォーム CLI を使用 して拡張機能をパッケージ化します。 を実行して、Node.jsのコンポーネントを使用 npm します npm i -g 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
重要
開発マシンは、記述されたコードがエージェント上の運用環境および最新のプレビュー以外のバージョンと互換性があることを確認するために、最新バージョンの azure-pipelines-task-lib
Node を実行する必要があります。 次のコマンドに従って、task.json ファイルを更新します。
"execution": {
"Node16": {
"target": "index.js"
}
}
1. カスタム タスクを作成する
この手順のすべての部分をフォルダー内で buildandreleasetask
実行します。
Note
このチュートリアルの例では、PowerShell で Windows を使用します。 すべてのプラットフォームで汎用にしましたが、環境変数を取得するための構文は異なります。 Mac または Linux を使用している場合は、$env:<var>=<val>
export <var>=<val>
タスク スキャフォールディングの作成
タスクのフォルダー構造を作成し、必要なライブラリと依存関係をインストールします。
PowerShell コマンド ウィンドウを開き、フォルダー
buildandreleasetask
に移動して、次のコマンドを実行します。npm init --yes
npm init
はファイルを作成しますpackage.json
。 すべての既定npm init
のオプションを--yes
受け入れるパラメーターを追加しました。ヒント
タスク フォルダーにノード モジュールが含まれると想定されているため、エージェントは必要なモジュールを自動的にインストールしません。 これを軽減するには、次の値をコピーします
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を追加します。 ビルド プロセス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
Note
コマンドを使用できるように
tsc
、TypeScript が npm を使用してグローバルに開発環境にインストールされていることを確認します。 この手順をスキップすると、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": { "Node": { "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
するフォルダーからbuildandreleasetask
「tsc」と入力します。
task.json コンポーネント
ファイルのコンポーネントの一部については、次の説明を task.json
参照してください。
プロパティ | 説明 |
---|---|
id |
タスクの一意の GUID。 |
name |
スペースのない名前。 |
friendlyName |
わかりやすい名前 (スペースを使用できます)。 |
description |
タスクの内容の詳細な説明。 |
author |
ビルドタスクまたはリリース タスクを開発するエンティティを説明する短い文字列 (例: "Microsoft Corporation")。 |
instanceNameFormat |
ビルド/リリース ステップの一覧内でのタスクの表示方法。 $(variablename) を使用して変数値を使用できます。 |
groups |
UI でのタスク プロパティの論理的なグループ化について説明します。 |
inputs |
ビルドまたはリリース タスクの実行時に使用する入力。 このタスクでは、samplestring という名前 の入力が必要です。 |
execution |
スクリプトを含む、このタスクの実行オプション。 |
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
今回は、タスクが指定され、"Hello Human!" が正しく出力されたため samplestring
、タスクは成功しました。
ヒント
さまざまなタスク ランナーの詳細と、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 フォルダーに sync-request を追加することで、このエラー
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('it should fail if tool returns 1', function(done: Mocha.Done) { this.timeout(1000); let tp = path.join(__dirname, 'failure.js'); let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); tr.run(); 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コードをコピーし、ディレクトリにhome
ファイルとしてvss-extension.json
保存します。
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"
}
}
]
}
Note
発行元を 発行元 名に変更します。 詳細については、「パブリッシャーの作成」を参照してください。
貢献
プロパティ | 説明 |
---|---|
id |
コントリビューションの識別子。 拡張機能内で一意である必要があります。 ビルド タスクまたはリリース タスクの名前と一致する必要はありません。 通常、ビルドまたはリリース タスク名はコントリビューションの ID にあります。 |
type |
コントリビューションの種類。 ms.vss-distributed-task.task である必要があります。 |
targets |
この投稿の "対象" である投稿。 ms.vss-distributed-task.tasks である必要があります。 |
properties.name |
タスクの名前。 この名前は、対応する自己完結型ビルドまたはリリース パイプライン タスクのフォルダー名と一致する必要があります。 |
ファイル
プロパティ | 説明 |
---|---|
path |
ディレクトリを基準とするファイルまたはフォルダーの home パス。 |
Note
拡張マニフェスト ファイルのプロパティや実行内容など、拡張マニフェスト ファイルの詳細については、拡張機能マニフェスト リファレンスを 参照してください。
4. 拡張機能をパッケージ化する
すべてのファイルをパッケージ化して、拡張機能を Visual Studio Marketplace に取り込みます。 すべての拡張機能は、VSIX 2.0 と互換性のある .vsix ファイルとしてパッケージ化されています。 Microsoft では、拡張機能をパッケージ化するためのクロスプラットフォーム コマンド ライン インターフェイス (CLI) を提供しています。
tfx-cli を取得したら、拡張機能のホーム ディレクトリに移動し、次のコマンドを実行します。
tfx extension create --manifest-globs vss-extension.json
Note
拡張機能または統合のバージョンは、更新ごとにインクリメントする必要があります。
既存の拡張機能を更新する場合は、マニフェストのバージョンを更新するか、コマンド ライン スイッチを --rev-version
渡します。 これにより、拡張機能の パッチ バージョン番号がインクリメントされ、新しいバージョンがマニフェストに保存されます。
更新を行うには、タスクのバージョンと拡張機能のバージョンの両方を変更する必要があります。 tfx extension create --manifest-globs vss-extension.json --rev-version
は、タスクのバージョンではなく、拡張機能のバージョンのみを更新します。 詳細については、「GitHub のビルド タスク」を参照してください。
パッケージ化された拡張機能が .vsix ファイルに含まれると、Marketplace に拡張機能を発行する準備が整います。
5. 拡張機能を公開する
拡張機能を発行するには、最初 に発行元を作成し、次に 拡張機能をアップロードして、最後に 共有します。
発行元を作成する
Microsoft の拡張機能を含むすべての拡張機能は、発行元によって提供されていると識別されます。 既存のパブリッシャーのメンバーでない場合は、作成します。
- Visual Studio Marketplace 発行ポータルに サインインします。
- 既存のパブリッシャーのメンバーでない場合は、パブリッシャーの作成を求められます。 発行元の作成を求めるメッセージが表示されない場合は、ページの下部まで下にスクロールし、[関連サイト] で [拡張機能の発行] を選択します。
- 発行元の識別子を指定します。次に例を示します
mycompany-myteam
。- この識別子は、拡張機能のマニフェスト ファイル内の
publisher
属性の値として使用されます。
- この識別子は、拡張機能のマニフェスト ファイル内の
- 発行元の表示名を指定します。次に例を示します
My Team
。
- 発行元の識別子を指定します。次に例を示します
- Marketplace パブリッシャー契約を確認し、[作成] を選択します。
発行元が定義されています。 今後のリリースでは、発行元の拡張機能を表示および管理するためのアクセス許可を付与できます。 ユーザー間で資格情報のセットを共有する必要なく、共通の発行元の下で拡張機能を公開する方が簡単で安全です。
拡張機能をアップロードする
[新しい拡張機能のアップロード] ボタンを見つけて、パッケージ化された .vsix ファイルに移動し、[アップロード] を選択します。
また、1 つの手順で拡張機能をパッケージ化して発行するのではなく
tfx extension create
、コマンド ライン インターフェイス (CLI) を使用tfx extension publish
して拡張機能をアップロードすることもできます。 必要に応じて、公開後に拡張機能を 1 つ以上のアカウントと共有するために使用--share-with
できます。tfx extension publish --manifest-globs your-manifest.json --share-with yourOrganization
個人用アクセス トークン (PAT) を作成します。
- [Marketplace (発行)]スコープを選択します。 このスコープにより、トークンは Marketplace に拡張機能を発行することのみに制限されます。
拡張機能を共有する
拡張機能をアップロードすると、Marketplace に表示されますが、誰も表示できません。 インストールしてテストできるように、組織と共有します。
拡張機能を右選択し、[共有] を選択し、組織の情報を入力します。 拡張機能にアクセスする他のアカウントと共有することもできます。
重要
公開されている拡張機能を共有するには、発行元を確認する必要があります。 詳細については、「パッケージ/発行/インストール」を参照してください。
拡張機能が Marketplace で共有されたので、それを使用するすべてのユーザーがインストールする必要があります。
6.拡張機能を Marketplace に発行するビルドおよびリリース パイプラインを作成する
Marketplace でカスタム タスクをメインするために、Azure DevOps でビルドとリリースのパイプラインを作成します。
前提条件
ソフトウェア/ツール
情報
Azure DevOps プロジェクト
Azure DevOps 拡張機能タスク拡張機能
組織に無料 の Azure DevOps 拡張機能タスク をインストールします。
パイプライン ライブラリ変数グループ
パイプラインで使用される変数を保持するパイプライン ライブラリ変数グループを作成します。 詳細については、「変数グループの追加と使用」を参照してください。 変数グループは、Azure DevOps ライブラリ タブまたは CLI から作成できます。 パイプラインでこのグループ内の変数 を使用します。 また、変数グループで次の変数を宣言します。
publisherId
: Marketplace パブリッシャーの IDextensionId
: vss-extension.json ファイルで宣言されている拡張機能の IDextensionName
: 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'
詳細については、「パイプラインをトリガーするイベントを指定する」を参照してください。
Note
各ジョブは新しいユーザー エージェントを使用し、依存関係をインストールする必要があります。
パイプライン ステージ
次のセクションは、パイプライン ステージのしくみを理解するのに役立ちます。
ステージ 1: 単体テストを実行して発行する
このステージでは、単体テストを実行し、テスト結果を Azure DevOps に発行します。
単体テストを実行するには、次の例のように、package.json ファイルにカスタム スクリプトを追加します。
"scripts": {
"testScript": "mocha ./TestFile --reporter xunit --reporter-option output=ResultsFile.xml"
},
"Use Node CLI for Azure DevOps (tfx-cli)" を追加して、tfx-cli をビルド エージェントにインストールします。
"install" コマンドを使用して "npm" タスクを追加し、package.json ファイルを含むフォルダーをターゲットにします。
"Bash" タスクを追加して、TypeScript を JavaScript にコンパイルします。
"カスタム" コマンドを使用して "npm" タスクを追加し、単体テストを含むフォルダーをターゲットにして、コマンドとして入力
testScript
します。 次の入力を使用します。- コマンド: カスタム
- package.jsonを含む作業フォルダー: /TestsDirectory
- コマンドと引数:
testScript
[テスト結果の発行] タスクを追加します。 Mocha XUnit レポーターを使用している場合は、結果の形式が "XUnit" ではなく "JUnit" であることを確認します。検索フォルダーをルート ディレクトリに設定します。 次の入力を使用します。
- テスト結果の形式: JUnit
- テスト結果ファイル: **/ResultsFile.xml
- 検索フォルダー:
$(System.DefaultWorkingDirectory)
テスト結果が発行されると、[テスト] タブの出力は次の例のようになります。
ステージ 2: 拡張機能をパッケージ化し、ビルド成果物を発行する
"Use Node CLI for Azure DevOps (tfx-cli)" を追加して、tfx-cli をビルド エージェントにインストールします。
"install" コマンドを使用して "npm" タスクを追加し、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)
- 拡張機能の可視性: 拡張機能がまだ開発中の場合は、値を private に設定します。 拡張機能をパブリックにリリースするには、値を public に設定します。
発行されたファイルをコピーする "ファイルのコピー" タスクを追加します。 次の入力を使用します。
- 内容: 成果物として発行するためにコピーされるすべてのファイル
- ターゲット フォルダー: ファイルのコピー先フォルダー
- 例: $(Build.ArtifactStagingDirectory)
"ビルド成果物の発行" を追加して、他のジョブまたはパイプラインで使用するために成果物を発行します。 次の入力を使用します。
- 発行するパス: 発行されるファイルを含むフォルダーへのパス
- 例: $(Build.ArtifactStagingDirectory)
- 成果物名: 成果物に指定された名前
- 成果物の発行場所: 今後のジョブで成果物を使用するには、[Azure Pipelines] を選択します
- 発行するパス: 発行されるファイルを含むフォルダーへのパス
ステージ 3: ビルド成果物をダウンロードして拡張機能を発行する
"Use Node CLI for Azure DevOps (tfx-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
) から、プロジェクト コレクションの管理ページに移動します。 - [拡張機能] タブで、[自分と共有されている拡張機能] グループで拡張機能を見つけて、拡張機能のリンクを選択します。
- 拡張機能をインストールします。
[拡張機能] タブが表示されない場合は、プロジェクトの管理ページではなく、https://dev.azure.com/{organization}/_admin
コントロール パネル (プロジェクト コレクション レベルの管理ページ) にいることを確認します。
[拡張機能] タブが表示されない場合、組織の拡張機能は有効になりません。 Visual Studio パートナー プログラムに参加することで、拡張機能機能に早期にアクセスできます。
Azure DevOps 拡張機能をパッケージ化して Visual Studio Marketplace に発行するには、Azure DevOps 拡張機能タスクをダウンロードできます。
よく寄せられる質問
Azure DevOps の拡張機能にカスタム ビルドタスクまたはリリース タスクを追加する方法については、よく寄せられる質問 (FAQ) を参照してください。
Q: タスクの Azure Pipelines コマンドの使用を制限するにはどうすればよいですか?
タスクによって設定される Azure Pipelines コマンドの使用と変数を制限できます。 このアクションは、タスクが実行されるカスタム スクリプトの変数/vso コマンドへの無制限のアクセスを防ぐのに役立ちます。 新しいタスク用に設定することをお勧めします。 適用するには、task.json ファイルに次のステートメントを追加する必要がある場合があります。
"restrictions": {
"commands": {
"mode": "restricted"
},
"settableVariables": {
"allowed": ["variable1", "test*"]
}
}
値が指定されているmode
場合restricted
は、タスクによって次のコマンドのみを実行できます。
logdetail
logissue
complete
setprogress
setsecret
setvariable
debug
settaskvariable
prependpath
publish
このsettableVariables
制限により、変数の許可リストを渡すことができます。変数の許可リストは、コマンドによってsetvariable
prependpath
設定されます。 また、基本的な正規表現も使用できます。 たとえば、許可リストが次 ['abc', 'test*']
の場合、設定 abc
、 test
または test1
任意の値を持つ変数として、またはパスの前に置かれた変数は成功しますが、変数プロキシを設定しようとすると警告が表示されます。 空のリストは、タスクによって変数が変更されていないことを意味します。
またはcommands
キーをsettableVariables
省略した場合、関連する制限は適用されません。
この制限機能は、2.182.1 エージェント バージョンから入手できます。
Q: キャンセルシグナルはタスクによってどのように処理されますか?
A: パイプライン エージェントは、関連する子プロセスに送信してSIGTERM
シグナルを送信SIGINT
します。 タスク ライブラリには、処理する明示的な手段はありません。 詳しくは、エージェント・ジョブの取り消しを参照してください。
Q: プロジェクト コレクションからタスクを削除するにはどうすればよいですか?
A: タスクの自動削除はサポートされていません。 自動削除は安全ではなく、そのようなタスクを既に使用している既存のパイプラインを中断します。 ただし、タスクは非推奨としてマークできます。 これを行うには、タスクのバージョンをバンプし、タスクを非推奨としてマークします。
Q: タスクを最新のノードにアップグレードするにはどうすればよいですか?
A: 最新の Node バージョンにアップグレードすることをお勧めします。 例については、ノード 16 へのタスクのアップグレードを参照してください。
関連記事
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示