Skip to content

Commit 9f59284

Browse files
fix: make Docker build and PostgreSQL migrations work end-to-end
- Update Dockerfile base image to bookworm-20260202 (old tag missing) - Reorder Dockerfile: run mix compile before assets.deploy so Phoenix colocated hooks are generated before esbuild needs them - Add :phoenix_live_view compiler to mix.exs for colocated JS generation - Guard Oban SQLite migration with adapter check to skip on PostgreSQL - Rewrite discovery_sources migration to use ALTER TABLE on PostgreSQL instead of SQLite-specific table recreation with TEXT foreign keys
1 parent e29b25e commit 9f59284

4 files changed

Lines changed: 92 additions & 69 deletions

File tree

Dockerfile

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# ---- Build Stage ----
22
ARG ELIXIR_VERSION=1.19.5
33
ARG OTP_VERSION=28.3.1
4-
ARG DEBIAN_VERSION=bookworm-20241202-slim
4+
ARG DEBIAN_VERSION=bookworm-20260202-slim
55
ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}"
66
ARG RUNNER_IMAGE="debian:${DEBIAN_VERSION}"
77

@@ -28,18 +28,18 @@ RUN mkdir config
2828
COPY config/config.exs config/prod.exs config/
2929
RUN mix deps.compile
3030

31-
# Copy application code
31+
# Copy application code and runtime config
3232
COPY priv priv
3333
COPY lib lib
3434
COPY assets assets
35-
36-
# Compile assets
37-
RUN mix assets.deploy
38-
39-
# Compile the release
4035
COPY config/runtime.exs config/
36+
37+
# Compile the application (generates phoenix-colocated hooks needed by esbuild)
4138
RUN mix compile
4239

40+
# Compile assets (must run after mix compile for colocated hooks)
41+
RUN mix assets.deploy
42+
4343
# Build the release
4444
RUN mix release
4545

mix.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ defmodule SentinelCp.MixProject do
1010
start_permanent: Mix.env() == :prod,
1111
aliases: aliases(),
1212
deps: deps(),
13+
compilers: [:phoenix_live_view] ++ Mix.compilers(),
1314
listeners: [Phoenix.CodeReloader]
1415
]
1516
end

priv/repo/migrations/20260116063800_create_oban_jobs.exs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,19 @@ defmodule SentinelCp.Repo.Migrations.CreateObanJobs do
22
use Ecto.Migration
33

44
def up do
5-
Oban.Migrations.SQLite.up(version: 1)
5+
if Application.get_env(:sentinel_cp, :ecto_adapter) == Ecto.Adapters.Postgres do
6+
# PostgreSQL Oban tables are handled by the earlier migration
7+
:ok
8+
else
9+
Oban.Migrations.SQLite.up(version: 1)
10+
end
611
end
712

813
def down do
9-
Oban.Migrations.SQLite.down(version: 1)
14+
if Application.get_env(:sentinel_cp, :ecto_adapter) == Ecto.Adapters.Postgres do
15+
:ok
16+
else
17+
Oban.Migrations.SQLite.down(version: 1)
18+
end
1019
end
1120
end

priv/repo/migrations/20260213140003_add_discovery_source_config.exs

Lines changed: 73 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -2,74 +2,87 @@ defmodule SentinelCp.Repo.Migrations.AddDiscoverySourceConfig do
22
use Ecto.Migration
33

44
def up do
5-
# SQLite doesn't support ALTER COLUMN, so we recreate the table
6-
# to make hostname nullable (K8s sources don't use it)
7-
execute("""
8-
CREATE TABLE discovery_sources_new (
9-
id TEXT PRIMARY KEY,
10-
source_type TEXT NOT NULL DEFAULT 'dns_srv',
11-
hostname TEXT,
12-
config TEXT DEFAULT '{}',
13-
sync_interval_seconds INTEGER DEFAULT 60,
14-
auto_sync INTEGER DEFAULT 1,
15-
last_synced_at TEXT,
16-
last_sync_status TEXT DEFAULT 'pending',
17-
last_sync_error TEXT,
18-
last_sync_targets_count INTEGER DEFAULT 0,
19-
upstream_group_id TEXT NOT NULL REFERENCES upstream_groups(id) ON DELETE CASCADE,
20-
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
21-
inserted_at TEXT NOT NULL,
22-
updated_at TEXT NOT NULL
23-
)
24-
""")
5+
if Application.get_env(:sentinel_cp, :ecto_adapter) == Ecto.Adapters.Postgres do
6+
# PostgreSQL supports ALTER COLUMN directly
7+
alter table(:discovery_sources) do
8+
modify :hostname, :string, null: true
9+
add_if_not_exists :config, :map, default: %{}
10+
end
11+
else
12+
# SQLite doesn't support ALTER COLUMN, so we recreate the table
13+
execute("""
14+
CREATE TABLE discovery_sources_new (
15+
id TEXT PRIMARY KEY,
16+
source_type TEXT NOT NULL DEFAULT 'dns_srv',
17+
hostname TEXT,
18+
config TEXT DEFAULT '{}',
19+
sync_interval_seconds INTEGER DEFAULT 60,
20+
auto_sync INTEGER DEFAULT 1,
21+
last_synced_at TEXT,
22+
last_sync_status TEXT DEFAULT 'pending',
23+
last_sync_error TEXT,
24+
last_sync_targets_count INTEGER DEFAULT 0,
25+
upstream_group_id TEXT NOT NULL REFERENCES upstream_groups(id) ON DELETE CASCADE,
26+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
27+
inserted_at TEXT NOT NULL,
28+
updated_at TEXT NOT NULL
29+
)
30+
""")
2531

