HIDARI日記(右)

そのときどき興味ある技術を中心にだらだら書いてます。内容は個人の見解であり、所属する企業を代表するものではありません。

コマンドプロンプトの errorlevel を確認してエラーなら処理を終了する方法

基本中の基本なんですが、最近はエラーが起こったら処理を終了することが重要になってくるとき、例えば「コマンドプロンプトしか使えない状況でCI回したい」みたいな縛りプレイしてるときに使ってます。具体的にはJenkinsのジョブを失敗させるためですが。

手順

まず、バッチファイルに以下の様なサブルーチンを用意しておきます。

:SuccessOrDie
if not %errorlevel% == 0 (
    echo [ERROR] :P
    exit 1
)
exit /b 0

これをerrorlevelに戻り値を返すコマンドのあとにcallで呼び出します。

xcopy src\hoge.dll dest\ /Y /F
call :SuccessOrDie

もしエラーが発生していたら(errorlevel0でなかったら)exit 1が実行されコマンドプロンプトが戻り値1、つまりエラーで終了します。Jenkinsだとこれだけでジョブを失敗させることができます。

一方、エラーがなかった場合(errorlevel0の場合)はexit /b 0が実行されます。/bオプションによってサブルーチンを終了し呼び出し元に戻ることができます。

バッチファイルではよくgoto使ってエラー処理をしているのを見かけますが、呼び出し元に戻りたいのに加えて、思わぬバグが生まれることがあるので使うのを避けて、callexitの組み合わせを使っています。

errorlevelを含む条件式での注意点

if not errorlevel 0 exit 1

って書いてしまうと「0以上ではないとき終了する」になるので、errorlevelが負のときにしかexitが実行されません。

if not %errorlevel% == 0 exit 1

というように展開した上で文字列での比較を行うことで「0ではないとき終了」するようになります。

手動で実行したい!

基本的にはCIサーバでコンソール出力を記録しながら使うことを前提としたバッチファイルですが、CIとかよくわからんから手動でもログを残して実行できるようにしておいてくれないと困るって言う人が稀によくいます。

そういうときは以下のような処理を書いた手動実行用のラッパーを用意しています。

@echo build.batを実行します。
@echo ログは build.bat.logに出力されます。
@pause

@echo 実行中...
@call build.bat > build.bat.log 2>&1

このバッチファイルをダブルクリックするだけでログ出力まで行います。

サンプル全文

ここまでで紹介したあれこれをまとめたサンプルの全文です。

@echo off
set SELF_PATH=%~dp0
cd /d %SELF_PATH%

xcopy src\hode.dll dest\ /Y /F
call :SuccessOrDie

goto end

:SuccessOrDie
if not %errorlevel% == 0 (
    echo [ERROR] :P
    cd /d %SELF_PATH%
    exit 1
)
exit /b 0

:end
echo [SUCCESS] :)
echo on
exit 0

第6回 PowerShell勉強会 に参加してきました #jpposh

第 6 回 PowerShell 勉強会 - Japan PowerShell User Group (JPPOSH) | Doorkeeper に参加して、LTでPesterについて少しだけ話をさせてもらって来ました。

LT資料はこちら。

せっかくなので、ちょっとLTの補足なんかをしておきたいと思います。

TestDrive

TestDriveにアクセスするときTestDrive:\$TestDriveが使えますが、微妙に異なる点があります。

前者は通常のPSDriveですが、後者にはTestDriveが指す場所のフルパスが入っています。

そんなに困ることは無い気がしますが、一応覚えておいた方がいいかと思います。

コードカバレッジ

二点ほど。

