Skip to content

Commit aa5291f

Browse files
committed
Rename all env vars, even ones from other systems.
1 parent 6d2bf8b commit aa5291f

25 files changed

Lines changed: 186 additions & 226 deletions

File tree

.env.example

Lines changed: 15 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
# is also what the admin Settings page renders. Values shown are defaults;
55
# a commented line means the default applies when the variable is unset.
66
#
7+
# Every name is derived from its declaration as GAMEND_<GROUP>_<KEY>, with
8+
# no exceptions. Variables other software reads (RELEASE_COOKIE for the
9+
# release boot script, FLY_* from the platform) are not settings and are
10+
# not listed here.
11+
#
712
# Settings can equally be configured in Elixir, which skips this file
813
# entirely:
914
#
@@ -59,36 +64,9 @@
5964
# DNS name whose A/AAAA records list the other nodes, polled at boot.
6065
# GAMEND_CLUSTER_DNS_QUERY=
6166

62-
# Extra BEAM flags, e.g. -proto_dist inet6_tcp for IPv6-only networking.
63-
# Inherited: this name is defined by other software.
64-
# ERL_AFLAGS=
65-
66-
# Inherited: this name is defined by other software.
67-
# FLY_APP_NAME=
68-
69-
# Inherited: this name is defined by other software.
70-
# FLY_PRIVATE_IP=
71-
72-
# Inherited: this name is defined by other software.
73-
# FLY_REGION=
74-
7567
# Shared fallback URL used by the cache and rate limiter when neither sets
7668
# its own.
77-
# Inherited: this name is defined by other software.
78-
# REDIS_URL=
79-
80-
# Shared secret every node in the cluster must match.
81-
# Secret — never commit a real value.
82-
# Inherited: this name is defined by other software.
83-
# RELEASE_COOKIE=
84-
85-
# name (long names) or sname. Read by the release boot script.
86-
# Inherited: this name is defined by other software.
87-
# RELEASE_DISTRIBUTION=
88-
89-
# This node's name. Must be unique across the cluster.
90-
# Inherited: this name is defined by other software.
91-
# RELEASE_NODE=
69+
# GAMEND_CLUSTER_REDIS_URL=
9270

9371
# ──────────────────────────────────────────────────────────────────────────
9472
# Content & plugins
@@ -123,21 +101,16 @@
123101
# How long a request waits to check out a connection, in milliseconds.
124102
# GAMEND_DB_POOL_TIMEOUT=10000
125103

126-
# Inherited: this name is defined by other software.
127-
# POSTGRES_DB=
104+
# GAMEND_DB_POSTGRES_DB=
128105

129-
# Inherited: this name is defined by other software.
130-
# POSTGRES_HOST=
106+
# GAMEND_DB_POSTGRES_HOST=
131107

132108
# Secret — never commit a real value.
133-
# Inherited: this name is defined by other software.
134-
# POSTGRES_PASSWORD=
109+
# GAMEND_DB_POSTGRES_PASSWORD=
135110

136-
# Inherited: this name is defined by other software.
137-
# POSTGRES_PORT=5432
111+
# GAMEND_DB_POSTGRES_PORT=5432
138112

139-
# Inherited: this name is defined by other software.
140-
# POSTGRES_USER=
113+
# GAMEND_DB_POSTGRES_USER=
141114

142115
# GAMEND_DB_QUERY_TIMEOUT=15000
143116

@@ -158,10 +131,9 @@
158131

159132
# GAMEND_DB_SQLITE_WAL_AUTOCHECKPOINT=2000
160133

161-
# Full ecto:// URL. Takes precedence over the individual POSTGRES_* values.
134+
# Full ecto:// URL. Takes precedence over the individual postgres_* values.
162135
# Secret — never commit a real value.
163-
# Inherited: this name is defined by other software.
164-
# DATABASE_URL=
136+
# GAMEND_DB_URL=
165137

