CircleCI で postgresql-client パッケージをインストールできない問題

CircleCI でとある Rails プロジェクトをビルドする際、structure.sql を使っている関係で psql コマンドを実行する必要があり postgresql-client パッケージをインストールしています。

しかし 2019/05 上旬から bin/rails db:test:prepare を実行するタスクで Please check the output above for any errors and make sure that psql is installed in your PATH and has proper permissions. というエラーが表示されてビルドが失敗するようになりました。

CircleCI のビルドログを確認してみると、postgresql-client をインストールするタスクでエラーが発生していました。 バージョン 9.6.11 のパッケージをインストールしようとしたけど、パッケージが 404 Not Found になっているようです。

Docker イメージは circleci/ruby:2.6.1-node-browsers を使用しています。

#!/bin/bash -eo pipefail
sudo apt install -y postgresql-client
Reading package lists... Done


Building dependency tree       


Reading state information... Done

The following additional packages will be installed:
  postgresql-client-9.6 postgresql-client-common
Suggested packages:
  postgresql-9.6 postgresql-doc-9.6
The following NEW packages will be installed:
  postgresql-client postgresql-client-9.6 postgresql-client-common
0 upgraded, 3 newly installed, 0 to remove and 2 not upgraded.
Need to get 1416 kB of archives.
After this operation, 6001 kB of additional disk space will be used.
Get:1 http://deb.debian.org/debian stretch/main amd64 postgresql-client-common all 181+deb9u2 [79.2 kB]
Err:2 http://deb.debian.org/debian stretch/main amd64 postgresql-client-9.6 amd64 9.6.11-0+deb9u1
  404  Not Found
Get:3 http://deb.debian.org/debian stretch/main amd64 postgresql-client all 9.6+181+deb9u2 [55.8 kB]
Fetched 135 kB in 0s (0 B/s)
E: Failed to fetch http://deb.debian.org/debian/pool/main/p/postgresql-9.6/postgresql-client-9.6_9.6.11-0+deb9u1_amd64.deb  404  Not Found
E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?

エラーメッセージの最後に apt-get update を実行してみて、と書かれています。パッケージ情報が古くなっていそうですね。

パッケージ情報を更新する

プロジェクトの .circleci/config.yml で、postgresql-client をインストールする前に apt update を実行し、パッケージ情報を更新するようにしました。

      - run: sudo apt update
      - run: sudo apt install -y postgresql-client

再度、ビルドを実行したところ、バージョン 9.6.12 がインストールされて、ビルドが成功するようになりました。

#!/bin/bash -eo pipefail
sudo apt install -y postgresql-client
Reading package lists... Done

Building dependency tree       


Reading state information... Done

The following additional packages will be installed:
  libpq-dev libpq5 postgresql-client-9.6 postgresql-client-common
Suggested packages:
  postgresql-doc-9.6 postgresql-9.6
The following NEW packages will be installed:
  postgresql-client postgresql-client-9.6 postgresql-client-common
The following packages will be upgraded:
  libpq-dev libpq5
