Help us understand the problem. What is going on with this article?

D言語+Travis-CIでリリースのデプロイ自動化する話

概要

D言語でもTravis-CIやCircle-CIをはじめとする各種CIサービスでテスト・デプロイが可能です。
今回はTravis-CIを用いてReleaseのデプロイを自動化するテンプレを紹介します。
ちなみにビルドにはdubを使う前提です。

  1. D言語+Travis-CIでテスト自動化する話➀
  2. D言語+Travis-CIでテスト自動化する話②
  3. D言語+Travis-CIでリリースのデプロイ自動化する話 ← この記事
  4. D言語+Travis-CIでドキュメントのデプロイ自動化する話

.travis.yml のテンプレ

.travis.yml
language: d

# ここにテストの記述

jobs:
    include:
        - stage: GitHub Release
          d: ldc
          os: linux
          script: echo "Deploying to GitHub releases ..." && ./.travis-release.sh
          deploy:
            provider: releases
            api_key: $GH_REPO_TOKEN
            file_glob: true
            file: <プロジェクト名>-*.tar.gz
            after_success: true
            skip_cleanup: true
            on:
              repo: <アカウント名>/<プロジェクト名>
              tags: true
        - stage: GitHub Release
          d: ldc
          os: osx
          script: echo "Deploying to GitHub releases ..." && ./.travis-release.sh
          deploy:
            provider: releases
            api_key: $GH_REPO_TOKEN
            file_glob: true
            file: gendoc-*.tar.gz
            after_success: true
            skip_cleanup: true
            on:
              repo: <アカウント名>/<プロジェクト名>
              tags: true
        - stage: GitHub Release
          d: dmd
          os: linux
          language: generic
          sudo: yes
          script: echo "Deploying to GitHub releases ..." && ARCH=32 ./.travis-release-windows.sh
          addons:
            apt:
              packages:
                - p7zip-full
          deploy:
            provider: releases
            api_key: $GH_REPO_TOKEN
            file_glob: true
            file: <プロジェクト名>-*.zip
            after_success: true
            skip_cleanup: true
            on:
              repo: <アカウント名>/<プロジェクト名>
              tags: true
        - stage: GitHub Release
          d: dmd
          os: linux
          language: generic
          sudo: yes
          script: echo "Deploying to GitHub releases ..." && ARCH=64 ./.travis-release-windows.sh
          addons:
            apt:
              packages:
                - p7zip-full
          deploy:
            provider: releases
            api_key: $GH_REPO_TOKEN
            file_glob: true
            file: <プロジェクト名>-*.zip
            after_success: true
            skip_cleanup: true
            on:
              repo: <アカウント名>/<プロジェクト名>
              tags: true

解説

この設定で、タグをつけてpushした際に、GitHubのReleaseページに以下4つのアーカイブファイルを追加することができます。

OS アーキテクチャ ファイル名
Linux x86_64 <プロジェクト名>-<バージョン>-linux-x86_64.tar.gz
OSX x86_64 <プロジェクト名>-<バージョン>-osx-x86_64.tar.gz
Windows x86_64 <プロジェクト名>-<バージョン>-windows-x86_64.tar.gz
Windows x86 <プロジェクト名>-<バージョン>-windows-x86.tar.gz

ポイントは以下:

  • $GH_REPO_TOKEN はデプロイに必要なトークン。
    GitHubにて、ユーザーアカウントの「Settings」→「Developer settings」→「Personal access tokens」へとたどり発行できます。権限はSelect scopesで設定し、「repo_deployment / Access deployment status」をチェックします。
    このキーをTravis-CIの各リポジトリの設定で「more options」→「Environment Variables」の欄に登録します。
  • ./.travis-release.sh は、Linux / OSX 向け
  • ./.travis-release-windows.sh および ./.travis-release-windows-setup.shはWindows向け(Travis-CIのLinuxサーバー上でクロスコンパイルする)です。
  • Windows向けでは後述の7z解凍用にp7zip-fullが必要です。
  • 上記テンプレの設定の場合、毎回ビルド(アーカイブの作成)は行うが、デプロイはしない、という設定になる。「テストは通っているけどアーカイブにする段になって何かしら問題が生じたためタグをつけたのにデプロイできず、さらにはタグをつけたところが build failed になる」という恥ずかしい状況を防ぐのに効果があると思います。
  • 毎回ビルドしたくない場合 → TravisCI タグをプッシュした時だけ動くビルドステージの設定 By @masakurapa

