カスタム パイプライン タスク拡張機能を追加する

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-libNode を実行する必要があります。 次のコマンドに従って、task.json ファイルを更新します。

"execution": {
   "Node16": {
     "target": "index.js"
   }
 }

1. カスタム タスクを作成する

この手順のすべての部分をフォルダー内で buildandreleasetask 実行します。

Note

このチュートリアルの例では、PowerShell で Windows を使用します。 すべてのプラットフォームで汎用にしましたが、環境変数を取得するための構文は異なります。 Mac または Linux を使用している場合は、$env:<var>=<val>export <var>=<val>

タスク スキャフォールディングの作成

  1. タスクのフォルダー構造を作成し、必要なライブラリと依存関係をインストールします。

  2. PowerShell コマンド ウィンドウを開き、フォルダー buildandreleasetask に移動して、次のコマンドを実行します。

    npm init --yes
    

    npm init はファイルを作成します package.json 。 すべての既定npm initのオプションを--yes受け入れるパラメーターを追加しました。

    ヒント

    タスク フォルダーにノード モジュールが含まれると想定されているため、エージェントは必要なモジュールを自動的にインストールしません。 これを軽減するには、次の値をコピーしますnode_modulesbuildandreleasetask。 タスクが大きくなると、VSIX ファイルのサイズ制限 (50 MB (メガバイト)) を超えるのは簡単です。 ノード フォルダーをコピーする前に、実行 npm install --production するか、スクリプト npm prune --productionを記述してすべてをビルドしてパックすることができます。

  3. ライブラリに追加 azure-pipelines-task-lib します。

    npm install azure-pipelines-task-lib --save
    
  4. 外部の依存関係に対して TypeScript 型指定がインストールされていることを確認します。

    npm install @types/node --save-dev
    npm install @types/q --save-dev
    
  5. ファイルを .gitignore 作成し、node_modulesを追加します。 ビルド プロセスnpm installtypings installでは、毎回node_modulesをビルドし、チェックする必要がないようにする必要があります。

    echo node_modules > .gitignore
    
  6. 開発の依存関係として Mocha をインストールします。

    npm install mocha --save-dev -g
    npm install sync-request --save-dev
    npm install @types/mocha --save-dev
    
  7. 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

  8. コンパイラ オプションを作成 tsconfig.json します。 このファイルにより、TypeScript ファイルが JavaScript ファイルにコンパイルされます。

    tsc --init --target es2022
    

タスクを作成する

スキャフォールディングが完了したので、カスタム タスクを作成できます。

  1. フォルダーに task.json ファイルを buildandreleasetask 作成します。 このファイルは task.json ビルド/リリース タスクを記述し、ビルド/リリース システムが構成オプションをユーザーにレンダリングし、ビルド/リリース時に実行するスクリプトを把握するために使用します。

  2. 次のコードをコピーし、タスクの {{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"
         }
     }
     }
    
  3. 次のコードを 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();
    
  4. ファイルをコンパイルindex.jsindex.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 コマンドに関するタスクに適用される制限と、変数タスクを設定できます。 新しいタスクには制限モードを指定することをお勧めします。

Note

PowerShell で id 次のコマンドを使用して作成します。

(New-Guid).Guid

詳細については、ビルド/リリース タスクリファレンスを参照してください

タスクを実行する

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. タスク スクリプトを単体テストする

単体テストを実行して、呼び出す外部ツールではなく、タスク スクリプトをすばやくテストします。 成功パスと失敗パスの両方のすべての側面をテストします。

  1. テスト ツールをインストールします。 この手順では、テスト ドライバーとして Mocha を使用します。

    npm install mocha --save-dev -g
    npm install sync-request --save-dev
    npm install @types/mocha --save-dev
    
  2. 次の内容の 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を回避できます。

  3. 次の内容を 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();
    

    成功テストでは、適切な入力でエラーや警告なしで成功し、正しい出力が返されることを検証します。

  4. 次の成功テストの例を _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
        });
    });
    
  5. テスト ディレクトリに、 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();
    

    エラー テストでは、ツールが不適切または不完全な入力を取得すると、役に立つ出力で予期された方法で失敗することを検証します。

  6. 次のコードを _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();
    });
    
  7. テストを実行します。

    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 の拡張機能を含むすべての拡張機能は、発行元によって提供されていると識別されます。 既存のパブリッシャーのメンバーでない場合は、作成します。

  1. Visual Studio Marketplace 発行ポータルに サインインします
  2. 既存のパブリッシャーのメンバーでない場合は、パブリッシャーの作成を求められます。 発行元の作成を求めるメッセージが表示されない場合は、ページの下部まで下にスクロールし、[関連サイト] で [拡張機能の発行] を選択します。
    • 発行元の識別子を指定します。次に例を示します mycompany-myteam
      • この識別子は、拡張機能のマニフェスト ファイル内の publisher 属性の値として使用されます。
    • 発行元の表示名を指定します。次に例を示します My Team
  3. Marketplace パブリッシャー契約を確認し、[作成] を選択します

