Azure Pipelines task library v272/v273解説:実装・移行・自動化が楽になるポイント

2026年4月20日時点で確認すべきポイントは、Azure Pipelines task library 周辺の更新が「単発のバグ修正」ではなく、タスク実装・Nodeランタイム移行・依存関係更新・セキュリティ修正をまとめて進める波になっていることです。特に Coordinated Azure Pipelines Tasks v272/v273 release wave lands として見ると、開発者やPlatform Engineer、DevOpsチームが楽になるのは、カスタムタスクの実装基盤を新しい azure-pipelines-task-lib、Node 20/24、事前ツール準備、L0テスト、自動パッケージングへ寄せやすくなる点です。

v272では複数のAzure系タスクで task-lib や azure-arm-rest の共通パッケージ更新、azure-pipelines-task-lib 5.2.8への更新、DownloadPackage/NuGetToolInstallerのL0テスト強化などが入りました。v273では、Node 24対応、@azure/msal-browser 関連の脆弱性対応、AzureCLI V1など一部タスクの非推奨化、AzureCLI V3の改善、SQL DACPAC系タスクのセキュリティ修正が目立ちます。つまり、既存のAzure Pipelinesタスク利用者だけでなく、独自タスクを作っているチームも「今の実装を棚卸しするタイミング」と考えるべき更新です。(GitHub)

目次

Azure Pipelines task library のv272/v273更新は何が重要なのか

Azure Pipelines task library を使う開発者にとって、v272/v273の本質は「Microsoftの組み込みタスクが、依存関係・ランタイム・テスト・セキュリティをまとめて現代化している」ことです。

Azure Pipelinesのタスクは、YAML上では AzureCLI@2 や PublishTestResults@2 のように短く見えます。しかし内部では、Node.jsランナー、task.json、TypeScript/JavaScript実装、azure-pipelines-task-lib、共通パッケージ、サービス接続、ツールダウンロード処理などが組み合わさっています。

今回のリリース波を実務目線で読むと、次の4点が重要です。

観点v272/v273で見える動き開発者にとって楽になること
ライブラリ更新複数タスクで task-lib や共通パッケージを更新カスタムタスクも更新基準を決めやすい
NodeランタイムNode 24対応タスクが増加将来のランナー移行を前提にテストしやすい
セキュリティMSAL、basic-ftp、Invoke-Expression関連の修正依存関係監査・シェル注入対策の見直しポイントが明確になる
自動化品質L0テスト、事前ツールインストール、バージョン解析改善CIで壊れやすい箇所を先に検出しやすい

重要なのは、「組み込みタスクが更新されたから安心」で終わらせないことです。カスタムタスクや社内拡張機能を運用している場合、同じ設計思想を自分たちのタスクにも取り込む必要があります。

v272で注目すべき変更:task-lib 5.2.8と共通パッケージ更新

v272では、AzureCLI V2/V3、AzureKeyVault V2、AzurePowerShell V4/V5などで task-lib 5.2.8への更新が行われています。また、Azure App Service、Azure Function、ARMテンプレートデプロイ、JenkinsDownloadArtifacts、KubeloginInstallerなどでは task-lib と azure-arm-rest の共通パッケージ更新がまとめて入っています。(GitHub)

これは、Azure Pipelines task library を使う開発者にとって「自分のタスクも依存関係を固定したまま放置していないか」を確認するサインです。

カスタムタスクで確認すべきpackage.json

カスタムタスクをTypeScriptで実装している場合、まず確認するのはタスクフォルダ内の package.json です。

{
  "dependencies": {
    "azure-pipelines-task-lib": "5.2.8"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "typescript": "^4.6.3"
  }
}

v272で参照されている 5.2.8 を基準にする場合は、単に package.json を書き換えるだけでは不十分です。Azure Pipelinesのカスタムタスクは、実行時にタスクフォルダ内の node_modules を参照します。Microsoft Learnでも、タスクフォルダに node_modules を含めること、VSIXサイズを抑えるために本番依存関係だけを残すことが案内されています。(Microsoft Learn)

実務では次の順序で進めると安全です。

cd tasks/MyCustomTask

npm install [email protected] --save
npm install
npm run build
npm test

npm prune --omit=dev

失敗しやすいのは、リポジトリ直下の依存関係だけ更新して、実際にVSIXへ同梱されるタスクフォルダ側の node_modules を更新し忘れるケースです。この場合、ローカルテストでは新しいライブラリで動いているように見えても、Azure DevOpsに配布されたタスクは古い依存関係で動き続けます。

