もちゅろぐ

iOSやSwift、モバイル設計だったりRailsについてまとめていく

CircleCIで別途SSHキーを追加して使う方法

最近CircleCIを使って定期実行的なことをするために弄り始めました。

CircleCI が自動で生成&登録してる鍵は read-only

CircleCIを使ってサーバーにデプロイしたい場合やGitHubへpushしたい場合は、 自動生成&登録されるSSH Keyでは権限が足りずエラーになります。

別途SSH Keyを登録して利用することで上記のような目的を達成できるようになります。

手順

  1. ssh-keygen -m PEM -t rsa などで鍵生成
  2. GitHubのrepository設定のdeploy keyに公開鍵を登録
  3. repository毎の設定 > PERMISSIONS > SSH Permissions へ移動
  4. Add SSH Key を押下
  5. ホスト名を github.com
  6. Private Keyに秘密鍵を登録
  7. .circleci/config.yml の steps 内で add_ssh_key コマンドを記入

add_ssh_key に関してはこちら参照。 記事中に出てくる Fingerprint は GitHubかCircleCIのrepository設定ページで確認可能。

関連

CircleCIにSSH Key登録が失敗する場合はこちらをどうぞ mothulog.hateblo.jp

CircleCIでSSH Key登録が失敗する場合の原因特定方法と自分が見つけた解決方法

最近CircleCIを使って定期実行的なことをするために弄り始めました。

CircleCIの簡単な説明

CircleCIはGitHubのレポジトリベースで管理されており、セットアップすると自動でread-onlyの鍵がGitHubの対象レポジトリに登録されてます。 これによりCircleCIがGitHubのレポジトリをgit pullして取得したコードのテストを実行できるようになります。

自分が試したかったのは少し違う

自分がやりたかったのはgit pull後にテストではなくバッヂスクリプトを走らせた後に 成果物を再度対象レポジトリにgit push することでした。

自動で登録される read-only な鍵では足りないので新たに鍵を追加する必要があります。 そのさいに何故か秘密鍵が登録できず失敗になって躓いたのでその時に調べたことを紹介しようと思います。

SSH Key 追加画面 f:id:motom552:20181126162504p:plain

エラーはブラウザコンソールに出る

f:id:motom552:20181126163343p:plain

エラーになると失敗しか表示されず一見まったく原因が分からないですが、 ここでエラーになったらブラウザコンソールでエラーログに失敗要因が表示されてます。 Chromeであればoption+command+iで呼び出せます。

自分が躓いたのはエラーログでは分からず

しかし自分が躓いたのはエラーログが単純に400が変えるだけで詳しい原因が分からなかったのですが、 次の方法で解決できました。

SSH Keyを登録する時に

$ ssh-keygen -t rsa -b 4096 -C "メールアドレスなど"

のようなコマンドだと思いますが、これに -m PEM をつけて強制的にPEM形式にすることで無事登録できました。

$ ssh-keygen -m PEM -t rsa -b 4096 -C "メールアドレスなど"

参考

discuss.circleci.com discuss.circleci.com

クラス名にSimpleやEasyがついててもクラス内コードが単純なわけではない

クラス名は目的やできることや塊を表現する。
そのためクラス名にSimpleやEasyがついてる場合

  1. 提供してる機能自体がシンプル
  2. 提供してる機能の使い方がシンプル
  3. 保持してるデータ構造の名前が「シンプル」とネーミングされている

と少なくとも3つの解釈ができる。

ここで、クラス名にSimpleだからといってクラス内コードがシンプルと思うのは、
設計において

  • 「できること」とその「実現方法」の隠蔽化による関心ごとの分離を理解できていない
  • クラス名の活用意図を間違えている

と言える。どの解釈においてもコードがシンプルと断言には至らない。

「3.がそうじゃないのか?」と思っても、仕様・要件上「シンプルな方」だからシンプルと名付けてるだけであって 絶対にコードがシンプルになるわけではない。

データ構造がシンプルだからコードもシンプルと言うのは、偶然コードもシンプルになりやすいだけである。

提供してる機能自体がシンプル

何か高機能なサービスをラッパーして使いたい機能のみを提供するクラスなどによく見かける。

提供してる機能の使い方がシンプル

スレッド操作や並列処理、直接扱おうとするとコードが複雑になり、ボイラープレートコードなどで埋め尽くされるのを1つのクラスに隠蔽化することで、手段を簡単に扱えるようにさせる場合に使われやすい。

保持してるデータ構造の名前がシンプル

