diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..7c59f61 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +priv/uploads +deps/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2b9b569 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,98 @@ +# Find eligible builder and runner images on Docker Hub. We use Ubuntu/Debian instead of +# Alpine to avoid DNS resolution issues in production. +# +# https://hub.docker.com/r/hexpm/elixir/tags?page=1&name=ubuntu +# https://hub.docker.com/_/ubuntu?tab=tags +# +# +# This file is based on these images: +# +# - https://hub.docker.com/r/hexpm/elixir/tags - for the build image +# - https://hub.docker.com/_/debian?tab=tags&page=1&name=bullseye-20210902-slim - for the release image +# - https://pkgs.org/ - resource for finding needed packages +# - Ex: hexpm/elixir:1.12.3-erlang-24.1.4-debian-bullseye-20210902-slim +# +ARG BUILDER_IMAGE="hexpm/elixir:1.12.3-erlang-24.1.4-debian-bullseye-20210902-slim" +ARG RUNNER_IMAGE="debian:bullseye-20210902-slim" + +FROM ${BUILDER_IMAGE} as builder + +# install build dependencies +RUN apt-get update -y && apt-get install -y build-essential git \ + && apt-get clean && rm -f /var/lib/apt/lists/*_* + +# prepare build dir +WORKDIR /app + +# install hex + rebar +RUN mix local.hex --force && \ + mix local.rebar --force + +# set build ENV +ENV MIX_ENV="prod" + +# install mix dependencies +COPY mix.exs mix.lock ./ +RUN mix deps.get --only $MIX_ENV +RUN mkdir config + +# copy compile-time config files before we compile dependencies +# to ensure any relevant config change will trigger the dependencies +# to be re-compiled. +COPY config/config.exs config/${MIX_ENV}.exs config/ +RUN mix deps.compile + +COPY priv priv + +# note: if your project uses a tool like https://purgecss.com/, +# which customizes asset compilation based on what it finds in +# your Elixir templates, you will need to move the asset compilation +# step down so that `lib` is available. +COPY assets assets + +# For Phoenix 1.6 and later, compile assets using esbuild +RUN mix assets.deploy + +# For Phoenix versions earlier than 1.6, compile assets npm +# RUN cd assets && yarn install && yarn run webpack --mode production +# RUN mix phx.digest + +# Compile the release +COPY lib lib + +RUN mix compile + +# Changes to config/runtime.exs don't require recompiling the code +COPY config/runtime.exs config/ + +COPY rel rel +RUN mix release + +# start a new build stage so that the final image will only contain +# the compiled release and other runtime necessities +FROM ${RUNNER_IMAGE} + +RUN apt-get update -y && apt-get install -y libstdc++6 openssl libncurses5 locales \ + && apt-get clean && rm -f /var/lib/apt/lists/*_* + +# Set the locale +RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen + +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + +WORKDIR "/app" +RUN chown nobody /app + +# Only copy the final release from the build stage +COPY --from=builder --chown=nobody:root /app/_build/prod/rel ./ + +USER nobody + +# Create a symlink to the application directory by extracting the directory name. This is required +# since the release directory will be named after the application, and we don't know that name. +RUN set -eux; \ + ln -nfs /app/$(basename *)/bin/$(basename *) /app/entry + +CMD /app/entry start \ No newline at end of file diff --git a/README.md b/README.md index 427ad23..edbd77b 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,12 @@ Play music together with Phoenix LiveView! Visit [todo]() to try it out, or run locally: * Create a [Github OAuth app](https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app) - * Export your GitHub client ID and secret: + - Set the app homepage to `http://localhost:4000` and `Authorization callback URL` to `http://localhost:4000/oauth/callbacks/github` + - After completing the form, click "Generate a new client secret" to obtain your API secret + * Export your GitHub Client ID and secret: - export LIVE_BEATS_GITHUB_CLIENT_ID="..." - export LIVE_BEATS_GITHUB_CLIENT_SECRET="..." + export LIVE_BEATS_GITHUB_CLIENT_ID="..." + export LIVE_BEATS_GITHUB_CLIENT_SECRET="..." * Install dependencies with `mix deps.get` * Create and migrate your database with `mix ecto.setup` diff --git a/assets/js/app.js b/assets/js/app.js index e696062..872b831 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -1,7 +1,7 @@ import "phoenix_html" import {Socket} from "phoenix" -import {LiveSocket} from "./phoenix_live_view" -// import {LiveSocket} from "phoenix_live_view" +// import {LiveSocket} from "./phoenix_live_view" +import {LiveSocket} from "phoenix_live_view" import topbar from "../vendor/topbar" let nowSeconds = () => Math.round(Date.now() / 1000) @@ -33,8 +33,10 @@ Hooks.AudioPlayer = { let enableAudio = () => { if(this.player.src){ document.removeEventListener("click", enableAudio) - this.player.play().catch(error => null) - this.player.pause() + if(this.player.readyState === 0){ + this.player.play().catch(error => null) + this.player.pause() + } } } document.addEventListener("click", enableAudio) diff --git a/config/runtime.exs b/config/runtime.exs index 18490b6..76f2616 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -14,9 +14,11 @@ if config_env() == :prod do For example: ecto://USER:PASS@HOST/DATABASE """ + ipv6? = !!System.get_env("IPV6") + config :live_beats, LiveBeats.Repo, # ssl: true, - # socket_options: [:inet6], + socket_options: if(ipv6?, do: [:inet6], else: []), url: database_url, pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10") @@ -27,7 +29,11 @@ if config_env() == :prod do You can generate one by calling: mix phx.gen.secret """ + app_name = System.fetch_env!("FLY_APP_NAME") + host = System.get_env("URL_HOST") || "example.com" + config :live_beats, LiveBeatsWeb.Endpoint, + url: [host: host, port: 80], http: [ # Enable IPv6 and bind on all interfaces. # Set it to {0, 0, 0, 0, 0, 0, 0, 1} for local network only access. @@ -36,33 +42,18 @@ if config_env() == :prod do ip: {0, 0, 0, 0, 0, 0, 0, 0}, port: String.to_integer(System.get_env("PORT") || "4000") ], - secret_key_base: secret_key_base + check_origin: ["//#{host}"], + secret_key_base: secret_key_base, + server: true - # ## Using releases - # - # If you are doing OTP releases, you need to instruct Phoenix - # to start each relevant endpoint: - # - # config :live_beats, LiveBeatsWeb.Endpoint, server: true - # - # Then you can assemble a release by calling `mix release`. - # See `mix help release` for more information. + config :live_beats, :file_host, %{ + scheme: "http", + host: host, + port: 80 + } - # ## Configuring the mailer - # - # In production you need to configure the mailer to use a different adapter. - # Also, you may need to configure the Swoosh API client of your choice if you - # are not using SMTP. Here is an example of the configuration: - # - # config :live_beats, LiveBeats.Mailer, - # adapter: Swoosh.Adapters.Mailgun, - # api_key: System.get_env("MAILGUN_API_KEY"), - # domain: System.get_env("MAILGUN_DOMAIN") - # - # For this example you need include a HTTP client required by Swoosh API client. - # Swoosh supports Hackney and Finch out of the box: - # - # config :swoosh, :api_client, Swoosh.ApiClient.Hackney - # - # See https://hexdocs.pm/swoosh/Swoosh.html#module-installation for details. + config :live_beats, :github, %{ + client_id: System.fetch_env!("LIVE_BEATS_GITHUB_CLIENT_ID"), + client_secret: System.fetch_env!("LIVE_BEATS_GITHUB_CLIENT_SECRET"), + } end diff --git a/fly.toml b/fly.toml new file mode 100644 index 0000000..5f07bf5 --- /dev/null +++ b/fly.toml @@ -0,0 +1,42 @@ +app = "livebeats" + +kill_signal = "SIGTERM" +kill_timeout = 5 +processes = [] + +[deploy] + release_command = "/app/entry eval LiveBeats.Release.migrate" + +[env] + IPV6 = 1 + URL_HOST = "livebeats.fly.dev" + +[experimental] + allowed_public_ports = [] + auto_rollback = true + +[[services]] + http_checks = [] + internal_port = 4000 + processes = ["app"] + protocol = "tcp" + script_checks = [] + + [services.concurrency] + hard_limit = 25 + soft_limit = 20 + type = "connections" + + [[services.ports]] + handlers = ["http"] + port = 80 + + [[services.ports]] + handlers = ["tls", "http"] + port = 443 + + [[services.tcp_checks]] + grace_period = "30s" # allow some time for startup + interval = "15s" + restart_limit = 0 + timeout = "2s" \ No newline at end of file diff --git a/lib/live_beats/accounts/user.ex b/lib/live_beats/accounts/user.ex index b61caa9..e6c007f 100644 --- a/lib/live_beats/accounts/user.ex +++ b/lib/live_beats/accounts/user.ex @@ -12,6 +12,8 @@ defmodule LiveBeats.Accounts.User do field :role, :string, default: "subscriber" field :profile_tagline, :string field :active_profile_user_id, :id + field :avatar_url, :string + field :external_homepage_url, :string has_many :identities, Identity @@ -22,7 +24,7 @@ defmodule LiveBeats.Accounts.User do A user changeset for github registration. """ def github_registration_changeset(info, primary_email, emails, token) do - %{"login" => username} = info + %{"login" => username, "avatar_url" => avatar_url, "html_url" => external_homepage_url} = info identity_changeset = Identity.github_registration_changeset(info, primary_email, emails, token) @@ -31,11 +33,13 @@ defmodule LiveBeats.Accounts.User do params = %{ "username" => username, "email" => primary_email, - "name" => get_change(identity_changeset, :provider_name) + "name" => get_change(identity_changeset, :provider_name), + "avatar_url" => avatar_url, + "external_homepage_url" => external_homepage_url } %User{} - |> cast(params, [:email, :name, :username]) + |> cast(params, [:email, :name, :username, :avatar_url, :external_homepage_url]) |> validate_required([:email, :name, :username]) |> validate_username() |> validate_email() diff --git a/lib/live_beats/media_library.ex b/lib/live_beats/media_library.ex index 8d227e2..46fbace 100644 --- a/lib/live_beats/media_library.ex +++ b/lib/live_beats/media_library.ex @@ -203,7 +203,7 @@ defmodule LiveBeats.MediaLibrary do where: s.status in [:playing], limit: ^Keyword.fetch!(opts, :limit), order_by: [desc: s.updated_at], - select: struct(u, [:id, :username, :profile_tagline]) + select: struct(u, [:id, :username, :profile_tagline, :avatar_url, :external_homepage_url]) ) |> Repo.all() |> Enum.map(&get_profile!/1) @@ -214,7 +214,13 @@ defmodule LiveBeats.MediaLibrary do end def get_profile!(%Accounts.User{} = user) do - %Profile{user_id: user.id, username: user.username, tagline: user.profile_tagline} + %Profile{ + user_id: user.id, + username: user.username, + tagline: user.profile_tagline, + avatar_url: user.avatar_url, + external_homepage_url: user.external_homepage_url + } end def owns_profile?(%Accounts.User{} = user, %Profile{} = profile) do diff --git a/lib/live_beats/media_library/profile.ex b/lib/live_beats/media_library/profile.ex index a8a1026..815b2d6 100644 --- a/lib/live_beats/media_library/profile.ex +++ b/lib/live_beats/media_library/profile.ex @@ -1,3 +1,3 @@ defmodule LiveBeats.MediaLibrary.Profile do - defstruct user_id: nil, username: nil, tagline: nil + defstruct user_id: nil, username: nil, tagline: nil, avatar_url: nil, external_homepage_url: nil end diff --git a/lib/live_beats/release.ex b/lib/live_beats/release.ex new file mode 100644 index 0000000..a39eb54 --- /dev/null +++ b/lib/live_beats/release.ex @@ -0,0 +1,28 @@ +defmodule LiveBeats.Release do + @moduledoc """ + Used for executing DB release tasks when run in production without Mix + installed. + """ + @app :live_beats + + 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 diff --git a/lib/live_beats_web/channels/presence.ex b/lib/live_beats_web/channels/presence.ex new file mode 100644 index 0000000..299464d --- /dev/null +++ b/lib/live_beats_web/channels/presence.ex @@ -0,0 +1,34 @@ +defmodule LiveBeatsWeb.Presence do + @moduledoc """ + Provides presence tracking to channels and processes. + + See the [`Phoenix.Presence`](http://hexdocs.pm/phoenix/Phoenix.Presence.html) + docs for more details. + """ + use Phoenix.Presence, otp_app: :live_beats, + pubsub_server: LiveBeats.PubSub + + import Phoenix.LiveView.Helpers + import LiveBeatsWeb.LiveHelpers + + def listening_now(assigns) do + ~H""" + +
+

