astamuse Lab

astamuse Labとは、アスタミューゼのエンジニアとデザイナーのブログです。アスタミューゼの事業・サービスを支えている知識と舞台裏の今を発信しています。

NO MORE リリース職人 〜リリースツールをごっそり置き換えた話〜

はじめまして、JVMの世界に4年目、勇気と根性で乗り切る脳筋系エンジニア、chotaroと申します。
astamuse.comのバグフィックスや改善活動を担当しています。

今回はそのastamuse.comにおける改善活動の一部をご紹介します。
同じ悩みを抱えている組織や、アスタミューゼの開発チームに興味を持たれた方の参考になれば、幸いです。

ブラックボックス化する運用ツール

長年メンテナンスを続けてきたサービスでは、その運用方法や使っている技術要素が負債になってしまう、というのはよくあることだと思います。
astamuse.comも例に漏れず、そんな状況下にあります。

実装やプログラムの品質面では過去にえいやさんが記事を上げていますが、運用においてはまた異なる起因からメンテナンスを行う必要が生じます。

弊社開発チームでは、直接的にはメンバーの離脱や参入が見直しのきっかけとなりました。
過去に作られたしくみが「どうやってかは分からないがとりあえず動いているからOK」という状態になってしまっており、修正も難しくなっていることを検知したためです。

具体的には、

  • webサイトの運用ツール
  • リリース用のシェルスクリプト
  • jenkinsのJOB構成(およびその環境)

などのツールが対象です。

それぞれ残されたドキュメントや動いているツールのコードをもとに改善・再構築を進めていますが、中でも特に問題であったのはリリース用のシェルスクリプトでした。

既存の仕組みの問題点

これまでのリリースのしくみは、以下のような構成になっていました。

構成

f:id:astamuse:20180418115311j:plain
構成図_before

  • 担当者はgitlabからリリース対象のリポジトリをcloneする
  • リリース用のシェルスクリプトを、リリースする環境ごとの設定ファイルを食わせて実行する
  • ローカルの開発環境でビルドした資材をアプリケーションサーバーに配備し、リリースが完了する

問題点

  • リリース作業の成否、および対象がローカル環境に依存する
  • シェルスクリプトの可読性が低い
  • リリース手順の保守性が低い

特にシェルスクリプトでは、

  • mvn、gradleなどのうちからプロジェクトの構成にマッチするものでテスト・パッケージ化実行
  • 設定ファイルの権限変更および再配置
  • cacheの削除

など多くのタスクを条件に応じて行っており、上から下に読み下すことが困難な状態となっていました。
そのため、リリースに必要なタスクの全容を把握することすらも難しくする要因となっていました。

新しい仕組みの設計

暗黙知化していたリリースプロセス

もともとの構成は、全体としてオペレーションする開発者に依存する形となっているため、以下のような前提に基づいていたと考えられます。

  • 開発者は優秀なので、何かリリースで技術的な問題が起きてもシェルスクリプトを読めばすぐに問題点を解決できる。
  • 開発者は開発環境についても博識で注意深いので、ローカルとステージング・プロダクション環境での差分にも注意を払うことができる。
  • 開発者は構成管理についての知識と経験値を持っているので、デグレした資材をリリースするなんてありえない。

ある意味で、性善説的な哲学に則っているように思われます。

このあり方は人に大きく依存してしまうため、ノウハウが暗黙知化されてしまい、結果的にその人がいなくなったときのオーバーヘッドがかなり大きくなってしまいます。
そのため、新しく開発チームに入ってきた人でも、少し努力すれば形式知に落とし込めるくらいにプロセスをわかりやすくする必要がありました。

形式知化させるためのリリース戦略

2つの方針を立てました。

リリースはリモートの環境からそれぞれ行う。

個人の環境に依存させないようにします。

  • 各開発者のローカル環境からリリースはできないようにする(=シェルスクリプトは廃棄。)。
  • リリース作業用を行うマシンをクラウド上に配置し、リリースはそこから行う。

リリースタスクを構造化してオートメーションツールに任せる。

複雑怪奇なシェルスクリプトをオートメーションツールでリファクタリングします。

  • リリースプロセスに伴うタスクを抽象化することで、実施するタスクの全容をわかりやすくする。
  • 構造化することによって、パラメータをタスクから分離させる(パラメータによって振る舞いを定義する)。
  • 条件分岐を可能な限りなくし、実行するタスクを明確にする。

