ikeh1024のブログ

ZennやQiitaに書くにはちょっと小粒なネタをこちらに書いています

証明書周りで参考になりそうなリンク

メモ

  • 証明書の期限が切れる場合は、更新するのではなく新しい証明書を作成するみたい

参考

Swiftで適当なエラーを使いたいときの実装

参考

struct MessageError: Swift.Error & CustomStringConvertible {
  var description: String
}

使用例

  • 実装例
let error = MessageError(description: "hoge")
print(error.localizedDescription)
print(error.description)
  • 出力結果
The operation couldn’t be completed. (iOSEngineerCodeCheck.MessageError error 1.)
hoge

別の案

  • もしくは以下が便利

  • String+LocalizedError.swiftを作成
#if DEBUG
extension String: LocalizedError {
    public var errorDescription: String? { self }
}
#endif
  • 呼び出し例
private func someFunction() throws {
    throw "エラーだよ"
}

do {
    try someFunction()
} catch {
    print(error.localizedDescription)  // エラーだよ
}

forkしたリポジトリを本家リポジトリの最新情報で更新する

概要

  • main(デフォルトブランチ)に関しては下記のようにGitHubから更新可能

image

  • developに関しては下記の手順。
    • 本家のdevelop(upstream)をfetchして情報を取得
    • forkしたdevelopをチェックアウトし、本家のdevelop(upstream)にマージ

参考

SourceTreeで、GitHubでFork/cloneしたリポジトリを本家リポジトリに追従する

SwiftPMの自動アップデート

DependabotはSwiftPMに非対応

Renovate

概要

Renovateの導入デモ

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'GitHubPlayground' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for GitHubPlayground
  pod 'SDWebImageSwiftUI', '1.3.3'

end

RenovateをiOSアプリ開発に導入してみた - dely tech blog 1つのPRでまとめて更新してほしいものをpackageNamesでまとめています。 また、バージョンを更新したくない場合、"enabled": falseを設定することでPRが生成されなくなります(e.g. SwiftLint)

{
  "packageRules": [
    {
      "groupName": "SDWebImage",
      "managers": [
        "cocoapods"
      ],
      "packageNames": [
        "SDWebImageSwiftUI",
      ]
    }
  ]
}
  • しばらくするとRenovateのbotがPRを作成してくれる

image

image

NSSavePanelの保存パスを記憶しているplistの場所

/Users/ユーザ名/Library/Preferences/jp.co.ikeh.Hoge.plist

image

[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"NSNavLastRootDirectory"];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"NSNavLastCurrentDirectory"];
[[NSUserDefaults standardUserDefaults] synchronize];

NSSavePanel *savePanel = [NSSavePanel savePanel];

ArchiveがGeneric Xcode Archiveとなり公証できない問題の対処

概要

  • static libraryを含めるプロジェクトの場合、Archiveがうまく作られずに公証処理に進めない問題。

image

  • ライブラリ側のbuild settingsにてSkip InstallをYesにする必要がある。

image

参考

developer.apple.com The Skip Install build setting is set to YES in your Build Settings pane. Skip Install (SKIP_INSTALL) must be set to YES for static libraries and NO for applications as shown in Figure 3. See SKIP_INSTALL for more information about it.

FileManager.default.urlsの出力結果

概要

  • アプリから何かしらのファイルを保存したい場合、フォルダのパスの取得にurls(for:in:)を使用する。
  • 以下はその際の出力のメモ書き。

参考

出力例

