My tech diary

ソフトウェアエンジニアをやっています。技術的内容を中心に調べたことを書いていきます。

Git 2.27 での git pull 時の warning について

概要

今更ですが、いつぞや Git のバージョンを上げた後、 git pull したときに、以下の warning が出るようになりました。

warning: Pulling without specifying how to reconcile divergent branches is
discouraged. You can squelch this message by running one of the following
commands sometime before your next pull:

  git config pull.rebase false  # merge (the default strategy)
  git config pull.rebase true   # rebase
  git config pull.ff only       # fast-forward only

You can replace "git config" with "git config --global" to set a default
preference for all repositories. You can also pass --rebase, --no-rebase,
or --ff-only on the command line to override the configured default per
invocation.

いつかちゃんと対処しようと思いつつ、時間が経ってしまったので、ちゃんと対処します。

このメッセージは、検索すると山ほど情報が出てくる通り Git 2.27.0 で導入されたメッセージのようです。 メッセージにあるように、以下の 3 つの設定のうち、いずれかを実施すれば、 warning は出なくなります。

  • git config pull.rebase false
  • git config pull.rebase true
  • git config pull.ff only

特に、今までの動作に不満がないという人は git config --global pull.rebase false をやっておけば、今までの挙動の通り、 warning だけ出なくなります。

まぁ、なのですが、せっかくの機会なので、振り返りを込めて、もうちょっと理解を深めておきます。

git merge の選択肢の理解

git pull というのは、基本的には remote branch の local branch への "マージ" です。

git merge の戦略には、以下の 2 つがあります。

  • merge commit を作成 (3-way merge が行われる)
  • (必要なら merge 対象のブランチを rebase した上での) fast-forward (merge commit を作成しない)

例えば、以下のように main branch と developcommit a 以降で分岐しているとします。

git_merge_base.png

merge commit を作って merge する場合は、それぞれの branch の履歴はそのままに、新たに merge commit m が作られます。

git_merge_merge_commit.png

fast-forward する場合は、 merge commit を作成しないということなので、 develop 分岐後に main branch には何もコミットがされていないことが条件になります。 (つまり main branch が commit a の時点のままなら、そのまま develop を fast-forward merge できる)

git_merge_base_simple.png

そうでない場合は、まず develop の分岐元が main の HEAD コミットである commit d になるように develop の付け替え (rebase) を行います。 develop 側の全ての commit は、元の commit とは別物の e', f', g' になります。 このように、履歴が書き換わるので、コンフリクトにご注意ください。 また、 Git 上はコンフリクトしなくても、コードの意味的・実際の動作上、コンフリクトする場合があるので、テストは必ず行いましょう。 (これは merge commit 作るときも同じですが)

git_merge_fast_forward_1.png

その上で fast-forward を行います。これは main branch の HEAD を commit g' に移動させるだけです。このように履歴の上では一直線になります。

git_merge_fast_forward_2.png

git pull 操作の選択肢の理解

さて、そこで、先程の warning に対処するための 3 つの選択肢を考えたいのですが、その前に、 git pull--rebase option について確認します。 何も指定しない場合は、 --rebase false と同じで、これがデフォルトの動作です。 --rebase を指定した場合は --rebase true と同じです。 他にも rebase の挙動を細かく制御するための --rebase merges, --rebase preserve, --rebase interactive がありますが、割愛します。

git_pull_base.png

通常、 git pull (--rebase を付けない) を行うと、 git fetch を行った上で git merge を行う流れになります。 デフォルトの設定では、 rebase せずに fast-forward 可能な場合は fast-forward を行い、そうでない場合は、先程の図のように merge commit を生成しようとします。

git_pull_merge.png

それに対して git pull --rebase を行うと、 git fetch を行った上で、ローカルブランチ (この例では main branch) の git rebase を行う流れになります。 上述の git merge の際の fast-forward の説明では、 git merge を行うために develop 側の rebase を行ってから fast-forward を実行しましたが、この場合は、 main 側の rebase を行っていることに注意してください。(main - develop の関係が origin/main - main の関係になっているだけで、全く同じことではあるのですが)

