Obj-Cライブラリ由来のNSExceptionのSwiftでのハンドリング

ずばりこれ。
NSSetUncaughtExceptionHandler(_:) - Foundation | Apple Developer Documentation

swiftのcatchで拾えないものもこちらでハンドルできる。
AppDelegate等に入れておく。

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    NSSetUncaughtExceptionHandler { exception in
        print(exception)
        fatalError() // 適当な処理の後落とす
    }
    return true
}

ただ処理を継続しようとしても落ちるので、fatalError等できちんと落とす。

iOS Simulatorにディスクイメージをマウント

hdiutilからマウントできました。Xcode 10👌です。

ディスクイメージ作成

iOSのシステムが数百MB使用するので、その分は最低限起動に必要です。

# APFS
hdiutil create -size 1g -fs APFS /tmp/ios.dmg
# HFS+
hdiutil create -size 1g -fs HFS+ /tmp/ios.dmg

Simulatorのデバイスにマウント

新しくシミュレータを用意しておいたほうが良いです。

f:id:scior:20181010220514p:plain

マウント先のデバイスのパスは、~/Library/Developer/CoreSimulator/Devices/[Device Identifier]です。

cd ~/Library/Developer/CoreSimulator/Devices/CB63F64D-xxxx
hdiutil attach /tmp/ios.dmg -mountpoint .

起動

起動済みのシミュレーターの場合、XcodeからRunすると1回怒られますが、

f:id:scior:20181011002755p:plain

もう一回Runすると起動できます。

f:id:scior:20181011005612p:plain

iOS(Swift)プロジェクトにSonarCloudを導入する

今回は、静的解析ツールのSonarQubeのクラウド版、 SonarCloudを導入します。

Travis, fastlane導入までは、前回の記事をご参照ください。 scior.hatenablog.com


環境

(追記: 2018/10/8) Xcode 10は❌です。 カバレッジレポートのパスが変わったので現在調査中。
Xcode10⭕️です。

Ruby関連は、

  • ruby 2.5.1p57
  • bundler 1.16.2
  • fastlane 2.104.0

SonarQube

SonarQubeは、静的解析によって、脆弱性やバグ、コードの重複などを診断するサービスです。
他の機能で測定した、Coverage Reportも表示してくれます。
サポートしている言語も多いので、今回Swiftにも導入してみました。

Continuous Inspection | SonarQube

見た目はこのようになっています。
(ほぼ空のプロジェクトなので、クリーンな状態です。)

f:id:scior:20180917223853p:plain

ローカルや自前のサーバーで使うこともできますが、
今回はホスティング版のSonarCloudを利用します。

こちらは、publicリポジトリに対しては無料です。

自前で環境を用意したい方はこちらです。

Downloads | SonarQube

Continuous Inspection

アカウント登録

SonarCloud https://sonarcloud.io/

こちらから、各種ソースホスティングサービス(GitHubなど)と連携して、アカウントを作成します。
登録の際にリポジトリを指定して読み込めますが、後から追加で読み込む際は、
SonarCloudからでは出来ないので、GitHub側から指定します。

GitHubのアカウント設定のApplicationsの画面を開き、

f:id:scior:20180917221523p:plain

Configureからリポジトリを追加します。

f:id:scior:20180917221529p:plain

Select repositoriesで追加したいリポジトリを選びます。

SonarCloudの設定

リポジトリの追加後、この画面に遷移します。

f:id:scior:20180917221535p:plain

適当な名前をつけて、tokenを生成します。

f:id:scior:20180917221538p:plain

上の画像のようにOther, macOSを選択して、sonar-scannerをダウンロードしてPATHを通すと、
一番下のコマンドで、ローカルのソースコードを直接SonarCloudにかけることができます。
(ただし、Swiftの場合、次のsonar-project.propertiesで、
sonar.language=swiftを設定してからでないと、うまく動きません。)

sonar-project.properties

プロジェクトルートにsonar-project.propertiesを作ります。
今回は、MinimumWKWebViewというプロジェクトを例にします。

github.com

# SonarQubeで割り振られるプロジェクトごとのキー
sonar.projectKey=Scior_MinimumWKWebView
sonar.projectName=MinimumWKWebView
sonar.projectVersion=1.0
# 今回はSonarCloudを用いるのでそちらに向ける
sonar.host.url=https://sonarcloud.io