Who's Here

+ +
+ """ + end +end diff --git a/lib/live_beats_web/controllers/user_auth.ex b/lib/live_beats_web/controllers/user_auth.ex index 02b881d..a646cde 100644 --- a/lib/live_beats_web/controllers/user_auth.ex +++ b/lib/live_beats_web/controllers/user_auth.ex @@ -70,7 +70,7 @@ defmodule LiveBeatsWeb.UserAuth do conn |> renew_session() - |> redirect(to: "/") + |> redirect(to: Routes.sign_in_path(conn, :index)) end @doc """ diff --git a/lib/live_beats_web/live/live_helpers.ex b/lib/live_beats_web/live/live_helpers.ex index a7e98f8..7e6608f 100644 --- a/lib/live_beats_web/live/live_helpers.ex +++ b/lib/live_beats_web/live/live_helpers.ex @@ -95,7 +95,7 @@ defmodule LiveBeatsWeb.LiveHelpers do assigns = assigns |> assign_new(:outlined, fn -> false end) - |> assign_new(:class, fn -> "w-4 h-4" end) + |> assign_new(:class, fn -> "w-4 h-4 inline-block" end) ~H""" <%= if @outlined do %> diff --git a/lib/live_beats_web/live/sign_in_live.ex b/lib/live_beats_web/live/sign_in_live.ex index 7b67750..90760df 100644 --- a/lib/live_beats_web/live/sign_in_live.ex +++ b/lib/live_beats_web/live/sign_in_live.ex @@ -12,7 +12,7 @@ defmodule LiveBeatsWeb.SignInLive do

Or - start your 14-day free trial + listen now without signing in (TODO)

diff --git a/lib/live_beats_web/live/song_live/index.ex b/lib/live_beats_web/live/song_live/index.ex index d6c59f6..43d8879 100644 --- a/lib/live_beats_web/live/song_live/index.ex +++ b/lib/live_beats_web/live/song_live/index.ex @@ -2,13 +2,20 @@ defmodule LiveBeatsWeb.SongLive.Index do use LiveBeatsWeb, :live_view alias LiveBeats.{Accounts, MediaLibrary, MP3Stat} - alias LiveBeatsWeb.LayoutComponent + alias LiveBeatsWeb.{LayoutComponent, Presence} alias LiveBeatsWeb.SongLive.{SongRowComponent, UploadFormComponent} def render(assigns) do ~H""" <.title_bar> - <%= @profile.tagline %> <%= if @owns_profile? do %>(you)<% end %> +
+
+ <%= @profile.tagline %> <%= if @owns_profile? do %>(you)<% end %> +
+ <.link href={@profile.external_homepage_url} _target="blank" class="block text-sm text-gray-600"> + <.icon name={:code}/> <%= url_text(@profile.external_homepage_url) %> + +
<:actions> <%= if @active_profile_id == @profile.user_id do %> @@ -32,6 +39,11 @@ defmodule LiveBeatsWeb.SongLive.Index do + + <:abbrev let={user}><%= String.first(user.username) %> + <:title let={user}><%= user.username %> + + <%= for song <- if(@owns_profile?, do: @songs, else: []), id = "delete-modal-#{song.id}" do %> <.modal id={id} @@ -89,6 +101,7 @@ defmodule LiveBeatsWeb.SongLive.Index do owns_profile?: MediaLibrary.owns_profile?(current_user, profile) ) |> list_songs() + |> assign_presences() {:ok, socket, temporary_assigns: [songs: []]} end @@ -216,4 +229,15 @@ defmodule LiveBeatsWeb.SongLive.Index do defp list_songs(socket) do assign(socket, songs: MediaLibrary.list_profile_songs(socket.assigns.profile, 50)) end + + defp assign_presences(socket) do + # TODO + assign(socket, presences: Accounts.list_users(limit: 10)) + end + + defp url_text(nil), do: "" + defp url_text(url_str) do + uri = URI.parse(url_str) + uri.host <> uri.path + end end diff --git a/lib/live_beats_web/templates/layout/live.html.heex b/lib/live_beats_web/templates/layout/live.html.heex index 2f8152d..a8bdfd1 100644 --- a/lib/live_beats_web/templates/layout/live.html.heex +++ b/lib/live_beats_web/templates/layout/live.html.heex @@ -124,7 +124,7 @@ > Open user menu diff --git a/lib/live_beats_web/views/layout_view.ex b/lib/live_beats_web/views/layout_view.ex index 007f114..f4823eb 100644 --- a/lib/live_beats_web/views/layout_view.ex +++ b/lib/live_beats_web/views/layout_view.ex @@ -74,7 +74,7 @@ defmodule LiveBeatsWeb.LayoutView do <%= @current_user.name %> diff --git a/mix.exs b/mix.exs index 1e92211..96dea1c 100644 --- a/mix.exs +++ b/mix.exs @@ -39,8 +39,8 @@ defmodule LiveBeats.MixProject do {:postgrex, ">= 0.0.0"}, {:phoenix_html, "~> 3.0"}, {:phoenix_live_reload, "~> 1.2", only: :dev}, - {:phoenix_live_view, path: "~/oss/phoenix_live_view", override: true}, - # {:phoenix_live_view, github: "phoenixframework/phoenix_live_view", branch: "cm-sticky-live-render", override: true}, + # {:phoenix_live_view, path: "~/oss/phoenix_live_view", override: true}, + {:phoenix_live_view, github: "phoenixframework/phoenix_live_view", branch: "cm-sticky-live-render", override: true}, {:floki, ">= 0.30.0", only: :test}, {:phoenix_live_dashboard, "~> 0.5"}, {:esbuild, "~> 0.2", runtime: Mix.env() == :dev}, @@ -51,7 +51,8 @@ defmodule LiveBeats.MixProject do {:jason, "~> 1.2"}, {:plug_cowboy, "~> 2.5"}, {:mint, "~> 1.0"}, - {:heroicons, "~> 0.2.2"} + {:heroicons, "~> 0.2.2"}, + {:castore, "~> 0.1.13"} ] end @@ -63,12 +64,11 @@ defmodule LiveBeats.MixProject do # See the documentation for `Mix` for more info on aliases. defp aliases do [ - setup: ["deps.get", "ecto.setup", "cmd --cd assets npm install"], + setup: ["deps.get", "ecto.setup"], "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"], "ecto.reset": ["ecto.drop", "ecto.setup"], test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"], "assets.deploy": [ - "cmd --cd assets npm run deploy", "esbuild default --minify", "phx.digest" ] diff --git a/mix.lock b/mix.lock index d045ef2..f9c1f6d 100644 --- a/mix.lock +++ b/mix.lock @@ -1,5 +1,5 @@ %{ - "castore": {:hex, :castore, "0.1.11", "c0665858e0e1c3e8c27178e73dffea699a5b28eb72239a3b2642d208e8594914", [:mix], [], "hexpm", "91b009ba61973b532b84f7c09ce441cba7aa15cb8b006cf06c6f4bba18220081"}, + "castore": {:hex, :castore, "0.1.13", "ccf3ab251ffaebc4319f41d788ce59a6ab3f42b6c27e598ad838ffecee0b04f9", [:mix], [], "hexpm", "a14a7eecfec7e20385493dbb92b0d12c5d77ecfd6307de10102d58c94e8c49c0"}, "connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"}, "cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, @@ -25,7 +25,7 @@ "phoenix_html": {:hex, :phoenix_html, "3.1.0", "0b499df05aad27160d697a9362f0e89fa0e24d3c7a9065c2bd9d38b4d1416c09", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "0c0a98a2cefa63433657983a2a594c7dee5927e4391e0f1bfd3a151d1def33fc"}, "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.5.0", "3282d8646e1bfc1ef1218f508d9fcefd48cf47f9081b7667bd9b281b688a49cf", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.6", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.16.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "609740be43de94ae0abd2c4300ff0356a6e8a9487bf340e69967643a59fa7ec8"}, "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.3.3", "3a53772a6118d5679bf50fc1670505a290e32a1d195df9e069d8c53ab040c054", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "766796676e5f558dbae5d1bdb066849673e956005e3730dfd5affd7a6da4abac"}, - "phoenix_live_view": {:git, "https://github.com/phoenixframework/phoenix_live_view.git", "fba1ff66483c20d1c163ee9cd3aa74024d196f17", [branch: "cm-sticky-live-render"]}, + "phoenix_live_view": {:git, "https://github.com/phoenixframework/phoenix_live_view.git", "0cb64f7b6082dc07e488d5547a35c32f8af18650", [branch: "cm-sticky-live-render"]}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"}, "phoenix_view": {:hex, :phoenix_view, "1.0.0", "fea71ecaaed71178b26dd65c401607de5ec22e2e9ef141389c721b3f3d4d8011", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "82be3e2516f5633220246e2e58181282c71640dab7afc04f70ad94253025db0c"}, "plug": {:hex, :plug, "1.12.1", "645678c800601d8d9f27ad1aebba1fdb9ce5b2623ddb961a074da0b96c35187d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d57e799a777bc20494b784966dc5fbda91eb4a09f571f76545b72a634ce0d30b"}, diff --git a/priv/repo/migrations/20211116125213_add_avatar_url_to_users.exs b/priv/repo/migrations/20211116125213_add_avatar_url_to_users.exs new file mode 100644 index 0000000..1b54e68 --- /dev/null +++ b/priv/repo/migrations/20211116125213_add_avatar_url_to_users.exs @@ -0,0 +1,10 @@ +defmodule LiveBeats.Repo.Migrations.AddAvatarUrlToUsers do + use Ecto.Migration + + def change do + alter table(:users) do + add :avatar_url, :string + add :external_homepage_url, :string + end + end +end diff --git a/rel/env.bat.eex b/rel/env.bat.eex new file mode 100644 index 0000000..22be280 --- /dev/null +++ b/rel/env.bat.eex @@ -0,0 +1,6 @@ +@echo off +rem Set the release to work across nodes. If using the long name format like +rem the one below (my_app@127.0.0.1), you need to also uncomment the +rem RELEASE_DISTRIBUTION variable below. Must be "sname", "name" or "none". +rem set RELEASE_DISTRIBUTION=name +rem set RELEASE_NODE=<%= @release.name %>@127.0.0.1 diff --git a/rel/env.sh.eex b/rel/env.sh.eex new file mode 100644 index 0000000..69cea06 --- /dev/null +++ b/rel/env.sh.eex @@ -0,0 +1,6 @@ +#!/bin/sh + +ip=$(grep fly-local-6pn /etc/hosts | cut -f 1) +export RELEASE_DISTRIBUTION=name +export RELEASE_NODE=$FLY_APP_NAME@$ip +export ELIXIR_ERL_OPTIONS="-proto_dist inet6_tcp" \ No newline at end of file diff --git a/rel/remote.vm.args.eex b/rel/remote.vm.args.eex new file mode 100644 index 0000000..5886aa8 --- /dev/null +++ b/rel/remote.vm.args.eex @@ -0,0 +1,11 @@ +## Customize flags given to the VM: https://erlang.org/doc/man/erl.html +## -mode/-name/-sname/-setcookie are configured via env vars, do not set them here + +## Number of dirty schedulers doing IO work (file, sockets, and others) +##+SDio 5 + +## Increase number of concurrent ports/sockets +##+Q 65536 + +## Tweak GC to run more often +##-env ERL_FULLSWEEP_AFTER 10 diff --git a/rel/vm.args.eex b/rel/vm.args.eex new file mode 100644 index 0000000..5886aa8 --- /dev/null +++ b/rel/vm.args.eex @@ -0,0 +1,11 @@ +## Customize flags given to the VM: https://erlang.org/doc/man/erl.html +## -mode/-name/-sname/-setcookie are configured via env vars, do not set them here + +## Number of dirty schedulers doing IO work (file, sockets, and others) +##+SDio 5 + +## Increase number of concurrent ports/sockets +##+Q 65536 + +## Tweak GC to run more often +##-env ERL_FULLSWEEP_AFTER 10