26-
execute("""
27-
INSERT INTO discovery_sources_new
28-
SELECT id, source_type, hostname, '{}', sync_interval_seconds, auto_sync,
29-
last_synced_at, last_sync_status, last_sync_error, last_sync_targets_count,
30-
upstream_group_id, project_id, inserted_at, updated_at
31-
FROM discovery_sources
32-
""")
32+
execute("""
33+
INSERT INTO discovery_sources_new
34+
SELECT id, source_type, hostname, '{}', sync_interval_seconds, auto_sync,
35+
last_synced_at, last_sync_status, last_sync_error, last_sync_targets_count,
36+
upstream_group_id, project_id, inserted_at, updated_at
37+
FROM discovery_sources
38+
""")
3339

34-
execute("DROP TABLE discovery_sources")
35-
execute("ALTER TABLE discovery_sources_new RENAME TO discovery_sources")
40+
execute("DROP TABLE discovery_sources")
41+
execute("ALTER TABLE discovery_sources_new RENAME TO discovery_sources")
3642

37-
# Recreate indexes
38-
create index(:discovery_sources, [:project_id])
39-
create unique_index(:discovery_sources, [:upstream_group_id])
43+
create index(:discovery_sources, [:project_id])
44+
create unique_index(:discovery_sources, [:upstream_group_id])
45+
end
4046
end
4147

4248
def down do
43-
execute("""
44-
CREATE TABLE discovery_sources_old (
45-
id TEXT PRIMARY KEY,
46-
source_type TEXT NOT NULL DEFAULT 'dns_srv',
47-
hostname TEXT NOT NULL,
48-
sync_interval_seconds INTEGER DEFAULT 60,
49-
auto_sync INTEGER DEFAULT 1,
50-
last_synced_at TEXT,
51-
last_sync_status TEXT DEFAULT 'pending',
52-
last_sync_error TEXT,
53-
last_sync_targets_count INTEGER DEFAULT 0,
54-
upstream_group_id TEXT NOT NULL REFERENCES upstream_groups(id) ON DELETE CASCADE,
55-
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
56-
inserted_at TEXT NOT NULL,
57-
updated_at TEXT NOT NULL
58-
)
59-
""")
49+
if Application.get_env(:sentinel_cp, :ecto_adapter) == Ecto.Adapters.Postgres do
50+
alter table(:discovery_sources) do
51+
modify :hostname, :string, null: false
52+
remove :config
53+
end
54+
else
55+
execute("""
56+
CREATE TABLE discovery_sources_old (
57+
id TEXT PRIMARY KEY,
58+
source_type TEXT NOT NULL DEFAULT 'dns_srv',
59+
hostname TEXT NOT NULL,
60+
sync_interval_seconds INTEGER DEFAULT 60,
61+
auto_sync INTEGER DEFAULT 1,
62+
last_synced_at TEXT,
63+
last_sync_status TEXT DEFAULT 'pending',
64+
last_sync_error TEXT,
65+
last_sync_targets_count INTEGER DEFAULT 0,
66+
upstream_group_id TEXT NOT NULL REFERENCES upstream_groups(id) ON DELETE CASCADE,
67+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
68+
inserted_at TEXT NOT NULL,
69+
updated_at TEXT NOT NULL
70+
)
71+
""")
6072

61-
execute("""
62-
INSERT INTO discovery_sources_old
63-
SELECT id, source_type, COALESCE(hostname, ''), sync_interval_seconds, auto_sync,
64-
last_synced_at, last_sync_status, last_sync_error, last_sync_targets_count,
65-
upstream_group_id, project_id, inserted_at, updated_at
66-
FROM discovery_sources
67-
""")
73+
execute("""
74+
INSERT INTO discovery_sources_old
75+
SELECT id, source_type, COALESCE(hostname, ''), sync_interval_seconds, auto_sync,
76+
last_synced_at, last_sync_status, last_sync_error, last_sync_targets_count,
77+
upstream_group_id, project_id, inserted_at, updated_at
78+
FROM discovery_sources
79+
""")
6880

69-
execute("DROP TABLE discovery_sources")
70-
execute("ALTER TABLE discovery_sources_old RENAME TO discovery_sources")
81+
execute("DROP TABLE discovery_sources")
82+
execute("ALTER TABLE discovery_sources_old RENAME TO discovery_sources")
7183

72-
create index(:discovery_sources, [:project_id])
73-
create unique_index(:discovery_sources, [:upstream_group_id])
84+
create index(:discovery_sources, [:project_id])
85+
create unique_index(:discovery_sources, [:upstream_group_id])
86+
end
7487
end
7588
end

0 commit comments

Comments
 (0)