Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ that is not one task (`taskgate`).
module's defaults by `task reference`, and a page shows one with `<Value name="…" />`.
- **A figure said in prose has a line** in `tools/refgen/figures.txt`: every duration, size and
count a hand-written page says outside `<Value>`, with the constant of spin's that decides it
(`spin:<file>#<Constant> = 15m`), which `task reference:check` reads and holds the line to, or
why nothing holds it. A figure with no line fails, and so does a line its page no longer says.
(`spin:<file>#<Constant> = 15m`), which `task reference:check` reads and holds the line to; with the text of a file
that decides it where no constant does (`spin:<file> has "<text>"`); or with why nothing holds it. A figure with no line fails, and so does a line its page no longer says.
- **What a release is made of**, `reference/release.md`, is written from spin's `versions.yaml` at
the release installations run (its spin-machine), images.json and the module's newest release.
- **Diagrams** are the ones spin and spin-terraform-aws draw beside their sources (`.dot`, `.d2`):
Expand Down
42 changes: 33 additions & 9 deletions tools/refgen/figures.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,14 @@ import (
//
// <page> | <the words on the page> | spin:<file>#<Constant> = <its value>
//
// for a figure a constant of spin's decides, which refgen reads and compares - 15m, 12h, 300, 3 -
// or, in the third place, why nothing holds it: a default of a file refgen cannot evaluate, or
// words that are no figure of the code's. A page that showed a figure with <Value> has no line:
// for a figure a constant of spin's decides, which refgen reads and compares - 15m, 12h, 300, 3;
//
// <page> | <the words on the page> | spin:<file> has "<text>"
//
// for one decided where no constant is - a field's default, a timer's unit, a template's line, a
// Terraform local - held by the text that decides it still being in the file, of spin or of
// spin-terraform-aws, whatever its spacing; or, in the third place, why nothing holds it: another
// party's fact, or words that are no figure of the code's. A page that showed a figure with <Value> has no line:
// the component is the code's own number.
//
// Before it a page said "an hour" of a credential the code had made fifteen minutes, and "about
Expand All @@ -29,19 +34,24 @@ const figuresList = "tools/refgen/figures.txt"
// saidFigure is a duration, a size or a count of tries, in digits or in words.
var saidFigure = regexp.MustCompile(`(?i)\b(?:(?:\d+(?:[.,]\d+)?|an?|one|two|three|four|five|six|seven|eight|nine|ten|twelve|fourteen|fifteen|twenty|thirty|sixty|ninety|half an?|a quarter of an|a few|few)[ -](?:(?:second|minute|hour|day|week|month|year)s?|times|attempts)|\d+(?:\.\d+)? ?[KMGT]i?B)\b`)

// held is a figure's third place when a constant decides it.
var held = regexp.MustCompile(`^spin:(\S+)#(\w+) = (\S+)$`)
// held is a figure's third place when a constant decides it, and has when a file's text does.
var (
held = regexp.MustCompile(`^spin:(\S+)#(\w+) = (\S+)$`)
has = regexp.MustCompile(`^([\w-]+):(\S+) has "(.+)"$`)
gaps = regexp.MustCompile(`\s+`)
)

type figureLine struct {
n int
page, words, what string
}

// checkFigures holds every figure in the prose of a hand-written page to a line of list, every
// line to words its page still says, and every line that names a constant to that constant's
// value in the checkout spin. spin is "" in a run without it, which leaves the constants to the
// run that has it.
func checkFigures(docs, list, spin string) ([]string, error) {
// line to words its page still says, and every line that names a constant or a file's text to
// the checkout that has it. from is the checkouts at hand: a line of a repository that is not
// among them - spin's, in a run without spin - is left to the run that has it.
func checkFigures(docs, list string, from map[string]checkout) ([]string, error) {
spin := from["spin"].root
raw, err := os.ReadFile(list)
if err != nil {
return nil, err
Expand Down Expand Up @@ -89,6 +99,20 @@ func checkFigures(docs, list, spin string) ([]string, error) {
bad = append(bad, fmt.Sprintf("%s:%d: %s does not say %q: take the line out", list, l.n, l.page, l.words))
continue
}
if m := has.FindStringSubmatch(l.what); m != nil {
c, ok := from[m[1]]
if !ok {
continue
}
raw, err := os.ReadFile(filepath.Join(c.root, m[2]))
switch {
case err != nil:
bad = append(bad, fmt.Sprintf("%s:%d: %s says %q, and %s no longer has %s: correct the page and the line", list, l.n, l.page, l.words, m[1], m[2]))
case !strings.Contains(gaps.ReplaceAllString(string(raw), " "), gaps.ReplaceAllString(m[3], " ")):
bad = append(bad, fmt.Sprintf("%s:%d: %s says %q, and %s's %s no longer says %q: correct the page and the line", list, l.n, l.page, l.words, m[1], m[2], m[3]))
}
continue
}
m := held.FindStringSubmatch(l.what)
if m == nil || spin == "" {
continue
Expand Down
25 changes: 13 additions & 12 deletions tools/refgen/figures.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,27 @@
# <page> | <the words on the page> | spin:<file>#<Constant> = <its value>
#
# where a constant of spin's decides the figure - task reference:check reads it and fails when it
# is another value, naming the page - or, in the third place, why nothing holds it. A figure a
# is another value, naming the page; or `<repo>:<file> has "<text>"`, where the text that decides
# it is held to still being in the file; or, in the third place, why nothing holds it. A figure a
# page says that has no line fails, and so does a line whose words its page no longer says. A
# "not held" line is a debt: the figure is true only while somebody remembers it.
admin/configuration.md | seven days | not held: struct field default SessionDurationHours: 168 in DefaultSecurity() of internal/controlplane/settings/security.go, overridden by the session_duration_hours setting
admin/configuration.md | seven days | spin:internal/controlplane/settings/security.go has "SessionDurationHours: 168,"
admin/hosts.mdx | 24 hours | spin:internal/controlplane/server/runnertokenserver/runnertoken.go#registrationTokenExpiry = 24h
admin/hosts.mdx | 30 days | spin:internal/controlplane/server/runnertokenserver/runnertoken.go#maxRegistrationTokenExpiry = 720h
admin/observability.md | fifteen minutes | not held: systemd timer OnUnitActiveSec=15min in internal/installation/install/units/spin-vmbackup.timer
admin/observability.md | 30 days | not held: var DefaultRetention (PlatformLogs: 30) in internal/logstore/logstore.go, overridden by the logs_platform_retention_days setting
admin/observability.md | 7 days | not held: var DefaultRetention (WorkspaceLogs: 7) in internal/logstore/logstore.go, overridden by the logs_workspace_retention_days setting
admin/observability.md | 7 days | not held: var DefaultRetention (Traces: 7) in internal/logstore/logstore.go, overridden by the traces_retention_days setting
admin/observability.md | fifteen minutes | spin:internal/installation/install/units/spin-vmbackup.timer has "OnUnitActiveSec=15min"
admin/observability.md | 30 days | spin:internal/logstore/logstore.go has "PlatformLogs: 30,"
admin/observability.md | 7 days | spin:internal/logstore/logstore.go has "WorkspaceLogs: 7,"
admin/observability.md | 7 days | spin:internal/logstore/logstore.go has "Traces: 7}"
admin/observability.md | 30 days | spin:internal/metricstore/metricstore.go#RetentionDays = 30
admin/observability.md | thirty seconds | not held: poll_frequency = "30s" in the Alloy template internal/installation/boot/files/alloy.alloy.tmpl
admin/observability.md | thirty seconds | spin:internal/installation/boot/files/alloy.alloy.tmpl has "poll_frequency = "30s""
admin/recovery.md | five minutes | spin:internal/pgserver/server.go#ArchiveTimeoutSeconds = 300
admin/recovery.md | five minutes | spin:internal/pgserver/server.go#ArchiveTimeoutSeconds = 300
admin/users.md | seven days | not held: struct field default SessionDurationHours: 168 in DefaultSecurity() of internal/controlplane/settings/security.go, overridden by the session_duration_hours setting
admin/users.md | seven days | spin:internal/controlplane/settings/security.go has "SessionDurationHours: 168,"
admin/users.md | a year | spin:internal/controlplane/server/authserver/apikeys.go#maxAPIKeyLifetime = 8784h
aws/cost.mdx | Three months | not a figure: a heading naming the period the cost table prices
aws/cost.mdx | a month | not a figure: the unit of S3's price per GB a month
aws/cost.mdx | a month | not a figure: the unit of Route 53's price per hosted zone
aws/network.mdx | ten-second | not held: Terraform local internal_record_ttl = 10 in modules/controlplane/dns.tf of spin-terraform-aws
aws/network.mdx | ten-second | spin-terraform-aws:modules/controlplane/dns.tf has "internal_record_ttl = 10"
aws/setup.md | a few minutes | not a figure: an estimate of how long Let's Encrypt issuance takes
aws/setup.md | ten minutes | not a figure: an estimate ("About") of the first bring-up time
aws/setup.md | a few minutes | not a figure: an estimate of how long a first runner takes to come up
Expand All @@ -39,16 +40,16 @@ concepts/workspaces.md | 512 MB | spin:internal/controlplane/server/workspaceser
concepts/workspaces.md | 10 GB | spin:internal/controlplane/server/workspaceserver/workspace.go#DefaultDiskGB = 10
concepts/workspaces.md | three times | spin:internal/lifecycle/budget.go#GenerationAttempts = 3
concepts/workspaces.md | Ten minutes | spin:internal/controlplane/server/workspaceserver/idle.go#WarnMinutes = 10
overview/evaluate.md | 30 GB | not held: flag default -free-gb 30 in hack/lanes/cmd/lanes/ci.go (the CI run's preflight); nothing checks it for the development stack
overview/evaluate.md | 30 GB | spin:hack/lanes/cmd/lanes/ci.go has "fs.Int("free-gb", 30,"
overview/how-it-works.mdx | five minutes | spin:internal/pgserver/server.go#ArchiveTimeoutSeconds = 300
overview/how-it-works.mdx | a minute | spin:internal/controlplane/domain/reconcile/reconcile.go#Every = 1m
overview/how-it-works.mdx | three times | spin:internal/lifecycle/budget.go#GenerationAttempts = 3
overview/how-it-works.mdx | five minutes | spin:internal/controlplane/settings/settings.go#DefaultVolumeRPOSeconds = 300
overview/one-machine.md | 30 GB | not held: flag default -free-gb 30 in hack/lanes/cmd/lanes/ci.go (the CI run's preflight); nothing checks it for the development stack
overview/one-machine.md | 30 GB | spin:hack/lanes/cmd/lanes/ci.go has "fs.Int("free-gb", 30,"
quickstart.md | few minutes | not a figure: an estimate of how long a runner takes to come up
security/data.md | 64 KiB | spin:internal/storage/crypto/layer.go#LayerFrameBytes = 65536
security/data.md | fifteen minutes | spin:internal/controlplane/server/volumeserver/storagecreds.go#StorageCredentialTTL = 15m
security/identity.md | seven days | not held: struct field default SessionDurationHours: 168 in DefaultSecurity() of internal/controlplane/settings/security.go, overridden by the session_duration_hours setting
security/identity.md | seven days | spin:internal/controlplane/settings/security.go has "SessionDurationHours: 168,"
security/identity.md | a year | spin:internal/controlplane/server/authserver/apikeys.go#maxAPIKeyLifetime = 8784h
security/identity.md | fifteen minutes | spin:internal/installation/provider/aws/stsjoin/stsjoin.go#maxExpiry = 15m
security/identity.md | an hour | spin:internal/controlplane/server/runnertokenserver/runnertoken.go#runnerTokenExpiry = 1h
Expand Down
7 changes: 5 additions & 2 deletions tools/refgen/figures_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ func TestCheckFigures(t *testing.T) {
"listed with why nothing holds it": {"About 220 MB.", "# sizes\np.md | 220 MB | not held: the size of Microsoft's server\n", ttl, ""},
"a link's target is not the page's": {"[It stops](<feature:Stopped after half an hour>) and [reads](/a/30-days/).", "", ttl, ""},
"a flag's own value is the CLI's": {"Pass `--expires 30 days`.\n\n```bash\nsleep 5 minutes\n```", "", ttl, ""},
"held by a file's text": {"Lasts seven days.", "p.md | seven days | spin:p/p.go has \"Tries = 3\"\n", ttl, ""},
"the text is gone": {"Lasts seven days.", "p.md | seven days | spin:p/p.go has \"Tries = 4\"\n", ttl, `no longer says "Tries = 4"`},
"the text's file is gone": {"Lasts seven days.", "p.md | seven days | spin:q/q.go has \"Tries = 3\"\n", ttl, "spin no longer has q/q.go"},
"a figure with no line": {"Lasts an hour.", "", ttl, `says "an hour", which nothing holds`},
"the constant moved": {"Lasts fifteen minutes.", "p.md | fifteen minutes | spin:p/p.go#TTL = 15m\n", strings.Replace(ttl, "15", "10", 1), "TTL is now 10m0s, not 15m"},
"the count moved": {"Tried three times.", "p.md | three times | spin:p/p.go#Tries = 3\n", strings.Replace(ttl, "= 3", "= 5", 1), "Tries is now 5, not 3"},
Expand All @@ -42,7 +45,7 @@ func TestCheckFigures(t *testing.T) {
if err := os.WriteFile(list, []byte(c.list), 0o644); err != nil {
t.Fatal(err)
}
bad, err := checkFigures(docs, list, spin)
bad, err := checkFigures(docs, list, map[string]checkout{"spin": {root: spin}})
if err != nil {
t.Fatal(err)
}
Expand All @@ -64,7 +67,7 @@ func TestCheckFiguresWithoutSpin(t *testing.T) {
if err := os.WriteFile(list, []byte("p.md | fifteen minutes | spin:gone.go#TTL = 15m\n"), 0o644); err != nil {
t.Fatal(err)
}
if bad, err := checkFigures(docs, list, ""); err != nil || len(bad) > 0 {
if bad, err := checkFigures(docs, list, nil); err != nil || len(bad) > 0 {
t.Errorf("checkFigures without spin: %v, %v", bad, err)
}
}
2 changes: 1 addition & 1 deletion tools/refgen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ func run() error {
func() ([]string, error) { return checkDomains(*docs, *tf) },
func() ([]string, error) { return checkTofu(*docs, *tf) },
func() ([]string, error) { return checkReads(*docs, from) },
func() ([]string, error) { return checkFigures(*docs, figuresList, *spin) },
func() ([]string, error) { return checkFigures(*docs, figuresList, from) },
} {
b, err := c()
if err != nil {
Expand Down
Loading