Commit f782f13
committed
feat(theme): mirror theme-scoped translations on blue/green deploy
Translations registered via Translate & Adapt (and any caller of the
Translations API) for resources of type ONLINE_STORE_THEME_* are keyed
to a specific theme GID. Blue and Green are distinct permanent themes,
so translations written against the currently-live color do not follow
when the on-deck color is promoted. The previously-live color's
translations are silently stranded, and the storefront reverts to
source-language strings on the next deploy.
This PR adds:
- `shopkeeper theme translations mirror` — a standalone command that
copies theme-scoped translations from one theme to another.
* `--from / --to` explicit override (recovery scenarios where
the authoritative-translations theme is no
longer [live])
* `--blue / --green` derive source = live, target = on-deck via
the same getLiveTheme + getOnDeckThemeId
helpers `theme deploy` uses
* `--locale` restrict to a single locale (default: every
non-primary published locale)
* `--resource-type` restrict to a single theme-scoped resource
type (useful for targeted ops + testing)
* `--dry-run` build the write plan, do not register
- Optional auto-step inside `blueGreenDeploy()`, gated on the new
`--mirror-translations` flag (env: SKR_FLAG_MIRROR_TRANSLATIONS).
Default-off because most client stores don't use Translate & Adapt
and paying the pre-flight cost on every deploy isn't justified for
them. Stores that need it (e.g. Hiya) opt in via env.
Performance:
- Pre-flight short-circuit: before doing the full inventory, compare
aggregate translation maps for ONLINE_STORE_THEME,
ONLINE_STORE_THEME_LOCALE_CONTENT, and
ONLINE_STORE_THEME_SETTINGS_DATA_SECTIONS between source and target.
If all match per-locale, skip the mirror entirely (~6 queries vs
the full ~250).
- Source-is-live fast path: when source = live, the type-scoped list
query returns content + translations directly, so we avoid a
per-resource source-fetch round-trip (~50% fewer reads).
- Bounded-concurrency parallelism on per-resource target fetches
(concurrency 8, hand-rolled in src/utilities/concurrency.ts).
Together these bring a typical mirror on Hiya's catalog (~124 theme-
scoped resources) from ~5 minutes to well under a minute.
Auth:
- Requires a Shopify Theme Access password (--password or
SHOPIFY_CLI_THEME_TOKEN). The token's Theme Access app must include
read_translations + write_translations scopes; ensureAuthenticatedThemes
uses the password directly without falling back to OAuth.
Resource scope:
ONLINE_STORE_THEME
ONLINE_STORE_THEME_APP_EMBED
ONLINE_STORE_THEME_JSON_TEMPLATE
ONLINE_STORE_THEME_LOCALE_CONTENT
ONLINE_STORE_THEME_SECTION_GROUP
ONLINE_STORE_THEME_SETTINGS_CATEGORY
ONLINE_STORE_THEME_SETTINGS_DATA_SECTIONS
Resource-scoped translations (PRODUCT, COLLECTION, METAOBJECT, PAGE,
etc.) are not theme-keyed and survive blue/green without
intervention, so they are intentionally excluded.
Idempotent + safe:
- Skips writes when the target value already matches the source.
- Skips keys whose source content has been removed on the target, or
whose digest no longer matches between deploys.
- Refuses to mirror a theme onto itself.
- Anchoring on explicit `--from` / `--to` is intentional: in recovery
scenarios the most-up-to-date translations may live on a no-longer-
live theme. Deriving direction from [live] would invert the mirror
and overwrite the freshly-edited theme with stale data.
Tests: 164 passing. New coverage in services/theme/translations.test.ts
covers resolveThemes flag matrix, password requirement, sourceIsLive
detection, digest-match registration, idempotent skip, dry-run,
target-resource-absent, locale/resource-type filters, and the
pre-flight skip + full-mirror-on-mismatch behavior. Deploy tests
updated to assert default-off and explicit opt-in.1 parent a1c53f5 commit f782f13
10 files changed
Lines changed: 1728 additions & 375 deletions
File tree
- docs/commands
- src
- commands/theme
- translations
- services/theme
- utilities
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
47 | 53 | | |
48 | 54 | | |
49 | 55 | | |
| |||
60 | 66 | | |
61 | 67 | | |
62 | 68 | | |
| 69 | + | |
63 | 70 | | |
64 | 71 | | |
65 | 72 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
21 | 22 | | |
22 | 23 | | |
23 | 24 | | |
| |||
27 | 28 | | |
28 | 29 | | |
29 | 30 | | |
| 31 | + | |
30 | 32 | | |
31 | 33 | | |
32 | | - | |
| 34 | + | |
33 | 35 | | |
34 | 36 | | |
35 | 37 | | |
36 | | - | |
| 38 | + | |
37 | 39 | | |
38 | 40 | | |
39 | 41 | | |
| |||
42 | 44 | | |
43 | 45 | | |
44 | 46 | | |
45 | | - | |
| 47 | + | |
46 | 48 | | |
47 | 49 | | |
48 | 50 | | |
| |||
74 | 76 | | |
75 | 77 | | |
76 | 78 | | |
77 | | - | |
78 | 79 | | |
79 | 80 | | |
| 81 | + | |
80 | 82 | | |
81 | 83 | | |
82 | 84 | | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
83 | 163 | | |
84 | 164 | | |
85 | 165 | | |
| |||
144 | 224 | | |
145 | 225 | | |
146 | 226 | | |
| 227 | + | |
147 | 228 | | |
148 | 229 | | |
149 | 230 | | |
150 | 231 | | |
151 | 232 | | |
152 | 233 | | |
153 | | - | |
| 234 | + | |
154 | 235 | | |
| 236 | + | |
155 | 237 | | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
156 | 244 | | |
157 | 245 | | |
158 | 246 | | |
| |||
220 | 308 | | |
221 | 309 | | |
222 | 310 | | |
223 | | - | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
224 | 314 | | |
225 | 315 | | |
226 | 316 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
| 8 | + | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
| |||
48 | 49 | | |
49 | 50 | | |
50 | 51 | | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
51 | 67 | | |
52 | 68 | | |
53 | 69 | | |
| |||
72 | 88 | | |
73 | 89 | | |
74 | 90 | | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
75 | 109 | | |
76 | 110 | | |
77 | 111 | | |
| |||
0 commit comments