コミットIDを指定してリモートにpushする

Jenkinsさんがご立腹

久々に使ったJenkinsさんがご立腹なので、僕が彼に食べさせたものが悪いのか、彼自身が体調を崩したのかを切り分けようと思い、過去に大丈夫だったコミットを食わせてみることにした。ので、特定のコミットをリモートにpushするのに

git checkout -b foobar <commit SHA> && git push origin foobar

みたいにすればいいんだけど、サクッとできないかな?と思ってぐぐったらあった。

コミットIDを指定してリモートにpushする

へー。

git push <remotename> <commit SHA>:refs/heads/<new remote branch name>

git - How can I push a specific commit to a remote, and not previous commits? - Stack Overflow

知らんかった。便利。

ところで

ちょっと気になってJenkinsさんにコミットIDを渡してあげたら普通にビルドできた。わざわざブランチを作る必要なかった。

さすが。(´・ω・`)

組織を改善するときは足すより引く感じで

僕は数年前に改善グループってのを立ち上げて、部内の他のグループに行ってそこの改善を手伝うみたいな活動をしてる。開発の進め方の改善をしたり、アーキテクチャーの改善をしたり、他のグループの人どうしをつないだり、とか。そういう感じのこと。

そしたら、この前「うちの部署の改善活動の参考にしたいから、意見交換しようー」って、他の部署の人が話をしに来てくれて、そのおかげでぼやーっと感覚でやってた自分の頭の中が少し言葉にできたのでメモ。

良くないの

こういうのは良くないよねーって話をしたのが。

上からの指示で改善活動をさせられてるけど意味分からん。

みたいなの。

良くないの2

でも、こういうのも良くないよねーって話をしたのが。トップダウンじゃうまくいかないから現場を中心にしよう!ってことで

「ぜひ自分たちで問題と思ってるところを出して、それを改善する方法を考えて、実施してください!」みたいなの。

結局それって全部現場に丸投げして負担増やしてるだけじゃん。てか、それできるならやってる。

じゃあどうするの?

トップダウンでもだめ、ボトムアップでもだめ、じゃあどうするの?って考えてみると、今僕がいる部署は、両方からだなーって話をした。

現場の意見を元に、組織として方向性を決めて、その改善活動をサポートして、結果を評価する。みたいなの。たぶん、改善活動って組織全体の活動なんだろうなー。

現場の意見を元に

そもそも現場のみんなは改善したくないというわけじゃなくて、何かしら改善したいと思ってる。

話を聞きに行くと、みんな「テスト改善したいんですよねー」とか「開発プロセスをもうちょっと整理したいな」とか「レガシーなんとかしたい!」とかいっぱい意見が出てくる。

組織として方向性を決めて

そんな風に色々意見を持ってるのに、なかなか自分たちで行動にうつすのって難しい。なんでかっていうと、それよりも優先することがあって忙しいから。その忙しさが減らない状態で改善をしようって言っても無理なんよね。

だから、トップが「組織の方針として」現場から出てきた意見の中から例えば「テストの自動化をする」ことを組織の目標に入れる。

その改善活動をサポートして

組織の目標に入れることで何をするかって言うと、「じゃ、それを改善をしてね!」ってやることを足すというよりも「あなたたちの出してくれたこの改善案は組織としての方針にしたので、他の何かの優先度を下げていいから!」って現場の忙しさを引いてあげることで、改善するために必要な場所を作りだす。という感じ。

そのへんで「テスト自動化について聞きたいことあったら、この人に聞いたらよいよ。他のグループがどうやってるかとか色々知ってるからー」って僕は紹介されて行ってくる。

結果を評価する

あとは、その活動もサービスの売上を伸ばしたりするのと同じように「組織に対する貢献」として評価されるようにして、その活動で給料があがるようにする。大切。

まとめ

ということで

  • 現場のみんなが改善したいなって思っていることを元に
  • 組織として方向性を決めることで組織としても価値があることを認識して
  • サービス開発のバックログの中でその改善活動の優先順位を上げることで
  • 改善したいことを実行にうつすことができる場を作りだして
  • その活動を評価して給料があがるようにする

といった感じかな。全体の活動になってる。

サービス開発運用エンジニア

僕は、Javaのエンジニアだけど。全然JVMについて詳しいわけでもないし。技術トレンドのキャッチアップも、だいたい3,4年遅れてる感じあるし。Linux上でサービスを動かしてるけど、Linuxがどんな風に動いてるか分かってないし。

エンジニアとしてまだまだだなーって思うんだけど。

でも、そんな僕でも、結構役に立ってるように感じてはいて。だから、自分の強いとこってなんだろうなー?って考えると。こんな感じ:

  • 事業部や編成部やプロデューサーと信頼関係を築いてお互いに同じものを見ながら開発できること
  • 目の前でサービスを生き残らせるためにどんな技術的負債を受け入れないといけないかのトレードオフを考えること
  • とは言っても、サービスを開発することの先にあるサービス運用を中心において開発すること
  • メンバーじゃなくてチームとしての場が会社に残るようなチームづくりをすること

技術的に尖ってるって訳じゃないけど、サービスの開発と運用をチームでやってくことに関してはそれなりにスキルが身についてるかなぁ。なんというか「サービス開発運用エンジニア」みたいな雰囲気。

DevOpsっていう文脈のOps(運用)じゃなくて、色んな制約がある中でサービスを守りつつ伸ばしつつ改善しつつ、なサービス運用とそれを中心においた開発ね。

そういうのにも価値はあるよなーって、自分で自分をちょっと褒めとこうと思った。ご褒美にチョコソフトを食べよう。

SpringBootアプリのDockerイメージをGradleでビルドしてプッシュ

Mavenではやったことあるけど、Gradleでやったことないなーって思って、ここを見ながらやったらすぐできるかな?と思ったけど、いつも通りなんか色々気になって結局うろうろ見て回ってしまった。

spring.io

今回使ったソース

github.com

違うとこ

  • DockerfileにJAVA_OPTSを足しといた
  • gradle-dockerの最新バージョン(0.19.2)を使っといた

結構色々見て回った気がしたけど、こう書いてみるとたいしたことしてないな。

DockerfileにJAVA_OPTSを足しといた

Gradle全然関係ないか。。。

Dockerfileどこに置くん?ってなったけどサンプルコード(https://github.com/spring-guides/gs-spring-boot-docker/tree/master/complete)見たらリポジトリーのルートだった。まぁ、そこがプラグインのデフォルトってだけなので、設定で場所を指定できるすね。

で、そのDockerfile:

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT exec java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar

これで、起動時にJAVA_OPTS環境変数でごにょごにょ指定できる。でも、どうしてSpringの公式にはDockerfileでオプションを渡せるようにする方法が書いてないんだろう?別のいいやり方があるのかな?と思いながら、うろうろしてみたけど特に見つけられなかったや。

gradle-dockerの最新バージョン(0.19.2)を使っといた

dependsOn buildの部分で怒られるのなんだろうなー?と思いながら。プラグインリポジトリーを見に行って、README読みながら、こんな感じかなって思うのを書いた。結局その怒られる部分は削っといた。

GitHub - palantir/gradle-docker: a Gradle plugin for orchestrating docker builds and pushes.

SpringInitializrで生成されたやつに対して書き加えたのはこの辺:

buildscript {
  …
  repositories {
    maven {
      url "https://plugins.gradle.org/m2/"
    }
    …
  }
  dependencies {
    …
    classpath('gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.19.2')
  }
}

…
apply plugin: 'com.palantir.docker'

…

ext {
  dockerImagePrefix = 'bufferings'
}

docker {
  name "${dockerImagePrefix}/${project.name}"
  files bootJar.archivePath
  buildArgs(['JAR_FILE': "${bootJar.archiveName}"])
}

なんとなくDockerHubのpush先のprefixにgroup使うよりは別の名前のがいいなって思ってdockerImagePrefixという名前の変数を作ってみた。extってこういう使い方でいいんかな?

ビルド

Dockerイメージのビルドは、こんな感じで

$ ./gradlew build docker

イメージが作られる。今回サンプルで作ったプロジェクトの名前はhello-bootだからそれがイメージのリポジトリー名に使われてる。

$ docker images
REPOSITORY                             TAG                 IMAGE ID            CREATED             SIZE
bufferings/hello-boot                  latest              6a1a102d8c30        42 minutes ago      119MB

プッシュ

DockerHubへのプッシュは、こんな感じで

$ ./gradlew dockerPush

pushされてた。docker loginしとかないとエラーになるすね。

https://hub.docker.com/r/bufferings/hello-boot/

ヽ(=´▽`=)ノ