2 upgraded, 3 newly installed, 0 to remove and 35 not upgraded.
Need to get 1767 kB of archives.
After this operation, 6007 kB of additional disk space will be used.
Get:1 http://deb.debian.org/debian stretch/main amd64 libpq-dev amd64 9.6.12-0+deb9u1 [216 kB]
Get:2 http://deb.debian.org/debian stretch/main amd64 libpq5 amd64 9.6.12-0+deb9u1 [136 kB]
Get:3 http://deb.debian.org/debian stretch/main amd64 postgresql-client-common all 181+deb9u2 [79.2 kB]
Get:4 http://deb.debian.org/debian stretch/main amd64 postgresql-client-9.6 amd64 9.6.12-0+deb9u1 [1281 kB]
Get:5 http://deb.debian.org/debian stretch/main amd64 postgresql-client all 9.6+181+deb9u2 [55.8 kB]
Fetched 1767 kB in 0s (61.2 MB/s)
debconf: delaying package configuration, since apt-utils is not installed
(Reading database ... 41645 files and directories currently installed.)
Preparing to unpack .../libpq-dev_9.6.12-0+deb9u1_amd64.deb ...
Unpacking libpq-dev (9.6.12-0+deb9u1) over (9.6.11-0+deb9u1) ...
Preparing to unpack .../libpq5_9.6.12-0+deb9u1_amd64.deb ...
Unpacking libpq5:amd64 (9.6.12-0+deb9u1) over (9.6.11-0+deb9u1) ...
Selecting previously unselected package postgresql-client-common.
Preparing to unpack .../postgresql-client-common_181+deb9u2_all.deb ...
Unpacking postgresql-client-common (181+deb9u2) ...
Selecting previously unselected package postgresql-client-9.6.
Preparing to unpack .../postgresql-client-9.6_9.6.12-0+deb9u1_amd64.deb ...
Unpacking postgresql-client-9.6 (9.6.12-0+deb9u1) ...
Selecting previously unselected package postgresql-client.
Preparing to unpack .../postgresql-client_9.6+181+deb9u2_all.deb ...
Unpacking postgresql-client (9.6+181+deb9u2) ...
Setting up libpq5:amd64 (9.6.12-0+deb9u1) ...
Processing triggers for libc-bin (2.24-11+deb9u4) ...
Setting up postgresql-client-common (181+deb9u2) ...
Setting up libpq-dev (9.6.12-0+deb9u1) ...
Setting up postgresql-client-9.6 (9.6.12-0+deb9u1) ...
update-alternatives: using /usr/share/postgresql/9.6/man/man1/psql.1.gz to provide /usr/share/man/man1/psql.1.gz (psql.1.gz) in auto mode
Setting up postgresql-client (9.6+181+deb9u2) ...

apt update は 1 秒程度で完了する処理なので、パッケージのインストールが必要なビルドでは実行した方が良さそうです。

CircleCI で Mocha と TSLint を実行する

CircleCI で Mocha と TSLint を実行し、ビルドページにレポートを表示するまでのメモ。 Mocha と TSLint の設定は終わっている前提。

パッケージのインストール

JUnit 形式のテストレポートを出力するための npm パッケージを追加する。

www.npmjs.com

yarn add -D mocha-circleci-reporter

設定ファイルの編集

package.json

scripts に CircleCI で実行するコマンドを定義する。 JUnit 形式で reports ディレクトリにレポートを書き出すようにしている。 TypeScript プロジェクトなので、細かいオプションは環境によって異なる。

  "scripts": {
    "tslint:ci": "tslint --fix --force --format stylish --project ./tsconfig.json --format junit --out reports/tslint/test-results.xml ./*.{ts,tsx}",
    "test:ci": "mocha --require ts-node/register --reporter mocha-circleci-reporter --reporter-options mochaFile=reports/mocha/test-results.xml test/**/*.ts"
  },

.circleci/config.yml

主に後半がメインで、package.json に定義したコマンドを実行し、テスト結果を CircleCI にアップロードしている。

version: 2
jobs:
  build:
    docker:
      - image: circleci/node:8
    working_directory: ~/repo
    steps:
      - checkout

      - restore_cache:
          name: Restore Yarn Package Cache
          keys:
            - yarn-packages-{{ checksum "yarn.lock" }}

      - run:
          name: Install Dependencies
          command: yarn install --frozen-lockfile

      - save_cache:
          name: Save Yarn Package Cache
          key: yarn-packages-{{ checksum "yarn.lock" }}
          paths:
            - ~/.cache/yarn

      - run: mkdir reports

      - run:
          name: Run test
          command: yarn test:ci
          when: always

      - run:
          name: Run tslint
          command: yarn tslint:ci
          when: always

      - store_test_results:
          path: reports

      - store_artifacts:
          path: ./reports/mocha/test-results.xml

      - store_artifacts:
          path: ./reports/tslint/test-results.xml

これで設定は完了。 CircleCI のビルドが走って、テストや Lint が失敗していたりすると、以下のようにビルドページの「Test Summary」に失敗している項目が表示される。

f:id:cho_co_by:20190429121305p:plain

SendGrid API v3 で Dynamic Template の一覧を取得する

2019/03/17 現在、SendGrid の API v3 でテンプレートの一覧を取得しようとしても、デフォルトでは Legacy Transactional Templates しか取得されない。 Dynamic Template の一覧を取得するには、以下のように URL に generations=dynamic を指定する。

curl --request GET \
  --url 'https://api.sendgrid.com/v3/templates?generations=dynamic' \
  --header 'authorization: Bearer <API_KEY>'