データクラスにおいて保持するデータ構造の名前が「シンプル」とついてる。つまりドメイン用語でシンプルとついてる。

RailsのController内におけるエラーハンドリングのベストプラクティスについて調べてみた

概要

  • 各APIControllerでエラー検知とエラーレスポンスを書くのDRY違反してる
  • エラーレスポンスは構造が統一できていないとクライアント側が死んでしまう
  • Applicationで一律例外検知してエラー内容をハンドリングしたほうが楽

C#のASP.NET MVC5ではController毎に例外キャッチなどはせずApplicationで一律ハンドリングするので、 Railsにも同様の機能は提供されていると思う。

その方法を調べると同時にRailsにおけるベストプラクティスを知っておこうって思った。

Applicationで一律例外検知してハンドリングする方法

  • ApplicationController で rescue_from メソッドを使う
  • 404や500は 専用Controller用意とroutes.rb更新してconfig.exceptions_app = routesでカスタマイズする

ベストプラクティス

  • ExceptionではなくStandardErrorをキャッチする
  • 各ControllerではなくApplicationControllerでハンドリングする
  • エラーハンドリング処理はApplicationControllerから分離する
  • Custom Errorでエラー情報の詳細化を助ける
  • アプリケーションエラーとシステムエラーは分けるハンドリングする
  • アプリケーションエラーはユーザーフレンドリーを目指す
  • システムエラーはデベロッパーフレンドリーを目指す

  • 参考サイトA

  • 参考サイトB

XcodeのPlaygroundが動かないとか遅いとか不安定な場合は新しく作り直すといい

過去に作ったPlaygroundのままだと動作が変だよって話。

自分もだいぶ前に作ったPlaygroundをちょっとしたコード動かしたい時にXcodeプロジェクトが立ち上がった状態 Playground を立ち上げてコード書いてた。

だけど以前から Playgroundがずっと何かを処理中のまま止まって、再起動しないと動かないことが頻発してた。

試しに現バージョンのXcodeから新しくPlaygroundを作り直したら、今までの不安定な動きは見せず快適になった。

Playgroundが重いな、動かないな、不安定だなって感じる人がいたら試してみるといいです。

Optional<String>をExtension化したのにエラーになって役に立たない

事の発端

nil結合演算子コンパイルが重くなる要因だし、見た目としてもよくないから解決したいと考えてた。

そこで Optional を拡張してそのコードを次のようにカプセル化した。 これなら nil結合演算子も使わずにコード量も抑えられる。

extension Optional where Wrapped == String {
    var orEmpty: String {
        guard let value = self else { return "" }
        return value
    }
}

だけど実際のコードではエラーになる

let url: URL? = URL(string: "https://hogehogex.jp")
url?.absoluteString.orEmpty // Value of type 'String' has no member 'orEmpty'

エラー説明見ると String に orEmpty がないと言われてるので試しに用意してもダメ。

extension String {
    var orEmpty: String {
        return self
    }
}

let url: URL? = URL(string: "https://hogehogex.jp")
url?.absoluteString.orEmpty // Value of optional type 'String?' not unwrapped; did you mean to use '!' or '?'?

こっちみたいに一度格納すると認識する。

let value: String? = url?.absoluteString
value.orEmpty // OK

結局これだとほとんどのケースで無駄にコード量が増えるので役に立たなかった。

言語不具合

Swiftコードを見たことないけど、これバグだよな。 nilの伝搬とメソッドの評価順が逆なんじゃないかと思う。

App Store へのアップロードでThere was an error sending data to the iTunes Store. Scheduling restart shortly が出たとき自分はこれで解決した

f:id:motom552:20180405031818p:plain

いつもと同じ手順でXcodeのOrganizerでApp Storeへアップロードしたら次のエラーが出ました。

There was an error sending data to the iTunes Store. Scheduling restart shortly...

考えてみた所いくつか前回と異なる点がありました。

いつもと違うところ

  • Sierra から High Sierra にバージョンアップした
  • iTunes Connect や Xcode 内 Accounts がログイン期限切れしてた

おそらく一番の要因は最初のOSバージョンだと思います。その次のログインの期限切れも影響していると思います。

やったこと

  • 時間を置いた(約4時間)
  • iTunes Connect に入ったら何故か認証エラーになっていたので再ログインした

2つ目が正直謎です。 というのもアップロードする前に対象バージョンの枠を作るために一度 iTunes Connect に接続できているためです。

確実な解決方法は分かっていませんが、同様に起きている場合は一度認証が必要な箇所を一通りチェックしてみてはいかがでしょうか?