search
LoginSignup
1
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

Elixir その2 Advent Calendar 2020 Day 8

posted at

updated at

Organization

CircleCIでmix testする、Gigalixirへデプロイする(Elixir/Phoenix)

この記事はElixir その2 Advent Calendar 2020 8日目です。
前日は、WindowsでIExで日本語を使う(iex --werl) (Elixir) でした。

はじめに

  • Phoenixプロジェクトで、CircleCIを使ってみました
  • アカウント登録とかGitHubBitbucketリポジトリとの連携はなんとな〜くやればできます
  • mix testが自動で行われるようにします
  • ついでにGigalixirへのデプロイも行います
  • プロジェクトのルートに.circleci/config.ymlを置きます

スクリーンショット 2020-12-07 20.02.43.png

.circleci/config.yml

.circleci/config.yml
version: 2
jobs:
  build:
    parallelism: 1
    docker:
      - image: circleci/elixir:1.10.4
        environment:
          MIX_ENV: test
      - image: circleci/postgres:10.1-alpine
        environment:
          POSTGRES_USER: postgres
          POSTGRES_DB: my_app_test
          POSTGRES_PASSWORD: postgres

    working_directory: ~/app

    steps:
      - checkout

      - run: mix local.hex --force
      - run: mix local.rebar --force

      - restore_cache:
          keys:
            - v1-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
            - v1-mix-cache-{{ .Branch }}
            - v1-mix-cache
      - restore_cache:
          keys:
            - v1-build-cache-{{ .Branch }}
            - v1-build-cache
      - run: mix do deps.get, compile
      - save_cache:
          key: v1-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
          paths: "deps"
      - save_cache:
          key: v1-mix-cache-{{ .Branch }}
          paths: "deps"
      - save_cache:
          key: v1-mix-cache
          paths: "deps"
      - save_cache:
          key: v1-build-cache-{{ .Branch }}
          paths: "_build"
      - save_cache:
          key: v1-build-cache
          paths: "_build"

      - run:
          name: Wait for DB
          command: dockerize -wait tcp://localhost:5432 -timeout 1m

      - run: mix test

      - store_test_results:
          path: _build/test/lib/my_app

  deploy:
    docker:
      - image: circleci/elixir:1.10.4
    steps:
      - add_ssh_keys
      - checkout
      - run: sudo apt-get update
      - run: sudo apt-get install -y python-pip
      - run: sudo pip install gigalixir --ignore-installed six
      - run:
          name: my_app
          command: |
            echo 'export SUFFIX=$(echo $CIRCLE_BRANCH | tr "[:upper:]" "[:lower:]" | tr -cd "[a-z0-9-]")' >> $BASH_ENV
            echo 'export APP_NAME="$GIGALIXIR_APP_NAME-$SUFFIX"' >> $BASH_ENV
            source $BASH_ENV
      - run: gigalixir login -e "$GIGALIXIR_EMAIL" -p "$GIGALIXIR_PASSWORD" -y
      - run: gigalixir git:remote $GIGALIXIR_APP_NAME
      - run: git push -f gigalixir HEAD:refs/heads/main

      - run: printf "Host *\n StrictHostKeyChecking no" > ~/.ssh/config
      - run: gigalixir ps:migrate

workflows:
  version: 2
  deploy:
    jobs:
      - build
      - deploy:
          requires:
            - build
          filters:
            branches:
              only: main

プロジェクト固有の設定

mix release

  1. config/prod.secret.exsconfig/releases.exsにリネーム
  2. config/releases.exsの先頭のほうにあるuse Mix.Configimport Configに書き換える
  3. config/prod.exsの中でimport_config "prod.secret.exs"を呼び出しているところはもはやいらないので消す
  4. config/releases.exsに、config :my_app, MyAppWeb.Endpoint, server: trueを足す
  5. config/prod.exsurl:のところを変更する
  6. lib/my_app/release.exをつくる
config/prod.exs
@@ -10,7 +10,7 @@ use Mix.Config
 # which you should run after static files are built and
 # before starting your production server.
 config :yubaba, YubabaWeb.Endpoint,
-  url: [host: "example.com", port: 80],
+  url: [host: "gigalixir-app-name.gigalixirapp.com", port: 443],
   cache_static_manifest: "priv/static/cache_manifest.json"

 # Finally import the config/prod.secret.exs which loads secrets
 # and configuration from environment variables.
-import_config "prod.secret.exs"
+# import_config "prod.secret.exs"
  • gigalixir-app-name.gigalixirapp.comは適宜読み替えてください
lib/my_app/release.ex
defmodule MyApp.Release do
  @app :my_app

  def migrate do
    load_app()

    for repo <- repos() do
      {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true))
    end
  end

  def rollback(repo, version) do
    load_app()
    {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :down, to: version))
  end

  defp repos do
    Application.fetch_env!(@app, :ecto_repos)
  end

  defp load_app do
    Application.load(@app)
  end
end
  • MyApp:my_appは適宜読み替えてください

CircleCI

  • プロジェクトの設定で設定します

Environment Variables

  • GIGALIXIR_APP_NAME
    • gigalixir appsして、unique_nameを指定します
  • GIGALIXIR_EMAIL
  • GIGALIXIR_PASSWORD
    • Gigalixirのログインパスワードです
    • Circle CIのコンテナからGigalixirにログインするために教えてあげます

SSH Key

  • 秘密鍵
    • passphraseは空2
  • Hostnameは空

たとえば

cd ~/.ssh
ssh-keygen -b 4096 -f gigalixir

で作った場合、~/.ssh/gigalixir の中身を登録します。
CircleCIのコンテナからGigalixirのアプリコンテナへデプロイをしますので、CircleCIが秘密鍵を知っておく必要があるというわけです。

Gigalixir

Wrapping Up :lgtm: :santa: :santa_tone1: :santa_tone2: :santa_tone3: :santa_tone4: :santa_tone5: :lgtm:

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1
Help us understand the problem. What are the problem?