あ、でも、違うんやで。今日はこれがやりたかったというわけじゃないんやで。まいっか、やりたかったことは、また次の機会に。

Minikube v0.26.1 にしたら Starting cluster components... でハングしたけど解決した

minikubeをv0.26.1に上げたら、minikube startの途中の Starting cluster components... でハングした。

$ minikube start                                                                                                                                                                 
Starting local Kubernetes v1.10.0 cluster...                                                                                                                                     
Starting VM...                                                                                                                                                                   
Getting VM IP address...                                                                                                                                                         
Moving files into cluster...                                                                                                                                                     
Setting up certs...                                                                                                                                                              
Connecting to cluster...                                                                                                                                                         
Setting up kubeconfig...                                                                                                                                                         
Starting cluster components...                                                                                                                                                   
E0513 11:59:51.236808    2782 start.go:281] Error restarting cluster:  restarting kube-proxy: waiting for kube-proxy to be up for configmap update: timed out waiting for the con
dition                                                                                                                                                                           
================================================================================                                                                                                 
An error has occurred. Would you like to opt in to sending anonymized crash             
information to minikube to help prevent future errors?                                  
To opt out of these messages, run the command:                                          
        minikube config set WantReportErrorPrompt false                                 
================================================================================        
Please enter your response [Y/n]:

ので、見てみたら、Issueがあった。僕はMacじゃなくてUbuntuだけど、同じ状況。

github.com

そこに書いてあるみたいに

$ rm -rf ~/.minikube  
$ minikube start

ってやってから起動したら無事起動したやヽ(=´▽`=)ノ

$ minikube start      
Starting local Kubernetes v1.10.0 cluster...                                            
Starting VM...        
Downloading Minikube ISO                    
 150.53 MB / 150.53 MB [============================================] 100.00% 0s        
Getting VM IP address...                    
Moving files into cluster...                
Downloading kubeadm v1.10.0                 
Downloading kubelet v1.10.0                 
Finished Downloading kubelet v1.10.0        
Finished Downloading kubeadm v1.10.0        
Setting up certs...   
Connecting to cluster...                    
Setting up kubeconfig...                    
Starting cluster components...              
Kubectl is now configured to use the cluster.                                           
Loading cached images from config file.   

違うんやで。今日はこれがやりたかったというわけじゃないんやで。

僕はドキュメントを読むのが苦手

頭の中にスタックが3つしかないからネストは3つまでがいいし。リンクを辿って色んなところに飛ぶと戻ってこれないし。こういう意味にも取れるけどどっちだろう?とかなるし。似たようなことが複数の箇所に書いてあると目diffをしてしまうし。気が散りやすいし。

自分にとって読みやすいドキュメントを書く

だから、書くときは「自分が頑張らなくても読めるように」と思って書く。そしたら、他の人にとっても読みやすいんじゃないかと思って。

そんな風にして最近書いたドキュメントを褒めてもらって喜んだので、こんなこと気にしながら書いてるかなーと思うのをメモ。ふわっとした話。

誰にどうなって欲しいか?

具体的に誰か一人を想像する。「全員にとって」ではなく「その人にとって」価値のあるドキュメントにする。

  • 彼は、どうしてこのドキュメントを見たいと思ったのか?何に困っているのか?
  • 彼は、今どんなことを知ってるのか?
  • 彼は、このドキュメントを読むことで、次にどんなアクションを起こすことができるようになるか?

みたいな。「何を書くか」より「それによってどうなって欲しいか」を考える。プロダクトも、プレゼンも似てるとこあるよね。

Agile 2011 Conference : ジェフ・パットン氏によるアジャイルな要件定義手法「ユーザーストーリーマップ」のチュートリアル - kawaguti’s diary

プレゼンテーション・パターン (Presentation Patterns)

言葉の定義

ひとつのものを色んな呼び方で呼ぶとつらいし、ひとつの言葉で複数のものを指すのもつらい。結局どれを指してるんだろう?ってのを文脈から想像しないといけないし、そもそも違うものを想像してしまったりしてしまうから。

ので、紛らわしいものは、言葉の定義を作る。「このドキュメントでは、こう呼ぶ」で構わないかな。全部細かく定義してあったら読みたくなくなるから、紛らわしいものだけ。

最初から書くときもあるけど、どっちかというとドキュメントを書きながら「あれ?この言葉さっき違うものを指すのに使ったなぁ・・・」ってなることが多くて。そういうときはちゃんと名前を与えてあげると色々発見できてスッキリする時ある。

ユビキタス言語 な雰囲気するね。

ぱっと見て分かりたい

ぱっと見:図を使う

図とかを使って、最初に全体の概要をぱっと見て「なるほど?」って言えるようにしたい。んで、図は、そのぱっと見の印象が正しい理解になるように書く。たまに、ぱっと見た印象と実際が違うドキュメントがあったりして、そういうの混乱するから。

ぱっと見:概要から詳細

最初から詳細を書くんじゃなくて、概要があって、全体像を頭の中に描けた後に、詳細が書いてあるのがいい。

ぱっと見:全部は要らない

書いてるときの自分の頭だと、その対象を深く理解してることが多いので、全部正確に書きたくなってしまうんだけど、「誰にどうなって欲しいか?」という目的に対して必要な最低限の情報を軸にする。

読まれる時間の方が多い

結構頑張って書いて書き終わったら(ヽ´ω`)するし、もういいじゃんって気持ちになるんだけど。一晩寝かせてみて、もっかい見てみる。んで、読みにくい部分があれば直すし、不要だなと思う部分があれば、頑張って書いたやつでも削除する。

