tmux/screen上でのnvimのescapeレスポンスを早くする - 真面目に、強く、上品に

これ!

ずっとneovimでESC押した後の次のキーの認識までのタイミングが長くて、vimのサクサクした操作というメリットがなくなっていました。しかしこの状況を言葉でなんと表現したら良いか難しくてググれず、困っていました。

いつも何か無意識にESCを押した後一瞬待つという謎のワークアラウンド作法が身につくほどでしたが、この度解決しました。ありがとうございます!サイコー!

先週、食中毒になったようで数日間非常に苦しんだ。

もう回復してあとは胃が荒れているぐらいなんだが、吐き気のない生活のなんとすばらしいことか。

おそらくしゃぶしゃぶ食べ放題に行った時の肉か生卵かどちらかに当たったと思うんだが・・・。

肉はしっかり火を通そうと固く決意したし、もう生卵を食べるのが怖くなった。

そういえばこのブログのドメイン(docs.komagata.org)ばかり使っていてkomagata.orgのドメインはだいぶ放置していたのでサイトを作りました。

Google Domainsを使ってるので(?)Firebase Hostingにおきました。

CSSのAnimationはTwitterで@shimewtrさんに教えてもらいました。ありがとうございます。

https://komagata.org

ずっと下記に書いたような問題意識を自分たちのプログラミングスクールに対して持っております。

OSS Gateオンラインワークショップに参加 - komagataのブログ

そこでこんな活動をやってみたらどうかな〜と思っています。(スクール内限定じゃなくてパブリックなワークショップにしたい)

ワークショップ

OSS活動は終わらないネットゲームであり、みんな脳汁を垂れ流して楽しんでおります。しかしそこに辿り着くまでに色々と障壁があり、プログラミングに興味のある人や初心者の方にプログラミングの楽しさを知ってもらうためのワークショップができないかと考えております。(また、OSS活動以外のプログラミングの楽しみもいいと思う)

Joy of Programming(プログラミングの楽しみ)

1回につき1テーマのプログラミングの楽しみについて体験してもらい、みんなで楽しむ。

役に立つとか、勉強になるとかは置いておいて、楽しさを一番重視する。

テーマ1

自分のための小さなスクリプトを作ろう。

~/binとかに置くような自分のためだけのちょっとした便利スクリプトをみんなでかく。

「昼飯をランダムで決めるスクリプト」とか「~/Downloadsディレクトリの中を定期的に削除するスクリプト」とか「平日の10時に自動で勤怠アプリにログインする」スクリプトとかそういうやつです。

テーマ2

基本のアルゴリズムを実装してみよう。現代のプログラミング言語であれば標準ライブラリで備えているような基本的な簡単なアルゴリズムを自分の得意な言語で実装してみる。

テーマ3

フリーソフトウェア運動に参加する。フリーソフトウェアとは何かを学んで入信する。自分の使ってるソフトをフリーソフトウェアに置き換えられないか検討したり、布教活動をする。

テーマ4

Quineを作ってみよう。(説明すると長くなるので省略)

テーマ5

使ったことない言語を使ってみよう。

テーマ6

使ったことないOSを使ってみよう。

テーマ7

競技プログラミングに挑戦しよう

テーマ8

名著を読もう。

みんなで色々な名著を読んできて、大体の内容を話してもらう。他人におすすめする。

テーマ9

ライブラリを作ろう。gemとかnpmとかそういうのの作り方ワークショップ。これができたらOSS活動に進む感じ。

どういうワークショップにするか

1〜3時間ぐらいの長すぎないワークショップにしたい。一回につき1テーマで開催する。色々やってみて評判の良いテーマが絞れたらそれらを繰り返しやる。1 > 3 > 7...とか。

前半は説明をして、後半で手を動かしてやってみる。最初は1人でサポートしきれるぐらいの人数が良いかもしれない。

全体として、Terminalの使い方、簡単なコードが書ける力(どの言語でもいいが)などが必要になる。

Terminalの使い方は(昔に書いた)下記で学べるかもだが、基本的なプログラミングも学べる何かが欲しい。

本当は怖くない 黒い画面入門: https://fjord.jp/kuroigamen.html

初心者向けだけど、プロでもネタのチョイスによってはずっと楽しめる感じにしたい。例えばQuine入門の内容をやるけど、超難しいやつを自分のテーマとして毎回作っても良いみたいな感じ。競プロ入門を毎回やるけど、すげー人が既にいるとか。コミュニティーの中に目指したくなるロールモデルがいるとより良いと思うので。

ちょっとできるように考えてみたいと思います。

OSS Gateオンラインワークショップ2021-03-13にサポーターとして初参加させていただきました。

参加理由

フィヨルドブートキャンプというプログラミングスクールを運営していますが、生徒の方で「頑張って、歯を食いしばって勉強する!」という状態になる方が出てしまうのが常々僕らの取り組みの問題だと感じています。