v273で注目すべき変更:Node 24移行とセキュリティ修正

v273では、AppCenterDistribute V3、DownloadBuildArtifacts V0、AzureSpringCloud V0などでNode 24対応が進んでいます。実際のタスク定義を見ると、Node16、Node20_1、Node24 のように複数の実行ハンドラーを並べ、対応エージェントに応じて実行できる形になっています。(GitHub)

Azure Pipelines Agentは、2026年1月以降Node.js 24を含む方針が示されており、拡張機能やカスタムタスクの作者にはNode.js 24での更新・テストが求められています。公式ドキュメント上では、Node 24、20、16、10、6のサポート・削除時期も整理されています。(Microsoft Learn)

task.jsonはNode 20/24を前提に見直す

新規のカスタムタスクであれば、まずはMicrosoft Learnで示されている Node20_1 を基本に設計し、Node 24対応を進める環境では Node24 でもテストします。(Microsoft Learn)

{
  "execution": {
    "Node20_1": {
      "target": "index.js",
      "argumentFormat": ""
    },
    "Node24": {
      "target": "index.js",
      "argumentFormat": ""
    }
  }
}

Azure DevOps Serverや古いセルフホストエージェントを使う組織では、古いNodeハンドラーを残す判断もあります。ただし、Node 6/10/16へ依存し続ける設計は、将来的な警告や実行失敗の原因になります。互換性のために残す場合でも、「いつ削除するか」をロードマップに入れておくべきです。

Node移行で壊れやすいポイント

Node 24対応は、task.json に行を追加するだけでは終わりません。次のようなコードは、ランタイム更新時に問題が出やすい箇所です。

壊れやすい箇所例対策
古い依存関係古いHTTPクライアント、古い認証ライブラリlockfileを更新し、npm audit と実行テストを両方行う
暗黙のCommonJS前提ESM対応パッケージとの混在ビルド後の index.js を実エージェントで確認する
外部コマンド実行文字列連結でCLI引数を作るToolRunner.arg() で配列として渡す
ファイルパス処理Windowsだけで通る区切り文字path.join() とOS別テストを使う
環境変数依存process.env を直接読むだけtask-lib の入力・変数APIを優先する

task-lib実装で楽になるポイント:入力、変数、結果処理を標準化できる

Azure Pipelines task library の価値は、単に「入力を読むライブラリ」ではありません。タスク入力、パイプライン変数、サービス接続、ツール実行、ログ、タスク結果、シークレット処理をAzure Pipelinesの作法に合わせて扱える点にあります。

たとえば、次のように getPathInputRequired、getBoolInput、getVariable、setResult を使うと、パイプライン上の入力・変数・失敗結果を一貫して扱えます。task-libのAPIドキュメントでも、入力取得、変数取得、ToolRunner、setResult などが整理されています。(GitHub)

import tl = require('azure-pipelines-task-lib/task');

async function run(): Promise<void> {
  try {
    const workingDirectory = tl.getPathInputRequired('workingDirectory', true);
    const failOnStderr = tl.getBoolInput('failOnStderr', false);

    const retryDetection =
      tl.getVariable('MYTASK_RETRY_DETECTION') === 'true' ||
      process.env.MYTASK_RETRY_DETECTION === 'true';

    tl.debug(`workingDirectory=${workingDirectory}`);
    tl.debug(`retryDetection=${retryDetection}`);

    // ここに実処理を置く
    tl.setResult(tl.TaskResult.Succeeded, 'Task completed');
  } catch (err: any) {
    tl.setResult(tl.TaskResult.Failed, err.message);
  }
}

run();

v272では PublishTestResults でリトライ検出フラグをパイプライン変数または環境変数から読む変更も入っています。これは、カスタムタスクでも参考になる設計です。設定をコード内に固定せず、パイプライン変数で切り替えられるようにすると、グローバルに展開するチームでも段階的に機能を有効化できます。(GitHub)

入力値は「必須」「任意」「検証あり」を分ける

実務で多い失敗は、すべての入力を getInput() で読み、後から文字列チェックを散らばらせる実装です。保守しやすいタスクでは、最初に入力を分類します。

const sourcePath = tl.getPathInputRequired('sourcePath', true);
const outputPath = tl.getPathInputRequired('outputPath', false);
const dryRun = tl.getBoolInput('dryRun', false);
const tags = tl.getDelimitedInput('tags', ',', false);

