-
Notifications
You must be signed in to change notification settings - Fork 29
feat: custom code #1733
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
feat: custom code #1733
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mfbx9da4
approved these changes
Dec 1, 2025
a390fd2 to
a07d32e
Compare
498f437 to
1ae60e7
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The Persistent Edits feature enables arbitrary code changes on top of any speakeasy generation target. Just make whatever changes you want on top of Speakeasy's target files and we'll start prompting you if you want us to maintain those changes by enabling before we overwrite them.
If this feature is enabled, conflicts may happen when Speakeasy Generation wants to touch the same lines as something with a custom modification, and are expected to be resolved locally after
speakeasy run(and then re-running it withspeakeasy run --skip-versioning).Git interface → effective commands
HasObject(hash)git cat-file -e <hash>ReadBlob(hash)git cat-file -p <hash>WriteObject(content)git hash-object -w --stdinCreateSnapshotTree(map)GIT_INDEX_FILE=.git/speakeasy_temp_index git update-index --add --cacheinfo ...; git write-treeCommitSnapshot(tree,parent)git commit-tree <tree> [-p <parent>]FetchSnapshot(uuid)git fetch origin refs/speakeasy/gen/<uuid>PushSnapshot(commit, uuid)git push origin <commit>:refs/speakeasy/gen/<uuid>Caution
Enabling this (it's default OFF) does rely on an assumption that
git pushandgit fetchinteractions withoriginare possible and can occur without prompting. It does NOT however interact with any branches or non-speakeasy-generated code: it purely makes low-level git refs to be able to detect any user changes on speakeasy-tracked files.Git Ref structure
refs/speakeasy/gen/<generation_id>. Subsequent generations will reference this to determine the user patch f we detect that the generated files are no longer equivalent via an integrity hash checkrefs/heads/so there won't be any visible branches in GitHub; ref keeps objects reachable sogit gcwon't prune them. Similarly this shouldn't cause local repository bloat as we only need to fetch the most recent one on generation.generation_id,pristine_commit_hash,pristine_tree_hashto help make it all work.Algorithm (4 steps)
Immediate blobbing
VirtualFilessystem. I.e. during generation if the option is enabled, files no longer get updated on file-system directly but in-memory.git hash-object -w→ build mappath → blobHashNo-op detection
git write-treepristine_tree_hashfrom lockfile: exit early, no changes (we don't want a fresh no-op tree commit as it's noisy)Merge loop (per file)
// @generated-id: <uuid>headers to detect movesdisk_checksum == last_write_checksum): overwrite with new contentgit cat-file -p <git_object>), disk, and new generatedgit applywhere there's a conflict:Finalization
git commit-tree <new_tree> [-p <pristine_commit_hash>]git push origin <commit>:refs/speakeasy/gen/<new-uuid>(fire-and-forget)Multi-target handling
Each target in a configured monorepo (
go-sdk/,ts-sdk/) has its owntrackedFilessection ingen.lock. TheGitAdaptertakes abaseDirparam to translate logical paths (models/pet.go) to repo paths (go-sdk/models/pet.go). All targets share the same git object database and ref namespace. Because we're committing independent git trees and indexing them viagen.lock, should work in any arbitrary git repo.Lockfile structure
Healer / offline
Before a git fetch, check if
pristine_commit_hashexists locally (git cat-file -e). If yes, no need to fetch it.Test plan
@generated-iddetection worksgit show-ref | grep refs/speakeasy/gen/to inspect refs, manual execution under a bunch of different cases with some test repos.