Flags: changed, listed and removed
jadpo flags reads and changes jadpo_flags in the flags' store, found
as jadpo schedules finds its database, and runs none of the app's code
(jadpo flags).
Setting a value
jadpo flags set <flag> [<value>] changes one part of the flag's state
and leaves the rest:
- With no option,
<value>becomes everyone's value. --users <id>,<id>gives those users<value>, eachidaUuid.--percent <n>replaces the shares with one,<value>forn% of users;--percent 0removes them.--split <value>=<n>,…replaces the shares with one for each value, in the order written, the percentages adding up to 100 or less. It takes no<value>, and not with--percent.
--users and --percent go together. A Bool flag's <value> is
true when an option is given without one. A value is written as a
test's flags: writes it, true or a variant's name.
jadpo flags reset <flag> gives everyone the default: again, its row
deleted; with --users, only those users stop being named.
The log
Each change writes a row of jadpo_flag_changes in the same statement
as the change: when, the flag, set or reset, its state before and
after, the name the operator's machine gives (USER, else LOGNAME or
USERNAME), and the database role PostgreSQL authenticated
(session_user), which the statement reads itself so it can't be
faked. The screen shows both, as jadpo deliveries does. A row is kept
for good: changes are few, and a flag's history is what a reviewer reads
when a release went wrong. Its rows, like jadpo_flags, hold named
users' ids; a user's erasure removes them from both, which comes with
erasures (Erasures). A change is made
only to the row as it was read, so of two operators acting at once, one
acts and the other is told it changed (flags.unavailable).
There is no production guard and no prompt. Changing a flag is the point of a running app's flags; a change is logged, reversible and reaches every server within ten seconds.
Ready to remove
A flag is ready to remove when every caller gets one value (each named user's, each share's with a percentage above 0 and everyone's are the same) and its row last changed seven days ago or more. A flag never changed has no row, so it is never marked: it hasn't been released.
Both values tested
flag.value_untested follows the calls each test makes, through the
actions and fixtures it reaches and the routes it sends requests
through (their run: and the action it runs), to every flags.<name>
in the bodies it reaches, whichever branch of them it takes. A test gives each flag its flags: value, or the
default:. A read the reaching tests don't give every value is an
error at the read, naming the values missing, and it can't be declined.
A test's own read of a flag isn't counted.
Removing
jadpo flags remove <flag> --keep <value> refuses a project that
doesn't check, and refuses <value> that isn't one of the flag's. Then:
-
A read that is an
if's whole condition, alone, behind!, or compared with==or!=to a value, decides theif: its block or itselsestays, unwrapped to the enclosing block, and anelse ifchain keeps its own conditions. When the kept block ends by returning, what came after it in the same block can't run and goes. -
Every other read becomes the kept value,
trueorType.variant. -
The declaration goes from
flags { }. When it was the last,flags { }stays, empty, sojadpo_flagsand its log stay: dropping them is a migration of its own, which comes with dropping tables. -
Each test's
flags:line for it goes, andflags:with it when it was the last. A test whose value was another and that reached a read goes whole; here a read inside anifanother flag decides is reached only by the tests whose values take that branch. -
An enum flag's type goes too when nothing uses it any more, and its file when nothing else is in it.
Imports a change leaves unused go, and each file is formatted as it
was. The result is checked, and undone with its errors when it doesn't
check. A flag a route's run: passes on is refused before anything
changes, since a route's run: passes no value written out: the
action reads the flag itself first.
GET /flags
Each API with a record gets GET <prefix>/flags while a flag has
client: true. It is authenticated as the API's routes are, and
answers with a JSON object of each client: true flag by name, a
Bool as true or false and an enum as its variant's name, worked
out for the caller as an action's read is, with cache-control: no-store. The OpenAPI document gives its schema, the enum's values
listed. A route the app writes at that path is route.path_overlap.
Markdown for agents: /docs/flags-changed-listed-and-removed.md.Built from Jadpo main at e00e61f.