「プログラミングが面白くてハマってたらスキルが上がっていた」というのが理想です。逆にハマりさえすればあとは勝手に勉強していくので面白さを伝えるのがスクールの一番の目標といっても過言ではありません。

「どうやったらプログラミングの面白さを伝えられるんだろう?」と考えたときに、やはり「プログラミングの楽しさっつったらOSS活動だろう」ということでOSS活動に参加する人を日夜増やし続けているOSS Gateさんのやり方を学びたく、また僕もその活動をしたいと思って参加しました。

OSS活動参加をサポート

今回はビギナーの方が自身で選んだOSSであるApache AirFlowの開発に参加してみるのをサポートしました。(実際は進行役のPiroさんのメンタリングを僕はほとんど聞いてるだけの形ですが🤭)

詳細なメモを取りながらまず自分でインストールしてみる。わかりにくかった部分をIssueフィードバックする。その部分を直すPRを作って送ってみるという一連の流れをやりました。

僕もAirFlowって初めて知りましたし、途中でちょっとしたbashの問題にハマったり、Issueを書く時の適した英語表現など、僕も非常に勉強になりました。

感想

事前に動画で予習してる時から感じてたのですが、非常に実践的で、そして予想以上に手厚くサポートしてもらえるワークショップですごいなと思いました。

まさに今回参加されたビギナーさんは「これだったらこのあと家で一人でもできる」と思ってもらえたんじゃないかと思います。

「ソフトの文句を言う人」から「ソフトの開発者」に半日で変わったのだからすごい進化です。

スクールでの適用に対する問題点

ひるがえって自分の運営するスクールでの適用を考えた時の問題点を考えてみました。

OSSって何?

プログラミングスクールの生徒として考えるとまず、「OSSってなんですか?」という状態の人にはまだ早いということです。

人が作ってる?

「XXX(ソフト・ライブラリ名)がとても便利!こんなのがあるなんて知りませんでした。」

という感想に対して僕が

あるというより誰かが便利に作ってくれたってことなんですよね。」

とコメントをすると

「そうですよね。誰かが作っているんですよね。考えてみたこともなかったです。」

的なやりとりが大体発生し、そこで初めてOSSなどを意識して学習していくことが多いです。まずそこを超えた人(=ソフトのありがたみを感じたことのある人)じゃないと参加が難しいと思いました。

コマンドライン・gitが使えない

また、コマンドライン・gitが使えることも前提となるので、フィヨルドブートキャンプでいえばそれらのカリキュラムを履修した人以降が対象だと思いました。

スクールに適用するなら

OSS GateではOSS活動に参加したことのないプログラマーが対象ですが、フィヨルドブートキャンプの生徒に対して行う(またはプログラミング学習中の人に行う)ならば、「XXXが使える人」「XXXのカリキュラムより先に進んでいる人」などの前提条件を決める必要があるなと感じました。

そして僕の問題意識から考えると、まずはそこに達していない人にプログラミングの楽しさを伝える活動が必要なのかなと思いました。(達してる人はOSS Gateへ!)

ちょっとそういった活動も考えてみたいと思います。

フィヨルドブートキャンプではチャットをSlackからDiscordに移行しようとしています。

DiscordにはSlackのようなReminder機能がメジャーなBotの中には無いので定期的なミーティングのリマインドを簡単に移行することができません。

有名なreminder-botでは「72時間おきにリマインド」のような単純Interval形式しか対応してません。「毎月1日の9時にリマインド」のようなことができないので困ってました。

ブートキャンプでは現在リマインドすべきものは3つしかなく、SlackのようなReminder Botを僕が作るのも面倒なのでCloud Functionsでやってみました。

流れ

Cloud Scheduler -> Pub/Sub -> Cloud Functions -> Discord

Cloud Schedulerでcronと同じインターフェースで時間を指定できるのでjobを作ります。

Image from Gyazo

ターゲットにはHTTPを指定してリクエストを飛ばしたりもできますが、Pub/Subも指定できます。

Pub/Subはややこしいかと思ってたんですが単に名前決めて作るだけでした。

Cloud FunctionsではPub/Subで作ったイベントをSubscriptionしてそのタイミングで実行できます。

コード

Image from Gyazo

require 'functions_framework'
require 'net/http'
require 'json'

FunctionsFramework.cloud_event 'reminder_sub' do |event|
  uri = URI.parse(ENV['WEBHOOK_URL'])
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  params = { "content" => "💬 14:00からふりかえりミーティングが 🔈ミーティング チャンネルで始まります。" }
  headers = { "Content-Type" => "application/json" }
  http.post(uri.path, params.to_json, headers)
end

Discordの発言はwebhookにPOSTするだけです。Cloud Schedulerからpayloadに何か値を入れてれば上記のeventの中にそれが(base64でエンコードされて)入っているのでその内容を使って処理を分けたりもできます。(実際のコードでは3種類の通知をそれで出し分けてます。)

最初のテンプレにGemfileも含まれていて、gemを使うのも何にも苦労せずでした。

Image from Gyazo

