From e442da2beaa948a8206182de048fc253d8faf304 Mon Sep 17 00:00:00 2001 From: Kam Leung Date: Fri, 26 Mar 2021 14:27:38 -0400 Subject: [PATCH] Elixir upgrade (#687) Upgrade elixir and use runtime.exs --- .github/workflows/papercups.yml | 4 +- .tool-versions | 2 +- Dockerfile | 12 +-- config/config.exs | 63 --------------- config/prod.exs | 70 ++-------------- config/releases.exs | 78 ------------------ config/runtime.exs | 137 ++++++++++++++++++++++++++++++++ config/test.exs | 1 + docker-compose.prod.yml | 4 +- elixir_buildpack.config | 2 +- 10 files changed, 154 insertions(+), 219 deletions(-) delete mode 100644 config/releases.exs create mode 100644 config/runtime.exs diff --git a/.github/workflows/papercups.yml b/.github/workflows/papercups.yml index cb3bf0708..306c8c6ce 100644 --- a/.github/workflows/papercups.yml +++ b/.github/workflows/papercups.yml @@ -15,8 +15,8 @@ jobs: - name: Initial setup uses: erlef/setup-elixir@v1 with: - elixir-version: "1.10.4" - otp-version: "22.2.6" + elixir-version: "1.11.4" + otp-version: "23.0.3" - name: Install dependencies run: mix deps.get diff --git a/.tool-versions b/.tool-versions index d5a4bb02f..34c64af36 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,4 +1,4 @@ erlang 23.0.3 -elixir 1.10.4-otp-23 +elixir 1.11.3-otp-23 nodejs 12.18.3 postgres 12.3 diff --git a/Dockerfile b/Dockerfile index e18521e79..1013764a2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,35 +1,25 @@ -FROM elixir:1.10.4-alpine as builder +FROM elixir:1.11.3-alpine as builder # build step ARG MIX_ENV=prod ARG NODE_ENV=production ARG APP_VER=0.0.1 -ARG REACT_APP_URL=localhost:3000 ARG USE_IP_V6=false ARG REQUIRE_DB_SSL=false ARG AWS_ACCESS_KEY_ID ARG AWS_SECRET_ACCESS_KEY ARG BUCKET_NAME ARG AWS_REGION -ARG REACT_APP_ADMIN_ACCOUNT_ID ARG PAPERCUPS_STRIPE_SECRET -ARG REACT_APP_STRIPE_PUBLIC_KEY -ARG REACT_APP_EU_EDITION=false -ARG REACT_APP_FILE_UPLOADS_ENABLED -ENV REACT_APP_FILE_UPLOADS_ENABLED=1 ENV APP_VERSION=$APP_VER -ENV REACT_APP_URL=$REACT_APP_URL ENV REQUIRE_DB_SSL=$REQUIRE_DB_SSL ENV USE_IP_V6=$USE_IP_V6 ENV AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID ENV AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY ENV BUCKET_NAME=$BUCKET_NAME ENV AWS_REGION=$AWS_REGION -ENV REACT_APP_ADMIN_ACCOUNT_ID=$REACT_APP_ADMIN_ACCOUNT_ID ENV PAPERCUPS_STRIPE_SECRET=$PAPERCUPS_STRIPE_SECRET -ENV REACT_APP_STRIPE_PUBLIC_KEY=$REACT_APP_STRIPE_PUBLIC_KEY -ENV REACT_APP_EU_EDITION=$REACT_APP_EU_EDITION RUN mkdir /app diff --git a/config/config.exs b/config/config.exs index 3091f9925..87f433eb2 100644 --- a/config/config.exs +++ b/config/config.exs @@ -1,22 +1,5 @@ -# This file is responsible for configuring your application -# and its dependencies with the aid of the Mix.Config module. -# -# This configuration file is loaded before any dependency and -# is restricted to this project. - -# General application configuration use Mix.Config -sentry_dsn = System.get_env("SENTRY_DSN") -mailgun_api_key = System.get_env("MAILGUN_API_KEY") -domain = System.get_env("DOMAIN") -site_id = System.get_env("CUSTOMER_IO_SITE_ID") -customerio_api_key = System.get_env("CUSTOMER_IO_API_KEY") -aws_key_id = System.get_env("AWS_ACCESS_KEY_ID") -aws_secret_key = System.get_env("AWS_SECRET_ACCESS_KEY") -bucket_name = System.get_env("BUCKET_NAME", "papercups-files") -region = System.get_env("AWS_REGION") - config :chat_api, environment: Mix.env(), ecto_repos: [ChatApi.Repo], @@ -32,22 +15,11 @@ config :chat_api, ChatApiWeb.Endpoint, pubsub_server: ChatApi.PubSub, live_view: [signing_salt: "pRVXwt3k"] -config :logger, - backends: [:console, Sentry.LoggerBackend] - # Configures Elixir's Logger config :logger, :console, format: "$time $metadata[$level] $message\n", metadata: [:request_id] -config :logger, Sentry.LoggerBackend, - # Also send warn messages - level: :warn, - # Send messages from Plug/Cowboy - excluded_domains: [], - # Send messages like `Logger.error("error")` to Sentry - capture_log_messages: true - # Use Jason for JSON parsing in Phoenix config :phoenix, :json_library, Jason @@ -69,14 +41,6 @@ config :chat_api, :phoenix_swagger, ] } -# Configure Sentry -config :sentry, - dsn: sentry_dsn, - environment_name: Mix.env(), - included_environments: [:prod], - enable_source_code_context: true, - root_source_code_path: File.cwd!() - config :pow, Pow.Postgres.Store, repo: ChatApi.Repo, schema: ChatApi.Auth.PowSession @@ -100,35 +64,8 @@ config :chat_api, Oban, # {"0 * * * *", ChatApi.Workers.ArchiveStaleFreeTierConversations} ] -# Configure Mailgun -config :chat_api, ChatApi.Mailers.Mailgun, - adapter: Swoosh.Adapters.Mailgun, - api_key: mailgun_api_key, - domain: domain - config :chat_api, ChatApi.Mailers.Gmail, adapter: Swoosh.Adapters.Gmail -config :customerio, - site_id: site_id, - api_key: customerio_api_key - -case System.get_env("PAPERCUPS_STRIPE_SECRET") do - "sk_" <> _rest = api_key -> - config :stripity_stripe, api_key: api_key - - _ -> - nil -end - -config :ex_aws, - access_key_id: aws_key_id, - secret_access_key: aws_secret_key, - s3: [ - scheme: "https://", - host: bucket_name <> ".s3.amazonaws.com", - region: region - ] - # Import environment specific config. This must remain at the bottom # of this file so it overrides the configuration defined above. import_config "#{Mix.env()}.exs" diff --git a/config/prod.exs b/config/prod.exs index 7e8d2eb35..667ec8dc2 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -1,17 +1,7 @@ use Mix.Config -# For production, don't forget to configure the url host -# to something meaningful, Phoenix uses this information -# when generating URLs. -# -# Note we also include the path to a cache manifest -# containing the digested version of static files. This -# manifest is generated by the `mix phx.digest` task, -# which you should run after static files are built and -# before starting your production server. -use Mix.Config - -database_url = System.get_env("DATABASE_URL") || "ecto://postgres:postgres@localhost/chat_api" +database_url = System.get_env("DATABASE_URL") || "ecto://postgres:postgres@localhost/chat_api_dev" +pool_size = String.to_integer(System.get_env("POOL_SIZE") || "10") require_db_ssl = case System.get_env("REQUIRE_DB_SSL") do @@ -20,57 +10,13 @@ require_db_ssl = _ -> true end -socket_options = - case System.get_env("USE_IP_V6") do - "true" -> [:inet6] - "false" -> [:inet] - _ -> [:inet] - end +# Do not print debug messages in production +config :logger, level: :info +# Heroku needs ssl to be set to true and it doesn't run config :chat_api, ChatApi.Repo, ssl: require_db_ssl, url: database_url, - pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"), - socket_options: socket_options - -secret_key_base = - System.get_env("SECRET_KEY_BASE") || - "dvPPvOjpgX2Wk8Y3ONrqWsgM9ZtU4sSrs4l/5CFD1sLm4H+CjLU+EidjNGuSz7bz" - -config :chat_api, ChatApiWeb.Endpoint, - http: [ - port: String.to_integer(System.get_env("PORT") || "4000"), - compress: true, - transport_options: [socket_opts: [:inet6]] - ], - url: [scheme: "https", host: {:system, "BACKEND_URL"}, port: 443], - # FIXME: not sure the best way to handle this, but we want - # to allow our customers' websites to connect to our server - check_origin: false, - force_ssl: [rewrite_on: [:x_forwarded_proto]], - secret_key_base: secret_key_base - -# Do not print debug messages in production -config :logger, level: :info - -# The `cipher_suite` is set to `:strong` to support only the -# latest and more secure SSL ciphers. This means old browsers -# and clients may not be supported. You can set it to -# `:compatible` for wider support. -# -# `:keyfile` and `:certfile` expect an absolute path to the key -# and cert in disk or a relative path inside priv, for example -# "priv/ssl/server.key". For all supported SSL configuration -# options, see https://hexdocs.pm/plug/Plug.SSL.html#configure/1 -# -# We also recommend setting `force_ssl` in your endpoint, ensuring -# no data is ever sent via http, always redirecting to https: -# -# config :chat_api, ChatApiWeb.Endpoint, -# force_ssl: [hsts: true] -# -# Check `Plug.SSL` for all available options in `force_ssl`. - -# Finally import the config/prod.secret.exs which loads secrets -# and configuration from environment variables. -# import_config "prod.secret.exs" + show_sensitive_data_on_connection_error: true, + socket_options: [:inet], + pool_size: pool_size diff --git a/config/releases.exs b/config/releases.exs deleted file mode 100644 index 083978c1d..000000000 --- a/config/releases.exs +++ /dev/null @@ -1,78 +0,0 @@ -import Config - -database_url = - System.get_env("DATABASE_URL") || - raise """ - environment variable DATABASE_URL is missing. - For example: ecto://USER:PASS@HOST/DATABASE - """ - -secret_key_base = - System.get_env("SECRET_KEY_BASE") || - raise """ - environment variable SECRET_KEY_BASE is missing. - You can generate one by calling: mix phx.gen.secret - """ - -backend_url = - System.get_env("BACKEND_URL") || - raise """ - environment variable BACKEND_URL is missing. - For example: myselfhostedwebsite.com or papercups.io - """ - -# Configure your database -config :chat_api, ChatApi.Repo, - url: database_url, - show_sensitive_data_on_connection_error: false, - pool_size: 10 - -ssl_key_path = System.get_env("SSL_KEY_PATH") -ssl_cert_path = System.get_env("SSL_CERT_PATH") -https = (ssl_cert_path && ssl_key_path) != nil - -if https do - config :chat_api, ChatApiWeb.Endpoint, - http: [ - port: String.to_integer(System.get_env("PORT") || "4000"), - transport_options: [socket_opts: [:inet6]] - ], - url: [host: backend_url], - pubsub_server: ChatApi.PubSub, - secret_key_base: secret_key_base, - https: [ - port: 443, - cipher_suite: :strong, - otp_app: :hello, - keyfile: ssl_key_path, - certfile: ssl_cert_path - ], - server: true -else - config :chat_api, ChatApiWeb.Endpoint, - http: [ - port: String.to_integer(System.get_env("PORT") || "4000"), - transport_options: [socket_opts: [:inet6]] - ], - url: [host: backend_url], - pubsub_server: ChatApi.PubSub, - secret_key_base: secret_key_base, - server: true -end - -# https = (ssl_cert_path && ssl_key_path) != nil -# # ## SSL Support -# # -# # To get SSL working, you will need to add the `https` key -# # to the previous section and set your `:url` port to 443: -# if ssl_key_path && ssl_cert_path do -# config :chat_api, ChatApiWeb.Endpoint, -# url: [host: "example.com", port: 443], -# https: [ -# port: 443, -# cipher_suite: :strong, -# keyfile: ssl_key_path, -# certfile: ssl_cert_path, -# transport_options: [socket_opts: [:inet6]] -# ] -# end diff --git a/config/runtime.exs b/config/runtime.exs new file mode 100644 index 000000000..1644c1ea5 --- /dev/null +++ b/config/runtime.exs @@ -0,0 +1,137 @@ +import Config + +require_db_ssl = + case System.get_env("REQUIRE_DB_SSL") do + "true" -> true + "false" -> false + _ -> true + end + +socket_options = + case System.get_env("USE_IP_V6") do + "true" -> [:inet6] + "false" -> [:inet] + _ -> [:inet] + end + +pool_size = String.to_integer(System.get_env("POOL_SIZE") || "10") + +if config_env() === :prod do + database_url = + System.get_env("DATABASE_URL") || + raise """ + environment variable DATABASE_URL is missing. + For example: ecto://USER:PASS@HOST/DATABASE + """ + + secret_key_base = + System.get_env("SECRET_KEY_BASE") || + raise """ + environment variable SECRET_KEY_BASE is missing. + You can generate one by calling: mix phx.gen.secret + """ + + backend_url = + System.get_env("BACKEND_URL") || + raise """ + environment variable BACKEND_URL is missing. + For example: myselfhostedwebsite.com or papercups.io + """ + + # Configure your database + config :chat_api, ChatApi.Repo, + ssl: require_db_ssl, + url: database_url, + show_sensitive_data_on_connection_error: false, + socket_options: socket_options, + pool_size: pool_size + + ssl_key_path = System.get_env("SSL_KEY_PATH") + ssl_cert_path = System.get_env("SSL_CERT_PATH") + https = (ssl_cert_path && ssl_key_path) != nil + port = String.to_integer(System.get_env("PORT") || "4000") + + config :chat_api, ChatApiWeb.Endpoint, + http: [ + port: port, + compress: true, + transport_options: [socket_opts: [:inet6]] + ], + url: [host: backend_url], + pubsub_server: ChatApi.PubSub, + secret_key_base: secret_key_base, + server: true, + check_origin: false + + if https do + config :chat_api, ChatApiWeb.Endpoint, + https: [ + port: 443, + cipher_suite: :strong, + otp_app: :chat_api, + keyfile: ssl_key_path, + certfile: ssl_cert_path + ], + force_ssl: [rewrite_on: [:x_forwarded_proto]] + end +end + +# Optional +sentry_dsn = System.get_env("SENTRY_DSN") +mailgun_api_key = System.get_env("MAILGUN_API_KEY") + +# Configure Sentry +config :sentry, + dsn: sentry_dsn, + environment_name: config_env(), + included_environments: [:prod], + enable_source_code_context: true, + root_source_code_path: File.cwd!() + +config :logger, + backends: [:console, Sentry.LoggerBackend] + +config :logger, Sentry.LoggerBackend, + # Also send warn messages + level: :warn, + # Send messages from Plug/Cowboy + excluded_domains: [], + # Send messages like `Logger.error("error")` to Sentry + capture_log_messages: true + +# Domain is the email address that mailgun is sent from +domain = System.get_env("DOMAIN") +# Configure Mailgun +config :chat_api, ChatApi.Mailers.Mailgun, + adapter: Swoosh.Adapters.Mailgun, + api_key: mailgun_api_key, + domain: domain + +site_id = System.get_env("CUSTOMER_IO_SITE_ID") +customerio_api_key = System.get_env("CUSTOMER_IO_API_KEY") + +config :customerio, + site_id: site_id, + api_key: customerio_api_key + +aws_key_id = System.get_env("AWS_ACCESS_KEY_ID") +aws_secret_key = System.get_env("AWS_SECRET_ACCESS_KEY") +bucket_name = System.get_env("BUCKET_NAME", "papercups-files") +region = System.get_env("AWS_REGION") + +config :ex_aws, + access_key_id: aws_key_id, + secret_access_key: aws_secret_key, + s3: [ + scheme: "https://", + host: bucket_name <> ".s3.amazonaws.com", + region: region + ] + +case System.get_env("PAPERCUPS_STRIPE_SECRET") do + "sk_" <> _rest = api_key -> + config :stripity_stripe, api_key: api_key + + _ -> + nil +end diff --git a/config/test.exs b/config/test.exs index bfaed86a0..167e24f68 100644 --- a/config/test.exs +++ b/config/test.exs @@ -11,6 +11,7 @@ config :chat_api, ChatApi.Repo, database: "chat_api_test#{System.get_env("MIX_TEST_PARTITION")}", hostname: "localhost", port: System.get_env("DATABASE_PORT") || 5432, + ssl: false, pool: Ecto.Adapters.SQL.Sandbox, # increase pool queue timeout_ms since async test # in sandbox mode may produces get connection timeout diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 0cd484cda..eee5a405b 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -12,9 +12,11 @@ services: environment: DATABASE_URL: "ecto://postgres:postgres@db/postgres" # PUT YOUR OWN SECRET KEYBASE HERE - SECRET_KEY_BASE: 'dvPPvOjpgX2Wk8Y3ONrqWsgM9ZtU4sSrs4l/5CFD1sLm4H+CjLU+EidjNGuSz7bz' + SECRET_KEY_BASE: "dvPPvOjpgX2Wk8Y3ONrqWsgM9ZtU4sSrs4l/5CFD1sLm4H+CjLU+EidjNGuSz7bz" BACKEND_URL: "localhost" MIX_ENV: "prod" + REQUIRE_DB_SSL: "false" + REACT_APP_FILE_UPLOADS_ENABLED: 1 db: image: postgres:alpine container_name: papercups diff --git a/elixir_buildpack.config b/elixir_buildpack.config index 4f1ee7491..e019683a8 100644 --- a/elixir_buildpack.config +++ b/elixir_buildpack.config @@ -1,5 +1,5 @@ # Elixir version -elixir_version=1.10.4 +elixir_version=1.11.3 # Erlang version # available versions https://github.com/HashNuke/heroku-buildpack-elixir-otp-builds/blob/master/otp-versions