Money in billing's messages reads to the cent, and the deploy reads migrations again after a failure
- Balances and amounts owed say $3.99, not $3.987 (cents(); dollars() keeps its finer digits for prices under a cent). - deploy.mjs lists pending migrations once more when the first try fails: Cloudflare answered 403 while Wrangler's login refreshed, and the packages deploy stopped with nothing deployed.
3 files+23−60/3 viewed
| 161 | 161 | ||
| 162 | 162 | /** Pending migrations of a unit's database: { pending } or { error }. */ | |
| 163 | 163 | export async function pendingMigrations(unit) { | |
| 164 | − | const found = await wrangler(["d1", "migrations", "list", unit.d1.database, "--remote"], { cwd: join(ROOT, unit.path) }); | |
| 164 | + | const list = () => wrangler(["d1", "migrations", "list", unit.d1.database, "--remote"], { cwd: join(ROOT, unit.path) }); | |
| 165 | + | // Once more after a failure: Cloudflare's API sometimes answers 403 | |
| 166 | + | // while Wrangler's login refreshes (seen on 2026-10-06). | |
| 167 | + | let found = await list(); | |
| 168 | + | if (found.code !== 0) found = await list(); | |
| 165 | 169 | if (found.code !== 0) return { error: lastLines(found.out) }; | |
| 166 | 170 | return { pending: pendingFrom(found.out) }; | |
| 167 | 171 | } |
| 27 | 27 | ||
| 28 | 28 | use crate::Billing; | |
| 29 | 29 | use crate::accounts::own_account; | |
| 30 | − | use crate::features::dollars; | |
| 30 | + | use crate::features::cents; | |
| 31 | 31 | ||
| 32 | 32 | /// `repo.transferred` (see `g1t_kit::transfer`): `?1` the repository's | |
| 33 | 33 | /// path now, `?2` a path it had. Ledger rows, runs and holds keep the path | |
| 79 | 79 | if facts.balance_micros > 0 { | |
| 80 | 80 | return Err(format!( | |
| 81 | 81 | "{ws} has {} of prepaid credit left, which would be lost. Spend it, or write to support@g1t.sh about a refund, first.", | |
| 82 | − | dollars(facts.balance_micros) | |
| 82 | + | cents(facts.balance_micros) | |
| 83 | 83 | )); | |
| 84 | 84 | } | |
| 85 | 85 | if facts.metering_micros > 0 { | |
| 86 | 86 | return Err(format!( | |
| 87 | 87 | "{ws} has {} of usage this month (storage and git operations) that is charged when the month closes. You can delete it from {}.", | |
| 88 | − | dollars(facts.metering_micros), | |
| 88 | + | cents(facts.metering_micros), | |
| 89 | 89 | facts.next_month | |
| 90 | 90 | )); | |
| 91 | 91 | } | |
| 94 | 94 | if !facts.has_card { | |
| 95 | 95 | return Err(format!( | |
| 96 | 96 | "{ws} owes {}. Add a card or pay it from the workspace's Billing page first.", | |
| 97 | − | dollars(owed) | |
| 97 | + | cents(owed) | |
| 98 | 98 | )); | |
| 99 | 99 | } | |
| 100 | 100 | return Ok(Settle::Charge(owed)); | |
| 176 | 176 | FailureCode::PaymentRequired, | |
| 177 | 177 | format!( | |
| 178 | 178 | "The card on file was declined for the {} {workspace} owes. Pay it from the workspace's Billing page first.", | |
| 179 | − | dollars(owed) | |
| 179 | + | cents(owed) | |
| 180 | 180 | ), | |
| 181 | 181 | )); | |
| 182 | 182 | } |
| 105 | 105 | format!("${whole}.{fraction:0<2}") | |
| 106 | 106 | } | |
| 107 | 107 | ||
| 108 | + | /// An amount of money to the cent, as balances and amounts owed read: | |
| 109 | + | /// `$3.99`, never `$3.987`. Prices use [`dollars`]. | |
| 110 | + | pub(crate) fn cents(micros: i64) -> String { | |
| 111 | + | format!("${:.2}", micros as f64 / MICROS_PER_DOLLAR as f64) | |
| 112 | + | } | |
| 113 | + | ||
| 108 | 114 | /// `units` at `each` micros a unit, as the pricing page writes it: a | |
| 109 | 115 | /// build second's price times 60 is the build minute both quote. | |
| 110 | 116 | pub(crate) fn per_units(each: f64, units: f64) -> String { | |
| 685 | 691 | } | |
| 686 | 692 | ||
| 687 | 693 | #[test] | |
| 694 | + | fn amounts_of_money_read_to_the_cent() { | |
| 695 | + | assert_eq!(cents(3_986_990), "$3.99"); | |
| 696 | + | assert_eq!(cents(5_000_000), "$5.00"); | |
| 697 | + | assert_eq!(cents(4_000), "$0.00"); | |
| 698 | + | } | |
| 699 | + | ||
| 700 | + | #[test] | |
| 688 | 701 | fn prices_under_a_cent_keep_their_digits() { | |
| 689 | 702 | assert_eq!(dollars(1512), "$0.0015"); | |
| 690 | 703 | assert_eq!(dollars(24_000), "$0.024"); |