こうすることで、リモートブランチにはなんら影響を与えることがないのです。

git_pull_rebase_1.png

git_pull_rebase_2.png

git pull--rebase option の使い所ですが、主に以下の 2 つがあるようです。

  • 同一ブランチに対して、複数人が同時並行で開発を行う場合
    • ローカルブランチを rebase した上で push することで、 merge commit が乱立することを防ぐことができます
  • Pull Request マージ前に、マージ先のデフォルトブランチを取り込んで、テストなどを行う場合
    • 例えば、 Pull Request の feature ブランチにマージ先である main ブランチをあらかじめマージしても、 feature ブランチには merge commit が作られずに済みます (結果的に履歴が綺麗になります)

また git pull の fast-forward 関連の以下の 3 つの option も確認します。 (git merge にも全く同じ option があります) 以下の表にまとめます。 (デフォルトは --ff です)

option fast-forward 可能な場合 fast-forward できない場合
--ff fast-forward で merge する merge commit を生成する
--no-ff merge commit を生成する merge commit を生成する
--ff-only fast-forward で merge する merge せず、エラー終了する

先程の 3 つの選択肢をそれぞれ選んだ場合の挙動

ここまでくれば、 git pull にオプションを付けずに実行したときの動作について、 Git が以下のいずれかを要求していることが分かります。

git config pull.rebase false

デフォルトの挙動です。git pull--rebase option を付けずに実行するのと同じです。 標準動作では rebase せずに fast-forward 可能な場合は fast-forward を行い、そうでない場合は、 merge commit を生成しようとします。

git config pull.rebase true

git pull --rebase を行う場合と同じです。 git fetch を行った上で、ローカルブランチに対して rebase を実施するので、merge commit が作られずに、コミット履歴が一直線になります。

git config pull.ff only

--ff-only option を付けた時と同様、 fast-forward 可能な場合のみ、 fast-forward します。 そうでない場合は、 merge/rebase せず、エラー終了します。

結局

merge/pull の戦略をどうするかは、結局は、チームごとの方針だと思います。 基本的にはチーム内で揃えておいた方が、 Git の履歴を見るときにやりやすいとは思います。人が増えるとなかなかそれも難しかったりしますが。

merge/pull の戦略は、コードの履歴をどうまとめたいかという話であって、現在のスナップショットには特に影響を及ぼしません。 (Git 運用時の操作で問題が起きやすいとかの影響は出るかもしれませんが) 特に致命的な問題はないので、結論としては、悩んだときはデフォルトの設定にしておきましょう😂

References

IaC から始まる幸せなエンジニアライフ

ここ最近忙しく、久しぶりの投稿になってしまいました。 ちょっと前から書きたかった布教用の記事を書きます。 みんなが IaC すれば、世界がちょっと happy になります。。

IaC って何?

ここ 2-3 年、僕が注力した分野の一つが IaC です。

IaC は Infrastructure as Code の略です。 つまり、インフラ構成をコードで管理しましょう、っていうことですね。

その対極にあるのは、インフラ構成を CLIGUI を使って、手動で作成・管理するというものです。 その場合は、しばしば手順書をドキュメントとして残すことになります。

こんなにあるよ! IaC のメリット

IaC のメリットとして、パッと思いつくだけでも、以下のようなものがあります。 (何か語呂合わせにしたいけど、思いつかないのでいいや...)

  • Easy to Reproduce (再現容易性)
  • Easy to View (閲覧容易性)
  • Easy to Destroy (破棄容易性)
  • Easy to Share (共有容易性)
  • Easy to Transplant (移植容易性)
  • Easy to Find (検索容易性)
  • Easy to Review (レビュー容易性)
  • Easy to Rollback (ロールバック容易性)
  • Easy to Refactor (リファクタ容易性)

GUI でポチポチやった時に、上記のいずれもが、かなり難しいことはすぐ理解していただけるかと思います。