発行元が定義されています。 今後のリリースでは、発行元の拡張機能を表示および管理するためのアクセス許可を付与できます。 ユーザー間で資格情報のセットを共有する必要なく、共通の発行元の下で拡張機能を公開する方が簡単で安全です。

拡張機能をアップロードする

[新しい拡張機能のアップロード] ボタンを見つけて、パッケージ化された .vsix ファイルに移動し、[アップロード] を選択します

  1. また、1 つの手順で拡張機能をパッケージ化して発行するのではなくtfx extension create、コマンド ライン インターフェイス (CLI) を使用tfx extension publishして拡張機能をアップロードすることもできます。 必要に応じて、公開後に拡張機能を 1 つ以上のアカウントと共有するために使用 --share-with できます。

    tfx extension publish --manifest-globs your-manifest.json --share-with yourOrganization
    
  2. 個人用アクセス トークン (PAT) を作成します。

    • [Marketplace (発行)]スコープを選択します。 このスコープにより、トークンは Marketplace に拡張機能を発行することのみに制限されます。

拡張機能を共有する

拡張機能をアップロードすると、Marketplace に表示されますが、誰も表示できません。 インストールしてテストできるように、組織と共有します。

拡張機能を右選択し、[共有] を選択し、組織の情報を入力します。 拡張機能にアクセスする他のアカウントと共有することもできます。

重要

公開されている拡張機能を共有するには、発行元を確認する必要があります。 詳細については、「パッケージ/発行/インストール」を参照してください

拡張機能が Marketplace で共有されたので、それを使用するすべてのユーザーがインストールする必要があります。

6.拡張機能を Marketplace に発行するビルドおよびリリース パイプラインを作成する

Marketplace でカスタム タスクをメインするために、Azure DevOps でビルドとリリースのパイプラインを作成します。

前提条件

ソフトウェア/ツール

情報

Azure DevOps プロジェクト

Azure DevOps 拡張機能タスク拡張機能

組織に無料 の Azure DevOps 拡張機能タスク をインストールします。

パイプライン ライブラリ変数グループ

パイプラインで使用される変数を保持するパイプライン ライブラリ変数グループを作成します。 詳細については、「変数グループの追加と使用」を参照してください。 変数グループは、Azure DevOps ライブラリ タブまたは CLI から作成できます。 パイプラインでこのグループ内の変数 を使用します。 また、変数グループで次の変数を宣言します。

  • publisherId: Marketplace パブリッシャーの 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'

詳細については、「パイプラインをトリガーするイベントを指定する」を参照してください

Note

各ジョブは新しいユーザー エージェントを使用し、依存関係をインストールする必要があります。

パイプライン ステージ

次のセクションは、パイプライン ステージのしくみを理解するのに役立ちます。

ステージ 1: 単体テストを実行して発行する

このステージでは、単体テストを実行し、テスト結果を Azure DevOps に発行します。

単体テストを実行するには、次の例のように、package.json ファイルにカスタム スクリプトを追加します。

"scripts": {
    "testScript": "mocha ./TestFile --reporter xunit --reporter-option output=ResultsFile.xml"
},
  1. "Use Node CLI for Azure DevOps (tfx-cli)" を追加して、tfx-cli をビルド エージェントにインストールします。

  2. "install" コマンドを使用して "npm" タスクを追加し、package.json ファイルを含むフォルダーをターゲットにします。

  3. "Bash" タスクを追加して、TypeScript を JavaScript にコンパイルします。

  4. "カスタム" コマンドを使用して "npm" タスクを追加し、単体テストを含むフォルダーをターゲットにして、コマンドとして入力 testScript します。 次の入力を使用します。

    • コマンド: カスタム
    • package.jsonを含む作業フォルダー: /TestsDirectory
    • コマンドと引数: testScript
  5. [テスト結果の発行] タスクを追加します。 Mocha XUnit レポーターを使用している場合は、結果の形式が "XUnit" ではなく "JUnit" であることを確認します。検索フォルダーをルート ディレクトリに設定します。 次の入力を使用します。

    • テスト結果の形式: JUnit
    • テスト結果ファイル: **/ResultsFile.xml
    • 検索フォルダー: $(System.DefaultWorkingDirectory)

    テスト結果が発行されると、[テスト] タブの出力は次の例のようになります。

    テスト結果の例のスクリーンショット。