FileManager.SearchPathDirectory Detail Paths
applicationDirectory Supported applications (/Applications). /Users/hogeuser/Applications
demoApplicationDirectory Unsupported applications and demonstration versions. /Users/hogeuser/Applications/Demos
developerApplicationDirectory Developer applications (/Developer/Applications). /Users/hogeuser/Developer/Applications
adminApplicationDirectory System and network administration applications. /Users/hogeuser/Applications/Utilities
libraryDirectory Various user-visible documentation, support, and configuration files (/Library). /Users/hogeuser/Library
developerDirectory Developer resources (/Developer). /Users/hogeuser/Developer
userDirectory User home directories (/Users). (nil)
documentationDirectory Documentation. /Users/hogeuser/Library/Documentation
documentDirectory Document directory. /Users/hogeuser/Documents
coreServiceDirectory Core services (System/Library/CoreServices). (nil)
autosavedInformationDirectory The user’s autosaved documents (Library/Autosave Information). /Users/hogeuser/Library/Autosave Information
desktopDirectory The user’s desktop directory. /Users/hogeuser/Desktop
cachesDirectory Discardable cache files (Library/Caches). /Users/hogeuser/Library/Caches
applicationSupportDirectory Application support files (Library/Application Support). /Users/hogeuser/Library/Application Support
downloadsDirectory The user’s downloads directory. /Users/hogeuser/Downloads
inputMethodsDirectory Input Methods (Library/Input Methods). /Users/hogeuser/Library/Input Methods
moviesDirectory The user’s Movies directory (~/Movies). /Users/hogeuser/Movies
musicDirectory The user’s Music directory (~/Music). /Users/hogeuser/Music
picturesDirectory The user’s Pictures directory (~/Pictures). /Users/hogeuser/Pictures
printerDescriptionDirectory The system’s PPDs directory (Library/Printers/PPDs). (nil)
sharedPublicDirectory The user’s Public sharing directory (~/Public). /Users/hogeuser/Public
preferencePanesDirectory The PreferencePanes directory for use with System Preferences (Library/PreferencePanes). /Users/hogeuser/Library/PreferencePanes
applicationScriptsDirectory The user scripts folder for the calling application (~/Library/Application Scripts/<code-signing-id>. /Users/hogeuser/Library/Application Scripts/com.apple.dt.Xcode.PlaygroundStub-macosx
itemReplacementDirectory The constant used to create a temporary directory. (nil)
allApplicationsDirectory All directories where applications can be stored. /Users/hogeuser/Applications
/Users/hogeuser/Applications/Utilities
/Users/hogeuser/Developer/Applications
/Users/hogeuser/Applications/Demos
allLibrariesDirectory All directories where resources can be stored. /Users/hogeuser/Library
/Users/hogeuser/Developer
trashDirectory The trash directory. /Users/hogeuser/.Trash

Code

import Cocoa

struct Directory {
    var directory: FileManager.SearchPathDirectory
    var name: String
    var detail: String
    
    var commonDirectoryURLs: [URL] {
        let urls = FileManager.default.urls(for: directory, in: .userDomainMask)
        return urls
    }
    
    var descriptionForMarkdown: String {
        var message = "|\(name)|\(detail)"
        
        let urls = self.commonDirectoryURLs
        
        if urls.isEmpty {
            message += "|(nil)"
        }
        
        for (index, url) in urls.enumerated() {
            if index == 0 {
                message += "|\(url.path)"
            } else {
                message += "<br>\(url.path)"
            }
        }
        message += "|"
        
        return message
    }
}

extension Directory {
    // ref: [FileManager\.SearchPathDirectory](https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory)
    // 2022/07/14
    static let allDirectories = [
        Directory(directory: .applicationDirectory, name: "applicationDirectory", detail: "Supported applications (/Applications)."),
        Directory(directory: .demoApplicationDirectory, name: "demoApplicationDirectory", detail: "Unsupported applications and demonstration versions."),
        Directory(directory: .developerApplicationDirectory, name: "developerApplicationDirectory", detail: "Developer applications (/Developer/Applications)."),
        Directory(directory: .adminApplicationDirectory, name: "adminApplicationDirectory", detail: "System and network administration applications."),
        Directory(directory: .libraryDirectory, name: "libraryDirectory", detail: "Various user-visible documentation, support, and configuration files (/Library)."),
        Directory(directory: .developerDirectory, name: "developerDirectory", detail: "Developer resources (/Developer)."),
        Directory(directory: .userDirectory, name: "userDirectory", detail: "User home directories (/Users)."),
        Directory(directory: .documentationDirectory, name: "documentationDirectory", detail: "Documentation."),
        Directory(directory: .documentDirectory, name: "documentDirectory", detail: "Document directory."),
        Directory(directory: .coreServiceDirectory, name: "coreServiceDirectory", detail: "Core services (System/Library/CoreServices)."),
        Directory(directory: .autosavedInformationDirectory, name: "autosavedInformationDirectory", detail: "The user’s autosaved documents (Library/Autosave Information)."),
        Directory(directory: .desktopDirectory, name: "desktopDirectory", detail: "The user’s desktop directory."),
        Directory(directory: .cachesDirectory, name: "cachesDirectory", detail: "Discardable cache files (Library/Caches)."),
        Directory(directory: .applicationSupportDirectory, name: "applicationSupportDirectory", detail: "Application support files (Library/Application Support)."),
        Directory(directory: .downloadsDirectory, name: "downloadsDirectory", detail: "The user’s downloads directory."),
        Directory(directory: .inputMethodsDirectory, name: "inputMethodsDirectory", detail: "Input Methods (Library/Input Methods)."),
        Directory(directory: .moviesDirectory, name: "moviesDirectory", detail: "The user’s Movies directory (~/Movies)."),
        Directory(directory: .musicDirectory, name: "musicDirectory", detail: "The user’s Music directory (~/Music)."),
        Directory(directory: .picturesDirectory, name: "picturesDirectory", detail: "The user’s Pictures directory (~/Pictures)."),
        Directory(directory: .printerDescriptionDirectory, name: "printerDescriptionDirectory", detail: "The system’s PPDs directory (Library/Printers/PPDs)."),
        Directory(directory: .sharedPublicDirectory, name: "sharedPublicDirectory", detail: "The user’s Public sharing directory (~/Public)."),
        Directory(directory: .preferencePanesDirectory, name: "preferencePanesDirectory", detail: "The PreferencePanes directory for use with System Preferences (Library/PreferencePanes)."),
        Directory(directory: .applicationScriptsDirectory, name: "applicationScriptsDirectory", detail: "The user scripts folder for the calling application (~/Library/Application Scripts/<code-signing-id>."),
        Directory(directory: .itemReplacementDirectory, name: "itemReplacementDirectory", detail: "The constant used to create a temporary directory."),
        Directory(directory: .allApplicationsDirectory, name: "allApplicationsDirectory", detail: "All directories where applications can be stored."),
        Directory(directory: .allLibrariesDirectory, name: "allLibrariesDirectory", detail: "All directories where resources can be stored."),
        Directory(directory: .trashDirectory, name: "trashDirectory", detail: "The trash directory."),
    ]
}

print("""
|FileManager.SearchPathDirectory|Detail|Paths|
|---|---|---|
""")

for directory in Directory.allDirectories {
    print(directory.descriptionForMarkdown)
}

Makefileで複数行のコマンドを書くときのセミコロン

概要

  • とても難しい。わかるようなわからんような。
  • 一旦シェルスクリプトで考えるといい。

参考

# Standard
for x in 1 2 3
do
    echo $x
done

# 1 line
for x in 1 2 3; do echo $x; done
.PHONY: test
test:
    @for x in 1 2 3;\
    do\
        echo $$x;\
    done
# Standard
if true; then
    echo "hello"
else
    echo "goodbye"
fi

# 1 line
if true; then echo "hello"; else echo "goodbye"; fi
.PHONY: test
test:
    if true; then\
        echo "hello";\
    else\
        echo "goodbye";\
    fi

SwiftでColorSpaceを扱うときのメモ

まとめ

  • macOS/iOSアプリを作るときはDisplay P3を採用すれば良さそう。
    • より色の表現幅が大きいため。

参考

macOSのRBG指定

  • ある種の条件によっては Deviced にすべきだけれども、広く一般(つまり、common/general user)には Calibrated や NSColor.systemXXX が妥当とのこと?

What's the difference between colorWithSRGBRed vs colorWithDeviceRed vs colorWithCalibratedRed

SwiftUIのプレビューのデバイス設定

SwiftUIのプレビューのデバイス設定

  • 設定方法
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .previewDevice("iPhone 8")
        ContentView()
            .previewDevice("iPad Pro (9.7-inch)")
    }
}
  • 使用できるデバイスは以下で確認できる
  • 例えばiPhone 4sが指定する対象文字列