特に一番最初の、 "再現性" は非常に重要です。

どうせ、1回作ったら同じものは作らないんだから、 GUI でぱぱっと作っちゃったほうが早いじゃん、という意見。 その断面だけ見たら、至極まっとうで正しいのですが...

でも、僕が大事にしているエンジニアの鉄則によると、そもそもその前提が間違っています。 1度あることは、10度ある のです。 似たような構成は、絶対にまた作ります。会社組織の中でやるなら、あなたでなくても、他の誰かがきっと似たことをやるでしょう。いわんや、世界規模で言えば...

コード化によるオートメーションがもたらす利益こそが、 IaC がもたらす最大のメリットです。

IaC の進化

上記したように、さまざまなメリットがある IaC ですが、その普及を妨げるダメな点が (主観ですが) 一つだけあります。 IaC 関連のツールが成熟していない 点です。学習コストが基本的に高いですし、慣れても、どうしてもある種の使いづらさがあります。

インフラ製品を作っている人は、基本的には IaC のことまで考えて、インフラを作っていません。 IaC 関連ツールを作る人は、常に 既に存在するインフラを、コードの形で記述できるようにする という、後追いの作業を強いられているのです。 それ故に使いにくさが出てくるのだと思います。

ツールの進化について、私の知る範囲で、ちょっと歴史をさかのぼってみたいと思います。 (多々認識がずれているところがあるかもしれません。間違っていたら、ご指摘くださると嬉しいです)

構成管理ツール

もともと、インフラ構成といえば、ハードウェア周りの構築は仕方ないから手動でやって、物理サーバマシン上の (主に) Linux OS の設定と、そこで動作するミドルウェアなどのインストール・設定のことを指していました。故に、基本的には、ツールもその部分の面倒を見てくれるものが中心でした。そのようなツールには、以下のようなものがあります。

  • CFEngine
  • Puppet
  • Chef
  • Itamae
  • Ansible

これらのツールの誕生と並行して、インフラ構成における最も大きな変化が進んでいきます。仮想化技術の登場です。

開発環境での仮想化技術の利用

仮想化技術の利用例の一つが、開発環境を仮想化技術で構築するものです。

一昔前は、これの代表例として VagrantVirtualBox との組み合わせでよく使われていました。ローカル環境で仮想マシンを立てようということです。 複雑な構成の場合、これに、さらに Chef や Ansible などを組み合わせて使うこともありました。

しかし、コンテナ技術である Docker が新たに誕生して以降は、開発環境の IaC には (特に Linux 環境において軽量な) Docker が使われることが増えてきました。 Docker は、今では、持ち運び容易かつ軽量な環境として、開発環境のみならず、本番環境でも普通に運用されるようになっています。

クラウド環境での仮想化技術の利用

仮想化技術の利用例のもう一つ大きなものが、 AWSGCP などのクラウド環境の登場です。

これによって、従来のインフラは劇的に拡張されることになりました。ハードウェア、ネットワーク周りも、仮想化技術によって、ソフトウェアによる制御が可能になり、また、各社が便利なマネージドサービスの数々を提供することによって、従来ミドルウェアとしてインストールして使っていたような類のものも、インフラ構成のパーツとして管理可能になりました。

iac_cloud_resources.png

ベースとして OS (仮想マシン) があって、その上でゴニョゴニョ構築する、という世界を離れて、もう一段、抽象化した世界の上で、インフラを構成できるようになったのです。

このクラウド環境に特化したプロビジョニングツールも、サービスごとに出てくるようになりました。

  • CloudFormation (AWS)
  • Cloud Deployment Manager (GCP)
  • Azure Resource Manager (Azure)
  • Terraform

最後の Terraform だけは、特定のクラウドサービスに特化するものではなく、サービス横断的に利用できるものになります。

そして、1年くらい前には AWS から新手のツールとして CDK がリリースされました。