このように書くと、必須入力の不足、ファイルパスの存在チェック、真偽値変換、リスト入力の分割をタスク開始時にまとめて扱えます。エラー時もAzure Pipelinesのログに自然な形で出るため、利用者が原因を見つけやすくなります。

CLI実行はToolRunnerで安全にする

v273では、AzureCLI V3で az version のstdoutが空の場合のフォールバックや、Azure DevOps CLI拡張機能をwheelファイルからインストールするサポートが入りました。これは、閉域網やミラー環境でAzure CLIを使うチームにとって重要です。(GitHub)

カスタムタスクでも、CLI実行は文字列連結ではなく ToolRunner を使うべきです。

import tl = require('azure-pipelines-task-lib/task');

async function installAzureDevOpsExtensionFromWheel(wheelPath: string): Promise<void> {
  const az = tl.which('az', true);

  await tl.tool(az)
    .arg(['extension', 'add', '--source', wheelPath, '--yes'])
    .exec({
      failOnStdErr: false,
      ignoreReturnCode: false
    });
}

避けたい実装は次のようなものです。

// 避けたい例:入力値が混ざるとコマンドインジェクションの余地がある
await tl.exec('bash', `-c "az extension add --source ${wheelPath}"`);

ToolRunner.arg() に配列で渡すと、引数の境界が明確になります。ファイル名にスペースが含まれる場合や、ユーザー入力が混ざる場合でも壊れにくくなります。

事前ツールインストールでパイプラインの失敗箇所を前倒しできる

v272ではUniversalPackages V0でArtifactToolのインストールを事前実行ステップに移す変更、v273ではUniversalPackages V1でAgentToolのインストールをpre-executionへ移す変更が入っています。(GitHub)

これは地味ですが、DevOps運用ではかなり重要です。ツールのダウンロードや検証を本処理の途中で行うと、デプロイ直前や成果物操作中に失敗します。事前にツール準備を済ませれば、ネットワーク、権限、キャッシュ、バージョン不一致の問題を早い段階で検出できます。

カスタムタスクでも、次の順序を意識すると安定します。

順序やること目的
1入力値を検証する必須値不足・パス誤りを早期発見
2必要なツールの存在を確認するCLI未インストールを早期発見
3ツールをキャッシュまたは取得する実処理中のダウンロード失敗を減らす
4バージョンをログに出す障害調査をしやすくする
5実処理を開始する本処理の失敗原因を絞り込む

たとえば、外部CLIを使うタスクでは次のように「準備」と「実行」を分けます。

import tl = require('azure-pipelines-task-lib/task');

async function resolveTool(): Promise<string> {
  const toolPath = tl.which('mytool', false);

  if (toolPath) {
    tl.debug(`mytool found: ${toolPath}`);
    return toolPath;
  }

  throw new Error('mytool is not installed. Install it before running this task.');
}

async function run(): Promise<void> {
  try {
    const mytool = await resolveTool();

    await tl.tool(mytool)
      .arg(['--version'])
      .exec();

    // 実処理
    await tl.tool(mytool)
      .arg(['deploy', '--config', 'deploy.json'])
      .exec();

    tl.setResult(tl.TaskResult.Succeeded, 'Deployment completed');
  } catch (err: any) {
    tl.setResult(tl.TaskResult.Failed, err.message);
  }
}

run();

閉域網やプロキシ環境では、タスク内で毎回インターネットからツールを取得する設計は避けた方が安全です。Azure CLI拡張機能のwheelファイル対応のように、事前に成果物として持ち込める構成にすると、再現性が上がります。

セキュリティ面で見るv273:依存関係更新だけでなく実装パターンを見直す

v273では、@azure/msal-browser 関連の脆弱性対応、FtpUpload V2の basic-ftp 更新、PowerShellOnTargetMachinesのセキュリティ修正、SQL DACPAC系タスクで Invoke-Expression 利用に関するセキュリティ修正が入っています。(GitHub)

ここから読み取れるのは、依存関係の更新だけでなく、タスク実装そのものの安全性を見直す必要があるということです。

カスタムタスクで確認すべきセキュリティ項目

確認項目危険な状態改善策
シークレット処理console.log() でトークンを出すtl.setSecret() を使い、ログ出力しない
コマンド実行入力値を文字列連結して実行ToolRunner.arg() で引数配列化する
変数設定任意の変数名を setVariable できるtask.json の restrictions で許可範囲を絞る
依存関係lockfileが古い、監査していないnpm audit、依存更新、実行テストをセットで行う
PowerShellInvoke-Expression にユーザー入力を渡す明示的な引数渡し、許可リスト、エスケープを使う