新しい仕組みに組み替える

検討結果を踏まえ新しい構成は、以下のようになりました。

構成

f:id:astamuse:20180418115230j:plain
構成図_after

  • 担当者はリリースする環境ごとのjenkinsにアクセスし、リリース用のjobを実行する
  • jenkinsはgitlabからリリース対象のリポジトリをcloneする
  • jenkinsはcloneしたリポジトリをもとにビルドを行い、warファイルなどリリース資材を作成する
  • jenkinsはansible-playbookを実行し、ビルドした資材をアプリケーションサーバーに配備し、リリースが完了する

改善効果

タスクの実行管理ツールとしてjenkinsを、オートメーションツールとしてansibleをそれぞれ活用することにより、以下のような効果を生み出すことができました。

jenkins採用のメリット

  • クラウド環境のjenkinsから、開発チームであれば誰でもリリースが可能になった。
  • 常にgitから最新のリビジョンを取得するため、デグレリスクがほぼゼロになった。

ansible-playbook採用のメリット

  • リリースタスクが抽象化されたことで、参入したての人でもリリースにかかるタスクの流れを把握できるようになった。
  • シェルスクリプトのときと比較してコード量が削減され、可読性、および保守性が向上された。

astamuse.comのこれから。

さて、そんな改善活動を推し進めているastamuse.comですが、事業モデルや取り巻く環境の変化に合わせ、プロダクトの方向性を再検討する必要が生じてきています。

開発に携わるメンバーが変遷し、また各要素技術のバージョンやトレンドが移り行く環境下でそのような対応を進めるには、「節約」することが必要です。
すなわち、負債になる部分および負債となってしまっている部分を、できるだけ抑制できる体制を仕組みの面で作り上げなくてはなりません。

今後開発チームとしては、引き続き本記事のような改善活動、開発プロセスの整備と共にプロダクトの再構築や改修の検討、実装を推進して行きます。
そのためには当然マンパワーも必要になります。

というわけで奥付で恐縮ではありますが、弊社のサービスや、これらの活動に興味を持っていただける方がおられましたら、是非お気軽に、下のバナーやwantedlyよりご応募いただければと思います。

以上、Have a nice development day!

PWAの将来性についての考察

f:id:astamuse:20180411105633p:plain デザイン部でフロントエンドエンジニアをしているkitoです。
先日、iOS 11.3のリリースでiPhoneでもPWAの一部の機能が利用できるようになりました。(プッシュ通知等は利用できない)今回は、Web界隈で急速に注目を上げ始めているPWA(Progressive Web Apps)の将来性を考察したいと思います。

いわゆるフロントエンド界隈では、新しいツールや技術が短いスパーンで登場しては消えていくということを繰り返しています。新陳代謝が激しい故に、革新的な技術がいち早く取り入れられる若々しいエコシステムは利点ではありますが、反面、苦労して学習した技術やツールが、立ちどころに古びて投資が無駄になってしまうケースも間々あります。これは現代のフロントエンドエンジニアには避けられない運命でしょう。とはいえ、それをむしろ楽しみ新しい技術の到来やそれをリードする若きエンジニアたちの登場を喜ぶべきかもしれません。

今回取り上げるPWAも、まだこれから普及するかどうかわからない技術です。しかし、もし普及すれば大きなインパクトがある技術で特別ホットな技術だと思います。このエントリーでは、PWAの個別の技術ではなく、PWAが開拓するかもしれないアプリの未来について個人的な展望を書きたいと思います。

PWAの概要

PWA(Progressive Web Apps)とは、端的に言うとHTMLとCSSとJavaScriptなどのWebアプリを作成する技術で、スマホのネイティブアプリにしかない機能を実現できる技術です。
主に下記のようなものです。

  • キャッシュを利用してオフライン時でも操作できる。
  • 全画面表示。
  • ネイティブアプリのようなプッシュ通知。
  • App StoreやGoogle Playを通さず、Web経由でのアプリ配布が可能。