まず一点目。Pester自体はPowerShell2.0以上で動作するんですが、コードカバレッジ機能だけはPowerShell3.0が必要です。そんな環境でPester使うことあるんかって話は置いといてください(ニッコリ。

もう一点は計測結果に出てくる 「commands」 についてです。資料の中では

Code coverage report:
Covered 66.67 % of 3 analyzed commands in 1 file.

って出てるやつです。

Pesterのコードカバレッジの計測はPSBreakpointsで実行されたcommand(文)を記録することで実現されています。実行されたPSBreakpointsがcommandsとして報告されます。 そのためPowerShellの仕様としてPSBreakpointsが置けないelsetryfinallyなんかはcommandsにカウントされません。ifとかthrowとかreturnとかはカウントされます。

コードカバレッジの結果を見て数が合わないなって思ったときは、一度確認してみてください。

ほかの方々の資料

は、こちらから

Jenskinsでのsvnリポジトリのポーリングで発生するエラー

Jenkinsでsvnをポーリングするようにしていると、以下の様なエラーが発生することがあります(「Subversionのポーリングログ」から確認できます)。

ERROR: Failed to check repository revision for proto://host:port/path/to/repo
org.tmatesoft.svn.core.SVNCancelException: svn: E200015: E200015: ISVNAuthentication provider did not provide credentials; HTTP authorization cancelled.

数日前からこのエラーが起きてたのをようやく解決できたのでメモしておきます。

このエラーは svn:externals を使って別のリポジトリを参照する構成になっている場合で、メインのリポジトリと、参照先のリポジトリの認証情報が異なるときに起こるとのこと。

実際にエラーが発生した環境は、メインも参照先も同じサーバのリポジトリで同じ認証情報だったので、 あまり気にしたことなかったんですが、Jenkinsから外部リポジトリの更新を行う時には通常とは異なる動きでsvnクライアントが 起動するらしく、何らかのタイミングでメインのリポジトリと参照先のリポジトリの認証情報に齟齬が発生していたようです。

正しく動作させるにはジョブの設定で [Additional Credentials] を追加し、外部リポジトリのrealmというのと、それに紐付いたCredentialsを指定します。

realmの確認は以下のコマンドで出来ます。ダイアログが出てくるけどキャンセルでいいです。

svn --no-auth-cache --config-dir invalid info proto://host:port/path/to/repo

この問題は、今回みたいに同じsvnサーバ上のリポジトリでも起こりえるので svn:externals を使っているリポジトリをJenkins で触るときは必ず [Additional Credentials] を指定しておくのが正解っぽい。

tscとlite-serverで作るシンプルなTypeScript開発環境

最近MacでカジュアルにTypeScriptを書いてブラウザで確認したいなってときに使っている環境です。 ぶっちゃけAngular2の 5 Min Quickstart で使われている方法ですが。 (なお、前提としてnode.jsをインストールしてnpmを使えるようにしておく必要があります。)

使用するツールはTypeScript(tsc)の他には lite-serverという開発用のhttpサーバだけです。 上記二つを使って、[TypeScript書く] > [自動ビルド] > [ブラウザの自動リロード]を実現していきます。

まず、実験用のディレクトリを作ってTypeScriptをインストールしておきましょう。

mkdir my-proj
cd my-proj
npm install typescript

これでTypeScriptをコンパイルするコマンドtscが使えるようになります。 適当に以下のような sample.ts を作って node_modules/.bin/tsc sample.ts を実行すると sample.js が出来ますね。

class Person {
    public Name:string;
    constructor(name:string) {
        this.Name = name;
    }
}

var me = new Person("Hidari");
document.body.innerHTML = me.Name;

さて、tscには -w オプションがあり、tsファイルの変更を検知してコンパイルを自動で行うことが出来ます。 これを行うために、まず tsconfig.json というファイルを sample.ts と同じ場所に作成し、以下の内容を記述します。

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es5",
        "rootDir": ".",
        "outDir": ".",
        "noImplicitAny": false
    },
    "exclude": [
        "node_modules"
    ]
}

ファイルが作成できたら node_modules/.bin/tsc -w を実行してみましょう。 tsファイルの変更が監視されます。試しに sample.ts を変更してみてもいいと思います。

次にlite-server。これはnode.js上で動作する開発用のhttpサーバで、ファイルの変更を検知してブラウザで表示中のページを自動でリロードしてくれます。 npm install lite-server でインストール。

続いて適当に以下の様な index.html を作り、新しいターミナルでnode_modules/.bin/lite-server を実行します。 するとブラウザが開いてindex.htmlが表示され、同ファイルの変更監視が開始されます。

<!DOCTYPE html>
<html>
    <head>
        <title>sample</title>
    </head>
    <body>
        <script src="sample.js"></script>
    </body>
</html>

以上で終わりです。

