tag:blogger.com,1999:blog-77026129453544923732023-11-17T01:41:59.586+09:00memorandumhttps://blog.ksoichiro.com/ に移転しました。Webアプリ開発などを中心としたITに関するメモのブログです。ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.comBlogger177125tag:blogger.com,1999:blog-7702612945354492373.post-61082976498249829802020-12-21T00:42:00.002+09:002020-12-21T00:50:09.128+09:00VSCode Extension<p>少し前に <a href="https://marketplace.visualstudio.com/items?itemName=ksoichiro.vscode-status-bar-title">Status Bar Title</a> という VSCode Extension を作った。全然大したことないのだが、2020年ももう終わりに近づくのに今年は全然書いていなかったので記録しておく。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIoM3gYu8nuK_rJxzU9HjYuEVsKeayVDSOD611ZiJEx0IjJw5SwujOEHOn4gjL_sFBGRrK-CHNEGqljRbbr-hrcbg010TNfzHQMC8u-_Xc9iSrDtqkcz46rCoDMbZ6VGTPI3LESYYxJZLX/w510-h76-no/" alt=""></p>
<a name='more'></a>
<h2 id="作った理由">作った理由</h2>
<p>vim などのように terminal ベースのエディタを使っていると、作業領域が広く取れるのが良いなと思っていて、VSCode でも少しでも近づけられればと思ったところ <a href="https://marketplace.visualstudio.com/items?itemName=iocave.customize-ui">Customize UI</a> という extension を見つけた。</p>
<p>これを使うと、Activity Bar (エクスプローラ、検索、等のメニューのアイコンが並んだバー) の位置を変えたり、タイトルバーを隠すことができる。</p>
<p>これは良いと思ったが、タイトルが出ていないと、複数のウィンドウを開いているときに今どのウィンドウが開いているのかわかりにくいという問題がある。</p>
<p>エクスプローラの上部に表示されているが、視認しにくいのと、エクスプローラ以外を表示していると見えない。</p>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZH_m7EJ48PhFF3RK7VVAHdL-_6x_WI_AWej3bDkY7ZQ357xXlSiS8iqvwoPCD0gwcWKVAmU72pYoMiEQfv6Qi9eh4FyzLlPiEHr06rI_njtyTjCHwCABPltpu_w6fYIYlLp474Hu4Vj48/w716-h144-no/" width="400px">
<p>だったらタイトルバーを表示すれば良いのでは…と思うかもしれないが、タイトルバー非表示のほうが何かカッコいいなと思ってしまったのだよな…</p>
<p>そこで、ステータスバーにタイトル(プロジェクト名)を表示できれば良いと思ったのだが、標準機能にはないらしく、ちょうどよい extension も見つからなかったので、作ってみることにした。</p>
<h2 id="結果">結果</h2>
<p>結果が以下。Gitのブランチ名(master)の左側に表示されている <code>memorandum</code> の部分がプロジェクト名。本当に表示だけで、クリックしても何も起きない。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLoGw_TH0zvRPqXtct_pjad7ZcpiuaOOs5k3YC1arO0-qBSsJyD_nfA_keE9zdBZAjor5lP49xHPEFksVvnk-9UpgobIJWaV-Akq-gzDr8j9F4MIbKKc9JfPh_UL54bxV88jmtId2ws6bB/w1476-h84-no/" alt=""></p>
<p>ウィンドウ全体で見るとこんな感じ。目立たないが、同じ位置にあるとわかっていればそれなりに見分けられる。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwFZBNu2ezVurpmims5BA3QmoD_UsLTzReljZpupx_nwR_AUBETY0Nm3UbRA38Tejn_EmCt05-t8jp3v2MhDkoP5zqFpaTiCPFxxPe80kJZ1SUE-h5PyEV_udie-xFxXS-1ahZG6jZnadt/w3102-h1896-no/" alt=""></p>
<p>extension のデバッグのウィンドウ(Extension Development Host)の場合はアイコンがbugのアイコンに変わる (これはextensionの開発者向けの相当に地味な機能…)。</p>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWZWfjxdUce44AM38fS0iZFCDG2tkMb7fAdsJJLE5225JoqkXjjPb3KbDsaWSB5HxbDvspjBi8f3AeUPYBBb7w5rn4Dxq2AnmHSLpG8S99mPopLRlaVOImlDVOQs0vwDosTbU-SltGGVIZ/w660-h64-no/" width="400px">
<p>こんな地味なもの使う人は自分くらい…とも思ったが、わずかながらダウンロードしてくれている人がいる。(最初の5~8件くらいは自分)</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4FvCjo5wF2f0gmGrUqx2Qg0oTFVixJHplGO6krL8du_ziHIdXBPHpI9MgDEue0xAPmMtDZVZxKl0vKGUnkOQAArYQSmBI9QrShuF9r9C8jsa9TOhOS_q0tKNBURrayW5GAa-T64JkABog/w868-h347-no/" alt=""></p>
<p>リポジトリは<a href="https://github.com/ksoichiro/vscode-status-bar-title">こちら</a>。</p>
<h2 id="内容">内容</h2>
<p>本当に単純で、Hello Worldレベルな感じ。<br>
起動とともに有効にしてほしいextensionなので、アクティベーションのイベントはすべて(<code>*</code>)。</p>
<pre class=" language-json"><code class="prism language-json"><span class="token string">"activationEvents"</span><span class="token punctuation">:</span> <span class="token punctuation">[</span>
<span class="token string">"*"</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
</code></pre>
<p>activate の function で statusBarItem を作って登録する。<br>
位置の制御のために優先度を示す整数値を与えるが、他のextensionがあっても基本的に一番左に表示したいという意味で大きい値を設定している。</p>
<pre class=" language-typescript"><code class="prism language-typescript">myStatusBarItem <span class="token operator">=</span> vscode<span class="token punctuation">.</span>window<span class="token punctuation">.</span><span class="token function">createStatusBarItem</span><span class="token punctuation">(</span>vscode<span class="token punctuation">.</span>StatusBarAlignment<span class="token punctuation">.</span>Left<span class="token punctuation">,</span> <span class="token number">10000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
context<span class="token punctuation">.</span>subscriptions<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>myStatusBarItem<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>あとは表示するitemを組み立てるだけ。<br>
前述の通り Extension Development Hostかどうかという判定は <a href="https://github.com/microsoft/vscode/issues/10272">https://github.com/microsoft/vscode/issues/10272</a> のworkaroundに頼っているが、それ以外は単純にworkspace名とアイコンを文字列で設定しているだけ。アイコンについては <a href="https://code.visualstudio.com/api/references/icons-in-labels">Product Icon Reference</a> で説明されているが、 <code>$(project)</code> という文字列表現だけで簡単に設定できる。</p>
<pre class=" language-typescript"><code class="prism language-typescript"><span class="token keyword">const</span> isDevelopment <span class="token operator">=</span> vscode<span class="token punctuation">.</span>env<span class="token punctuation">.</span>sessionId <span class="token operator">===</span> <span class="token string">'someValue.sessionId'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> icon <span class="token operator">=</span> isDevelopment <span class="token operator">?</span> <span class="token string">'$(debug)'</span> <span class="token punctuation">:</span> <span class="token string">'$(project)'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> name <span class="token operator">=</span> vscode<span class="token punctuation">.</span>workspace<span class="token punctuation">.</span>name<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>name<span class="token punctuation">)</span> <span class="token punctuation">{</span>
myStatusBarItem<span class="token punctuation">.</span>text <span class="token operator">=</span> <span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>icon<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span><span class="token punctuation">;</span>
myStatusBarItem<span class="token punctuation">.</span><span class="token function">show</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre>
<h2 id="リリース">リリース</h2>
<p>細かな手順は様々なブログ等で説明されているので割愛するが、1点だけ。</p>
<p>ちょうどこの頃、GitHubではGitリポジトリのデフォルトブランチをmasterブランチではなくmainブランチとするようになった頃だったのだが、これに沿って main ブランチとしたところ、VSCode Extension の marketplace でうまく画像が出ないという事象に遭遇した。工夫をすれば回避できなくもなさそうだったが、その後も問題に遭遇しそうな気がしたので、まだ main にするのは早いかなと判断して master に戻した。</p>
ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-79968656033253590142020-01-17T00:58:00.002+09:002020-01-17T00:58:12.521+09:00ghq rootが複数あると最後のrootにcloneされるようになった<p>最初のrootが使われると思っていたが、最後(2つめ)が使われた。<br>
調べてみると以下の issue があり、v0.17から挙動が変更されていた。当初意図したものではなかったようだが、今後この仕様になるとのこと。<br>
<a href="https://github.com/motemen/ghq/issues/239">https://github.com/motemen/ghq/issues/239</a></p>
<p>README には最初の root に clone されると説明されていたので、修正の pull request を送ったところすぐに修正を取り込んでいただけた。</p>
<p>というわけで、README の説明の通り ghq.root が複数定義されている場合は最後のものが clone に使われるので、ghq list に Go の GOPATH のような固有のパスを含めたい場合は ghq get で使ってほしいパスを最後に書くと良い。</p>
ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-59159252466191594002020-01-14T23:14:00.002+09:002020-01-14T23:14:51.732+09:00EvernoteからSimplenoteに移行しようとしたがEvernoteに戻った<p>プライベートなメモは長らくEvernoteを使っていたが、ローカルのデータが大きくなりすぎるとか、コストを安くしたい(プレミアム版を使っていた)とか、Markdownを編集したいとか…そういった理由から、Evernoteの代替サービスを探していた。</p>
<p>結果として 2018 年の11月頃に Simplenote に乗り換えた。</p>
<a name='more'></a>
<p>当時良いと思ったのは以下のような点。</p>
<ul>
<li>無料で利用でき、利用に(Evernoteのような)制限がない。</li>
<li>Markdown形式で編集できる。</li>
<li>モバイルアプリ、Macデスクトップアプリがあり普段使いできる (Evernote相当の使い方ができる)。</li>
<li>機能が少なくノートブックもなければ画像の添付もできないのだが、実際に振り返ってみるとテキストのメモが大半であったため、メモをすることだけが目的と割り切れば、むしろ集中できて良いとも思えた。</li>
</ul>
<p>1年以上使っていたことになるので結構うまくいっていたとも思うのだが、使い始めた当初から感じていたアプリへのイライラが解決されず、再びEvernoteに戻ってきた。</p>
<p>Simplenote を諦めたのは以下のような点を強いデメリットに感じ、これらを回避するためにはやはりEvernoteの方が良いと感じたから。</p>
<ul>
<li>Androidアプリの操作性が悪い。何かの拍子に入力が勝手にコピー&ペースト(?)され無限に増殖していったこともあった。(「あ」と入力したら「あああああ…」と勝手に入力が増えていくイメージ)</li>
<li>登録・更新した日付がわかりにくい。</li>
<li>アプリ(Android?Mac?失念…)で入力が受け付けられなくなったことがあった。</li>
<li>Androidアプリで新規ノートを作成するのになぜか時間がかかり、思いついたことをすぐ記録したいときにストレスになる。(最近は改善された?)</li>
<li>確かにMarkdownに対応しているものの、プレビューを同時に見ることができないせいか、誰かと共有するのではなく一人でメモをする上では有用に感じられなかった。つまり、実は Markdown というのは個人のメモアプリとしてはあまり本質的な要求ではなかったらしいと気づいたともいえる。(ただ、チェックボックスは編集画面で表示されたのでよく使った)</li>
<li>新規ノートの作成が遅いことや編集機能の弱さといった使い勝手の悪さが主要因だと思うのだが、以前に比べて利用頻度が大幅に下がってしまった。</li>
</ul>
<p>こうしてみると、サービスのメニューなどではなくアプリのUXの話ばかりなのが惜しい…。</p>
<p>今調べてみると Simplenote は <a href="https://github.com/Automattic/simplenote-macos">macOS 版</a>も <a href="https://github.com/Automattic/simplenote-android">Android 版</a>もアプリは OSS のようなので、contribute してみるのも面白いかもしれない。(が、それは目的ではない。)</p>
<p>Evernote に戻るにあたって、Simplenote に書いていたメモを移行する必要があったが、手軽な方法は見つからなかった。<br>
このため、すごく地道に、手動で一つずつコピー&ペーストする方法をとった。Simplenote で作成したメモだというのがわかるようにタグをつけた程度。この方法だと作成日・更新日の情報や Simplenote が持っていたスタイル情報などが失われてしまうが、そこは諦めた。</p>
<p>ということで、またEvernoteをしばらく使ってみたい。</p>
ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-76096700606382836882020-01-14T22:33:00.002+09:002020-01-14T22:33:36.389+09:00ダークモードに対応<p>このサイトもダークモードに対応しておこうと思い、<code>prefers-color-scheme</code> を使って配色を分けるようにしてみた。</p>
<p>基本的な方法を解説しているブログは多数あるので、その上で必要だった工夫をメモ。</p>
<p>全体の構成の方針としては、CSS変数を活用してライトモードとの重複コード、または漏れを防ぐようにした。</p>
<p>以下はCSSの構成イメージ。</p>
<a name='more'></a>
<pre class=" language-css"><code class="prism language-css"><span class="token selector"><span class="token pseudo-class">:root</span> </span><span class="token punctuation">{</span>
<span class="token comment">/* 変数定義 */</span>
<span class="token punctuation">}</span>
<span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">prefers-color-scheme</span><span class="token punctuation">:</span> dark<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
<span class="token selector"><span class="token pseudo-class">:root</span> </span><span class="token punctuation">{</span>
<span class="token comment">/* ダークモードの変数定義 */</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">/* 変数を使った定義 */</span>
<span class="token selector">body </span><span class="token punctuation">{</span>
<span class="token punctuation">}</span>
<span class="token punctuation">:</span>
</code></pre>
<p>以下は、このブログ固有の事情で注意が必要だったその他のポイント。</p>
<h2 id="意図しないライトモードの適用の回避">意図しないライトモードの適用の回避</h2>
<p>Syntax highlight には highlight.js を使用しており、このサイトのCSSの中に埋め込む構成をとっている。</p>
<p>当初、ダークモード用のテーマとライトモード用のテーマとで定義しているクラスに差分があった。最初は以下のように定義していたせいでダークモードでもライトモードの値が使用されてしまいおかしい配色になってしまった。</p>
<p>イメージ:</p>
<pre class=" language-css"><code class="prism language-css"><span class="token comment">/* ライトモード用のhighlight.jsテーマ */</span>
<span class="token selector"><span class="token class">.x</span> </span><span class="token punctuation">{</span> <span class="token number">...</span> <span class="token punctuation">}</span>
<span class="token selector"><span class="token class">.y</span> </span><span class="token punctuation">{</span> <span class="token number">...</span> <span class="token punctuation">}</span>
<span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">prefers-color-scheme</span><span class="token punctuation">:</span> dark<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
<span class="token comment">/* ダークモードのhighlight.jsテーマ */</span>
<span class="token selector"><span class="token class">.y</span> </span><span class="token punctuation">{</span> <span class="token number">...</span> <span class="token punctuation">}</span> <span class="token comment">/* .xはダークモードで上書きしていない */</span>
<span class="token punctuation">}</span>
</code></pre>
<p>そこで、ダークモードのときはライトモードのテーマを読み込まないように以下のように変更して対応した。</p>
<pre class=" language-css"><code class="prism language-css"><span class="token atrule"><span class="token rule">@media</span> not all and <span class="token punctuation">(</span><span class="token property">prefers-color-scheme</span><span class="token punctuation">:</span> dark<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
<span class="token comment">/* ライトモードのhighlight.jsテーマ */</span>
<span class="token punctuation">}</span>
<span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">prefers-color-scheme</span><span class="token punctuation">:</span> dark<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
<span class="token comment">/* ダークモードのhighlight.jsテーマ */</span>
<span class="token punctuation">}</span>
</code></pre>
<h2 id="アイコンのsvg化">アイコンのSVG化</h2>
<p>ラベルのアイコンをbase64エンコードして埋め込んで作っていたが、背景色が透過していなかったためダークモードで目立つ状態になってしまった。これを機にSVGに変更してどちらでもまともな見栄えになるように修正。</p>
<h2 id="コメント投稿フォームはそのまま諦め">コメント投稿フォームはそのまま(諦め)</h2>
<p>Bloggerのコメント投稿フォームはウィジェットとして簡単に埋め込めるが、白い背景であり、ダークモードに合わない。スタイルを変更できればよいが、iframeで実装されておりCSSを親から適用することができない。これは避けることができないため、ポップアップで開く設定にすることでダークモードの画面内に埋め込まないようにした。</p>
<p>モバイル版ではなぜかポップアップにすることができなかったため、埋め込みのままとしている。</p>
<h2 id="最初に一瞬白くなる未対応">最初に一瞬白くなる(未対応)</h2>
<p>おそらくテーマのデフォルトのCSSを先に読み込んでしまっているせいで、一瞬従来のライトモードの配色が反映されてしまう。<a href="https://ksoichiro.blogspot.com/2020/01/blogger-accessibility-performance.html">パフォーマンス改善</a>でCSSをHTMLに埋め込んだが、このCSSの中身もダークモード対応する必要がありそう。これは少し時間がかかりそうな気がするので一旦保留…。</p>
ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-9570044941132518462020-01-13T16:19:00.001+09:002020-01-13T16:19:13.105+09:00Blogger Accessibility Performance改善<p>以前改善してからまた時間がたったので、改めてLighthouseの点数改善にチャレンジ。</p>
<p>なお、Chromeでログインして拡張機能でLighthouseを使っている場合、シークレットウィンドウからの実行を許可した上でシークレットウィンドウから実行しないと、キャッシュが使われてしまい正しい結果が出ない。<br>
lighthouse の npm コマンドで実行するのが無難。</p>
<a name='more'></a>
<h2 id="accessibility-selectにlabelがついてない">Accessibility: selectにlabelがついてない</h2>
<p>このブログには上部に blog apps github というリンクがあり、モバイルの場合は select になっている。ここに label が設定されていないというもの。<br>
これは単に対象の select に title=‘Category’ と付与することで解決した。</p>
<h2 id="accessibility-iframe-に-title-がついていない">Accessibility: iframe に title がついていない</h2>
<p>BloggerのテーマのHTMLを"iframe"で検索したところ、コメントフォームにiframeがあった。<br>
title='comment-editor’を埋め込んで対応。</p>
<h2 id="accessibility-imageにaltがない">Accessibility: imageにaltがない</h2>
<p>class <code>mobile-index-thumbnail</code> に該当のものがあった。alt=’'を設定して解決。</p>
<p>これでついに Acccessibility が 100 点になった。</p>
<h2 id="performance-bloggerアイコンのcache">Performance: Bloggerアイコンのcache</h2>
<p>めったに変わるものでもないのでbase64化して埋め込みするのが良さそう。<br>
Font Awesomeのアイコンなどでも良かったが、ロゴアイコンなので一応配慮してBloggerのものを使うことにした。</p>
<pre class=" language-html"><code class="prism language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>profile-name-link g-profile<span class="token punctuation">'</span></span> <span class="token attr-name"><span class="token namespace">expr:</span>href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>data:i.userUrl<span class="token punctuation">'</span></span> <span class="token attr-name"><span class="token namespace">expr:</span></span><span class="token style-attr language-css"><span class="token attr-name"><span class="token attr-name">style</span></span><span class="token punctuation">='</span><span class="token attr-value">&quot<span class="token punctuation">;</span><span class="token property">background-image</span><span class="token punctuation">:</span> <span class="token url">url(&quot; + data:i.profileLogo + &quot;)</span><span class="token punctuation">;</span>&quot<span class="token punctuation">;</span></span><span class="token punctuation">'</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token namespace">data:</span>i.display-name</span><span class="token punctuation">/></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
</code></pre>
<p>これを以下に変更。</p>
<pre class=" language-html"><code class="prism language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>profile-name-link g-profile<span class="token punctuation">'</span></span> <span class="token attr-name"><span class="token namespace">expr:</span>href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>data:i.userUrl<span class="token punctuation">'</span></span> <span class="token attr-name"><span class="token namespace">expr:</span></span><span class="token style-attr language-css"><span class="token attr-name"><span class="token attr-name">style</span></span><span class="token punctuation">='</span><span class="token attr-value">&quot<span class="token punctuation">;</span><span class="token property">background-image</span><span class="token punctuation">:</span> <span class="token url">url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA3klEQVQ4y2P4l8YUCsT/ycT6DBRoBmNMA5IZ/v+LB+IYKI5lgIgRZUACUOH2jv//3j/5/+//fwj+8/P/vyNz/v8rliRgQDJUM0jTv39oGCh2ceP/f0kMeAwAORtkM0gDyJBzqyEYZiCILpXCYwDIvzDF1/YAFUtCMIgNM2BVyf9/hWJEGPD3LyIMQGx0sRgGEgxAN4goA2BeqJCDYHSvYDUAWyCCQh6EkQPz08v//+IYSI3GfwiD58cTSEggBSBb0MMAJAaSS2AgkJRBOA4pKcNwHAOReYGMzKRPgQEGAIvy2M2lOZIeAAAAAElFTkSuQmCC)</span><span class="token punctuation">;</span>&quot<span class="token punctuation">;</span></span><span class="token punctuation">'</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token namespace">data:</span>i.display-name</span><span class="token punctuation">/></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
</code></pre>
<p>もう一つ。</p>
<pre class=" language-html"><code class="prism language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>profile-name-link g-profile<span class="token punctuation">'</span></span> <span class="token attr-name"><span class="token namespace">expr:</span>href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>data:userUrl<span class="token punctuation">'</span></span> <span class="token attr-name"><span class="token namespace">expr:</span></span><span class="token style-attr language-css"><span class="token attr-name"><span class="token attr-name">style</span></span><span class="token punctuation">='</span><span class="token attr-value">&quot<span class="token punctuation">;</span><span class="token property">background-image</span><span class="token punctuation">:</span> <span class="token url">url(&quot; + data:profileLogo + &quot;)</span><span class="token punctuation">;</span>&quot<span class="token punctuation">;</span></span><span class="token punctuation">'</span></span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>author<span class="token punctuation">'</span></span><span class="token punctuation">></span></span>
</code></pre>
<p>これを以下に変更。</p>
<pre class=" language-html"><code class="prism language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>profile-name-link g-profile<span class="token punctuation">'</span></span> <span class="token attr-name"><span class="token namespace">expr:</span>href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>data:userUrl<span class="token punctuation">'</span></span> <span class="token attr-name"><span class="token namespace">expr:</span></span><span class="token style-attr language-css"><span class="token attr-name"><span class="token attr-name">style</span></span><span class="token punctuation">='</span><span class="token attr-value">&quot<span class="token punctuation">;</span><span class="token property">background-image</span><span class="token punctuation">:</span> <span class="token url">url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA3klEQVQ4y2P4l8YUCsT/ycT6DBRoBmNMA5IZ/v+LB+IYKI5lgIgRZUACUOH2jv//3j/5/+//fwj+8/P/vyNz/v8rliRgQDJUM0jTv39oGCh2ceP/f0kMeAwAORtkM0gDyJBzqyEYZiCILpXCYwDIvzDF1/YAFUtCMIgNM2BVyf9/hWJEGPD3LyIMQGx0sRgGEgxAN4goA2BeqJCDYHSvYDUAWyCCQh6EkQPz08v//+IYSI3GfwiD58cTSEggBSBb0MMAJAaSS2AgkJRBOA4pKcNwHAOReYGMzKRPgQEGAIvy2M2lOZIeAAAAAElFTkSuQmCC)</span><span class="token punctuation">;</span>&quot<span class="token punctuation">;</span></span><span class="token punctuation">'</span></span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>author<span class="token punctuation">'</span></span><span class="token punctuation">></span></span>
</code></pre>
<h2 id="webフォントの読み込みが遅い">Webフォントの読み込みが遅い</h2>
<p>単に link タグで貼り付けていたものを、こちらを参考に非同期化する。: <a href="https://hail2u.net/blog/webdesign/async-web-font-loader.html">https://hail2u.net/blog/webdesign/async-web-font-loader.html</a><br>
さらに Lato は利用を諦めて Noto Sans JP のみにした。<br>
Web フォントのロード中にも文字が描画されるように、display=swap をつけておく。</p>
<pre class=" language-javascript"><code class="prism language-javascript"><span class="token operator"><</span>script<span class="token operator">></span>
<span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span>d<span class="token punctuation">,</span> f<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">var</span> l <span class="token operator">=</span> d<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'link'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
l<span class="token punctuation">.</span>rel <span class="token operator">=</span> <span class="token string">'stylesheet'</span><span class="token punctuation">;</span>
l<span class="token punctuation">.</span>href <span class="token operator">=</span> f<span class="token punctuation">;</span>
<span class="token keyword">var</span> s <span class="token operator">=</span> d<span class="token punctuation">.</span><span class="token function">getElementsByTagName</span><span class="token punctuation">(</span><span class="token string">'script'</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
s<span class="token punctuation">.</span>parentNode<span class="token punctuation">.</span><span class="token function">insertBefore</span><span class="token punctuation">(</span>l<span class="token punctuation">,</span> s<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span>document<span class="token punctuation">,</span> <span class="token string">'https://fonts.googleapis.com/css?family=Noto+Sans+JP:400,700&display=swap'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator"><</span><span class="token operator">/</span>script<span class="token operator">></span>
</code></pre>
<h2 id="widget_css_mobile_2_bundle.cssの読み込みが遅い">widget_css_mobile_2_bundle.cssの読み込みが遅い</h2>
<p>こちらを参考に無効化してみる: <a href="http://blogger.weblix.net/2013/02/blogger-remove-bundle-css.html">http://blogger.weblix.net/2013/02/blogger-remove-bundle-css.html</a></p>
<pre class=" language-html"><code class="prism language-html"> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token namespace">b:</span>skin</span><span class="token punctuation">></span></span><span class="token cdata"><![CDATA[
]]></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span><span class="token namespace">b:</span>skin</span><span class="token punctuation">></span></span>
</code></pre>
<p>これを以下のようにする。</p>
<pre class=" language-html"><code class="prism language-html"><span class="token entity" title="<">&lt;</span>style type=<span class="token entity" title=""">&quot;</span>text/css<span class="token entity" title=""">&quot;</span><span class="token entity" title=">">&gt;</span>
<span class="token entity" title="<">&lt;</span>!-- /*<span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token namespace">b:</span>skin</span><span class="token punctuation">></span></span><span class="token cdata"><![CDATA[*/]]></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span><span class="token namespace">b:</span>skin</span><span class="token punctuation">></span></span>
</code></pre>
<p>うまくいかない…<br>
今度はこちらを参考に: <a href="http://holidaybuggy.blogspot.com/2017/03/bloggerbundlecss.html">http://holidaybuggy.blogspot.com/2017/03/bloggerbundlecss.html</a><br>
こちらは成功。だいぶ点数が改善した。<br>
authorization.cssは空のようだったので省いている。<br>
また、若干文法エラーがあったので修正している。</p>
<pre class=" language-html"><code class="prism language-html"><b:if cond='data:blog.isMobile’>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>!--モバイル環境の場合—</span><span class="token punctuation">></span></span>
<style type='text/css’><span class="token style language-css">
//*-widget_css_mobile_<span class="token number">2</span>_bundle<span class="token number">.</span>cssの内容
</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>style</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token namespace">b:</span>else</span><span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>!--PC環境の場合—</span><span class="token punctuation">></span></span>
<style type='text/css’><span class="token style language-css">
//*-css_bundle_v<span class="token number">2.</span>cssの内容
</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>style</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span><span class="token namespace">b:</span>if</span><span class="token punctuation">></span></span>
</code></pre>
<h2 id="人気の投稿のサムネイル画像の読み込みが遅い">人気の投稿のサムネイル画像の読み込みが遅い</h2>
<p><code>img</code> に <code>decoding="async"</code> を付与する。</p>
<pre class=" language-html"><code class="prism language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token namespace">b:</span>with</span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>data:post.featuredImage.isResizable ? resizeImage(data:post.featuredImage, 72, <span class="token entity" title=""">&quot;</span>1:1<span class="token entity" title=""">&quot;</span>) : data:post.thumbnail<span class="token punctuation">'</span></span> <span class="token attr-name">var</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>image<span class="token punctuation">'</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span><span class="token punctuation">'</span></span> <span class="token attr-name">decoding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>async<span class="token punctuation">'</span></span> <span class="token attr-name">border</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>0<span class="token punctuation">'</span></span> <span class="token attr-name"><span class="token namespace">expr:</span>src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>data:image<span class="token punctuation">'</span></span><span class="token punctuation">/></span></span>
</code></pre>
<p>以上でほぼ満点となった!</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHk-t9l5Nm9Se7KRk44W6uF-7xtRg11m1tiPl-bKgXxVmt5LELsUXGYbop_Y_SKcsedb6QJ7YvPYz1W01de37ExG5WdLCljO1O0jaKQri-wUdLE0AHwkeLpZrr5R6Cho4iSBfeO1x8os8E/w500/" alt=""></p>
ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-25065795360910465462020-01-12T01:05:00.002+09:002020-01-12T01:05:49.535+09:00かなり今さらながらghqやpecoなどをきちんと使ってみる<p>今さらすぎるだろという話ではあるのだが、<a href="https://github.com/motemen/ghq">ghq</a>、<a href="https://github.com/peco/peco">peco</a>などのツールを、知っていたけどちゃんと普段使いしたことがなかった。以前は Java 中心の開発をしていたせいか CLI はそれほど身近でないというか、あまり高頻度に使わなくても問題のない世界だった。今の職場では、こうしたツールなしでは難があるなと感じてようやく導入した。今さら書くのも恥ずかしい気はするのだが…いくつか気づきや工夫があったので書いておきたい。</p>
<a name='more'></a>
<p>導入する前にやっていたこと、思っていたことは以下の通り。</p>
<ol>
<li>~/workspace などのディレクトリを作り、基本的にそこにすべて clone していた。</li>
<li>Go のリポジトリの場合、go get すると $GOPATH/src に配置されてしまうし、GOPATH から外れようとすると色々問題が起こるため結局諦めるものの、Go だけ別管理になって嫌だな…という違和感を抱いていた。</li>
<li>ghq を使うとリポジトリが1つのディレクトリにフラットに並ばないので、Git の GUI ツールで様々なリポジトリを扱うのが面倒になるのではないかと思っていた。</li>
</ol>
<p>実際に試してみて、上記はすべて解決して今のところ快適に扱えている。</p>
<p>まず ~/workspace, ~/go/src を ghq の root に設定する。デフォルトのrootから変更したり複数のroot を設定したりしたいには ~/.gitconfig に記述すればよい。こうしておけば、Go の場合は go get で ~/go/src に配置、その他は ghq get で ~/workspace に配置されるが、ghq list でどちらでも検索することができる。</p>
<p>Go のバージョンをすぐ切り替えられるように <a href="https://github.com/syndbg/goenv">goenv</a> を使うと、デフォルトでは ~/go/1.13.4 のように GOPATH にバージョン番号が含まれてしまう。この仕様だと、バージョンを追加したり切り替えるたびに clone し直したり ghq root の変更が必要になると考えていたが、goenv が GOPATH を変更するのは無効化することができた: <code>export GOENV_DISABLE_GOPATH=1</code> とすれば良い。</p>
<p>そしてGUIのGitクライアントについて。最近は <a href="https://git-fork.com/">Fork</a> を使っている。そもそも GUI 必要なの?という点については、もちろんコマンドやIDE付属のもので基本的な操作はできるのだが、複数のブランチを比較したり、merge や rebase をしたりするときにはブランチを視覚的に見れたほうが安心感があるため、GUIも併用している (この時点で負けてる感じもする…)。これについては、VSCode での code コマンドのような感じで fork コマンドというのがインストールできるようになっていたため、ターミナル上でプロジェクトのディレクトリに移動して <code>fork .</code> とすれば簡単に Fork で開くことができた。他のプロジェクトに簡単に移動するのに使うのは ghq と peco を組み合わせればできる。つまり、多数のプロジェクトを同じディレクトリにフラットに並べなくておかなくても簡単に開ける。</p>
<p>というわけで、ghqやpecoの設定。</p>
<p>まず ~/.gitconfig での ghq の root 設定。これは先ほど説明した通り。</p>
<pre><code>[ghq]
root = ~/Workspace
root = ~/go/src
</code></pre>
<p>peco については、オーソドックスに zshrc にて 履歴の検索、移動先リポジトリの検索、移動履歴の検索を設定して使ってみている。peco の prompt は <code>QUERY></code> だが、設定したキーが身体に染み付いていないせいか、今何の検索画面が出ているんだっけ?となってしまうことが何度かあったため、prompt には icon font を設定して区別ができるようにしている。</p>
<pre class=" language-sh"><code class="prism language-sh"># peco + history
function peco-history-selection() {
BUFFER=`history -n 1 | tail -r | awk '!a[$0]++' | peco --prompt "❯"`
CURSOR=$#BUFFER
zle reset-prompt
}
zle -N peco-history-selection
bindkey '^R' peco-history-selection
# peco + ghq
function peco-src () {
local selected_dir=$(ghq list -p | peco --prompt "❯" --query "$LBUFFER")
if [ -n "$selected_dir" ]; then
BUFFER="cd ${selected_dir}"
zle accept-line
fi
#zle clear-screen
}
zle -N peco-src
bindkey '^g' peco-src
# peco + cdr
if [[ -n $(echo ${^fpath}/chpwd_recent_dirs(N)) && -n $(echo ${^fpath}/cdr(N)) ]]; then
autoload -Uz chpwd_recent_dirs cdr add-zsh-hook
add-zsh-hook chpwd chpwd_recent_dirs
zstyle ':completion:*' recent-dirs-insert both
zstyle ':chpwd:*' recent-dirs-default true
zstyle ':chpwd:*' recent-dirs-max 1000
zstyle ':chpwd:*' recent-dirs-file "$HOME/.cache/chpwd-recent-dirs"
fi
function peco-cdr () {
local selected_dir="$(cdr -l | sed 's/^[0-9]* *//' | peco --prompt "❯" --query "$LBUFFER")"
if [ -n "$selected_dir" ]; then
BUFFER="cd ${selected_dir}"
zle accept-line
fi
}
zle -N peco-cdr
bindkey '^J' peco-cdr
</code></pre>
ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-14629928177887120622020-01-12T00:01:00.002+09:002020-01-12T00:01:54.675+09:00Terraform: API Gatewayでdeploymentとstageでstage_nameがconflictする<p>プライベートでVPSを借りて動かしている古いAPIがある。これをAWSに移行しようと考えており、その過程でTerraformを使ってコード化を進めている。</p>
<p>その中で API Gateway を使っているのだが、stage、deploymentのresourceを普通に定義していったところ、conflictしてしまい正常に実行できなかった。</p>
<a name='more'></a>
<p>GitHub でも issue が見つかり <code>stage_name</code> を <code>”"</code> とするという解法も見つけた。<br>
<a href="https://github.com/terraform-providers/terraform-provider-aws/issues/2918">Error creating API Gateway Stage: ConflictException: Stage already exists #2918</a></p>
<p>以下のような形になる。</p>
<pre><code>resource "aws_api_gateway_stage" "stage" {
depends_on = ["aws_cloudwatch_log_group.log-group-api-gateway-rest-api"]
stage_name = "${var.stage-name}"
rest_api_id = "${aws_api_gateway_rest_api.api-gateway-rest-api.id}"
deployment_id = "${aws_api_gateway_deployment.api-gateway-deployment.id}"
}
resource "aws_api_gateway_deployment" "api-gateway-deployment" {
depends_on = ["aws_api_gateway_integration.api-gateway-integration"]
rest_api_id = "${aws_api_gateway_rest_api.api-gateway-rest-api.id}"
stage_name = ""
}
</code></pre>
<p>一見これで解決するようにも思えたが、API Gateway の設定を変更してデプロイしなければならないときには deploymentを更新する必要があり、そのときには <code>stage_name</code> が空では動かない。</p>
<p>対策として、stageの定義自体は実はdeploymentにも情報が含まれているため、stageに含まれていた depends_on を deployment に移し、deployment に統合してstageのresource定義を廃止した。</p>
<pre><code>resource "aws_api_gateway_deployment" "api-gateway-deployment" {
depends_on = ["aws_cloudwatch_log_group.log-group-api-gateway-rest-api", "aws_api_gateway_integration.api-gateway-integration"]
rest_api_id = "${aws_api_gateway_rest_api.api-gateway-rest-api.id}"
stage_name = "${var.api-gateway-rest-api-stage-name}"
stage_description = "${md5(file("../../modules/apigateway.tf"))}"
lifecycle {
create_before_destroy = true
}
}
</code></pre>
<p>なお、設定変更しても deploy してくれない問題を避けるため、deployment の stage_description は tf ファイルの内容が変わったら変更が入ったとみなされるようにしている。</p>
ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-25057432040967961392020-01-11T23:36:00.002+09:002020-01-11T23:36:55.920+09:00ghqのroot配下ではVCS導入しないとghq listが遅くなる<p>今さらながら ghq を使うのをデフォルトにしようと考えてローカルにあるリポジトリをすべて ghq の root に移したところ、ghq list がだいぶ遅くなったように感じた。</p>
<p>以下が原因&解決策であった。<br>
<a href="https://hirakiuc.hatenablog.com/entry/2017/05/06/205846">https://hirakiuc.hatenablog.com/entry/2017/05/06/205846</a></p>
<p>バージョン管理システムがないディレクトリが多数含まれていると遅くなってしまうらしい。</p>
<p>サンプルプロジェクトは <code>~/.ghq/github.com/ksoichiro</code> に移動してあったため、そのディレクトリで以下を実行して git 管理としたところ改善した。(管理といっても git init しているだけ)</p>
<pre class=" language-sh"><code class="prism language-sh">for i in $(ls -1); do if [ ! -f $i/.git/config ]; then echo "$i is not in vcs"; pushd $i > /dev/null; git init; popd > /dev/null; fi; done
</code></pre>
ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-88210144986136539142020-01-11T23:30:00.001+09:002020-01-11T23:30:45.152+09:00一区切り...<p>2019年は自分にとって大きな変化のあった年となった。あまりそれ自体については詳しくは書かないつもりだが、具体的にいうと転職して12月から新しい職場で働いている。</p>
<p>このブログの更新も停滞していたが、これを機に再開していきたい。</p>
<a name='more'></a>
<p>これからプログラミングなど、このブログで扱うような内容について費やす時間が増えると思われるので、関連する内容をアウトプットしていきたい。</p>
<p>また、これは今まで思いつつもやれていなかったことだが、記事が短かったとしても積極的に書いていくようにしたいと思っている。例えば、数回Google検索しても見つからなかったのであれば、それを解決したという記事は、たとえ1行であっても誰かの役に立つかもしれない。</p>
<p>新しい職場ではスゴい人が多いのだが…ではこのブログに書くネタがないくらい何も困らないのか、といえば違うし、当然大小の躓きはあるし、ちょっと工夫してみようとしたら調べ物が必要になる。むしろ、書くネタが見つからないのであればチャレンジ不足というくらいで考えていきたい。</p>
ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-80030272422621804002019-05-01T14:36:00.001+09:002019-05-01T14:36:44.105+09:00GitLab CI をセットアップする<p>今さらだが、自分でセットアップする機会ができたので。</p>
<p>ただのセットアップは公式のマニュアルなどで確認できるので、ここでは実際にビルド、テスト、レビューで活用できるようにするためのことを書く。 <br>
かなりの長文なので注意。 <br>
<a name='more'></a></p>
<h2 id="事前準備">事前準備</h2>
<p>検証には <a href="https://github.com/ksoichiro/gitlab-i18n-patch">gitlab-i18n-patch</a> を利用して Vagrant の GitLab v11.9.8 の VM を使用する。 <br>
<code>private_network</code> で IP アドレス <code>192.168.33.10</code> を指定しておく。 <br>
GitLab の VM には CPU x 2、4 GB を割り当てておく。 <br>
GitLab Runner の VM には CPU x 2、3GB を割り当てておく。</p>
<h2 id="gitlab-runner-インストール">GitLab Runner インストール</h2>
<p>こちらを参考にインストールする。 <br>
<a href="https://docs.gitlab.com/11.9/runner/install/linux-manually.html">https://docs.gitlab.com/11.9/runner/install/linux-manually.html</a></p>
<p>Vagrant で ubuntu/trusty64 の VM を作成。 <br>
インストールできるバージョンについては以下を参照。</p>
<ul>
<li><a href="https://docs.gitlab.com/11.9/runner/install/bleeding-edge.html#download-any-other-tagged-release">https://docs.gitlab.com/11.9/runner/install/bleeding-edge.html#download-any-other-tagged-release</a></li>
<li><a href="https://gitlab.com/gitlab-org/gitlab-runner/tags">https://gitlab.com/gitlab-org/gitlab-runner/tags</a></li>
</ul>
<pre class="prettyprint"><code class="language-sh hljs lasso">vagrant ssh
sudo su <span class="hljs-subst">-</span>
wget <span class="hljs-attribute">-O</span> /usr/<span class="hljs-built_in">local</span>/bin/gitlab<span class="hljs-attribute">-runner</span> https:<span class="hljs-comment">//gitlab-runner-downloads.s3.amazonaws.com/v11.9.2/binaries/gitlab-runner-linux-amd64</span>
chmod <span class="hljs-subst">+</span>x /usr/<span class="hljs-built_in">local</span>/bin/gitlab<span class="hljs-attribute">-runner</span>
curl <span class="hljs-attribute">-sSL</span> https:<span class="hljs-comment">//get.docker.com/ | sh</span>
useradd <span class="hljs-subst">--</span>comment <span class="hljs-string">'GitLab Runner'</span> <span class="hljs-subst">--</span>create<span class="hljs-attribute">-home</span> gitlab<span class="hljs-attribute">-runner</span> <span class="hljs-subst">--</span>shell /bin/bash
gitlab<span class="hljs-attribute">-runner</span> install <span class="hljs-subst">--</span>user<span class="hljs-subst">=</span>gitlab<span class="hljs-attribute">-runner</span> <span class="hljs-subst">--</span>working<span class="hljs-attribute">-directory</span><span class="hljs-subst">=</span>/home/gitlab<span class="hljs-attribute">-runner</span>
gitlab<span class="hljs-attribute">-runner</span> start</code></pre>
<p>これでインストールは完了。</p>
<h2 id="トークン取得初期設定">トークン取得、初期設定</h2>
<p>GitLab の 管理>概要>Runner からトークンを参照する。</p>
<pre class="prettyprint"><code class="language-sh hljs markdown">root@vagrant-ubuntu-trusty-64:~# gitlab-runner register
Runtime platform arch=amd64 os=linux pid=10312 revision=fa86510e version=11.9.2
Running in system-mode.
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
http://192.168.33.10/
Please enter the gitlab-ci token for this runner:
DZt6Gx2oWtbm1T9G3xZE
Please enter the gitlab-ci description for this runner:
[<span class="hljs-link_reference">vagrant-ubuntu-trusty-64</span>]:<span class="hljs-link_url">
Please enter the gitlab-ci tags for this runner (comma separated):</span><span class="hljs-link_url">
</span><span class="hljs-link_url">
Registering runner... succeeded runner=DZt6Gx2o</span><span class="hljs-link_url">
Please enter the executor: shell, docker+machine, docker-ssh+machine, docker, docker-ssh, parallels, ssh, virtualbox, kubernetes:</span><span class="hljs-link_url">
docker</span><span class="hljs-link_url">
Please enter the default Docker image (e.g. ruby:2.1):</span><span class="hljs-link_url">
ruby:2.1</span><span class="hljs-link_url">
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!</span><span class="hljs-link_url">
root@vagrant-ubuntu-trusty-64:~# gitlab-runner restart</span><span class="hljs-link_url">
Runtime platform arch=amd64 os=linux pid=10320 revision=fa86510e version=11.9.2</span></code></pre>
<p>登録が完了すると、GitLab の 管理>概要>Runner の画面で一覧表示される。 <br>
最初は <code>locked</code> の表示になっているため、鉛筆のアイコンから編集してロックを解除する。</p>
<p>試してみると、以下のようなエラーで失敗。</p>
<pre class="prettyprint"><code class=" hljs r">Running with gitlab-runner <span class="hljs-number">11.9</span><span class="hljs-number">.2</span> (fa86510e)
on vagrant-ubuntu-trusty-<span class="hljs-number">64</span> FrxqXAaT
Using Docker executor with image node:<span class="hljs-number">8.15</span><span class="hljs-number">.0</span>-alpine <span class="hljs-keyword">...</span>
ERROR: Failed to create container volume <span class="hljs-keyword">for</span> /builds/root Error response from daemon: OCI runtime create failed: container_linux.go:<span class="hljs-number">348</span>: starting container process caused <span class="hljs-string">"process_linux.go:297: copying bootstrap data to pipe caused \"write init-p: broken pipe\""</span>: unknown (executor_docker.go:<span class="hljs-number">423</span>:1s)
ERROR: Preparation failed: Error response from daemon: OCI runtime create failed: container_linux.go:<span class="hljs-number">348</span>: starting container process caused <span class="hljs-string">"process_linux.go:297: copying bootstrap data to pipe caused \"write init-p: broken pipe\""</span>: unknown (executor_docker.go:<span class="hljs-number">423</span>:1s)
Will be retried <span class="hljs-keyword">in</span> 3s <span class="hljs-keyword">...</span></code></pre>
<p><a href="https://gitlab.com/gitlab-org/gitlab-runner/issues/3457">GitLab Runner #3457</a> に辿り着いたが、こちらを参考にすると以下のセットアップが必要だった模様。 <br>
<a href="https://docs.gitlab.com/ee/ci/docker/using_docker_build.html">https://docs.gitlab.com/ee/ci/docker/using_docker_build.html</a></p>
<pre class="prettyprint"><code class="language-sh hljs lasso">sudo <span class="hljs-attribute">-u</span> gitlab<span class="hljs-attribute">-runner</span> <span class="hljs-attribute">-H</span> docker info</code></pre>
<p>以下の結果となった。</p>
<pre class="prettyprint"><code class=" hljs livecodeserver">Got permission denied <span class="hljs-keyword">while</span> trying <span class="hljs-built_in">to</span> connect <span class="hljs-built_in">to</span> <span class="hljs-operator">the</span> Docker daemon <span class="hljs-built_in">socket</span> <span class="hljs-keyword">at</span> unix:<span class="hljs-comment">///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.38/info: dial unix /var/run/docker.sock: connect:</span>
permission denied</code></pre>
<p>gitlab-runner ユーザを docker グループに追加。</p>
<pre class="prettyprint"><code class="language-sh hljs lasso">usermod <span class="hljs-attribute">-aG</span> docker gitlab<span class="hljs-attribute">-runner</span></code></pre>
<p>もう一度確認すると、この確認は成功した。</p>
<pre class="prettyprint"><code class=" hljs r">sudo -u gitlab-runner -H docker info
Containers: <span class="hljs-number">0</span>
Running: <span class="hljs-number">0</span>
Paused: <span class="hljs-number">0</span>
Stopped: <span class="hljs-number">0</span>
Images: <span class="hljs-number">1</span>
Server Version: <span class="hljs-number">18.06</span><span class="hljs-number">.3</span>-ce
Storage Driver: aufs
Root Dir: /var/lib/docker/aufs
Backing Filesystem: extfs
Dirs: <span class="hljs-number">1</span>
Dirperm1 Supported: false
<span class="hljs-keyword">...</span></code></pre>
<p>しかしジョブをリトライするとまたもや失敗。 <br>
以下も失敗していて、dockerのインストール自体がうまくいっていなかった模様。</p>
<pre class="prettyprint"><code class="language-sh hljs applescript">docker <span class="hljs-command">run</span> hello-world</code></pre>
<p>以下を参考に Docker を再インストール。</p>
<p><a href="https://github.com/opencontainers/runc/issues/1343">https://github.com/opencontainers/runc/issues/1343</a></p>
<pre class="prettyprint"><code class="language-sh hljs lasso">apt<span class="hljs-attribute">-get</span> <span class="hljs-attribute">-y</span> install <span class="hljs-subst">--</span>force<span class="hljs-attribute">-yes</span> docker<span class="hljs-attribute">-ce</span><span class="hljs-subst">=</span><span class="hljs-number">18.06</span><span class="hljs-number">.1</span>~ce~<span class="hljs-number">3</span><span class="hljs-subst">-</span><span class="hljs-number">0</span>~ubuntu</code></pre>
<p><code>docker run hello-world</code> は成功。リトライすると、ジョブも無事成功。</p>
<pre class="prettyprint"><code class=" hljs r">Running with gitlab-runner <span class="hljs-number">11.9</span><span class="hljs-number">.2</span> (fa86510e)
on vagrant-ubuntu-trusty-<span class="hljs-number">64</span> FrxqXAaT
Using Docker executor with image node:<span class="hljs-number">8.15</span><span class="hljs-number">.0</span>-alpine <span class="hljs-keyword">...</span>
Pulling docker image node:<span class="hljs-number">8.15</span><span class="hljs-number">.0</span>-alpine <span class="hljs-keyword">...</span>
Using docker image sha256:e8ae960eaa9e4aeb9741d7d34178e375d218e59f98699962dc03ffcd3c8192bf <span class="hljs-keyword">for</span> node:<span class="hljs-number">8.15</span><span class="hljs-number">.0</span>-alpine <span class="hljs-keyword">...</span>
Running on runner-FrxqXAaT-project-<span class="hljs-number">2</span>-concurrent-<span class="hljs-number">0</span> via vagrant-ubuntu-trusty-<span class="hljs-number">64.</span>..
Initialized empty Git repository <span class="hljs-keyword">in</span> /builds/root/gitlab-ci-test/.git/
Clean repository
Fetching changes...
Created fresh repository.
From http://<span class="hljs-number">192.168</span><span class="hljs-number">.33</span><span class="hljs-number">.10</span>/root/gitlab-ci-test
* [new branch] master -> origin/master
Checking out b71eea8f as master...
Skipping Git submodules setup
$ npm install
added <span class="hljs-number">196</span> packages from <span class="hljs-number">543</span> contributors and audited <span class="hljs-number">400</span> packages <span class="hljs-keyword">in</span> <span class="hljs-number">32.</span>854s
found <span class="hljs-number">1</span> high severity vulnerability
run `npm audit fix` to fix them, or `npm audit` <span class="hljs-keyword">for</span> details
$ npm test
> @ test /builds/root/gitlab-ci-test
> nyc mocha
index
✓ <span class="hljs-comment">#func()</span>
<span class="hljs-number">1</span> passing (45ms)
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line <span class="hljs-comment">#s |</span>
----------|----------|----------|----------|----------|-------------------|
All files | <span class="hljs-number">100</span> | <span class="hljs-number">100</span> | <span class="hljs-number">100</span> | <span class="hljs-number">100</span> | |
index.js | <span class="hljs-number">100</span> | <span class="hljs-number">100</span> | <span class="hljs-number">100</span> | <span class="hljs-number">100</span> | |
----------|----------|----------|----------|----------|-------------------|
Job succeeded</code></pre>
<p>なお、このときの <code>.gitlab-ci.yml</code> の内容は以下の通り。 <br>
GitLab.com で CI を試したプロジェクト <a href="https://gitlab.com/ksoichiro/citest">citest</a> を利用した。</p>
<pre class="prettyprint"><code class="language-yaml hljs http"><span class="hljs-attribute">image</span>: <span class="hljs-string">node:8.15.0-alpine</span>
<span class="haml">stages:
-<span class="ruby"> build
</span>
before_script:
-<span class="ruby"> npm install
</span>
build:
stage: build
script: npm test</span></code></pre>
<h2 id="複数の-runner-のセットアップ">複数の Runner のセットアップ</h2>
<p>以下のようにコマンドを複数回実行すれば良い。 <br>
トークンは検証用の VM で発行したもので実際のものに読み替える。</p>
<pre class="prettyprint"><code class="language-sh hljs haml">sudo gitlab-runner register -n \
-<span class="ruby">-url <span class="hljs-symbol">http:</span>/<span class="hljs-regexp">/192.168.33.10/</span> \
</span> -<span class="ruby">-registration-token <span class="hljs-constant">DZt6Gx2oWtbm1T9G3xZE</span> \
</span> -<span class="ruby">-executor docker \
</span> -<span class="ruby">-description <span class="hljs-string">"My Docker Runner"</span> \
</span> -<span class="ruby">-docker-image <span class="hljs-string">"docker:stable"</span> \
</span> -<span class="ruby">-docker-privileged</span></code></pre>
<h2 id="artifact-の利用">Artifact の利用</h2>
<p>例えば Java のプロジェクトであれば jar ファイルなど、ビルドの成果物 (artifact) を利用することがあるはず。</p>
<p>サンプルの Java プロジェクトとして GitHub においてある <a href="https://github.com/ksoichiro/task">task</a> リポジトリを利用。</p>
<p>以下のように <code>.gitlab-ci.yml</code> を追加する。</p>
<pre class="prettyprint"><code class="language-yaml hljs http"><span class="hljs-attribute">image</span>: <span class="hljs-string">adoptopenjdk/openjdk8:x86_64-ubuntu-jdk8u212-b03-slim</span>
<span class="haml">stages:
-<span class="ruby"> build
</span>
build:
stage: build
before_script:
-<span class="ruby"> apt-get update > <span class="hljs-regexp">/dev/null</span>
</span> -<span class="ruby"> apt-get install -y git > <span class="hljs-regexp">/dev/null</span>
</span> -<span class="ruby"> chmod +x gradlew
</span>
script:
-<span class="ruby"> ./gradlew assemble --stacktrace --no-daemon
</span>
after_script:
-<span class="ruby"> ls -al subprojects/site/build/libs
</span>
artifacts:
paths:
-<span class="ruby"> subprojects/*<span class="hljs-regexp">/build/libs</span><span class="hljs-regexp">/*.jar
</span></span> expire_in: 1 week</span></code></pre>
<p>これで、ジョブから jar ファイルをダウンロードできるようになる。</p>
<h2 id="キャッシュの利用">キャッシュの利用</h2>
<p>上記の Java プロジェクトでは Gradle を使っているが、Gradle Wrapper を使ってダウンロードされた Gradle などをキャッシュしないと、ビルドの都度外部からダウンロードすることになり非常に遅いため、キャッシュの設定を追加する。</p>
<p>Gradle のファイルが通常キャッシュされる位置はプロジェクトのフォルダではないが、GitLab CI のキャッシュはプロジェクトフォルダ配下のみのようなので調整する必要がある。</p>
<p><a href="https://stackoverflow.com/a/35478988">Stackoverflow</a> を参考にすると、<code>GRADLE_USER_HOME</code> 環境変数を変更すれば良いらしい。</p>
<p><code>cache:paths</code> でキャッシュのパスを指定しつつ、起点となるディレクトリを <code>before_script</code> で <code>GRADLE_USER_HOME</code> 環境変数を使って指定する。</p>
<pre class="prettyprint"><code class="language-yaml hljs http"><span class="hljs-attribute">image</span>: <span class="hljs-string">adoptopenjdk/openjdk8:x86_64-ubuntu-jdk8u212-b03-slim</span>
<span class="haml">stages:
-<span class="ruby"> build
</span>
build:
stage: build
cache:
paths:
-<span class="ruby"> .gradle/wrapper
</span> -<span class="ruby"> .gradle/caches
</span>
before_script:
-<span class="ruby"> apt-get update > <span class="hljs-regexp">/dev/null</span>
</span> -<span class="ruby"> apt-get install -y git > <span class="hljs-regexp">/dev/null</span>
</span> -<span class="ruby"> chmod +x gradlew
</span> -<span class="ruby"> export <span class="hljs-constant">GRADLE_USER_HOME</span>=`pwd`/.gradle
</span>
script:
-<span class="ruby"> ./gradlew clean assemble --stacktrace --no-daemon
</span>
after_script:
-<span class="ruby"> ls -al subprojects/site/build/libs
</span> -<span class="ruby"> ls -al .gradle/wrapper
</span> -<span class="ruby"> ls -al .gradle/caches
</span>
artifacts:
paths:
-<span class="ruby"> subprojects/*<span class="hljs-regexp">/build/libs</span><span class="hljs-regexp">/*.jar
</span></span> expire_in: 1 week</span></code></pre>
<h2 id="danger-を使う">Danger を使う</h2>
<p>レビューの一部を自動化するために <a href="https://danger.systems/ruby/">Danger</a> を導入する。 <br>
JavaScript にしたかったが、現時点ではまだ JavaScript 版は GitLab と統合できていないようなので見送り。</p>
<p>プロジェクトの設定>CI / CD>環境変数にて、<code>DANGER_GILTAB_API_TOKEN</code> を定義しておく。値は自分自身またはボット用アカウントで発行した API アクセストークン。 <br>
トークンはユーザの設定画面のアクセストークン画面で、api のスコープにチェックを入れて発行する。</p>
<p>また、以下の値を <code>.gitlab-ci.yml</code> の variables に定義しておく。</p>
<ul>
<li><code>DANGER_GITLAB_HOST</code></li>
<li><code>DANGER_GITLAB_API_BASE_URL</code></li>
</ul>
<p>以下は <code>review</code> というジョブを追加したもの。</p>
<pre class="prettyprint"><code class="language-yaml hljs haml">stages:
-<span class="ruby"> build
</span>
variables:
DANGER_GITLAB_API_BASE_URL: http://192.168.33.10/api/v4
DANGER_GITLAB_HOST: 192.168.33.10
review:
stage: build
image: ruby:2.6-stretch
only:
variables:
-<span class="ruby"> <span class="hljs-variable">$DANGER_GITLAB_API_TOKEN</span>
</span>
before_script:
-<span class="ruby"> gem install danger-gitlab
</span> -<span class="ruby"> danger --version
</span>
script:
-<span class="ruby"> danger --fail-on-errors=<span class="hljs-keyword">true</span></span></code></pre>
<p>そして以下のような <code>Dangerfile</code> を作成しておく。</p>
<pre class="prettyprint"><code class="language-ruby hljs ">warn <span class="hljs-string">"This is test for using Danger"</span></code></pre>
<p>これでブランチを作成して適当なコミットをした上でマージリクエストすると、Danger が実行され <code>1 warning</code> として <code>This is test for using Danger</code> のメッセージがコメントされる。</p>
<p>同じブランチで修正してプッシュした場合、もう一度パイプラインが実行されるが、 Danger のコメントは新しく追加されるのではなく更新される模様。</p>
<p>マージリクエストでないジョブの場合は Danger の実行は自動的にスキップされる。</p>
<pre class="prettyprint"><code class="language-sh hljs autohotkey">$ danger --fail-on-errors=<span class="hljs-literal">true</span>
<span class="hljs-literal">Not</span> <span class="hljs-literal">a</span> GitLabCI Pull Request - skipping <span class="hljs-escape">`d</span>anger<span class="hljs-escape">` </span>run.</code></pre>
<p>ここまでできてしまえば、あとは Dangerfile を編集していけばレビュー内容をブラッシュアップしていくだけのはず。</p>
<p>また、<a href="https://gitlab.com/gitlab-org/gitlab-ce/">GitLab Community Edition のリポジトリ</a>が Danger を採用しているので内容はこちらが非常に参考になる。</p>
<h2 id="docker-プライベートレジストリ">Docker プライベートレジストリ</h2>
<p>Java の例では、ビルド手順において git コマンドを使うため、<code>before_script</code> で <code>apt-get install -y git</code> を実行した。また Danger の例では <code>gem install danger-gitlab</code> で Danger をインストールした。このような事前準備は可能な限り Docker のイメージにしておき、ビルド時間を短縮したい。</p>
<p>ただし、単に Docker のイメージをビルドする処理 (Dockerfile) に移しただけでは、イメージを毎回ビルドすることになりビルド時間の短縮にならない。Docker プライベートレジストリを用意してプッシュしておくようにする。</p>
<p>registry のセットアップは簡単で、Docker でセットアップできる。</p>
<p>この検証では、GitLab の VM (192.168.33.10) に同居させておく。</p>
<pre class="prettyprint"><code class="language-sh hljs lasso">curl <span class="hljs-attribute">-sSL</span> https:<span class="hljs-comment">//get.docker.com/ | sh</span>
apt<span class="hljs-attribute">-get</span> <span class="hljs-attribute">-y</span> install <span class="hljs-subst">--</span>force<span class="hljs-attribute">-yes</span> docker<span class="hljs-attribute">-ce</span><span class="hljs-subst">=</span><span class="hljs-number">18.06</span><span class="hljs-number">.1</span>~ce~<span class="hljs-number">3</span><span class="hljs-subst">-</span><span class="hljs-number">0</span>~ubuntu
docker pull registry:<span class="hljs-number">2.7</span>
docker run hello<span class="hljs-attribute">-world</span>
docker run <span class="hljs-attribute">-d</span> <span class="hljs-attribute">-p</span> <span class="hljs-number">5000</span>:<span class="hljs-number">5000</span> <span class="hljs-subst">--</span>name registry <span class="hljs-attribute">-v</span> /docker:/<span class="hljs-built_in">var</span>/lib/registry registry:<span class="hljs-number">2.7</span></code></pre>
<p>これで registry は準備できた。</p>
<h2 id="ビルドの中での-docker-の利用">ビルドの中での Docker の利用</h2>
<p>次のステップとして、CI でイメージをビルドして registry にプッシュするようなリポジトリを準備する必要がある。(手作業で準備してもいいが、ビルド用イメージもプロジェクトを構成する成果物のうち、と考えればリポジトリや CI のプロセスを準備するべきだろう。)</p>
<p>CI で Docker イメージをビルドするということは GitLab Runner の中で docker コマンドを利用できるようにする必要がある。Docker イメージのビルドの説明の中にある <a href="https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#use-docker-in-docker-executor">Use docker in docker executor</a> の説明が参考になる。</p>
<p>以下の方法では GitLab Runner を <code>--docker-privileged</code> で起動しておく必要があるが、Shell executor を使ったりソケットを共有する方法を使ったりすることもできるらしい。</p>
<pre class="prettyprint"><code class="language-yaml hljs http"><span class="hljs-attribute">image</span>: <span class="hljs-string">docker:stable</span>
<span class="haml">stages:
-<span class="ruby"> build
</span>
services:
-<span class="ruby"> <span class="hljs-symbol">docker:</span>dind
</span>
before_script:
-<span class="ruby"> docker info
</span>
build:
stage: build
script: docker run hello-world</span></code></pre>
<p>これで、ビルドの中で Docker イメージをビルドして registry にプッシュすることもできる。 <br>
…が、後述の問題により、プッシュできるようにするにはさらに変更が必要。</p>
<h2 id="レビュー用コンテナのビルドとプライベートレジストリへのプッシュ">レビュー用コンテナのビルドとプライベートレジストリへのプッシュ</h2>
<p><a href="https://gitlab.com/gitlab-org/gitlab-build-images">GitLab CE を参考にビルド用イメージのリポジトリを作成して</a> Danger 用(レビュー用)のイメージを作成してみる。</p>
<p>このイメージをわざわざ提供するのは gem でインストールする時間を省くのが主な目的。</p>
<p><code>Dockerfile.danger</code>:</p>
<pre class="prettyprint"><code class="language-dockerfile hljs lasso">FROM ruby:<span class="hljs-number">2.6</span><span class="hljs-attribute">-stretch</span>
RUN gem install danger<span class="hljs-attribute">-gitlab</span> <span class="hljs-subst">--</span>no<span class="hljs-attribute">-document</span> <span class="hljs-subst">\</span>
<span class="hljs-subst">&&</span> echo <span class="hljs-string">"Danger version "</span> $(danger <span class="hljs-subst">--</span>version)</code></pre>
<p>ビルド時につけるタグはプッシュするホスト・ポートをつけておく。</p>
<pre class="prettyprint"><code class="language-yaml hljs http"><span class="hljs-attribute">image</span>: <span class="hljs-string">docker:stable</span>
<span class="haml">stages:
-<span class="ruby"> build
</span>
services:
-<span class="ruby"> <span class="hljs-symbol">docker:</span>dind
</span>
before_script:
-<span class="ruby"> docker info
</span>
danger:
stage: build
script:
-<span class="ruby"> docker build -t <span class="hljs-number">192.168</span>.<span class="hljs-number">33.10</span><span class="hljs-symbol">:</span><span class="hljs-number">5000</span>/build-images/<span class="hljs-symbol">review:</span>latest -f <span class="hljs-constant">Dockerfile</span>.danger .
</span> -<span class="ruby"> docker push <span class="hljs-number">192.168</span>.<span class="hljs-number">33.10</span><span class="hljs-symbol">:</span><span class="hljs-number">5000</span>/build-images/<span class="hljs-symbol">review:</span>latest</span></span></code></pre>
<p>しかし、ここまでの手順で準備した Runner では以下のように push が失敗してしまう。</p>
<pre class="prettyprint"><code class="language-sh hljs livecodeserver">$ docker push <span class="hljs-number">192.168</span><span class="hljs-number">.33</span><span class="hljs-number">.10</span>:<span class="hljs-number">5000</span>/build-images/review:latest
The push refers <span class="hljs-built_in">to</span> repository [<span class="hljs-number">192.168</span><span class="hljs-number">.33</span><span class="hljs-number">.10</span>:<span class="hljs-number">5000</span>/build-images/review]
Get <span class="hljs-keyword">https</span>://<span class="hljs-number">192.168</span><span class="hljs-number">.33</span><span class="hljs-number">.10</span>:<span class="hljs-number">5000</span>/v2/: <span class="hljs-keyword">http</span>: server gave HTTP response <span class="hljs-built_in">to</span> HTTPS client
ERROR: Job failed: exit code <span class="hljs-number">1</span></code></pre>
<p>http だと push できない模様。</p>
<p><a href="https://github.com/docker/distribution/issues/1874">こちら</a>を参考にすると、プッシュするホストの Docker デーモンに対して<code>/etc/docker/daemon.json</code> で <code>{ "insecure-registries":["192.168.33.10:5000"] }</code> と指定する必要がある。 <br>
GitLab Runner を実行する側の <code>/etc/docker/daemon.json</code> を以下のように作成する。</p>
<pre class="prettyprint"><code class="language-json hljs ">{
"<span class="hljs-attribute">insecure-registries</span>": <span class="hljs-value">[
<span class="hljs-string">"192.168.33.10:5000"</span>
]
</span>}</code></pre>
<p><code>/etc/init.d/docker restart</code> で Docker を再起動してパイプラインを再実行。</p>
<p>しかしこれは GitLab Runner のホストに対する設定なのでこのままでは効かない。</p>
<p>Runner を privileged で登録するのをやめ、ソケットを共有する方式で起動する。</p>
<p>以下の Runner を登録し、古いものは停止しておく。</p>
<pre class="prettyprint"><code class="language-sh hljs haml">sudo gitlab-runner register -n \
-<span class="ruby">-url <span class="hljs-symbol">http:</span>/<span class="hljs-regexp">/192.168.33.10/</span> \
</span> -<span class="ruby">-registration-token <span class="hljs-constant">DZt6Gx2oWtbm1T9G3xZE</span> \
</span> -<span class="ruby">-executor docker \
</span> -<span class="ruby">-description <span class="hljs-string">"My Docker Runner"</span> \
</span> -<span class="ruby">-docker-image <span class="hljs-string">"docker:stable"</span> \
</span> -<span class="ruby">-docker-volumes /var/run/docker.<span class="hljs-symbol">sock:</span>/var/run/docker.sock</span></code></pre>
<p>これでもう一度試すと、プッシュが成功した。</p>
<p>副次的な効果として、ホストの Docker を共有しているため、別のジョブでダウンロード済みの image を pull する場合はすぐに完了するというメリットもあった。</p>
<p>実際にビルド用イメージのリポジトリを準備する際は、<code>.gitlab-ci.yml</code> にもう少し工夫が必要だろう。このままだと、master 以外のブランチのビルドで作られたイメージで latest タグが更新されてしまう。</p>
<h2 id="レビュー用コンテナを使ってビルドする">レビュー用コンテナを使ってビルドする</h2>
<p>次は、このイメージを使ってビルドしてみる。</p>
<p>以下のように、<code>.gitlab-ci.yml</code> の Danger を使うジョブの定義で <code>image</code> に <code>192.168.33.10:5000/build-images/review:latest</code> を指定すれば良い。</p>
<pre class="prettyprint"><code class="language-yaml hljs haml">stages:
-<span class="ruby"> build
</span>
variables:
DANGER_GITLAB_API_BASE_URL: http://192.168.33.10/api/v4
DANGER_GITLAB_HOST: 192.168.33.10
review:
stage: build
image: 192.168.33.10:5000/build-images/review:latest
only:
variables:
-<span class="ruby"> <span class="hljs-variable">$DANGER_GITLAB_API_TOKEN</span>
</span>
script:
-<span class="ruby"> danger --fail-on-errors=<span class="hljs-keyword">true</span></span></code></pre>
<h2 id="ビルドの条件">ビルドの条件</h2>
<p><a href="https://docs.gitlab.com/ee/ci/yaml/README.html#onlyexcept-basic">公式マニュアル</a>を参考に、基本的には <code>only</code> / <code>except</code> を使えばジョブの実行条件を指定することができる。以下にいくつか使えそうなものをリストアップしてみる。</p>
<h3 id="master-ブランチのみ">master ブランチのみ</h3>
<p>MR と master ブランチでは異なる内容を実行したいこともあるはず。</p>
<pre class="prettyprint"><code class="language-yaml hljs haml">only:
refs:
-<span class="ruby"> master</span></code></pre>
<h3 id="mr-のみ">MR のみ</h3>
<p>レビューすることが前提となるもの。Danger も上述の通り、そのジョブが MR でトリガーされているのかどうかをチェックしてくれるようだが、このカテゴリに含めるのが良さそう。</p>
<pre class="prettyprint"><code class="language-yaml hljs haml">only:
refs:
-<span class="ruby"> merge_requests</span></code></pre>
<h3 id="特定のファイルが更新された場合のみ">特定のファイルが更新された場合のみ</h3>
<p>具体的には、Gradle ファイルまたは API、画面のサブプロジェクトのファイルが更新された MR のみ、という例。</p>
<p>Markdown ファイルだけ更新した場合に CI をスキップしたいとか、関連のないサブプロジェクトのビルドを避けて時間短縮したいとか、工夫ができそう。ただし、条件を正しく設定しないとテスト漏れに繋がる。</p>
<pre class="prettyprint"><code class="language-yaml hljs haml">only:
refs:
-<span class="ruby"> merge_requests
</span> changes:
-<span class="ruby"> subprojects/{api,site}-*<span class="hljs-regexp">/*
</span></span> -<span class="ruby"> **<span class="hljs-regexp">/*.gradle</span></span></code></pre>
<p>以上。</p>
<p>別途、以下のようなトピックについても検討してみたい。</p>
<ul>
<li>docker-compose を使ったプロジェクトでのビルド・テストのやり方</li>
<li>特定の種類のブランチの場合にジョブの中で自動的にマージする</li>
<li>Dangerfile を編集した場合のチェック用に、ローカルで Danger を実行できるようにする方法</li>
</ul>ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-31259052879055493042019-02-20T00:54:00.001+09:002019-02-20T00:54:18.901+09:00yEdの基本的な操作方法+α<p><a href="https://www.yworks.com/products/yed">yEd</a> の基本操作を確認する。 <br>
内容は独立しているが、一応以下の続き。</p>
<p><a href="https://ksoichiro.blogspot.com/2019/02/yed-edge-routing.html">yEdでジョブフロー図っぽいものを描く: Edge Routing</a> <br>
<a href="https://ksoichiro.blogspot.com/2019/02/yed-layout.html">yEdでジョブフロー図っぽいものを描く: Layout</a></p>
<p>yEdをすごく気に入っているような感じになってきているが…あくまで評価の過程。 <br>
なお、操作は Windows 10 で行っている。 <br>
<a name='more'></a></p>
<h2 id="ノードの配置">ノードの配置</h2>
<p>Paletteからドラッグアンドドロップする。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuevFtxQ-GTUjGHUQU5dgV3b35utEMsXkiDbfdmdZOO2dGJeW-OitJvUqiQ64ItztoUIQrINFHHdBzD0OQ8edK0iEr6gaAW3Sua0RSVKAD_ZLwMA1Z-leuiAcdQnPOl1cciRWZqWesbonX/s0/" alt="" title="yed-operation-palette.png"></p>
<p>PaletteにはSectionがあり、このSectionは増やすことができる(Edit>Manage Palette)。</p>
<h2 id="ノードの接続">ノードの接続</h2>
<p>オブジェクトから別のオブジェクトへドラッグするとコネクタがつく。以前のエントリでEdge Routingを見たとおり、コネクタのことはエッジ(Edge)と呼んでいる模様。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0FJpe2dOYgCrUdC8j9dm9iFsK0BYK3UYknrbFIrgp8FMnFe55Aryl91kZtSac51tfRwQ6fkfzC8-vlsdfRadQTi-oVJJUiCcJO5IsVs4DrPjoEp8DDQ6IUJqSVTrbmltAY61iF4teNHuT/s0/" alt="" title="yed-operation-connecting.png"></p>
<p>オブジェクトを移動したいときは、オブジェクトを一度クリックしてからドラッグする。いきなりドラッグしようとするとコネクタがマウスにくっついてきて、離すと線が折れ曲がって…と以下のようにおかしなことになる。そのような状態になったらEscキーで中止できる。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibsQLcT76C5QrAx98VWnaJsXKC79VpqL_4ybB_VdCceOGLrudAI6nbfBj1RDxIS4-YGIQkY05MWjnmhZX1dLY3LK2xLJkZWXbD_31TEQd04m_NLs533a_gOWMxLuL7mYLQucx2ntErynLs/s0/" alt="" title="yed-operation-move-failure.png"></p>
<h2 id="ラベル">ラベル</h2>
<p>Office系のオートシェイプだとテキストのみのオブジェクトを作ることができる(以下はOpenOffice Calcでの例)が、yEdにはそのようなものがない模様。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr5AEGl6FjlqOvucW0rqs3dh4ZUxipmrQxYCSBsI6jYK9S2tRADaJ3MLOBYKT5lrY9-90afZex9f3h4bXhJrbODvHnFxhzEqxLmnX8mhQhEBqH-ri48OkrIg8Z4Fx6N4IfXi3Yd1qcSWgo/s0/" alt="" title="yed-operation-text-label-openoffice.png"></p>
<p>もし必要なら通常のノードの色を消して作る。</p>
<p>ノードを右クリック>Propertiesでダイアログを開き、GeneralタブのFill Colorの右側の「…」をクリック、No Colorを選択する。Line Colorも同じくNo Colorにする。Okボタンで確定。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuR9Dphn0UOS83VC9Gn2I4986tXGiDH3dsBy8hqONFmJxeUJx9TwO8-yq-0PC04VwZ3BoxjCWowu9KeWVlszaUilquluY0KaYyLxWfOuyrRh2L4Ni1gyXeNsczoCyTQzaW_2cJvpfhTgIp/s0/" alt="" title="yed-operation-text-label.png"></p>
<p>ノード内にテキストを入れるのはノードをダブルクリックするか、ノードをクリックしてF2キーで編集開始できる。ノードからテキストがはみ出ている場合(以下)、</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhs2hET-ja7Ao_Z5_EJd4nJ5edK4xzXuuh7s9LwGu3ml9EIWuAWx3Zmi4iTWYze3ACb8cSgvBP_XM7yrlYdVhBbmK5eQ6iTiJDI7yOIVSFQ0zIaeGV6whiEmB04SJlywXHTlha3FneLWO0D/s0/" alt="" title="yed-operation-label-overflow.png"></p>
<p>メニューのTool>Fit Node to Labelでラベルが収まる大きさに変えることができる。</p>
<p>すべてのノードではなく選択したノードだけ適用したい場合は、ノードを選択した上でFit Node to Labelのダイアログを開き、Act on Selection Onlyにチェックを入れると選択したものだけに適用することができる。</p>
<h2 id="フォントの変更">フォントの変更</h2>
<p>あえて取り上げるものでもないかもしれないが…デフォルトではDialogというフォントになっており、日本語だと見栄えが良くない(と個人的には思う)。 <br>
ノードのプロパティを開いてLabelタブ>Font Familyでフォントを変更することができる。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLBSeGexJFi72Y5qI6de-EBDKlSGM76hMZZdjbg7ZVjrD5LBQCZtSg3Mv8_rO4lf5jLUC6RQ2VfXIa3Gi7VyCYyvYSkAWvimvb97w4U7ckkP_mKiWdGULpMX9znPbZ-76YpOPDjjzB2x62/s0/" alt="" title="yed-operation-japanese-font.png"></p>
<p>特に文字化けのような問題は起きない。 <br>
複数をまとめて変更したい場合は、ドラッグしてノードを複数選択した状態でノードの一つを右クリックしてPropertiesを開くか、F6キーでプロパティのダイアログを開いて変更する。 <br>
この変更方法は他のプロパティでも同じと思われる。</p>
<p>いちいちこのような設定をするのは面倒なので、よく使うノードはPaletteに登録すると良いだろう。以下などがそうだが、Paletteはgraphmlファイルとして外部化できるらしい。 <br>
<a href="https://github.com/pafnow/vrt-graphml-for-yed">https://github.com/pafnow/vrt-graphml-for-yed</a></p>
<h2 id="ラベルの配置の変更">ラベルの配置の変更</h2>
<p>ノード内でのラベルの配置は、Properties > Labelタブ > PlacementでModelをInternalにしてPositionで変更することができる。以下はTop Leftにした場合の例。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXjVe6d7BKegsYWBvplielNDOWVnwPdHbmB9UC__lu8_Ie4Xmly2WuS0ygPcP6RofysmaQWkcpVk7DX2zWav5MuKpes34PAXn9Yh182gO4BlV5L8i95XMz9zqNxiqLgmlLt1c_iIlOiAGq/s0/" alt="" title="yed-operation-label-position.png"></p>
<h2 id="表示を中央に持ってくる">表示を中央に持ってくる</h2>
<p>メニューView>Fit Content、またはツールバー上の以下のボタンを押すと、配置されているノード群が中央に来るように移動する。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXSBTSK98TliNFbS2SJnaMNUGmIVJG5z7x25gei5OO8o5L9-msqTSFGWjxKZY3KOC5-I-ISwHGAUGRSwi6_1KiCcr7UfSD9vdgZOPPsoEfjcPQYpIlRnxEcZ8PiFVb58l0O4_RtXU6W_qP/s0/" alt="" title="yed-operation-show-entire-graph.png"></p>
<h2 id="選択したものを整列する">選択したものを整列する</h2>
<p>例えば以下のように配置がバラバラなノード群があるとする。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrKqoxaUjj4lsS8oZorc2y17mm7TIC5yNL9kD0TAuC2J6Py8OO98FHOTNhkq0OGYD4SiFUr0uQTUkRANbxL3Do_ohezTNuSavzFQzjYPTMrUL06zcrudx1wsUcQc5TCT7j8IbBVJi9OM9C/s0/" alt="" title="yed-operation-before-align.png"></p>
<p>左の2つのノードを左揃えしたい場合、以下のようにノードを選択して…</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyLg4XfykP5_SvsMx7FK1_T-oo6FBN8lYHkDg9TS6zOi2DWyNCHdnXDygaPn6BMqKJ2z-MbOOkHVk_Gq_ZKVfTlWr70KTA0vCsVzanyCforptVF_Tt1Rfr5gTYLLds-g1MioGu-7a1JyvM/s0/" alt="" title="yed-operation-before-align-selecting.png"></p>
<p>メニューEdit>Align Nodes>Align Leftを選択すると整列できる。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgA6eY9ou9-ZsAbtq1JIvz4aApAyVa4TRT2m5aGqDBDogDjVdg-6C-4Y1_E2g5YySeF9hmVf7ttm770wHOYRYgom8ECRBfYcCXUFgW8HnDPbNKpWGsq1dET7wDhmh9XVclOCnv4b3rV_s4C/s0/" alt="" title="yed-operation-after-align.png"></p>
<h2 id="重なったノードの上下">重なったノードの上下</h2>
<p>以下のように後からノードを配置して下に移したいとする。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7IezO1BKiDwQyQgCSlf0_XuSryb_EIFXVzrFZW1XDAikhnA_u7_F8ZqLL8Brl2YuUasfqcQVo5LKh4zpk_ztJD07qdP36V-BN_JnNKBMGSqg0-PBfGoZBTVUxct53i8n8A5lbSSJjVTq8/s0/" alt="" title="yed-operation-before-lowering.png"></p>
<p>対象のノードを右クリックし、Lower Selectionを選択すると一番下に移される(1つずつ下に移るのかと思いきや、おそらく一番下に移されている)。逆に、上に移動したい場合はRaise Selectionを選ぶ。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibfxWKfqBXXoPKYrDQu39tak5dZHpV9U-SxUVfEf9-UgI7nIgxOgUh_DHEKr93Ai3jIXUSUu5DT-qCCygCrow7XlhdWUy5EW2AsKYy9YPuFIq_5HDNmK5miVJpV9PGeV3f-BhcxLJL_sFD/s0/" alt="" title="yed-operation-after-lowering.png"></p>
<h2 id="グループ化">グループ化</h2>
<p>複数のノードを選択してグループ化することができるが、Excelなどのグループ化とは違う印象。単純にグループ化されるだけではなく、グループが”見える”状態になる。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjR77UEs5XzPO8DLPsMCPj_VHLTL7m-Q4byJkabrubp7oHQv-RGW2kGm5fHQpygEUYCb92t-ab8lh7ySbD9MdX9Mn8bvsudOZGqKoPR-GW48AZ2PJgAeJxhRUNNI86hwGuWgLgQJzqgW4Cy/s0/" alt="" title="yed-operation-grouping.png"></p>
<p>画像としてエクスポートすると、ラベルや周囲の罫線、背景色も出力されており、単にグループ化したいだけなら邪魔になる場合が多そうな気がする。</p>
<p>プロパティでFill Color、Line ColorをNo Colorに変更すれば、枠の線や背景色は消える。ラベルを非表示にする場合はプロパティのLabelタブでVisibleのチェックを外せば良い。すると以下のようにグループとしてドラッグで移動はできるがグループそのものをノードとして表示することはなくなる。「-」の部分は画像としては出力されない。この場合、グループの範囲がどこまでなのかがわかりにくく、グループ内のノードをドラッグしそうになるかもしれない。グループ化していてもグループ内のノードを普通に操作できてしまうため、うっかりグループ内のものだけ操作してしまうこともありそう。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkC81zIck6d0lQL2idcwXOwkk1bp0QYubQQPeVGuCXWERBR3JHLTrwsN-K6moYnLcK8ANEFh1RWkHDdPmhTfLU2dsY7pWQzO_D2paNXxZCYQxIOQoLiRcv6e2_kGrpzdOFHwaFTUBvlCvu/s0/" alt="" title="yed-operation-invisible-group.png"></p>
<p>グループの左上の「-」をクリックするとグループが閉じられて「フォルダ」になる。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNiGDbxEHtVajQJeBVcqI-4gx3iK5_KWxiE_56T4TLO0FU1Mx2yZQ64D4Q-Y0DVoLebS3OFpdzCE_AOFAA-Yp9FjIKEriP-Y_omOm_hZ32NgKi8lTmuL6t2QmPCTyXoCs6glm-0W5NIdvl/s0/" alt="" title="yed-operation-folder.png"></p>
<p>フォルダの色も消すことはできるが、ただの透明な領域になってしまうためあまり意味はないだろう。</p>
<h2 id="ズームインズームアウト">ズームイン・ズームアウト</h2>
<p>マウスのホイールでズームイン・ズームアウトができる。あるいはツールバー上の虫眼鏡のアイコン(「+」「-」の印が中にあるもの)を操作する。中身のない虫眼鏡をクリックすると、選択領域をズームするモードに変わる。図の一部をドラッグして領域選択すると、その部分にズームインする。</p>
<h2 id="移動">移動</h2>
<p>表示する領域を移動するには、右ドラッグする。</p>
<h2 id="エッジの付け替え">エッジの付け替え</h2>
<p>既にノード同士が接続されている状態で、接続先のノードを別のノードに変えたいとする。</p>
<p>その場合はエッジをクリックして、接続先のノードの中心部分にマウスをフォーカスすると移動のアイコンに切り替わるので、そのままクリックし、変更先のノードにドラッグする。</p>
<p>一度クリックしてからでないと移動できないのは、最初に説明した「ノードの接続」と同じ。</p>
<h2 id="吹き出しっぽいもの">吹き出しっぽいもの</h2>
<p>これは基本操作というよりExcelと比較しての応用編かもしれないが… </p>
<p>Excelのオートシェイプで吹き出しはよく使う(と思う)。これに相当するものはできるか確認してみたが、結論から言うと難しい。</p>
<p>yWorksのマニュアル <a href="https://yed.yworks.com/support/manual/custom_nodes.html">Custom Symbols</a> の説明によると、SVGやVisioのXMLをインポートすることはできるらしい。Paletteにインポートすることもできるし、.svgファイルをドラッグアンドドロップすればそのまま取り込めるとのこと。試しに以下のような吹き出しっぽいものをInkscapeで作ってみて…</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGi5QCchFC0r8-wuMVCDiSw86AmzcFRD0L4Na_qczjz2ykQ-zGamt-BKpBu6GCQFqg7SxmpznORVgtodQ8hxoZm8cqU7Vfb3ZocuXskWA7e8QNtTue5rkrLQnHcdTlVW0uPjNMxuJHhjWa/s0/" alt="" title="yed-operation-svg-balloon.png"></p>
<p>ドラッグアンドドロップすると確かに取り込める。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIYZa4vzZ7uBs_S8nFqqX7OOzuhglZO0aXHRXVj8MYE3MfOUj2f3Au3poNGSEvMGCMoAdM_AK0fzGSwQTLoRGwFbe_Ru63JF_DS7VHSi7p2Wx0TYIl7VTeRI403L9U8_vDrUUdrjFCB5A3/s0/" alt="" title="yed-operation-import-svg.png"></p>
<p>しかし、ラベルを入れようとすると残念なことになる。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIdvqW2fWXmoOUL1rEAUzrDDZwpYz7cUYe7c4cVCuye-lnLJEmCF9qNfTW1awIXra76Kl-yH1m9QslkB9dZh4uKONkJthXTjSPiTSZ2iOElD4DmS-azx8R_wsXxZa8xA70zCdHdTec5Qmb/s0/" alt="" title="yed-operation-label-on-svg.png"></p>
<p>吹き出しノードを選択した上で、メニューTool>Fit Label to Nodeを選択し、StrategyをWrap Linesに、Act On Selected Nodes Onlyにチェックを入れてOkすると折り返すことは一応できる。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFNNeZI3jhxJTaKFHG76YGMefHhz_hT-6LWy4sFItPkGFb-0tvlan6VcZi7ZXBVrnO64cfd8vwsdJEDBrptOyFixEVlzyIm5gPP4pDCZsFq1-xqt9fvm0UrHrtnB0utKGXGVS0tNnKgSHN/s0/" alt="" title="yed-operation-label-on-svg-wrap-lines.png"></p>
<p>ただ、あくまでノードの矩形領域全体を調整可能な範囲としてみているようなので、折り返しとフォントサイズを小さくするのを両方行うStarategy(Wrap Lines and Resize Font)を選んだとしてもはみ出してしまう。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiza1DyjpYqX8uIkUd6coWA1ToaHd5hi0Speuk0gqZavob80jKQdttcyl9RubqiSuaDBLEKvFA389k6ON32NaqnhAPWk4hKX1NtVgpITUIMD3Ug3ccr1a9TmSqyXNKYiEU48PFhU78JHjHo/s0/" alt="" title="yed-operation-balloon-fit-label-overflow.png"></p>
<p>また、吹き出しの伸びている部分をドラッグすることはできないし、背景色などを変更することもできない。SVGなのだからできるのではと期待してしまうが、以下のように現時点ではできないとマニュアル(<a href="https://yed.yworks.com/support/manual/custom_nodes.html">Custom Symbols</a>)に書かれている。残念。</p>
<blockquote>
<p>Please note that images and SVG files will be used for the representation of nodes “as is.” Thus, unlike predefined shapes and symbols, changing visual properties like, for example background color or line type, has no effect on these nodes.</p>
</blockquote>
<p>ただ、これに関しては吹き出し型にこだわらなくても以下のように通常のShapeで何とかすることはできるとは思う。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqdvz6htUcYOoOn5GwDnni49Bjw3gsfjGM5y9Rm-XXYVx73jlsUvpIxd25qnvLIbVrlhozj8JlsjvPV69LRSvbs3uaFZEDF4INQfgO1RfuTAxd683t6hPxUaBPoAg3UedbgQg0n0MSjFsa/s0/" alt="" title="yed-operation-balloon-with-predefined-shape.png"></p>
<p>以上、気になった部分を中心に(かなり中途半端な感じではあるものの)確認してみた。 <br>
何となくExcel/PowerPointでの操作に近いことはできそうな感じはする。</p>
<hr>
<p>特に最後の例などを見ると、Excel/PowerPointのオートシェイプというのはよくできているなと思う。</p>
<p>だったらそちらを使えば…という思いもなくはないが、ファイルがテキストでないためにGitなどでの差分管理が適切にできないという点が引っかかる。yEd単独で使いたいのではなく、Markdownのようなテキストフォーマットでドキュメント作成・バージョン管理するのはどうかというお題からスタートしているので、テキストファイルとして保存されることは重要視したい。適切なバージョン管理(差分確認)という意味では、突き詰めると本当はmermaidやPlantUMLなどを使って”人が読んで理解できる”テキスト形式を選ぶ必要があるのだが。</p>
<p>また、Excel/PowerPointだと画像としてエクスポートする手順も面倒になると思うし、yEdが複雑なレイアウトを自動的に整理してくれるという機能もなかなか使えそうで、これだけでもyEdを選んでも良いのではないかと思う部分もある。</p>
<p>…などなど、現実的にどうするのが良いかというのは、実際に描きそうな図が表現できるのかを試してみたり、もう少し周辺の仕組み(GitLabでのマージリクエストやCI運用)とセットでシミュレーションしてみて考えたい。</p>ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com1tag:blogger.com,1999:blog-7702612945354492373.post-13676212231138255812019-02-19T00:23:00.001+09:002020-01-12T21:45:17.732+09:00yEdでジョブフロー図っぽいものを描く: Layout<p><a href="https://www.yworks.com/products/yed">yEd</a>でどこまで描けるか?本当に良いかを確認するためいくつか図を描いてみる。以下の続編。 <br>
<a href="https://ksoichiro.blogspot.com/2019/02/yed-edge-routing.html">yEdでジョブフロー図っぽいものを描く: Edge Routing</a></p>
<h2 id="ベースとなる図">ベースとなる図</h2>
<p>前回同様に以下をいじってみる。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfE_EITYYp_IJ7qnF_DHVu2xEG0qcbQIueh4HkAcMkYNtCsJhnM6_6y83T_U0bF0JFZaiRoJuiPPBJzLdPauvxcMXcrZ_Gbj_P1TeLZcSLkwo7VQC_Bp3AKC7U6nDlARyNzXMEFRNzdX4h/s0/" alt="" title="job-flow.png" decoding="async"></p>
<p>レイアウトといいながらEdge Routingから入ってしまったが、今回はメニューのLayout直下の項目を試す。 <br>
<a name='more'></a></p>
<h3 id="hierarchical">Hierarchical</h3>
<p>階層構造。フローチャートに向いているかも。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQKiDI6mBXN5s_rum4NwyYcxCEq3qfvn3x9q472UI5O2yyCbf59SJf4KnvfduuH74unkB9lIBsrhHX2OydF1JtNkAbrRsCMYNKc0bdmkC9DJRZq8xmUJ9zsKnsn2Ss3sRwSLyW9fnRQOEk/s0/" alt="" title="job-flow-layout-hierarchical.png"></p>
<h3 id="organic">Organic</h3>
<p>実行するたびに微妙に変わる。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUqmuUjl9Vmd9Bum3iAuNW7zjjk6h5hc-0Z90VUXk84WiVkJ0l9jNlwvAYRFvu7QFfYI6qAjUFnJL9qTYCiHo1Yd-_Ziaho6MRHVO-kLCd-0eH5Hbt099q_lkfrZM9JLvNoL3487uR2tBc/s0/" alt="" title="job-flow-layout-organic.png"></p>
<h3 id="orthogonal-classic">Orthogonal > Classic</h3>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTn-uNkBffaiCE78CiqtGYO9IlSGhSY6UF0ryhzqkUbrUCeV14vlaw-Gnj0S36q8yjyHZBPBYzHaL6zi5lChcrE3s_krRQWzJHLclTjHO-WTjT2kmlS-tQ-OO_VV1coHywZL4LyBPFiWJX/s0/" alt="" title="job-flow-layout-orthogonal-classic.png"></p>
<h3 id="orthogonal-uml-style">Orthogonal > UML Style</h3>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXdvzDCCG18JVlSj3pUZJkPXExtxFrEjaooeUTHFbeLLsBRul-f28H7WB1xD4epXBYCzOslcJn79JeBB5fHQzrpkEWEQlTEh4_yKosPPH4_hypgtulp4CAVizmx_Y670IotY6ZpaoRQfPc/s0/" alt="" title="job-flow-layout-orthogonal-uml-style.png"></p>
<h3 id="orthogonal-compact">Orthogonal > Compact</h3>
<p>コンパクトすぎる?</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC0eX0EE4l2-ZeJTUKA_mC4Gh9D19HmoqvQW3xvLTKLGc3fkzGHJN2Wx_3cwLCbboUNQD7HcHdHMzUtsnFVYq-Z4fAytw85VQ8LOWKKkXfXy9g3vyBLoVKjRz8q6NR3d125UYId-fEmElX/s0/" alt="" title="job-flow-layout-orthogonal-compact.png"></p>
<h3 id="orthogonal-circular">Orthogonal > Circular</h3>
<p>放射状な配置。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiauthU3VJfIq5KDgzQ2jS88TgmtKkoK32117oVvG2N3A26yR-abY2sFxkEDxwmuUUgbuhAI_9S1sdMZSo8vqeWQ1GPTATnBwCnDQuXZB1utqQh9LoONeBjXxCHBYvitXL1BfrVnt3U_pKs/s0/" alt="" title="job-flow-layout-circular.png"></p>
<h3 id="tree-directed">Tree > Directed</h3>
<p>Hierarchicalと似ている。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcQtCU3-EknuddzQywr2W-pHicrK3upkNnOFkvewyKeWFSERKjkAKADwNeJGResSmA-se2dzMqdqWCcirNL3JIrNJQrVkSHtDYCXE0dFqJY-yJmC_XmBuM3MMZFwcF5A1XUcJcW_gFJDSw/s0/" alt="" title="job-flow-layout-tree-directed.png"></p>
<p>Tree>Directedの設定画面でDirectedタブを開き、OrientationをBottom To Topにすると以下のようになる。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg29e37I5kaXkD6onHN3sgpXeFFXbk2BbbctcxTIa_zzEG_pT8MkVc6Fcef83E7nCfxZ7IcW5kuw_0go28NkzMfgaBlZQZyOp_7Nq46jb4t1Ga9CionWngTT0Oi7O17vgd2vh-owy_2_6gk/s0/" alt="" title="job-flow-layout-tree-directed-bottom-to-top.png"></p>
<p>OrientationをRight To Leftにすると以下。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFmzy7pYcLxIZTgNQcsvB5WvTyC_lzTrGL74tk-DdT2HR5jLe2pvpcDl3NfrTfcnPpdHo5xpBhGVskZgCNOeQwrSPL3DPdSYsrzhekjk9gCJyR7dn0f0SGd-_sMxUt7f8nkFOZdMe88Z9m/s0/" alt="" title="job-flow-layout-tree-directed-right-to-left.png"></p>
<h3 id="tree-balloon">Tree > Balloon</h3>
<p>Organicと違って何度やっても同じ配置。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9ZZDbcDQbGzePGRM9i1sbYlXhsMxvwNfT4-ZxxwgwGWEMSp0hknjEwab_fcgmxcYsS7G9xA-jU1a-T3MRH7d8yE2B8dzTjq_KwMayWHmYVMyyW8qG5aw6eIVYMzXu8vE4vROZIyvfLJ2K/s0/" alt="" title="job-flow-layout-tree-balloon.png"></p>
<h3 id="radial">Radial</h3>
<p>こちらが本当の放射状らしい。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo0xct98gczx5sI4hiz18LgtP-zMOH0LUYXIj72WUri1C_lrWmC2tBIJOu0u22o70q5yCZU4esSBPZjvHE5jf-uuVBW6G28RtzkSFnnFChZnQvIoEmi48FAm14VN4nn7Ny5N9S2kQGsGfF/s0/" alt="" title="job-flow-layout-radial.png"></p>
<h3 id="series-parallel">Series Parallel</h3>
<p>トーナメント表っぽい配置。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYRh4VFnh7RtOzRZ-4HaOUisayRU8UoZ6rTJS6WmWklonlME6uo2ofPI2rn_3wdhBn-YD8hEHt3TmF0oSRMo_qQX4YJtnkU4IBdh7_oyU87BnMF5_hEzYuybIKn48sDwixOBFiH0RbG7gL/s0/" alt="" title="job-flow-layout-series-parallel.png"></p>
<p>パラメータを変えるとさらにいろいろできそうだが、今回はここまで。</p>ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-83570692379993951402019-02-19T00:15:00.001+09:002019-02-19T00:25:19.829+09:00yEdでジョブフロー図っぽいものを描く: Edge Routing<p><a href="https://www.yworks.com/products/yed">yEd</a>でどこまで描けるか?本当に良いかを確認するためいくつか図を描いてみる。</p>
<h2 id="ベースとなる図の作成">ベースとなる図の作成</h2>
<p>まずPaletteのFlowchartのSectionから、適当にボックスをドラッグアンドドロップする。</p>
<p>ダブルクリックでラベルを入力。</p>
<p>オブジェクトからオブジェクトへドラッグするとラインが引かれる。</p>
<p>オブジェクトの配置の際には、ガイドとなるラインが表示されるため縦横とも周囲の部品と合わせた位置に置くことができる。</p>
<p>ここまでで作れたのが以下。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiShMFvR9VQYumm-waEmnjndo-_F51pJRUk8WBErfNNNZS593AnATVHrLPXrSGPW6UzHBulhR88arlOaZ4qVkjxVS035qtyzjZeigAo1v6qrsDg58xbiA7jXUSvFwdF023hKI3CThIIQOF5/s0/" alt="" title="job-flow.png"></p>
<p>レイアウトをいろいろとうまくやってくれるのが yEd の良いところのようなので試してみる。今回はEdge Routing。 <br>
<a name='more'></a></p>
<h2 id="edge-routing">Edge Routing</h2>
<p>オブジェクトを結ぶ線の引き方のことと思われる。 <br>
メニューのLayout>Edge Routingで選択できる。以下はそれぞれデフォルトのパラメータで設定している。</p>
<h3 id="orthogonalpolyline">Orthogonal/Polyline</h3>
<p>Orthogonal=直交らしい。単純な操作でこれができるのはすごい。Excelではできない。線が数回折れているのがPolylineということだろうか。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGAGzFe1eyoqqo3618rD7_nu-b7x9cgE9zfLcR-Ebpvpzrot0YOf5uOoUbPYDScioObU6fXkegWwkOB75sGkLhw8vk9KfGLLy1-7hVyTuZxVDkxnrfQch9Q4wiDOBOR8aMrX0dk-4OVlUP/s0/" alt="" title="job-flow-edge-routing-orthogonal-polyline.png"></p>
<h3 id="orthogonal-channel">Orthogonal Channel</h3>
<p>Job4の右側に回り込んでいる点が特徴的?どういう意味の配置だろう。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKqnACby0QbxKbtb7uHVo0nwS7IwhqNh6gKkVPb6xzTBc4mjgsSbLC4zlbSETf1BZboX0XRB0_dydoqJ7Pu8BW9Piawa7H49EUGOGHTajHp9AxOGxOLZtr4EOKj96_nQBm4fqjqw3AFtKA/s0/" alt="" title="job-flow-edge-routing-orthogonal-channel.png"></p>
<h3 id="orthogonal-bus-style">Orthogonal Bus-style</h3>
<p>確かにBUSっぽい引き方。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUtpkC2MIYyPnMyXJziX7HhK3bfa0trvcnYi1zLVz8Ub-BTJ8iVQpLJHxvAOIyj3zpMdCiqQqbhJd7gjrrFc1OE5cve5qA_zVo4UYiYzMV8jCaR4xMtRgfdngeUBw8RojWDiQrMu2w_luX/s0/" alt="" title="job-flow-edge-routing-orthogonal-bus-style.png"></p>
<h3 id="orthogonal">Orthogonal</h3>
<p>Excelでコネクタを使うとこうなる。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVj0R59NbXmdpCGs9ogPDMikxSXGGDQNew3f5RIi4yNv2SMqK0J1avcutlEIFtJR1HSe13IhMXQajt4D1_m7YUad0-GIJ_FhhLRRfOwtpunxLuerMUF79To3sB6f1Yg3IMPFGKz6UT0btj/s0/" alt="" title="job-flow-edge-routing-orthogonal.png"></p>
<h3 id="organic">Organic</h3>
<p>単純にオブジェクトからオブジェクトへ線を引いた場合と同じ。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfE_EITYYp_IJ7qnF_DHVu2xEG0qcbQIueh4HkAcMkYNtCsJhnM6_6y83T_U0bF0JFZaiRoJuiPPBJzLdPauvxcMXcrZ_Gbj_P1TeLZcSLkwo7VQC_Bp3AKC7U6nDlARyNzXMEFRNzdX4h/s0/" alt="" title="job-flow.png"></p>
<h3 id="straight-line">Straight Line</h3>
<p>Organicと変わらない結果。適用範囲によっては変わるかもしれない。 <br>
全く同じ画像だったため割愛。</p>
<p>今回はここまで。</p>
<p>続き:<a href="https://ksoichiro.blogspot.com/2019/02/yed-layout.html">yEdでジョブフロー図っぽいものを描く: Layout</a></p>ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-55971689271457955512019-02-18T23:10:00.001+09:002019-02-18T23:10:15.794+09:00マークアップ言語によるドキュメント作成<p>大げさなタイトル?な感じもするが、MarkdownかAsciiDocで技術ドキュメントを書けないかなと改めて調べたことを記録する。</p>
<p>結論としては、MarkdownとyEdが良さそうだと思っている。 <br>
(すぐにまた評価が変わるかもしれないが…) <br>
<a name='more'></a></p>
<h2 id="前提">前提</h2>
<ul>
<li>クラウドサービスは利用しない <br>
<ul><li>デスクトップアプリやオンプレミスなサーバにインストールできるOSSツールなどを利用</li></ul></li>
</ul>
<h2 id="言語">言語</h2>
<h3 id="asciidoc">AsciiDoc</h3>
<ul>
<li>Pros: テーブルなど詳細な書式が指定可能。</li>
<li>Pros: 亜種がなく仕様が明確。</li>
<li>Cons: 環境構築が面倒。手軽という人もいるが、VSCodeやTyporaなどエディタのみで完結するMarkdownに比べたら面倒なのは間違いない。</li>
<li>Cons: 文法がMarkdownほど知られておらず、学習コストが発生する。</li>
<li>Cons: 非エンジニアの利用の障壁も上がる。</li>
</ul>
<h3 id="markdown">Markdown</h3>
<ul>
<li>Pros: 人気=各種ツールの対応が多い。非エンジニアでも普通に書けるのがGood</li>
<li>Cons: 亜種が多いため、標準記法を定めないと各自の環境(エディタ)でしか表示できない表現が使われてしまう</li>
<li>編集/プレビュー環境 <br>
<ul><li>Typora <br>
<ul><li>非エンジニアでも触りやすい</li></ul></li>
<li>VSCode <br>
<ul><li>エンジニアはこちらか</li>
<li>MPEでプレビュー</li></ul></li></ul></li>
</ul>
<h2 id="図をどう表現するか">図をどう表現するか?</h2>
<ul>
<li>Excel/PowerPointのオートシェイプでの作図の手軽さは重要 <br>
<ul><li>UMLなどで表現できるものならmermaid, PlantUMLなどで対応可能だが。</li>
<li>設計の初期段階など、あまりUMLの表現にとらわれずにイメージを描きたい。</li>
<li>また、Markdownで書くなら図だけExcelを開くようなことは避けたく、Markdownに埋め込みたい。</li>
<li>Excel/PowerPointでも良いが、キャプチャなりエクスポートなりした画像をセットで管理する運用だと、その画像のとり方が属人的になり再現性が低い。</li>
<li>MarkdownにPlantUMLを埋め込んだり(GitLabだと外部サーバが必要)AsciiDocのように各種ツールを入れて生成するのも良いのだが、そこまで環境構築に手間がかかると(メンバー含めた)整備が大変だし、ツールに制限されるのが問題になる可能性もある。</li>
<li>元ファイルがOfficeでも良いが、出力される画像が安定する方式が良い。</li></ul></li>
<li>テキストファイルであるSVGが良さそうと考えたが… <br>
<ul><li>VS Codeの標準のプレビューでも読み込める</li>
<li>Typoraでも読み込める</li>
<li>編集が問題。だから編集用のソフトを探す? <br>
<ul><li>Inkscapeで編集はできるが目的が違うため難</li></ul></li>
<li>Excelオートシェイプのような操作感でSVGファイルとして管理できるものがあれば…</li>
<li>draw.ioが良さそう。 <br>
<ul><li>図が豊富に作れるようだがクラウドサービス</li></ul></li></ul></li>
<li>と思ったが… <br>
<ul><li>GitLabではgitlab.comの11.7.5-ee(2019/2/10時点)でもsvgはmdで表示できないようだった。</li>
<li>コミットの差分を見ても、画像のほうがわかりやすい。 <br>
<ul><li>onion skinでスライドしながら変化が見られるため。</li>
<li>SVGはテキストとして差分が出てくるため、少し変えただけでもだいぶ変わってしまう可能性がある。</li></ul></li>
<li>ということでSVGに拘る必要はない。</li>
<li>しかしながら、PNGでも何でも、編集後に期待通りの形で安定して簡単に出力がしやすいツールを選ぶことが重要。</li>
<li>CIで元ファイルから変換して出力・コミットさせるような方法も考えられるが、そこまで煩雑にする必要はない。今ターゲットとするのは、プロジェクトの序盤に検討するような全体のイメージ図やちょっとした補助的な図であり、手動でツールからPNGを出力する運用でもそう困らない。ただしシステム構成などメンテナンスは必要な可能性のある図で、編集手段は用意する必要tがあるという想定。</li></ul></li>
</ul>
<h3 id="図を編集するアプリケーションとしてはdrawioが秀逸だがその代わりのdesktop-appはないか">図を編集するアプリケーションとしてはdraw.ioが秀逸だが、その代わりのDesktop Appはないか?</h3>
<h4 id="yed"><a href="https://www.yworks.com/products/yed">yEd</a></h4>
<ul>
<li>良さそう <br>
<ul><li>日本語の解説記事は少ないけど…</li></ul></li>
<li>yWorksが開発</li>
<li>マルチプラットフォーム</li>
<li>データファイルはテキスト(.graphml)</li>
<li>普通にSVGエクスポートすると適切な範囲で切り出してくれる</li>
<li>パレットとして他のgraphmlから読み込みも可能</li>
<li>全選択してCopy to System clipboardすればExcelに画像として貼り付けられる</li>
</ul>
<h4 id="libreoffice-draw"><a href="https://ja.libreoffice.org/discover/draw/">LibreOffice Draw</a></h4>
<ul>
<li>OSS</li>
<li>Officeの操作感なのが良い</li>
<li>データファイルはバイナリ(.odg)</li>
<li>GitLabではSVGのプレビューが正しく表示されなかった。</li>
<li>PNGへのエクスポートは縦横比が崩れてNG。</li>
</ul>
<h4 id="openoffice-draw"><a href="https://www.openoffice.org/ja/intro/draw.html">OpenOffice Draw</a></h4>
<ul>
<li>LibreOfficeと同じ。LibreOfficeの方が操作しやすい印象だが、アイコンはこちらが充実?</li>
<li>こちらは縦横比が崩れることはなかった。こちらのほうが良い?</li>
<li>オブジェクトを全選択してからエクスポートして、選択範囲をエクスポートするようにすれば余白は含まれない。</li>
<li>透過率を保存、としなければ背景色は透過しない。</li>
<li>GitLabでの表示はできているようにも見えるが顔の画像の色がはみ出していた。</li>
</ul>
<h4 id="pencil"><a href="https://pencil.evolus.vn/">Pencil</a></h4>
<ul>
<li>重い。</li>
<li>画像のせいかもしれないが、SVGファイルが大きい。</li>
<li>バイナリファイル(epgz, epz)。</li>
<li>GitLabではSVGのプレビューが正しく表示されなかった。</li>
</ul>
<hr>
<p>メジャーなツールとは言えない気がするので不安がなくはないが、yEdが一番良さそう。</p>
<p>ツール自体は日本語化はされていないため慣れが必要と思われるが、こんな図はどう書くの?という確認のために触ると思うのでその記録もこのブログに残していきたい。</p>
<p>今回いろいろ試行錯誤したファイル群は以下に残している。 <br>
<a href="https://github.com/ksoichiro/document-test">https://github.com/ksoichiro/document-test</a></p>ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-25751793092298559782019-01-20T19:47:00.001+09:002019-01-20T19:47:43.894+09:00GitLab v7.9.4 のサーバ移行とアップグレード<p>GitLab Omnibus Package でインストールして運用してきた古い GitLab を別のサーバに移行し、最新版にアップグレードしたい。</p>
<p>ここでは v7.9.4 からの移行とアップグレードを考える。</p>
<p>サーバ移行については、データバックアップが取れるのでそれを新環境で取り込めば良い。</p>
<p>アップグレードについては Omnibus Package でインストールしたものなら基本的に以下を参照すればできる。 <br>
<a href="https://docs.gitlab.com/omnibus/update/">https://docs.gitlab.com/omnibus/update/</a></p>
<p>メジャーバージョンアップはバージョンをまたがない方がよい(1つずつ上げる)ということで、何度かに分けて上げる。</p>
<p>基本的に公式ドキュメントに記載されていることを正しく読み取って組み合わせれば良いのだが、以下では今回のケースで必要なことを事例として説明する。</p>
<a name='more'></a>
<h2 id="サーバ移行">サーバ移行</h2>
<p>データをバックアップして、tarを抽出しておく。</p>
<pre class="prettyprint"><code class="language-sh hljs css"><span class="hljs-tag">gitlab-rake</span> <span class="hljs-tag">gitlab</span><span class="hljs-pseudo">:backup</span><span class="hljs-pseudo">:create</span></code></pre>
<p><code>/var/opt/gitlab/backups</code> に作られた tar ファイルを利用する。 <br>
サイズを小さくしたければ gzip してから取り出す。 <br>
また、このファイルに含まれない設定ファイル群は個別にバックアップする必要がある。</p>
<p>移行先については、ここでは Vagrant で構築した Ubuntu のサーバを想定する。</p>
<p>Vagrant の場合、<a href="https://github.com/ksoichiro/gitlab-i18n-patch">gitlab-i18n-patch</a> にある Vagrantfile やシェルスクリプトを参考に構築できる。</p>
<p>これを参考に(日本語化パッチをあてていない) GitLab をインストールする。日本語化パッチはその後のアップグレードの妨げになるかもしれないため、必要なら最後に適用する。 <br>
なお、バージョン 9.2 以降は多言語化がサポートされているため、その内容でよければパッチは不要である。</p>
<p>gitlab-i18n-patch の Vagrantfile ではポートフォワードさせる設定になっているが、移行後に clone などを確認するなら <code>private_network</code> の設定をして IP アドレスを割り当て、 <code>/etc/gitlab/gitlab.rb</code> の <code>external_url</code> をその値で設定しておく。</p>
<p>立ち上がるようになったら、<code>/var/opt/gitlab/backups</code> の中に、旧サーバで取得した tar ファイルを配置する。</p>
<p>バックアップが複数ある場合はプレフィクスを指定する必要があるが、以下のようにデータベースアクセスのあるプロセスを止めた上でリストアする。</p>
<pre class="prettyprint"><code class="language-sh hljs lasso">gitlab<span class="hljs-attribute">-ctl</span> stop unicorn
gitlab<span class="hljs-attribute">-ctl</span> stop sidekiq
gitlab<span class="hljs-attribute">-rake</span> gitlab:backup:restore</code></pre>
<p>あとは設定ファイルとして <code>/etc/gitlab/gitlab-secrets.json</code> や <code>/etc/gitlab/gitlab.rb</code> を適切にリストアし、<code>gitlab-ctl restart</code> で反映する。</p>
<h2 id="アップグレード">アップグレード</h2>
<p>基本的に<a href="https://docs.gitlab.com/omnibus/update/">公式ドキュメント</a>で説明されている通りに実施すれば良い。</p>
<p>v7.9.4 のような古いバージョンから最新版へアップグレードしたい場合、1回の操作でアップグレードするのではなく、<a href="https://docs.gitlab.com/ee/policy/maintenance.html#upgrade-recommendations">こちらに説明されているように</a>アップグレードパスとして推奨されているステップに沿って複数回のアップグレードを重ねる。</p>
<p>今回は以下の順番で実施。</p>
<ol>
<li>7.9.4->8.17.7</li>
<li>8.17.7->9.5.10</li>
<li>9.5.10->10.8.7</li>
<li>10.8.7->11.6.5 (現時点での最新版)</li>
</ol>
<p>ひとつひとつのアップグレード手順は非常に簡単。</p>
<p>手動でパッケージをダウンロードしてアップグレードする手順の場合、<a href="https://packages.gitlab.com/gitlab/gitlab-ce">パッケージの配布サイト</a>からファイルをダウンロードして適用する。 <br>
先ほどの Vagrantfile で構築した環境なら、ubuntu/precise のパッケージが利用できる。 <br>
以下のような手順。</p>
<pre class="prettyprint"><code class="language-sh hljs lasso">cd /usr/<span class="hljs-built_in">local</span>/src
wget <span class="hljs-subst">--</span>content<span class="hljs-attribute">-disposition</span> https:<span class="hljs-comment">//packages.gitlab.com/gitlab/gitlab-ce/packages/ubuntu/precise/gitlab-ce_XXX_amd64.deb/download.deb</span>
dpkg <span class="hljs-attribute">-i</span> gitlab<span class="hljs-attribute">-ce_XXX_amd64</span><span class="hljs-built_in">.</span>deb
gitlab<span class="hljs-attribute">-ctl</span> restart</code></pre>
<p>注意点として、v9.2 以降は precise のパッケージが配布されていないため、trusty にアップグレードするなどの対応が必要。 <br>
precise から trusty へのアップグレードは以下などが参考になる。 <br>
<a href="https://qiita.com/white_aspara25/items/5187b357235ce9d275bf">[Ubuntu] 12.04 から 14.04 へアップデートした時のメモ</a> <br>
GitLab で現在配布されているのは v7.10 が一番古いバージョンのようだが、これも trusty 用のものが配布されているので、新規に構築するなら最初から trusty にインストールしたほうがスムーズ。</p>
<p>今回は Vagrant での手順を説明したが、この環境をそのまま運用する必要はない。ここからさらにバックアップを取って、運用環境にデータを移行することもできる。アップグレードが失敗するリスクを心配する場合は、このようなやり直しがしやすい環境でアップグレードを試し、うまくいったらデータを運用環境に持っていくという手順も良いかもしれない。</p>
<h2 id="日本語化の今後">日本語化の今後</h2>
<p>現在は公式に日本語化も進められているようだが、v9, v10 は日本語化されている部分が少なく、最新の v11.6.5 でもまだ英語の部分が多い印象だった。</p>
<p>v9.2 以降での日本語化の仕方がわからなかったため検索してみたところ、gitlab-i18n-patch を使って日本語化してくれている方の記事が 2018 年のものでもいくつも見つかった。既に v11 系もリリースされているにもかかわらず、最後に追加した v9.1.4 のパッチを適用している。v9.2 での多言語化対応が開始した時点で gitlab-i18n-patch の更新はやめてしまったのだが、もしかしたら gitlab-i18n-patch での日本語化はまだニーズがあるのかもしれない。v9.2 以降のコードでも今の gitlab-i18n-patch の仕組みで翻訳できそうなら取り組んでみよう。</p>ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-71900960131024838262019-01-08T23:20:00.001+09:002019-01-08T23:21:00.738+09:00Android ナイトモードをダークテーマとして提供する<p>以前の以下のエントリの関連。 <br>
<a href="https://ksoichiro.blogspot.com/2018/12/android-oncreate.html">Android ナイトモードを起動時に設定するとonCreateが二度呼ばれる</a></p>
<p>ナイトモードは時間に応じて自動的に変わる設定もできて、そのようになっているアプリもある。ただ、いくつかのアプリを調べてみた感じでは、現状ではON/OFFの設定のみのアプリが多い印象。三日月のアイコンをタップするとON/OFFが切り替わったり、ダークテーマ、ダークモードなど別の名前で提供されているものも多い。</p>
<p>ON/OFFの切り替えだけなら実質的にはテーマの変更であって、テーマの変更として実現すれば configuration の変更にならず onCreate の二重呼び出しなども発生しない。ナイトモードを適用したからといって起動が遅いのは何かを見落としているのかもしれないが、現状では、単純なON/OFFで提供したいならテーマとして提供する方法が無難かもしれない。</p>
<p>以下、ナイトモードの実装状況について確認したアプリについて記録しておく。 <br>
<a name='more'></a></p>
<h3 id="ナイトモードダークテーマが提供されているアプリの例">ナイトモード/ダークテーマが提供されているアプリの例</h3>
<p>提供されている名前、UIで分類して記載する。</p>
<h4 id="ナイトモードor-ナイトモード相当">ナイトモード(or ナイトモード相当)</h4>
<ul>
<li><a href="https://play.google.com/store/apps/details?id=com.medium.reader">Medium</a>: 「Night mode」として Off/Auto/On が選択可能</li>
<li><a href="https://play.google.com/store/apps/details?id=com.automattic.simplenote">Simplenote</a>: 「テーマ」としてライト/ダーク/Dark at night only から選択でき、Dark at night only が自動切り替えのナイトモードと思われる</li>
</ul>
<h4 id="三日月アイコン">三日月アイコン</h4>
<ul>
<li><a href="https://play.google.com/store/apps/details?id=com.twitter.android">Twitter</a>: アイコンのタップでON/OFF切り替えのみ(日中でもダークなまま)</li>
</ul>
<h4 id="ダークモード">ダークモード</h4>
<ul>
<li><a href="https://play.google.com/store/apps/details?id=com.evernote">Evernote</a>: スイッチでON/OFF切り替えのみ</li>
</ul>
<h4 id="ダークテーマ">ダークテーマ</h4>
<ul>
<li><a href="https://play.google.com/store/apps/details?id=com.google.android.youtube">YouTube</a>: ダークテーマとしてON/OFF切り替え</li>
<li><a href="https://play.google.com/store/apps/details?id=com.ideashower.readitlater.pro">Pocket</a>: ダークテーマとしてON/OFF切り替え</li>
<li><a href="https://play.google.com/store/apps/details?id=com.todoist">Todoist</a>: テーマの中のひとつとして「ダーク」が存在</li>
</ul>
<h4 id="その他">その他</h4>
<ul>
<li><a href="https://play.google.com/store/apps/details?id=com.amazon.kindle">Kindle</a>: 「色のテーマ」として明るい/濃い が選択可能で、「濃い」がダークなテーマ。</li>
<li><a href="https://play.google.com/store/apps/details?id=com.underwood.monospace">Monospace</a>: 画面上部のアイコン(白と黒半々の色のしずくのような形)をタップするとON/OFFが切り替わる</li>
</ul>ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-29446794252444191302019-01-08T22:59:00.001+09:002019-01-08T22:59:48.657+09:00Node.js の csv-stringify で CSV レコード内の改行をダブルクォートで括る<p>Node.js で <a href="https://www.npmjs.com/package/csv-stringify">csv-stringify</a> による CSV 出力をする際、項目(レコード)に何種類かの文字があった場合はダブルクォートで括るようにしたい。</p>
<p>csv-stringify が大体勝手にやってくれるが、現時点の最新版 v5.1.2 では改行の一部の取扱いが期待通りでなかった。</p>
<ul>
<li>行のデリミタが LF なら項目内に LF が含まれているとダブルクォートで括られる。→期待通り</li>
<li>行のデリミタが CRLF なら項目内に CRLF が含まれているとダブルクォートで括られる。→期待通り</li>
<li>行のデリミタが CRLF なら項目内に LF が含まれていてもダブルクォートで括られない。→期待と異なる <br>
<a name='more'></a></li>
</ul>
<p>オプションで何とかできないだろうかと<a href="https://csv.js.org/stringify/options/">ドキュメント</a>を確認したが、それらしいものが見当たらない。</p>
<p>ソースコードを眺めてみると、<a href="https://github.com/adaltas/node-csv-stringify/blob/v5.1.2/lib/index.js">lib/index.js</a> にある <code>quoted_match</code> が、<a href="https://github.com/adaltas/node-csv-stringify/blob/v5.1.2/lib/index.js#L395">正規表現でマッチした場合にクォートさせることに使えるように見える</a>。</p>
<p>npm には <code>Test with RunKit</code> のボタンがついているので、これで動作確認してみた。</p>
<p>まずは、行デリミタを CRLF にして、項目内に CRLF (<code>\r\n</code>) が含まれたらダブルクォートされることを確認。</p>
<pre class="prettyprint"><code class="language-js hljs "><span class="hljs-keyword">var</span> stringify = <span class="hljs-built_in">require</span>(<span class="hljs-string">'csv-stringify'</span>);
<span class="hljs-keyword">var</span> should = <span class="hljs-built_in">require</span>(<span class="hljs-string">'should'</span>);
input = [ [ <span class="hljs-string">'1'</span>, <span class="hljs-string">'2\r\nx'</span>, <span class="hljs-string">'3'</span>, <span class="hljs-string">'4'</span> ], [ <span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>, <span class="hljs-string">'c'</span>, <span class="hljs-string">'d'</span> ] ];
stringify(input,
{
record_delimiter: <span class="hljs-string">'windows'</span>
},
<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(err, output)</span>{</span>
output.should.eql(<span class="hljs-string">'1,"2\r\nx",3,4\r\na,b,c,d\r\n'</span>);
});</code></pre>
<p>次に、問題である項目内に LF (<code>\n</code>) が含まれる場合にクォートされないことを確認。</p>
<pre class="prettyprint"><code class="language-js hljs ">input = [ [ <span class="hljs-string">'1'</span>, <span class="hljs-string">'2\r\nx'</span>, <span class="hljs-string">'3\ny'</span>, <span class="hljs-string">'4'</span> ], [ <span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>, <span class="hljs-string">'c'</span>, <span class="hljs-string">'d'</span> ] ];
stringify(input,
{
record_delimiter: <span class="hljs-string">'windows'</span>
},
<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(err, output)</span>{</span>
output.should.eql(<span class="hljs-string">'1,"2\r\nx","3\ny",4\r\na,b,c,d\r\n'</span>);
});</code></pre>
<p>これは期待通り失敗した。 <br>
いよいよ <code>quoted_match</code> を使って LF が含まれたときにのみクォートさせるようにする。 <br>
LF の前に CR がなければ LF にマッチする、という否定後読みで実装してみる。</p>
<pre class="prettyprint"><code class="language-js hljs ">input = [ [ <span class="hljs-string">'1'</span>, <span class="hljs-string">'2\r\nx'</span>, <span class="hljs-string">'3\ny'</span>, <span class="hljs-string">'4'</span> ], [ <span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>, <span class="hljs-string">'c'</span>, <span class="hljs-string">'d'</span> ] ];
stringify(input,
{
record_delimiter: <span class="hljs-string">'windows'</span>,
quoted_match: <span class="hljs-regexp">/(?<!\r)\n/</span>
},
<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(err, output)</span>{</span>
output.should.eql(<span class="hljs-string">'1,"2\r\nx","3\ny",4\r\na,b,c,d\r\n'</span>);
});</code></pre>
<p>成功。 <br>
ただ、<a href="https://github.com/adaltas/node-csv-stringify/blob/v5.1.2/lib/index.js#L399">クォートされる条件の部分</a>を見れば、いくつかのクォートされる条件のうちのいずれかに合致したらクォートされるという実装なので、行デリミタが CRLF であろうと <code>quoted_match</code> では CRLF へのマッチを回避する必要はなかった。 <br>
単純に以下で良かった。</p>
<pre class="prettyprint"><code class="language-js hljs ">input = [ [ <span class="hljs-string">'1'</span>, <span class="hljs-string">'2\r\nx'</span>, <span class="hljs-string">'3\ny'</span>, <span class="hljs-string">'4'</span> ], [ <span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>, <span class="hljs-string">'c'</span>, <span class="hljs-string">'d'</span> ] ];
stringify(input,
{
record_delimiter: <span class="hljs-string">'windows'</span>,
quoted_match: <span class="hljs-regexp">/\n/</span>
},
<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(err, output)</span>{</span>
output.should.eql(<span class="hljs-string">'1,"2\r\nx","3\ny",4\r\na,b,c,d\r\n'</span>);
});</code></pre>
<p>というわけで、場合によってはプルリクエストだそうかなと考えたが、 <br>
やりたかったことは提供されている機能で実現できることがわかった。</p>ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-65357729305028069842019-01-06T23:22:00.001+09:002019-01-06T23:22:24.745+09:00Android Studio (Asset Studio) で扱える SVG 画像を Inkscape で作る場合の注意点 (グラデーション)<p>Asset Studio で、Inkscape で作成した SVG 画像を扱うとき、Inkscape 特有のタグなどのせいでエラーが発生する場合は「プレーンSVG」として保存すれば良さそう。 <br>
ただ、この場合は Inkscape のデータが失われる。</p>
<p>参考: <br>
<a href="https://graphicdesign.stackexchange.com/questions/82219/how-to-create-proper-vector-images-that-can-be-used-as-an-android-vector-drawabl">https://graphicdesign.stackexchange.com/questions/82219/how-to-create-proper-vector-images-that-can-be-used-as-an-android-vector-drawabl</a></p>
<p>グラデーションに関しては上記では解決せず、 <br>
例えば ic_launcher.svg などを Inkscape で作って Asset Studio でアップロードしようとすると</p>
<pre class="prettyprint"><code class=" hljs vbnet"><span class="hljs-keyword">ERROR</span> @ line <span class="hljs-number">83</span>: Gradient has no <span class="hljs-keyword">stop</span> info</code></pre>
<p>のようなエラーが出て、グラデーションが適用されない。 <br>
<a name='more'></a></p>
<p>これは Inkscape が以下のように、実際に適用するグラデーションを分離して定義するせいで stop 要素のない linearGradient が作られてしまうのが原因と思われる。</p>
<pre class="prettyprint"><code class=" hljs applescript"><linearGradient
inkscape:collect=<span class="hljs-string">"always"</span>
<span class="hljs-property">id</span>=<span class="hljs-string">"linearGradient4389"</span>>
<stop
<span class="hljs-property">id</span>=<span class="hljs-string">"stopShadow0"</span>
<span class="hljs-command">offset</span>=<span class="hljs-string">"0"</span>
style=<span class="hljs-string">"stop-color:#000000;stop-opacity:0.40000001"</span> />
<stop
<span class="hljs-property">id</span>=<span class="hljs-string">"stopShadow1"</span>
<span class="hljs-command">offset</span>=<span class="hljs-string">"1"</span>
style=<span class="hljs-string">"stop-color:#000000;stop-opacity:0;"</span> />
</linearGradient>
<linearGradient
inkscape:collect=<span class="hljs-string">"always"</span>
xlink:href=<span class="hljs-string">"#linearGradient4389"</span>
<span class="hljs-property">id</span>=<span class="hljs-string">"linearGradient4395"</span>
gradientTransform=<span class="hljs-string">"translate(0,-2)"</span>
gradientUnits=<span class="hljs-string">"userSpaceOnUse"</span>
y2=<span class="hljs-string">"98"</span>
x2=<span class="hljs-string">"94.57196"</span>
y1=<span class="hljs-string">"37.802406"</span>
x1=<span class="hljs-string">"30"</span> /></code></pre>
<p>これは <code>xlink:href</code> 属性で単純にリンクされているだけなので、以下のように統合すれば解決する。</p>
<pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">linearGradient
</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"linearGradient4395"</span>
<span class="hljs-attribute">gradientTransform</span>=<span class="hljs-value">"translate(0,-2)"</span>
<span class="hljs-attribute">gradientUnits</span>=<span class="hljs-value">"userSpaceOnUse"</span>
<span class="hljs-attribute">y2</span>=<span class="hljs-value">"98"</span>
<span class="hljs-attribute">x2</span>=<span class="hljs-value">"94.57196"</span>
<span class="hljs-attribute">y1</span>=<span class="hljs-value">"37.802406"</span>
<span class="hljs-attribute">x1</span>=<span class="hljs-value">"30"</span>></span>
<span class="hljs-tag"><<span class="hljs-title">stop
</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"stopShadow0"</span>
<span class="hljs-attribute">offset</span>=<span class="hljs-value">"0"</span>
<span class="hljs-attribute">style</span>=<span class="hljs-value">"stop-color:#000000;stop-opacity:0.40000001"</span> /></span>
<span class="hljs-tag"><<span class="hljs-title">stop
</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"stopShadow1"</span>
<span class="hljs-attribute">offset</span>=<span class="hljs-value">"1"</span>
<span class="hljs-attribute">style</span>=<span class="hljs-value">"stop-color:#000000;stop-opacity:0;"</span> /></span>
<span class="hljs-tag"></<span class="hljs-title">linearGradient</span>></span></code></pre>ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com1tag:blogger.com,1999:blog-7702612945354492373.post-77594697680674651512018-12-31T18:22:00.001+09:002018-12-31T18:22:14.128+09:00フォーマッタの自動適用<p>前のエントリでも紹介した <a href="https://github.com/ksoichiro/node-archiver-zip-encryptable">node-archiver-zip-encryptable</a> の開発では <a href="https://prettier.io">Prettier</a> を適用したが、フォーマットの統一に注意を払わなくて済むのは非常に快適だった。 <br>
ルーツが何かは調べられていないが、過去の自分の経験の中で似たようなものには Golang の gofmt があった。 <br>
Java のプロジェクトでも適用できないものかと思ったが、 <a href="https://github.com/jhipster/prettier-java">prettier-java</a> は現在 Work in Progress の状態。 <br>
<a name='more'></a></p>
<p>Eclipse など IDE でもフォーマッタはあるが、これがバージョン管理やビルドシステムと統合されて自動的に実行されるようになると、人による修正やチェックが不要になるはず。 </p>
<p>探してみると、Google のフォーマッタ <a href="https://github.com/google/google-java-format/blob/master/README.md">google-java-format</a> がメジャーなようだった。</p>
<p>IntelliJ や Eclipse のプラグインの他、Gradle や Maven との統合もできる模様。</p>
<p>あとは保存や pre-commit のタイミングで対象ファイルのみフォーマットすることができるかどうかだが、IntelliJ の場合は Reformat Code を実行しないと作動しないように見える。</p>
<p>pre-commitに関しては、npm を導入して Prettier と同様に husky などと組み合わせるか、上記のライブラリからもリンクされている <br>
<a href="https://github.com/maltzj/google-style-precommit-hook">google-style-precommit-hook</a> を使うのが良さそう。</p>ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-26324588795473423162018-12-31T11:36:00.001+09:002018-12-31T11:36:26.423+09:00vim でタスク管理<p>これもまた少し前の話になるが、vim スクリプトで簡単なタスク管理用スクリプトを作った。 <br>
結果は以下のようなイメージ。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9kPcpO8MVqDRUbpUTsQswpHlSzK0B0EfyT-bUrVXEytjgMafgwjrnlHv0drcOsW0DejuEWvhdUbNm-eL0zmJF7F7LG_E9mTlBCJzFeMmoY4ZALSPyki5APqb-3bf5SU2weL2dOSlXs_5Z/s0/20181231001.png" alt="TODO" title="20181231001.png"> <br>
<code>~/.vimrc</code></p>
<h3 id="要件">要件</h3>
<p>タスク管理のツールは世の中に数え切れないほどあるが、自分の場合は以下のようなことが要件で、ちょうど良いものが見つからなかった。 <br>
<a name='more'></a></p>
<ul>
<li>入力が簡単である (とにかく漏らさないことが大事)</li>
<li>チーム利用ではなく個人のタスクを管理できれば良い (開発プロジェクトのものではなく、GitLab などに載せるものではない。むしろ載せるとまずいタスクも含む)</li>
<li>業務で使いたいため、クラウドサービスではない (ルール上不可)</li>
<li>無料</li>
<li>運用の手間はかけられない</li>
<li>タスクを階層化して管理できる</li>
<li>検索ができる</li>
<li>完了と未完了両方が見える (完了したら消えるのは困る)</li>
<li>完了したものの表示はわかりやすくあってほしい</li>
<li>タスクの説明、補足情報を記入できる</li>
<li>カテゴリ分け、タグ付け的なことができる</li>
</ul>
<p>上記の整理をするまで、クラウドサービスを使うとか、OSSをローカルで動かすとか、Webアプリを作ろうかとか色々考えてきたのだが、実際に試したのは Excel でシートを作ったり、テキストファイルに<code>□■</code>などステータスを表す記号を付けて管理したり、といったことだった。</p>
<p>チームで扱うなら Web のツールを考えたほうが良さそうだし、分析・フィルタリングなどをするなら Excel などを使うのが良さそうだったが、今一番重要視したいのは入力が簡単、かつ自由に情報を追加できることだったので、意外にもシンプルにテキストで管理することに落ち着いていた。</p>
<p>よく考えると <code>■</code> ってキーストロークが多いから <code>x</code> にしようとか、そうするとどれが終わったのか一目では見分けがつきにくいな…などと考える中で、これは vim スクリプトで実現するのが一番手軽で確実なのではと思いこれを作ってみた。 </p>
<h3 id="仕様">仕様</h3>
<p>おおまかな仕様は以下。</p>
<ul>
<li>拡張子 <code>todo</code> で動作する</li>
<li>先頭の文字が <code>x</code> で完了、<code>_</code> で未完了、<code>-</code> が中止、<code>.</code> が仕掛り</li>
<li>完了・中止は色を暗くして目立ちにくくする</li>
<li><code>[タグ]</code> は色を変えてどのカテゴリのタスクなのかが見やすいようにする</li>
<li><code>[タグ]</code> は複数書ける</li>
<li>インデントを下げて別のタスク行を書ける</li>
<li>タスクの完了/未完了のトグル、完了などいくつかの頻繁に使う操作はショートカットを割り当てる</li>
</ul>
<h3 id="実装">実装</h3>
<p>現時点でプラグイン化はしておらず、まだ改善の余地もありそうなので手作業でファイルを用意して利用している。</p>
<p>以下のように <code>~/.vimrc</code> に定義していて、 <code>~/.vim</code> に各種ファイルを配置すれば読み込んでくれる構成を想定。</p>
<pre class="prettyprint"><code class=" hljs bash">execute <span class="hljs-string">'set runtimepath+='</span> . <span class="hljs-variable">$HOME</span> . <span class="hljs-string">'/.vim'</span></code></pre>
<p><code>~/.vim/syntax/todo.vim</code> のファイルを以下の内容で作成する。</p>
<pre class="prettyprint"><code class=" hljs ruby">syntax region todoTag start=<span class="hljs-regexp">/\[/</span> <span class="hljs-keyword">end</span>=<span class="hljs-regexp">/\]/</span>
syntax region todoDone start=<span class="hljs-regexp">/^\s*x /ms</span>=e-<span class="hljs-number">1</span> <span class="hljs-keyword">end</span>=<span class="hljs-regexp">/^\s*[_x\-.]/me</span>=s-<span class="hljs-number">1</span>
hi link todoTag <span class="hljs-constant">Constant</span>
<span class="hljs-keyword">if</span> &background == <span class="hljs-string">"light"</span>
hi todoDone ctermfg=darkgray guifg=<span class="hljs-comment">#999999</span>
<span class="hljs-keyword">else</span>
hi todoDone ctermfg=darkgray guifg=<span class="hljs-comment">#666666</span>
endif
set cursorline
command! -nargs=<span class="hljs-number">0</span> <span class="hljs-constant">TodoToggle</span> call <span class="hljs-constant">TodoToggle</span>()
function! <span class="hljs-constant">TodoToggle</span>()
<span class="hljs-keyword">if</span> !empty(matchstr(getline(<span class="hljs-string">'.'</span>), <span class="hljs-string">'\(\s*\)x '</span>))
s/\(\s*\)x /\<span class="hljs-number">1_</span> /
elseif !empty(matchstr(getline(<span class="hljs-string">'.'</span>), <span class="hljs-string">'\(\s*\)_ '</span>))
s/\(\s*\)<span class="hljs-number">_</span> /\<span class="hljs-number">1</span>x /
endif
endfunction
command! -nargs=<span class="hljs-number">0</span> <span class="hljs-constant">TodoDone</span> call <span class="hljs-constant">TodoDone</span>()
function! <span class="hljs-constant">TodoDone</span>()
<span class="hljs-keyword">if</span> !empty(matchstr(getline(<span class="hljs-string">'.'</span>), <span class="hljs-string">'\(\s*\)[_\-.] '</span>))
s/\(\s*\)[<span class="hljs-number">_</span>\-.] /\<span class="hljs-number">1</span>x /
endif
endfunction
command! -nargs=<span class="hljs-number">0</span> <span class="hljs-constant">TodoUndone</span> call <span class="hljs-constant">TodoUndone</span>()
function! <span class="hljs-constant">TodoUndone</span>()
<span class="hljs-keyword">if</span> !empty(matchstr(getline(<span class="hljs-string">'.'</span>), <span class="hljs-string">'\(\s*\)[x\-.] '</span>))
s/\(\s*\)[x\-.] /\<span class="hljs-number">1_</span> /
endif
endfunction
map <<span class="hljs-constant">Leader</span>>tt <span class="hljs-symbol">:TodoToggle<CR><Esc></span>
map <<span class="hljs-constant">Leader</span>>td <span class="hljs-symbol">:TodoDone<CR><Esc></span>
map <<span class="hljs-constant">Leader</span>>tu <span class="hljs-symbol">:TodoUndone<CR><Esc></span>
let <span class="hljs-symbol">b:</span>current_syntax = <span class="hljs-string">"todo"</span></code></pre>
<p><code>~/.vimrc</code> にて、拡張子 <code>todo</code> と紐付ける。</p>
<pre class="prettyprint"><code class=" hljs avrasm">au BufNewFile,BufRead *<span class="hljs-preprocessor">.todo</span> setf todo</code></pre>
<h3 id="利用方法">利用方法</h3>
<p>冒頭のスクリーンショットのように拡張子 <code>todo</code> のテキストファイルを vim で開いて利用するだけ。</p>
<p>例えば先頭の文字を <code>x</code> にすると色が変わるはず。</p>
<p>Leader がスペースの場合、<code>スペース t t</code> で完了・未完了を切り替えられる。</p>ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-41882054179464971322018-12-31T10:08:00.001+09:002018-12-31T10:08:32.677+09:00Node.js での Traditional PKWARE encryption 実装の記録<p>少し前、従来のパスワードつきのZIP圧縮(Traditional PKWARE encryption)をNode.js (Lambda)で使いたかったが、ちょうどよいものが見当たらなかったので <a href="https://github.com/ksoichiro/node-archiver-zip-encryptable">node-archiver-zip-encryptable</a> というものを作成したので記録しておく。</p>
<p>これは <a href="https://github.com/archiverjs/node-archiver">node-archiver</a> をベースにして、拡張機能的に付加することで利用する。 <br>
この archiver とその依存ライブラリが変わらない限りは、100% ピュア JavaScript の実装である。</p>
<p>今回の実装をするにあたり、そもそも普通に Windows で展開できるような(セキュリティ的には弱い)パスワードつきの圧縮というものに名前がついているのを知らず、調査に手間取った。</p>
<p><a href="https://github.com/alexmullins/zip">Golang での ZIP 圧縮ライブラリ alexmullins/zip</a> にパスワード付与を実装している <a href="https://github.com/yeka/zip">yeka/zip</a> と、こちらの仕様を参考に実装。 <br>
<a href="https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT">https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT</a> <br>
<a name='more'></a></p>
<p>archiver は汎用的なアーカイブ作成のライブラリになっており、プラグインのような仕組みとして拡張子とその処理を登録することができる。これを利用して、以下のように archiver を読み込み、追加の拡張子として パスワードつき ZIP を登録する構成としている。</p>
<pre class="prettyprint"><code class="language-js hljs "><span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
<span class="hljs-keyword">var</span> archiver = <span class="hljs-built_in">require</span>(<span class="hljs-string">'archiver'</span>);
archiver.registerFormat(<span class="hljs-string">'zip-encryptable'</span>, <span class="hljs-built_in">require</span>(<span class="hljs-string">'archiver-zip-encryptable'</span>));</code></pre>
<p>あとは、archiver の API 仕様に沿って利用すれば良い (パスワードのオプションは追加で必要だが)。</p>
<pre class="prettyprint"><code class="language-js hljs "><span class="hljs-keyword">var</span> output = fs.createWriteStream(__dirname + <span class="hljs-string">'/example.zip'</span>);
<span class="hljs-keyword">var</span> archive = archiver(<span class="hljs-string">'zip-encryptable'</span>, {
zlib: { level: <span class="hljs-number">9</span> },
forceLocalTime: <span class="hljs-literal">true</span>,
password: <span class="hljs-string">'test'</span>
});
archive.pipe(output);
archive.append(Buffer.from(<span class="hljs-string">'Hello World'</span>), { name: <span class="hljs-string">'test.txt'</span> });
archive.append(Buffer.from(<span class="hljs-string">'Good Bye'</span>), { name: <span class="hljs-string">'test2.txt'</span> });
archive.finalize();</code></pre>
<p>実装するにあたり、実はほとんどが archiver に含まれる ZIP の実装と同じなのだが、それ自体は拡張されることを意図した構成にはなっていなかったため、既存のクラスを継承して必要な function をオーバーライドするようにした。</p>
<p>ZIP 形式そのものの理解ができていなかったため、実行してはバイナリエディタでバイナリの中身を確認し、仕様通りになっているかの確認を繰り返すようなデバッグをした。</p>
<p>ファイルの仕様を理解していくのもなかなか面白いというか、今さらではあるが以下のような気付きがあった。</p>
<ul>
<li>ZIP のエントリの元サイズを記述するための領域が 4 バイト(符号なし)で固定長で用意されているため、この領域で表現できる最大値=4GB が通常の(従来の) ZIP ファイルに含められる最大サイズ。</li>
<li>ZIP の各領域にはシグニチャと呼ばれる固定のバイト列があり、それを目印にして諸々の処理をするため、これを見ればファイルの内容が ZIP なのかどうかを判別することはできそう。</li>
</ul>
<p>その他の気づき、感想。</p>
<ul>
<li>バイナリのバイト列を扱うため、当然ながらリトルエンディアン、ビッグエンディアンを意識しないと実装できない。こういうのを実装しないとなかなかその概念自体触れる機会がないが…</li>
<li>JavaScript (Node.js) では公式には 64bit の整数値を扱う方法がない模様。これにより計算過程でオーバーフローしていることにしばらく気付かなかった…。</li>
</ul>ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-5558498539591464902018-12-30T23:46:00.001+09:002018-12-30T23:49:35.273+09:00Blogger 高速化<p>自分で構築すればもっとシンプルで楽にできるのかもしれないが、長らくこのドメインでやってきていることもあり Blogger を続けようと思っている。 <br>
ただ、Blogger の「テンプレート」にはいろいろムダなものが入っていて、ページの表示が遅かったりする。ブログ再開を機に更新することにした。</p>
<p>Lighthouse の Chrome Extension での計測で、以下のように改善。</p>
<table>
<thead>
<tr>
<th>項目</th>
<th align="right">変更前</th>
<th align="right">変更後</th>
</tr>
</thead>
<tbody><tr>
<td>Performance</td>
<td align="right">75</td>
<td align="right">90</td>
</tr>
<tr>
<td>Progressive Web App</td>
<td align="right">58</td>
<td align="right"></td>
</tr>
<tr>
<td>Accessibility</td>
<td align="right">44</td>
<td align="right">65</td>
</tr>
<tr>
<td>Best Practices</td>
<td align="right">79</td>
<td align="right">93</td>
</tr>
<tr>
<td>SEO</td>
<td align="right">100</td>
<td align="right">100</td>
</tr>
</tbody></table>
<p><a href="https://developers.google.com/speed/pagespeed/insights/">PageSpeed Insights</a> だとモバイルが 91 点、PC が 100 点に改善した。</p>
<p>実際に表示した場合のあるときの数値は <br>
69 リクエスト、652 KB、5.9 秒から <br>
38 リクエスト、325 KB、3.1 秒に改善 (ばらつきはある)。</p>
<p>以下では、その改善のための変更内容について説明。 <br>
<a name='more'></a></p>
<h2 id="共有ボタンを消す">共有ボタンを消す</h2>
<p>Blogger 特有のメール/Blog this!/Facebook/Twitter/Google+のボタンのセットは、シンプルに見えて意外に時間がかかっているようだったため、思い切って除去してみた。これで <br>
59 リクエスト、624KB、4.1秒に削減。</p>
<h2 id="1ボタンの廃止">+1ボタンの廃止</h2>
<p>Google+ の +1 のボタン。Google+ も終了することだし、なくなっても良いだろうと考えた。 <br>
特に、plusone.js という JavaScript がパフォーマンスに悪影響を及ぼしているようで、テンプレートが実際の HTML に展開されるときに埋め込まれる。 <br>
これを削除するには、以下のようなコードを削除し(<code>&lt;</code> などは誤りではなく、実際そのように埋め込まれている)、</p>
<pre class="prettyprint"><code class="language-html hljs ">&lt;script type=&quot;text/javascript&quot; src=&quot;https://apis.google.com/js/plusone.js&quot;&gt;&lt;/script&gt;</code></pre>
<p>以下のように <code><body></code> の閉じタグを記述する。 <br>
いくつかのブログで見かけたが、おそらく Blogger が <code></body></code> を検出して何かしようとしているのをごまかしているのだろう。</p>
<pre class="prettyprint"><code class="language-html hljs ">&lt;!--<span class="hljs-tag"></<span class="hljs-title">body</span>></span>--&gt; &lt;/body&gt;</code></pre>
<p>これで 40 リクエスト、358 KB、 3.8 秒まで減った。</p>
<p>ここでもう一度 Lighthouse で計測すると Performance が 88 まで改善した。</p>
<p>ここからしばらくは、改善項目として挙げられていたものへの対処。 <br>
速度に影響するものもあるが、途中から面倒になり計測していなかった…。</p>
<h2 id="他ドメインを-targetblank-で開く場合の-noopener-の付与">他ドメインを target=”_blank” で開く場合の noopener の付与</h2>
<p>開いたページを切り離して動作させるために <code>rel="noopener"</code> を付与する。 <br>
以下参考。</p>
<p><a href="https://developers.google.com/web/tools/lighthouse/audits/noopener?hl=ja">サイトで rel=”noopener” を使用して外部アンカーを開く</a></p>
<p>フッター部の Powered by Blogger のリンクが曲者。 <br>
Blogger が生成しているコードのため、単純には手を入れられない。 <br>
<code><body></code> の閉じタグの前に以下を追加。 <br>
これで動作するかどうかはブログの構成によるだろう。</p>
<pre class="prettyprint"><code class="language-html hljs "><span class="hljs-tag"><<span class="hljs-title">script</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">'text/javascript'</span>></span><span class="javascript">
$(<span class="hljs-string">'#Attribution1 a[target="_blank"]'</span>).attr(<span class="hljs-string">'rel'</span>, <span class="hljs-string">'noopener'</span>);
</span><span class="hljs-tag"></<span class="hljs-title">script</span>></span></code></pre>
<h2 id="jquery-のアップデート">jQuery のアップデート</h2>
<p>古い、脆弱性のあるバージョン(1.8.3)を使っていたため、今のところ問題の出ていない 3.3.1 にアップデート。</p>
<p>なお、ページ内でこの jQuery に依存する JavaScript がある場合、上記のような大幅なアップデートで動かなくなるものがある可能性もあるので注意が必要。</p>
<h2 id="html-タグへの-lang-属性の指定">html タグへの lang 属性の指定</h2>
<p>Accessibility の項目。 <br>
<code><html></code> タグに <code>lang='ja'</code> を追加。</p>
<h2 id="meta-タグの-max-scale-値を除去">meta タグの max-scale 値を除去</h2>
<p>これも Accessibility の項目。単純に削除。</p>
<pre class="prettyprint"><code class="language-diff hljs "><span class="hljs-deletion">- <meta content='width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0' name='viewport'/></span>
<span class="hljs-addition">+ <meta content='width=device-width,initial-scale=1.0,minimum-scale=1.0' name='viewport'/></span></code></pre>
<h2 id="色のコントラストの調整">色のコントラストの調整</h2>
<p>文字と背景のコントラストの差が小さいと、Accessiblity の観点ではよろしくない。 <br>
以下で確認しながら色を調整。</p>
<p><a href="https://dequeuniversity.com/rules/axe/2.2/color-contrast?application=lighthouse">Text elements must have sufficient color contrast against the background</a></p>
<h2 id="最近の投稿の削除">最近の投稿の削除</h2>
<p>このブログのフィードを解析して最近の投稿を表示するようなウィジェットを追加していたが、これが遅さの原因のようだったため、思い切って一旦削除。</p>
<h2 id="httphttps-の混在しているものを修正">http/https の混在しているものを修正</h2>
<p><code>http://</code> と書かれているものを <code>//</code> に修正し、アクセスしたプロトコルに応じて変更するようにした。一応、どちらでも各リソースがアクセスできることは確認しておく。</p>
<h2 id="skin-の中の-css-を外部-css-ファイルに移動">skin の中の CSS を外部 CSS ファイルに移動</h2>
<p>テンプレートのデザインの根幹部分のはずだが、ここには変数の定義が書かれていて、変数を使ったスタイルが定義されている。実際にアクセスして出力されている CSS を別の CSS ファイルに移し、この領域は空にした。</p>
<pre class="prettyprint"><code class="language-xml hljs "> <span class="hljs-tag"><<span class="hljs-title">b:skin</span>></span><span class="hljs-cdata"><![CDATA[
]]></span><span class="hljs-tag"></<span class="hljs-title">b:skin</span>></span>
<span class="hljs-tag"><<span class="hljs-title">b:template-skin</span>></span>
<span class="hljs-cdata"><![CDATA[
]]></span>
<span class="hljs-tag"></<span class="hljs-title">b:template-skin</span>></span></code></pre>
<p>なお、外部 CSS は minify しておく。 <br>
当初、外部ウェブサイトで CSS を minify していたが、スタイルが想定外に崩れてしまっていたため、テンプレート、CSS 等を管理する <a href="https://github.com/ksoichiro/memorandum">Git リポジトリ</a>を用意して npm を導入し、<a href="https://github.com/jakubpawlowicz/clean-css-cli">clean-css-cli</a> で minify するようにした。</p>
<p>また、いきなり Blogger のテンプレートを変更して本番反映するのも避けたかったので、 npm の導入したので <a href="https://github.com/lwsjs/local-web-server">local-web-server</a> を使い、HTML をローカルで動作確認してから反映するようにした。</p>
<h2 id="一部のスタイルをインライン化">一部のスタイルをインライン化</h2>
<p>スタイルを外部 CSS に移動させてしまった結果、ページ表示の初期段階ではスタイルなしの状態になってしまうため、初期表示の見た目に大きく影響するようなスタイルを抽出して HTML ファイル内部に埋め込んだ。</p>
<p>埋め込む際には、minify してから埋め込む。</p>
<p>このためのツールもありそうだが、今回は inline.css というファイルを作ってローカルで少しずつ移して動作確認し、できてきたら clean-css-cli で minify してから以下のように外部 CSS の読み込みの前に埋め込むようにした。</p>
<pre class="prettyprint"><code class="language-html hljs "><span class="hljs-tag"><<span class="hljs-title">style</span>></span><span class="css"><span class="hljs-tag">body</span><span class="hljs-rules">{<span class="hljs-rule"><span class="hljs-attribute">background</span>:<span class="hljs-value"><span class="hljs-hexcolor">#c5eaf7</span></span></span>;<span class="hljs-rule"><span class="hljs-attribute">font</span>:<span class="hljs-value">normal normal <span class="hljs-number">12</span>px Arial...(略)</span></span></span></span><span class="hljs-tag"></<span class="hljs-title">style</span>></span>
<span class="hljs-tag"><<span class="hljs-title">link</span> <span class="hljs-attribute">as</span>=<span class="hljs-value">'style'</span> <span class="hljs-attribute">href</span>=<span class="hljs-value">'//ksoichiro.github.io/memorandum/memorandum.min.css'</span> <span class="hljs-attribute">onload</span>=<span class="hljs-value">'this.rel=&apos;stylesheet&apos;'</span> <span class="hljs-attribute">rel</span>=<span class="hljs-value">'preload'</span>/></span></code></pre>
<h2 id="quick-edit-の削除">Quick Edit の削除</h2>
<p>自分で表示した場合に出てくる、編集用のアイコンは不要なため削除。 <br>
(これはあまり Lighthouse に関係ないが)</p>
<p>以下の記述を削除することで反映。</p>
<pre class="prettyprint"><code class=" hljs ruby"><<span class="hljs-symbol">b:</span><span class="hljs-keyword">include</span> name=<span class="hljs-string">'quickedit'</span>/></code></pre>
<pre class="prettyprint"><code class=" hljs ruby"><<span class="hljs-symbol">b:</span><span class="hljs-keyword">include</span> data=<span class="hljs-string">'post'</span> name=<span class="hljs-string">'postQuickEdit'</span>/></code></pre>
<p>改善は以上。</p>ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-2154182412092062102018-12-29T18:44:00.001+09:002018-12-29T18:44:52.804+09:00Android PNG画像をVectorに変換する<p>2017年以降 ブログ更新が停滞していたので、シンプル単語帳のアップデートを進める中での課題から。</p>
<p>アプリ内で使う小さい画像ファイルは DPI ごとに用意していて、より大きな解像度が登場すると作り直すようなことをしていたが、これをやらなくて済むようにするのと、アプリのサイズを少しでも減らせたらという思いで、今さらながら VectorDrawable を試した。 <br>
<a name='more'></a></p>
<p>対象としたのは「↓」という感じの画像で、以下のようなXMLで簡単につくれる。</p>
<pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-pi"><?xml version="1.0" encoding="utf-8"?></span>
<span class="hljs-tag"><<span class="hljs-title">vector</span> <span class="hljs-attribute">xmlns:android</span>=<span class="hljs-value">"http://schemas.android.com/apk/res/android"</span>
<span class="hljs-attribute">android:height</span>=<span class="hljs-value">"48dp"</span>
<span class="hljs-attribute">android:width</span>=<span class="hljs-value">"48dp"</span>
<span class="hljs-attribute">android:viewportHeight</span>=<span class="hljs-value">"100"</span>
<span class="hljs-attribute">android:viewportWidth</span>=<span class="hljs-value">"100"</span> ></span>
<span class="hljs-tag"><<span class="hljs-title">group
</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"arrow"</span>></span>
<span class="hljs-tag"><<span class="hljs-title">path
</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"line"</span>
<span class="hljs-attribute">android:fillColor</span>=<span class="hljs-value">"#ffffa713"</span>
<span class="hljs-attribute">android:pathData</span>=<span class="hljs-value">"m 25,0 l 0,50 50,0 0,-50 z"</span> /></span>
<span class="hljs-tag"><<span class="hljs-title">path
</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"triangle"</span>
<span class="hljs-attribute">android:fillColor</span>=<span class="hljs-value">"#ffffa713"</span>
<span class="hljs-attribute">android:pathData</span>=<span class="hljs-value">"m 0,50 l 100,0 -50,50 z"</span> /></span>
<span class="hljs-tag"></<span class="hljs-title">group</span>></span>
<span class="hljs-tag"></<span class="hljs-title">vector</span>></span></code></pre>
<p>結果は以下のような画像になる。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_TivLgWiwO83OiD9ZZ2NlyYFaOYoEvkiIcegJN4Y7alG6_0TntUFqFcO9Giy-7axgecZytRSIeINfAEnv36c1JT8m4BRC2YBuH272G11yCXaYT7nk36lWieOWXsHwMKZ6iMND1Hx3FsiR/s0/20181229001.png" alt="Arrow" title="20181229001.png"></p>
<p>アニメーションを取り入れるのがより良い使い方と思われるが、目的は達成できた。</p>
<p>パスの編集には以下が参考になる。</p>
<p><a href="https://medium.com/@ali.muzaffar/understanding-vectordrawable-pathdata-commands-in-android-d56a6054610e">Understanding VectorDrawable pathData commands in Android</a></p>ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-58272002304792989102018-12-29T18:14:00.001+09:002018-12-29T18:14:50.519+09:00Android ナイトモードを起動時に設定するとonCreateが二度呼ばれる<p>シンプル単語帳にナイトモードを導入してほしいリクエストがあり、 <br>
確かにあったほうが良さそうだと思ったため実装している。 <br>
(現時点ではまだリリースしていない)</p>
<p>ただ、どうもアプリの起動が遅くなっているように見える。</p>
<p>各 Activity の onCreate でナイトモードを設定するような方法で実装。 <br>
<a name='more'></a></p>
<pre class="prettyprint"><code class="language-kotlin hljs avrasm">override fun onCreate(savedInstanceState: Bundle?) {
super<span class="hljs-preprocessor">.onCreate</span>(savedInstanceState)
if (App<span class="hljs-preprocessor">.instance</span><span class="hljs-preprocessor">.nightModeEnabled</span>) {
AppCompatDelegate<span class="hljs-preprocessor">.setDefaultNightMode</span>(AppCompatDelegate<span class="hljs-preprocessor">.MODE</span>_NIGHT_YES)
} else {
AppCompatDelegate<span class="hljs-preprocessor">.setDefaultNightMode</span>(AppCompatDelegate<span class="hljs-preprocessor">.MODE</span>_NIGHT_NO)
}</code></pre>
<p>デバッグしてみると、これが原因で onCreate が二回呼ばれてしまい初期画面の表示が遅くなっている模様。</p>
<p>ナイトモードが変更されたことによって再度 onCreate が呼び出されてしまっている。</p>
<p>onCreate が複数回呼び出されるというところでピンとくるべきだったが、 <br>
よく調べてみると<a href="https://developer.android.com/guide/topics/manifest/activity-element?hl=ja#config">設定変更のイベント</a>によって発生しているのだった。</p>
<p>この設定変更が必要ないなら以下のようにすると解決するが、 <br>
今回のケースではナイトモードが反映されなくなってしまう。</p>
<pre class="prettyprint"><code class="language-xml hljs "> <span class="hljs-tag"><<span class="hljs-title">activity</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">".app.MainActivity"</span>
<span class="hljs-attribute">android:configChanges</span>=<span class="hljs-value">"uiMode"</span>></span></code></pre>
<p>というわけで、対象 Activity の onCreate をなるべく軽くしておくくらいしか対処はできなさそう。</p>ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0tag:blogger.com,1999:blog-7702612945354492373.post-33987706237695351302018-12-24T22:36:00.001+09:002018-12-24T22:38:24.777+09:00Concourse CI チュートリアルの実践<p><a href="https://ksoichiro.blogspot.com/2018/12/ci.html">前回のエントリ</a>でふれた Concourse CI について。 <br>
チュートリアルを試したのだが、いくつか躓くポイントがあったため記録しておく。 <br>
※Concourse CI を批判するわけではなく、単なる記録。 <br>
<a name='more'></a> <br>
環境としては Windows 10、Docker Toolbox の Docker で Concourse をインストールした。</p>
<h3 id="コンソール出力">コンソール出力</h3>
<p>Concourse は fly コマンドを使って操作することになっているが、まず、 fly コマンドを実行したときに色がうまく出ない。 </p>
<pre class="prettyprint"><code class=" hljs lasso">C:<span class="hljs-subst">\</span>Users<span class="hljs-subst">\</span>soichiro<span class="hljs-subst">\</span>workspace<span class="hljs-subst">\</span>concourse<span class="hljs-attribute">-tutorial</span><span class="hljs-subst">></span>fly <span class="hljs-attribute">-t</span> tutorial watch <span class="hljs-attribute">-j</span> hello<span class="hljs-attribute">-world</span>/job<span class="hljs-attribute">-hello</span><span class="hljs-attribute">-world</span>
<span class="hljs-preprocessor">[</span><span class="hljs-number">35</span>maborted <span class="hljs-preprocessor">[</span><span class="hljs-number">0</span>m</code></pre>
<p>builds コマンドでは着色されていたりするので、環境的な問題というよりコマンドごとの問題なのかもしれない。</p>
<h3 id="スクリプトの実行">スクリプトの実行</h3>
<p><a href="https://concoursetutorial.com/basics/task-scripts/">https://concoursetutorial.com/basics/task-scripts/</a></p>
<p>そのままだと以下のようなエラーが発生して実行できない。</p>
<pre class="prettyprint"><code class=" hljs vbscript">Backend <span class="hljs-keyword">error</span>: <span class="hljs-keyword">Exit</span> status: <span class="hljs-number">500</span>, message: {<span class="hljs-string">"Type"</span>:<span class="hljs-string">""</span>,<span class="hljs-string">"Message"</span>:<span class="hljs-string">"runc exec: exit status 1: exec failed: container_linux.go:348: starting container process caused \"</span>exec: \\\<span class="hljs-string">"./task-scripts/task_show_uname.sh\\\"</span>: permission denied\<span class="hljs-string">"\n"</span>,<span class="hljs-string">"Handle"</span>:<span class="hljs-string">""</span>,<span class="hljs-string">"ProcessID"</span>:<span class="hljs-string">""</span>,<span class="hljs-string">"Binary"</span>:<span class="hljs-string">""</span>}</code></pre>
<p><code>./test.sh</code> の形式だとアクセス権がなく実行できない模様。 <br>
Windows全般の問題?</p>
<p>シェバンが <code>#!/bin/sh</code> なら、<code>sh test.sh</code> の形式にすることで実行はできる。</p>
<pre class="prettyprint"><code class=" hljs avrasm"><span class="hljs-label">run:</span>
path: sh
args: [<span class="hljs-string">"./task-scripts/task_show_uname.sh"</span>]</code></pre>
<p>バイナリの場合は問題になるかも。</p>
<h3 id="スリープからの復帰失敗未解決">スリープからの復帰失敗(未解決)</h3>
<p>途中、PCをスリープさせたところ <code>docker-machine</code> 内からHTTPアクセスできなくなりジョブが失敗するようになったため、<code>docker-machine</code> を restart した。</p>
<pre class="prettyprint"><code class=" hljs haskell"><span class="hljs-title">docker</span>-machine ssh <span class="hljs-default"><span class="hljs-keyword">default</span></span>
<span class="hljs-title">sudo</span> su -
<span class="hljs-title">shutdown</span> -r now
<span class="hljs-title">docker</span>-machine restart <span class="hljs-default"><span class="hljs-keyword">default</span></span>
<span class="hljs-title">eval</span> <span class="hljs-string">"$(docker-machine env)"</span></code></pre>
<p>その後、unpause してジョブは動いているかのように見えたがことごとく失敗しており、CLI からリソースチェックしても以下のようになっていた。</p>
<pre class="prettyprint"><code class=" hljs lasso">$ fly <span class="hljs-attribute">-t</span> tutorial cr <span class="hljs-attribute">-r</span> hello<span class="hljs-attribute">-world</span>/my<span class="hljs-attribute">-timer</span>
error: check failed <span class="hljs-keyword">with</span> exit status <span class="hljs-string">'70'</span>:
unknown <span class="hljs-keyword">handle</span>: <span class="hljs-number">7</span>c3bb164<span class="hljs-subst">-</span><span class="hljs-number">0233</span><span class="hljs-subst">-</span><span class="hljs-number">44</span>df<span class="hljs-subst">-</span><span class="hljs-number">67</span>b1<span class="hljs-subst">-</span><span class="hljs-number">0</span>d9d0bae2dcd</code></pre>
<p><a href="https://github.com/concourse/concourse/issues/2603">concourseのissue#2603</a> より、workers を確認するのが良さそうだった。</p>
<pre class="prettyprint"><code class=" hljs livecodeserver">$ fly -t tutorial workers
name containers <span class="hljs-built_in">platform</span> tags team state <span class="hljs-built_in">version</span>
<span class="hljs-number">43</span>aec2779db0 <span class="hljs-number">0</span> linux <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> running <span class="hljs-number">2.1</span>
<span class="hljs-operator">the</span> following workers have <span class="hljs-operator">not</span> checked <span class="hljs-operator">in</span> recently:
name containers <span class="hljs-built_in">platform</span> tags team state <span class="hljs-built_in">version</span>
<span class="hljs-number">03</span>dd08af10de <span class="hljs-number">0</span> linux <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> stalled <span class="hljs-number">2.1</span>
these stalled workers can be cleaned up <span class="hljs-keyword">by</span> running:
fly -t tutorial prune-worker -w (name)</code></pre>
<p>ここで <code>stalled</code> の表示になっているものを prune してみる。</p>
<pre class="prettyprint"><code class=" hljs lasso">$ fly <span class="hljs-attribute">-t</span> tutorial prune<span class="hljs-attribute">-worker</span> <span class="hljs-attribute">-w</span> <span class="hljs-number">03</span>dd08af10de
pruned <span class="hljs-string">'03dd08af10de'</span></code></pre>
<p>workers の一覧からは消えたが、解決しない。</p>
<p><code>unknown handle</code> と表示されているのは container のようだが、これを削除するやり方があるのだろうか。</p>
<pre class="prettyprint"><code class=" hljs livecodeserver">$ fly -t tutorial cs
handle worker pipeline job build <span class="hljs-comment"># build id type name attempt</span>
<span class="hljs-number">098</span>b0351-<span class="hljs-number">20</span>c8-<span class="hljs-number">415</span><span class="hljs-operator">a</span>-<span class="hljs-number">50</span>c5-f8911b8b8e27 <span class="hljs-number">43</span>aec2779db0 <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> check <span class="hljs-constant">none</span> n/<span class="hljs-operator">a</span>
<span class="hljs-number">5</span>a6de26c-<span class="hljs-number">6544</span>-<span class="hljs-number">40</span>c2-<span class="hljs-number">69</span>ac-<span class="hljs-number">2</span>a09d756363c <span class="hljs-number">43</span>aec2779db0 hello-world job-hello-world <span class="hljs-number">9</span> <span class="hljs-number">21</span> task hello-world n/<span class="hljs-operator">a</span>
<span class="hljs-number">7</span>c3bb164-<span class="hljs-number">0233</span>-<span class="hljs-number">44</span>df-<span class="hljs-number">67</span>b1-<span class="hljs-number">0</span>d9d0bae2dcd <span class="hljs-number">43</span>aec2779db0 <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> check <span class="hljs-constant">none</span> n/<span class="hljs-operator">a</span>
fafbf18d-<span class="hljs-number">0116</span>-<span class="hljs-number">4</span>be9-<span class="hljs-number">4</span>afb-<span class="hljs-number">472</span>a10142432 <span class="hljs-number">43</span>aec2779db0 <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> check <span class="hljs-constant">none</span> n/<span class="hljs-operator">a</span></code></pre>
<p>わからないが、コンテナ自体は確認できるため</p>
<pre class="prettyprint"><code class=" hljs lasso">fly <span class="hljs-attribute">-t</span> tutorial i <span class="hljs-attribute">-c</span> hello<span class="hljs-attribute">-world</span>/my<span class="hljs-attribute">-timer</span></code></pre>
<p>でコンテナの中に入ってみたものの、何を見たら良いものか… <br>
と考えているうちに、いつの間にか、定期的にトリガーイベントを発生させる <code>my-timer</code> のリソースと、チュートリアルのコード <code>resource-tutorial</code> の check は正常になり、動き始めていた。</p>
<p>しかし、結局タスク自体は失敗している。</p>
<pre class="prettyprint"><code class=" hljs ruby">task config <span class="hljs-string">'resource-tutorial/tutorials/basic/task-hello-world/task_hello_world.yml'</span> <span class="hljs-keyword">not</span> found</code></pre>
<p>リポジトリは clone できているのでそんなことはないはずなのだが…</p>
<p><a href="https://github.com/concourse/concourse/issues/1796">https://github.com/concourse/concourse/issues/1796</a> <br>
これを参考にしてみると、この方の対処では</p>
<blockquote>
<ul>
<li>stop Concourse containers: docker-compose down</li>
<li>delete worker folder: rm -rf </li>
<li>start Concourse containers: docker-compose up -d</li>
<li>wait for worker to stall (or rather, wait for Fly to report it stalled), then prune it</li>
<li>everything goes back to normal</li>
</ul>
</blockquote>
<p>ということなので、worker のフォルダを docker の別ボリュームで分けておいて物理的に削除できるようにしたほうが良いのかもしれない。これは未確認。</p>
<p>改めて container を確認すると、使われていないものが残ったままになっている。</p>
<pre class="prettyprint"><code class=" hljs livecodeserver">$ fly -t tutorial containers
handle worker pipeline job build <span class="hljs-comment"># build id type name attempt</span>
<span class="hljs-number">098</span>b0351-<span class="hljs-number">20</span>c8-<span class="hljs-number">415</span><span class="hljs-operator">a</span>-<span class="hljs-number">50</span>c5-f8911b8b8e27 <span class="hljs-number">43</span>aec2779db0 <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> check <span class="hljs-constant">none</span> n/<span class="hljs-operator">a</span>
<span class="hljs-number">5</span>a6de26c-<span class="hljs-number">6544</span>-<span class="hljs-number">40</span>c2-<span class="hljs-number">69</span>ac-<span class="hljs-number">2</span>a09d756363c <span class="hljs-number">43</span>aec2779db0 hello-world job-hello-world <span class="hljs-number">9</span> <span class="hljs-number">21</span> task hello-world n/<span class="hljs-operator">a</span>
<span class="hljs-number">62</span>c4120f-c67e-<span class="hljs-number">466</span>b-<span class="hljs-number">77</span>d6-c4c3a074a2b7 <span class="hljs-number">43</span>aec2779db0 hello-world job-hello-world <span class="hljs-number">20</span> <span class="hljs-number">64</span> <span class="hljs-built_in">get</span> my-timer n/<span class="hljs-operator">a</span>
<span class="hljs-number">6687</span>c1f4-<span class="hljs-number">7636</span>-<span class="hljs-number">4</span>a0b-<span class="hljs-number">4940</span>-<span class="hljs-number">0e6</span>c7f891d62 <span class="hljs-number">43</span>aec2779db0 hello-world job-hello-world <span class="hljs-number">19</span> <span class="hljs-number">63</span> <span class="hljs-built_in">get</span> my-timer n/<span class="hljs-operator">a</span>
f192aa51-<span class="hljs-number">9e47</span>-<span class="hljs-number">4</span>d84-<span class="hljs-number">4</span>af0-<span class="hljs-number">35e2248</span>d57f7 <span class="hljs-number">43</span>aec2779db0 <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> check <span class="hljs-constant">none</span> n/<span class="hljs-operator">a</span>
fafbf18d-<span class="hljs-number">0116</span>-<span class="hljs-number">4</span>be9-<span class="hljs-number">4</span>afb-<span class="hljs-number">472</span>a10142432 <span class="hljs-number">43</span>aec2779db0 <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> <span class="hljs-constant">none</span> check <span class="hljs-constant">none</span> n/<span class="hljs-operator">a</span></code></pre>
<p>一度 pipeline の設定から resource を削除し、ジョブを失敗させた後に再びもとの設定を反映した。(ビルド履歴を残したままにしようとした)</p>
<p>今度は <code>file not found</code> の結果となってしまった…。</p>
<p>仕方ないので pipeline を削除して再作成したが、同じ結果。 <br>
Windows で docker を使って試しているせいなのか…これだとかなり信頼性が低いと言わざるを得ない。</p>
<p>Concourse 自体を再起動してみる。</p>
<pre class="prettyprint"><code class=" hljs lasso">docker<span class="hljs-attribute">-compose</span> restart</code></pre>
<p>また <code>unknown handle</code> が出る…。</p>
<p>もう少し試したいが、今回は断念。 <br>
Windows の Docker Toolbox ではなく Vagrant で Linux の VM を作った上でその中で docker をインストールするとか、Windows のバイナリを実行するようにしたら変わるのかもしれない。</p>ksoichirohttp://www.blogger.com/profile/13313957386090295244noreply@blogger.com0