ローカルキャッシュによるオフライン操作やスマホでのプッシュ通知は、Webのスマホサイトでは実現できない機能で、ネイティブアプリ固有の大きなアドバンテージでした。ストアを通さないアプリの配布は、開発者にとっては利点はありますが、ストアからアプリをインストールする習慣が身についているユーザーにとっては、必ずしも利点とは言えません。
あるいは、PWAはネイティブアプリのような大きなアプリを最初にインストールする必要がないので、通信環境が良くない地域の人にとっては良い選択肢なるという見解もあります。それはつまり、ネイティブアプリよりPWAが「poor」であることを逆手にとって、その「poor」さこそPWAの強味であるというわけです。

ただ、私はその売り出し方では、あまりインパクトがないように思えます。少なくとも日本にいる多くのユーザーにって、PWAは自分には関係ないと思うでしょう。そうではなく、後で詳述するユニバーサルアプリの文脈で、より低コストで必要十分なユーザー体験が実現できるアプリの技術として位置付けるべきです。それを詳しく見る前に、現状のPWAが直面している問題点をいくつか上げたい思います。

PWAの課題

まずひとつ目は、先にも触れましたがpoorである点です。
PWAは、ネイティブアプリよりパフォーマンスが明らかに劣っています。そもそもネイテイブアプリは、使われているプログラミング言語を含め、デバイスに最適化されていることが多いので、Web技術を借用しているPWAの方がパフォーマンス上は不利でしょう。ただし、PWAのpoorさは看過できないほどpoorであるとは考えていません。

実際、Google mapと日経新聞のPWAを使ってみると、ユーザー体験はそれほど悪くはないなという印象です。確かに、ネイティブアプリのGoogleマップの方が地図描画などがスムーズですが、実用に耐えないほどではなく、経路を検索したりする通常の用途では必要充分で、まあこれでも良いのではないかと思えました。もちろん、これはあくまで個人的な感想です。あなたもhttps://google.com/maps?force=pwaにスマホでアクセスし、ホーム画面にアプリを追加して使ってみてはいかがでしょうか。(もしネイティブアプリの方が起動してしまう場合は、シークレットモードやプライベートモードで開い下さい) 日本経済新聞のPWAもあります。https://r.nikkei.com/こちらもコンテンツを閲覧するのに必要充分だと思いました。(現在、Androidではプッシュ通知は来ますがiPhoneでは来ません)

ではネイティブアプリより、PWAを選ぶ積極的に選ぶ理由とは何でしょうか?
それはユーザーが選ぶというより、開発者がPWAを選ぶ理由ということですが、簡単に言うならコスト面で有利だからだと思います。
デバイスごとに最適化されるリッチなネイティブアプリより、Web技術を活用したユニバーサル志向のプアなアプリを作るほうが低コストですむからです。 そして、これは重要な観点ですが、今後10年を見据えた場合、VR/ARデバイスが普及した時代になると新たに3次元のアプリを作製してメンテンスしていかなければならなくなるでしょう。中長期的に考えるなら、Web、スマホなどの2次元用アプリは、ユニバーサルアプリに収斂させて、3次元用アプリは独自のアプリとして最適化する道を辿るのではないかと推測します。
つまり、ユニバーサルアプリは2次元用アプリのことで、その宇宙にはVR/ARデバイス用のアプリなどは想定されていません。ユニバーサルアプリに3次元用アプリも含めれば良いと思うかもしれません。しかし、少なくとも3次元用アプリが普及して離陸していく段階では、3次元用アプリはそこに含まれないと思います。なぜなら、2次元用アプリと3次元用アプリでは、デザインのロジックからして全然別だからです。

(参考:リープモーション社の3次元用アプリUIのサンプル動画です。)

例えば、Googleのマテリアルデザインは、2次元用のユニバーサルアプリのデザインとしては機能するでしょう。しかし、これを3次元用のアプリのデザインとして見た場合、オブジェクトが掴めたり、回転させたりという3次元特有のインタラクションを感じさせるUIデザインは見あたりません。もし、ユニバーサルアプリに3次元用のアプリを含めようとするなら、もっと新しいデザインコンセプトが必要になるでしょう。しかし、そのようなデザインはゲームの中では一部存在していますが、今のところ統一されたアプリのUIデザインとして成立していないです。ですから、ユニバーサルアプリには3次元用のアプリは容易には取り込まれないだろうと考えられます。私見ですが、PWAのようなユニバーサルアプリとは、Web技術で構成された2次元用アプリのプラットフォームのことだと考えています。