Microsoft Learnでは、本番タスクに対してコマンドや設定可能な変数を制限する restrictions の利用も案内されています。(Microsoft Learn)

{
  "restrictions": {
    "commands": {
      "mode": "restricted"
    },
    "settableVariables": {
      "allowed": [
        "MYTASK_*"
      ]
    }
  }
}

社内向けタスクでも、「社内だから安全」と考えない方がよいです。パイプライン入力は、ブランチ、テンプレート、変数グループ、サービス接続、PR経由の変更など、複数の経路から影響を受けます。特にグローバルチームで使うタスクは、最初から最小権限・入力検証・ログマスクを前提にします。

非推奨タスクへの対応:AzureCLI@1を使い続けていないか確認する

v273では、AzureCLI V1、DownloadGitHubNpmPackage V1、DownloadGitHubNugetPackage V1の非推奨化が含まれています。(GitHub)

YAMLパイプラインではタスクのメジャーバージョンを @ で指定します。Microsoft Learnでも、マイナーバージョンは通常自動更新される一方、新しいメジャーバージョンへは手動変更が必要だと説明されています。(Microsoft Learn)

まず、リポジトリ全体を検索します。

grep -R "AzureCLI@1" .
grep -R "DownloadGitHubNpmPackage@1" .
grep -R "DownloadGitHubNugetPackage@1" .

AzureCLIを使っている場合は、AzureCLI@2 または AzureCLI@3 への移行を検討します。ただし、単純に番号を変える前に次を確認してください。

確認項目見るべきポイント
認証方式サービス接続、Managed Identity、サービスプリンシパルの扱い
スクリプト種別Bash、PowerShell、PowerShell Coreの違い
Azure CLI拡張機能オンライン取得か、wheelファイルなどの事前配置か
エージェントMicrosoft-hostedか、セルフホストか
ログトークンや接続情報が出力されていないか

特にAzureCLI V3の改善は、CLI拡張機能を制御したいチームに向いています。グローバル企業や規制業界では、エージェントが自由に外部ネットワークへ出られないことがあります。その場合、必要なwheelファイルを成果物として配布し、タスク内でインストールする設計が現実的です。

L0テストを導入すると移行が怖くなくなる

v272では、DownloadPackage V1やNuGetToolInstaller V0/V1にL0 functional coverageが追加されています。(GitHub)

L0テストは、Azure DevOpsサーバーや実エージェントに依存しすぎず、タスクの基本動作を短時間で検証するテストです。カスタムタスクでは、azure-pipelines-task-lib/mock-run と mock-test を使い、入力、環境変数、ツール応答、失敗時の結果をテストします。Microsoft Learnでも、タスクフォルダ内に tests を作成し、TaskMockRunner や MockTestRunner を使う流れが紹介されています。(Microsoft Learn)

最小構成のテスト観点は次の通りです。

テスト何を確認するか
正常系必須入力があると成功する
入力不足必須入力がないと失敗する
CLI失敗外部コマンドの終了コードを正しく扱う
パス違い存在しないファイルで失敗する
変数切り替えパイプライン変数・環境変数で動作が変わる
ログシークレットが出力されない

Node 20/24移行では、テストマトリクスも重要です。

trigger:
- main

pool:
  vmImage: ubuntu-latest

strategy:
  matrix:
    node20:
      nodeVersion: '20.x'
    node24:
      nodeVersion: '24.x'

steps:
- task: UseNode@1
  inputs:
    version: $(nodeVersion)
  displayName: 'Use Node.js $(nodeVersion)'

- script: |
    npm ci
    npm run build
    npm test
  workingDirectory: tasks/MyCustomTask
  displayName: 'Build and test custom task'

この段階で失敗するなら、Azure DevOpsにVSIXを配布する前に直せます。逆に、L0テストがない状態でNodeハンドラーや依存関係だけを更新すると、利用者の本番パイプラインで初めて壊れる可能性があります。

VSIX配布ではtask.jsonとvss-extension.jsonの両方を更新する

カスタムタスクをAzure DevOps拡張機能として配布している場合、更新時に忘れやすいのがバージョン管理です。

Microsoft Learnでは、拡張機能のバージョンは vss-extension.json、タスクのバージョンは task.json で管理し、変更を反映するには両方の更新が必要だと説明されています。(Microsoft Learn)

{
  "version": {
    "Major": 1,
    "Minor": 4,
    "Patch": 0
  }
}
{
  "version": "1.4.0"
}

