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
2 changes: 1 addition & 1 deletion .github/workflows/elixir.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ concurrency:
cancel-in-progress: true

env:
CACHE_VERSION: v16
CACHE_VERSION: v17
PERSISTENT_CACHE_DIR: cached

jobs:
Expand Down
4 changes: 2 additions & 2 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -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
9 changes: 6 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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 ./
Expand Down Expand Up @@ -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 <[email protected]>"

ARG BUILD_METADATA={}
Expand Down Expand Up @@ -84,3 +86,4 @@ EXPOSE 8000
ENV DEFAULT_DATA_DIR=/var/lib/plausible
VOLUME /var/lib/plausible
CMD ["run"]

24 changes: 12 additions & 12 deletions lib/plausible/auth/user.ex
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
2 changes: 1 addition & 1 deletion lib/plausible/google/ga4/api.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion lib/plausible/shield/country_rule_cache.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/plausible/shield/hostname_rule_cache.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion lib/plausible/shield/ip_rule_cache.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/plausible/shield/page_rule_cache.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/plausible/site/cache.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions lib/plausible/stats/query_optimizer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/plausible_web/controllers/avatar_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/plausible_web/plugs/favicon.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule Plausible.CondolidatedView.CacheTestSync do
defmodule Plausible.CondolidatedView.CacheSyncTest do
use Plausible.DataCase, async: false

on_ee do
Expand Down Expand Up @@ -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)
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
25 changes: 13 additions & 12 deletions test/plausible/segments/segment_test.exs
Original file line number Diff line number Diff line change
@@ -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"]]},
Expand All @@ -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]},
Expand All @@ -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
Expand All @@ -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)
Expand All @@ -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:
Expand All @@ -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
},
Expand All @@ -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" => []}
Expand All @@ -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: %{
Expand All @@ -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: %{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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])
])

Expand Down Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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])
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")
])
Expand Down
Loading
Loading