Feat/open projects config to any (#681)
* feat(server): derive owner/repo display name for any remote host Generalize deriveProjectGroupingName so any remote:<host>/<segments...> project key returns the last two path segments (owner/repo) instead of just the trailing segment. Path-fallback for non-remote keys is unchanged. Brings GitLab, Gitea, Bitbucket, and self-hosted remotes to parity with the prior github.com-only behavior — no separate special-case needed. * feat(app): show projects from any git remote in Projects settings Remove the isSupportedProjectKey filter so workspaces with non-GitHub remotes (GitLab, Gitea, Bitbucket, self-hosted, ssh-style) appear in the Projects list and route to the project settings screen. The daemon RPCs, config schema, and registry were already host-agnostic; this lifts a client-side filter that hid them. Also remove the now-vestigial hiddenUnsupportedRemoteCount field from ProjectSummary, BuildProjectsResult, and UseProjectsResult — once the filter is gone, the count is always zero and the field is dead state. This is an internal app-package type, not a wire schema, so deletion is safe. * chore(app): simplify Projects empty state to "No projects yet" Drop the "Non-GitHub remote projects aren't supported yet" empty-state branch — it can no longer fire now that any git remote is shown. The empty state is unconditional now. * test(app): cover non-GitHub remote in projects-settings e2e Add a fixture that creates a temp git repo with origin pointing at a gitlab.com URL and exercises the same paseo.json read/edit/save flow already covered for local repos. Verifies the project surfaces with the "acme/app" display name and that the round-trip persists correctly. Extracted the remote-setup branch in createTempGitRepo into a small configureRemote helper to keep the main function under the cyclomatic complexity limit. --------- Co-authored-by: Mathias Kurz <mkurz@stamus-networks.com>
This commit is contained in:
co-authored by
Mathias Kurz
parent
2b6d7d4ec2
commit
44d13919d7
@@ -356,7 +356,7 @@ describe("buildProjects", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("filters non-GitHub remote projects while keeping GitHub and local projects", () => {
|
||||
it("includes GitHub, GitLab, Bitbucket and local projects together, sorted by name", () => {
|
||||
const result = buildProjects({
|
||||
hosts: [
|
||||
{
|
||||
@@ -368,20 +368,30 @@ describe("buildProjects", () => {
|
||||
id: "github",
|
||||
repoRoot: "/repo/github",
|
||||
project: placement({
|
||||
projectKey: "remote:github.com/acme/app",
|
||||
projectName: "acme/app",
|
||||
projectKey: "remote:github.com/acme/web",
|
||||
projectName: "acme/web",
|
||||
cwd: "/repo/github",
|
||||
remoteUrl: "https://github.com/acme/app.git",
|
||||
remoteUrl: "https://github.com/acme/web.git",
|
||||
}),
|
||||
}),
|
||||
workspace({
|
||||
id: "gitlab",
|
||||
repoRoot: "/repo/gitlab",
|
||||
project: placement({
|
||||
projectKey: "remote:gitlab.com/acme/app",
|
||||
projectName: "app",
|
||||
projectKey: "remote:gitlab.com/acme/api",
|
||||
projectName: "acme/api",
|
||||
cwd: "/repo/gitlab",
|
||||
remoteUrl: "https://gitlab.com/acme/app.git",
|
||||
remoteUrl: "https://gitlab.com/acme/api.git",
|
||||
}),
|
||||
}),
|
||||
workspace({
|
||||
id: "bitbucket",
|
||||
repoRoot: "/repo/bitbucket",
|
||||
project: placement({
|
||||
projectKey: "remote:bitbucket.org/acme/cli",
|
||||
projectName: "acme/cli",
|
||||
cwd: "/repo/bitbucket",
|
||||
remoteUrl: "https://bitbucket.org/acme/cli.git",
|
||||
}),
|
||||
}),
|
||||
workspace({
|
||||
@@ -399,14 +409,15 @@ describe("buildProjects", () => {
|
||||
],
|
||||
});
|
||||
|
||||
expect(result.hiddenUnsupportedRemoteCount).toBe(1);
|
||||
expect(result.projects.map((project) => project.projectKey)).toEqual([
|
||||
"remote:github.com/acme/app",
|
||||
"remote:gitlab.com/acme/api",
|
||||
"remote:bitbucket.org/acme/cli",
|
||||
"remote:github.com/acme/web",
|
||||
"/repo/local",
|
||||
]);
|
||||
});
|
||||
|
||||
it("produces the unsupported empty-state signal when only non-GitHub remote projects are present", () => {
|
||||
it("renders a non-GitHub remote project on its own when no other projects are present", () => {
|
||||
const result = buildProjects({
|
||||
hosts: [
|
||||
{
|
||||
@@ -419,7 +430,7 @@ describe("buildProjects", () => {
|
||||
repoRoot: "/repo/gitlab",
|
||||
project: placement({
|
||||
projectKey: "remote:gitlab.com/acme/app",
|
||||
projectName: "app",
|
||||
projectName: "acme/app",
|
||||
cwd: "/repo/gitlab",
|
||||
remoteUrl: "https://gitlab.com/acme/app.git",
|
||||
}),
|
||||
@@ -429,8 +440,48 @@ describe("buildProjects", () => {
|
||||
],
|
||||
});
|
||||
|
||||
expect(result.projects).toEqual([]);
|
||||
expect(result.hiddenUnsupportedRemoteCount).toBe(1);
|
||||
expect(result.projects).toHaveLength(1);
|
||||
expect(result.projects[0]?.projectKey).toBe("remote:gitlab.com/acme/app");
|
||||
expect(result.projects[0]?.projectName).toBe("acme/app");
|
||||
expect(result.projects[0]?.githubUrl).toBeUndefined();
|
||||
});
|
||||
|
||||
it("groups two workspaces sharing a non-GitHub remote into one project with workspaceCount two", () => {
|
||||
const result = buildProjects({
|
||||
hosts: [
|
||||
{
|
||||
serverId: "local",
|
||||
serverName: "Local",
|
||||
isOnline: true,
|
||||
workspaces: [
|
||||
workspace({
|
||||
id: "main",
|
||||
repoRoot: "/repo/gitlab",
|
||||
project: placement({
|
||||
projectKey: "remote:gitlab.com/acme/app",
|
||||
projectName: "acme/app",
|
||||
cwd: "/repo/gitlab",
|
||||
remoteUrl: "https://gitlab.com/acme/app.git",
|
||||
}),
|
||||
}),
|
||||
workspace({
|
||||
id: "feature",
|
||||
repoRoot: "/repo/gitlab",
|
||||
project: placement({
|
||||
projectKey: "remote:gitlab.com/acme/app",
|
||||
projectName: "acme/app",
|
||||
cwd: "/repo/gitlab/feature",
|
||||
remoteUrl: "https://gitlab.com/acme/app.git",
|
||||
}),
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(result.projects).toHaveLength(1);
|
||||
expect(result.projects[0]?.hosts).toHaveLength(1);
|
||||
expect(result.projects[0]?.hosts[0]?.workspaceCount).toBe(2);
|
||||
});
|
||||
|
||||
it("falls back conservatively for mixed-version daemons whose descriptors lack project", () => {
|
||||
@@ -461,6 +512,5 @@ describe("buildProjects", () => {
|
||||
expect(summary?.hosts).toHaveLength(1);
|
||||
expect(summary?.hosts[0]?.repoRoot).toBe("/repo/legacy");
|
||||
expect(summary?.hosts[0]?.workspaceCount).toBe(1);
|
||||
expect(result.hiddenUnsupportedRemoteCount).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user