Cloud Functionsは高度な用途もありますが、こういうふうに週1回しか動かないクソちょっとしたプログラムを動かすにも安くていいなと思います。

フィヨルドブートキャンプでは終盤に生徒の方と一緒になってみんなが使っているEラーニングシステム自体をスクラムで開発するカリキュラムがあります。

そこでのブランチ戦略を最近変えたので生徒の方への説明も兼ねて紹介します。

Image from Gyazo

GitLab Flowです。 

糸冬 わ り

だとあんまりなのでデプロイについても書きます。

(厳密にはpre-productionはなくて、master=唯一のステージングです)

リリース

デプロイはCloud Buildでgit pushをきっかけにmain = ステージング環境、production = 本番環境という具合でデプロイしています。

デプロイは週1回で、毎週水曜日のふりかえりミーティングの後にリリースしています。

master(main)にPRがマージされるとgit-pr-releaseでリリース用のPRが作成されます。

ss

各担当者はステージング環境で動作確認したらここのチェックボックスにチェックを入れます。

ss2

そして各担当者は自分の実装したところをリリース文に書きます。

全部の動作確認が終わっていたらリリースします。(productionブランチにマージする)

Image from Gyazo

本番環境にデプロイされたらDiscordに通知が来るので、各担当者は本番環境で動作確認をして、IssueをCloseします。

最近変えたところ

以前まではGitHub Flowだったんですが、やっぱりいきなり本番にアップされるのは怖いという声もあり、Git Flowを検討していました。

しかし@kakutaniさんからGit Flowは提唱者自身が

「Git FlowはGitHubとかなかった昔に作ったものだから別のFlowがいいよ」

と言っていると聞いてGitLab Flowを見たら良さそうだったので決めました。

みんなでリリース文を書くというのも、誰がどの機能を作ってくれたのか、学習中の方にも伝わって楽しいということで初めてみましたが好評な感じです。

次はmasterをmainに変えると作業をやる予定です。

(ハライチ感)

Foo.configure do |config|
  config.name = "foo"
  config.email = "foo@example.com"
end

こっちでもかけたりする。

Foo.config.name = "foo"
Foo.config.email = "foo@example.com"

こういうやつ。

実装は大体こういう感じになってる。

module Foo
  class << self
    def configure
      yield config
    end

    def config
      @_config ||= Config.new
    end
  end

  class Config
    attr_accessor :name, :email

    def initialize
      @name = "no name"
      @email = "default@example.com"
    end
  end
end

これrubyでよくあるけど(他の言語であんま見ない)これなんて呼ぶのがいいのかな?

フィヨルドブートキャンプで説明する時にこれを表現したくても

「blockで設定するやつ」

としか言えない。

「なんでこれで設定できるんですか?」

と言われても、口で説明するのが大変なのでここに置いておきます。

Cloud Buildでのデプロイ通知を調べると相当ヘビーなやり方の公式ドキュメントが出てくる。

Slack 通知を構成する  |  Cloud Build のドキュメント  |  Google Cloud

Cloud Storageにおいた構成ファイルをもとにpub/subに通知を送ってそれを読み取ったCloud RunにデプロイしたSlackNotifierがSlackにメッセージを送る?

面倒クセェ〜!

  - id: Notify
    name: gcr.io/google.com/cloudsdktool/cloud-sdk
    entrypoint: curl
    args: ['-H', '"Content-Type: application/json"', '-X', 'POST', '-d', '''{"content": "Deployed."}''', '$_WEBHOOK_URL']

curlで良いやろ。(上記はDiscordへの通知)

公式ドキュメントにもしっかりあるし、みんなデフォルトでやってるかもしれないけど、すごく早くなったのでご紹介。

ビルドを高速化する際のおすすめの方法  |  Cloud Build のドキュメント  |  Google Cloud

今まではCloud BuildでCloud Runにデプロイするときにでdockerイメージをbuildするところを下記のようにしてたんですが、

  - id: Build
    name: gcr.io/cloud-builders/docker
    args: ['build',
           '-t', 'asia.gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA',
           '-t', 'asia.gcr.io/$PROJECT_ID/$REPO_NAME:latest',
           '.',
           '-f', 'Dockerfile']

そこの前に下記のように前回最後にbuildしたイメージを取ってくるようにして、build時に--cache-fromを入れると良い感じに前回のイメージを使ってくれる。

  - id: Fetch
    name: gcr.io/cloud-builders/docker
    entrypoint: 'bash'
    args: ['-c', 'docker pull asia.gcr.io/$PROJECT_ID/$REPO_NAME:latest || exit 0']
  - id: Build
    name: gcr.io/cloud-builders/docker
    args: ['build',
           '-t', 'asia.gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA',
           '-t', 'asia.gcr.io/$PROJECT_ID/$REPO_NAME:latest',
           '--cache-from', 'asia.gcr.io/$PROJECT_ID/$REPO_NAME:latest',
           '.',
           '-f', 'Dockerfile']

24分ぐらいかかってたのが4分になって嬉しい。