よく、コードは「書くよりも、読まれることの方が多いから読みやすいコードを書こう」って言われるけど、それってドキュメントもそうだなーって思いながら。

ということで

  • 誰にどうなって欲しいか?
  • 言葉の定義
  • ぱっと見て分かりたい
  • 読まれる時間の方が多い

を考えながら書いてるみたい。今日の朝ごはんはチョコクロにしようかな。

子どもたちに学ぶチームビルディング

最近、子どもに関することをちょこちょこ書いたので、ちょっとまとめ。

子どもたちを見てて良いなぁと思うのは

「言われていることを理解してはいても、やりたくない気持ちのときは実行できない」ということ。それを素直に表現してくれる。やらなきゃと思って行動しようとはしても、体が動かない。

大人は、嫌だなと思っていてもそれを抑えて行動しようとするし、自分がそれを嫌だと思ってること自体に気づいてないときもあるのかもしれない。

だから、子どもたちを見てると「あ、こういうのは嫌なのか。そういえば、そうだな」と気付かされたり、「じゃあ、どうやったらこの子が自分から進んでできるようになるだろう?」と考えてみたりする。

どうせなら大人だって、できるだけ嫌な気持ちにならずに、自然とそうできるようなやり方ができたらいいもんな。

自然とそうなる開発チーム

