Skip to content

web-deploy Focus-Page Icon Deploy Efficiency + Astro Patch Bump

Section titled “web-deploy Focus-Page Icon Deploy Efficiency + Astro Patch Bump”

Talbot noticed every focus-page deploy seemed to “regenerate” a series of icons and asked for an efficiency audit. The real cause wasn’t regeneration — Astro just copies static files from public/ to dist/, which is near-instant. The waste was in the FTP deploy step: deploy_sdc_focus.py / deploy_mbr_focus.py spawned a brand-new subprocess + fresh FTP connect/login for every one of the 13 favicon/PWA icon files, on every single deploy, regardless of whether content had changed. Visible in deployment.log as the same 13 files re-”deployed” every run — that’s what read as regeneration.

Fix: added focus-deploy/icon_manifest.py (sha256-based skip logic) and refactored both deploy scripts to open one FTP connection per run instead of one per file, importing ftp_deploy.py’s functions directly rather than shelling out to a subprocess per icon. A manifest hit still triggers a cheap FTP SIZE check (control-channel only, no data transfer) before skipping — so a manually deleted/corrupted remote icon is still caught and re-uploaded, preserving the single-source-of-truth guarantee without paying for a full re-upload every time. focus.html still deploys unconditionally every run (its content is expected to change).

Also investigated the “upgrade dependencies like Vite” part of the ask: no direct vite dependency exists anywhere in the monorepo (it’s bundled transitively via astro). Found astro pinned to 7.0.6 with 7.0.7 available — a pure patch (verified via upstream changelog: fixes a lightningcss CSS-module hash bug, unused here) — and bumped it across all four sites (template, sdc, mbr, ts). Other outdated deps (tailwindcss 3→4, typescript 5→7, eslint 9→10, wrangler 3→4) are all major-version bumps with likely breaking changes — left alone as out of scope for a low-risk ops task.

Tested end-to-end against production (both SDC and MBR): cold run uploads all 13 icons + builds the manifest; immediate re-run uploads 0/13 (all skipped), only focus.html deploys; a single modified favicon triggers exactly 1/13 re-uploads; restoring the original content correctly re-triggers a re-upload back to the byte-identical original. Re-ran again after the astro bump to confirm the skip logic still works on 7.0.7. Both live pages verified 200 throughout.

Efficiency win: a typical deploy with unchanged icons now opens 1 FTP connection instead of 14, and transfers 1 file instead of 14.

While cleaning up for commit, also caught and fixed: focus-deploy/deployment.log was a tracked, ever-growing log file dirtying the repo on every deploy — untracked it (git rm --cached) and added it to .gitignore (kept locally). Also picked up an unrelated, previously-uncommitted focus-deploy/README.md rewrite that had been sitting in the working tree since the sdc-mission-deployfocus-deploy rename (4315574) — the committed version was still describing the old, pre-rename folder.

web-deploy repo (commit fdf12ce):

  • focus-deploy/icon_manifest.py (new) — hash-based upload-skip + drift-check logic
  • focus-deploy/deploy_sdc_focus.py, focus-deploy/deploy_mbr_focus.py — single FTP connection per run, direct function imports instead of subprocess-per-file
  • focus-deploy/.gitignore — excludes .icon-manifest-*.json (local cache) and deployment.log (now untracked)
  • focus-deploy/README.md — rewritten to describe the current focus-deploy setup + document icon-skip behavior
  • CHANGELOG.md (0.4.1), pyproject.toml (version bump, closing a pre-existing 0.3.3 → 0.4.0 drift between the two files)

monorepo repo (commit 147382b):

  • sites/{template,sdc,mbr,ts}/package.json, pnpm-lock.yaml — astro 7.0.67.0.7
  • sites/mbr/src/data/rates.generated.json — refreshed automatically by mbr’s own prebuild hook (sync-rates.mjs) during test builds; routinely-committed live data, not hand-edited
  • CHANGELOG.md

Left out of both commits (pre-existing, unrelated, present before this session started): config.yaml and submodule pointers kb-business/kb-mbr in web-deploy; untracked .vscode/ in monorepo.

  • A per-file subprocess + fresh FTP connect/login is a silent, compounding cost that looks like “regeneration” from the outside. If a deploy script’s per-file loop shells out to a helper script instead of reusing one connection, every additional static asset (icons, manifests, cache-config files) multiplies connection overhead linearly — profile the actual bottleneck (connections/transfers) before assuming a build step is slow.
  • A hash-manifest skip should not blindly trust its own cache. A lightweight remote check (FTP SIZE, here — cheap because it’s control-channel only) before skipping preserves “what’s live matches what we think is live” even if the manifest itself never lies about local state — protects against out-of-band remote drift (manual deletion, corruption, another process touching the same path).
  • Check git status for pre-existing dirty/uncommitted state before scoping a task’s commit. This repo had 3 unrelated pre-existing uncommitted changes (config.yaml, kb-business, kb-mbr submodule pointers) sitting from before the task started, plus one relevant orphaned change (README.md rewrite from a prior rename that was never committed) mixed into the same file being edited. Stage by explicit filename, not git add -A/git add ., so task-scoped commits don’t silently sweep in unrelated work — but do fold in genuinely-related orphaned changes rather than re-doing them.
  • pyproject.toml version and CHANGELOG.md’s latest entry can drift (found at 0.3.3 vs. 0.4.0 here) if a past session added a changelog entry without bumping the version file, or vice versa. Worth a quick diff-check before adding a new version bump.