これでTypeScriptを編集すると自動でコンパイルされ、ブラウザがリロードされ、結果が確認出来るようになりました。 ガッツリ開発するにはちょっと力不足ですが、雑に書くぶんには十分だと思います。

ではでは。

CI勉強会に参加してきました #vshtc

びっくりするほどほったらかしになっててびっくりしました。

今日はVSハッカソン倶楽部主催のCI勉強会 - #vshtc - VSハッカソン倶楽部 | Doorkeeperに参加してきました。

会の構成としてはセッション4つと、今後計画されている「XFDハッカソン」のためのアイデアソンという形で、僕はセッションの一つで主催の森理 麟 (@moririring)さんと共に発表させてもらいました。

セッション部

一つ目のセッションは、Yu Nobuoka (@nobuoka)さんによる「CI のすすめ 〜はてなでの web サービス・モバイルアプリ開発と CI〜」。 はてなでのCIについてどんなふうに行っているのか、なぜCIが必要なのかといった話で、めっちゃ勉強になった!!

2つ目はLibreぽざうね (@Posaune)さんによる「ポストJenkins時代のCI戦略」。若干煽り気味のタイトルですが、内容は安定のPosauneさんクオリティ。毎回情報のカバレッジに驚かされ続けています。詳しくは公開されているスライドポストJenkins時代のCI戦略を見てみてください。

3つ目は我らが森理 麟 (@moririring)さんと、不肖わたくしによる「WindowsでbatとPowerShellでCI!」。前半が森理麟さんによるbatファイルとタスクスケジューラによるローカル環境CIについてデモをメインに紹介。後半で僕がPowershellを使ったWindows環境でのビルドについてデモを行いました。ほどんどスライドを使わないほぼ無刀セッションでしたが、なかなか興味を持ってもらえたようでありがたい限りです。

4つ目は三浦カズヒト(「らむだ」とか解らない人) (@kazuhito_m)さんによる「出来る!XFD!」。このセッションが次の「XFDハッカソン」につながる大きな布石となっています。こちらもスライドができるXFD - 2015/07/11 CI勉強会 - #vshtcで公開されているのでそちらを参照ください。パトランプパトランプ

イデアソン部

イデアソンとはハッカソンで作るもののアイデアをみんなで出し合っていく話し合いみたいなもの。数人でグループを作ってブレインストーミング的なことを行ってアイデアを出し合い、10分程度話し合ったらまた別のグループを作ってアイデア出し、という形式で計3回行われました。

XFDとしてどんな情報をFeedbackするのか、どんな方法でFeedbackするのかをわいわい出し合い、荒唐無稽なものからわりと現実味のあるものまでいろんなアイデアが出て楽しかったです。僕が参加したグループで出たのアイデアの一部としては

  • ビルドがコケるたびに連絡先を一個ずつ消していく
  • ビルドを壊した人をイニシャルで指摘
  • ビルドを壊した人のチャットなどのアイコンを「僕がやりました」を表すものに変える
  • ビルド成功などのたびにコーヒーの温度が5℃ずつあがり、一定の成果を出すとコーヒーが飲める
  • ビルド成功などのたびにキャラクターが褒めてくれる
  • プロダクトのモジュール図などで壊れている部分を赤くして他のチームに知らせてしまう
  • ビルド失敗などのたびにHPゲージが減って全損するとモニタの電源が落ち、復活させるにはチーム全員でKinectで変なポーズを認識させる

などでした。

おわりに

僕の発表はほぼ全部デモということもあり、いろいろ不安要素も多く中には実際に現実に上手くいかない部分もありましたが、予定していた内容は実行出来たので自己評価はなかなか(甘めですが)。反省としてはもう少しスムーズにデモをやると、時間を有効に使えるし、魅力ももっと伝えられるだろうなってところです。

イデアソンで出たアイデアは終盤にはかなり現実的なものに落とし込まれていて、参加者のレベルの高さを感じました。同時にハッカソン、ついていけるかなっていう不安も出てきました…。でもそれよりも早く動いてるところを観たいという気持ちが強く、とても楽しみです。

参加者の皆様、お疲れ様でした。

おまけ

懇親会でなぜか最近面白かった漫画を紹介する流れになったので、そこで出した本をご紹介。

ではでは。

