Leiningenからclojarsに非対話式にデプロイする


https://github.com/technomancy/leiningen/issues/1349

Mavenリポジトリといえば、[Maven Central Repository](http://search.maven.org/)が広く知られています。Sonatypeにより運営されており、Apache, Codehaus, Sonatypeなどのリポジトリを統合したものです。

Clojure用には、[Leiningen](http://leiningen.org/)の作者らによって作られた、[Clojars](https://clojars.org/)も存在します。Leiningenや[Boot](https://github.com/boot-clj/boot)との連携機能が組み込まれており、これらのビルドツールから容易にjarファイルとPOMメタデータをアップロードすることができます。また、Maven Centralより緩やかな登録ポリシーを採用しており、簡単にプロジェクトを公開できるようになっています。

###Clojarsにアカウントを作成する

```clj 
(defproject lein-zinc "0.1.3"
  :description "Typesafe zinc scala incremental compiler plugin"
  ;...中略...  
  :repositories [["clojars" {:url "https://clojars.org/repo"
                             :username [:env/clojars_username :gpg]
                             :password [:env/clojars_password :gpg]}]]
  :deploy-repositories  [["releases" :clojars]
                         ["snapshots" :clojars]]
  :signing {:gpg-key "868C4511"}
  :profiles {:dev {:global-vars {*warn-on-reflection* true}
                   :dependencies [[expectations "2.0.13"]]}})
```

まず、`:repositories`を定義します。リポジトリ名(任意の名前、この場合は"clojars"）をつけ、`:url`、`:username`、`:password`を指定します。ユーザー名とパスワードは、環境変数からが第一候補、もし指定されてなければgpgで暗号化された、`$HOME/.lein/credentials.clj.pgp`から読み出されます。`:username`、`:password`が定義されていな場合は、コマンドライン上で対話的に入力することになります。

###環境変数経由でアカウント情報を指定
環境変数から値を渡す場合は、下記のように定義します。

```
export CLOJARS_USERNAME=myuserid
export CLOJARS_PASSWORD=mypassword
```

###ホームディレクトリ配下の設定ファイル経由でアカウント情報を指定
まず、`$HOME/.lein/credentials.clj`ファイルを作成し、下記内容を定義します。

```clj
{#"https://clojars.org/repo"
  {:username  "myuserid" :password  "mypassword"}}
```

次に、[GnuPG](https://www.gnupg.org/)でファイルを暗号化します。LeiningenはGnuPGバージョン1を要求するようなので、インストールされていなければシステムに追加しましょう。Mac OS Xであれば、

```bash
$ brew install gnupg
```
です。

```bash
$ gpg --default-recipient-self -e \
    ~/.lein/credentials.clj > ~/.lein/credentials.clj.gpg
```

###Clojarsにアップロード
`project.clj`の`:repositories`で指定したリポジトリ名（上記の例では`clojars`）を引数に渡して下記のコマンドを実行すれば、プロンプトを出さずに、成果物をClojarsにアップロードすることができます。

```bash
$ lein deploy clojars
```

###CircleCIで自動化
以上で、手元のマシンで`lein deploy clojars`を実行すればアップロードできるようになりましたが、完全な自動化のためには、CIサーバ上で実現する必要があります。

もし、お使いのCIサーバが、安全にパスワードを環境変数で管理することができるのであれば、環境変数を用いるのが最も簡単です。例えば、JetBrainsのTeamCityではパスワードを第三者に晒すことなく使用することができます。

別の方法として、`credentials.clj.pgp`をプライベートリポジトリで管理して、CIサーバからチェックアウトして用いるアプローチもあります。ここでは、[CircleCI](https://circleci.com/)を用いてみたいと思います。

* プライベートリポジトリを用意する。Githubであれば、CircleCIは特別な設定なしに、プライベートリポジトリからチェックアウトすることができる。
* 上記の方法で`credentials.clj.gpg`を作成し、下記の`init.sh`ファイルも併せて、プライベートリポジトリにプッシュする。

```bash
    #!/bin/sh

    set -e

    echo "Init env..."
    git config --global user.name "Kenji Nakamura"
    git config --global user.email "kenjin@clazzsoft.com"
    mv ~/dotfiles/credentials.clj.gpg ~/.lein/credentials.clj.gpg
    echo -e "use-agent\ndefault-key kenjin@clazzsoft.com\npassphrase    your_super_secret_passphrase" >> ~/.gnupg/gpg.conf
    gpg --allow-secret-key-import --quiet --import ~/dotfiles/gnupg/secring.gpg
    echo "Done."
```
* プライベートリポジトリをチェックアウトする。CircleCIのPre-dependency commandsに下記の設定を入れる。

```bash
git clone git@github.com:k2n/dotfiles.git ~/dotfiles && . ~/dotfiles/init.sh
/usr/bin/curl -O https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein
chmod a+x lein
```

* Leiningenのdeployコマンドを実行する。

```bash
$ ./lein deploy clojars
```

[lein-zinc](https://github.com/k2n/lein-zinc)の[ビルドパイプライン](https://circleci.com/gh/k2n/lein-zinc/107)がこの手法を用いているので、参考にしてみてください。