mirror of
https://github.com/fly-apps/live_beats.git
synced 2024-11-24 17:01:00 +00:00
Deploy and presence stub
This commit is contained in:
parent
1a68db73f3
commit
364b0659e1
24 changed files with 332 additions and 55 deletions
2
.dockerignore
Normal file
2
.dockerignore
Normal file
|
@ -0,0 +1,2 @@
|
|||
priv/uploads
|
||||
deps/
|
98
Dockerfile
Normal file
98
Dockerfile
Normal file
|
@ -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
|
|
@ -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`
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
42
fly.toml
Normal file
42
fly.toml
Normal file
|
@ -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"
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
28
lib/live_beats/release.ex
Normal file
28
lib/live_beats/release.ex
Normal file
|
@ -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
|
34
lib/live_beats_web/channels/presence.ex
Normal file
34
lib/live_beats_web/channels/presence.ex
Normal file
|
@ -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"""
|
||||
<!-- users -->
|
||||
<div class="px-4 mt-6 sm:px-6 lg:px-8">
|
||||
<h2 class="text-gray-500 text-xs font-medium uppercase tracking-wide">Who's Here</h2>
|
||||
<ul role="list" class="grid grid-cols-1 gap-4 sm:gap-4 sm:grid-cols-2 xl:grid-cols-5 mt-3" x-max="1">
|
||||
<%= for presence <- @presences do %>
|
||||
<li class="relative col-span-1 flex shadow-sm rounded-md overflow-hidden">
|
||||
<.link redirect_to={profile_path(presence)} class="flex-1 flex items-center justify-between border-t border-r border-b border-gray-200 bg-white rounded-r-md truncate">
|
||||
<img class="w-10 h-10 flex-shrink-0 flex items-center justify-center rounded-l-md bg-purple-600" src={presence.avatar_url} alt="">
|
||||
<div class="flex-1 flex items-center justify-between text-gray-900 text-sm font-medium hover:text-gray-600 pl-3">
|
||||
<%= render_slot(@title, presence) %>
|
||||
</div>
|
||||
</.link>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
end
|
|
@ -70,7 +70,7 @@ defmodule LiveBeatsWeb.UserAuth do
|
|||
|
||||
conn
|
||||
|> renew_session()
|
||||
|> redirect(to: "/")
|
||||
|> redirect(to: Routes.sign_in_path(conn, :index))
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
|
|
@ -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 %>
|
||||
|
|
|
@ -12,7 +12,7 @@ defmodule LiveBeatsWeb.SignInLive do
|
|||
<p class="mt-2 text-center text-sm text-gray-600">
|
||||
Or
|
||||
<a href="#" class="font-medium text-indigo-600 hover:text-indigo-500">
|
||||
start your 14-day free trial
|
||||
listen now without signing in (TODO)
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
@ -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 %>
|
||||
<div>
|
||||
<div class="block">
|
||||
<%= @profile.tagline %> <%= if @owns_profile? do %>(you)<% end %>
|
||||
</div>
|
||||
<.link href={@profile.external_homepage_url} _target="blank" class="block text-sm text-gray-600">
|
||||
<.icon name={:code}/> <span class=""><%= url_text(@profile.external_homepage_url) %></span>
|
||||
</.link>
|
||||
</div>
|
||||
|
||||
<:actions>
|
||||
<%= if @active_profile_id == @profile.user_id do %>
|
||||
|
@ -32,6 +39,11 @@ defmodule LiveBeatsWeb.SongLive.Index do
|
|||
</:actions>
|
||||
</.title_bar>
|
||||
|
||||
<Presence.listening_now presences={@presences}>
|
||||
<:abbrev let={user}><%= String.first(user.username) %></:abbrev>
|
||||
<:title let={user}><%= user.username %></:title>
|
||||
</Presence.listening_now>
|
||||
|
||||
<%= 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
|
||||
|
|
|
@ -124,7 +124,7 @@
|
|||
>
|
||||
<span class="sr-only">Open user menu</span>
|
||||
<img class="h-8 w-8 rounded-full"
|
||||
src="https://images.unsplash.com/photo-1502685104226-ee32379fefbe?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
|
||||
src={@current_user.avatar_url}
|
||||
alt="">
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -74,7 +74,7 @@ defmodule LiveBeatsWeb.LayoutView do
|
|||
<span class="flex w-full justify-between items-center">
|
||||
<span class="flex min-w-0 items-center justify-between space-x-3">
|
||||
<img class="w-10 h-10 bg-gray-300 rounded-full flex-shrink-0"
|
||||
src="https://images.unsplash.com/photo-1502685104226-ee32379fefbe?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=3&w=256&h=256&q=80"
|
||||
src={@current_user.avatar_url}
|
||||
alt="">
|
||||
<span class="flex-1 flex flex-col min-w-0">
|
||||
<span class="text-gray-900 text-sm font-medium truncate"><%= @current_user.name %></span>
|
||||
|
|
10
mix.exs
10
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"
|
||||
]
|
||||
|
|
4
mix.lock
4
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"},
|
||||
|
|
|
@ -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
|
6
rel/env.bat.eex
Normal file
6
rel/env.bat.eex
Normal file
|
@ -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
|
6
rel/env.sh.eex
Normal file
6
rel/env.sh.eex
Normal file
|
@ -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"
|
11
rel/remote.vm.args.eex
Normal file
11
rel/remote.vm.args.eex
Normal file
|
@ -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
|
11
rel/vm.args.eex
Normal file
11
rel/vm.args.eex
Normal file
|
@ -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
|
Loading…
Reference in a new issue