sonar.language=swift
sonar.sources=MinimumWKWebView
# 静的解析の対象を指定する
sonar.inclusions=MinimumWKWebView/**
# カバレッジレポートの場所を指定
sonar.coverageReportPaths=sonarqube-generic-coverage.xml

sonar.projectKeyはSonarCloudに記載されているので、そちらを指定します。

sonar.inclusionsで解析の対象を指定します。
こちらを記述しない場合、fastlaneの.swiftファイルなども解析されてしまい、
ひどい結果になります。

Travis CIとの連携

Using SonarCloud with Travis CI - Travis CI

こちらのTravisのドキュメントを参考に進めていきます。
TravisCUIツールを用いて、先ほど取得したtokenを暗号化します。
(インストール: gem install travis)

travis encrypt [token]

出力された暗号化されたtokenを.travis.ymlに追記します。
organizationはSonarCloudのページに記載されているキーです。

dist: trusty

addons:
  sonarcloud:
    organization: "scior-github"
    token:
      secure: ********

scriptの適切な位置に、sonar-scannerを追加します。

script:
  # -XオプションでDebug出力される
  - sonar-scanner -X

ここまでで、静的解析の結果がSonarCloudに反映されます。

Coverage Reportの反映 (Xcode 9.3+)

xccovの利用

Xcode 9.3からxccovを使って、Coverage測定ができるようになりました。
xcodebuildで生成される.xccovarchivedファイルを、
SonarCloudが解釈できる形にパースして、Travisから渡します。

SonarQubeの解説: Swift Coverage Results Import - Plugins - Doc SonarQube

パースするシェルスクリプトは、下のものを利用します。

github.com

こちらのxccov-to-sonarqube-generic.shを用いて、XMLに変換します。
このシェルスクリプトを、プロジェクトの適当な場所にコピーします。
(今回は./utils/に置きました。)

  • .travis.yml
script:
  - fastlane coverage # 前回のfastlaneの時のスクリプト
  - find . -type d | grep -E  ".xccovarchive$" | xargs -I@ bash utils/xccov-to-sonarqube-generic.sh @ > sonarqube-generic-coverage.xml
  - sonar-scanner -X

fastlaneのビルド結果は、デフォルトではDerivedData云々の、
探しづらい場所に出力されてしまうので、出力先を./Buildに変更します。
(findのところは、-name-execなどお好みでお願いします。)

  • Fastfile
default_platform(:ios)

platform :ios do
  desc "Test"
  lane :test do
    scan(
      derived_data_path: "Build"
    )
  end
end

slatherなど他のコマンドを記述している場合は、そちらにも追記します。

試していないこと

fastlaneにもsonarコマンドがあるのですが、カバレッジの反映まで出来るかどうか、
encryptされたtokenが使えるかどうかなど、不明点が多いので未検証です。

その他参考

SonarQube Integration for Swift – SayTech

Express向けのSwaggerミドルウェア

Express向けのSwaggerパッケージを色々探しましたが、
依存パッケージが少なく、npm auditで引っかからなかった、
こちらを紹介します。

Swagger UI Express

www.npmjs.com

github.com

使い方

ExpresssのRouterと合わせて使うと、このような感じです。

const express = require('express');
// eslint-disable-next-line new-cap
const router = express.Router();
const swaggerUi = require('swagger-ui-express');
const swaggerDocument = require('./swagger.json');

router.use('/', swaggerUi.serve);
router.get('/', swaggerUi.setup(swaggerDocument));

const apiBaseUrl = '/api/v1/';

router.get(apiBaseUrl + 'about', (req, res) => {
  res.send('about');
});

module.exports = router;

yamljsを使うとyamlからも読み込めるので、Swagger Editorでも編集しやすいです。

その他

swagger-node

https://github.com/swagger-api/swagger-node

最近(2018.09現在)更新されていないようで、依存パッケージが古いみたいです。
脆弱性だらけなので使えなそう。

generator-express-no-stress

https://github.com/cdimascio/generator-express-no-stress

Swagger以外にも、ESlintやPinoやBabelを含めた雛形を作ってくれますが、
今回はSwaggerだけ欲しいということで外れました。