also looking at this
fix(images): name delivery variants independently of the output path
#1961
2 files
+102
-2
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | import { afterAll, beforeAll, describe, expect, it } from 'bun:test' |
| 2 | import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' | |
| 2 | import { mkdir, mkdtemp, readdir, rm, stat, writeFile } from 'node:fs/promises' | |
| 3 | 3 | import { tmpdir } from 'node:os' |
| 4 | 4 | import { join } from 'node:path' |
| 5 | 5 | import { encode } from 'ts-images' |
| @@ -103,4 +103,46 @@ describe('build-time Image delivery', () => { | ||
| 103 | 103 | expect(html).toContain(':src="avatarUrl"') |
| 104 | 104 | expect(html).not.toContain('<picture') |
| 105 | 105 | }) |
| 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 | }) | |
| 106 | 148 | }) |