xcrun simctl list devicetypes
== Device Types ==
iPhone 4s (com.apple.CoreSimulator.SimDeviceType.iPhone-4s)
iPhone 5 (com.apple.CoreSimulator.SimDeviceType.iPhone-5)
iPhone 5s (com.apple.CoreSimulator.SimDeviceType.iPhone-5s)
iPhone 6 Plus (com.apple.CoreSimulator.SimDeviceType.iPhone-6-Plus)
iPhone 6 (com.apple.CoreSimulator.SimDeviceType.iPhone-6)
iPhone 6s (com.apple.CoreSimulator.SimDeviceType.iPhone-6s)
iPhone 6s Plus (com.apple.CoreSimulator.SimDeviceType.iPhone-6s-Plus)
...

macOSアプリ→Sentry→Slackの連携を考えたときのメモ

概要

  • macOSアプリ→Sentry→Slackの連携をしようと思ったけど、SentryとSlackの連携は有償プランなので諦めた。
  • 忘備録としてメモだけ残す。

Memos

    @IBAction func buttonTapped(_ sender: Any) {

        let event = Event(level: .warning)
        event.environment = "develop"
        event.message = SentryMessage(formatted: "Sentry Message \(12)")
        event.extra = ["at": "\(#function),\(#line)"]
        SentrySDK.capture(event: event)
        
        do {
            try doSomething()
        } catch {
            SentrySDK.capture(error: error)
            return
        }
        SentrySDK.capture(message: "Task Completed!")
    }
    
    func doSomething() throws {
        throw NSError(domain: "さんごさんご", code: -1, userInfo: nil)
    }

Xcodeのアップデートが進行しているかどうかを確認する方法

概要

  • Xcodeのアップデートがいつまで経っても終わらない、ということが偶によくある。
  • しかし下記を見ても表示がざっくりとしていて、進捗があるかどうか分からない…

image

image

  • 具体的に進捗は何%なのかと知りたい…!

アップデートの進捗を確認する方法

  • コンソールを開き、右上にApp Storeと入力し絞り込む
  • メッセージのCompleted: xxx of 1000で進捗が確認できる

ScreenShot_2021-11-01_16_37_20

  • 数字が進んでいれば、進捗があることが確認できる

ScreenShot_2021-11-01_16_37_26

  • 800/1000から進みが遅くなり、そこから5時間ほどかかった…。
  • 一見止まっているのではと思ってしまうので、数字で進捗が見れるとまだ放置していいと分かり精神衛生上良い。

参考

「The DevOpsハンドブック 理論・原則・実践のすべて」の感想

本書の感想まとめ

  • DevOpsで検索しても概念的なところの説明だけで、イメージが全く掴めなかったが、本書を通してやるべき事柄の大枠が見えるようになった(気がする状態なので、あくまで実践しないと効果なさそう)
  • DevOpsとは現代のIT開発の仕事の進め方の基礎になっていて、導入することで利益だけでなく開発者の質・セキュリティレベル・プロダクトの改善率など総合的に向上させることができる
  • またDevOpsは単にツールを導入するだけで達成されるものではなく、タスクの進め方や組織のあり方など地に足をつけた改善も必要
  • 正直ツール類や横文字の分からない用語・馴染みのないデプロイライン周りの話があり、中盤から目が滑りがちになった…。
    • こちらの理解には具体的な実践を必要と感じた

目次:The DevOpsハンドブック 理論・原則・実践のすべて

序章 DevとOpsがDevOpsになる世界を想像してみよう

  • あらゆる人の時間を貴重なもの(資産)として捉える
  • DevOpsによって実現できること
    • コードのデプロイ数
    • デプロイリードタイムの短縮
    • 本番デプロイの成功率
    • 問題時の復元にかかる時間の短縮
    • 生産性・利益率の目標の達成率
  • デベロッパが増えると生産性は普通は下がるが、DevOpsにより容易にデプロイできる環境では線形に増える

第1部 3つの道

  • 習慣として業務改善を実践する構造を作り出さないといけない

第1章 アジャイル、継続的デリバリー、そして3つの道

  • 🐱

第2章 第1の道:フローの原則

  • 制約条件の改善
    • 個人で環境作成できるorいつでも使える環境がある状態にする
    • テストの自動化・並列実行
    • アーキテクチャ疎結合にして安全に変更できるようにする
  • 継続的な学習により、日々の業務から苦痛と重労働を取り除く
    • 余分な処理: 顧客のために付加価値を産まないプロセス

