Documentation
¶
Overview ¶
Package preflight is the read-only launch check behind `rivolt launch-preflight`: one report an operator reads before the Rivolt Pro flip (the launch runbook: rivolt-infra docs/launch-flip.md). It prints counts, names and status codes only, never a value of a setting, an id or an address, and it switches nothing on: the database part runs in a read-only transaction and the URL part is a GET of public pages.
Index ¶
- Variables
- func EmailURLs() []string
- func FoundingFromDB(pool *sql.DB, demo uuid.UUID) func(ctx context.Context, launch time.Time) (Founding, error)
- func HTTPAlertRules(base string) func(context.Context) ([]AlertRule, error)
- func HTTPFetch(ctx context.Context, url string) (int, error)
- func HTTPPostUnsigned(ctx context.Context, url string) (int, error)
- func ManualSteps() []string
- func URLs(base string) []string
- type AlertRule
- type AlertRuleFindings
- type Founding
- type Input
- type Report
- type RequiredRule
- type StripeFacts
Constants ¶
This section is empty.
Variables ¶
var RequiredAlertRules = []RequiredRule{
{Name: "RivoltBillingOnNoFoundingGrant"},
{Name: "RivoltEntitlementCountsMissing"},
{Name: "RivoltStripeWebhookRejected"},
{Name: "RivoltStripeWebhookUnmapped"},
{Name: "RivoltStripeWebhookUnmappedExpired"},
{Name: "RivoltStripeWebhookLag"},
{Name: "RivoltStripeWebhook5xx", QueryHas: `status=~"5..`},
{Name: "RivoltStripeRefundApplied"},
{Name: "RivoltBillingPaymentFailures"},
{Name: "RivoltBillingNonUS"},
{Name: "RivoltStripeCancelPending"},
{Name: "RivoltStripeCancelStuck"},
{Name: "RivoltDatedNoticeFailed"},
{Name: "RivoltFoundingNoticeLate"},
{Name: "RivoltAppleNotificationsRejected"},
{Name: "RivoltAppleNotificationsUnmapped"},
{Name: "RivoltBillingStartFailing", QueryHas: `5..`},
}
RequiredAlertRules are the billing alerts that must be loaded for a launch (rivolt-infra rivolt-alerts/manifests billing.yaml and accounts.yaml). Names only are ever printed.
Functions ¶
func EmailURLs ¶
func EmailURLs() []string
EmailURLs are the pages the emails and the launch notice link to, exactly as they state them (rivolt.dev), fragments dropped.
func FoundingFromDB ¶
func FoundingFromDB(pool *sql.DB, demo uuid.UUID) func(ctx context.Context, launch time.Time) (Founding, error)
FoundingFromDB reads the founding dry run's counts in a read-only transaction: nothing can be written through it.
func HTTPAlertRules ¶ added in v0.40.23
HTTPAlertRules reads the loaded alerting rules from a Prometheus server (GET /api/v1/rules?type=alert; read-only). The error never carries the address or the body.
func HTTPFetch ¶
HTTPFetch GETs url with a short timeout and reports the status after redirects; the body is not read.
func HTTPPostUnsigned ¶
HTTPPostUnsigned POSTs an empty body to url without following redirects and reports the status: what Stripe would get for an event with no signature.
func ManualSteps ¶
func ManualSteps() []string
ManualSteps are the launch prerequisites that live in the Stripe Dashboard, Cloudflare and the Valkey pod, where this command has no view.
Types ¶
type AlertRule ¶ added in v0.40.23
AlertRule is one alerting rule Prometheus has loaded: its name, its expression and whether the last evaluation worked.
type AlertRuleFindings ¶ added in v0.40.23
type AlertRuleFindings struct {
Found []string // loaded, with the expected expression, evaluating
Missing []string // not loaded at all
Stale []string // loaded, but the expression is not the fixed one
Failing []string // loaded, but the last evaluation failed
}
AlertRuleFindings is the outcome of comparing the loaded rules with RequiredAlertRules; names only.
func CheckAlertRules ¶ added in v0.40.23
func CheckAlertRules(loaded []AlertRule, required []RequiredRule) AlertRuleFindings
CheckAlertRules compares the loaded rules with the required ones.
type Founding ¶
type Founding struct {
Accounts int // every account
Demo int // 1 when the demo account exists
Eligible int // accounts created at or before launch, the demo excluded
Already int // of those, with a founding row
ToGrant int
After int // accounts created after the launch instant (not granted)
}
Founding is what the founding grant would do at the launch instant, counts only.
type Input ¶
type Input struct {
Getenv func(string) string
// Founding reads the counts; nil: the database part is skipped and the report says so.
Founding func(ctx context.Context, launch time.Time) (Founding, error)
// Fetch returns the status of a GET of url; nil skips the URL checks.
Fetch func(ctx context.Context, url string) (int, error)
// Webhook returns the status of an UNSIGNED, empty POST to url (Stripe's webhook endpoint); nil skips it.
Webhook func(ctx context.Context, url string) (int, error)
// RedisTime runs TIME as the app's Redis user, which is what the shared rate-limit script needs; nil skips it. It reports a denial
// (the ACL) apart from the other failures.
RedisTime func(ctx context.Context) (denied bool, err error)
// AlertRules lists the alerting rules Prometheus has loaded; nil skips the check. An error is a problem: the rules are unverified.
AlertRules func(ctx context.Context) ([]AlertRule, error)
// RequiredAlertRules overrides RequiredAlertRules (tests).
RequiredAlertRules []RequiredRule
// Stripe reads the Stripe API with the configured key; nil skips it.
Stripe func(ctx context.Context) StripeFacts
// BillingAddress is what our Checkout sessions ask for as the billing address (stripebill.BillingAddressCollection): "required" lets the
// webhook check the country (Rivolt Pro is sold in the US only).
BillingAddress string
Launch time.Time
}
Input is everything the report reads, so a test drives it without a database, a network or the process environment.
type Report ¶
type Report struct {
Lines []string
// Problems are what stops the flip; Warnings are worth a look but do not.
Problems []string
Warnings []string
}
Report is the result: lines to print and whether the deployment is ready for the flip.
type RequiredRule ¶ added in v0.40.23
RequiredRule is a billing alert the flip needs live. QueryHas, when set, must appear in the loaded expression: the same name with an older expression is not the fixed rule. (The Stripe webhook 5xx alert existed for a while matching status="5xx" against series whose status label is the numeric code, so it could never fire: the name was there, the rule was dead.)
type StripeFacts ¶
type StripeFacts struct {
Err error
Live bool // the key and the prices are in live mode
PricesActive bool // both prices exist and are active
PortalFound bool
TermsSet bool // the Customer Portal's Terms of service URL
PrivacySet bool // and its Privacy policy URL
PaymentMethodUpdate bool // customers can update their payment method in the portal
// The payment method configuration our Checkout sessions use (RIVOLT_STRIPE_PAYMENT_METHOD_CONFIG): read at all, found and active, and the
// payment method types it has on (sorted).
PMCRead bool
PMCFound bool
PMCActive bool
PMCLive bool // the configuration's livemode, to compare with the mode of the key (Live)
PMCMethods []string
// The account's DEFAULT configuration, which our sessions do not use but the Customer Portal's update-payment-method follows.
CheckoutMethods []string
CheckoutRead bool
// The Stripe API version the server pins on every call (stripebill.APIVersion) and the versions of the account's ENABLED webhook endpoints,
// whose payloads the webhook structs read. A mismatch, no enabled endpoint, or an unreadable list is a problem.
PinnedVersion string
WebhookRead bool
WebhookVersions []string
TaxRead bool // Stripe Tax's settings were read (only asked when automatic tax is on)
TaxActive bool // and Stripe Tax is active in this mode
}
StripeFacts is what the Stripe API says, booleans and a mode only. Err is set when the key could not read it (sanitised, no key).