CDK は、基本的には CloudFormation をラップしたものではあるんですが、もっと良質にクラウド上のリソースが抽象化されており、さらに、完全にプログラミング言語によるコードとして記載することができます。今の僕の推しツールになります。 CDK for Terraform なるものも出てきていますので、 AWS 以外のリソースも構築できるようになりそうですし、今後も要注目です。

命令的な記述と宣言的な記述

プロビジョニングツールの大きな流派の違いに、命令的 (逐次実行的) に記述するか、宣言的に記述するか、というものがあります。

コードの記述が命令的 (Imperative/Procedural) であるというのは、インフラ構成が、最新形になるまでの過程を記述するということです。 Railsマイグレーションに例えるなら、各 migration ファイルだと言えますね。

一方、コードの記述が宣言的 (Declarative) であるとは、過程はどうでもいい(!?)、結果としてどうなるのかを記述するということです。 Railsマイグレーションに例えるなら、 schema.rb, structure.sql です。

この宣言的な記述とおそらく関係があるのが Immutable Infrastructure という考え方です。 ざっくりといえば、この考え方は、インフラの構成は、簡単に破棄・同じものを再構築 (冪等性) できるようにしておき、構成に変更を与えたい場合は、作り直したものに切り替えればいい (Blue-Green Deployment なんて呼ばれる)、ということです。まさに IaC がピタッとはまる考え方ですね。

その考え方で言えば、まさに最新のインフラ構成さえ分かればいいのだから、逐次処理的に書く必要はなくて、宣言的に書けば十分だし、その方がシンプルなわけです。 順を追ってコードを追わなくても、宣言的に書いておけば、「今、どういう構成になっているのか」 (現在のインフラ構成のスナップショット) が、一目瞭然なのです。

ただ、宣言的なコードの場合には、一つ大きな問題があります。 現実的には、コストが高すぎて、なかなか全部を破棄して、再構築したものに切り替える、みたいなことはできないケースがあることです。

Database のマイグレーションの場合も、まさか、毎回全てのデータを移したコピーを作ってから、そちらに切り替えるみたいな暴挙はできません。 それと同じく、複雑なクラウド環境などの場合には、わざわざ全てのリソースを作り直すみたいなことは、現実問題できないことです。 (もちろん、うまく部分部分に切り出せると、その各部分で Blue-Green Deployment のようなことをするという手もありますが)

そうした場合に問題になるのが、宣言的な書き方しか用意していないツールでは、各 "snapshot" 間を移行するにはどうすればよいのかを、ツール側が解析して、解読しなければいけないという点です。そこはツール側任せの部分になります。場合によっては、ここで移行が難しかったり、移行中にサービスのダウンタイムが発生してしまったりしてしまいます。

このツールの気持ちに立って、段階的な移行をかけられるかどうかが、宣言的記述の IaC ツールを使いこなす上で大事なポイントになってきます。 でも、考えてみてほしいのですが、 GUI でやる場合も、段階を追って、ダウンタイムが生じないように移行するのだから、そこはプロビジョニングツールを使う場合も同じです。 一度に変更できない場合は、何段階かに分けて変更を行った Pull Request を作成して、それらを順次デプロイすることで移行すればいいのです。

具体例がなくて、抽象的な表現になってしまいましたが。

でも、宣言的なプロビジョニングツールでも、 Railsマイグレーションと同じく、差分を実装して、その結果として宣言的なコードが吐かれる、みたいな感じでもよいよね、っていうのは思ったりします。

References

私の考える IaC の未来

IaC でいろいろ書いてきて、わたくし思うことがあります。 さまざまなシステムがあるけど、 インフラ構成は、ベースの部分では、共通したものが使われることが多い ということです。

アプリケーションコードもそういうところがあって、だからこそ、ライブラリやフレームワーク的なものが使われてきました。 インフラ構成も IaC が進めば、きっと同じような形になっていくでしょう。テンプレート的に使えるもの、部分的な形で取り込めるものがきっと出てくるのではないかと。 最近たまに見ますが、よく使われる構成の CDK のコードが公開されてくるだけでも、だいぶ助かる気がします。