sendgrid-nodejs だと以下のような感じ。

import * as sgClient from "@sendgrid/client";
sgClient.setApiKey(apiKey);

// ...

const request = {
  method: "GET",
  url: "/v3/templates?generations=dynamic"
};

const [response, body] = await sgClient.request(request);
console.log(body.templates);

Rails console を実行すると Library not loaded: /usr/local/opt/readline/lib/libreadline.7.dylib (LoadError) が発生するようになった

brew upgrade を実行したところ、bin/rails console を実行する際にエラーが発生するようになりました。

  • macOS Mojave 10.14
  • Ruby 2.6.1
  • Rails 5.2.2
  • readline 8.0.0

readline のメジャーバージョンが上がって、ライブラリのパスが変わったのが問題だったようです。

% bin/rails c
Traceback (most recent call last):
        42: from bin/rails:4:in `<main>'
        41: from /.bundle/gems/activesupport-5.2.2/lib/active_support/dependencies.rb:291:in `require'
        40: from /path/to/.bundle/gems/activesupport-5.2.2/lib/active_support/dependencies.rb:257:in `load_dependency'
        39: from /path/to/.bundle/gems/activesupport-5.2.2/lib/active_support/dependencies.rb:291:in `block in require'
        38: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:29:in `require'
        37: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:20:in `require_with_bootsnap_lfi'
        36: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/loaded_features_index.rb:83:in `register'
        35: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `block in require_with_bootsnap_lfi'
        34: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require'
        33: from /path/to/.bundle/gems/railties-5.2.2/lib/rails/commands.rb:18:in `<main>'
        32: from /path/to/.bundle/gems/railties-5.2.2/lib/rails/command.rb:44:in `invoke'
        31: from /path/to/.bundle/gems/railties-5.2.2/lib/rails/command.rb:70:in `find_by_namespace'
        30: from /path/to/.bundle/gems/railties-5.2.2/lib/rails/command/behavior.rb:79:in `lookup'
        29: from /path/to/.bundle/gems/railties-5.2.2/lib/rails/command/behavior.rb:79:in `each'
        28: from /path/to/.bundle/gems/railties-5.2.2/lib/rails/command/behavior.rb:80:in `block in lookup'
        27: from /path/to/.bundle/gems/railties-5.2.2/lib/rails/command/behavior.rb:80:in `each'
        26: from /path/to/.bundle/gems/railties-5.2.2/lib/rails/command/behavior.rb:84:in `block (2 levels) in lookup'
        25: from /path/to/.bundle/gems/activesupport-5.2.2/lib/active_support/dependencies.rb:291:in `require'
        24: from /path/to/.bundle/gems/activesupport-5.2.2/lib/active_support/dependencies.rb:257:in `load_dependency'
        23: from /path/to/.bundle/gems/activesupport-5.2.2/lib/active_support/dependencies.rb:291:in `block in require'
        22: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:29:in `require'
        21: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:20:in `require_with_bootsnap_lfi'
        20: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/loaded_features_index.rb:83:in `register'
        19: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `block in require_with_bootsnap_lfi'
        18: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require'
        17: from /path/to/.bundle/gems/railties-5.2.2/lib/rails/commands/console/console_command.rb:4:in `<main>'
        16: from /path/to/.bundle/gems/activesupport-5.2.2/lib/active_support/dependencies.rb:291:in `require'
        15: from /path/to/.bundle/gems/activesupport-5.2.2/lib/active_support/dependencies.rb:257:in `load_dependency'
        14: from /path/to/.bundle/gems/activesupport-5.2.2/lib/active_support/dependencies.rb:291:in `block in require'
        13: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:29:in `require'
        12: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:20:in `require_with_bootsnap_lfi'
        11: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/loaded_features_index.rb:83:in `register'
        10: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `block in require_with_bootsnap_lfi'
         9: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require'
         8: from /Users/chocoby/.rbenv/versions/2.6.1/lib/ruby/2.6.0/irb/completion.rb:10:in `<main>'
         7: from /path/to/.bundle/gems/activesupport-5.2.2/lib/active_support/dependencies.rb:291:in `require'
         6: from /path/to/.bundle/gems/activesupport-5.2.2/lib/active_support/dependencies.rb:257:in `load_dependency'
         5: from /path/to/.bundle/gems/activesupport-5.2.2/lib/active_support/dependencies.rb:291:in `block in require'
         4: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:29:in `require'
         3: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:20:in `require_with_bootsnap_lfi'
         2: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/loaded_features_index.rb:83:in `register'
         1: from /path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `block in require_with_bootsnap_lfi'
/path/to/.bundle/gems/bootsnap-1.4.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require': dlopen(/Users/chocoby/.rbenv/versions/2.6.1/lib/ruby/2.6.0/x86_64-darwin17/readline.bundle, 9): Library not loaded: /usr/local/opt/readline/lib/libreadline.7.dylib (LoadError)
  Referenced from: /Users/chocoby/.rbenv/versions/2.6.1/lib/ruby/2.6.0/x86_64-darwin17/readline.bundle
  Reason: image not found - /Users/chocoby/.rbenv/versions/2.6.1/lib/ruby/2.6.0/x86_64-darwin17/readline.bundle

調べてみると libreadline.dylib のシンボリックリンクを貼り直すとか、rb-readline gem をインストールするなどの情報がありましたが、 素直に Ruby を再インストールすることで解決できました。

rbenv で Ruby を再インストールする (自分の環境は 2.6.1):

$ rbenv install 2.6.1
rbenv: /Users/chocoby/.rbenv/versions/2.6.1 already exists
continue with installation? (y/N)
ruby-build: use openssl from homebrew
Downloading ruby-2.6.1.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.1.tar.bz2
Installing ruby-2.6.1...
ruby-build: use readline from homebrew
Installed ruby-2.6.1 to /Users/chocoby/.rbenv/versions/2.6.1

一度 .bundle ディレクトリを全削除 (環境によっては vendor/bundle ディレクトリなど) し、Gem を再インストールする:

% rm -rf .bundle
% bundle install

再度 bin/rails console を実行したところ、Rails console を開けるようになりました。

% bin/rails c
Loading development environment (Rails 5.2.2)
[1] pry(main)>

はてなブログを試してみることにした

こんにちは。

GitHub では chocoby, Twitter では cho_co という名前で活動しているものです。 普段は主に Ruby を書いていて、趣味で CurryBu というサービスを作っていたりします。

自前で運用していたブログの更新を停めて、はてなブログを試してみることにしました。

以前のブログはこちらです。

chocoby.jp

最近の自分のブログへの思い

2018 年は色々あってまったくアウトプットできず、今年こそはアウトプットするぞ!と思いつつ、もう 3 月。 この状況をどうにかできないか、考えました。

まず、自分のブログは自分がコントロール出来るところに置いておきたい、と思いがあり、Middleman + AWS S3 + AWS CloudFront という構成でこの数年運用していました。

この運用を行った結果、以下の感想がありました。

  • エディターで記事を書いて、Git にコミットして、GitHub にプッシュして、という手順が重たい
  • Middleman やプラグインをアップデートできておらず、メンテナンスが止まっている

エディターやライブラリは悪くありません。自分がただ怠惰なだけです。

自分で HTML や CSS を書くのは楽しい作業ですし、GitHub にプッシュした後は CI で S3 にデプロイするようにしています。 ただ、今はいかに PC やスマートフォンで、シュッと記事を書き始められるか、というのが重要な気がしています。

「自分がコントロール出来る」という思いとは反しますが、気分を新たにする意味でも、外部のサービスを使うことにしました。 (Netlify CMS も考えましたが、作っている途中で飽きそうだったのでパスしました。)

なぜはてなブログなのか

深い理由はありません。一番身近なブログサービスがはてなブログだったからです。 自分もはてなブログを使っている時期がありましたし、普段目にする技術ブログの多くが、はてなブログを使っています。

Medium や note も検討しましたが、ゆるい事も書きたいので候補から外しました。

はてなブログ Pro の 1 年コースに登録し、独自ドメインを割り当てました。最初から HTTPS が有効になっていて嬉しいです。 デザインは初期状態のままでも見やすいので、今のところはそのままです。

もともと、id:Cliche という ID ではてなブックマークをやっていたのですが、ブログは普段の ID に近づけたいなと思い、新たにはてな ID を登録しました。 cho_cochocoby は登録済みだったので id:cho_co_by になってしまいましたが...

以前のブログからの移行

以前のブログの記事ですが、移行に手間がかかりそうなので、このブログをしばらく続けられたら移行しようと思います。