JavaScriptだけでブラウザの「戻る」ボタンを無効化する方法

このあいだ諸事情で調べたら、意外とまとまってるとこなかったなのでちょこっと書いてみます。

  • IE8以降を対象
  • ブラウザの「戻る」ボタンで他のページに遷移しない
  • Backspaceキーでの「戻る」も許可しない

みたいな方針で調べてみました。

まあ結論から言うと

Ah, the back button. You might imagine "back" fires a JavaScript event which you could simply cancel like so:

document.onHistoryGo = function() { return false; }

No so. There simply is no such event.

javascript - Intercepting call to the back button in my AJAX application: I don't want it to do anything! - Stack Overflow

というわけで、ブラウザの戻るボタンをお手軽に無効にする方法はないようですね。

方法

1.window.onunloadイベントを利用する

まず直接的なイベントが無いなら似たようなイベントをかわりに使おう!みたいな安直な発想で。

ページから離れる際に発生するonunloadイベントをトリガーとして、次に表示されるページ(遷移先)を現在のページにしてしまう関数を実行する方法。

window.onunload = function() {
    alert('Back buttom is pushed ??');
    location.replace(document.location);
};  

onunloadは戻るボタン以外でも発生するの。Backspaceキー、URLの直接入力、履歴からの遷移でも。リンクをクリックしたときも当然発生する。その結果、このコードがあるページからは移動できなくなるという仕組み。

対象を「戻る」ボタンの動作だけに絞ることができないので、この方法はちょっと厳しそう。

以下のように、適当なタイミングでイベントハンドラを削除することで移動できるようにすることもできなくはないけど、釈然としない。

<script type="text/javascript">
    function goNextPage() {
        window.onunload = null;
    };
</script>

<a href="./Page3.html" onclick=" goNextPage(); ">Go Next</a>

