YAMAGUCHI::weblog

海水パンツとゴーグルで、巨万の富を築きました。カリブの怪物、フリーアルバイター瞳です。

Goのハンズオン環境としてGlitchを使う

はじめに

こんにちは、Stackdriver担当者です。この記事はGo Advent Calendar 2019の24日目の記事です。昨日は@fist0さんでした。

私は職業柄「コードラボ」「ハンズオン」「ワークショップ」と呼ばれるような、参加者に実際に手を動かして課題を解いてもらうことで特定の技術や製品を理解してもらうイベントを開催したり講師をしたりすることがあります。その場合にこちらがコントロールしづらいものの一つが実行環境です。諸々のバージョンを固定したり、コンテナを用意したり、などいろいろな方法がありますが、今回はglitchを使ってGoでのハンズオン環境を用意する方法とその使い方を紹介します。

TL;DR

Glitchを使ってGo用のハンズオン環境を容易に提供できる。サンプルプロジェクトはこれ。

glitch.com

Glitchとは

glitch.com

ウェブアプリケーションを公開する無料の実行環境で、デフォルトではNode.jsの実行環境が用意されています。日本語でGlitchの丁寧な解説をしている記事もありますので詳細はそちらに譲ります。

で、今回はこのGlitchをGoの実行環境として利用する方法について紹介して、さらにハンズオンなどで便利に使う方法についても解説します。

準備するもの

主催者・チューター

  1. Glitchアカウント
  2. Goのハンズオン用にセットアップされたGlitchプロジェクト
  3. (optional) 2.のコードをミラーするGitHubレポジトリ

参加者

  1. (optional) Glitchアカウント

手順

1. Glitchアカウント

フェデレーテッドログインができるので好きなIdPを選んでアカウントを作ってください。すぐにできます。参加者はアカウントが無くても一時アカウントが利用できるので大丈夫です。

2. GlitchプロジェクトをGo用にセットアップする

メインはここです。GlitchはデフォルトではNode.jsの実行環境なのですが、実はGoの実行環境も実は入っています。しかし、設定ファイルを書くことで、Goのダウンロードとインストールをして特定のバージョンのGoを使わせたり、コード変更時のGoプロジェクトの自動ビルドなどを設定して、さらにハンズオン環境として良い物にできます。

glitch.json

Goを含むNode.js以外のランタイムは glitch.json と呼ばれる設定ファイルを用意する必要があります。JSONで設定できるフィールドはそれぞれ次のとおりです。

{
  "install": string,
  "start": string,
  "watch": {
    ...
  }
}

それぞれ次のような内容です。

  • install: プロジェクトのコンテナ起動時に実行されるコマンド
  • start: watchで定期的に実行されるコマンド
  • watch: watch.json に関する設定(watch.json を別途作成する場合は書かなくて良い)

watch.json

watch.json というファイルを設定すると、編集後に自動で実行したいコマンド等を記述できます。Linux等のwatchコマンドに似ていますね。ここではどのファイルを変更した場合にどういったトリガーを起動するかを設定します。対象ファイル名は正規表現で指定できます。

{
  "install": {
    "include": [
      "^glitch\\.json$",
      "^init\\.sh$",
      "^\\.env$"
    ]
  },
  "restart": {
    "exclude": [
      "^go/",
      "^pkg/"
    ],
    "include": [
      "\\.go$"
    ]
  },
  "throttle": 5000
}

設定項目はそれぞれ次のとおりです。

  • install: include で記載されているファイルが変更されるとコンテナ自体の再インストールが行われる
  • restart: exclude で記載されているファイルが変更された場合は何もしない、include で記載されているファイルが変更された場合はコンテナを再起動する
  • throttle: watchの確認自体の間隔を設定する(ミリ秒)

Go用プロジェクトセットアップのコツ

これは通常のコンテナイメージ構築の場合と勘所は同じです。つまり次のようにします。

  1. Goのバージョンを固定する
  2. go.mod でパッケージのバージョンを固定する

1のGoのバージョンの固定は、glitch.jsoninstall に適当な初期化用のシェルスクリプトを指定して、その中でLinux用のtarballとsha256のチェックサムの確認をすることで固定できます。上のサンプルプロジェクトではこのような形で設定しています。

GO_ARCHIVE=go1.13.5.linux-amd64.tar.gz

if [ ! -d /tmp/go ]; then
  cd /tmp
  if [ ! -f /tmp/${GO_ARCHIVE} ]; then
    wget -q https://dl.google.com/go/${GO_ARCHIVE}
  fi
  sha256sum -c ~/${GO_ARCHIVE}.SHA256SUMS || (echo "failed to verify go tarball" && rm /tmp/{$GO_ARCHIVE} && exit 1)
  tar -xzf ${GO_ARCHIVE}
  rm /tmp/${GO_ARCHIVE}
