• ..

Vue

    GitHub にプッシュする

    CircleCI 上のリポジトリでは、最初から以下のようなリモート設定がされているようです。

    origin  git@github.com:user/repo.git (fetch)
    origin  git@github.com:user/repo.git (push)

    github.com に ssh できるようにする

    対象のプロジェクトの設定の

    1. SSH Permissions
    2. Add SSH Key

    から以下のように「Hostname」にはgithub.comを設定し、「Private Key」には自分がいつも使っている秘密鍵の内容をコピペして追加します。

    一覧画面のそのホストの行にフィンガープリントが一緒に置いてあるはずなのでそれをコピーしておきます。

    .circleci/config.yaml の編集

    ssh時に鍵認証できる必要があるので.ssh/configを編集する必要があります。これにはstepsadd_ssh_keysを設定しておきます。以下のような感じです。

    jobs:
      - checkout
      - add_ssh_keys:
          fingerprints:
            - '**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**'

    この'**:**:...の部分に先ほどコピーしたフィンガープリントを置きます。これでここを実行した時に~/.ssh/configに以下のような設定が追加されます。

    Host github.com
      IdentitiesOnly yes
      IdentityFile /home/circleci/.ssh/id_rsa_********************************

    step で push する

    git pushを実行するには、 git ユーザーのメールと名前は最低限設定する必要があるのでそれらを設定した上でgit pushします。

    steps:
      - ...
      - run:
          name: git push
          command: |
            git config --global user.email "$GIT_AUTHOR_EMAIL"
            git config --global user.name "$GIT_AUTHOR_NAME"
            # add とかするならここで
            export GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
            git push origin master:****

    now を使ってデプロイするワークフロー

    version: 2
    
    references:
      config: &config
        working_directory: ~/repo
        docker:
          - image: circleci/node:8
      commands:
        print_pkg: &print_pkg
          run:
            name: Print package.json
            command: cat package.json
        restore_cache: &restore_cache
          restore_cache:
            keys:
              - v1-dependencies-{{ checksum "package.json" }}
              - v1-dependencies-
        save_cache: &save_cache
          save_cache:
            paths:
              - node_modules
            key: v1-dependencies-{{ checksum "package.json" }}
      scripts:
        yarn_install: &yarn_install
          run:
            name: Yarn install
            command: yarn --ignore-scripts
        yarn_install_now: &yarn_install_now
          run:
            name: Yarn install now
            command: yarn add -D now
        yarn_test: &yarn_test
          run:
            name: Yarn test
            command: yarn test
        yarn_now_deploy: &yarn_deploy
          run:
            name: Yarn deploy to now
            command: yarn deploy
    
    jobs:
      setup:
        <<: *config
        steps:
          - checkout
          - *print_pkg
          - *restore_cache
          - *yarn_install
          - *save_cache
      test:
        <<: *config
        steps:
          - checkout
          - *print_pkg
          - *restore_cache
          - *yarn_install
          - *save_cache
          - *yarn_test
      deploy:
        <<: *config
        steps:
          - checkout
          - *print_pkg
          - *restore_cache
          - *yarn_install
          - *save_cache
          - *yarn_install_now
          - *yarn_deploy
    
    workflows:
      version: 2
      deploy:
        jobs:
          - setup:
              filters:
                branches:
                  only:
                    - master
          - test:
              requires:
                - setup
          - deploy:
              requires:
                - test

    基本複雑になりそうな部分はリファレンスブロックで細分化して管理しています。ワークフローの流れは以下のような感じです。

    setup

    masterブランチがgit pushで更新されると、まずこれが走ります。これは単に後の共通フローの高速化のためです。ここではyarnした時の結果をキャッシュして、後のフローでのyarnが早く終わるようにしています。

    test

    setupが無事に終わったのを確認してから走ります。主にテストを行い、それが正常に終了したらdeployにバトンタッチします。

    deploy

    testが無事に終わったのを確認してから走ります。ここでは now でのデプロイを行います。

    - *yarn_install_now
    - *yarn_deploy

    がここ固有のステップでこれらは展開すると以下のようになります。

    - run:
        name: Yarn install now
        command: yarn add -D now
    - run:
        name: Yarn deploy to now
        command: yarn deploy
    1. nowをインストール
    2. now でデプロイ

    now をインストール

    nowを依存に含めないかと思うかもしれないですが、含めています。ただ依存のインストールを(環境によっては)もっと時間短縮になるyarn --ignore-scriptsを使ってインストールしていて、これだと now のインストールが完全に行われないため再度インストールしています。--ignore-scriptsというのはフックスクリプトを実行しないというオプションフラグです。

    now でデプロイ

    この run-scripts の中はこのように定義しています。(npm-run-allの中のrun-sという並行実行の記述をちょっと短縮できるコマンドを使ってます)

    1. デプロイ
    2. エイリアス設定
    3. エイリアス付けた環境以外削除

    といういつものプロセスを行っています。

    {
      "scripts": {
        "now.deploy": "now --team $NOW_TEAM --token $NOW_TOKEN",
        "now.alias": "now alias --team $NOW_TEAM --token $NOW_TOKEN",
        "now.rm": "now rm smilesumai-sindan.now.sh --team $NOW_TEAM --token $NOW_TOKEN",
        "deploy": "run-s now.deploy now.alias now.rm"
      }
    }

    $NOW_TEAMにはデプロイしたいチーム名、$NOW_TOKENには個人トークンを発行して設定します。これはら CircleCI の「 Environment Variables 」へ設定します。

    結果

    git pushして、うまくいけば以下のように完了するはずです。

    タグをプッシュした時にワークフローが走るようにする

    CircleCI ではデフォルトで、すべてのブランチが対象で、すべてのタグ名は除外のような設定になっています。
    そのため、以下のようなタグプッシュではワークフローが走ってくれません。

    git tag -a v0.0.1 -m '...'
    git push origin v0.0.1

    CircleCI ではタグの場合「このタグ名(タグ名のパターン)で来たとき走ってほしい」というような名前指定をする必要があります。これはワークフローのフィルターのtagsブロックで設定できます。

    以下は、/v[0-9]+\.[0-9]+\.[0-9]+/というタグ名(v0.0.1にマッチ)の時にワークフローが走る設定です。

    workflows:
      version: 2
      workflow_name:
        jobs:
          - job_name:
              filters:
                tags:
                  only: /v[0-9]+\.[0-9]+\.[0-9]+/

    タグ名プッシュの時だけに走るワークフロー

    上の設定はまだ以下のような設定のものと同じです。

    filters:
      tags:
        only: /v[0-9]+\.[0-9]+\.[0-9]+
      branches:
        only: /.*/

    なのですべてのブランチを除外するという設定も必要になります。

    filters:
      tags:
        only: /v[0-9]+\.[0-9]+\.[0-9]+
      branches:
        ignore: /.*/

    失敗した時だけ実行されるステップ

    runオブジェクトにwhen: on_failセクションを置くと、前回のステップが失敗した時にだけ実行させることができます。

    以下の例は1つ目のステップでfoo != barじゃない時は失敗(exit: 0以外が返される)とするようなスクリプトになっています。もちろんこれは失敗するので、次のステップのecho "bar"が実行されるはずです。

    version: 2.1
    
    jobs:
      build:
        docker:
        - image: alpine
        steps:
        - run: |
            if [ "foo" != "bar" ]; then
              exit 1
            fi
        - run:
            name: on fail
            command:
              echo "bar"
            when: on_fail
        - run: ': 1'
        - run: ': 2'
        - run: ': 3'

    望んだ通りになりました。

    処理を続ける

    when: on_failなステップを複数置いている時、1度でもwhen: on_failなステップが実行されると、それ以降のwhen: on_fail(とalways)なステップはすべて実行されます。

    以下のような場合最後のon_success以外のすべてのステップが実行されます。

    version: 2.1
    
    jobs:
      build:
        docker:
        - image: alpine
        steps:
        - run: |
            if [ "foo" != "bar" ]; then
              exit 1
            fi
        - run:
            name: on fail 1
            command:
              echo on fail 1
            when: on_fail
        - run:
            name: on fail 2
            command:
              echo on fail 2
            when: on_fail
        - run:
            name: on fail 3
            command:
              echo on fail 3
            when: always
        - run:
            name: on fail 4
            command:
              echo on fail 4
            when: on_success