ReviewOS

also looking at this

stacks/stx

fix(images): name delivery variants independently of the output path

#1961
Merged chris wants to merge fix/stable-image-delivery-names into main
2 files +102 -2
packages/stx/test/builtins/image-delivery.test.tsmodified+43-1
Changes to packages/stx/test/builtins/image-delivery.test.ts
@@ -1,5 +1,5 @@
11import { afterAll, beforeAll, describe, expect, it } from 'bun:test'
2import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises'
2import { mkdir, mkdtemp, readdir, rm, stat, writeFile } from 'node:fs/promises'
33import { tmpdir } from 'node:os'
44import { join } from 'node:path'
55import { encode } from 'ts-images'
@@ -103,4 +103,46 @@ describe('build-time Image delivery', () => {
103103 expect(html).toContain(':src="avatarUrl"')
104104 expect(html).not.toContain('<picture')
105105 })
106
107 it('names variants the same from any output directory, so releases reuse the cache', async () => {
108 // An atomic-release deploy runs the exact same build from a new absolute
109 // path each time. If the output directory leaks into the variant names,
110 // every release re-encodes the whole public directory and the previous
111 // release's output is dead weight on disk.
112 const releaseOne = join(tempDir, 'releases', 'aaaaaaa', 'delivery')
113 const releaseTwo = join(tempDir, 'releases', 'bbbbbbb', 'delivery')
114
115 clearImageDeliveryCatalog()
116 const first = await prepareImageDelivery(publicDir, releaseOne)
117 const firstNames = (await readdir(join(releaseOne, '_stx', 'images'))).sort()
118
119 clearImageDeliveryCatalog()
120 const second = await prepareImageDelivery(publicDir, releaseTwo)
121 const secondNames = (await readdir(join(releaseTwo, '_stx', 'images'))).sort()
122
123 expect(firstNames.length).toBeGreaterThan(0)
124 expect(secondNames).toEqual(firstNames)
125 expect(second.fingerprint).toBe(first.fingerprint)
126 })
127
128 it('reuses variants already on disk instead of re-encoding them', async () => {
129 const outDir = join(tempDir, 'releases', 'ccccccc', 'delivery')
130
131 clearImageDeliveryCatalog()
132 await prepareImageDelivery(publicDir, outDir)
133 const written = join(outDir, '_stx', 'images')
134 const before = await Promise.all(
135 (await readdir(written)).sort().map(async name => [name, (await stat(join(written, name))).mtimeMs] as const),
136 )
137
138 clearImageDeliveryCatalog()
139 await prepareImageDelivery(publicDir, outDir)
140 const after = await Promise.all(
141 (await readdir(written)).sort().map(async name => [name, (await stat(join(written, name))).mtimeMs] as const),
142 )
143
144 // Same names and untouched mtimes: the second pass found every variant and
145 // wrote nothing. A miss would rewrite the file and move the mtime.
146 expect(after).toEqual(before)
147 })
106148})