Go 言語のオーサリングツールの godzil を使ってみた
はじめに
Go 言語でプロジェクトをはじめるときに設定ファイルや Makefile
を既存レポジトリからコピーしていました。しかし、抜け漏れやいつまでも古い設定を引き継いでいくのもあまり良くないと思い、何かしらのオーサリングツールがないか探していました。
そこで
で godzil
を知ったので試してみました。
使ってみた感想と、現状作者の方のテンプレートしかないのですが、他の種類のテンプレート追加するにはどうすればよいかを調べてみました。
TL;DR
- Golang のオーサリングツールの Songum/godzil を使ってみた
- Songum/godzil で雛形を追加する方法を調べた (v0.2.3 での確認)
- Songum/godzil を
git clone
make devel-deps
で開発に必要なモジュールをインストールtestdata/assets/{雛形名}
配下に雛形を配置。テンプレートは Goのテンプレートが使えるmake assets
で新しい雛形追加したtestdata/assets
が入った状態のstatik/statik.go
を作成make build
でバイナリを作成- 作成したバイナリで
./godzil new -profile {雛形名} /path/to/repository
すると./repository
配下にtestdata/assets/{雛形名}
以下のテンプレートからファイルが生成される
- Songum/godzil を
使ってみた
インストール
macOS なので homebrew
でインストールします。
% brew install songmu/tap/godzil
モジュールの作成
モジュールを作成するディレクトリで new
します。
% godzil new github.com/noissefnoc/oreore
開発とかビルドとか
開発はお好きなように。ビルドはディフォルトの雛形に Makefile
が入っているので、それを使うことになります。
リリース
pull request ベース開発でマージコミット作成している開発フローが前提になっていますが
% godzil release
で semver
形式で新しいバージョン入力すると
- バージョンの更新
CHANGELOG.md
の更新- 新しいバージョンでタグ打って push
をしてくれます。
使った感想
雛形に関する個人の好みの問題ですが
.gitignore
にmake build
の生成物を入れておきたい- CLI 作るテンプレだとしたらフラグパーサのレイヤは
cli.go
みたいなので一段噛ませたい
あたりはパッと思いました。
error
系のモジュールは入ってるといいかとも思いましたが、バージョン追従のためにテンプレートを更新するのも、HEAD指定するのもどちらも微妙なので守備範囲にはしないほうがいい気がしました。
雛形の追加
v0.2.3 で確認しています。 今回は確認だけのためなので、ソース取ってきていじってます。
前準備
# ソースコードの取得 % git clone https://github.com/Songmu/godzil # 必要なモジュールをインストール % make devel-deps
雛形の作成と配置
ソースを読むと godzil new -profile {雛形名}
で testdata/assets/{雛形名}
配下の雛形を展開する仕様(ディフォルトはtestdata/assets/basic
) なので
となります。
雛形ファイルの更新
godzil
ではバイナリに静的ファイルを同梱するために rakyll/statik を使っているので statik/statik.go
に testdata/assets
配下のデータが書き込まれています。
雛形を追加したので、 statik/statik.go
を更新します。 Makefile
に更新のターゲットがあるので、それを利用します。
# statik/statik.go を更新 % make assets
ビルド
% make build
新しい雛形を使ったモジュールの作成
作成したバイナリ( ./godzil
) で
% ./godzil new -profile {雛形名} /path/to/repository
とすると ./repository
配下に testdata/assets/{雛形名}
以下のテンプレートからファイルが生成されます。
おわりに
雛形の整備をしてみて、しばらくは独自ビルドで追加して様子見てみようかなと思います。
"草APIサービス" Pixela v1.10.0 リリースに伴い、私家版クライアントライブラリのアップデートをしました
本日 "草APIサービス" Pixela v1.10.0 のリリースが行われました。
グラフ詳細ページに出ている統計情報(草の数、登録の最大値/最小値他)が取得できるようになりました(ref: Pixela API Document: get-graph-stats )。
上記リリースに伴い、私がメンテナンスしている以下ライブラリで対応を実施しました。
- noissefnoc/pixela-client-go: Go 製CLI (※ CLIはオフィシャルの a-know/pi がありますので、そちらの利用をお勧めします)
graph stat
サブコマンドを追加した v0.0.6 をリリース
- noissefnoc/gas-library-pixela: Google Apps Script ライブラリ
get-graph-stats
に対応したgetGraphStat
v2.0.0 (※ Google Apps Script のバージョンはメジャーバージョンが1づつ上がっていくので、これが最小です) をリリース- 「リソース」 > 「ライブラリ...」から Pixela のバージョンのプルダウンを2にしてください。
以上です。
Google Apps Script でクラス型のコードを書いたさいのスクリプトエディタでの補完への対処方法 (Bad Hack)
TL;DR
Bad Hack の類の話です。
- グローバルにインスタンス生成関数を定義し、関数にJSDocを記載して補完に使う
- グローバルに補完用の関数を定義し、関数にJSDocを記載して補完に使う
ことで、副作用が発生しますが、それなりにスクリプトエディタで補完がきくようにできます。
背景
Google Apps Script のスクリプトエディタの補完の使用上、グローバルに定義されている関数定義に対するJSDocしか補完が効かない様子。JavaScriptのレイヤーでメソッドを定義すると、 Foge.prototype.bar = function() { ... }
のようなコードになるので補完がきかない。
ライブラリ利用者はスクリプトエディタを使う人も多いことが想定されるので、スクリプトエディタ上で補完がきくのが望ましい。
対応策
対応策としては以下
- グローバルにインスタンス生成関数を定義し、関数に対するJSDocを記載して補完に使う
- グローバルに補完用の関数を定義し、関数に対するJSDocを記載して補完に使う
各パートでやることをもう少し具体化すると
- 実体隠蔽Hack:
- インスタンス生成関数からのみインスタンスを生成したいので、
new
を呼べないようにクラス定義を隠す - Google Apps Script の機能で名前がアンダースコアで終わるものは外部参照できなくなるので、それを使う
- インスタンス生成関数からのみインスタンスを生成したいので、
- インスタンス補完Hack
- 1で、直接
new
できなくなったのでインスタンス生成関数をグローバルに定義。JSDocで型を指定 - コード上は隠蔽した実体(アンダースコアで終わるもの)を返すが JSDoc 上の
@return
ではパッケージ名を返す
- 1で、直接
- メソッド補完Hack:
- グローバルに補完用の関数を定義し、補完用の定義をJSDocで記載する
で、副作用が発生するのは「3. メソッド補完」で、他は正しくはないがコメントなので諦められなくは、ない...かな?
Google Apps Script のライブラリの外部参照
Google Apps Script でライブラリを使う場合、下図のような参照になります。
この後クラス型のコードを書くことを想定しているので、 Pixela.Pixela
のような名前になっています。
この仕様から察するにGoogle Apps Script の発想としては
- メンバ変数やメソッドはグローバルに書く
- プライベートなものは名前にアンダースコアをつけることで隠す
という方法で Pixela.create
などとするのでしょう。
しかし、非JavaScript民としてはTypeScriptで書きたいという気分もあり、完全に Google Apps Script のローカルルールを過学習するのは辛い。よって何か方法がないか考えます。
そのまま書いた場合の状態
Hackを試みず、クラス型を素直に書くと下図の状態になります。
コンストラクタ含め、各メソッドが補完できません。
「ドキュメント見ろ」というのもその通りですが、ライブラリを作った自分ですら関数名やオプション覚えてないこともままあるのでこれはちょっと辛い。
Bad Hack 適応時
対してHackを試みると下図の状態になります。
「対応策」の箇所で書いたHackを適応すると概ね期待通りの動作となります。
副作用として実体のない補完用の関数(例: Pixela.createUser
)が補完候補に登場する上に、実行すると期待と違う結果になるという事態が発生します。
順に細かく見ていきましょう。
1. 実体隠蔽Hack
これは単純に対象とするクラスの名前の最後にアンダースコア(今回の例だと Pixela_
)を付けるだけです。
※これはHackと書きましたが、Google Apps Script で提供されている公式の機能です
2. インスタンス補完Hack
ここからHackです。コード上はアンダースコア付きの戻り値ですが、 JSDoc上はパッケージ名の型を返す のがポイントです。
以下がnoissefnoc/gas-library-pixelaでの実装です。
/** * create pixe.la API client<br /> * ... * @param {string} username pixe.la username * @param {string} token pixe.la API token * @return {Pixela} pixe.la API client instance */ function create(username: string, token: string): Pixela_ { return new Pixela_(username, token); }
これで
- コードを正とする Google Apps Script
- JSDocを正とするスクリプトエディタの補完
の両方を誤魔化すことができます。Linterに「間違っている」と指摘されますが、そこはスルーしましょう。
3. メソッド補完Hack
これでライブラリ利用者側からは
な状態になりました。
ということで、 メソッドの関数と同じシグネチャの補完のためだけの関数をJSDoc付きでグローバルに定義します 。
利用者側から見たときには
Pixela.Pixela_.createUser
:処理実体。Pixela.createUser
:補完の時に参照する関数。ライブラリのグローバルに定義し、実体的な処理はない
の二つの関数があることになります。
利用者が行儀よく
var pi = Pixela.create(u, t); var resp = pi.createUser("yes", "yes"); // Pixela.Pixela_.createUser を呼んでいる
のような呼び方をしてくれる場合は問題ないのですが
var resp = Pixela.createUser("yes", "yes"); // Pixela.createUser を呼んでいる
とした場合は期待していない結果が返ってきます(補完候補に出てくるのに!)。この点は現状如何ともしがたそうで、解決は難しそうです。
まとめ
- 上記のHackで Google Apps Script でクラス型のコードを書いたさいにもスクリプトエディタで補完をすることができるようになった
- しかし、微妙な副作用が発生している
dep で管理していた Go言語のレポジトリを go modules に移行しました
Go言語の依存関係管理に dep
を使っていたのですが、Go言語標準になる go modules
に重い腰をあげて移行しました。
dep
を使っていると以下で対応完了し、マイグレーションは簡単でした。
Go1.13になるまではモードが混在するので、やや使いにくいケースもあると思いますが、先行して使ってみようと思います。
以下詳細です。
1. 環境変数設定
現状、環境変数 GO11MODULE
で GOPATHモードとモジュールモードを切り替える仕様になっているので、モジュールモードになるように設定します。
$ export GO11MODULE=on
2. 初期化
レポジトリのルートディレクトリで初期化コマンドを実行します。これで go.mod
ファイルが作成されます。
$ go mod init
3. 依存関係抽出
go mod tidy
で依存関係を抽出します。
$ go mod tidy
4. dep 関連ファイル削除
dep
が使っていた設定ファイルやインストールディレクトリが不要になるので削除。
$ rm -r Gopkg.toml Gopkg.lock vendor/
5. ビルド・CI関連ファイル修正
ビルドに Makefile
、CI に TravisCI を使っていたので .travis.yml
をそれぞれ修正。
Makefile
これまでは
dep
をインストールdep ensure
で依存をインストール
だったのが
go mod download
だけでよくなりました。
.travis.yml
TravisCI の標準の GO11MODULE
の値は auto
でこのモードの場合は GOPATH
配下のコードはモジュールモードで動作しないので、 on
にセット。
env: GO11MODULE=on
before_install
ないしは install
セクションで依存モジュールをインストールするが、Makefile
側で対応したので、この点は対応する必要なし。
"草APIサービス" Pixela のステッカーいただきました
いただきました! id:a-know さんありがとうございます!
がありまして
で応募しました。
先日、v1.9.0 のリリースコメントにも載りました。
あまり大した貢献ではないのですが、これからも頑張ります。
"草APIサービス" Pixela v1.9.0 リリースに伴い、私家版クライアントライブラリのアップデートをしました
本日 "草APIサービス" Pixela v1.9.0 のリリースが行われました。
SVG形式でグラフを取得するさいに折れ線グラフでの取得が可能になる機能追加がありました。
(ref: Pixela API Document: get-svg )
上記リリースに伴い、私がメンテナンスしている以下ライブラリで対応を実施しました。
- noissefnoc/pixela-client-go: Go 製CLI (※ CLIはオフィシャルの a-know/pi がありますので、そちらの利用をお勧めします)
- パラメータ取得値の部分を修正した v0.0.5 をリリース
- noissefnoc/gas-library-pixela: Google Apps Script ライブラリ
- (元々雑な作りなので)コードへの影響がありませんでした
- レポジトリ上はドキュメントをアップデートし、バージョンはそのままとしてあります
以上です。
"草APIサービス" Pixela の Google Apps Script ライブラリを作成しました
TL;DR
"草*1APIサービス" Pixela の Google Apps Script ライブラリを作成しました。
以下 Google Apps Script プロジェクトIDにて公開しています
1lYZA6IF2D62qUb3prkWH4UX5zLEaqy1VrbU2jOwHM3hdjkl7gG3nh33Y
Libraries | Apps Script | Google Developers (英語) を参考に追加・利用いただければと思います。
スクリプトエディタでの入力であれば補完もききます。フォトライフへのアップロードがうまくいってないので、アニメーションgifは以下Tweetに張ってあるものをご参照ください。
https://t.co/VnTMaI5mDV の GASライブラリ、ライブラリ使う側はこんな感じで使えます。(ちっさくてすいません) pic.twitter.com/w8IFCQ2wAL
— K.Saito (@noissefnoc) 2019年3月26日
注意点として
Google Apps Script のライブラリの呼び出し回数制限が現状不明なため、Google から呼び出し制限がかかる可能性がります
- 公開されている制限は Quotas for Google Services | Apps Script | Google Developers だが、ここに明記なし
- 気になる方は GitHub の Release にコピペできる状態で Google Apps Script を置いています。ご利用になるプロジェクトにコピー&ペーストの上ご利用ください*2
用途例
私の使い方だと現状以下の2用途です。
G Suite を利用している組織だと Google Sheets が人も入力可能なデータ管理システムになっていると思うので、その辺で何か用途があると思います。
Google Sheets に連携/人手で入力している情報を日次で pixe.la に連携
元々ヘルスケアや読書/書籍管理*3に Google Sheets を使っていました。
そこで、これを使ってGoogle Apps Script の Trigger でまだ未送信の入力値を送る Google Apps Script を作成して pixe.la に記録しています。
この手の管理だと数値だけでなく、コメントも記録しておきたい(例:走った距離を記録するときに走ってない日の理由を入れたいなど)ので optionalData
に入れておきたいのですが、自分でJSONは書きたくないので併せて実装してあります。
Google Sheets / Google Forms でユーザ/グラフ作成のための GUI を提供
現在、pixe.la にはユーザに関する確認APIがないので管理のために残しておきたいというのがあって利用しています。
グラフに関しては一覧は分かるのですが、新しくグラフを作るときにオプションを思い出せません(細かく設定できる嬉しさの反面ですね)。ドキュメントページを逐次見直すのも面倒なので、設定値をどこかに持っていて欲しいと思ってグラフ作成のための Google Sheets を作っています。Google Sheets の「シートの保護」「入力規制」「カスタムメニュー」などを使って作った例は以下になります。
細かい点としては作成が成功した場合は別シートに設定保存するようにしています。
技術的な話
- 開発
- 言語:TypeScript (+ Node.js)
- ユーティリティー:google/clasp でG Suite からのダウンロード/TypeScript変換/アップロード/バージョン付与
- エディタ:VS Code
- テスト
- テスト用のGoogle Apps Script の Standalone Script のプロジェクトを作ってそこから作成ライブラリを呼び出し
- ライブラリ経由で pixe.la の API を呼び出してのテスト
- その他
- Google Apps Script のスクリプトエディタ上で補完出すためにJSDocをこまめに書いた
今回初 TypeScript と clasp
とGoogle Apps Scriptのライブラリ化だったので色々調べながらで拙いことが多かったように思います。
特に Google Apps Script の以下2点は困ったので暫定対応方法と併せて別途エントリを書きたいと思っています。
- ライブラリとクラス形式にしたときの外部エクスポートの方法
- ライブラリとクラス形式にしたときのスクリプトエディタでの補完