166138
# ──────────────────────────────────────────────────────────────────────────
167139
# Email
@@ -681,9 +653,8 @@
681653
# Public hostname, used to build URLs and OAuth redirect URIs.
682654
# GAMEND_HTTP_HOST=localhost
683655

684-
# TCP port the HTTP listener binds. Injected by most platforms.
685-
# Inherited: this name is defined by other software.
686-
# PORT=4000
656+
# TCP port the HTTP listener binds.
657+
# GAMEND_HTTP_PORT=4000
687658

688659
# http or https. Defaults to http for localhost, https otherwise.
689660
# GAMEND_HTTP_SCHEME=

.github/workflows/build-and-check.yml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,8 @@ jobs:
121121
122122
docker network create smoke-net
123123
124-
# POSTGRES_* are inherited names — platforms provision them, so they
125-
# are the only database variables the server reads. Using a derived
126-
# GAMEND_DB_POSTGRES_* name here silently configures nothing.
124+
# The postgres container reads its own POSTGRES_* names to
125+
# initialise; the server reads ours. They are deliberately distinct.
127126
{
128127
echo "GAMEND_AUTH_SECRET_KEY_BASE=$(head -c 48 /dev/urandom | base64 | tr -d '\n')"
129128
echo "GAMEND_HTTP_HOST=localhost"
@@ -143,10 +142,10 @@ jobs:
143142
done
144143
145144
{
146-
echo "POSTGRES_HOST=smoke-db"
147-
echo "POSTGRES_USER=postgres"
148-
echo "POSTGRES_PASSWORD=postgres"
149-
echo "POSTGRES_DB=game_server_prod"
145+
echo "GAMEND_DB_POSTGRES_HOST=smoke-db"
146+
echo "GAMEND_DB_POSTGRES_USER=postgres"
147+
echo "GAMEND_DB_POSTGRES_PASSWORD=postgres"
148+
echo "GAMEND_DB_POSTGRES_DB=game_server_prod"
150149
} >> smoke.env
151150
fi
152151

apps/game_server_core/lib/game_server/cluster.ex

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,17 @@ defmodule GameServer.Cluster do
33
Erlang distribution, needed for multi-node deployments and the partitioned
44
L2 cache.
55
6-
Every name here is inherited: `RELEASE_*` and `ERL_AFLAGS` are read by the
7-
BEAM and by Elixir's release scripts before any of our code runs, and the
8-
`FLY_*` values are injected by the platform. They are declared so the admin
9-
page can show what the node actually came up with.
6+
Only `dns_query` and `redis_url` are settings — values this server reads.
7+
The rest of a clustered deployment is configured through variables *other
8+
software* reads before any of our code runs: `RELEASE_DISTRIBUTION`,
9+
`RELEASE_NODE` and `RELEASE_COOKIE` are consumed by the release boot script,
10+
`ERL_AFLAGS` by `erl` itself, and the `FLY_*` values are injected by the
11+
platform.
12+
13+
Declaring those as settings would be a lie: renaming them onto our convention
14+
would not rename what the BEAM and the platform read, it would leave the
15+
settings permanently empty. `environment/0` reports them for the admin page
16+
as observations rather than settings.
1017
"""
1118

1219
use GameServer.Settings.Provider,
@@ -18,38 +25,26 @@ defmodule GameServer.Cluster do
1825
doc: "DNS name whose A/AAAA records list the other nodes, polled at boot."
1926
)
2027

21-
setting(:release_distribution, :string,
22-
env: "RELEASE_DISTRIBUTION",
23-
external: true,
24-
doc: "name (long names) or sname. Read by the release boot script."
25-
)
26-
27-
setting(:release_node, :string,
28-
env: "RELEASE_NODE",
29-
external: true,
30-
doc: "This node's name. Must be unique across the cluster."
28+
setting(:redis_url, :string,
29+
doc: "Shared fallback URL used by the cache and rate limiter when neither sets its own."
3130
)
3231

33-
setting(:release_cookie, :string,
34-
env: "RELEASE_COOKIE",
35-
external: true,
36-
secret: true,
37-
doc: "Shared secret every node in the cluster must match."
38-
)
32+
@external ~w(RELEASE_DISTRIBUTION RELEASE_NODE RELEASE_COOKIE ERL_AFLAGS
33+
FLY_APP_NAME FLY_PRIVATE_IP FLY_REGION)
3934

40-
setting(:erl_aflags, :string,
41-
env: "ERL_AFLAGS",
42-
external: true,
43-
doc: "Extra BEAM flags, e.g. -proto_dist inet6_tcp for IPv6-only networking."
44-
)
35+
@secret ~w(RELEASE_COOKIE)
4536

46-
setting(:redis_url, :string,
47-
env: "REDIS_URL",
48-
external: true,
49-
doc: "Shared fallback URL used by the cache and rate limiter when neither sets its own."
50-
)
37+
@doc """
38+
The clustering variables other software reads, with their current values,
39+
for display only.
5140
52-
setting(:fly_app_name, :string, env: "FLY_APP_NAME", external: true)
53-
setting(:fly_private_ip, :string, env: "FLY_PRIVATE_IP", external: true)
54-
setting(:fly_region, :string, env: "FLY_REGION", external: true)
41+
These are not settings and cannot be renamed onto our convention — the BEAM
42+
and the platform read these exact names.
43+
"""
44+
@spec environment() :: [%{name: String.t(), value: String.t() | nil, secret: boolean()}]
45+
def environment do
46+
for name <- @external do
47+
%{name: name, value: System.get_env(name), secret: name in @secret}
48+
end
49+
end
5550
end

apps/game_server_core/lib/game_server/database.ex

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ defmodule GameServer.Database do
66
`adapter` here is documentation and admin display rather than something a
77
restart can change — the app refuses to start on a stale build and says so.
88
9-
`DATABASE_URL` and the `POSTGRES_*` family are inherited names: platforms
9+
`GAMEND_DB_URL` and the `POSTGRES_*` family are inherited names: platforms
1010
provision them, and renaming them would break every managed-database
1111
attachment.
1212
"""
@@ -22,17 +22,15 @@ defmodule GameServer.Database do
2222
)
2323