第3章 第2の道:フィードバックの原則

  • 問題解決はコードの修正からなるべく早いほうが良い、デベロッパが反省しやすくなる。素早いフィードバックが大事。
    • テストの自動化
    • リアルタイムの問題発見

第4章 第3の道:継続的な学習と実験の原則

  • 改善したいが無関心という厚い壁がある
    • 日業業務の一部として新しい改善を行う→そういう文化が必要
  • ヒューマンエラーを追求しない
    • ミスは研究、調査のきっかけ
    • 再発防止のためにシステムをどのように作り直すかを追求する
  • インシデント発生→非難のない事後検証をするといい
  • 「日業業務よりも大切なのは、日常業務の改善だ」
    • 以前よりも弱い兆候から問題を見つけ出し、修正できるようになる
  • リーダーとワーカーの協業が必要
    • リーダー: チームが業務内で改善を見つけ出してくる環境をつくる
    • ワーカー: 自身の作業分野で問題を見つける。権限がないのでリーダーに共有して実行してもらう。

第2部 スタートのための糸口

第5章 最初に手を付けるバリューストリームの選択方法

  • グリーンフィールド: 新規アプリケーションの開発環境
  • ブラウンフィールド: 既存アプリケーションの開発環境
  • DevOpsの改善ストーリーの60%はブラウンフィールド
  • 最初の導入時期は小さいグループで早期の成功を目指す

第6章 バリューストリーム内の作業を理解し、それを可視化して、組織全体に広げる

  • バリューストリーム: 改善に必要な項目を洗い出す
  • 改善が必要な作業を一人で把握している人はいないので、全てのメンバーを明らかにして情報をまとめる
    • 他のチーム等の待機が必要な場所
    • 大量の手戻りが生まれる所
  • 明確な改善の目標をたてる
    • e.g. コードのチェックインから本番リリースまでのリードタイムを1週間以下にする
  • 改善のイテレーションは2-4週間で
  • 20%を開発・運用サイクルの改善にあてる
    • 顧客からは見えないポジティブな価値
    • 技術的負債を増やさないために
    • いわば20%税
  • 技術的負債を改善するとリードタイムと品質が劇的に改善される

第7章 Conwayの法則を念頭に置いた組織とアーキテクチャの設計

  • Conwayの法則: 「システムを設計する組織は、そのコミュニケーション構造をそっくりまねた構造の設計を生み出してしまう」
  • 職務指向(専門分業)
    • 開発チームの増大・デプロイの回数が増えると結果が振るわなくなる
  • 市場指向
    • 毒力で安全に仕事を進められる小さなチームを編成
    • DevOpsの成果が得られる
  • 職務指向でも、部門間の連携がスムーズに協力できていればいい結果が残せる
  • 全てのメンバーがジェネラリストになることを推奨する
  • ポジティブな破壊(既存の障害を排除)できる人材が良い
  • Conwayの法則に従って、チームを小さく保つ
    • two-pizza rule: ピザ2枚で満足できるチーム人数。5-10人

第8章 開発の日常業務に運用を統合してすばらしい成果を生み出す方法

  • 市場指向の成果を生み出すには…
    • 生産性の上げるツールの標準化をする
      • チームが異動しても高い生産性を保つ
    • 製品チームに運用エンジニアを配置する
      • 運用の知識・専門能力をチームに広げる
      • 知識を自動化コードという知見で残せる利点
  • 運用な製品のバリューストリームの一部、大切にする

第3部 第1の道:フロー改善の技術的実践

第9章 デプロイパイプラインの基礎の構築

  • 本番と同じ環境は自動的に作成できないといけない
    • Git管理されているものを基礎として完全な本番環境を再現するのが目標
  • 全ての成果物をGit管理する
    • コードよりも環境設定が変わることのほうが何桁分も多い
    • 運用・QAに渡って全てのメンバーが使用する
  • 本番環境の手作業の修正を許さない
    • ゼロから新しく作り直す意外の方法を許さない
    • 本番環境に差異が生まれることが無くなる
  • 完成の定義を変える: 本番に近い環境で実証された段階で初めて完成とする

