Repository navigation
CLI: handle multiple local copies of the same project - #1575
Open
midigofrank wants to merge 4 commits into
Open
midigofrank wants to merge 4 commits into
midigofrank wants to merge 4 commits into
Conversation
A workspace can hold several local copies of one project, each from its own state file (main@app.openfn.org.yaml, backup@app.openfn.org.yaml). They share a UUID and id, so anything keyed on those mixed them up. Copies overwrote each other's entries in the path map, openfn.yaml had no way to say which copy was checked out, and get() threw even when given an exact alias. matchProject now returns the exact alias match when all the other matches share its UUID. Real ambiguity still throws, and the error lists each clash as alias@host and suggests using one. Workspace keeps project paths by Project rather than by id, so each copy keeps its own file. getProjectPath() now takes a Project. extractConfig writes the active project's alias to openfn.yaml, and getTrackedProject() looks that alias and host up first. The alias is left out of project.openfn so the metadata doesn't store it twice. merge used getProjectPath(id) to find where to write. With --base it only got the right file because the id-keyed map happened to point there. It now writes back to the --base file directly.
…explicit `openfn project fetch <uuid> --endpoint X -o file.yaml` threw MultipleMatchingProjectsError if two local project files shared the UUID. With a full UUID, an endpoint and an output path, the command has everything it needs, so the local copies don't matter. Skip the local workspace lookup in that case. Also stop searching the workspace for an output target once -o is given, because the path is the target. Duplicates still throw when the UUID, endpoint or output path is missing.
When no project was given, pull and deploy fell back to the active project's UUID. That throws if another local copy shares the UUID, even though openfn.yaml says which one is checked out. If openfn.yaml records an alias, pull now defaults to the tracked project's alias@host and deploy uses the tracked project. Without an alias, both fall back to the UUID as before.
midigofrank
marked this pull request as ready for review
October 6, 2026 12:51
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
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.
Short Description
Lets a workspace hold several local copies of the same project (same UUID/id under different aliases, or the same UUID on different hosts) without the CLI throwing
MultipleMatchingProjectsErrorwhere the intent is clear.Fixes #1119
Fixes #1541 (OFN-4589)
Implementation Details
Aliases come from state file names (
main@app.openfn.org.yaml), so within a workspace they're the one identifier that's unique per copy. The fix uses them wherever lookups used to rely on UUID or id:alias@hostand suggests using one.openfn.yamlnow recordsalias, so the CLI knows which copy is checked out (this resolves the TODOs inWorkspace.tsanddeploy.ts). It stays local: it's stripped from project metadata and never sent to Lightning.getTrackedProject()prefers alias + host.pullanddeploywith no project or target use it rather than the UUID.mergenow writes to the right file, andmerge --basewrites back to the base file. That only worked by luck before.fetch <uuid> --endpoint X -o fileskips the local workspace lookup, since it has everything it needs (OFN-4589). With-o, the output path is the target and the workspace isn't searched.Behaviour is unchanged for an
openfn.yamlwith no alias (every existing workspace until its next checkout or pull): lookups fall back to UUID/id and throw on duplicates rather than guess.QA Notes
.projects/(e.g. copymain@<host>.yamltobackup@<host>.yaml), then:openfn project checkout backupworks, andopenfn.yamlgetsalias: backupopenfn project pull(no argument) pulls into the checked-out copyopenfn project fetch <uuid>with no-ostill errors, because it's unclear which file to writeopenfn project fetch <uuid> --endpoint <url> -o out.yamlsucceeds with duplicates presentpullanddeploydefaults. There are nopulltests in the CLI yet, so those are worth a manual check.AI Usage