Travis CIとcopr.fedoraproject.orgを使ってrpmをビルド・配布するのを試してみた
2015-12-15 追記
nginxのカスタムrpmをmockでビルドできることを確認してからcoprでビルド・配布する環境を作りました · hnakamur’s blog at githubという記事を書きましたのでそちらもご参照ください。
はじめに
CentOSを使っていると、パッケージのバージョンが古いのでspecファイルを改変してrpmをビルドすることがちょくちょくあります。 一度ビルドした後は、自作rpmのレポジトリサーバを立ててそこに置いておくのが本来は良いんだろうなと思います。 ですが、サーバの運用の手間を考えると面倒だなと思って、AnsibleやDockerでのプロビジョニング中にビルドするようにしていました。
fedora projectのcoprというサービスを使うと、自分でサーバを用意しなくても 自作rpmのビルドとホスティングが出来ることを知り、試してみました。
今回試したサンプル
githubのレポジトリはhnakamur/nodejs-rpmにあります。Node.jsをビルドするrpmです。
specファイルはkazuhisya/nodejs-rpmのをほぼ流用しています。ありがとうございます!
一点変更したのはダウンロードするNode.jsのソースのtarballを node-v*.tar.gz
ではなく node-v*.tar.xz
にしています。
coprについて
coprに説明があります。FAQのHow is Copr pronounced?によると、銅(copper)と同じでカッパーと発音するそうです。
How long do you keep the builds?によるとプロジェクトごとに最後に成功したビルドだけが保持されて、古いバージョンのビルドや失敗したビルドは14日後に削除されるそうです。
ですので、古いバージョンも残しておきたい場合は、coprは使えません。その場合は自前でレポジトリサーバを立てて運用するしかなさそうです。
参考: coprのウェブ管理画面にsrpmをアップロードしてrpmをビルドする手順
ScreenshotsTutorial – coprにcoprのウェブ管理画面からsrpmをアップロードしてrpmをビルドする手順がスクリーンショット満載で説明されています。
今回試したビルド手順の流れ
今回試したビルド手順の流れは以下の通りです。
- githubのプロジェクトにspecファイルを置きます。
- git pushしたときにTravis CIでdockerコンテナを動かしてsrpmを作ってcoprに投入します。
- coprでrpmをビルドしてホスティングしてもらいます。
事前準備
Fedora account 登録
まずは Sign up for a Fedora account からアカウント登録します。手順はメモしてなかったので省略します。
私のアカウントのログイン後の「アカウントの詳細」のページを見ると「あなたの役割」のところにSigned CLA GroupとSigners of the Fedora Project Contributor Agreementという項目があり、共にステータスが「承認されました」となっているので、これらの申請の手順が必要だったと思います。
承認されるまでしばらく時間がかかって、その間にrpmをビルドしてみたら署名されないことがありました。今ではプロジェクトごとに鍵が自動生成されてrpmが署名されるようになっています。
Travis CIのプロジェクト作成
Travis CI上にhnakamur/nodejs-rpmプロジェクトを作成して、githubのレポジトリhnakamur/nodejs-rpmに対応付けておきます。手順はメモしてなかったので省略します。
Travis CIでdockerでコンテナを動かしてsrpmを作る
Travis CIでdockerを使う方法は Using Docker in Builds - Travis CI で説明されています。
試行錯誤の結果、以下のような .travis.ymlを作成しました。
sudo: required
services:
- docker
branches:
only:
- master
- LTS
install:
- docker build -t hnakamur/nodejsrpm .
script:
- case $TRAVIS_BRANCH in master) project=nodejs5;; LTS) project=nodejs;; esac
- docker run hnakamur/nodejsrpm "$COPR_LOGIN" "$COPR_USERNAME" "$COPR_TOKEN" "$project"
hnakamur/nodejs-rpmでは、mainブランチでNode.jsのv5.x (Stable)、LTSブランチでNode.jsのv4.x (LTS)のspecファイルを保持しています。
coprは上記の通り1つのプロジェクトで複数バージョンは保持できないので、 hnakamur/nodejs5 Copr と hnakamur/nodejs Copr の2つのプロジェクトを作ることにしました。
Environment Variables - Travis CIによると TRAVIS_BRANCH
環境変数でgitのブランチが取得できます。ブランチ名に応じてプロジェクト名を切り替え、 docker run
で呼び出すスクリプトの引数に渡しています。
COPR_LOGIN、COPR_USERNAME、COPR_TOKENの3つの環境変数ですが、Fedora accountにログインした状態で API for Coprにアクセスし表示された値を使います。表示されているのはcoprのコマンドラインクライアント copr-cli用の設定ファイル ~/.config/copr
の内容です。
APIのアクセストークンなどは秘密にすべき情報なのでgithubのレポジトリ内のファイルには含めてはいけません。
そこでこれらの値はTravis CI上のhnakamur/nodejs-rpmプロジェクトでDefining Variables in Repository Settingsの手順に従って設定しておきます。
プロジェクトの管理画面の右上の[Settings]/[Settings]メニュー (このメニューはプロジェクトの管理者にのみ表示されます)を選んでCOPR_LOGIN、COPR_USERNAME、COPR_TOKENの3つの環境変数を追加します。COPR_LOGINとCOPR_TOKENの2つは[Display value in build log]を[ON]にしてログに出力しないようにしました。
docker runで実行されるスクリプトの内容は以下の通りです。
https://github.com/hnakamur/nodejs-rpm/blob/0ed19cd5504fcb11875f12184bdb3ccd27caa6aa/copr-build.sh
#!/bin/bash
set -e
copr_login=$1
copr_username=$2
copr_token=$3
project_name=$4
spec_file=/root/rpmbuild/SPECS/nodejs.spec
mkdir -p /root/.config
cat > /root/.config/copr <<EOF
[copr-cli]
login = ${copr_login}
username = ${copr_username}
token = ${copr_token}
copr_url = https://copr.fedoraproject.org
EOF
status=`curl -s -o /dev/null -w "%{http_code}" https://copr.fedoraproject.org/api/coprs/${copr_username}/${project_name}/detail/`
if [ $status = "404" ]; then
copr-cli create --chroot epel-7-x86_64 --description 'node.js repository' ${project_name}
fi
version=`awk '$1=="Version:" {print $2}' ${spec_file}`
release=$(rpm --eval `awk '$1=="Release:" {print $2}' ${spec_file}`)
srpm_file=/root/rpmbuild/SRPMS/nodejs-${version}-${release}.src.rpm
copr-cli build --nowait ${project_name} ${srpm_file}
rm /root/.config/copr
まず、引数で渡された情報を元にcopr-cliの設定ファイル /root/.config/copr
を生成します。
次にcoprのAPIでプロジェクトが作成済みかチェックし、作成されていなければ作成します。
その後、 copr-cli build
でsrpmをcoprにアップロードしてビルドを開始します。
curlでhttpステータスだけを出力する方法は Getting curl to output HTTP status code? - Super User で知りました。ありがとうございます!
ビルド完了までTravis側で待つようにするのはムダだと思ったので copr-cli build
には --nowait
オプションを指定しました。代わりに Fedora Notificationsでメール通知を有効にして、ビルド終了時には notifications@fedoraproject.org
からメールが届くようにして使っています。
srpmのビルドとcopr-cliのインストール
話が前後しますが、srpmのビルドとcopr-cliのインストールは docker build
で行っています。
Dockerfileの内容は以下の通りです。
FROM centos:7
MAINTAINER Hiroaki Nakamura <hnakamur@gmail.com>
RUN yum -y install rpmdevtools rpm-build \
&& rpmdev-setuptree
RUN yum -y install epel-release \
&& yum -y install python-pip \
&& pip install copr-cli
ADD nodejs.spec /root/rpmbuild/SPECS/
ADD node-js.*patch /root/rpmbuild/SOURCES/
RUN version=`awk '$1=="Version:" {print $2}' /root/rpmbuild/SPECS/nodejs.spec` \
&& curl -sL -o /root/rpmbuild/SOURCES/node-v${version}.tar.xz https://nodejs.org/dist/v${version}/node-v${version}.tar.xz \
&& rpmbuild -bs /root/rpmbuild/SPECS/nodejs.spec
ADD copr-build.sh /root/
ENTRYPOINT ["/bin/bash", "/root/copr-build.sh"]
copr-cliはCentOS 7だとepelから yum install
でインストール可能なのですが、バージョンが古いため copr-cli build
でsrpmファイルのパスを指定してアップロードする機能が無いようです。サイトにアップロードしておいてURLを指定することは可能なのですが、それだと面倒なので pip
を使って最新版の copr-cli
をインストールしています。
長く運用するサーバならrpmでインストールされるパスと同じパスにpipでインストールしてしまうのは良くないかもしれませんが、ビルド終了したら破棄するコンテナなので気にせず上書きインストールとしています。
rpmを使う手順
例えばhnakamur/nodejs Coprだと右の方の[Quick Enable]という欄に dnf copr enable hnakamur/nodejs
というコマンドで有効にできるという説明があります。
その下のリンクをたどるとHowToEnableRepo – coprに
yumの場合は yum copr enable user/project
となるとあります。ただし、 yum-plugin-copr
という yum
のプラグインが必要です。
これはepelとかには無いようで、alonid/yum-plugin-copr Coprにありました。が、これをインストールするにはこのプロジェクトを有効にする必要があるので面倒です。
コマンドを使わなくてもhnakamur/nodejs CoprのActive Releasesセクションの表のRepo Downloadの列にある[Epel 7]というボタンを押すと以下のようにレポジトリの設定ファイルが表示されます。
https://copr.fedoraproject.org/coprs/hnakamur/nodejs/repo/epel-7/hnakamur-nodejs-epel-7.repo
[hnakamur-nodejs]
name=Copr repo for nodejs owned by hnakamur
baseurl=https://copr-be.cloud.fedoraproject.org/results/hnakamur/nodejs/epel-7-$basearch/
skip_if_unavailable=True
gpgcheck=1
gpgkey=https://copr-be.cloud.fedoraproject.org/results/hnakamur/nodejs/pubkey.gpg
enabled=1
enabled_metadata=1
なので、これを /etc/yum.repos.d/hnakamur-nodejs-epel-7.repo
に保存して yum install nodejs
でインストールすればOKです。
まとめ
これでスペックファイルを書いてgithubにプッシュすれば、coprでrpmをビルドして公開されるようになり便利になりました。
ただし問題もあって、coprのビルドはときどき失敗してしまうようです。スペックファイルの中身を変えずにREADMEに無意味な空行を入れるなどして再度pushしてビルドを再実行すると成功したりしました。
さらに気になっていること
ScreenshotsTutorial – coprの[New Build]タブのスクリーンショットには[From URLs]と[Upload SRPM]という2つのタブしかないですが、実際の画面ではそれに加えて [Git and Tito]、[Mock SCM]というタブがあります。
これらを使うとTravis CIを使わずにビルドできるかもしれないと期待しているのですが、使い方の説明を見つけられておらず使い方がわからない状態です。ということで一旦この記事を書きました。
2015-12-06 追記
rpmのビルドが通るまでの試行錯誤中は毎回coprでビルドするより手元の環境でビルドするほうが快適です。そのための手順をmockコマンドでrpmをビルドする · hnakamur’s blog at githubに書きましたので、ご参照ください。