僕が「こうだったらいいな」と思ってるチームは、ちょうど2年前に「とちぎテストの会議」でお話させてもらったことから変わってない。

自然とそうなる開発チームをつくるいとなむ #toteka // Speaker Deck

自分の子どもをあずけたいと思えるチームがいい。子どもが楽しみながら成長していけるような、「自然とそちらに気持ちが向く」ようなチーム。

そこで、僕が最近子どもたちとやりとりした中から、どういうことが子どもたちにとって自然なのか、学んだことを書いてみる。

スコープとタイムボックスと達成感

娘たちに部屋のお掃除をやってもらいたいなー - Mitsuyuki.Shiiba

30分で部屋全体のお片付けをお願いをするといつまでたっても始まらない。でも、3分で1畳分をキレイにしてよって言うとすぐにやってくれる。それを褒めてあげると喜んでくれて、次の畳もささっとやってくれる。そんなことを繰り返してると、あっという間に部屋全体のお掃除が終わる。

確かに「まだ時間があるから」って思って調べものをしたり、タスクを先延ばしにしてしまうことってあるなぁ。で、ギリギリになって焦ってやってしまって、遅れたり、中途半端になったりしてしまう。

だからといって「期間が長くても集中してやるように!」って指示を出したり「みんなの作業効率を管理します!」ってしてしまうんじゃなくて。スコープを小さく切って、タイムボックスを短く切って、それを達成できたらみんなでやったー!して、次のスコープに進む。

そっちの方が楽しく集中してできそう。

隣で一緒に考える

宿題やりなよー(๑˘・з・˘)エーーーーヤダーー - Mitsuyuki.Shiiba

「宿題をやりなさい」って言うんじゃなくて、答えが合ってるか間違ってるかだけを伝えるんじゃなくて、生徒になったり、お友達になったり、ライバルになったりしながら、一緒に勉強を楽しむのが一番身につくなぁって思う。

ペアになったり、モブになったりして、お互いに教え合ったり、一緒に悩んだり、時にはライバルになって競ったりしながら、一緒にプログラミングを楽しむ方が「そこ間違えてるからちゃんとやって」ってレビューで指摘するより楽しく身につきそうかなと思う。

たまに「どんな答えを出したのかを質問して、答え合わせをしてあげる」という人がいるけど、それは「正解じゃなきゃ怒られる」とか「この人が答えを知っている」みたいになっちゃうから、あんまり良くなさそう。

そうじゃなくて「僕はこう考えてるんだけどどうかな?」くらいで一緒に答えを探すんで良さそう。たとえそれが「私もそう思ってた」って今は言われるんだとしても。

苦手な部分と得意な部分

お父さんは時間の感覚をみにつけたいぞ! - Mitsuyuki.Shiiba

子どもの苦手な部分って目につくけど、そこを無理に直させるよりも、得意な部分を褒めてのばす方が良いなって思う。そうすることで、苦手な部分も引っ張られて良くなっていくんじゃないかな。

チームをリードしてるときには、自分が得意でメンバーは苦手な部分が目についてしまうけど、そこは自分がカバーできるんだから、それよりも、そのメンバーが得意な部分をのばして、僕にはできない部分をどんどんできるようになったら、お互いに色んなことをカバーし合えて良さそう。

今できていることを褒めて一歩ずつ

お姉ちゃんは教え上手 - Mitsuyuki.Shiiba

たまに「割り算ができたよ!」ってのを聞いて「お。筆算は?」「(´・ω・`)まだ分からない・・・」ってなったりするんだけど。お姉ちゃんが妹に接してるのを見て「あぁ、ちゃんと割り算ができたことを褒めてあげなきゃ」って教えてもらう。そうよなー、そうじゃないと「やってもやってもまだ足りないって言われる」みたいになるもんね。

今できていることを褒めて、じゃあ次はこれができるようになると良いね!って言えるように頑張ろうと思う。

そんなことを子どもたちに教えてもらった、今日この頃でした。