Skip to content

feat: generate edge function tarballs #6568

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 41 commits into from
Jul 30, 2025
Merged

feat: generate edge function tarballs #6568

merged 41 commits into from
Jul 30, 2025

Conversation

eduardoboucas
Copy link
Member

Copy link
Contributor

This pull request adds or modifies JavaScript (.js, .cjs, .mjs) files.
Consider converting them to TypeScript.

@@ -50,12 +50,12 @@ jobs:
os: [ubuntu-24.04, macos-14, windows-2025]
node-version: ['22']
# Must include the minimum deno version from the `DENO_VERSION_RANGE` constant in `node/bridge.ts`.
deno-version: ['v1.39.0', 'v2.2.4']
deno-version: ['v2.4.2']
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unfortunate, as it's the only part of this PR that affects users not targeted by the feature flag. But deno bundle isn't available in previous versions.

@eduardoboucas eduardoboucas marked this pull request as ready for review July 28, 2025 09:36
@eduardoboucas eduardoboucas requested a review from a team as a code owner July 28, 2025 09:36
const entries: string[] = []

async function walk(currentPath: string): Promise<void> {
const dirents = await fs.readdir(currentPath, { withFileTypes: true })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be safe, we should sort the directory entries, this will help ensure we have a consistent hash between runs

Suggested change
const dirents = await fs.readdir(currentPath, { withFileTypes: true })
const dirents = await fs.readdir(currentPath, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done a little bit differently in 92603bb.

Comment on lines 16 to 19
} else if (dirent.isFile()) {
const fileHash = await getFileHash(fullPath)
entries.push(`${relativePath}:${fileHash}`)
}
Copy link
Contributor

@JakeChampion JakeChampion Jul 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the package being bundled uses a package manager like pnpm which uses symbolic links, i think we will be missing those in the bundling with this current implementation. Perhaps we should treat symlinks and files the same like this?

Suggested change
} else if (dirent.isFile()) {
const fileHash = await getFileHash(fullPath)
entries.push(`${relativePath}:${fileHash}`)
}
} else if (dirent.isFile() || dirent.isSymbolicLink()) {
const fileHash = await getFileHash(fullPath)
entries.push(`${relativePath}:${fileHash}`)
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can actually remove the if entirely? Done in 92603bb.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, that should likely work but dirents can be also be block devices, character devices, fifos, and sockets - i don't imagine people would be having those in the directories we are traversing but it is a possibility

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Added back in b1a719b.

@@ -22,7 +22,7 @@ export const getDirectoryHash = async (dirPath: string): Promise<string> => {

await walk(dirPath)

return getStringHash(entries.join('\n'))
return getStringHash(entries.sort().join('\n'))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we might need to do a locale aware sort due to modern filesystems allowing pretty much any byte-sequence in a pathname

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But does that matter, since we don't really care where in the list each element appears as long as it always appears in the same place? I'm happy to add locale-aware sorting, I'm just trying to understand where the simpler solution will break.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we do not supply a comparator to Array.prototype.sort then it is implementation-defined, which means it could potentially not be a stable sort, which would lead to non-stable hashes being generated

step 5 of Array.prototype.sort which calls SortIndexedProperties and step 4 of that is the implementation-defined behaviour we would be invoking

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 719b9c1.

@eduardoboucas eduardoboucas enabled auto-merge (squash) July 29, 2025 15:12
@eduardoboucas eduardoboucas merged commit a5e2746 into main Jul 30, 2025
66 of 67 checks passed
@eduardoboucas eduardoboucas deleted the feat/ef-tarball branch July 30, 2025 11:05
This was referenced Jul 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants