Platform upgrade: elixir 1.19.4 and otp 27.3.4.6 (#5920)
* Platform upgrade: elixir 1.19.4 and otp 27.3.4.6 * !fixup * credo * credo * Bump cache * fix docker image tag * hum * hum * Match docker images * Define ALPINE_VERSION once * fixup
This commit is contained in:
parent
8a7d681c43
commit
b64a2355a0
|
|
@ -11,7 +11,7 @@ concurrency:
|
|||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
CACHE_VERSION: v16
|
||||
CACHE_VERSION: v17
|
||||
PERSISTENT_CACHE_DIR: cached
|
||||
|
||||
jobs:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
erlang 27.3.1
|
||||
elixir 1.18.3-otp-27
|
||||
erlang 27.3.4.6
|
||||
elixir 1.19.4-otp-27
|
||||
nodejs 23.2.0
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
# we can not use the pre-built tar because the distribution is
|
||||
# platform specific, it makes sense to build it in the docker
|
||||
|
||||
ARG ALPINE_VERSION=3.22.2
|
||||
|
||||
#### Builder
|
||||
FROM hexpm/elixir:1.18.3-erlang-27.3.1-alpine-3.21.3 AS buildcontainer
|
||||
FROM hexpm/elixir:1.19.4-erlang-27.3.4.6-alpine-${ALPINE_VERSION} AS buildcontainer
|
||||
|
||||
ARG MIX_ENV=ce
|
||||
|
||||
|
|
@ -20,7 +22,7 @@ RUN mkdir /app
|
|||
WORKDIR /app
|
||||
|
||||
# install build dependencies
|
||||
RUN apk add --no-cache git "nodejs-current=23.2.0-r1" yarn npm python3 ca-certificates wget gnupg make gcc libc-dev brotli
|
||||
RUN apk add --no-cache git "nodejs-current=23.11.1-r0" yarn npm python3 ca-certificates wget gnupg make gcc libc-dev brotli
|
||||
|
||||
COPY mix.exs ./
|
||||
COPY mix.lock ./
|
||||
|
|
@ -54,7 +56,7 @@ COPY rel rel
|
|||
RUN mix release plausible
|
||||
|
||||
# Main Docker Image
|
||||
FROM alpine:3.21.3
|
||||
FROM alpine:${ALPINE_VERSION}
|
||||
LABEL maintainer="plausible.io <hello@plausible.io>"
|
||||
|
||||
ARG BUILD_METADATA={}
|
||||
|
|
@ -84,3 +86,4 @@ EXPOSE 8000
|
|||
ENV DEFAULT_DATA_DIR=/var/lib/plausible
|
||||
VOLUME /var/lib/plausible
|
||||
CMD ["run"]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,3 @@
|
|||
defimpl Bamboo.Formatter, for: Plausible.Auth.User do
|
||||
def format_email_address(user, _opts) do
|
||||
{user.name, user.email}
|
||||
end
|
||||
end
|
||||
|
||||
defimpl FunWithFlags.Actor, for: Plausible.Auth.User do
|
||||
def id(%{id: id}) do
|
||||
"user:#{id}"
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Plausible.Auth.User do
|
||||
use Plausible
|
||||
use Ecto.Schema
|
||||
|
|
@ -284,3 +272,15 @@ defmodule Plausible.Auth.User do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
defimpl Bamboo.Formatter, for: Plausible.Auth.User do
|
||||
def format_email_address(user, _opts) do
|
||||
{user.name, user.email}
|
||||
end
|
||||
end
|
||||
|
||||
defimpl FunWithFlags.Actor, for: Plausible.Auth.User do
|
||||
def id(%{id: id}) do
|
||||
"user:#{id}"
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ defmodule Plausible.Google.GA4.API do
|
|||
end
|
||||
end
|
||||
|
||||
defp prepare_request(report_request, date_range, property, access_token) do
|
||||
defp prepare_request(%GA4.ReportRequest{} = report_request, date_range, property, access_token) do
|
||||
%GA4.ReportRequest{
|
||||
report_request
|
||||
| date_range: date_range,
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ defmodule Plausible.Shield.CountryRuleCache do
|
|||
|> where([rule, site], rule.country_code == ^country_code and site.domain == ^domain)
|
||||
|
||||
case Plausible.Repo.one(query) do
|
||||
{_, _, rule} -> %CountryRule{rule | from_cache?: false}
|
||||
{_, _, rule = %CountryRule{}} -> %CountryRule{rule | from_cache?: false}
|
||||
_any -> nil
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ defmodule Plausible.Shield.HostnameRuleCache do
|
|||
|
||||
case Plausible.Repo.all(query) do
|
||||
[_ | _] = results ->
|
||||
Enum.map(results, fn {_, _, rule} ->
|
||||
Enum.map(results, fn {_, _, rule = %HostnameRule{}} ->
|
||||
%HostnameRule{rule | from_cache?: false}
|
||||
end)
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ defmodule Plausible.Shield.IPRuleCache do
|
|||
|> where([rule, site], rule.inet == ^address and site.domain == ^domain)
|
||||
|
||||
case Plausible.Repo.one(query) do
|
||||
{_, _, rule} -> %IPRule{rule | from_cache?: false}
|
||||
{_, _, rule = %IPRule{}} -> %IPRule{rule | from_cache?: false}
|
||||
_any -> nil
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ defmodule Plausible.Shield.PageRuleCache do
|
|||
|> where([..., site], site.domain == ^domain)
|
||||
|
||||
case Plausible.Repo.one(query) do
|
||||
{_, _, rule} -> %PageRule{rule | from_cache?: false}
|
||||
{_, _, rule = %PageRule{}} -> %PageRule{rule | from_cache?: false}
|
||||
_any -> nil
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ defmodule Plausible.Site.Cache do
|
|||
query = from s in base_db_query(), where: s.domain == ^domain
|
||||
|
||||
case Plausible.Repo.one(query) do
|
||||
{_, _, site} -> %Site{site | from_cache?: false}
|
||||
{_, _, site = %Site{}} -> %Site{site | from_cache?: false}
|
||||
_any -> nil
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ defmodule Plausible.Stats.QueryOptimizer do
|
|||
end
|
||||
end
|
||||
|
||||
defp update_time_in_order_by(query) do
|
||||
defp update_time_in_order_by(%Query{} = query) do
|
||||
order_by =
|
||||
query.order_by
|
||||
|> Enum.map(fn
|
||||
|
|
@ -126,7 +126,7 @@ defmodule Plausible.Stats.QueryOptimizer do
|
|||
# To avoid showing referrers across hostnames when event:hostname
|
||||
# filter is present for breakdowns, add entry/exit page hostname
|
||||
# filters
|
||||
defp extend_hostname_filters_to_visit(query) do
|
||||
defp extend_hostname_filters_to_visit(%Query{} = query) do
|
||||
# Note: Only works since event:hostname is only allowed as a top level filter
|
||||
hostname_filters =
|
||||
query.filters
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ defmodule PlausibleWeb.AvatarController do
|
|||
end
|
||||
|
||||
@forwarded_headers ["content-type", "cache-control", "expires"]
|
||||
defp forward_headers(conn, headers) do
|
||||
defp forward_headers(%Plug.Conn{} = conn, headers) do
|
||||
headers_to_forward = Enum.filter(headers, fn {k, _} -> k in @forwarded_headers end)
|
||||
%Plug.Conn{conn | resp_headers: headers_to_forward}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ defmodule PlausibleWeb.Favicon do
|
|||
end
|
||||
|
||||
@forwarded_headers ["content-type", "cache-control", "expires"]
|
||||
defp forward_headers(conn, headers) do
|
||||
defp forward_headers(%Plug.Conn{} = conn, headers) do
|
||||
headers_to_forward = Enum.filter(headers, fn {k, _} -> k in @forwarded_headers end)
|
||||
%Plug.Conn{conn | resp_headers: headers_to_forward}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
defmodule Plausible.CondolidatedView.CacheTestSync do
|
||||
defmodule Plausible.CondolidatedView.CacheSyncTest do
|
||||
use Plausible.DataCase, async: false
|
||||
|
||||
on_ee do
|
||||
|
|
@ -27,10 +27,10 @@ defmodule Plausible.CondolidatedView.CacheTestSync do
|
|||
}
|
||||
] = Sentry.Test.pop_sentry_reports()
|
||||
end
|
||||
end
|
||||
|
||||
defp start_test_cache(cache_name) do
|
||||
%{start: {m, f, a}} = Cache.child_spec(cache_name: cache_name)
|
||||
apply(m, f, a)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
defmodule Plausible.Segments.SegmentTest do
|
||||
use ExUnit.Case
|
||||
doctest Plausible.Segments.Segment, import: true
|
||||
alias Plausible.Segments.Segment
|
||||
doctest Segment, import: true
|
||||
|
||||
setup do
|
||||
segment = %Plausible.Segments.Segment{
|
||||
segment = %Segment{
|
||||
name: "any name",
|
||||
type: :personal,
|
||||
segment_data: %{"filters" => ["is", "visit:page", ["/blog"]]},
|
||||
|
|
@ -15,7 +16,7 @@ defmodule Plausible.Segments.SegmentTest do
|
|||
end
|
||||
|
||||
test "changeset has required fields" do
|
||||
assert Plausible.Segments.Segment.changeset(%Plausible.Segments.Segment{}, %{}).errors == [
|
||||
assert Segment.changeset(%Segment{}, %{}).errors == [
|
||||
segment_data: {"property \"filters\" must be an array with at least one member", []},
|
||||
name: {"can't be blank", [validation: :required]},
|
||||
segment_data: {"can't be blank", [validation: :required]},
|
||||
|
|
@ -27,7 +28,7 @@ defmodule Plausible.Segments.SegmentTest do
|
|||
|
||||
test "changeset does not allow setting owner_id to nil (setting to nil happens with database triggers)",
|
||||
%{segment: valid_segment} do
|
||||
assert Plausible.Segments.Segment.changeset(
|
||||
assert Segment.changeset(
|
||||
valid_segment,
|
||||
%{
|
||||
owner_id: nil
|
||||
|
|
@ -38,7 +39,7 @@ defmodule Plausible.Segments.SegmentTest do
|
|||
end
|
||||
|
||||
test "changeset forbids too long name", %{segment: valid_segment} do
|
||||
assert Plausible.Segments.Segment.changeset(
|
||||
assert Segment.changeset(
|
||||
valid_segment,
|
||||
%{
|
||||
name: String.duplicate("a", 256)
|
||||
|
|
@ -51,7 +52,7 @@ defmodule Plausible.Segments.SegmentTest do
|
|||
end
|
||||
|
||||
test "changeset forbids too large segment_data", %{segment: valid_segment} do
|
||||
assert Plausible.Segments.Segment.changeset(
|
||||
assert Segment.changeset(
|
||||
valid_segment,
|
||||
%{
|
||||
segment_data:
|
||||
|
|
@ -65,9 +66,9 @@ defmodule Plausible.Segments.SegmentTest do
|
|||
end
|
||||
|
||||
test "changeset allows setting nil owner_id to a user id (to be able to recover dangling site segments)",
|
||||
%{segment: valid_segment} do
|
||||
assert Plausible.Segments.Segment.changeset(
|
||||
%Plausible.Segments.Segment{
|
||||
%{segment: valid_segment = %Segment{}} do
|
||||
assert Segment.changeset(
|
||||
%Segment{
|
||||
valid_segment
|
||||
| owner_id: nil
|
||||
},
|
||||
|
|
@ -78,7 +79,7 @@ defmodule Plausible.Segments.SegmentTest do
|
|||
end
|
||||
|
||||
test "changeset requires segment_data to be structured as expected", %{segment: valid_segment} do
|
||||
assert Plausible.Segments.Segment.changeset(
|
||||
assert Segment.changeset(
|
||||
valid_segment,
|
||||
%{
|
||||
segment_data: %{"filters" => 1, "labels" => true, "other" => []}
|
||||
|
|
@ -93,7 +94,7 @@ defmodule Plausible.Segments.SegmentTest do
|
|||
end
|
||||
|
||||
test "changeset forbids empty filters list", %{segment: valid_segment} do
|
||||
assert Plausible.Segments.Segment.changeset(
|
||||
assert Segment.changeset(
|
||||
valid_segment,
|
||||
%{
|
||||
segment_data: %{
|
||||
|
|
@ -107,7 +108,7 @@ defmodule Plausible.Segments.SegmentTest do
|
|||
end
|
||||
|
||||
test "changeset permits well-structured segment data", %{segment: valid_segment} do
|
||||
assert Plausible.Segments.Segment.changeset(
|
||||
assert Segment.changeset(
|
||||
valid_segment,
|
||||
%{
|
||||
segment_data: %{
|
||||
|
|
|
|||
|
|
@ -224,7 +224,12 @@ defmodule PlausibleWeb.Api.ExternalStatsController.QuerySpecialMetricsTest do
|
|||
build(:pageview, user_id: 1, pathname: "/two", timestamp: ~N[2021-01-01 00:10:00]),
|
||||
build(:pageview, user_id: 3, pathname: "/one", timestamp: ~N[2021-01-01 00:00:00]),
|
||||
build(:pageview, user_id: 3, pathname: "/never-exit", timestamp: ~N[2021-01-01 00:00:00]),
|
||||
build(:event, user_id: 3, name: "a", pathname: "/one", timestamp: ~N[2021-01-01 00:00:00]),
|
||||
build(:event,
|
||||
user_id: 3,
|
||||
name: "a",
|
||||
pathname: "/one",
|
||||
timestamp: ~N[2021-01-01 00:00:00]
|
||||
),
|
||||
build(:pageview, user_id: 3, pathname: "/one", timestamp: ~N[2021-01-01 00:10:00])
|
||||
])
|
||||
|
||||
|
|
@ -323,8 +328,16 @@ defmodule PlausibleWeb.Api.ExternalStatsController.QuerySpecialMetricsTest do
|
|||
|
||||
test "in visit:exit_page breakdown filtered by visit:country", %{conn: conn, site: site} do
|
||||
populate_stats(site, [
|
||||
build(:pageview, pathname: "/one", country_code: "EE", timestamp: ~N[2021-01-01 00:00:00]),
|
||||
build(:pageview, pathname: "/one", country_code: "US", timestamp: ~N[2021-01-01 00:00:00]),
|
||||
build(:pageview,
|
||||
pathname: "/one",
|
||||
country_code: "EE",
|
||||
timestamp: ~N[2021-01-01 00:00:00]
|
||||
),
|
||||
build(:pageview,
|
||||
pathname: "/one",
|
||||
country_code: "US",
|
||||
timestamp: ~N[2021-01-01 00:00:00]
|
||||
),
|
||||
build(:pageview,
|
||||
user_id: 1,
|
||||
pathname: "/one",
|
||||
|
|
|
|||
|
|
@ -615,7 +615,11 @@ defmodule PlausibleWeb.Api.ExternalStatsController.TimeseriesTest do
|
|||
user_id: @user_id,
|
||||
timestamp: ~N[2021-01-01 00:25:00]
|
||||
),
|
||||
build(:pageview, pathname: "/blog", user_id: @user_id, timestamp: ~N[2021-01-01 00:25:00]),
|
||||
build(:pageview,
|
||||
pathname: "/blog",
|
||||
user_id: @user_id,
|
||||
timestamp: ~N[2021-01-01 00:25:00]
|
||||
),
|
||||
build(:pageview, pathname: "/", timestamp: ~N[2021-01-01 00:25:00])
|
||||
])
|
||||
|
||||
|
|
|
|||
|
|
@ -1166,8 +1166,18 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do
|
|||
|
||||
populate_stats(site, site_import.id, [
|
||||
build(:imported_pages, page: "/", visitors: 1, pageviews: 1, date: ~D[2021-01-01]),
|
||||
build(:imported_pages, page: "/blog/one", visitors: 2, pageviews: 2, date: ~D[2021-01-01]),
|
||||
build(:imported_pages, page: "/blog/two", visitors: 3, pageviews: 3, date: ~D[2021-01-01]),
|
||||
build(:imported_pages,
|
||||
page: "/blog/one",
|
||||
visitors: 2,
|
||||
pageviews: 2,
|
||||
date: ~D[2021-01-01]
|
||||
),
|
||||
build(:imported_pages,
|
||||
page: "/blog/two",
|
||||
visitors: 3,
|
||||
pageviews: 3,
|
||||
date: ~D[2021-01-01]
|
||||
),
|
||||
build(:imported_pages,
|
||||
page: "/blog/three",
|
||||
visitors: 4,
|
||||
|
|
|
|||
|
|
@ -849,7 +849,11 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do
|
|||
site: site
|
||||
} do
|
||||
populate_stats(site, [
|
||||
build(:pageview, user_id: @user_id, pathname: "/blog", timestamp: ~N[2020-01-01 00:00:00]),
|
||||
build(:pageview,
|
||||
user_id: @user_id,
|
||||
pathname: "/blog",
|
||||
timestamp: ~N[2020-01-01 00:00:00]
|
||||
),
|
||||
build(:engagement,
|
||||
user_id: @user_id,
|
||||
pathname: "/blog",
|
||||
|
|
|
|||
|
|
@ -21,8 +21,16 @@ defmodule PlausibleWeb.Api.StatsController.ScreenSizesTest do
|
|||
|
||||
test "returns bounce_rate and visit_duration when detailed=true", %{conn: conn, site: site} do
|
||||
populate_stats(site, [
|
||||
build(:pageview, user_id: 123, timestamp: ~N[2021-01-01 12:00:00], screen_size: "Desktop"),
|
||||
build(:pageview, user_id: 123, timestamp: ~N[2021-01-01 12:10:00], screen_size: "Desktop"),
|
||||
build(:pageview,
|
||||
user_id: 123,
|
||||
timestamp: ~N[2021-01-01 12:00:00],
|
||||
screen_size: "Desktop"
|
||||
),
|
||||
build(:pageview,
|
||||
user_id: 123,
|
||||
timestamp: ~N[2021-01-01 12:10:00],
|
||||
screen_size: "Desktop"
|
||||
),
|
||||
build(:pageview, timestamp: ~N[2021-01-01 12:00:00], screen_size: "Desktop"),
|
||||
build(:pageview, timestamp: ~N[2021-01-01 12:00:00], screen_size: "Laptop")
|
||||
])
|
||||
|
|
|
|||
|
|
@ -1279,7 +1279,11 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do
|
|||
populate_stats(site, [
|
||||
build(:pageview, pathname: "/index", hostname: "example.com"),
|
||||
build(:pageview, pathname: "/index", hostname: "example.com", user_id: @user_id),
|
||||
build(:pageview, pathname: "/blog/post1", hostname: "blog.example.com", user_id: @user_id),
|
||||
build(:pageview,
|
||||
pathname: "/blog/post1",
|
||||
hostname: "blog.example.com",
|
||||
user_id: @user_id
|
||||
),
|
||||
build(:pageview, pathname: "/blog/post2", hostname: "blog.example.com")
|
||||
])
|
||||
|
||||
|
|
@ -1306,8 +1310,16 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do
|
|||
populate_stats(site, [
|
||||
build(:pageview, pathname: "/index", hostname: "example.com"),
|
||||
build(:pageview, pathname: "/index", hostname: "example.com", user_id: @user_id),
|
||||
build(:pageview, pathname: "/blog/post1", hostname: "blog.example.com", user_id: @user_id),
|
||||
build(:pageview, pathname: "/blog/post2", hostname: "blog.example.com", user_id: @user_id),
|
||||
build(:pageview,
|
||||
pathname: "/blog/post1",
|
||||
hostname: "blog.example.com",
|
||||
user_id: @user_id
|
||||
),
|
||||
build(:pageview,
|
||||
pathname: "/blog/post2",
|
||||
hostname: "blog.example.com",
|
||||
user_id: @user_id
|
||||
),
|
||||
build(:pageview, pathname: "/blog/post2", hostname: "blog.example.com"),
|
||||
build(:pageview, pathname: "/blog/post2", hostname: "about.example.com")
|
||||
])
|
||||
|
|
@ -1336,8 +1348,16 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do
|
|||
populate_stats(site, [
|
||||
build(:pageview, pathname: "/index", hostname: "example.com"),
|
||||
build(:pageview, pathname: "/index", hostname: "example.com", user_id: @user_id),
|
||||
build(:pageview, pathname: "/blog/post1", hostname: "blog.example.com", user_id: @user_id),
|
||||
build(:pageview, pathname: "/blog/post2", hostname: "blog.example.com", user_id: @user_id),
|
||||
build(:pageview,
|
||||
pathname: "/blog/post1",
|
||||
hostname: "blog.example.com",
|
||||
user_id: @user_id
|
||||
),
|
||||
build(:pageview,
|
||||
pathname: "/blog/post2",
|
||||
hostname: "blog.example.com",
|
||||
user_id: @user_id
|
||||
),
|
||||
build(:pageview, pathname: "/blog/post3", hostname: "blog.example.com"),
|
||||
build(:pageview,
|
||||
pathname: "/blog/post2",
|
||||
|
|
|
|||
|
|
@ -37,7 +37,8 @@ defmodule ObanErrorReporterTest do
|
|||
)
|
||||
end)
|
||||
|
||||
assert log =~ "[error] ** (BadMapError) expected a map, got: :bad_job"
|
||||
assert log =~ "(BadMapError)"
|
||||
assert log =~ ":bad_job"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue