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、依存更新、実行テストをセットで行う |
| PowerShell | Invoke-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.json | vss-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タスク更新にも追従しやすくなります。

コメント