Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ jobs:
uses: actions/cache@v3
with:
path: deps
key: ${{ runner.os }}-mix-6-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ runner.os }}-mix-6
key: ${{ runner.os }}-mix-119-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ runner.os }}-mix-119
- name: Restore _build
uses: actions/cache@v3
with:
path: _build
key: ${{ runner.os }}-mix-6-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ runner.os }}-mix-6
key: ${{ runner.os }}-mix-119-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ runner.os }}-mix-119
- run: mix deps.get
- run: mix test
- uses: 8398a7/action-slack@v3
Expand Down
16 changes: 8 additions & 8 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,14 @@ jobs:
uses: actions/cache@v3
with:
path: deps
key: ${{ runner.os }}-mix-6-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ runner.os }}-mix-6
key: ${{ runner.os }}-mix-119-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ runner.os }}-mix-119
- name: Restore _build
uses: actions/cache@v3
with:
path: _build
key: ${{ runner.os }}-mix-6-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ runner.os }}-mix-6
key: ${{ runner.os }}-mix-119-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ runner.os }}-mix-119
- run: mix deps.get
- run: mix test
- uses: 8398a7/action-slack@v3
Expand All @@ -196,14 +196,14 @@ jobs:
uses: actions/cache@v3
with:
path: deps
key: ${{ runner.os }}-mix-6-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ runner.os }}-mix-6
key: ${{ runner.os }}-mix-119-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ runner.os }}-mix-119
- name: Restore _build
uses: actions/cache@v3
with:
path: _build
key: ${{ runner.os }}-mix-6-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ runner.os }}-mix-6
key: ${{ runner.os }}-mix-119-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ runner.os }}-mix-119
- name: get dependencies
run: mix deps.get
- name: update schema
Expand Down
4 changes: 2 additions & 2 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ stages:

build:
stage: test
# Align with Dockerfile / .tool-versions (Elixir 1.13.4). Bandit 1.11+ needs this.
image: hexpm/elixir:1.13.4-erlang-24.3-alpine-3.17.0
# Align with Dockerfile / .tool-versions (Elixir 1.19.4 / OTP 28.5).
image: hexpm/elixir:1.19.4-erlang-28.5-alpine-3.23.4
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
Expand Down
4 changes: 2 additions & 2 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
erlang 24.3.4.17
elixir 1.13.4
erlang 28.5
elixir 1.19.4
65 changes: 25 additions & 40 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,41 +1,31 @@
FROM bitwalker/alpine-elixir:1.13.4 AS builder
ARG ELIXIR_VERSION=1.19.4
ARG OTP_VERSION=28.5
ARG OS_VARIANT=alpine
ARG OS_VERSION=3.23.4
ARG RUNNER_IMAGE=alpine:3.23.4

FROM hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-${OS_VARIANT}-${OS_VERSION} AS builder

# The following are build arguments used to change variable parts of the image.
# The name of your application/release (required)
ARG APP_NAME
# The environment to build with
ARG MIX_ENV=prod

ENV APP_NAME=${APP_NAME} \
MIX_ENV=${MIX_ENV}
ENV MIX_ENV=${MIX_ENV}

# By convention, /opt is typically used for applications
WORKDIR /opt/app

# This step installs all the build tools we'll need
RUN apk update --allow-untrusted && \
apk upgrade --no-cache && \
apk add --no-cache \
git \
build-base && \
RUN apk update && apk upgrade --no-cache && \
apk add --no-cache git build-base curl ca-certificates && \
mix local.rebar --force && \
mix local.hex --force

# This copies our app source code into the build container
COPY . .

# needed so that we can get the app version from the git tag
RUN git config --global --add safe.directory '/opt/app'

RUN mix do deps.get, compile