以下実際のプロジェクトで使われている設定です。大いに参考にしました。

.travis-release.sh

#!/usr/bin/env bash
set -eux -o pipefail

PROJECTNAME=<プロジェクト名>

VERSION=$(git describe --abbrev=0 --tags)
ARCH="${ARCH:-64}"
LDC_FLAGS=()
unameOut="$(uname -s)"
case "$unameOut" in
    Linux*) OS=linux; LDC_FLAGS=("-flto=full" "-linker=gold" "-static") ;;
    Darwin*) OS=osx; LDC_FLAGS+=("-L-macosx_version_min" "-L10.7" "-L-lcrt1.o"); ;;
    *) echo "Unknown OS: $unameOut"; exit 1
esac

case "$ARCH" in
    x86_64) ARCH_SUFFIX="x86_64";;
    64) ARCH_SUFFIX="x86_64";;
    i386) ARCH_SUFFIX="x86";;
    i686) ARCH_SUFFIX="x86";;
    x86) ARCH_SUFFIX="x86";;
    32) ARCH_SUFFIX="x86";;
    *) echo "Unknown ARCH: $ARCH"; exit 1
esac

archiveName="$PROJECTNAME-$VERSION-$OS-$ARCH_SUFFIX.tar.gz"

echo "Building $archiveName"

dub build -b=release

cd build
tar cvfz "../$archiveName" -C . *
cd ..

ポイントは以下:

  • PROJECTNAME=<プロジェクト名>としているところでプロジェクト名を入力します。アーカイブ名に使われます。
  • dub build -b=release でビルド。このプロジェクトはtargetPathbuildを指定しているので、buildディレクトリ以下をアーカイブする。
  • cd buildcd .. の箇所はアーカイブを作成するところ。ライセンスを入れたりディレクトリの構造いじったりする場合はここでやります。

.travis-release-windows.sh, .travis-release-windows-setup.sh

.travis-release-windows.sh
#!/usr/bin/env bash
# Build the Windows binaries under Linux
set -eux -o pipefail

PROJECTNAME=<プロジェクト名>

# Allow the script to be run from anywhere
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $DIR

source .travis-release-windows-setup.sh

# Run LDC with cross-compilation
archiveName="$PROJECTNAME-$VERSION-$OS-$ARCH_SUFFIX.zip"
echo "Building $archiveName"

dub build -a=$TARGET_MTRIPLE -b=release -c=default --compiler=ldc2

cd build
zip -r "../$archiveName" "./"
cd ..

※リリース前・マージ後のやり方
.travis-release-windows.sh
#!/usr/bin/env bash
# Build the Windows binaries under Linux
set -eux -o pipefail

PROJECTNAME=<プロジェクト名>

# Allow the script to be run from anywhere
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $DIR

source .travis-release-windows-setup.sh

# Run LDC with cross-compilation
archiveName="$PROJECTNAME-$VERSION-$OS-$ARCH_SUFFIX.zip"
echo "Building $archiveName"

git clone https://github.com/dlang/dub.git --depth=1 && dub run --root=dub -- build -a=$TARGET_MTRIPLE -b=release -c=default --compiler=ldc2

cd build
zip -r "../$archiveName" "./"
cd ..

  • Windows向けのクロスコンパイルを行い、zipでアーカイブします。
  • ただし、現在 dub がクロスコンパイルに対応しておらず、Pull Requestが出ていますのでリリースを待ちましょう。
    • マージされました。次回リリースで導入されるでしょう。
    • マージされたので、dubのmasterをcloneしてビルドしつつ、ビルドしたdubで-a=$TARGET_MTRIPLEを指定することでクロスコンパイルできるようにしています。
    • リリースされました。 これに伴い、上記例も修正しました。v1.18.0より前のLDCを使用してクロスコンパイルをする場合は、「※リリース前・マージ後のやり方」を参考にして、デプロイ中にクロスコンパイル対応のdubをビルド・実行してください。
  • makeなどを使う場合は、ここで -mtriple=$TARGET_MTRIPLE を指定したldc2でビルドすることでクロスコンパイルできます。ちなみに、後述しますが、途中で読んでいる source .travis-release-windows-setup.sh の部分で $TARGET_MTRIPLE に適切な -mtriple の値が設定されています。

以下実装例