(2020-10-05 追記) ちょうど Classmethod さんの記事で、ここで書いていたようなパターンが紹介されていましたので、掲載しておきます: AWS CDK+Serverlessのアーキテクチャパターンの実装が勢揃い!CDK Patternsの紹介 | Developers.IO

まぁ、広く言えば (最近あんまり言葉としては使われませんが) SaaS, PaaS なども、コードとして設定管理できる場合は IaC の一種ですし、 Serverless Framework や Amplify, Firebase, Netlify などは、アプリケーションコードと絡めた形で、裏側でゴリゴリ、インフラを構築しますので、その意味では、既にそういうものは出ているのですが、でもそれらはアプリケーションのおまけに過ぎないので、僕の思っているのとちょっと違う。 (構築メインで、その後の保守はあんまり考えられていない気がする)

そういう形ではなく、インフラ面にも注力した、もうちょっとクレバーなプロダクトが出てくることを期待しています。いずれにしても、今は IaC は過渡期でしかないので、その覚悟は必要かなと思います。

蛇足: DaC

ちなみに、私は DaC (Documentation as Code, Docs as Code) も推進しています。完全オリジナルな造語だと思っていたら、ネット調べたら普通にあったです・・・ メリットは、だいたい IaC のそれと同じです。

ということで、この記事も https://github.com/tearoom6/articles で見れます。この記事、全く上手く書けた自信がないので、書き直したいってなった時に、差分が確認できたりします。

References

URL 一覧を Markdown リンク一覧に変換する

一時的に取っておいた URL 一覧を見やすい Markdown の形に変換したいというニーズが生じたため、サクッと行いました。