第10章 高速で信頼性の高い自動テストの実現

  • テストがないとき
    • 恐怖で変更を加えるのをやめてしまう
  • ユニットテストで大半のエラーを検知したい
    • ただ我々はマニュアルテストやインテグレーションテストに重点を起きがち
  • テストが書きにくい場合は、アーキテクチャが密結合の可能性がある。疎結合なシステムを作りたい。
  • パフェーマンスの低下を防ぐため、パフォーマンスのテストを追加する
  • 非機能要件のテスト
    • 環境が正しく構成されているか

第11章 継続的インテグレーションの実現と実践

  • テスト自動化がないと新機能の開発に使える時間が無くなってしまう
  • 以下に開発者が優秀であろうと、CI/CDがなければ生産性を上げるのは難しい
  • Selenium回帰テストのツール例として挙げられる
  • CIによりある程度安全に変更を加えられるようにしたい
  • トランクベースなGit運用を行う
    • Git-Flowで充分だろうか
  • CIはとてつもなくメリットが高いことを知ろう

第12章 自動化とローリスクリリースの実現

  • 機能変更をより多く加えたければ、デプロイを増やす必要がある
  • CIによりコードデプロイのリスクと作業工数を少なくする
  • 自動化には、デプロイプロセスのステップを"完全にドキュメント化"する必要がある
    • バリューストリームマッピングの実施や更新されるドキュメント(wiki)を使う
  • ドキュメント化のあとはプロセスの単純化・自動化を図るだけ
  • ダークローンチ(機能のトグル)という手法も有効

    https://www.infoq.com/jp/news/2021/08/dark-launches-best-practices/ ダークローンチとは、新しい能力や機能を公的に発表する前に、システムに対する付加的ロードやパフォーマンス上の影響を測定するという、デプロイメント戦略のひとつで、一般的にエンドユーザが感知することはない。

第13章 ローリスクリリースのアーキテクチャ

  • 絞め殺しアプリケーションパターン(strangler application)が、既存アーキテクチャの改善に有効

第4部 第2の道:フィードバックの技術的実践

第14章 問題の可視化と解決のための基礎となる遠隔測定データを作り出す

  • 一人の人間でシステム全体を理解することは無理
  • 遠隔測定データを継続的に生成するシステムを作る
    • 問題がどこにあるかすぐに発見・対処できる
    • パフェーマンスの低下も改善できる
    • 全体の健全性を確かめることができる
    • 組織全体で簡単に見れるようにする
    • 致命的な障害を起こす前に兆候にきづける
  • ものの追跡を簡単にする
  • 共通サービスに全てのログを送って一元管理するのが望ましい
  • 作成、運用するアプリではすべての機能を測定すべき
  • 同様にビジネス指標のグラフも取ると良い
    • 問題の

第15章 遠隔測定データを分析して問題の予測と目標の達成に活かす

  • データ分析に、外れ値検出や標準偏差を使うことができる
  • 正規分布に従わないカイ二乗分布の場合も、FFTや線形回帰で対応できる
    • スパイク値とかでもいい感じに処理できるよ、くらいの理解…
  • KS検定により一見抽出しにくいような異常値も検知できる

第16章 フィードバックループを実現して開発と運用が安全にコードをデプロイできるようにする

  • 遠隔測定の仕組みにより、問題を早期に発見できる
  • ステージングでエラーを捕捉するのが理想だが、どうしてもできない部分もあるので遠隔測定でカバー
  • 遠隔測定に関するリリース定義をしておくと良い

第17章 日常業務に仮説駆動開発とA/Bテストを組み込む

  • 長期間開発しながら望ましい成果が得られたかどうかを確認しないことが多い
  • A/Bテストしよう
  • ユーザリサーチをしない場合、1/3の機能しか指標が向上しない
  • A/Bテストを反復的に実施するには、遠隔測定の整備が必要
    • 機能トグル
  • A/Bテストを頻繁に実施しフィードバックのサイクルを早める
    • 価値のある改善案が早く見つかる、その結果デプロイの回数を増やすことができる

第18章 レビューと調整プロセスによって現在の仕事の品質を上げる

  • GitHub FlowによるPRのススメ
  • コードレビューのススメ
  • ペアを組んだ場合仕事のペースが15%下がるが、エラーフリーコードは70->85%に上がる
  • ペアプログラミングは楽しい、教え/教えられる効果的な方法でもある
    • コードレビューのつなぎの方法としても有効

