From 053d51875e270f0f53819ec59a39841d7c6490de Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Thu, 1 Oct 2026 10:52:51 -0500 Subject: [PATCH 1/2] backport storbyook rm for GHSA-mhcv-h7gf-57cf (CVE-2026-8467 --- .formatter.exs | 3 +-- CHANGELOG.md | 1 + Dockerfile | 1 - README.md | 8 ++++++ assets/css/storybook.css | 12 --------- assets/js/storybook.js | 36 --------------------------- config/config.exs | 9 +------ config/dev.exs | 4 +-- config/runtime.exs | 2 -- lib/plausible_web/router.ex | 10 -------- lib/plausible_web/storybook.ex | 13 ---------- mix.exs | 4 +-- mix.lock | 4 --- storybook/_root.index.exs | 8 ------ storybook/button.story.exs | 43 -------------------------------- storybook/dropdown.story.exs | 31 ----------------------- storybook/input.story.exs | 45 ---------------------------------- 17 files changed, 13 insertions(+), 221 deletions(-) delete mode 100644 assets/css/storybook.css delete mode 100644 assets/js/storybook.js delete mode 100644 lib/plausible_web/storybook.ex delete mode 100644 storybook/_root.index.exs delete mode 100644 storybook/button.story.exs delete mode 100644 storybook/dropdown.story.exs delete mode 100644 storybook/input.story.exs diff --git a/.formatter.exs b/.formatter.exs index 06ece05b6a92..93242c55c0b2 100644 --- a/.formatter.exs +++ b/.formatter.exs @@ -5,8 +5,7 @@ inputs: [ "*.{heex,ex,exs}", "{config,lib,test,extra}/**/*.{heex,ex,exs}", - "priv/*/seeds.exs", - "storybook/**/*.exs" + "priv/*/seeds.exs" ], locals_without_parens: [assert_matches: 1] ] diff --git a/CHANGELOG.md b/CHANGELOG.md index fa4292529979..88e9fb9dd67c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ All notable changes to this project will be documented in this file. ### Fixed +- Backport upstream Storybook removal ([`ce6c8468`](https://github.com/plausible/analytics/commit/ce6c8468e7f9c2a57fd09000f80c2ef8d922a0d6)) to fix unauthenticated remote code execution, [GHSA-mhcv-h7gf-57cf / CVE-2026-8467](https://github.com/plausible/analytics/security/advisories/GHSA-mhcv-h7gf-57cf). - Fixed Stats API timeseries returning time buckets falling outside the queried range - Fixed issue with all non-interactive events being counted as interactive - Fixed countries map countries staying highlighted on Chrome diff --git a/Dockerfile b/Dockerfile index 5479288ddd0e..2a28a965e51f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -43,7 +43,6 @@ COPY tracker ./tracker COPY priv ./priv COPY lib ./lib COPY extra ./extra -COPY storybook ./storybook RUN npm run deploy --prefix ./tracker && \ mix assets.deploy && \ diff --git a/README.md b/README.md index 927efbc4ecc4..f6983fe9abd4 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,14 @@ This runs on [Cabotage](https://github.com/cabotage/cabotage-app), the PSF's Paa Image builds happen automatically from the `v3.0.1-psf` branch. To deploy, trigger a build and deploy through the Cabotage UI. +### Storybook security update + +This fork backports the upstream removal of Storybook for [GHSA-mhcv-h7gf-57cf](https://github.com/plausible/analytics/security/advisories/GHSA-mhcv-h7gf-57cf). Deploy a newly built image containing the fix; the branch name alone does not identify patched code. + +Until the patched image is deployed, block `/storybook` and its subpaths at every ingress, including direct-origin access. Preserve access logs and incident evidence. After deployment, verify the running commit and image digest and confirm that Storybook is unavailable. + +If credentials were disclosed or compromise is suspected, rotate or revoke all secrets accessible to the container after containment and assess downstream access with PSRT. Use the supported rotation procedure for encryption keys. Deploying this patch does not invalidate stolen credentials. + ## Upstream Sync This fork tracks `plausible/analytics:master` as the `upstream` remote. diff --git a/assets/css/storybook.css b/assets/css/storybook.css deleted file mode 100644 index 2764e94fa378..000000000000 --- a/assets/css/storybook.css +++ /dev/null @@ -1,12 +0,0 @@ -@import 'tailwindcss' source(none); - -/* - * Put your component styling within the Tailwind utilities layer. -* See the https://hexdocs.pm/phoenix_storybook/sandboxing.html guide for more info. - */ - -@layer utilities { - * { - font-family: system-ui; - } -} diff --git a/assets/js/storybook.js b/assets/js/storybook.js deleted file mode 100644 index c211a67d66bd..000000000000 --- a/assets/js/storybook.js +++ /dev/null @@ -1,36 +0,0 @@ -import Alpine from 'alpinejs' -import dropdown from './liveview/dropdown' - -// If your components require any hooks or custom uploaders, or if your pages -// require connect parameters, uncomment the following lines and declare them as -// such: -// -// import * as Hooks from "./hooks"; -// import * as Params from "./params"; -// import * as Uploaders from "./uploaders"; - -// (function () { -// window.storybook = { Hooks, Params, Uploaders }; -// })(); - -window.Alpine = Alpine -document.addEventListener('DOMContentLoaded', () => { - window.Alpine.start() -}) - -document.addEventListener('alpine:init', () => { - window.Alpine.data('dropdown', dropdown) -}) -;(function () { - window.storybook = { - LiveSocketOptions: { - dom: { - onBeforeElUpdated(from, to) { - if (from._x_dataStack) { - window.Alpine.clone(from, to) - } - } - } - } - } -})() diff --git a/config/config.exs b/config/config.exs index 1e0f80d7ebc3..0b6efb948791 100644 --- a/config/config.exs +++ b/config/config.exs @@ -20,7 +20,7 @@ config :esbuild, version: "0.17.11", default: [ args: - ~w(js/app.js js/storybook.js js/dashboard.tsx js/embed.host.js js/embed.content.js --bundle --target=es2017 --loader:.js=jsx --outdir=../priv/static/js --define:BUILD_EXTRA=true), + ~w(js/app.js js/dashboard.tsx js/embed.host.js js/embed.content.js --bundle --target=es2017 --loader:.js=jsx --outdir=../priv/static/js --define:BUILD_EXTRA=true), cd: Path.expand("../assets", __DIR__), env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)} ] @@ -33,13 +33,6 @@ config :tailwind, --output=priv/static/css/app.css ), cd: Path.expand("..", __DIR__) - ], - storybook: [ - args: ~w( - --input=assets/css/storybook.css - --output=priv/static/css/storybook.css - ), - cd: Path.expand("..", __DIR__) ] config :ua_inspector, diff --git a/config/dev.exs b/config/dev.exs index 41d6c44f6bee..7201157eea5b 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -8,7 +8,6 @@ config :plausible, PlausibleWeb.Endpoint, watchers: [ esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]}, tailwind: {Tailwind, :install_and_run, [:default, ~w(--watch)]}, - storybook_tailwind: {Tailwind, :install_and_run, [:storybook, ~w(--watch)]}, npm: ["--prefix", "assets", "run", "typecheck", "--", "--watch", "--preserveWatchOutput"], npm: [ "run", @@ -22,8 +21,7 @@ config :plausible, PlausibleWeb.Endpoint, ], patterns: [ ~r{priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$}, - ~r"lib/plausible_web/(controllers|live|components|templates|views|plugs)/.*(ex|heex)$", - ~r"storybook/.*(exs)$" + ~r"lib/plausible_web/(controllers|live|components|templates|views|plugs)/.*(ex|heex)$" ] ] diff --git a/config/runtime.exs b/config/runtime.exs index 5ae1132919a8..426d4215978a 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -1089,5 +1089,3 @@ unless s3_disabled? do end config :plausible, Plausible.Cache.Adapter, sessions: [partitions: 100] - -config :phoenix_storybook, enabled: env !== "prod" diff --git a/lib/plausible_web/router.ex b/lib/plausible_web/router.ex index 9f5265bd0163..a00d5fd1e720 100644 --- a/lib/plausible_web/router.ex +++ b/lib/plausible_web/router.ex @@ -2,7 +2,6 @@ defmodule PlausibleWeb.Router do use PlausibleWeb, :router use Plausible import Phoenix.LiveView.Router - import PhoenixStorybook.Router pipeline :browser do plug :accepts, ["html"] @@ -109,15 +108,6 @@ defmodule PlausibleWeb.Router do forward "/sent-emails-api", Bamboo.SentEmailApiPlug end - scope "/" do - storybook_assets() - end - - scope "/", PlausibleWeb do - pipe_through :browser - live_storybook("/storybook", backend_module: PlausibleWeb.Storybook) - end - on_ee do scope alias: PlausibleWeb.Live, assigns: %{connect_live_socket: true, skip_plausible_tracking: true} do diff --git a/lib/plausible_web/storybook.ex b/lib/plausible_web/storybook.ex deleted file mode 100644 index 9846e9ea6323..000000000000 --- a/lib/plausible_web/storybook.ex +++ /dev/null @@ -1,13 +0,0 @@ -defmodule PlausibleWeb.Storybook do - @moduledoc false - - use PhoenixStorybook, - otp_app: :plausible_web, - title: "Plausible Storybook", - content_path: Path.expand("../../storybook", __DIR__), - # assets path are remote path, not local file-system paths - css_path: "/css/storybook.css", - js_path: "/js/storybook.js", - sandbox_class: "plausible", - color_mode: true -end diff --git a/mix.exs b/mix.exs index 696f3d4d316c..68c4d1d2d187 100644 --- a/mix.exs +++ b/mix.exs @@ -177,7 +177,7 @@ defmodule Plausible.MixProject do {:odgn_json_pointer, "~> 3.1.0"}, {:phoenix_bakery, "~> 0.1.2", only: [:ce, :ce_dev, :ce_test, :e2e_test]}, {:site_encrypt, github: "sasa1977/site_encrypt", only: [:ce, :ce_dev, :ce_test, :e2e_test]}, - {:phoenix_storybook, "~> 0.9"}, + {:phoenix_html_helpers, "~> 1.0"}, {:libcluster, "~> 3.5"} ] end @@ -207,12 +207,10 @@ defmodule Plausible.MixProject do "assets.typecheck": ["cmd npm --prefix assets run typecheck"], "assets.build": [ "tailwind default", - "tailwind storybook", "esbuild default" ], "assets.deploy": [ "tailwind default --minify", - "tailwind storybook --minify", "esbuild default --minify", "phx.digest" ] diff --git a/mix.lock b/mix.lock index d9d463b4272a..3746e1afaac7 100644 --- a/mix.lock +++ b/mix.lock @@ -31,7 +31,6 @@ "dialyxir": {:hex, :dialyxir, "1.4.7", "dda948fcee52962e4b6c5b4b16b2d8fa7d50d8645bbae8b8685c3f9ecb7f5f4d", [:mix], [{:erlex, ">= 0.2.8", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "b34527202e6eb8cee198efec110996c25c5898f43a4094df157f8d28f27d9efe"}, "digital_token": {:hex, :digital_token, "1.0.0", "454a4444061943f7349a51ef74b7fb1ebd19e6a94f43ef711f7dae88c09347df", [:mix], [{:cldr_utils, "~> 2.17", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "8ed6f5a8c2fa7b07147b9963db506a1b4c7475d9afca6492136535b064c9e9e6"}, "double": {:hex, :double, "0.8.2", "8e1cfcccdaef76c18846bc08e555555a2a699b806fa207b6468572a60513cc6a", [:mix], [], "hexpm", "90287642b2ec86125e0457aaba2ab0e80f7d7050cc80a0cef733e59bd70aa67c"}, - "earmark": {:hex, :earmark, "1.4.48", "5f41e579d85ef812351211842b6e005f6e0cef111216dea7d4b9d58af4608434", [:mix], [], "hexpm", "a461a0ddfdc5432381c876af1c86c411fd78a25790c75023c7a4c035fdc858f9"}, "earmark_parser": {:hex, :earmark_parser, "1.4.41", "ab34711c9dc6212dda44fcd20ecb87ac3f3fce6f0ca2f28d4a00e4154f8cd599", [:mix], [], "hexpm", "a81a04c7e34b6617c2792e291b5a2e57ab316365c2644ddc553bb9ed863ebefa"}, "ecto": {:hex, :ecto, "3.13.5", "9d4a69700183f33bf97208294768e561f5c7f1ecf417e0fa1006e4a91713a834", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "df9efebf70cf94142739ba357499661ef5dbb559ef902b68ea1f3c1fabce36de"}, "ecto_ch": {:hex, :ecto_ch, "0.8.6", "f31b507e86690c003f46e75d6e742e6b5d8ce34b6b10a86604b1c3aa785e0b56", [:mix], [{:ch, "~> 0.5.0 or ~> 0.6.0 or ~> 0.7.0", [hex: :ch, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.13.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}], "hexpm", "6ca9f1cf9680452b1925c6a3a7b5e3d8b12e38ee134b03c6a45a8b26434fad97"}, @@ -80,10 +79,8 @@ "locus": {:hex, :locus, "2.3.12", "aa3992023363a523e5c6d0d104da1cd1026626d16b32a480903083201057f281", [:rebar3], [{:tls_certificate_check, "~> 1.9", [hex: :tls_certificate_check, repo: "hexpm", optional: false]}], "hexpm", "e9bacd644127c5aaac478461e8b4bcd49479e7bb9f665b48ab4ebac2b7adc1ec"}, "mail": {:hex, :mail, "0.4.4", "2ed92e3b2dedb2013ba8eef9fb7ace3892e0eae1f45c0658738a72c195f7649b", [:mix], [], "hexpm", "bd44bf3e253d8be9c7f2e59b3253aff1efc1c9fa7d8ab4430c96780683faa8e2"}, "makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"}, - "makeup_eex": {:hex, :makeup_eex, "2.0.2", "88983b72aadb2e8408b06f7c9413804ce7eae2ca2a5a35cb738c6a9cb393c155", [:mix], [{:makeup, "~> 1.2.1 or ~> 1.3", [hex: :makeup, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_html, "~> 0.2.0 or ~> 1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 1.2", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "30ac121dda580298ff3378324ffaec94aad5a5b67e0cc6af177c67d5f45629b9"}, "makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"}, "makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"}, - "makeup_html": {:hex, :makeup_html, "0.2.0", "9f810da8d43d625ccd3f7ea25997e588fa541d80e0a8c6b895157ad5c7e9ca13", [:mix], [{:makeup, "~> 1.2", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "0856f7beb9a6a642ab1307e06d990fe39f0ba58690d0b8e662aa2e027ba331b2"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"}, "mimerl": {:hex, :mimerl, "1.4.0", "3882a5ca67fbbe7117ba8947f27643557adec38fa2307490c4c4207624cb213b", [:rebar3], [], "hexpm", "13af15f9f68c65884ecca3a3891d50a7b57d82152792f3e19d88650aa126b144"}, @@ -130,7 +127,6 @@ "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.6.1", "05df733a09887a005ed0d69a7fc619d376aea2730bf64ce52ac51ce716cc1ef0", [:mix], [{:file_system, "~> 0.2.10 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "74273843d5a6e4fef0bbc17599f33e3ec63f08e69215623a0cd91eea4288e5a0"}, "phoenix_live_view": {:hex, :phoenix_live_view, "1.1.27", "9afcab28b0c82afdc51044e661bcd5b8de53d242593d34c964a37710b40a42af", [:mix], [{:igniter, ">= 0.6.16 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:lazy_html, "~> 0.1.0", [hex: :lazy_html, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0 or ~> 1.8.0-rc", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "415735d0b2c612c9104108b35654e977626a0cb346711e1e4f1ed16e3c827ede"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.2.0", "ff3a5616e1bed6804de7773b92cbccfc0b0f473faf1f63d7daf1206c7aeaaa6f", [:mix], [], "hexpm", "adc313a5bf7136039f63cfd9668fde73bba0765e0614cba80c06ac9460ff3e96"}, - "phoenix_storybook": {:hex, :phoenix_storybook, "0.9.3", "4f94e731d4c40d4dd7d1eddf7d5c6914366da7d78552dc565b222e4036d0d76f", [:mix], [{:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:jason, "~> 1.3", [hex: :jason, repo: "hexpm", optional: true]}, {:makeup_eex, "~> 2.0.2", [hex: :makeup_eex, repo: "hexpm", optional: false]}, {:makeup_html, "~> 0.2.0", [hex: :makeup_html, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.8.1", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html_helpers, "~> 1.0", [hex: :phoenix_html_helpers, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}], "hexpm", "4c8658b756fd8238f7e8e4343a0f12bdb91d4eba592b1c4e8118b37b6fd43e4b"}, "phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"}, "phoenix_view": {:hex, :phoenix_view, "2.0.4", "b45c9d9cf15b3a1af5fb555c674b525391b6a1fe975f040fb4d913397b31abf4", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "4e992022ce14f31fe57335db27a28154afcc94e9983266835bb3040243eb620b"}, "php_serializer": {:hex, :php_serializer, "2.0.0", "b43f31aca22ed7321f32da2b94fe2ddf9b6739a965cb51541969119e572e821d", [:mix], [], "hexpm", "61e402e99d9062c0225a3f4fcf7e43b4cba1b8654944c0e7c139c3ca9de481da"}, diff --git a/storybook/_root.index.exs b/storybook/_root.index.exs deleted file mode 100644 index 460c0dbdccf5..000000000000 --- a/storybook/_root.index.exs +++ /dev/null @@ -1,8 +0,0 @@ -defmodule Storybook.Root do - # See https://hexdocs.pm/phoenix_storybook/PhoenixStorybook.Index.html for full index - # documentation. - - use PhoenixStorybook.Index - - def folder_name, do: "Plausible Components" -end diff --git a/storybook/button.story.exs b/storybook/button.story.exs deleted file mode 100644 index b43217624b81..000000000000 --- a/storybook/button.story.exs +++ /dev/null @@ -1,43 +0,0 @@ -defmodule PlausibleWeb.Storybook.Button do - @moduledoc false - use PhoenixStorybook.Story, :component - - def function, do: &PlausibleWeb.Components.Generic.button/1 - - def attributes, do: [] - def slots, do: [] - - def variations do - [ - %Variation{ - id: :default, - description: "Primary button", - slots: ["Click me!"] - }, - %Variation{ - id: :disabled, - description: "Disabled button", - attributes: %{ - "disabled" => "true" - }, - slots: ["Click me!"] - }, - %Variation{ - id: :secondary, - description: "Secondary button", - attributes: %{ - "theme" => "secondary" - }, - slots: ["Click me!"] - }, - %Variation{ - id: :danger, - description: "Danger button", - attributes: %{ - "theme" => "danger" - }, - slots: ["Click me!"] - } - ] - end -end diff --git a/storybook/dropdown.story.exs b/storybook/dropdown.story.exs deleted file mode 100644 index 6a3bbc01931f..000000000000 --- a/storybook/dropdown.story.exs +++ /dev/null @@ -1,31 +0,0 @@ -defmodule PlausibleWeb.Storybook.Dropdown do - @moduledoc false - use PhoenixStorybook.Story, :component - - # required - def function, do: &PlausibleWeb.Components.Generic.dropdown/1 - def imports, do: [{PlausibleWeb.Components.Generic, dropdown_item: 1, dropdown_divider: 1}] - - def attributes, do: [] - def slots, do: [] - - def variations do - [ - %Variation{ - id: :default, - description: "Default dropdown", - slots: [ - ~s| -<:button class="bg-transparent text-gray-800 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-700 focus-visible:outline-gray-100 whitespace-nowrap truncate inline-flex items-center gap-x-2 font-medium rounded-md px-3.5 py-2.5 text-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2">Click me -<:menu> - <.dropdown_item href="#">Option A - <.dropdown_item href="#">Option B - <.dropdown_divider /> - <.dropdown_item href="#" class="text-red-600 dark:text-red-600">Nuclear option - -| - ] - } - ] - end -end diff --git a/storybook/input.story.exs b/storybook/input.story.exs deleted file mode 100644 index 33a45a25867e..000000000000 --- a/storybook/input.story.exs +++ /dev/null @@ -1,45 +0,0 @@ -defmodule PlausibleWeb.Storybook.Input do - @moduledoc false - use PhoenixStorybook.Story, :component - - def function, do: &PlausibleWeb.Live.Components.Form.input/1 - - def attributes, do: [] - def slots, do: [] - - def variations do - [ - %Variation{ - id: :default, - description: "Basic input", - attributes: %{ - name: "user[name]", - value: "", - label: "Full name" - } - }, - %Variation{ - id: :errors, - description: "With help text and error", - attributes: %{ - name: "user[name]", - value: "", - label: "Email", - help_text: "Get ready for spam!", - errors: ["Cannot be blank"] - } - }, - %Variation{ - id: :select, - description: "Select input", - attributes: %{ - name: "user[color_mode]", - value: "System", - label: "Color mode", - type: "select", - options: ["System", "Light", "Dark"] - } - } - ] - end -end From 3b6f0c8f645e2d07f6817e69c660963942442e22 Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Thu, 1 Oct 2026 11:04:00 -0500 Subject: [PATCH 2/2] Build pinned MinIO test image from source The published minio/minio image is no longer available, preventing CI from reaching the test suite. Build the server and client from pinned upstream releases instead. Verified bucket creation, lifecycle policies, and object round-trip locally. --- Makefile | 5 +++-- test/support/minio/Dockerfile | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 test/support/minio/Dockerfile diff --git a/Makefile b/Makefile index 167706e68ac8..0e55a1045a49 100644 --- a/Makefile +++ b/Makefile @@ -56,8 +56,9 @@ postgres-stop: ## Stop and remove the postgres container browserless: docker run -e "TOKEN=dummy_token" -p 3000:3000 --network host ghcr.io/browserless/chromium -minio: ## Start a transient container with a recent version of minio (s3) - docker run -d --rm -p 10000:10000 -p 10001:10001 --name plausible_minio minio/minio server /data --address ":10000" --console-address ":10001" +minio: ## Build and start a transient minio (s3) test container + docker build -t plausible-minio:test test/support/minio + docker run -d --rm -p 10000:10000 -p 10001:10001 --name plausible_minio plausible-minio:test server /data --address ":10000" --console-address ":10001" while ! docker exec plausible_minio mc alias set local http://localhost:10000 minioadmin minioadmin; do sleep 1; done docker exec plausible_minio sh -c 'mc mb local/dev-exports && mc ilm add --expiry-days 7 local/dev-exports' docker exec plausible_minio sh -c 'mc mb local/dev-imports && mc ilm add --expiry-days 7 local/dev-imports' diff --git a/test/support/minio/Dockerfile b/test/support/minio/Dockerfile new file mode 100644 index 000000000000..a433cc8476d5 --- /dev/null +++ b/test/support/minio/Dockerfile @@ -0,0 +1,9 @@ +FROM golang:1.24.8-alpine3.22 AS build + +ENV CGO_ENABLED=0 +RUN go install github.com/minio/minio@RELEASE.2025-10-15T17-29-55Z && \ + go install github.com/minio/mc@RELEASE.2025-08-13T08-35-41Z + +FROM alpine:3.22.2 +COPY --from=build /go/bin/minio /go/bin/mc /usr/local/bin/ +ENTRYPOINT ["minio"]