基本的には References に挙げた Gist を参考にさせていただきました。 ただ、元コードが CORS 制限回避のため crossorigin.me という proxy ツールを使っていたんですが、こちらのサービスサイト (https://crossorigin.me/) がドメイン切れを起こしていたため、代替として CORS Anywhere というツールを使うように変更しました。

モダンブラウザで新規 blank タブを開いた状態で DevTools を開き、 Console に以下のスニペットを打ち込めば、そのまま動きます。 応用すれば、 HTML リンク一覧や、 FacebookTwitter みたいなカード形式での一覧とか、いろいろできそうです。

// Only using native browser features (no jQuery).
// Uses `fetch`, `DOMParser` and `querySelectorAll`.

const urls = [
  // Replace them with what you wanna save.
  'https://dev.classmethod.jp/articles/cdk-over-21-lambda-create-error/',
  'https://github.com/ReactorKit/ReactorKit',
  'https://github.com/date-fns/date-fns',
];

const getTitle = async (url) => {
  return fetch(`https://cors-anywhere.herokuapp.com/${url}`)
    .then(response => response.text())
    .then(html => {
      const doc = new DOMParser().parseFromString(html, 'text/html');
      const title = doc.querySelectorAll('title')[0];
      return title.innerText;
    });
};

const convertToMarkdownLink = async (url) => {
  const title = await getTitle(url);
  return `[${title}](${url})`;
};

const links = await Promise.all(
  urls.map(url => convertToMarkdownLink(url))
);

console.log(links.map(link => `- ${link}`).join('\n'));

References

macOS Docker BuildKit有効化

Docker BuildKit は次世代の Docker のビルドツール。

詳細は他の記事に譲るとして、 macOS の Docker Desktop 最新版 (2.3.0.4) で BuildKit を有効にする方法をメモします。

Docker Desktop の [Preferences] > [Docker Engine] の configuration に以下の内容を記載 (追記) します。

{
  "experimental": true,
  "features": {
    "buildkit": true
  }
}

docker_desktop_configuration_buildkit.png

この内容は ~/.docker/daemon.json に保存されます。

この設定を行っておけば、 CLIdocker command で実行する場合も含めて、自動で BuildKit が使われるようになります。 (DOCKER_BUILDKIT=1 を渡す必要がない)

docker build .

Docker Compose を用いる場合は、引き続き COMPOSE_DOCKER_CLI_BUILD=1 の方は指定する必要があります。

COMPOSE_DOCKER_CLI_BUILD=1 docker-compose up -d

References

MacBookProを修理に出した

会社の MacBook Pro (たぶん MacBook Pro (15-inch, 2017)) を修理に出してきました。

2015-2020 の間に発売されていた MacBook に搭載されていた、バタフライキーボード (Butterfly Keyboards) は、実用上の耐性が非常に低いことが知られており、故障が起きやすいことを Apple 自身が認めています。もともと、構造的に、キーボードの薄型化には有効だったため、 Apple も内部的に何度も改良を繰り返していたようですが、根本的な問題解消には至らず、 2019 より発売の MacBook のモデルでは、 Apple が Magic Keyboard と呼ぶ、シザー構造のキーボード (Scissor Switch Keyboards) が搭載されています。 (バタフライキーボードの以前に搭載されていたキーボードもシザー構造ですので、元に戻った形になります。キーボードの構造が戻ったことで、少し厚くなったらしい)

このような経緯があり、故障したユーザからも非常に不評を買ったため、 Apple の修理プログラムの一環として、以下のモデルに関しては、 MacBook 自体の保証期間が過ぎても、無償でキーボードの修理を行ってくれます。 (2020-07 現在, ただし、後述の通り 購入から4年以内 の場合に限ります)

私もご多分に漏れず、4月以降、 "J", つづいて "F" のキーボードのパネル部分が頻繁に剥がれるようになるという不具合に見舞われ、特に "F" は押しても反応しなくなることが増えたので、堪らず、修理プログラムに依頼することにしました。

このような有様に...

macbook_butterfly_keyboard_broken.jpg

修理プログラムのページから、、 Web 上で手続きを開始でき、以下の3つのオプションが記載されているのですが、コロナの影響なのか、 Apple Store 直営店の予約は、実際には予約のリストが表示されませんでした。そのため、 Apple 正規サービスプロバイダであるビックカメラで、予約を取ることにしました。やはりコロナの影響なのか、予約の空き枠も結構少なかったです。

  • Apple 正規サービスプロバイダ:こちらからお近くの正規サービスプロバイダをお探しください。
  • Apple Store 直営店: あらかじめこちらからご予約ください。
  • 配送修理:こちらから Apple リペアセンターへの配送手配をしてください。

配送修理だと確実にお預けすることになるので、万一サービスプロバイダなら、即日修理の可能性もあるかなと考えたのですが、どうやらおそらくその可能性はほぼないので、めんどくさければ配送修理でも良いかなと思います。

当日、ビックカメラに故障した MacBook を差し出し、見てもらうと、修理に 7-10 日程度かかるので、完了したら取りに来てくださいと言われました。まぁやっぱそうですよね。 しかも、データの紛失の可能性があるので、と念入りに確認され、念書みたいなのを書かされました。まぁやっぱそうなりますよね。 あと、めっちゃファンにホコリが溜まってますと言われました。全部バラしてキレイキレイにしてくれるみたいなので、それはちょっと嬉しい。

しばらく、会社の仕事も、個人の MacBook でやらなくてはいけません。メモリが倍違う (8GB vs 16GB) ので、ひぃふぅ言っています。。 4連休を挟むのがまだラッキーかな。早く修理完了の電話が来るのを心待ちにしています。。


2020-07-29 追記

修理に出した MacBook が返ってきました。 修理を依頼した日が 7/21 (Tue) で、昨日 7/28 (Tue) の時点で修理完了の連絡が来たので、4連休を挟んできっかり 1 週間ですね。

今日、ビックカメラに受け取りに行きました。ご覧の通り、まるで新品のような状態で返ってきました。

macbook_butterfly_keyboard_repaired.jpg

キーボードも実際に触って一日仕事しましたが、バッチリ直っています。 ドキュメントに記載のある通り、キーボード一式とともに、バッテリーまで交換にしてくれているとのこと。一体型になってるとは。

macbook_butterfly_keyboard_repair_detail.jpg

額もすんごいことになってますね。それを無料でやってくれてるのだから、 Apple 的にはまぁまぁ痛い出費に違いない。ハード製品を売るってのはなかなか難しいことだなぁと。

ちなみに、このキーボードの修理プログラムが適用されるのは、購入から 4 年間らしいので、私のこの PC の場合だと 2022-01 までとのこと。この点はご注意ください。

ともかく、データも全く消えたりしてなかったですし、これならもっと早めに依頼しておけばよかったと思った次第です。 (3ヶ月以上 "J" が剥がれる状態で仕事してたからなぁ...)

References

Confluenceで溜まった下書きのゴミを掃除する

Confluence を使う機会があるのですが、 個人の感想 としては、 Confluence は GitHub と並んで、基幹サービスにしては、障害が起きることが多いという印象を持っています。

それで、ある時、 Confluence の Drafts (下書き) 一覧を覗いてみると、なんじゃこりゃ!

confluence_drafts_before_cleanup.png

こんなふうに "Untitled" の下書きが軽く数えた感じ 100 個以上生成されています。

いや、絶対こんなたくさん下書き作ったことないし。断じてない! 基本的には、 サービスやライブラリのバグを疑う前に、己の不肖を疑え、(その上でどうしてもサービス・ライブラリ側のバグっぽい場合は、調査の上、エスカレーションなり、プルリクエストなりを出せ) というのが、できるエンジニアのモットーだと思ってるんですが、いや、今回に限っては、ほんとに断じて、こんな事した覚えないのです。。

きっと、ページが保存できなくなる障害が起きたときに、ページを開きっぱにしていて、こんな風にどんどんゴミができていったのでしょう。

それで、この微妙に手で消せそうな数。手動で消しちゃおうか、という誘惑にも駆られましたが、ここはもう一つのできるエンジニアの鉄則、 1度あることは、10度ある を思い出し、スクリプト書いて消すことにしました。ちょっと面倒でも自動でできるようにしておけば、それ自体が資産になって、次回以降同様の問題に素早く対処できます。

結果的に、以下のようなスクリプトを書きました。

  • USER_NAME はあなたのログイン時の email
  • API_TOKENhttps://id.atlassian.com/manage-profile/security/api-tokens から取得
  • BASE_URL, SPACE_KEY は、対象スペースをブラウザで開いた場合に表示される URL からそれぞれ取得
    • BASE_URL は Confluence Cloud を使っているか、 Confluence Server を使っているか、によってちょっと形式が変わってくると思います
BASE_URL="https://foobar.atlassian.net/wiki"
USER_NAME="hogehoge@fugafuga.com"
API_TOKEN="HIMITSU1X1HIMITSU"
SPACE_KEY="~111111111"
TITLE="" # Empty string means "Untitled"

curl \
  -u $USER_NAME:$API_TOKEN \
  -H "Content-Type: application/json" \
  -X GET "$BASE_URL/rest/api/content?type=page&spaceKey=$SPACE_KEY&title=$TITLE&status=draft&limit=100&expand=body.storage,version" \
  | jq -c '.results[]' \
  | while read -r content;
do
  content_id=$(echo "$content" | tr -d '[:cntrl:]' | jq -r '.id')
  content_view_body=$(echo "$content" | tr -d '[:cntrl:]' | jq -r '.body.storage.value')
  editor=$(echo "$content" | tr -d '[:cntrl:]' | jq -r '.version.by.displayName')
  echo
  echo "ID: $content_id"
  echo "Body: ${content_view_body:0:30}..."
  echo "Editor: $editor"

  echo "Are you sure to delete this draft?"
  select answer in "Yes" "No"; do
    case $answer in
      Yes)
        curl \
          -u $USER_NAME:$API_TOKEN \
          -H "Content-Type: application/json" \
          -X DELETE "$BASE_URL/rest/api/content/$content_id?status=draft"
        break
        ;;
      No)
        break
        ;;
    esac
  done
done

最大100件しか取得してないので、もしそれ以上ある場合は、繰り返し実行してください。複数スペースにまたがっている場合も、その都度実行してください。

一応、用心深く、1つずつ、 BodyEditor を確認しつつ、削除するようにしました。基本的に、自分の編集した、内容が空の下書きのみを削除しました。 もし、えいやっっと一括削除したい場合は、よしなに改変してください、責任は問いません。。

ちなみに途中で tr -d '[:cntrl:]' ってしてるのは、 jq さんが、途中で (ある種の) 改行文字が入っている JSON を正しく処理してくれないため、一括して制御文字を取り除いている、というものです。1回、変数 $content にいれた上で、 echo で出力するタイミングで \n がこんな風に改行文字に変わっちゃうっぽいですね。どうにかできそうだけど、いったん雑に対処。

実行後は、このようにきれいスッキリ。明日からも気持ちよく仕事ができそうです!

confluence_drafts_after_cleanup.png

References

エンジニア家を買う vol.07

Engineer will buy a house vol.07

これは、一介のソフトウェアエンジニア & デザイナーが、マイホームダッド & マミーになるまでを描いた記録である。

前回 vol.6 までで、土地の購入までを書いてきました。 だいぶあいてしまいましたが、今回からは、住宅の設計、建築編です。

設計会社/建設会社選定

さて、土地以上に重要といっても過言ではない、住宅の選択。

結論から言えば、これは非常にすんなりと決まりました。 妻が存分にネットを検索して、いい設計事務所を探してきてくれていたからです。

私がちょっと行けなかった平日に、話を聞きに行ってくれて、やっぱりよかったよ、ということだったので、ちょうど土地の契約をした次の週に、私も話を聞きに行き、確かに良かったので、その場で仮契約しました。

土地の選択の時点で、予算的に大手ハウスメーカーさんの家は無理だというのは分かっていたので、ローコストメーカーさんか、地元の工務店さんの建てる家を選ぶ必要があったんですが、この設計事務所さんは、地元の工務店さんと組んで、デザイン性の高くて、実用的な家をそこそこの価格で建ててくれるというのを売りにしていました。

ここは、私も従来の木造住宅のイメージが変わったポイントなんですが、木造住宅というのは、柱と梁で構造を構成するので、本来間取りの自由度が非常に高いらしいんですね。 壁は間仕切りでしかないという。柱や梁でさえ、デザインの一部として、きちんとやれば直接見える場所に配置することすらできます。 (鉄骨の場合だと、普通むき出しにできない)

確かに言われてみれば、合掌造りみたいな感じの木造住宅は、天井がすっごく高いイメージがある。

その自由度の高さを存分に生かして、吹き抜けや中庭などの、内部的に開放的な家の設計をしてくれるのが、この設計事務所さんでした。 光がたくさん差し込む、開放感のある家を望んでいた我々夫婦は一目惚れしたわけです。

スケジュールや今後の段取りの打ち合わせ

あくまで一時契約だったので、土地契約の際の (次回の記事で後述する) 住宅ローンの審査結果が判明する、だいたい3週間後を目安に、ラフデザインを書いてもらって、その契約を見て正式に契約する流れになりました。

そして、 3 月末に、ラフデザインを見ても、特に不満はなく、正式契約に至りました。

そこで今後のスケジュールに関しての確認がありました。 土地の契約と合わせて、今後は、以下のような流れになるようです。

  • 4-6 月: 数回打ち合わせを重ねて、家の設計図を仕上げていく (同時並行して、独自に住宅ローンを探す場合はその作業も)
  • 6 月末: 住宅ローン融資実行, 土地の代金支払い, 引き渡し
  • 7 月: 住宅施工開始, 建築代金 1 回目支払い
  • 11 月頃: 建築代金 2 回目支払い
  • 12 月?: 住宅完成, 建築代金最終支払い, 引き渡し (待ち遠しい...!)

ネクストアクション

次回も住宅の設計についてのお話です。もはや技術ブログちゃうやん、ってツッコミは置いといてください汗

つづく。

他の "家探し" シリーズの記事は こちら