ステージ 2: 拡張機能をパッケージ化し、ビルド成果物を発行する

  1. "Use Node CLI for Azure DevOps (tfx-cli)" を追加して、tfx-cli をビルド エージェントにインストールします。

  2. "install" コマンドを使用して "npm" タスクを追加し、package.json ファイルを含むフォルダーをターゲットにします。

  3. "Bash" タスクを追加して、TypeScript を JavaScript にコンパイルします。

  4. "拡張機能のバージョンのクエリ" タスクを追加して、既存の拡張機能のバージョンに対してクエリを実行します。 次の入力を使用します。

    • 接続: Visual Studio Marketplace
    • Visual Studio Marketplace (サービス接続): サービス接続
    • 発行元 ID: Visual Studio Marketplace パブリッシャーの ID
    • 拡張子ID:vss-extension.jsonファイル内の拡張子のID
    • バージョンを増やす: パッチ
    • 出力変数: Task.Extension.Version
  5. マニフェスト 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 に設定します。
  6. 発行されたファイルをコピーする "ファイルのコピー" タスクを追加します。 次の入力を使用します。

    • 内容: 成果物として発行するためにコピーされるすべてのファイル
    • ターゲット フォルダー: ファイルのコピー先フォルダー
      • 例: $(Build.ArtifactStagingDirectory)
  7. "ビルド成果物の発行" を追加して、他のジョブまたはパイプラインで使用するために成果物を発行します。 次の入力を使用します。

    • 発行するパス: 発行されるファイルを含むフォルダーへのパス
      • 例: $(Build.ArtifactStagingDirectory)
    • 成果物名: 成果物に指定された名前
    • 成果物の発行場所: 今後のジョブで成果物を使用するには、[Azure Pipelines] を選択します

ステージ 3: ビルド成果物をダウンロードして拡張機能を発行する

  1. "Use Node CLI for Azure DevOps (tfx-cli)" を追加して、tfx-cli をビルド エージェントにインストールします。

  2. "ビルド成果物のダウンロード" タスクを追加して、成果物を新しいジョブにダウンロードします。 次の入力を使用します。

    • 生成された成果物のダウンロード: 同じパイプラインから新しいジョブで成果物をダウンロードする場合は、[現在のビルド] を選択します。新しいパイプラインでダウンロードする場合は、[特定のビルド] を選択します。
    • ダウンロードの種類: [特定の成果物] を選択して、発行されたすべてのファイルをダウンロードします。
    • 成果物名: 発行された成果物の名前。
    • 宛先ディレクトリ: ファイルをダウンロードするフォルダー。
  3. 必要な最後のタスクは、"拡張機能の発行" タスクです。 次の入力を使用します。

    • 接続: Visual Studio Marketplace
    • Visual Studio Marketplace 接続: ServiceConnection
    • 入力ファイルの種類: VSIX ファイル
    • VSIX ファイル: /Publisher.*.vsix
    • 発行元 ID: Visual Studio Marketplace パブリッシャーの ID
    • 拡張子ID:vss-extension.jsonファイル内の拡張子のID
    • 拡張子名: vss-extension.json ファイル内の拡張機能の名前
    • 拡張機能の可視性: プライベートまたはパブリック

省略可能: 拡張機能をインストールしてテストする

いくつかの手順で共有されている拡張機能をインストールします。

  1. 組織のコントロール パネル (https://dev.azure.com/{organization}/_admin) から、プロジェクト コレクションの管理ページに移動します。
  2. [拡張機能] タブで、[自分と共有されている拡張機能] グループで拡張機能を見つけて、拡張機能のリンクを選択します。
  3. 拡張機能をインストールします。

[拡張機能] タブが表示されない場合は、プロジェクトの管理ページではなく、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制限により、変数の許可リストを渡すことができます。変数の許可リストは、コマンドによってsetvariableprependpath設定されます。 また、基本的な正規表現も使用できます。 たとえば、許可リストが次 ['abc', 'test*']の場合、設定 abctestまたは test1 任意の値を持つ変数として、またはパスの前に置かれた変数は成功しますが、変数プロキシを設定しようとすると警告が表示されます。 空のリストは、タスクによって変数が変更されていないことを意味します。

またはcommandsキーをsettableVariables省略した場合、関連する制限は適用されません。

この制限機能は、2.182.1 エージェント バージョンから入手できます。

Q: キャンセルシグナルはタスクによってどのように処理されますか?

A: パイプライン エージェントは、関連する子プロセスに送信してSIGTERMシグナルを送信SIGINTします。 タスク ライブラリには、処理する明示的な手段はありません。 詳しくは、エージェント・ジョブの取り消しを参照してください

Q: プロジェクト コレクションからタスクを削除するにはどうすればよいですか?

A: タスクの自動削除はサポートされていません。 自動削除は安全ではなく、そのようなタスクを既に使用している既存のパイプラインを中断します。 ただし、タスクは非推奨としてマークできます。 これを行うには、タスクのバージョンをバンプし、タスクを非推奨としてマークします。

Q: タスクを最新のノードにアップグレードするにはどうすればよいですか?

A: 最新の Node バージョンアップグレードすることをお勧めします。 例については、ノード 16 へのタスクのアップグレードを参照してください