もう一つPWAが直面している大きな問題点は、AppleがどれほどPWAを積極的にサポートしていくのだろうかという点です。
率直に言って、AppleがPWAを押し進めなければPWAは普及せず、それを構成しているService Workerのような一部の技術が普及するに留まるかもしれません。実際その可能性はあると思います。Appleは、現状ではApp Storeを重視するビジネスモデルで、そこから多くの利益を得ています。ストアを通さずに配布できるPWAのプラットフォームに対して、積極的に投資するとは簡単には思えません。しかし、先日のiOSのアップデートでPWAの一部の機能がSafariに実装されました。これはどう考えるべきなのでしょうか。

実は、既に報じられているようにAppleもユニバーサルアプリのプラットフォームを実現しようと動き出しています。ただ、これはWeb技術を活用したものだと言明されているわけではなく、まだまったく未知数です。
それでも、先行しているMicrosoftのUWPを考慮に入れるなら、おそらくそれはWeb技術を活用したプラットフォームであり、さらに全てではないにしてもPWAの技術を取り入れているのではないかというのが、私の推測です。仮にPWA準拠したものであったとしたら、やはりストアの問題がネックになるでしょう。

ストアの問題に対して、Appleが取りうる選択肢は大きく2つあると思います。
ひとつは、ユニバーサルアプリをストアからしかインストールさせないようにする方法です。Webからのダウンロード&インストールを禁止して、全て管理されたストアからインストールしなくてはならないようにするのです。開発者は、これまで通りアプリの審査に四苦八苦することにはなりますが、ユーザーにとっては管理されたストアから安心してアプリをインストールできるので、それほどマイナスとは感じないでしょう、Appleにとっては今まで通りのビジネスモデルで手数料を徴収できます。

もうひとつは、ストアがゴーストタウンになる可能性を恐れず、ストアからの手数料を犠牲にしてWebからアプリをインストールできるようにし、ストアからの手数料をあてにする代わりに、Apple Payの手数料を収益の柱にするビジネスモデルです。
先日のiOSのアップデートで、一部PWAに対応したと書きましたが、そのアップデートでは、Payment Request APIが含まれています。いわばWeb全体をストアだとみなして、Apple Payの決済で手数料を徴収するわけですが、これはAppleのビジネスモデルとしては大きな転換になるので、リスクも大きくなるでしょう。

今はAppleのユニバーサルアプリがどのような形になるか、予測の域をでません。先にあげた二つの予想のどちらかになるかもしれませんし、ふたつをミックスしたものかもしれません。それでも、MicrosoftがWindowsでPWAをサポートすることを決めたり、iOSのアップデートを見ているとPWA軸にしてユニバーサルアプリのプラットフォームが構築される可能性は充分あると思います。

PWAのWebへの影響

推測に推測を重ねることになりますが、PWAがユニバーサルアプリとして普及したとき、おそらくWebへの影響が少なくないだろうと思います。
もともとWebの技術なのだからPWAが普及したとしてもWebへは何の影響もないと考えるむきもあるかもしれませんが、しかし、あるサービスを新たにWebとスマホで開発して展開しようとしたとき、PWAとWebは出来るだけ同じコードを使い回したいと思うはずで、そうでなければコストを削減できません。
PWAはSPA(Single Page Application)として実装されるでしょうから、結局WebサイトもSPAとして作製されることになるでしょう。つまり、PWAが普及すれば普及するほどWebのSPA化が進むことになります。
必然的にSPAを支える技術としてReactやVueなどのJavaScriptフレームワークの重要性が更に増し、サーバーサイドは、DBからデータをとってきてjsonにして返すことと、SSR(サーバーサイドレンダリング)を行う役割が重要になってくるでしょう。
さらに、そうなるとJSフレームワークの役割が重くなってフロントエンドでの分業化が進み、分業化に適したフレームワークが必要とされると思います。今のVueやReactは、分業化にはそれほど向いているとは思えないので、VueやReactがJavaScriptフレームワークの回答ではなく、将来的には分業化に適したJavaScriptフレームワークが登場するのではないかというのが、私の見立てです。
そこまで行くとフロントエンド界隈の幼年期は終わり、入れ替わり立ち替わり現れていた様々なツールやJSフレームワークは収斂して固定化されていくのではないかと思われます。  

終わりに

