PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと
Upcoming SlideShare
Loading in...5
×
 

PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

on

  • 781 views

 

Statistics

Views

Total Views
781
Views on SlideShare
692
Embed Views
89

Actions

Likes
7
Downloads
5
Comments
0

2 Embeds 89

https://twitter.com 84
http://www.slideee.com 5

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと Presentation Transcript

  • PowerShellでOne-Get & Chocolateyパッケージを 作るときに気を付ける10のこと 第3回 PowerShell勉強会 2014/07/12 @oota_ken
  • アジェンダ OneGetとChocolateyとは? Chocolateyのパッケージの作り方 Chocolateyパッケージを作るときの10の地雷
  • OneGetとChocolateyとは? OneGet Windows Management Framework 5.0(現在はPreview)から追加されるMicrosoft謹製のパッケージマネージャー apt-getやyum, Homebrewのようなもの Storeアプリではなく、既存のネイティブアプリが対象 但し、ソースからではなく、バイナリでインストール、アンインストール プラグインを追加することで複数のリポジトリをサポート 但し、現状は後述のChocolateyのリポジトリのみ Chocolatey OneGet以前に有志により開発されたオープンなパッケージマネージャー インストール済みのものをインストールしないなど「冪等性」については、Chocolateyが担保してくれます 開発者登録すれば自由にパッケージをアップできます 故に、品質やサポートが玉石混淆です とはいえ、ブラウザからコマンド、開発ツールまで一通り揃っています cinst chrome firefox jdk8 git poshgit gradle intellijidea-community jenkins vim nodejs ruby
  • OneGetとChocolateyのインストール OneGet Windows Management Framework 5.0 Preview May 2014 http://www.microsoft.com/en-us/download/details.aspx?id=42936 コントロール パネルすべてのコントロール パネル項目言語 "English"にしないとインストールがこけます Chocolatey Windows PowerShell – 管理者として実行 Set-ExecutionPolicy Unrestricted iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))
  • Chocolateyパッケージの作り方
  • Chocolateyアカウントの作成 アカウント情報の登録 https://chocolatey.org/account/Register APIキーの取得 https://chocolatey.org/account APIキーの登録 nuget.exe setApiKey 上記URLから取得したAPIキー -Source http://chocolatey.org/
  • ひな形の取得とコピー cinst warmup git nuget.commandline cd %ChocolateyInstall% git clone [[https://github.com/chocolatey/chocolateytemplates.git]] cd chocolateytemplates_templates warmup addTemplateFolder chocolatey "%CD%chocolatey" warmup chocolatey jdk8
  • 最低限記述が必要なファイル インストールのみ パッケージ名.nuspec tools/chocolateyInstall.ps1 アンインストールもサポート 上記に加えて、 tools/chocolateyUninstall.ps1
  • パッケージ定義<?xml version="1.0"?> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>jdk8</id> <title>Java SE 8u5 </title> <version>8.0.5</version> <authors>Sun Microsystems/Oracle Corporation</authors> <owners>oota_ken</owners> <summary>The Java Development Kit (JDK) version 8.0.5</summary> <description>The Java Development Kit (JDK) version 8.0.5</description> <projectUrl>http://www.oracle.com/technetwork/java/javase/downloads/index.html</projectUrl> <tags>java jdk</tags> <licenseUrl>http://www.oracle.com/technetwork/java/javase/terms/license/index.html</licenseUrl> <requireLicenseAcceptance>false</requireLicenseAcceptance> <iconUrl>https://raw.githubusercontent.com/carolynvs/chocolatey-packages/master/Java.JDK/java-logo.jpg</iconUrl> </metadata> <files> <file src="tools**" target="tools" /> </files> </package>
  • 依存関係の定義 *.nuspecに下記のように依存関係を定義すると、aptやbrewのように最初のパッ ケージを指定してあげるだけで、芋づる式にパッケージがインストールされます 但し、バージョン番号とか細かい制御はできないようです <dependencies> <dependency id='gradle' /> <dependency id='maven' /> <dependency id='ant' /> </dependencies>
  • tools/chocolateyInstall.ps1 サイレントインストール対応のアプリケーションだと実質1行で済みます 例えば、JetBrains IntelliJ IDEA - Community Edition $name = "intellijidea-community" $url = "http://download.jetbrains.com/idea/ideaIC-13.1.2.exe" $kind = "EXE" $silent = "/S" Install-ChocolateyPackage $name $kind $silent $url
  • tools/chocolateyUninstall.ps1 現状の殆どのパッケージでは実装されていません 理由 https://github.com/chocolatey/chocolatey/wiki/CommandsUninstall There are no functions defined in the chocolatey powershell module that would help with uninstall Chocolatey側ではアンインストールには最小限のコマンドレット or 関数しか用意されていません パッケージ毎に個別に実装する必要があります jdk8 例 (抜粋) $jdk = "/qn /x {64A3A4F4-B792-11D6-A78A-00B0D0" + $uninstall_id + "0}" Start-ChocolateyProcessAsAdmin $jdk 'msiexec' $java_bin = get-java-bin Uninstall-ChocolateyPath $java_bin 'Machine'
  • パッケージ化と検証、発行 パッケージ化 cpack ローカルインストールで検証 cinst jdk8 -source '%cd%' (アンインストールをサポートしている場合) ローカルアンインストールで検証 cuninst jdk8 パッケージを発行する cpush jdk8.1.8.0.05.nupkg
  • Chocolateyパッケージを作るときの10の地雷
  • *.nuspecでのIDとバージョン番号 <id>jdk8</id> <title>Java SE 8u5 </title> <version>8.0.5</version> PowerShellではありませんが・・・ id 基本的に自由につけられます が、同じようなものが乱立しており、も めてます java.jdk, jdk7, jdk, jdk8 version JDK, JRE内で統一の動きがあります パッケージ自体のマイナーバージョン アップに統一見解がないです 8.0.501 とか?
  • 直ダウンロードインストールが簡単にできない場合 [System.Net.ServicePointManager]::Server CertificateValidationCallback = { $true } $client = New-Object Net.WebClient $client.Headers.Add('Cookie', 'gpw_e24=http://www.oracle.com; oraclelicense=accept-securebackup- cookie') $client.DownloadFile($url, $output_filename) 提供元のWebサイトを解析して、 認証やクッキーの設定をした上で、 ローカルにダウンロードする必要 があります 提供元のWebサイトの仕様変更があっ ても、文句は言えず、仕様変更に追従 する必要があります ライセンス上OKなのか怪しいところもあ ります
  • 副作用のある関数やコマンドレットを呼び出している場合 >function add($a, $b) { return $a + $b; } > function call_add { add 1 2; add 2 3; return 6 } C:UsersKenichiroOta> call_add 3 5 6 嵌まった場所 $dummy = [System.Net.ServicePointManager]::ServerCertificateValid ationCallback = { $true } $client = New-Object Net.WebClient 以下略 PowerShellでは、return文以外でも、値はすべて 関数の結果として返されます 結果ではなく副作用の動作を期待して、関数や コマンドレットを呼んでいる場合に忘れがちです 対応 メソッド:呼び出し[void]で打ち消します コマンドレット:$dummyとかに代入します 嵌まった場所 [System.Net.ServicePointManager]::ServerCertificateValid ationCallback = { $true } 実はこの代入文の戻り値はコールバックのスクリプトブ ロックですので下記のような修正が必要です $dummy = [System.Net.ServicePointManager]::ServerCertificateValid ationCallback = { $true }
  • アンインストールサポートの欠如 $use64bit = use64bit if ($use64bit) { $jdk = "/qn /x {64A3A4F4-B792-11D6-A78A- 00B0D0" + $uninstall_id + "0}" $jre = "/qn /x {26A24AE4-039D-4CA4-87B4- 2F864" + $uninstall_id + "FF}" } else { $jdk = "/qn /x {32A3A4F4-B792-11D6-A78A- 00B0D0" + $uninstall_id + "0}" $jre = "/qn /x {26A24AE4-039D-4CA4-87B4- 2F832" + $uninstall_id + "FF}" } Start-ChocolateyProcessAsAdmin $jdk 'msiexec' Start-ChocolateyProcessAsAdmin $jre 'msiexec' アンインストールに関するヘルパーが殆ど ありません https://github.com/chocolatey/chocolatey/wiki/Co mmandsUninstall サポートしているHelper Uninstall-ChocolateyPackage UnInstall-ChocolateyZipPackage サイレントアンインストールはソフトウェ アによってバラバラです 殆どのパッケージでアンインストールをサ ポートしていません →上記よりアンインストールの実装のノウハ ウが不足しています
  • 環境変数の取り扱い Install-ChocolateyPath $java_bin 'Machine' 内部実装 [Environment]::SetEnvironmentVariable('Path', $actualPath, $pathType) Install-ChocolateyEnvironmentVariable 'JAVA_HOME' $java_home 'Machine' $env:Path = $actualPath 環境変数の変更が反映されてない?? cinstでインストールして、環境変数を書き 換えたのに、元のシェル(コマンドプロンプ ト、PowerShell)上では環境変数の変更が 反映されていません cinstは新たにPowerShellを起動して、その中 でSetEnvironmentVariableしています 従って、親のシェルには反映されません 親のシェルはそのシェルの起動時に環境変数を 親プロセスからコピーするため、cinst後、再度 GetEnvironmentVraibleしても、更新後の環境変数 の値が取得できません →現実にはレアケースですが、同じシェ ルのまま、cinst, cuninstすると環境変数 の残骸が残るという面倒なことが起きま す 分かりにくいので次ページの図で
  • 環境変数の取り扱い ステップ Windows本体 cinstを起動したシェル cinst内部のPowerShell cuninst内部のPowerShell cinst後起動したシェル cinst前 cinst後 key=value key=value シェルもう一つ起動 key=value key=value cuninstを起動 key=value ない!!(cinstを起動した シェルを引き継ぐ) key=value cunsint後 key=value (残骸として残る) ※このシェルでcuninstを 起動すれば問題ない ※このシェルでcuninstを 起動すれば問題ない
  • x64, x86の判断 function use64bit() { $is64bitOS = (Get-WmiObject –Class Win32_ComputerSystem).SystemType -match ‘(x64)’ return $is64bitOS } if ($use64bit) { $jdk = "/qn /x {64A3A4F4-B792-11D6-A78A-00B0D0" + $uninstall_id + "0}" $jre = "/qn /x {26A24AE4-039D-4CA4-87B4-2F864" + $uninstall_id + "FF}" } else { # 略 } アプリケーションがx64版、x86版の方を用意して いる場合、オプションインストールのサポートを含 めると、最悪以下の組合せ毎にロジックを書く必 要があります x64 OSにx86アプリケーションを入れた先とx86 OS にx86アプリケーションを入れた先が異なるのが ロジックミスをしやすく要注意です OS アプリケーション 標準インストール先 x64 x64 C:Program Files x64 x86 C:Program Files (x86) x86 x86 C:Program Files
  • OneGetでのテスト Chocolatey cinst jdk8 -source '%cd%' OneGet cpush jdk8.1.8.0.05.nupkg Install-Package jdk8 Uninstall-Package jdk8 OneGetではローカルインストール検証の サポートは現状ありません Chocolateyでローカル検証した後、本番 アップして検証する綱渡りです 後述しますが、OneGetでは各コマンドは ネイティブ実装(DLL)されています Chocolateyのパッケージ・プロバイダーも DLLで実装されており、PowerShellで実装 されているオリジナルのChocolateyの挙 動と微妙に異なるところがあり、検証は 必須です OneGetで正常に動作しないと、その間の 本番パッケージはOneGetでインストール できない状態になるので注意が必要です 正式版のOneGetの改善を望みます
  • x64, x86 * Chocolatey, OneGetのテスト Chocolatey * x64, x86 cinst jdk8 –source '%cd%' cunint jdk8 OneGet cpush jdk8.1.8.0.05.nupkg Install-Package jdk8 Uninstall-Package jdk8 下記の組合せテストが必要です OS Chocolatey OneGet アプリ x64 Chocolatey x64 x86 OneGet x64 x86 x86 Chocolatey x86 OneGet x86
  • 開発効率のための管理者として実行 function Start-ChocolateyProcessAsAdmin { # 略 $psi = new-object System.Diagnostics.ProcessStartInfo; $psi.FileName = $exeToRun; if ([Environment]::OSVersion.Version -ge (new-object 'Version' 6,0)){ $psi.Verb = "runas"; } # 略 } Start-ChocolateyProcessAsAdmin 内部でrunasしています Start-ChocolateyProcessAsAdminを呼び 出しているfunctionごとに、以下のダイ アログがでます ユーザーアカウント制御 次のプログラムにこのコンピュータへの 変更を許可しますか? →ダイアログボックスを手動で"OK"する 必要があり、開発効率が悪いです →親プロセスのPowerShellを「管理者と して実行する」で起動して回避します →これで効率化すると次の地雷が・・・
  • 最終実行は通常実行 function Start-ChocolateyProcessAsAdmin { param( [string] $statements, [string] $exeToRun = 'powershell', [switch] $minimized, [switch] $noSleep, $validExitCodes = @(0) ) # 略 if ($minimized) { $psi.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Minimized; } # 略 } Start-ChocolateyProcessAsAdmin not 「管理者として実行」 かつ $minimized = $trueで呼び出さないと 呼び出す度にサブウィンドウが開きます 難解も開くのがウザいので間違って閉じてしまう可能性 があります というか、じぶんでやってしまいました そうすると、サブプロセスがエラーExitでインストールが失 敗します ユーザーがやってしまいがちです 対処方法 $minimized = $trueで呼びます ・・・が、 function Install-ChocolateyPath { # 略 Start-ChocolateyProcessAsAdmin "$psArgs" # 略 Chocolateyの関数自体がminimzed = $trueしてません
  • まとめ OneGet & Chocolatey ネイティブアプリの一括インストールは劇的に楽になりました ただし、アンインストールのサポートが殆ど無いです OneGetの今後の整備に期待します OneGet & Chocolateyのパッケージ作り OS x アプリ x (OneGet | Chocolatey)の組合せテストが大変です もうちょっと、アンインストール系を始めAPIが充実して欲しいです とはいえ、色々整備されると嬉しいのでみんな作ってみましょう (震え声)