.travis-release-windows-windows.sh
#!/usr/bin/env bash

# sets up LDC for cross-compilation. Source this script, s.t. the new LDC is in PATH

ARCH=${ARCH:-32}
VERSION=$(git describe --abbrev=0 --tags)
OS=windows

case "$ARCH" in
    x86_64) ARCH_SUFFIX="x86_64";;
    64) ARCH_SUFFIX="x86_64";;
    i386) ARCH_SUFFIX="x86";;
    i686) ARCH_SUFFIX="x86";;
    x86) ARCH_SUFFIX="x86";;
    32) ARCH_SUFFIX="x86";;
    *) echo "Unknown ARCH: $ARCH"; exit 1
esac

# Step 0: install ldc
if [ ! -f install.sh ] ; then
    wget https://dlang.org/install.sh
fi
LDC_VERSION=${LDC_VERSION:-$(bash ./install.sh -a ldc | sed -E 's/.+\/ldc-([0-9.]+)\/activate/\1/')}
. $(bash ./install.sh -a "ldc-${LDC_VERSION}")

# for the install.sh script only
LDC_PATH="$(dirname $(dirname $(which ldc2)))"

# Step 1a: download the LDC x64 windows binaries
if [ "${ARCH_SUFFIX}" == "x86_64" ] && [ ! -d "ldc2-${LDC_VERSION}-windows-x64" ] ; then
    wget "https://github.com/ldc-developers/ldc/releases/download/v${LDC_VERSION}/ldc2-${LDC_VERSION}-windows-x64.7z"
    7z x "ldc2-${LDC_VERSION}-windows-x64.7z" > /dev/null
    # Step 2a: Add LDC windows binaries to LDC Linux
    if [ ! -d "${LDC_PATH}/lib-win64" ] ; then
        cp -r ldc2-${LDC_VERSION}-windows-x64/lib "${LDC_PATH}/lib-win64"
        cat >> "$LDC_PATH"/etc/ldc2.conf <<EOF
"x86_64-.*-windows-msvc":
{
    switches = [
        "-defaultlib=phobos2-ldc,druntime-ldc",
        "-link-defaultlib-shared=false",
    ];
    lib-dirs = [
        "%%ldcbinarypath%%/../lib-win64",
    ];
};
EOF
    fi
fi
# Step 1b: download the LDC x86 windows binaries
if [ "${ARCH_SUFFIX}" == "x86" ] && [ ! -d "ldc2-${LDC_VERSION}-windows-x86" ] ; then
    wget "https://github.com/ldc-developers/ldc/releases/download/v${LDC_VERSION}/ldc2-${LDC_VERSION}-windows-x86.7z"
    7z x "ldc2-${LDC_VERSION}-windows-x86.7z" > /dev/null
    # Step 2b: Add LDC windows binaries to LDC Linux
    if [ ! -d "${LDC_PATH}/lib-win32" ] ; then
        cp -r ldc2-${LDC_VERSION}-windows-x86/lib "${LDC_PATH}/lib-win32"
        cat >> "$LDC_PATH"/etc/ldc2.conf <<EOF
"i686-.*-windows-msvc":
{
    switches = [
        "-defaultlib=phobos2-ldc,druntime-ldc",
        "-link-defaultlib-shared=false",
    ];
    lib-dirs = [
        "%%ldcbinarypath%%/../lib-win32",
    ];
};
EOF
    fi
fi

# set suffices and compilation flags
if [ "$ARCH_SUFFIX" == "x86_64" ] ; then
    export TARGET_MTRIPLE="x86_64-windows-msvc"
else
    export TARGET_MTRIPLE="i686-windows-msvc"
fi

ポイント(というか何をやっているかの概要)は以下

  • インストールスクリプトでldc2をインストール
  • Windows向けのldc2(中身のlibファイルが目当て)をダウンロード
  • 配布形態の7zipを解凍してlibファイルをコピー(ここで先述のp7zip-fullが必要)
  • ldc2.confにクロスコンパイル用の設定を追加(--windows-msvcのときのlibファイルの場所の指定など)
  • TARGET_MTRIPLE環境変数に -mtriple= の中身になるx86_64-windows-msvci686-windows-msvcを設定

以下実装例

ライセンス

今回紹介したスクリプトは多分 BSL-1.0 です。使用する場合はご注意ください。D-Scanner (BSD-1.0)で使われているスクリプトがベースになっています。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした