Skip to content

v0.14.0 VM 検証 skill の手順を実機に合わせ、winvm exec の出力と終了コードが消えないようにする

Choose a tag to compare

@hidari hidari released this 01 Oct 08:19
· 18 commits to main since this release
9bc82e6

配布物の変更は skills/devops の 2 つの VM 検証 skill (macos-vm-verification と windows-vm-verification) だけで、ほかの skill と plugin は v0.13.0 と同じ。skill 名、登録経路、CLI のサブコマンドと引数の形は変わらない。

振る舞いが変わる点は 4 つある。winvm exec の出力や終了コードで判定している消費側は、2 つ目から 4 つ目を確かめてから pin を上げる。

  • v0.13.0 で足した「検証 VM の扱い」の手順を、実機で通る形に直した。v0.13.0 の文面では、手順 1 と 6 はスナップショットが 0 件でも見出しの行が出るので「空か」の判定が成り立たず、手順 5 は一時停止の VM と起動中の macOS の VM を止められなかった
  • winvm exec の標準出力が増えて、形が変わる。オブジェクトを出すコマンドは、これまで表とそれより後の出力が rc 0 のまま消えていたが、この版から出る。出力は exec が文字列に整えてから返すので、表の見出しの色の制御文字が無くなり、幅は 4096 になる
  • winvm exec の終了コードが 1 つの形で変わる。native コマンドが失敗したあとに return / break / continue で抜けるコマンドは、v0.13.0 では rc 0 だったが、この版からその native の終了コードになる。最後まで走るコマンドの終了コードの決まり方 (native の終了コードを優先し、cmdlet の失敗は 1) は変わらない
  • コマンドがエラーのレコードをオブジェクトとして出す形 (catch { $_ }、$Error[0]、-ErrorVariable で受けた変数) は、v0.13.0 では標準出力に出たが、この版から標準エラーへ出る。-WarningVariable で受けた警告のレコードを出すと、v0.13.0 には無かった WARNING: が付く。どちらも rc は変わらない

2>&1 などでストリームを混ぜた出力の行き先と接頭辞は、v0.13.0 と同じに保った (下の winvm.py の項)。

消費側への影響

skills/devops/macos-vm-verification と skills/devops/windows-vm-verification — ISSUE-87

  • 手順 1 と 6: スナップショットの有無を prlctl snapshot-list "<vm>" -H の出力が空かどうかで判定する。-H は VM 名の後ろに置く。前に置くと VM 名がオプションとして読まれ、rc 255 になる
  • 手順 5: prlctl list -a の状態で分岐し、stopped でなければ止める。prlctl stop は状態ごとに失敗の返し方が違うので、終了コードでは分岐しない。stopped と suspended の VM へ打つと Failed を出しながら rc 0 (suspended は --kill でも同じで、何も変わらない) で、paused の VM と起動中の macOS の VM へ素の stop を打つと rc 255 になる
  • 一時停止 (suspended と paused) なら、先に prlctl resume で running へ戻す。macOS の VM は --kill で止める。止めたら stopped になったことを確かめ、なっていなければやり直す
  • windows-vm-verification の SKILL.md の全角括弧を半角に揃えた。文面は変えていない

skills/devops/windows-vm-verification (winvm.py) — ISSUE-88

  • winvm exec が VM へ送る .ps1 の形を変えた。.ps1 は自分自身を内側として呼び直してコマンドを動かし、外側でその出力を Out-String -Stream -Width 4096 で文字列にしてから終了コードを伝える。コマンドの中の exit、return、break、continue の手前の出力と、その終了コードが残る
  • 2>&1 で出力へ混ぜた cmdlet のエラーは標準エラーへ、native の標準エラーは標準出力へ出す。3>&1 や *>&1 で混ぜた警告・詳細・デバッグには、各行に接頭辞 (WARNING: など) を付ける。どれも v0.13.0 と同じ側、同じ接頭辞になる (色の制御文字は付かない)
  • 存在しないコマンドや 1/0 のように文だけを止めるエラーの後に、コマンドの続きが走るのは v0.13.0 と同じ
  • 既知の限界の正本は winvm.py の docstring にある (ISSUE-88 の記録は配布物ではない)。v0.13.0 との違いとして効くもの:
    • native コマンドの出力も Out-String を通るので、UTF-8 として読めないバイトは置換文字になって戻せず、単独の CR は改行になり、最後に改行の無い出力には改行が足されて次の出力と同じ行につながらない。v0.13.0 は生のバイトのまま返していたので、UTF-8 以外の符号で書くプログラムの出力は、この版ではホストで読み直せない。VM の cmd が出す日本語は v0.13.0 とバイトまで一致したが、cmd 以外の native プログラムは確かめていない
    • コマンドの中から見える $MyInvocation、$PSBoundParameters、$input は呼び直しのものになる。トップレベルの Write-Error のエラーは、呼び直しの行を位置として示し、複数行で出る (v0.13.0 では 1 行。手元の pwsh で実測)
    • $ErrorView のような表示の設定は、コマンドの中で $global: を付けないと効かない
    • Format-Wide は列のあいだを幅いっぱいまで空け、表の 1 つの値は 4096 文字で切られる
  • 既知の限界のうち v0.13.0 と同じもの: コマンドが throw すると手前の表は消える (rc 1 とエラーは出る。手を加えないスクリプトでも同じ)。コマンドの先頭の param() と using 文は効かない

確かめたこと: 手順の prlctl の一連と一時停止の扱いは、macOS (Apple の仮想化) と Windows の 2 台の実機で通した。winvm exec は手元の pwsh 7.6.4 で手を加えないスクリプトと v0.13.0 の形と比べたうえで、直した winvm.py を full chain (scp、pwsh -File、後始末) で Windows VM に通した。winvm.py のテストは、仕組みを 1 つずつ外す変異 (呼び直し、成功の初期値、1 回だけ回るループ、try/catch を足す形、振り分けの段、native の除外) で、狙ったテストが赤になることを確かめた。配布経路 (pin を上げた消費側) での確認はまだ。

pin を上げたあとで確かめること:

  • Skill ツールで読み込んだ 2 つの VM 検証 skill の手順 1、5、6 が、この版の文面になっていること
  • 実際に動く winvm.py が pin した版であること。winvm をシェルの関数などで別のパスへ向けているなら、その先のファイルに WinvmInner が含まれるかで確かめる
  • その winvm.py で、VM 検証 skill の手順どおりに VM を扱ったうえで、次を打つ。<ホスト名> は ssh の設定のホスト名に置き換える
    • winvm exec --host <ホスト名> -- "Get-Item C:/Windows | Select-Object Name; Write-Output after"; echo "rc=$?": 表と after が出て rc=0。v0.13.0 では表も after も出ないので、pin が上がったことをこれで見分けられる
    • winvm exec --host <ホスト名> -- "cmd /c exit 3"; echo "rc=$?": rc=3
    • winvm exec --host <ホスト名> -- "Get-Item C:/nope 2>&1; Write-Output after" 2>/dev/null; echo "rc=$?": after だけが出て rc=0 (エラーは標準エラーへ行くので出ない)。v0.13.0 でも同じになるので、振り分けが壊れていないことの確認であって、版の見分けには使えない

同伴 (配布物ではない): ISSUE-87 と ISSUE-88 の記録 (実機の測定値と、作り直しの経緯)。

commit range: v0.13.0..9bc82e6 (3 commits)