実務では、次のルールにすると混乱が減ります。

変更内容task.jsonvss-extension.json理由
バグ修正Patch更新Patch更新利用者に修正版を配布する
後方互換の機能追加Minor更新Minor更新入力や出力が増える
入力名変更・削除Major更新Major更新既存YAMLが壊れる可能性がある
依存関係更新のみPatchまたはMinor更新PatchまたはMinor更新配布物を明確に更新する

task.json だけ更新して vss-extension.json を忘れる、またはその逆を行うと、Azure DevOps上で期待したバージョンが反映されないことがあります。配布パイプラインで両方のバージョンを検査するスクリプトを入れておくと安全です。

v272/v273を受けた移行判断:すぐ対応すべきチーム、様子を見るチーム

すべてのチームが同じ速度で対応する必要はありません。影響範囲で優先度を分けます。

チームの状態優先度取るべき行動
カスタムタスクを公開・社内配布している高task-lib、Node 20/24、L0テスト、VSIX配布を見直す
AzureCLI@1など非推奨タスクを使っている高代替タスクへ移行し、認証・スクリプト差分を検証する
セルフホストエージェントを運用している高エージェント内のNodeランナー、agentバージョン、外部ツール取得経路を確認する
Microsoft-hosted agentで組み込みタスクだけ使う中パイプラインログの警告とタスクメジャーバージョンを棚卸しする
閉域網・規制環境で運用している高CLI拡張機能やツールを成果物として持ち込む方式に寄せる
小規模な検証環境のみ低〜中まずNode 24テストと依存関係監査を追加する

特にセルフホストエージェントでは、Hosted Agentと同じ前提で考えないことが重要です。新しいNodeハンドラーがタスク側にあっても、エージェント側に対応ランナーがなければ実行できません。古いAzure DevOps Serverを使っている場合も、対応状況を個別に確認してください。

実装・移行チェックリスト

最後に、Coordinated Azure Pipelines Tasks v272/v273 release wave lands を受けて、開発者が次に取るべき行動をチェックリストにまとめます。

既存パイプライン利用者向け

grep -R "AzureCLI@1" .
grep -R "DownloadGitHubNpmPackage@1" .
grep -R "DownloadGitHubNugetPackage@1" .
grep -R "Node10" .
grep -R "Node16" .

確認する項目は次の通りです。

  • 非推奨タスクを使っていないか
  • 古いNodeランナーに依存するMarketplaceタスクがないか
  • パイプラインログにNode EOL警告が出ていないか
  • Azure CLI拡張機能を毎回インターネットから取得していないか
  • セルフホストエージェントのNodeランナーが古くないか

カスタムタスク開発者向け

cd tasks/MyCustomTask

npm install [email protected] --save
npm install
npm run build
npm test
npm audit --omit=dev

あわせて、次の変更を検討します。

  • task.json に Node20_1 と Node24 の実行ハンドラーを追加する
  • 古いNodeハンドラーを残す場合は削除予定を決める
  • ToolRunner を使い、CLI引数を文字列連結しない
  • restrictions で設定可能な変数を制限する
  • シークレットをログに出さない
  • L0テストをNode 20/24の両方で実行する
  • task.json と vss-extension.json のバージョン更新を自動チェックする

DevOpsチーム向け

移行は一気に全パイプラインへ適用せず、次の順序で進めると失敗を抑えられます。

フェーズやること成功条件
棚卸し古いタスク、古いNode、非推奨タスクを検索影響パイプラインが一覧化されている
検証代表パイプラインでNode 20/24と新タスクを試すログ警告・失敗が解消されている
カナリア一部プロジェクトに先行適用本番相当のジョブが安定している
展開テンプレートや共通YAMLへ反映チーム横断で同じ設定になる
監視失敗率、警告、実行時間を確認更新前より不安定になっていない

v272/v273の更新は、Azure Pipelines task libraryを使う開発者にとって、単なる依存関係更新ではありません。Node 24時代に向けたタスク実装、セキュリティ修正、CLI実行の安全化、事前ツール準備、L0テスト、自動配布を見直すよい機会です。

次にやるべきことは明確です。まずリポジトリ内の古いタスク指定とカスタムタスクの package.json、task.json を確認してください。そのうえで、Node 20/24のテストマトリクスを追加し、VSIX配布まで含めた更新フローを自動化します。ここまで整えると、今後のAzure Pipelinesタスク更新にも追従しやすくなります。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次