fix: Use the specified project when the current project can not be inferred #3
Open
Robert Navarro opened 2 days ago

I use tod from coding agents against my OneDev 16.9.1 server, and the agents often run from a directory that is not a OneDev checkout. There, tod issue list --project pilot and tod issue get PILOT-5 both fail with exit 1 and failed to infer OneDev project from working directory '.': working directory is not inside a git repository..., even though the command already names the project. The agents ended up cloning a repo or calling the REST API with curl just to read an issue.

With this change, tod still infers the current project from the working directory first, exactly as before. Only when that fails does it fall back to the project the command names:

  • With --project (or --source-project), that project is sent as currentProject.
  • With a <project-path>#<number> reference, the path is sent.
  • With a <project-key>-<number> reference, the key is resolved to a path with query-projects ("Key" is "<KEY>", keeping only an exact key match). This lookup only runs when inference has failed.
  • With nothing to fall back to (no flag, and a #<number> or <number> reference), the original inference error is returned unchanged.

Inside a checkout, every request carries the same currentProject as before, so references in the output are rendered the same way and a #N from the output still resolves to the same entity in a follow-up command. An earlier version of this PR sent the specified project as currentProject even inside a checkout. For a project without a key, that rendered its entities as #N, and a follow-up tod issue edit #N in the same checkout would act on the checkout's project instead. This version does not change anything there.

This covers every issue, pr and build command that takes --project, --source-project or a reference. For issue link, the fallback is used only when both references are qualified, and the project comes from the source reference. pr create and the two requirement commands still read the source branch from the working directory, so outside a checkout they also need --source-branch. I left issue create-branch, the checkout and current-reference commands, project current, remote and build run as they are, since they work on the local repository. cli.md gets one sentence about the fallback.

One case this does not cover: a git repository with a single remote that is not on the OneDev server. Inference does not check the remote against the clone roots when there is only one remote, so it takes the path from that URL and succeeds, and the fallback never runs. tod issue get PILOT-5 there still fails with HTTP 404 ... Project not found or inaccessible: example/other, the same as today. I left that alone so that inference itself stays exactly as it is, since the point of this version is to change nothing wherever inference succeeds today.

Results from an empty directory that is not a git repository, with tod 4.3.4 and with this branch:

Commandtod 4.3.4this branch
issue list --project pilotexit 1, inference errorexit 0, issue list
issue get PILOT-5exit 1, inference errorexit 0
issue get pilot#5exit 1, inference errorexit 0
build list --project k0boardexit 1, inference errorexit 0
issue get 5, issue get #5, issue listexit 1, inference errorexit 1, same error text

Inside a real checkout of another project (k0board), I ran issue list --project pilot, issue get PILOT-5, issue get pilot#5, issue list, issue get 1, build list --project pilot, pr list --project pilot and issue get-comments PILOT-5 with tod 4.3.4, with current main, and with this branch. Stdout, stderr (without the log timestamps) and exit codes are identical across all three. I also put a small logging proxy in front of the server and compared the request URLs for the same commands except pr list: they are identical between 4.3.4, main and this branch, with currentProject=k0board on every call and no query-projects lookup.

I added tests in cli_common_test.go against an httptest server: an inferred project wins over --project and over qualified references (and no key lookup happens), the specified or referenced project is used when inference fails, a short reference with nothing to fall back to returns the original inference error, and key lookup takes only an exact match and reports a key that is not found. gofmt, go vet ./..., go test ./... and go build pass. I only ran read commands against a server for this version, I have no test for how issue link picks the project, and I only tested on Linux.

I searched the onedev/tod issues and pull requests and the onedev/server issues before putting this up. The closest is onedev/tod#2, older feedback from when tod ran as an MCP server, which mentions having to start it in a git directory.

I used an AI coding assistant to help write this change, and I reviewed and tested it myself.

Able to merge without conflicts
Pull request can only be merged by users with code write permission
  • fix: Do not require a git checkout when the project is specified
    Commands that take --project, or a reference in form of "<project-path>#<number>" or "<project-key>-<number>", inferred the current project from the working directory before doing anything else. Outside a OneDev checkout this failed with "working directory is not inside a git repository", even though the project was already known.
    
    Use the specified project as current project in that case, resolving a project key to its path via query-projects. The working directory is still used when no project is specified and for references in form of "#<number>" or "<number>".
    2 days ago
  • Robin Shen commented 2 days ago

    This has a big impact, as many operations and tod resource at server side assumes a current project. For instance, it is used to show issue/PR/build reference (if current project is same as issue project, the project will not be displayed etc), other parts may also rely on a current project assumption.

  • fix: Use the specified project when the current project can not be inferred
    Commands that take --project or --source-project, or a reference in form of "<project-path>#<number>" or "<project-key>-<number>", failed outside a OneDev checkout with "working directory is not inside a git repository", even though the project was already known.
    
    The current project is still inferred from the working directory first, so requests made inside a checkout are unchanged. Only when inference fails, the specified project is used as current project, with a project key resolved to its path via query-projects. References in form of "#<number>" or "<number>" still fail with the inference error.
    2 days ago
  • Robert Navarro changed title 2 days ago
    Previous Value Current Value
    fix: Do not require a git checkout when the project is specified
    "fix: Use the specified project when the current project can not be inferred"
    
  • Robert Navarro changed title 2 days ago
    Previous Value Current Value
    "fix: Use the specified project when the current project can not be inferred"
    
    fix: Use the specified project when the current project can not be inferred
  • Robert Navarro commented 2 days ago

    Thanks, you are right. I went through the server code and found a concrete case: inside a checkout of project A, tod issue create --project B for a project B without a key would print the new issue as #N, and a follow-up tod issue edit #N in the same checkout would resolve against A. I reworked the change so the working directory always wins when a project can be inferred from it, and the specified project is only used when it can't. Behavior inside a checkout is unchanged: I compared outputs and request URLs against tod 4.3.4 and current main, and currentProject is the same on every read command I compared. I updated the description with the details.

1/1
Merge Strategy
Create Merge Commit
Watchers (2)
Reference
PR TOD-3
Please wait...
Connection lost or session expired, reload to recover
Page is in error, reload to recover