2424
setting(:url, :string,
25-
env: "DATABASE_URL",
26-
external: true,
2725
secret: true,
28-
doc: "Full ecto:// URL. Takes precedence over the individual POSTGRES_* values."
26+
doc: "Full ecto:// URL. Takes precedence over the individual postgres_* values."
2927
)
3028

31-
setting(:postgres_host, :string, env: "POSTGRES_HOST", external: true)
32-
setting(:postgres_port, :integer, default: 5432, env: "POSTGRES_PORT", external: true)
33-
setting(:postgres_user, :string, env: "POSTGRES_USER", external: true)
34-
setting(:postgres_password, :string, env: "POSTGRES_PASSWORD", external: true, secret: true)
35-
setting(:postgres_db, :string, env: "POSTGRES_DB", external: true)
29+
setting(:postgres_host, :string)
30+
setting(:postgres_port, :integer, default: 5432)
31+
setting(:postgres_user, :string)
32+
setting(:postgres_password, :string, secret: true)
33+
setting(:postgres_db, :string)
3634

3735
setting(:ipv6, :boolean,
3836
default: false,

apps/game_server_core/lib/game_server/settings/provider.ex

Lines changed: 13 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,13 @@ defmodule GameServer.Settings.Provider do
1616
The declaration is the only place a setting is written down. Its environment
1717
variable name is **derived** — `<ROOT>_<GROUP>_<KEY>`, e.g.
1818
`GAMEND_RETENTION_CHAT_MESSAGES_DAYS` — so the key and its env var can never
19-
disagree. Pass `env:` only for the handful of names other software owns
20-
(`PORT`, `DATABASE_URL`), which should also carry `external: true`.
19+
disagree. There is no way to pin a different name: every setting follows the
20+
convention, without exception.
21+
22+
A variable that *other* software reads (`RELEASE_COOKIE` for the release boot
23+
script, `FLY_REGION` from the platform) is not a setting and does not belong
24+
here — renaming our declaration would not rename what that software reads.
25+
Report those separately; `GameServer.Cluster.environment/0` is the example.
2126
2227
Values are read back with `GameServer.Settings.get/2`, which checks
2328
`Application.get_env(app, module)` and falls back to the compiled default. A
@@ -33,10 +38,6 @@ defmodule GameServer.Settings.Provider do
3338
- `:root` — first segment of the env name. Defaults to `"GAMEND"`; a plugin
3439
passes its own (`root: "POLYGLOT"`).
3540
- `:label` — display name for the group. Defaults to a capitalised `:group`.
36-
- `:env_prefix` — replaces the derived `<ROOT>_<GROUP>_` prefix for every
37-
setting in the provider, so `LIMIT_MAX_PAGE_SIZE` can keep its name while
38-
the group is `:limits`. A transitional escape hatch for names that predate
39-
the convention; a per-setting `env:` still wins over it.
4041
4142
## Options for `setting/3`
4243
@@ -50,22 +51,18 @@ defmodule GameServer.Settings.Provider do
5051
them to hold.
5152
- `:with` — sibling keys forming a complete-or-empty group. All unset is
5253
silent; a partial set trips `:required`.
53-
- `:env` — override the derived env var name. For inherited names only.
54-
- `:external` — this name belongs to other software; the viewer files it
55-
under "Inherited" rather than implying we own it.
5654
"""
5755

5856
@types [:string, :integer, :float, :boolean, :atom, :list, :log_level]
5957

60-
@setting_opts [:default, :doc, :secret, :required, :when, :with, :env, :external]
58+
@setting_opts [:default, :doc, :secret, :required, :when, :with]
6159

6260
@doc false
6361
defmacro __using__(opts) do
6462
app = Keyword.fetch!(opts, :app)
6563
group = Keyword.fetch!(opts, :group)
6664
root = Keyword.get(opts, :root, "GAMEND")
6765
label = Keyword.get(opts, :label) || group |> to_string() |> String.capitalize()
68-
env_prefix = Keyword.get(opts, :env_prefix)
6966

7067
quote do
7168
import GameServer.Settings.Provider, only: [setting: 2, setting: 3]
@@ -76,7 +73,6 @@ defmodule GameServer.Settings.Provider do
7673
@gamend_settings_group unquote(group)
7774
@gamend_settings_root unquote(root)
7875
@gamend_settings_label unquote(label)
79-
@gamend_settings_env_prefix unquote(env_prefix)
8076

8177
@before_compile GameServer.Settings.Provider
8278
end
@@ -98,16 +94,8 @@ defmodule GameServer.Settings.Provider do
9894
group = Module.get_attribute(module, :gamend_settings_group)
9995
root = Module.get_attribute(module, :gamend_settings_root)
10096
label = Module.get_attribute(module, :gamend_settings_label)
101-
env_prefix = Module.get_attribute(module, :gamend_settings_env_prefix)
10297

103-
context = %{
104-
module: module,
105-
app: app,
106-
group: group,
107-
root: root,
108-
label: label,
109-
env_prefix: env_prefix
110-
}
98+
context = %{module: module, app: app, group: group, root: root, label: label}
11199

112100
definitions =
113101
module
@@ -155,10 +143,9 @@ option(s) #{inspect(unknown)}; expected one of #{inspect(@setting_opts)}"
155143
label: label,
156144
type: type,
157145
default: Keyword.get(opts, :default),
158-
env: Keyword.get(opts, :env) || derive_env(root, group, key, context.env_prefix),
146+
env: derive_env(root, group, key),
159147
doc: Keyword.get(opts, :doc, ""),
160148
secret: Keyword.get(opts, :secret, false),
161-
external: Keyword.get(opts, :external, false),
162149
required: required,
163150
when: Keyword.get(opts, :when),
164151
with: Keyword.get(opts, :with, [])
@@ -168,16 +155,10 @@ option(s) #{inspect(unknown)}; expected one of #{inspect(@setting_opts)}"
168155
@doc """
169156
The environment variable name for a group and key: `<ROOT>_<GROUP>_<KEY>`.
170157
171-
A provider-level `env_prefix` replaces the `<ROOT>_<GROUP>_` part.
158+
The only way a setting gets a name. There is no override.
172159
"""
173-
@spec derive_env(String.t(), atom(), atom(), String.t() | nil) :: String.t()
174-
def derive_env(root, group, key, env_prefix \\ nil)
175-
176-
def derive_env(_root, _group, key, env_prefix) when is_binary(env_prefix) do
177-
env_prefix <> String.upcase(to_string(key))
178-
end
179-
180-
def derive_env(root, group, key, nil) do
160+
@spec derive_env(String.t(), atom(), atom()) :: String.t()
161+
def derive_env(root, group, key) do
181162
[root, to_string(group), to_string(key)]
182163
|> Enum.map_join("_", &String.upcase/1)
183164
end

apps/game_server_core/lib/mix/tasks/gamend.settings.env_example.ex

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ defmodule Mix.Tasks.Gamend.Settings.EnvExample do
6363
# is also what the admin Settings page renders. Values shown are defaults;
6464
# a commented line means the default applies when the variable is unset.
6565
#
66+
# Every name is derived from its declaration as GAMEND_<GROUP>_<KEY>, with
67+
# no exceptions. Variables other software reads (RELEASE_COOKIE for the
68+
# release boot script, FLY_* from the platform) are not settings and are
69+
# not listed here.
70+
#
6671
# Settings can equally be configured in Elixir, which skips this file
6772
# entirely:
6873
#
@@ -105,11 +110,7 @@ defmodule Mix.Tasks.Gamend.Settings.EnvExample do
105110
defp annotations(definition) do
106111
[
107112
requirement_note(definition),
108-
if(definition.secret, do: "# Secret — never commit a real value.\n", else: []),
109-
if(definition.external,
110-
do: "# Inherited: this name is defined by other software.\n",
111-
else: []
112-
)
113+
if(definition.secret, do: "# Secret — never commit a real value.\n", else: [])
113114
]
114115
end
115116

apps/game_server_web/config/dev.exs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import Config
22

3-
if System.get_env("DATABASE_URL") ||
4-
(System.get_env("POSTGRES_HOST") && System.get_env("POSTGRES_USER")) do
3+
if System.get_env("GAMEND_DB_URL") ||
4+
(System.get_env("GAMEND_DB_POSTGRES_HOST") && System.get_env("GAMEND_DB_POSTGRES_USER")) do
55
database_url =
6-
System.get_env("DATABASE_URL") ||
7-
"ecto://#{System.get_env("POSTGRES_USER")}:#{System.get_env("POSTGRES_PASSWORD")}@#{System.get_env("POSTGRES_HOST")}:#{System.get_env("POSTGRES_PORT", "5432")}/#{System.get_env("POSTGRES_DB", "game_server_web_dev")}"
6+
System.get_env("GAMEND_DB_URL") ||
7+
"ecto://#{System.get_env("GAMEND_DB_POSTGRES_USER")}:#{System.get_env("GAMEND_DB_POSTGRES_PASSWORD")}@#{System.get_env("GAMEND_DB_POSTGRES_HOST")}:#{System.get_env("GAMEND_DB_POSTGRES_PORT", "5432")}/#{System.get_env("GAMEND_DB_POSTGRES_DB", "game_server_web_dev")}"
88

99
config :game_server_core, GameServer.Repo,
1010
url: database_url,

0 commit comments

Comments
 (0)