The file's schema version¶
.git-board.toml says which version of its format it is written in: a
top-level key, before the first table.
A file without the key is version 1: what git-board v0.11 and every earlier release write. git-board v0.12 (v2) writes version 2. Each version is a step from the one before, with its way back, as Alembic's migrations are for a database: git-board upgrades a file, and downgrades it for an older git-board, editing the lines that change and nothing else. Comments, order and every other line stay as they were.
The versions¶
| Version | Written by | What it changed | Down |
|---|---|---|---|
| 1 | v0.11 and earlier | The format Configuration describes, no schema key. |
|
| 2 | v0.12 | Sets aside [sprints] start_weekday and [repos] assignees, which no git-board reads, in a comment each: # start_weekday = "monday" # schema 2: git-board doesn't read this key. git board init wrote the first in every file; the second is dead since the assignees live where their field's mapping says (Forges). At version 2 both are keys git-board doesn't know, and warns of. |
lossless |
git board config schema lists the versions between the file and the
binary, with what each changes.
Reading and writing¶
A file older than git-board is read as if it were upgraded: the
upgrade runs in memory, and the file is left as it is. The first
explicit write (config set, config unset, a save in Settings) writes
it upgraded, and says so once:
A write that changes nothing writes nothing, the upgrade included.
A file newer than git-board is read for the tables it knows, with a warning, and never written:
warning: .git-board.toml is schema 3, newer than this git-board's 2: it reads what it knows, writes nothing to it, and ignores the rest; upgrade git-board
error: .git-board.toml is schema 3, and this git-board knows schema 2 at most: it writes nothing to it. Upgrade git-board, or have a git-board that knows schema 3 run git board config downgrade --to 2
Reads go on because a read can't harm the file, and because an older git-board already reads a newer file that way: a key it doesn't know is named and ignored, as a misspelled one is. Which tables a newer version changed only the newer git-board knows, so the older one can't pick the tables it would trust. A write could undo a newer version's edit, or write a form that version no longer reads: it is refused, for every table. A migration that changes what a key means renames the key, so an older git-board sees a key it doesn't know rather than a value it reads wrong.
git-board v0.11 on a version 2 file reads it. It doesn't know the
schema key: each command warns
schema: git-board doesn't know this key, ignored (git board lint) once,
and git board lint counts it as an unknown-key finding, so
lint --strict fails. The keys version 2 set aside are ones v0.11
doesn't read either. To hand the file to a team still on v0.11 without
the warning, downgrade it: git board config downgrade --to 1.
Upgrading and downgrading¶
git board config schema # the file's version, git-board's, the steps between
git board config schema --json # {"file", "binary", "pending"}
git board config upgrade --dry-run # the diff an upgrade would write, as diff -u prints it
git board config upgrade # to git-board's version
git board config upgrade --to 2
git board config downgrade --to 1 --dry-run
git board config downgrade --to 1 # for git-board v0.11
upgrade without --to goes to git-board's version. downgrade needs
--to. Both refuse a version git-board doesn't know, and a file newer
than git-board (exit code 2). Commit the change as any other: it is a
diff to review.
What is lossy¶
No step is lossy yet: from what an upgrade wrote, a downgrade gives the file back byte for byte. What a downgrade can't give back is what was done at the newer version:
- A line version 2 set aside and then edited by hand, its comment changed, stays a comment: the downgrade no longer recognizes it.
- A key set again at version 2 (
[repos] assignees, beside the line set aside) is refused by the downgrade, which would set it twice: keep one of the two by hand.
A lossy step says what it loses in config downgrade's output and in
this table's last column.
Adding a migration¶
A change to the file's format is a new version. The checklist:
- Code. Append a
MigrationtoMigrationsinconf/schema.go,Fromthe current version,Tothe next, a one-lineDesc, and raiseCurrent. BuildUpandDownfrom the edits inconf/migrate.go:RenameKey,MoveKey,RenameTable,MapValue,CommentKeyandUncommentKey,DropKey, joined withChain. Each takes a value over several lines (an array, a"""string) whole:CommentKeycomments every line of it andUncommentKeygives them all back;MapValuerefuses one. Each checks the file it gives back, so a key in a form it doesn't edit (an inline table, a dotted key) is an error the user reads, never a key left behind. - The domain. The table's domain reads the new form alone: an older file reaches it migrated. Don't keep a reader for the old form.
- Both directions.
DownundoesUp. When it can't, keep what it would lose in a comment (CommentKey), or say what is lost inLossy. Keep the lines where they are when you can: a read migrates in memory, and an error message names a line. - A changed meaning renames the key. An older git-board then warns of a key it doesn't know, instead of reading a value wrongly.
- Tests. Add a file to
conf/testdata/schema/<name>.v1.tomlthat has the old form, runGIT_BOARD_GOLDEN_UPDATE=1 go test ./conf -run TestMigrateBothWays, and review the<name>.v<N>.tomlit writes:TestMigrateBothWaysthen checks every fixture up to each version and back, byte for byte when no step is lossy. Test the forms the edit refuses beside it. - This page. A line in the table of versions, and the form in Configuration.
- Compatibility.
make compat.
For Settings and the HTTP API¶
app gives the versions: Config.SchemaVersion is the file's (0
without a file), app.CurrentSchema git-board's, app.ConfigSchema both
and the pending steps, app.MigrateConfig an upgrade or a downgrade,
and conf.ForWrite the text a write starts from (upgraded, or refused
when newer). app.SetConfig returns the write's ConfigWrite, whose
Notice is the line to show.