PWAは、ユニバーサルアプリを支える技術として注目を集める時代がもうすぐやってくるかもしれません。あるいは、AppleはPWAに投資せず、もっと違った方法でユニバーサルアプリを実現するかもしれません。実際にどう転ぶのかわかりませんが、わからないだけに独断と偏見で考えるのは面白いことだと思いました。ユニバーサルアプリがどんなものかは、これからそう遠くない未来にAppleが何らかの発表を行うのではないかと期待しています。そのときPWAの未来が決せられるでしょう。

アスタミューゼでは、エンジニア・デザイナーを募集中です。ご興味のある方は遠慮なく採用サイトからご応募ください。お待ちしています。

おためしpuppeteer

お久しぶりでございます。

本来のアップ予定であった、水曜日をおとし今この時間にやっと投稿させていただいた、

季節外れのインフルエンザ(A型)にやられてしまった、scalaでバックエンドを開発しているaxtstar(@axtstart)です。

まだ出勤するのは、はばかられる状態なので、リモートワーク中です。

実は何気に(前職も通して)初めてのリモートワークだったりして、新鮮というか、なんというか、

ただ、slackで仕事のやり取りを普段からしているためか、それほどの差は感じないですね。

社会の進化を感じます。

さて今回なのですが、だいぶ前の回で、phantomJS の話を書いたかと思うのですが、

その関連というか、headless chromeをあやつる、nodeJSで書かれたpuppeteerというののちょっとした紹介です。 github.com

背景

現在プロジェクトで使用している自動化ツールは、PhantomJSなのですが、

諸事情で他の自動化ツールを探している状態です。

こちらはそのあたりの、味見的な記事になります。

また、NodeJSのバージョンの高いものを利用するため、Ecmascriptのバージョンも新しく、

モダンな開発手法が可能ではないかという期待もあって、試してみました。

PhantomJSは独自実装のため、NodeJSができることができるとはならず、かつESの新しい機能はトランスパイルの必要がありました

Install

npm install puppeteer

でchroniumを含めてインストールしてくれます。

※↑Mac OS X

ただし、私のUbuntuでの動作には追加で以下の内容が必要でした。

sudo apt-get install gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget

curl -O https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb

sudo dpkg -i google-chrome-stable_current_amd64.deb

サンプル(公式そのまま)

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({path: 'example.png'});

  await browser.close();
})();

こちらは、公式ページからコピペしたスクリプトです。 これを、nodejsで動かせば、example.comを開いて、スクリーンショットを保存します。

ソースをご覧いただいてわかる通り、async,awaitというES7からのpromiseの糖衣構文を利用してかなり簡潔に記載できるようになっています。

※公式にも記載がある通り、上記のサンプルはNodeJSのv7.6.0以降が必要です。

実際の挙動

puppeteerのlauch時に、headlessをfalseにできたり、

キーボードの文字を打つスピードを調整できたりします。

  const browser = await puppeteer.launch({
    headless: false,
    slowMo: 50 // slow down by 50ms
  });

ページの生成とエラーハンドリング

    const page = await browser.newPage();

    page.on('error', err=> {
      console.log('error happen at the page: ', err);
    });

    page.on('pageerror', pageerr=> {
      console.log('pageerror occurred: ', pageerr);
    })

pageの表示

    await page.goto('http://exsample.com/', {
      timeout: 30000 //default 30s = 30000ms
    }); 

タイピング

    await page.type('input#textBox','typing...');

Wait

    await page.waitFor(5000);

文字列の内容の確認

    let h1 = await page.$('h1');
    let valueHandle1 = await h1.getProperty('innerHTML');
    
    assert.ok(await valueHandle1.jsonValue, 'TEST');

クリック

    await page.click('button.submit');

まとめ

○インストールが非常に簡単でドキュメントも豊富

○トランスパイルの必要なく、ES7の構文が利用できる

○NodeJSの機能が使えるため、Web画面の自動化を超えたような処理に応用が可能な手応えがある

○chroniumを使用するため、メモリ使用量は大きい

PhantomJSで結構苦労していた部分がすんなりできました。 また、書き方に統一感があり、かなり使いやすい印象でした。 自動テストはメモリ使用量は若干多めなのですが、今後自動テスト環境でも使って行きたいなと感じさせるものがありました。

今回はこの辺で。。

最後に

アスタミューゼでは現在、エンジニア・デザイナーを募集中です。 興味のある方はぜひ下記バナーからご応募ください。

Copyright © astamuse company, ltd. all rights reserved.