fi

mkdir -p /tmp/pkg
if [ ! -L pkg ]; then
  ln -s /tmp/pkg $GOPATH/pkg
fi

そしてこのSHA256SUMSのファイルは自分で手元で作成してもいいですし、Go公式サイトの配布先に書いてあるSHA256 Checksumを自分でコピーして作成しても良いでしょう。

512103d7ad296467814a6e3f635631bd35574cab3369a97a323c9a585ccaa569  go1.13.5.linux-amd64.tar.gz

2.の go.mod は固定です。ハンズオン参加者に編集させていはいけませんし、go mod tidy を実行させてはいけません。アンタッチャブルです。編集させると即座にプロジェクトが予想しない形に壊れるので、もし触ってしまった人がいたら元のgo.modファイルとgo.sumファイルを再度コピーしてもらうようにしましょう。またキャッシュも消す必要があります。

そしてプログラムのビルドと実行も glitch.jsonstart で指定したシェルスクリプト内で go fmtgo run 等を実行するようにし、ハンズオン参加者が go コマンドを自分で打つ必要がないように設定すると良いでしょう。

(optional) 3. 2.のコードをミラーするGitHubレポジトリ

万が一ブラウザではなくローカルで実行したい、もしくは何らかの事情でGlitchを使えない、という人がいた場合に備えて、GlitchのプロジェクトをGitHubミラーリングしておくと安心感が高まります。

注意点としては、事前にExport先のレポジトリを作成し、かつ1つでもコミットがされた状態にしておく必要があります。その上で "Export to GitHub" ボタンを実行してExport先のレポジトリを指定すると、giltchブランチに変更がpushされます。

f:id:ymotongpoo:20191219112030p:plain

実際にミラーしたのがこちらです。

github.com

ハンズオンの進め方

ハンズオンの進め方はまずハンズオン開始時に上の 2. で作成したプロジェクトのURLを参加者に共有します。参加者に "View Source" を押してもらい、コードエディターが読み込み専用モードで開いてもらいます。ここで画面の右上の "Remix to Edit" のボタンを押してもらうと "Remix" が行われます。

f:id:ymotongpoo:20191219141140p:plain

参加者がRemixをすると元のコードをforkしたプロジェクトが任意のIDとともに作成され、参加者は自由に変更を加えられる環境を手に入れられます。そして課題を書き進めるわけです。わからないことがあったら、その部分のコードをハイライトします。すると手を上げたアイコンが出現するのでそれを押すと、質問が出来るようになります。

f:id:ymotongpoo:20191219140615p:plain

remixしたプロジェクトで質問がでると、remix元のプロジェクトオーナー(つまりチューター)のトップ画面に「質問が来ていますよ」というメッセージが出てきます。("Help Others, Get Thanks→" の部分。ここでは "Test question: bra bra bra" という質問メッセージが来ています。)

f:id:ymotongpoo:20191219140344p:plain

もちろん普通に手を上げてもらっても良いのですが、こういう形で質問をしてもらうことで、チューターがスクリーンなどにこのトップ画面を映していると質問内容がわかりつつ、これからその部分に取り組む人も事前に注意が出来るというわけです。

実際に試した

この方法は今年の11月5日に行われたVelocity Berlin 2019のワークショップで実際に試してみました。チューターや参加者のパソコンのOSがWindowsLinuxmacOSChrome OSなど様々に分かれていたわけですが、OS特有のエラーなどにはまることがまったくありませんでした。

参加者が書いた結果のコードもプロジェクトの形で残るので、何か面白いことを取り組んだ参加者がいれば、そのプロジェクトURLを共有してもらうだけで手元でコードを見て、実行するところまでできるのも便利でした。

またハンズオンの内容もHTTPサーバーを立ててリクエストを受け取ったり投げたりするようなプログラムを書いたわけですが、ポート番号3000番で指定すればパブリックにサーバーを公開できるので、参加者同士で通信しあうような課題もできそうだったのが魅力的でした。

f:id:ymotongpoo:20191219142722p:plain
実際にGoでHTTPサーバーを立ててHello worldをしている様子

コンソールにアクセスしてコマンドを実行できるため、CLIを作るような課題もある程度可能です。

f:id:ymotongpoo:20191219142925p:plain

おわりに

コードラボやハンズオンは実際に手を動かすため短い時間で効率よく学習することが可能です。ぜひこの方法をいろいろな場所で試してもらって、Goのハンズオンとしてもっと便利な使い方を共有してもらえたらなと思います。

明日は最終日。担当は @tenntenn さんです。