第5部 第3の道:継続的な学習と実験の技術的実践

第19章 日常業務での学習の実現と日常業務への学習の注入

  • ヒューマンエラーは間違いの原因ではなく、必然的な結果
    • システムでの対策が必要
  • 反省の場では「だったはず」「できたはず」を明確に禁止する
  • ポストモーテムのドキュメントは共有の場にドキュメントを残しておく
    • 似た事例のときにそれが読まれ研究される
    • ドキュメントの作成を簡単にすることで、内容に注力できより細かい記録がされる
  • 失敗は下図ではない。変更の頻度が30倍にし失敗の割合を半分に押さえることが優秀
  • 本番環境で環境を壊すテストを行い、見えていなかった問題をあぶり出す
    • 日常的に避難訓練をして、障害が日常的なものにしてしまう

第20章 一部門の発見を全社的な進歩につなげる

  • チャットにBotをいれると、業務の軌跡になり共有するために効果がある
    • 全社的に情報共有することができる
    • チャットが給湯室になる
  • 組織で共有するリポジトリを作る
    • 全社員の専門能力を活用できる価値
  • テストスイートが、システムの生きた最新の仕様書になる
    • システムの使い方を知りたい場合は、テストスイートの中で生きた事例を見つけられる

第21章 組織的な学習と改善を生み出すための時間を確保する

  • 強制的に、日常業務の改善をするだけの時間をとる
    • 期間を決めて、終わりには取り組んだ問題を発表してて議論する
    • そうして日常的に改善する文化を作る
  • 社内で同僚に教えたり、改善専門のチームを作っても良い
  • 日常業務の中で全員が互いに教え合い、学びあう

第6部 情報セキュリティ、変更管理、コンプライアンスを統合するための技術的実践

  • セキュリティ管理に関しても日常業務に組み込む

第22章 すべてのエンジニアの毎日の職務として情報セキュリティを位置づける

  • 開発・運用・情報セキュリティ人数の比率は100:10:1
  • 開発と運用の日常業務に、自動化された状態でセキュリティが組み込まれる必要がある
  • 共有リポジトリに、情報セキュリティが推薦したライブラリ・サービスを加える
    • 間接的に情報セキュリティのガイダンスを使うことになる
  • 開発と運用にセキュリティのトレーニングを提供するのも良い
  • 情報セキュリティが、開発が作ったもののレビューをしてもいい
  • デプロイライン・自動テストにセキュリティに関するものを含める
  • コードの静的テスト、パフォーマンスなどの動的テスト
  • 情報セキュリテイの目的でも、遠隔測定のデータを集めると良い
  • 実際にサービスが攻撃をうけているのを見ると、デベロッパのセキュリテイの意識が劇的に上がる
  • CI/CD自体のセキュリティを担保する
    • テストに関してもコードレビューをする

第23章 デプロイパイプラインを防御する

  • 自動テストや本番環境のモニタリングにより、マニュアルの変更承認プロセスを必ず通さなくても良いようになる
  • 承認組織に説明の書類、RFCのためのフォームを用意する
  • 承認を省略するため、CABに変更がローリスクであることを説明する
    • 特定の期間で履歴をみて起きた問題をリストアップして、それをもとに説明をする
    • 履歴は結果が自動的に記録されるようにしたい
  • Gitのコミットのコメントに、課題のチケット番号を書き込むと履歴を追いやすくて良い

行動提起:DevOpsハンドブックの締めくくりに

  • DevOps改革によって…
    • 学習するダイナミックな組織を生む
    • フローの速さ・高セキュリティを達成
    • 競争力とシャインの満足感が上がる仕組み
  • 実現には各部門の連携が必要
  • DevOpsはITの仕事のあり方・企業としての必須事項になっている

GitHubのSSH接続設定

追記(2023-11-15)

概要

  • 下記の通りはよ対応しろと言われたのでSSH接続の設定を行った
Hi @xxx,

You recently used a password to access the repository at (unknown) with git using git/2.30.1 (Apple Git-130).

Basic authentication using a password to Git is deprecated and will soon no longer work. Visit https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/
Permission denied (publickey). fatal: Could not read from remote repository.

ssh-add -K ~/.ssh/id_ed25519

ssh-add -K ~/.ssh/id_ed25519