Skip to content

Commit 978fbed

Browse files
authored
Improve cache hit consistency across environments (#1010)
1 parent 6743ef9 commit 978fbed

31 files changed

+222
-125
lines changed

.changeset/sixty-mails-cheat.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@e2b/python-sdk': patch
3+
'e2b': patch
4+
---
5+
6+
improve cache hit consistency

packages/js-sdk/src/template/utils.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ export async function getAllFilesForFilesHash(
7171

7272
/**
7373
* Calculate a hash of files being copied to detect changes for cache invalidation.
74-
* The hash includes file content, metadata (mode, uid, gid, size, mtime), and relative paths.
74+
* The hash includes file content, metadata (mode, size), and relative paths.
75+
* Note: uid, gid, and mtime are excluded to ensure stable hashes across environments.
7576
*
7677
* @param src Source path pattern for files to copy
7778
* @param dest Destination path where files will be copied
@@ -106,13 +107,11 @@ export async function calculateFilesHash(
106107
throw error
107108
}
108109

109-
// Hash stats
110+
// Hash stats - only include stable metadata (mode, size)
111+
// Exclude uid, gid, and mtime to ensure consistent hashes across environments
110112
const hashStats = (stats: fs.Stats) => {
111113
hash.update(stats.mode.toString())
112-
hash.update(stats.uid.toString())
113-
hash.update(stats.gid.toString())
114114
hash.update(stats.size.toString())
115-
hash.update(stats.mtimeMs.toString())
116115
}
117116

118117
// Process files recursively

packages/js-sdk/tests/setup.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,21 @@ interface SandboxFixture {
1212
interface BuildTemplateFixture {
1313
buildTemplate: (
1414
template: TemplateClass,
15-
skipCache?: boolean,
15+
options?: { skipCache?: boolean },
1616
onBuildLogs?: (logEntry: LogEntry) => void
1717
) => Promise<void>
1818
}
1919

2020
function buildTemplate(
2121
template: TemplateClass,
22-
skipCache?: boolean,
22+
options?: { skipCache?: boolean },
2323
onBuildLogs?: (logEntry: LogEntry) => void
2424
) {
2525
return Template.build(template, {
2626
alias: `e2b-test-${randomUUID()}`,
2727
cpuCount: 1,
2828
memoryMB: 1024,
29-
skipCache: skipCache,
29+
skipCache: options?.skipCache,
3030
onBuildLogs: onBuildLogs,
3131
})
3232
}

packages/js-sdk/tests/template/build.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,13 @@ buildTemplateTest('build template', async ({ buildTemplate }) => {
3535
.setWorkdir('/app')
3636
.setStartCmd('echo "Hello, world!"', waitForTimeout(10_000))
3737

38-
await buildTemplate(template, undefined, defaultBuildLogger())
38+
await buildTemplate(template, { skipCache: true }, defaultBuildLogger())
3939
})
4040

4141
buildTemplateTest('build template with symlinks', async ({ buildTemplate }) => {
4242
const template = Template()
4343
.fromImage('ubuntu:22.04')
44+
.skipCache()
4445
.copy('folder/*', 'folder', { forceUpload: true })
4546
.runCmd('cat folder/symlink.txt')
4647

@@ -52,6 +53,7 @@ buildTemplateTest(
5253
async ({ buildTemplate }) => {
5354
const template = Template()
5455
.fromImage('ubuntu:22.04')
56+
.skipCache()
5557
.copy('folder/symlink.txt', 'folder/symlink.txt', {
5658
forceUpload: true,
5759
resolveSymlinks: true,

packages/js-sdk/tests/template/methods/aptInstall.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import { Template } from '../../../src'
22
import { buildTemplateTest } from '../../setup'
33

44
buildTemplateTest('apt install', async ({ buildTemplate }) => {
5-
const template = Template().fromImage('ubuntu:24.04').aptInstall(['vim'])
5+
const template = Template()
6+
.fromImage('ubuntu:24.04')
7+
.skipCache()
8+
.aptInstall(['vim'])
69

710
await buildTemplate(template)
811
})
@@ -12,6 +15,7 @@ buildTemplateTest(
1215
async ({ buildTemplate }) => {
1316
const template = Template()
1417
.fromImage('ubuntu:24.04')
18+
.skipCache()
1519
.aptInstall(['vim'], { noInstallRecommends: true })
1620

1721
await buildTemplate(template)

packages/js-sdk/tests/template/methods/bunInstall.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { buildTemplateTest } from '../../setup'
44
buildTemplateTest('bun install', async ({ buildTemplate }) => {
55
const template = Template()
66
.fromBunImage('1.3')
7+
.skipCache()
78
.bunInstall(['lodash', 'axios'])
89

910
await buildTemplate(template)
@@ -12,6 +13,7 @@ buildTemplateTest('bun install', async ({ buildTemplate }) => {
1213
buildTemplateTest('bun install global', async ({ buildTemplate }) => {
1314
const template = Template()
1415
.fromBunImage('1.3')
16+
.skipCache()
1517
.bunInstall(['tsx'], { g: true })
1618

1719
await buildTemplate(template)
@@ -20,6 +22,7 @@ buildTemplateTest('bun install global', async ({ buildTemplate }) => {
2022
buildTemplateTest('bun install dev', async ({ buildTemplate }) => {
2123
const template = Template()
2224
.fromBunImage('1.3')
25+
.skipCache()
2326
.bunInstall(['typescript'], { dev: true })
2427

2528
await buildTemplate(template)

packages/js-sdk/tests/template/methods/fromMethods.test.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,67 +21,67 @@ afterAll(async () => {
2121

2222
buildTemplateTest('fromBaseImage', async ({ buildTemplate }) => {
2323
const template = Template().fromBaseImage()
24-
await buildTemplate(template)
24+
await buildTemplate(template, { skipCache: true })
2525
})
2626

2727
buildTemplateTest('fromDebianImage', async ({ buildTemplate }) => {
2828
const template = Template().fromDebianImage()
29-
await buildTemplate(template)
29+
await buildTemplate(template, { skipCache: true })
3030
})
3131

3232
buildTemplateTest('fromDebianImage with variant', async ({ buildTemplate }) => {
3333
const template = Template().fromDebianImage('bookworm')
34-
await buildTemplate(template)
34+
await buildTemplate(template, { skipCache: true })
3535
})
3636

3737
buildTemplateTest('fromUbuntuImage', async ({ buildTemplate }) => {
3838
const template = Template().fromUbuntuImage()
39-
await buildTemplate(template)
39+
await buildTemplate(template, { skipCache: true })
4040
})
4141

4242
buildTemplateTest('fromUbuntuImage with variant', async ({ buildTemplate }) => {
4343
const template = Template().fromUbuntuImage('24.04')
44-
await buildTemplate(template)
44+
await buildTemplate(template, { skipCache: true })
4545
})
4646

4747
buildTemplateTest('fromPythonImage', async ({ buildTemplate }) => {
4848
const template = Template().fromPythonImage()
49-
await buildTemplate(template)
49+
await buildTemplate(template, { skipCache: true })
5050
})
5151

5252
buildTemplateTest('fromPythonImage with variant', async ({ buildTemplate }) => {
5353
const template = Template().fromPythonImage('3.12')
54-
await buildTemplate(template)
54+
await buildTemplate(template, { skipCache: true })
5555
})
5656

5757
buildTemplateTest('fromNodeImage', async ({ buildTemplate }) => {
5858
const template = Template().fromNodeImage()
59-
await buildTemplate(template)
59+
await buildTemplate(template, { skipCache: true })
6060
})
6161

6262
buildTemplateTest('fromNodeImage with variant', async ({ buildTemplate }) => {
6363
const template = Template().fromNodeImage('24')
64-
await buildTemplate(template)
64+
await buildTemplate(template, { skipCache: true })
6565
})
6666

6767
buildTemplateTest('fromBunImage', async ({ buildTemplate }) => {
6868
const template = Template().fromBunImage()
69-
await buildTemplate(template)
69+
await buildTemplate(template, { skipCache: true })
7070
})
7171

7272
buildTemplateTest('fromBunImage with variant', async ({ buildTemplate }) => {
7373
const template = Template().fromBunImage('1.3')
74-
await buildTemplate(template)
74+
await buildTemplate(template, { skipCache: true })
7575
})
7676

7777
buildTemplateTest('fromImage', async ({ buildTemplate }) => {
7878
const template = Template().fromImage('ubuntu:22.04')
79-
await buildTemplate(template)
79+
await buildTemplate(template, { skipCache: true })
8080
})
8181

8282
buildTemplateTest('fromTemplate', async ({ buildTemplate }) => {
8383
const template = Template().fromTemplate('base')
84-
await buildTemplate(template)
84+
await buildTemplate(template, { skipCache: true })
8585
})
8686

8787
buildTemplateTest('fromDockerfile', async ({ buildTemplate }) => {
@@ -91,5 +91,5 @@ COPY package.json .
9191
RUN npm install`
9292

9393
const template = Template({ fileContextPath }).fromDockerfile(dockerfile)
94-
await buildTemplate(template)
94+
await buildTemplate(template, { skipCache: true })
9595
})

packages/js-sdk/tests/template/methods/makeSymlink.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { buildTemplateTest } from '../../setup'
44
buildTemplateTest('make symlink', async ({ buildTemplate }) => {
55
const template = Template()
66
.fromImage('ubuntu:22.04')
7+
.skipCache()
78
.makeSymlink('.bashrc', '.bashrc.local')
89
.runCmd('test "$(readlink .bashrc.local)" = ".bashrc"')
910

@@ -13,6 +14,7 @@ buildTemplateTest('make symlink', async ({ buildTemplate }) => {
1314
buildTemplateTest('make symlink (force)', async ({ buildTemplate }) => {
1415
const template = Template()
1516
.fromImage('ubuntu:22.04')
17+
.skipCache()
1618
.makeSymlink('.bashrc', '.bashrc.local')
1719
.makeSymlink('.bashrc', '.bashrc.local', { force: true }) // Overwrite existing symlink
1820
.runCmd('test "$(readlink .bashrc.local)" = ".bashrc"')

packages/js-sdk/tests/template/methods/npmInstall.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { buildTemplateTest } from '../../setup'
44
buildTemplateTest('npm install', async ({ buildTemplate }) => {
55
const template = Template()
66
.fromNodeImage('24')
7+
.skipCache()
78
.npmInstall(['lodash', 'axios'])
89

910
await buildTemplate(template)
@@ -12,6 +13,7 @@ buildTemplateTest('npm install', async ({ buildTemplate }) => {
1213
buildTemplateTest('npm install global', async ({ buildTemplate }) => {
1314
const template = Template()
1415
.fromNodeImage('24')
16+
.skipCache()
1517
.npmInstall(['tsx'], { g: true })
1618

1719
await buildTemplate(template)
@@ -20,6 +22,7 @@ buildTemplateTest('npm install global', async ({ buildTemplate }) => {
2022
buildTemplateTest('npm install dev', async ({ buildTemplate }) => {
2123
const template = Template()
2224
.fromNodeImage('24')
25+
.skipCache()
2326
.npmInstall(['typescript'], { dev: true })
2427

2528
await buildTemplate(template)

packages/js-sdk/tests/template/methods/pipInstall.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { buildTemplateTest } from '../../setup'
44
buildTemplateTest('pip install', async ({ buildTemplate }) => {
55
const template = Template()
66
.fromPythonImage('3.13.7-trixie')
7+
.skipCache()
78
.pipInstall(['six', 'pyyaml'])
89

910
await buildTemplate(template)
@@ -12,6 +13,7 @@ buildTemplateTest('pip install', async ({ buildTemplate }) => {
1213
buildTemplateTest('pip install (user)', async ({ buildTemplate }) => {
1314
const template = Template()
1415
.fromPythonImage('3.13.7-trixie')
16+
.skipCache()
1517
.pipInstall(['six', 'pyyaml'], { g: false })
1618

1719
await buildTemplate(template)

0 commit comments

Comments
 (0)