diff --git a/.github/workflows/cache.yml b/.github/workflows/cache.yml index c6d325e..525fc70 100644 --- a/.github/workflows/cache.yml +++ b/.github/workflows/cache.yml @@ -17,7 +17,7 @@ jobs: - name: Build docker image from cache run: | docker pull docker.pkg.github.com/felipelincoln/branchpage/dev-cache:latest - docker build --build-arg MIX_ENV=test --cache-from docker.pkg.github.com/felipelincoln/branchpage/dev-cache:latest --tag new-cache . + docker build --target build --build-arg MIX_ENV=test --cache-from docker.pkg.github.com/felipelincoln/branchpage/dev-cache:latest --tag new-cache . - name: Push new cache image run: | diff --git a/.github/workflows/elixir.yml b/.github/workflows/elixir.yml index 8519b0e..7f3ca08 100644 --- a/.github/workflows/elixir.yml +++ b/.github/workflows/elixir.yml @@ -12,10 +12,23 @@ jobs: - name: Login to GitHub container registry run: echo ${{ secrets.WRITE_PACKAGE_TOKEN }} | docker login docker.pkg.github.com -u felipelincoln --password-stdin - - name: Docker build + - name: Build Docker image from cache run: | docker pull docker.pkg.github.com/felipelincoln/branchpage/dev-cache:latest - docker build --tag branchpage:latest --build-arg MIX_ENV=test --cache-from docker.pkg.github.com/felipelincoln/branchpage/dev-cache:latest . + docker build --target build --build-arg MIX_ENV=test --cache-from docker.pkg.github.com/felipelincoln/branchpage/dev-cache:latest --tag branchpage:latest . + + - name: Start container + run: docker-compose run -d -e MIX_ENV=test -e CODECOV_TOKEN=${{ secrets.CODECOV_TOKEN }} -v /branchpage/deps -v /branchpage/_build --name branchpage web /bin/sh + + - name: Code format + run: docker exec branchpage mix format --check-formatted + + - name: Code consistency + run: docker exec branchpage mix credo --strict - name: Test - run: docker run --rm -e MIX_ENV=test branchpage mix test + run: | + docker exec branchpage mix coveralls.json --umbrella + docker exec branchpage curl -s https://codecov.io/bash -o upload.sh + docker exec branchpage bash upload.sh + diff --git a/Dockerfile b/Dockerfile index 1bc7664..a6b275a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,24 @@ -FROM elixir:1.11-alpine +# ----------------- +# BASE +# ----------------- +FROM hexpm/elixir:1.11.4-erlang-23.2.7.2-alpine-3.13.3 AS base -# setup compile env -WORKDIR /app -ARG MIX_ENV=prod +WORKDIR /branchpage -# install hex and rebar RUN mix do local.hex --force, local.rebar --force -# install dependencies -RUN apk add npm inotify-tools +RUN apk add inotify-tools + + +# ----------------- +# BUILD +# ----------------- +FROM base AS build + +RUN apk add curl bash git + +ARG MIX_ENV=prod +ENV MIX_ENV=$MIX_ENV # install mix dependencies COPY mix.exs mix.lock ./ @@ -16,20 +26,46 @@ COPY apps/web/mix.exs apps/web/mix.exs COPY config config RUN mix do deps.get, deps.compile --skip-umbrella-children +# install application +COPY . ./ +RUN mix compile + + +# ----------------- +# RELEASE +# ----------------- +FROM build AS release + +RUN apk add npm + # install node dependencies -COPY apps/web/assets/package.json apps/web/assets/package-lock.json apps/web/assets/ RUN npm ci --prefix ./apps/web/assets --no-audit # generate static files -COPY apps/web apps/web RUN npm run --prefix ./apps/web/assets deploy # digests and compresses static files RUN mix phx.digest -# install umbrella apps -COPY . ./ -RUN mix compile +# generate release executable +RUN mix release + + +# ----------------- +# PRODUCTION +# ----------------- +FROM alpine:3.13.3 + +WORKDIR /branchpage + +ARG MIX_ENV=prod +ENV MIX_ENV=$MIX_ENV + +# install dependencies +RUN apk add ncurses-libs curl + +COPY --from=release /branchpage/_build/$MIX_ENV/rel/web ./ # start application -CMD ["mix", "phx.server"] +CMD ["bin/web", "start"] + diff --git a/apps/web/lib/web.ex b/apps/web/lib/web.ex index 2b825f0..85fdf3a 100644 --- a/apps/web/lib/web.ex +++ b/apps/web/lib/web.ex @@ -1,2 +1,3 @@ defmodule Web do + @moduledoc false end diff --git a/apps/web/lib/web/application.ex b/apps/web/lib/web/application.ex index 08eddde..437494c 100644 --- a/apps/web/lib/web/application.ex +++ b/apps/web/lib/web/application.ex @@ -1,4 +1,6 @@ defmodule Web.Application do + @moduledoc false + use Application def start(_type, _args) do diff --git a/apps/web/lib/web/live/article_live.ex b/apps/web/lib/web/live/article_live.ex index bddc7e0..21a8714 100644 --- a/apps/web/lib/web/live/article_live.ex +++ b/apps/web/lib/web/live/article_live.ex @@ -1,4 +1,6 @@ defmodule Web.ArticleLive do + @moduledoc false + use Phoenix.LiveView import Phoenix.HTML, only: [raw: 1] diff --git a/apps/web/lib/web/live/blog_live.ex b/apps/web/lib/web/live/blog_live.ex index c1be83f..de27f4c 100644 --- a/apps/web/lib/web/live/blog_live.ex +++ b/apps/web/lib/web/live/blog_live.ex @@ -1,4 +1,6 @@ defmodule Web.BlogLive do + @moduledoc false + use Phoenix.LiveView import Phoenix.HTML, only: [raw: 1] diff --git a/apps/web/lib/web/live/home_live.ex b/apps/web/lib/web/live/home_live.ex index 73c40ee..8c50c8b 100644 --- a/apps/web/lib/web/live/home_live.ex +++ b/apps/web/lib/web/live/home_live.ex @@ -1,4 +1,6 @@ defmodule Web.HomeLive do + @moduledoc false + use Phoenix.LiveView import Phoenix.HTML, only: [raw: 1] diff --git a/apps/web/lib/web/live/new_live.ex b/apps/web/lib/web/live/new_live.ex index 49d270c..f2c1f36 100644 --- a/apps/web/lib/web/live/new_live.ex +++ b/apps/web/lib/web/live/new_live.ex @@ -1,4 +1,6 @@ defmodule Web.NewLive do + @moduledoc false + use Phoenix.LiveView import Phoenix.HTML, only: [raw: 1] diff --git a/apps/web/lib/web/live/search_live.ex b/apps/web/lib/web/live/search_live.ex index 8ea3d51..12ebb89 100644 --- a/apps/web/lib/web/live/search_live.ex +++ b/apps/web/lib/web/live/search_live.ex @@ -1,4 +1,6 @@ defmodule Web.SearchLive do + @moduledoc false + use Phoenix.LiveView import Phoenix.HTML, only: [raw: 1] diff --git a/apps/web/mix.exs b/apps/web/mix.exs index 9625a54..c3af783 100644 --- a/apps/web/mix.exs +++ b/apps/web/mix.exs @@ -12,6 +12,7 @@ defmodule Web.MixProject do elixir: "~> 1.11", compilers: [:phoenix] ++ Mix.compilers(), start_permanent: Mix.env() == :prod, + test_coverage: [tool: ExCoveralls], deps: deps() ] end @@ -28,7 +29,7 @@ defmodule Web.MixProject do {:phoenix, "~> 1.5.8"}, {:phoenix_html, "~> 2.14"}, {:phoenix_live_view, "~> 0.15.4"}, - {:phoenix_live_reload, "~> 1.3"}, + {:phoenix_live_reload, "~> 1.3", only: :dev}, {:plug_cowboy, "~> 2.0"}, {:jason, "~> 1.2"}, {:timex, "~> 3.0"} diff --git a/config/prod.exs b/config/prod.exs index 2e88856..826a4dd 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -2,6 +2,7 @@ import Config config :web, Web.Endpoint, http: [port: {:system, "PORT"}], + server: true, cache_static_manifest: "priv/static/cache_manifest.json", check_origin: ["//branchpage.com", "//*.branchpage.com"] diff --git a/config/releases.exs b/config/releases.exs new file mode 100644 index 0000000..becde76 --- /dev/null +++ b/config/releases.exs @@ -0,0 +1 @@ +import Config diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..b5a99a7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +version: "3.8" + +services: + web: + build: + context: . + target: base + image: branchpage:latest + container_name: branchpage_web + command: mix phx.server + restart: unless-stopped + ports: + - 4000:4000 + volumes: + - .:/branchpage diff --git a/mix.exs b/mix.exs index 5059459..bab9e53 100644 --- a/mix.exs +++ b/mix.exs @@ -1,4 +1,4 @@ -defmodule BranchPage.MixProject do +defmodule BranchPage.Umbrella.MixProject do use Mix.Project def project do @@ -6,11 +6,30 @@ defmodule BranchPage.MixProject do apps_path: "apps", version: "0.1.0", start_permanent: Mix.env() == :prod, - deps: deps() + preferred_cli_env: [coveralls: :test, ci: :test], + test_coverage: [tool: ExCoveralls], + deps: deps(), + aliases: aliases(), + releases: releases() ] end defp deps do - [] + [ + {:credo, "~> 1.5", only: [:dev, :test], runtime: false}, + {:excoveralls, "== 0.13.3", only: [:dev, :test]} + ] + end + + defp aliases do + [ + ci: ["format --check-formatted", "credo --strict", "test"] + ] + end + + defp releases do + [ + web: [applications: [web: :permanent]] + ] end end diff --git a/mix.lock b/mix.lock index 9e11dfb..bf7a199 100644 --- a/mix.lock +++ b/mix.lock @@ -1,9 +1,12 @@ %{ - "certifi": {:hex, :certifi, "2.5.3", "70bdd7e7188c804f3a30ee0e7c99655bc35d8ac41c23e12325f36ab449b70651", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "ed516acb3929b101208a9d700062d520f3953da3b6b918d866106ffa980e1c10"}, + "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, + "certifi": {:hex, :certifi, "2.6.1", "dbab8e5e155a0763eea978c913ca280a6b544bfa115633fa20249c3d396d9493", [:rebar3], [], "hexpm", "524c97b4991b3849dd5c17a631223896272c6b0af446778ba4675a1dff53bb7e"}, "combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"}, "cowboy": {:hex, :cowboy, "2.8.0", "f3dc62e35797ecd9ac1b50db74611193c29815401e53bac9a5c0577bd7bc667d", [:rebar3], [{:cowlib, "~> 2.9.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "4643e4fba74ac96d4d152c75803de6fad0b3fa5df354c71afdd6cbeeb15fac8a"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.3.1", "ebd1a1d7aff97f27c66654e78ece187abdc646992714164380d8a041eda16754", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a6efd3366130eab84ca372cbd4a7d3c3a97bdfcfb4911233b035d117063f0af"}, "cowlib": {:hex, :cowlib, "2.9.1", "61a6c7c50cf07fdd24b2f45b89500bb93b6686579b069a89f88cb211e1125c78", [:rebar3], [], "hexpm", "e4175dc240a70d996156160891e1c62238ede1729e45740bdd38064dad476170"}, + "credo": {:hex, :credo, "1.5.5", "e8f422026f553bc3bebb81c8e8bf1932f498ca03339856c7fec63d3faac8424b", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "dd8623ab7091956a855dc9f3062486add9c52d310dfd62748779c4315d8247de"}, + "excoveralls": {:hex, :excoveralls, "0.13.3", "edc5f69218f84c2bf61b3609a22ddf1cec0fbf7d1ba79e59f4c16d42ea4347ed", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cc26f48d2f68666380b83d8aafda0fffc65dafcc8d8650358e0b61f6a99b1154"}, "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, "gettext": {:hex, :gettext, "0.18.2", "7df3ea191bb56c0309c00a783334b288d08a879f53a7014341284635850a6e55", [:mix], [], "hexpm", "f9f537b13d4fdd30f3039d33cb80144c3aa1f8d9698e47d7bcbcc8df93b1f5c5"}, "hackney": {:hex, :hackney, "1.17.0", "717ea195fd2f898d9fe9f1ce0afcc2621a41ecfe137fae57e7fe6e9484b9aa99", [:rebar3], [{:certifi, "~>2.5", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "64c22225f1ea8855f584720c0e5b3cd14095703af1c9fbc845ba042811dc671c"}, @@ -12,7 +15,7 @@ "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mime": {:hex, :mime, "1.5.0", "203ef35ef3389aae6d361918bf3f952fa17a09e8e43b5aa592b93eba05d0fb8d", [:mix], [], "hexpm", "55a94c0f552249fc1a3dd9cd2d3ab9de9d3c89b559c2bd01121f824834f24746"}, "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, - "parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"}, + "parse_trans": {:hex, :parse_trans, "3.4.0", "bb87ac362a03ca674ebb7d9d498f45c03256aded7214c9101f7035ef44b798c7", [:rebar3], [], "hexpm", "f99e368830bea44552224e37e04943a54874f08b8590485de8d13832b63a2dc3"}, "phoenix": {:hex, :phoenix, "1.5.8", "71cfa7a9bb9a37af4df98939790642f210e35f696b935ca6d9d9c55a884621a4", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "35ded0a32f4836168c7ab6c33b88822eccd201bcd9492125a9bea4c54332d955"}, "phoenix_html": {:hex, :phoenix_html, "2.14.3", "51f720d0d543e4e157ff06b65de38e13303d5778a7919bcc696599e5934271b8", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "efd697a7fff35a13eeeb6b43db884705cba353a1a41d127d118fda5f90c8e80f"}, "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.3.0", "f35f61c3f959c9a01b36defaa1f0624edd55b87e236b606664a556d6f72fd2e7", [: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", "02c1007ae393f2b76ec61c1a869b1e617179877984678babde131d716f95b582"},