RUN \
mkdir -p /opt/built && \
mix distillery.release --name ${APP_NAME} && \
cp _build/${MIX_ENV}/rel/${APP_NAME}/releases/*/${APP_NAME}.tar.gz /opt/built && \
cd /opt/built && \
tar -xzf ${APP_NAME}.tar.gz && \
rm ${APP_NAME}.tar.gz
ARG APP_NAME
ENV APP_NAME=${APP_NAME}
RUN mix release ${APP_NAME}

FROM alpine:3.21.7 as tools

Expand Down Expand Up @@ -85,39 +75,34 @@ RUN apk add --update --no-cache curl ca-certificates unzip wget openssl && \
chmod +x /usr/local/bin/helm /usr/local/bin/plural /usr/local/bin/trivy && \
rm -f /tmp/helm.tar.gz /tmp/plural-cli.tar.gz /tmp/trivy.tar.gz

FROM erlang:24.3.4.6-alpine
FROM ${RUNNER_IMAGE}

# The name of your application/release (required)
ARG APP_NAME
ARG GIT_COMMIT

RUN apk update && \
apk add --no-cache \
bash \
curl \
busybox=1.35.0-r18 \
ssl_client=1.35.0-r18 \
busybox \
openssl-dev \
ca-certificates \
git \
musl=1.2.3-r4 \
musl-utils=1.2.3-r4 \
ncurses=6.3_p20220521-r1 \
ncurses-libs=6.3_p20220521-r1 \
ncurses-terminfo=6.3_p20220521-r1 \
ncurses-terminfo-base=6.3_p20220521-r1
libstdc++ \
ncurses-libs

ENV REPLACE_OS_VARS=true \
APP_NAME=${APP_NAME} \
GIT_COMMIT=${GIT_COMMIT}
ENV APP_NAME=${APP_NAME} \
GIT_COMMIT=${GIT_COMMIT} \
MIX_ENV=prod \
LANG=en_US.UTF-8 \
LANGUAGE=en_US:en \
LC_ALL=en_US.UTF-8

WORKDIR /opt/app

COPY --from=tools /usr/local/bin/plural /usr/local/bin/plural
COPY --from=tools /usr/local/bin/helm /usr/local/bin/helm
# COPY --from=tools /usr/local/bin/goon /usr/local/bin/goon
# COPY --from=tools /usr/local/bin/terrascan /usr/local/bin/terrascan
COPY --from=tools /usr/local/bin/trivy /usr/local/bin/trivy
COPY --from=builder /opt/built .
COPY --from=builder /opt/app/_build/prod/rel/${APP_NAME} .

CMD trap 'exit' INT; /opt/app/bin/${APP_NAME} foreground
CMD trap 'exit' INT; /opt/app/bin/${APP_NAME} start
12 changes: 11 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: help up-docker down-docker up-docker-www test-docker-www build-docker-www testup testdown test-docker
.PHONY: help up-docker down-docker up-docker-www test-docker-www build-docker-www testup testdown test-docker stack-up stack-down

GCP_PROJECT ?= pluralsh
APP_NAME ?= plural
Expand All @@ -19,6 +19,16 @@ up-docker: ## start root dependencies via docker compose (db, cache, queue, etc.
down-docker: ## stop and remove root dependencies docker compose stack
docker compose -f docker-compose.yml down

stack-up: ## build Mix-release images sequentially, then run api/rtc/worker/cron
docker build --build-arg APP_NAME=plural --build-arg TARGETARCH=$(TARGETARCH) --build-arg GIT_COMMIT=local -t plural-stack-plural .
docker build --build-arg APP_NAME=rtc --build-arg TARGETARCH=$(TARGETARCH) --build-arg GIT_COMMIT=local -t plural-stack-rtc .
docker build --build-arg APP_NAME=worker --build-arg TARGETARCH=$(TARGETARCH) --build-arg GIT_COMMIT=local -t plural-stack-worker .
docker build --build-arg APP_NAME=cron --build-arg TARGETARCH=$(TARGETARCH) --build-arg GIT_COMMIT=local -t plural-stack-cron .
docker compose -f docker-compose.stack.yml up -d

stack-down: ## stop the local Mix-release stack
docker compose -f docker-compose.stack.yml down

test-docker: ## run backend tests in docker
@docker compose -f docker-compose.test.yml up --build --abort-on-container-exit --exit-code-from backend-test; \
status=$$?; \
Expand Down
10 changes: 6 additions & 4 deletions apps/api/lib/api_web.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ defmodule ApiWeb do

def controller do
quote do
use Phoenix.Controller, namespace: ApiWeb
use Phoenix.Controller,
namespace: ApiWeb,
formats: [html: "View", json: "View"]

import Plug.Conn
import ApiWeb.Gettext
import ApiWeb.Helpers
use Gettext, backend: ApiWeb.Gettext
alias ApiWeb.Router.Helpers, as: Routes

action_fallback ApiWeb.FallbackController
Expand All @@ -43,7 +45,7 @@ defmodule ApiWeb do
use Phoenix.HTML

import ApiWeb.ErrorHelpers
import ApiWeb.Gettext
use Gettext, backend: ApiWeb.Gettext
alias ApiWeb.Router.Helpers, as: Routes
end
end
Expand All @@ -59,7 +61,7 @@ defmodule ApiWeb do
def channel do
quote do
use Phoenix.Channel
import ApiWeb.Gettext
use Gettext, backend: ApiWeb.Gettext
end
end

Expand Down
2 changes: 1 addition & 1 deletion apps/api/lib/api_web/controllers/fallback_controller.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule ApiWeb.FallbackController do
use Phoenix.Controller
use Phoenix.Controller, formats: [html: "View", json: "View"]
require Logger

def call(conn, {:error, error}) do
Expand Down
2 changes: 1 addition & 1 deletion apps/api/lib/api_web/gettext.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ defmodule ApiWeb.Gettext do

See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
"""
use Gettext, otp_app: :api
use Gettext.Backend, otp_app: :api
end
2 changes: 1 addition & 1 deletion apps/api/lib/api_web/guardian_pipeline.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule ApiWeb.GuardianPipeline do

plug Api.Plugs.VerifyPersistedToken
plug Guardian.Plug.VerifySession
plug Guardian.Plug.VerifyHeader, realm: "Bearer"
plug Guardian.Plug.VerifyHeader, scheme: "Bearer"
# plug Guardian.Plug.EnsureAuthenticated
plug Guardian.Plug.LoadResource, allow_blank: true
end
16 changes: 10 additions & 6 deletions apps/api/lib/api_web/plugs/remote_ip.ex
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
defmodule ApiWeb.Plugs.RemoteIp do
alias RemoteIp
@headers ~w[forwarded x-forwarded-for x-client-ip x-real-ip]

def init(opts), do: RemoteIp.init(opts)
def init(opts), do: opts

def call(%{req_headers: headers} = conn, _opts) do
ips =
headers
|> RemoteIp.Headers.take(@headers)
|> RemoteIp.Headers.parse()
|> Enum.reverse()

def call(%{req_headers: headers} = conn, %RemoteIp.Config{headers: allowed}) do
ips = RemoteIp.Headers.parse(headers, allowed)
|> Enum.reverse()
%{conn | remote_ip: find_ip(ips, conn.remote_ip)}
end

defp find_ip([_, ip | _], _), do: ip # assume spoof after 2 layers of proxy
defp find_ip([_, ip | _], _), do: ip
defp find_ip([ip], _), do: ip
defp find_ip(_, ip), do: ip
end
22 changes: 11 additions & 11 deletions apps/api/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ defmodule Api.MixProject do
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.5",
elixir: "~> 1.16",
elixirc_paths: elixirc_paths(Mix.env()),
compilers: [:phoenix] ++ Mix.compilers(),
start_permanent: Mix.env() == :prod,
aliases: aliases(),
deps: deps(),
Expand All @@ -61,25 +60,26 @@ defmodule Api.MixProject do

defp deps do
[
{:sentry, "8.0.6"},
{:phoenix, "~> 1.6.17"},
{:sentry, "~> 10.2.0"},
{:phoenix, "~> 1.5"},
{:phoenix_view, "~> 2.0"},
{:phoenix_pubsub, "~> 2.0"},
{:phoenix_ecto, "~> 4.4.0"},
{:ecto_sql, "~> 3.9.0"},
{:phoenix_ecto, "~> 4.0"},
{:ecto_sql, "~> 3.13"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 3.2.0"},
{:phoenix_html, "~> 3.0"},
{:basic_auth, "~> 2.2.2"},
{:phoenix_live_reload, "~> 1.2", only: :dev},
{:gettext, "~> 0.20"},
{:jason, "~> 1.0"},
{:guardian, "~> 1.2.1"},
{:guardian, "~> 2.4"},
{:cors_plug, "~> 2.0"},
{:plug_cowboy, "~> 2.8.1", override: true},
{:reverse_proxy_plug, "~> 2.1.1"},
{:plug_cowboy, "~> 2.7"},
{:reverse_proxy_plug, "~> 3.0"},
{:libcluster, "~> 3.3.1"},
{:prometheus_ex, "~> 3.0"},
{:prometheus_plugs, "~> 1.1.1"},
{:remote_ip, "~> 0.2.0"},
{:remote_ip, "~> 1.2.0"},
{:hammer_plug, "~> 3.0"},
{:k8s_traffic_plug, git: "https://github.com/pluralsh/k8s_traffic_plug"},

Expand Down
8 changes: 6 additions & 2 deletions apps/core/lib/core/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ defmodule Core.Application do

def start(_type, _args) do
if Application.get_env(:sentry, :dsn) do
Logger.add_backend(Sentry.LoggerBackend)
:logger.add_handler(:sentry_logger, Sentry.LoggerHandler, %{
config: %{metadata: [:file, :line]}
})
end

Cloudflare.Client.init()
if Application.get_env(:cloudflare, :auth_token) not in [nil, ""] do
Cloudflare.Client.init()
end

children = [
Core.Repo,
Expand Down
14 changes: 6 additions & 8 deletions apps/core/lib/core/clients/console.ex
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ defmodule Core.Clients.Console do
{:ok, %Req.Response{body: %{"data" => %{"clusters" => %{"edges" => edges}}}}} ->
{:ok, Enum.map(edges, & &1["node"])}
res ->
Logger.warn "Failed to fetch clusters: #{inspect(res)}"
Logger.warning "Failed to fetch clusters: #{inspect(res)}"
{:error, "could not fetch clusters"}
end
end
Expand Down Expand Up @@ -183,7 +183,7 @@ defmodule Core.Clients.Console do
{:ok, %Req.Response{body: %{"errors" => [_ | _] = errors}}} -> {:error, errors}
{:ok, %Req.Response{body: %{"data" => %{^field => data}}}} -> {:ok, data}
res ->
Logger.warn "Failed to fetch #{field}: #{inspect(res)}"
Logger.warning "Failed to fetch #{field}: #{inspect(res)}"
{:error, "could not fetch #{field}"}
end
end
Expand All @@ -196,7 +196,7 @@ defmodule Core.Clients.Console do
case body[field] do
%{"id" => id} -> {:ok, id}
err ->
Logger.warn "invalid console gql response: #{inspect(err)}"
Logger.warning "invalid console gql response: #{inspect(err)}"
{:error, "#{field} query failed"}
end
end
Expand All @@ -206,10 +206,8 @@ defmodule Core.Clients.Console do
{:error, "console error"}
end

defp with_gql(url) do
case String.ends_with?(url, "/gql") do
true -> url
_ -> "#{url}/gql"
end
defp with_gql(url) when is_binary(url) do
if String.ends_with?(url, "/gql"), do: url, else: "#{url}/gql"
end
defp with_gql(_), do: nil
end
Loading
Loading