ようへいの日々精進XP

よかろうもん

2020 年 01 月 07 日 (火)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 詳細はこちら.

ジョギング

  • 久しぶりに山王公園周りを 30min (とてもゆっくりしたペース
  • 懸垂 x 8
  • ((腹筋 x 50 x 2) + 腕立て x 50) x 2
  • 恐る恐る走ってみたけど, やっぱり, 右足大腿の張りが強かった

よく考えたら, 今年の走り初めだった.

ギョーム

  • 年始の会議があったり
  • 証明書が適用されているロードバランサの洗い出しをして出来る限り ACM に移行したり
  • RDS の縮退の準備をしたり
  • Cloud Function をガチャガチャ ( Terraform で構築したり, GCS に保存したり...

そして, よくよく考えたら...

引き続き, 精進します.

夕飯

昨日の残りのとんかつ. 温め直したと思えないくらい味がしっかりついていて, 且つ, 豚の油が甘くて美味しかった!

【俺の一行チップス】 AWS の全リージョン名が今すぐ欲しい

やりたいこと

AWS のリージョン名が今すぐ欲しい.

諸注意

環境は以下の通り. (2020/01/07 時点で brew upgrade awscli してインストールされるバージョン.)

$ aws --version
aws-cli/1.16.310 Python/3.7.6 Darwin/18.7.0 botocore/1.13.46

やったこと

$ aws ec2 describe-regions --query=Regions[].RegionName

以下のように出力される.

[
    "eu-north-1",
    "ap-south-1",
    "eu-west-3",
    "eu-west-2",
    "eu-west-1",
    "ap-northeast-2",
    "ap-northeast-1",
    "sa-east-1",
    "ca-central-1",
    "ap-southeast-1",
    "ap-southeast-2",
    "eu-central-1",
    "us-east-1",
    "us-east-2",
    "us-west-1",
    "us-west-2"
]

ちなみに, --all-regions を付けるとアカウント的に無効になっているリージョン名も取得可能.

$ aws ec2 describe-regions --all-regions --query=Regions[].RegionName

以下のように出力される.

[
    "eu-north-1",
    "ap-south-1",
    "eu-west-3",
    "eu-west-2",
    "eu-west-1",
    "ap-northeast-2",
    "me-south-1",
    "ap-northeast-1",
    "sa-east-1",
    "ca-central-1",
    "ap-east-1",
    "ap-southeast-1",
    "ap-southeast-2",
    "eu-central-1",
    "us-east-1",
    "us-east-2",
    "us-west-1",
    "us-west-2"
]

me-south-1 なんていうリージョン. これは, 中東 (バーレーン) リージョンとのこと.

参考文献

リージョン、アベイラビリティーゾーン、および ローカルゾーン

(完)

2020 年 01 月 06 日 (月)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 詳細はこちら.

ジョギング

  • 引き続き, おやすみ
  • ((腹筋 x 50 x 2) + 腕立て x 50) x 2
  • 少しでも脚力を維持する為, ウォーキングで通勤してみたけど, 右足大腿の張りが強かった

ギョーム

  • お休みの間の CloudWatch メトリクスをザーッと眺めたり...
  • PostgreSQL のシーケンスが歯抜けになる件について調査したり...
  • Lambda のランタイムのアップデートをしたり...
  • GCP の Cloud Functions のチュートリアルとかしてた

年明けはあまり無理せずにゆったりとスタートを切らせて頂いた感.

ちょっと呑み

今日入社の方を囲んで有志メンバーで会社近くで一杯.

夕飯

呑みを途中退場させて頂いて帰宅. 夕飯は奥さん特製のトンカツ. カラッと揚がっていて美味しゅうございました.

冬休みの自由研究 (5) 〜 CircleCI プロジェクトを操作するコマンドラインツールを作ってみた 〜

tl;dr

CircleCI プロジェクトの環境変数を毎回 Web UI でいじるのが辛くなってきていましたが, 環境変数自体を API で操作出来ることを知ったのでコマンドラインツールを Go で作ってみました.

作ったもの

github.com

出来ることは基本的にはプロジェクト毎の環境変数を管理 (一覧取得, 追加, 削除) くらいです. 詳細は, リポジトリの README をご一読下さい.

以上

メモでした.

2020 年 01 月 05 日 (日)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 詳細はこちら.

ジョギング

  • 引き続き, おやすみ
  • ((腹筋 x 50 x 2) + 腕立て x 50) x 2 + 懸垂 x 8
  • いつになったら走れるのかな...

ギョーム

  • わー, 明日から仕事だーーーーーー

CircleCI API クライアント

Fitbit API 云々を検証するにあたり, プロジェクトの環境変数を Web UI でいじるのが辛くなったので API クライアントツールを作ってみた.

github.com

散歩

朝からとてもポカポカ陽気で奥さんと山王公園まで散歩. 汗ばむ感じで走りたい気持ちがマックス. グッとこらえて山王公園を後にした.

夕飯

久しぶりの鮭のムニエル. 美味しかった〜. お味噌汁の代わりにレトルトカレー. 男子高校生みたいな食事でお腹いっぱい.

2020 年 01 月 04 日 (土)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 詳細はこちら.

ジョギング

  • 引き続き, おやすみ
  • ((腹筋 x 50 x 2) + 腕立て x 50) x 2
  • いつになったら走れるのかな...

ギョーム

  • わー, 長かった休みが明日までだ...

ルミエール

殺伐とした激安ストアでお馴染みのルミエールに久しぶりに買い物に行った. 一週間分くらいの食材をざっくりと買い込んだ.

夕飯

奥さんのローストビーフリベンジ. 前回は焼き肉になってしまったので, 今回は慎重に火を入れたとのことで美味しかった. ちなみに, 調理中に包丁で指を切った奥さんは出血を見て「意識が遠のいて行く...」と言って調理を放棄したのが面白かった.

冬休みの自由研究 (4) 〜 CircleCI の Project Environment Variables を REST API で操作する 〜

tl;dr

CircleCI のプロジェクトで定義出来る環境変数 (以後, Project Environment Variables) を REST API で操作出来ないかなと思って調べていたら, シュッと出来たのでメモしておきます.

やりたいこと

  • ジョブ毎に異なる値をを動的にプロジェクトの環境変数に登録したい

CircleCI のプロジェクトで定義出来る環境変数 (以後, Project Environment Variables) を REST API で操作できれば, ジョブの中から環境変数を更新出来るんじゃないかと思った次第.

こんな感じで

なんのことない

ちゃんとドキュメントを読めば出来る.

API Reference

circleci.com

Personal API Token

API で操作するにあたり必要となります. ダッシュボードから取得出来ます.

f:id:inokara:20200104172921p:plain

実際に操作

キー foo, 値 bar を登録する場合.

curl -X POST --header "Content-Type: application/json" -d '{"name":"foo", "value":"bar"}' \
  "https://circleci.com/api/v1.1/project/[github|bitbacket]/[Username]/[Project Name]/envvar?circle-token=[Personal API Token]"

レスポンスは, 以下の通り.

{
  "name" : "foo",
  "value" : "xxxxr"
}

ダッシュボードでも確認することが出来る.

f:id:inokara:20200104171959p:plain

以下のように実行すると, [name] で指定したキーの環境変数を取得出来る.

curl -X GET \
  "https://circleci.com/api/v1.1/project/[github|bitbacket]/[Username]/[Project Name]/envvar/[name]?circle-token=[Personal API Token]"

レスポンスは以下の通り.

{
  "name" : "foo",
  "value" : "xxxxr"
}

以下のように実行すると, [name] で指定したキーの環境変数を削除出来る.

curl -X DELETE \
  "https://circleci.com/api/v1.1/project/[github|bitbacket]/[Username]/[Project Name]/envvar/[name]?circle-token=[Personal API Token]"

レスポンスは以下の通り.

{
  "message" : "ok"
}

以上

メモでした. これで悩み事が解決するかもしれない!

2020 年 01 月 03 日 (金)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 詳細はこちら.

ジョギング

  • おやすみ
  • ((腹筋 x 50 x 2) + 腕立て x 50) x 2
  • 右足大腿部については, 少しずつ張りは治まってきているけど, まだ, 特有の突っ張りがある

ギョーム

  • まだお休み
  • 冬休みの自由研究をブログに書いてアップ
  • 去年の今頃とやっていることがあまり変わってなくて笑えた

ランチ

  • 奥さんと博多散歩のついでに博多駅で回転寿司を少し
  • 帰りに冶一郎のプリンを購入

jiichiro.com

冶一郎のプリンは夕食後に食べたけど, 甘すぎずなかなか美味しかった.

夕飯

お鍋. 冬休み期間中はほぼほぼお鍋, 毎日ほぼ同じ味だったけど飽きずに食べれている.

MacBook Air のバッテリ

個人で利用している MacBook Air 11 インチ Mid 2012 モデルのバッテリが前々からへたってきていて, 「バッテリ交換が必要」的なメッセージが出ているけど, CMOS のクリアで「バッテリ交換が必要」のメッセージが消える. しばらくはこの状態で使い続けようかなと思う.

ちなみに, SMC のクリアは以下のドキュメントに記載されている.

support.apple.com

内蔵キーボードの左側の「shift + control + option」キーを押しながら、電源ボタンを押します。これらのキーと電源ボタンを 10 秒間押し続けてください。

とのこと.

冬休みの自由研究 (3) 〜 俺は一日どのくらい走って (歩いて) いるのかを Fitbit Web API と pixela を使って可視化する検証 CircleCI を添えて 〜

追記

CircleCI で定期的に... (01/04)

CircleCI の Schedule Job を利用して定期的に処理させようと思ったいたんだけど, Access Token の期限切れ対策で, 一日に一回よりも短い周期でスクリプトを動かす必要がありそう.

circleci.com

となると, CircleCI の Schedule Job では, crontab によく書く以下のような書き方をする必要があるんだけど...

# 5 分おきに my-script.rb を実行する
*/5 * * * * ruby my-script.rb

上記のドキュメントに,

Note: Cron step syntax (for example, /1, /20) is not supported. Range elements within comma-separated lists of elements are also not supported.

と書かれていて, 本案件では, 残念ながら CircleCI は利用出来なさそう.

Access Token の期限切れ対策 (01/03)

Access Token が expire する可能性があるので, Refresh Token を利用して Access Token を再取得しないといけないかもしれない.... 「かもしれない」じゃなくて, Refresh Token を利用して, Access Token の再取得が必須でした.

Fitbit Charge2 はスマートウォッチではなくトラッカー (01/03)

Fitbit Charge2 はスマートウォッチではなく, トラッカーという位置付けのようです.

f:id:inokara:20200103195836p:plain

tl;dr

箱根駅伝で母校を応援しながら, 自分は故障で走れない悔しさをどこかにぶつけたくて Fitbit Web API を pixela を使って可視化 (草を生やす) してみたいと思います.

www.hakone-ekiden.jp

モチベーション

自分は, 常日頃から Fitbit Charge2 を単純に腕時計, 走る時にストップウォッチと参考程度に心拍数を確認する目的で利用しています.

既に Fitbit Charge3 なる製品もリリースされているようですが, 今のところ Charge2 で間に合っているので買い換える予定はありません. 歩数や距離はイマイチ信頼性は低い印象ですが, バンドを変えられたり出来るので長く使えるスマートウォッチトラッカーなんじゃないかと思っています.

この Fitbit Charge2 (のみならず, 各種 Fitbit 製品) で収集した各種活動量等は REST API を介して取得することが出来ます. せっかくなので, この活動量 (この記事では走行 or 歩行距離のみを扱います) を年間を通して可視化してみたいと思います.

Pixela とは

過去に Fitbit Web API を利用して心拍数を Mackerel を使って可視化する記事を書きました.

inokara.hateblo.jp

似たようなことを, 今度は pixela という草を生やすサービス (ずいぶん乱暴な説明ですいません) を使って可視化してみたいと思います. 草を生やすというのは, Github のプロフィールページに掲載されているグラフです.

f:id:inokara:20200103123055p:plain

pixela は REST API を利用して, このグラフを生成するようなサービスです. 以下のように REST API で全ての操作が可能です.

# ユーザー登録
curl -X POST https://pixe.la/v1/users -d '{"token":"my-token-please-self-generate", "username":"username", "agreeTermsOfService":"yes", "notMinor":"yes"}'

# グラフ作成
curl -X POST https://pixe.la/v1/users/username/graphs -H 'X-USER-TOKEN:my-token-please-self-generate' -d '{"id":"my-graph","name":"my-graph","unit":"km","type":"int","color":"shibafu"}'

# グラフの設定 Timezone を Asia/Tokyo に設定
curl -X PUT https://pixe.la/v1/users/username/graphs/my-graph -H 'X-USER-TOKEN:my-token-please-self-generate' -d '{"timezone":"Asia/Tokyo"}'

# グラフの設定 selfSufficient を increment に設定
curl -X PUT https://pixe.la/v1/users/username/graphs/my-graph -H 'X-USER-TOKEN:my-token-please-self-generate' -d '{"selfSufficient":"increment"}'

# データの登録
curl -X POST https://pixe.la/v1/users/username/graphs/my-graph -H 'X-USER-TOKEN:my-token-please-self-generate' -d '{"date":"20200102","quantity":"5"}'

# データの削除
curl -X DELETE https://pixe.la/v1/users/username/graphs/my-graph/20200102 -H 'X-USER-TOKEN:my-token-please-self-generate'

# 登録データの取得
curl -X GET https://pixe.la/v1/users/username/graphs/my-graph/stats -H 'X-USER-TOKEN:my-token-please-self-generate  

ドキュメントが充実しているので, シュッと使い始めることが出来ます.

docs.pixe.la

Fitbit の Web API

dev.fitbit.com

OAuth で認証する部分がややこしいですが, アクセストークンを取得してしまえば, curl なり, 各種言語の HTTP ライブラリを利用して活動量を JSON で取得出来るようになります.

今回は, 以下の記事を参考にさせて頂いて, OAuth 認証を設定し, Ruby スクリプトも参考にさせていただきました. 有難うございます.

qiita.com

作ったもの

リポジトリ

実装したスクリプトは以下のリポジトリにアップしています.

github.com

活動量の取得

Fitbit Web API から, 活動量を取得する部分は以下の通りです.

class FitBitActivity
  def initialize(date)
    @base_url = 'https://api.fitbit.com/1/user/-'
    @request_header = { 'Authorization' => "Bearer #{ENV['FITBIT_ACCESS_TOKEN']}" }
    @date = date
  end

  def method_missing(resource)
    send("fetch_resource", resource, @date)
  end

  private

  def fetch_error(e)
    puts 'Error: ' + e['errors'][0]['errorType']
    exit 1
  end

  def fetch_resource(resource, date)
    activity_url = "#{@base_url}/activities/#{resource}/date/#{date}/1d.json"
    res = fetch(activity_url)
    res["activities-#{resource}"][0]['value'] if res.has_key?("activities-#{resource}")
    fetch_error(res) if res.has_key?('success')
  end
  
  def fetch(url)
    uri = URI.parse(url)
    https = Net::HTTP.new(uri.host, uri.port)
    https.use_ssl = true
    req = Net::HTTP::Get.new(uri.request_uri, @request_header)
    begin
      res = https.request(req)
      JSON.parse(res.read_body)
    rescue => ex
      puts 'Error: ' + ex
      exit 1
    end
  end
end

dev.fitbit.com

Activity から以下のような歩数, 距離数, カロリー毎に値を取得することを想定しています.

activities/calories
activities/steps
activities/distance
activities/floors
activities/elevation

例えば, 前日の消費カロリー数を取得したい場合には, 以下のように書きます.

d = Date.today - 1
puts FitBitActivity.new(d.strftime("%Y-%m-%d")).calories

実行すると, 以下のように出力されます.

$ ruby my-activity.rb
1608

単位はキロカロリーとなります.

同様に歩数を取得したい場合には, 以下のように書きます.

d = Date.today - 1
puts FitBitActivity.new(d.strftime("%Y-%m-%d")).steps

実行すると, 以下のように出力されます.

$ ruby my-activity.rb
4230

単位は歩数となりますな. 冬休みと故障中ということで歩数が全然伸びていないのが切ないですね...

草を生やしてみると...

サンプルのスクリプトを使って実際に草を生やしてみたのが以下の通りです.

https://pixe.la/v1/users/inokappa/graphs/my-test-graph1

パラメータに mode=short を付けると以下のようになります.

https://pixe.la/v1/users/inokappa/graphs/my-test-graph1?mode=short

おおー, いい感じです.

そして, CircleCI

毎日一回, このスクリプトを叩かせたい. となると思いつくのは Lambda + CloudWatch Events の組み合わせなんですが, とりあえず CircleCI で転がしてみようと思います.

version: 2.1

executors:
  default:
    docker:
      - image: circleci/ruby:2.6.5

jobs:
  check:
    executor: 
      name: default
    steps:
      - checkout
      - run:
          name: Check Activity
          command: |
            ruby my-activity.rb

workflows:
  check:
    jobs:
      - check:
          filters:
            branches:
              only:
                - master
  scheduled-check:
    triggers:
      - schedule:
          cron: "57 15 * * *"
          filters:
            branches:
              only:
                - master
    jobs:
      - check:
          filters:
            branches:
              only:
                - master

とてもシンプルな設定だと思います. ちゃんとした運用を考慮するならば, Slack 通知の orbs なんかを追加していい感じで自動化出来るのではと考えていますが, まだやっていません.

以上

Fitbit Web API と pixela を使って走行 (歩行) 距離を可視化を検討してみました. 毎日書いている日記に貼り付けてドヤってみようかなと考えています. やっぱり可視化は楽しいですね.

冬休みの自由研究 (2) 〜 Google SpreadSheet と Google Calendar の連携サンプルにコマンドラインツールの clasp を添えて 〜

tl;dr

以下のようなお誕生日リストを Google SpreadSheet で作っておいて, Google Calendar に登録する Google App Script (以後, GAS) を作ってみました. また, スクリプトをローカル環境からデプロイや関数の実行を操作出来る clasp も合わせて使ってみたのでメモしておきます.

f:id:inokara:20200103091651p:plain

作ったもの

github.com

スクリプトを実行すると, 下図のようにカレンダーに登録されます.

f:id:inokara:20200103105501p:plain

メモ

Google Calendar にイベントを登録する

Calendar クラスを利用して登録します.

developers.google.com

シンプルにイベントを登録する場合には, 以下のように createAllDayEvent メソッドを利用して書くことで登録できました.

// https://developers.google.com/apps-script/reference/calendar/calendar#createalldayeventtitle,-date より引用
// Creates an all-day event for the moon landing and logs the ID.
var event = CalendarApp.getDefaultCalendar().createAllDayEvent('Apollo 11 Landing',
    new Date('July 20, 1969'));
Logger.log('Event ID: ' + event.getId());

一方, 今回のように誕生日のような, 年間で繰り返しで登録する場合には, createAllDayEventSeries メソッドを利用しました.

// https://github.com/inokappa/spreadsheet-to-calendar/blob/master/main.js#L10-L25
  var calId = PropertiesService.getScriptProperties().getProperty("clendarId");
  var cal = CalendarApp.getCalendarById(calId);
  var eventId = event['id'];
  var eventTitle = event['t'];
  var birthDay = event['dt'];
  var eventDesc = event['ds'];

  // カレンダーに登録 (毎年繰り返す)
  eventSeries = cal.createAllDayEventSeries(eventTitle, new Date(birthDay),
    CalendarApp.newRecurrence().addYearlyRule(), {description: eventDesc});
  if(eventSeries){
    sheet.getRange(eventId, 6).setValue("登録済み");
  }else{
    sheet.getRange(eventId, 6).setValue("登録失敗");
  }

さらに, createAllDayEventSeries メソッドの引数としては, タイトル, 開始日, そして, Recurrence (繰り返し) を設定してあげる必要があります.

developers.google.com

毎年の場合には, 上記のように addYearlyRule() メソッドを利用しています.

スプレッドシートで getRange().getValue() の利用を出来るだけ避けたい

当初は, 以下のようなコードを書いて満足していました.

function main() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('birthdays');
  var lastRow = sheet.getLastRow();

  for (var i = 2; i <= lastRow; i++) {
    var birthLastName = sheet.getRange(i, 1).getValue();
    if (birthLastName == "") {
      break;
    }

    var registed = sheet.getRange(i, 6).getValue();
    if (registed == "") {
      var today = new Date();
      var todayYear = today.getYear();
      var birthMonth = sheet.getRange(i, 4).getValue();
      var birthDate = sheet.getRange(i, 5).getValue();
      var birthDay = todayYear + "/" + birthMonth + "/" + birthDate;
      var birthFirstName = sheet.getRange(i, 2).getValue();
      var birthMember = birthLastName + " " + birthFirstName;
      var eventTitle = birthMember + " さん誕生日";
      var eventDesc = birthMember + "さん、お誕生日おめでとう! ";
(略)

スプレッドシートのセルから値を取得する為に, sheet.getRange(i, 2).getValue() のように getRange().getValue() 関数を多用しているのがどうしても気になってしまいました. getRange().getValue() 関数を多用しすぎると, エラーにはならないものの, 利用頻度が高い旨の警告が出るようです.

qiita.com

ということで, 上記の Qiita 記事にも書かれているように, getValue() ではなく, 以下のように getValues() 関数をラップした関数を作ることにしました.

function getBirthdays() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('birthdays');
  var values = sheet.getDataRange().getValues(); 
  return values;
}

こうすることで, シート全体の内容が以下のような配列として返ってくるので, これを処理するように実装しています.

[[ (必須入力),  (必須入力), 生年月日,  (必須入力),  (必須入力), 登録済み], [テスト1, 太郎, Mon Feb 03 00:00:00 GMT+09:00 2020, 2.0, 3.0, ], [テスト2, 花子, Sun Apr 05 00:00:00 GMT+09:00 2020, 4.0, 5.0, ], [テスト3, 太郎, Mon Jun 08 00:00:00 GMT+09:00 2020, 6.0, 8.0, ], [テスト4, 花子, Fri Jul 10 00:00:00 GMT+09:00 2020, 7.0, 10.0, ], [テスト5, 太郎, Sat Aug 08 00:00:00 GMT+09:00 2020, 8.0, 8.0, ], [テスト6, 花子, Tue Sep 01 00:00:00 GMT+09:00 2020, 9.0, 1.0, ], [テスト7, 太郎, Fri Oct 30 00:00:00 GMT+09:00 2020, 10.0, 30.0, ], [テスト8, 花子, Sun Nov 08 00:00:00 GMT+09:00 2020, 11.0, 8.0, ]]

裏取りは完全にできていないのですが, おそらく, getValue() は毎回スプレッドシートにアクセスするのに対して, getValues()スプレッドシートへのアクセスは一回になるので, getValues() を使ったほうがエコであることは間違いないようです.

サンプルでは, getValue() を使いまくっているスクリプトを main-old.js, getValues() に置き換えたバージョンを main.js として保存しています.

clasp は良い

clasp とは

clasp とは, GAS をローカル環境からガチャガチャ出来るコマンドラインツールです.

github.com

clasp を使うと, GAS のスクリプトがローカル環境のお気に入りのエディタで書くことが出来たり, 書いたスクリプトを直接デプロイしたり, 関数単位で実行することが可能になります. そして, ローカル環境にスクリプトを取得することも可能ですので, git でスクリプトが管理出来るようになる点です. 素晴らしいですよね.

clasp のインストール等の基本的な利用方法については, リポジトリREADME 等をご一読下さい.

clasp create からの clasp push

今回のように既に SpreadSheet は存在していて, その SpreadSheet でスクリプトを書きたい場合には, 以下のように実行することで SpreadSheet とスクリプト (プロジェクト) を関連付けることが出来ます.

$ clasp create --parentId ${スプレッドシートの ID}

後は, 適当なファイル名でスクリプトを書いていきます. サンプルでは, main.js というファイル名で書いています. 一通り書いたら, clasp push でプロジェクトにスクリプトを登録することが出来ます.

$ clasp push

あとは, ブラウザを開いて (clasp open で開くことが出来ます), スクリプトを実行してみましょう... しかし, なんか違和感があります. 時代は令和です, やっぱり, 全ての操作をコマンドラインだけで完結したくなりますよね.

clasp run

ということで, clasp run というコマンドが用意されています. その名の如く, 関数を実行する為のコマンドです. このコマンドを利用する為には, GAS のプロジェクトと GCP のプロジェクトを紐付ける為に, ひと手間が必要になります...

github.com

上記のドキュメントの https://github.com/google/clasp/blob/master/docs/run.md#setup-instructions に書かれている手順に従います. この手順を遵守すれば, 特にハマりポイントはありません. ただし, 個人的には GCP のプロジェクト番号を確認する方法が判らずに泣きそうになりました. 何のことない, 下図のように 設定 ページにて確認することが出来ました.

f:id:inokara:20200103104008p:plain

f:id:inokara:20200103104112p:plain

以下は, hello world を出力するだけの GAS を clasp run している様子です.

$ clasp run
Running in dev mode.
? Select a functionName helloworld
No response.
$ clasp logs
NOTICE     2020-01-03T01:15:33.220Z CreateProject   Setting up StackDriver Logging.
NOTICE     2020-01-03T01:15:35.484Z google.api.servicemanagement.v1.ServiceManager.ActivateServices Setting up StackDriver Logging.
NOTICE     2020-01-03T01:15:37.820744550Z google.api.servicemanagement.v1.ServiceManager.ActivateServices Setting up StackDriver Logging.
NOTICE     2020-01-03T01:15:39.241Z AssignResourceToBillingAccount Setting up StackDriver Logging.
NOTICE     2020-01-03T01:18:39.131Z CreateBrand     Setting up StackDriver Logging.
NOTICE     2020-01-03T01:19:29.055Z CreateClient    Setting up StackDriver Logging.
NOTICE     2020-01-03T01:21:38.087Z CreateClient    Setting up StackDriver Logging.
NOTICE     2020-01-03T01:23:15.875Z google.api.serviceusage.v1.ServiceUsage.EnableService Setting up StackDriver Logging.
NOTICE     2020-01-03T01:23:17.901384489Z google.api.serviceusage.v1.ServiceUsage.EnableService Setting up StackDriver Logging.
DEBUG      2020-01-03T01:24:08.766Z helloworld      {"message":"Hello world","serviceContext":{"service":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}}
DEBUG      2020-01-03T01:42:18.018Z helloworld      {"serviceContext":{"service":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"},"message":"Hello world"}

ついでに, clasp logs というスクリプトのログを標準出力に出力するコマンドも実行しています.

いい感じです.

以上

Google SpreadSheet と Google Calendar の連携サンプルをネタに色々と GAS をイジってみました. clasp を使うことで, 手元で好きなエディタでスクリプトを書いて clasp run で動作確認をするという流れが良い感じでした. 今後は, スクリプトを TypeScript で書いて (TypeScript を勉強するところから), テストも書いたり出来ると嬉しいなあと考えています.

引き続き, 精進してまいります.