というかIE11ではlocation.replace()でランタイムエラーになって動かないんだよな…(だめじゃん

参考:ブラウザの戻るボタンを無効にする方法: ある SE のつぶやき

2.history.forward()関数を使う

検索するとよく見つかる方法。遷移元のページに 以下のJSを記述しておく。

window.onunload = function() {};
history.forward();

上のコードがhead要素辺りに書いてあるページAからページBへ遷移、その後Bから「戻る」ボタンでAへ戻ると、history.foward()関数でBへ送り返されます。なので、Backspaceキー使われても平気。

ただ、履歴の一つ前がAのときはBからだけでなくどのページからも戻れないことになるので、特定のページだけ「戻る」ボタンを使用不可にしたい!みたいな状況では使えない。

逆にこのページだけには戻ってきてほしくない、っていうときは、あるいは使える?

参考:[JavaScript] ブラウザの戻るボタンを無効にする方法 | 自由が丘で働くWeb屋のブログ

3.window.location.hashを使う

URLにhash(URLの後ろにくっつく#HogeHogeみたいな文字列で、ページ内リンクなんかに使われてる)をつけることで別ページへの遷移として履歴に残して、他のページに戻れなくしてしまう方法。

window.location.hash="no-back";
window.location.hash="no-back-button";
window.onhashchange=function(){
    window.location.hash="no-back";
}

ページが読み込まれたタイミングでURLの末尾に#no-back、あるいは#no-back-buttonを追加し、同時にhashが変更されると発生するonhashchangeでhashを変更する関数を追加する。

ページに遷移してきた時点で、履歴の一つ前のページが自分自身になっているため、戻るボタンを押しても自分に戻るだけになるという寸法。

URLに余計な文字列が含まれてしまうのを嫌がる人もいますが、先に挙げた方法よりだいぶ安定している印象ですね。

参考:javascript - How to Detect Browser Back Button event - Cross Browser - Stack Overflow

4. history.go()を使う???

+JavaScript+ブラウザの戻るボタンの無効化 - Free Flying

こういう方法もあるみたいだけど、なんでhistory.go()で「戻る」が使えなくなるのかイマイチ分からなかったんで試すのをやめました。

参考:go method (Internet Explorer)

5. HTML5の History API を利用する

今回僕が当たった要件では難しいけど、HTML5が利用できるIE10以降では以下の方法を使えば、概ねそれらしく動きます。

「戻る」を禁止したいページに以下のJSを書く。

<script type="text/javascript">
    history.pushState(null, null, null);

    window.addEventListener("popstate", function() {
        history.pushState(null, null, null);
    });
</script>

ページが読み込まれたらhistory.pushState()メソッドで履歴の先頭に新しい履歴がひとつ追加される。このとき第3引数がnullなので、追加された履歴は自分自身を指していることになる。続いてpopstateイベントのハンドラとしてhistory.pushState()を実行する関数を指定する。

「戻る」ボタンが押されるとpopstateからイベントハンドラが実行され、自分自身を指す履歴(history.pushState(null, null, null))がもう一つ追加される。

ページ読み込み時に実行されるhistory.pushState()では、最初に「戻る」が実行されたときに戻る先の履歴が追加され、2回目以降の「戻る」実行時はイベントハンドラで追加される履歴が使用される、はず。

戻る先は常に自分自身になるため、結果として「戻る」ボタンを無効化できます。先に書いたlocation.hashに近いもので、実際リファレンスには

ある意味では、pushState() の呼び出しは window.location = "#foo"; と設定するのと似ています。どちらも、現在のドキュメントに関連する別の履歴エントリの生成とアクティベートを行います。

Manipulating the browser history - Web developer guide | MDN

とあるので、HTML5が使えるならhistory.pushState()、ダメならlocation.hashを使うというのが、ある意味正攻法なのかも。

まあ、各種イベントの発火条件とかに違いがあるので、よく考えて使う必要があるのは言うまでもないのですが。

参考:

おわりに

かろうじて使えるかなって言うのがlocation.hashを使う方法でしょうか。

というかそもそもですね、特にレガシーな感じのブラウザで、「戻る」ボタンの無効化くらいJavaScriptだけでできるんでしょ?ちゃちゃっとやっちゃって?という、(冒頭の引用のような)安直な考えは捨てるべきなのではとか思わずにはいられないと思ったり思わなかったり。

「Windowsでの自動化について考える会」を開催してきました #WinAutoMate

f:id:hidari-yori:20150222023741j:plain

今日は Windowsでの自動化について考える会 - connpass を開催してきました。

実は見切り発車感の強い企画ではありましたが、蓋を開けてみるとキャンセル待ちまで出るほど多くの方に興味を持っていただけたみたいで、かつ僕自信にとっても非常に勉強になることが多い有意義な勉強会になりました。

参加者、発表者、そして会場を提供していただいたMOTEX様、ありがとうございました。お疲れ様でした。

発表の概要のようなもの

本日の発表資料はすべて公開されています。

僕の発表ではこの勉強会の導入として、自動化の「手段」について駆け足で紹介。 個人的に興味のあるプロダクトの名前もこっそり混ぜつつ、僕なりの解釈とゆるく絡めて話しました。

続いて森理麟さんから。自身がこれまでに行ってきた身の回りの自動化の経験や、これからの自動化の在り方についての大胆な予想が語られました。大小の様々なつまづきポイントについての知見がとても勉強になるものでした。

三番目の石川さんの発表はシステムテスト自動化について。石川さんが作られてるテスト自動化ライブラリ Friendly を使ったテストの自動化、そしてアプリケーションドライバーの重要性を強く訴えるものでした。途中、参加者に実際にその場でFriendlyを使ったテストを書いてもらうという面白い試みもされていて見応えがありました。

Hyper-VとPowerShellによる仮想サーバーの自動構築.pptx - Microsoft PowerPoint Online

最後の発表はwakaさん。Powershell DSCとHyper-Vを組み合わせて仮想マシンの新規インストールからWebサイトの立ち上げまでを行ってしまおうというものでした。OSの新規インストールにはライセンスの問題がつきまとうため、なかなか実行できないかもしれませんが、とても珍しい知見が得られたと思います。またデモ中、PowersShell DSCでサクラエディタのインストールが行われた時の参加者の食付きがすごかったのが印象的でした。

おわりに

Twitterでつぶきやかれた内容は Windowsでの自動化について考える会 #WinAutoMate まとめ - Togetterまとめ にまとめています。よければこちらも見てみてください。

次回はいつになるかわからないけど、もう一回くらいはやりたいな。

そういえば、次あれば資料はワイド表示でつくろうと思いました(小並感