jetify-com / devbox

Instant, easy, and predictable development environments
https://www.jetify.com/devbox/
Apache License 2.0
8.37k stars 196 forks source link

Proposed change to plugin schema #2179

Open Bee-Mar opened 3 months ago

Bee-Mar commented 3 months ago

What problem are you trying to solve?

I would like to use privately hosted plugins on non-GitHub servers (which includes non-GitHub servers that aren't public), and am currently working an implementation (https://github.com/Bee-Mar/devbox/tree/feature/gitlab-plugins), but discovered some issues along the way. Because GitLab allows for project subgroups, the URL structure can conflict with GitHub's expectation of a user/repo/ref. GitLab can have namespace/repo, namespace/subgroup/repo or namespace/subgroup1/subgroup2/repo, etc. up to 20 nested levels (https://docs.gitlab.com/ee/user/group/subgroups/).

Also, see the original issue created: https://github.com/jetify-com/devbox/issues/2048

What solution would you like?

While working on the implementation referenced above, I believe it would be more reasonable to use a JSON structure that provides more flexibility:

"include": [
  "namespace/subgroup/repo1": {
    "type": "ssh",
    "host": "gitlab.com",
    "port": 9999,
    "dir": "my-plugins",
    "ref": "myref",
    "branch": "mybranch"
  },
  "user/repo2": {
    "host": "github.com",
    "dir": "my-plugins",
    "ref": "myref",
    "branch": "mybranch"
  }
]

This is currently notional, but would work very well with the existing Ref struct in nix/flake/flakeref.go, and enable easy support for any repo type.

I'd like to pivot toward this in my implementation, but also wanted to get the opinion of the Devbox team before putting serious effort into it. Is this something that would be of interest? If so, I can provide a formalized schema to be agreed upon before moving forward.

Alternatives you've considered

No response

Bee-Mar commented 2 months ago

I've taken some time to put together a JSON schema for review:

{
  "include": {
    "description": "List of additional plugins to activate within your devbox shell",
    "type": "object",
    "patternProperties": {
      "^[a-zA-Z0-9/_.-]+$": {
        "description": "Configuration for each plugin specified by its path",
        "type": "object",
        "properties": {
          "protocol": {
            "description": "Protocol to use (https, ssh, or file)",
            "type": "string",
            "enum": ["https", "ssh", "file"]
          },
          "host": {
            "description": "Host of the repository (e.g., gitlab, github, bitbucket, localhost)",
            "type": "string"
          },
          "port": {
            "description": "Port to use for the connection",
            "type": "integer",
            "minimum": 1,
            "maximum": 65535
          },
          "directory": {
            "description": "Subdirectory that should be accessed in the repo. Defaults to the path key if not provided",
            "type": "string"
          },
          "ref": {
            "description": "Git reference",
            "type": "string"
          },
          "branch": {
            "description": "Git branch (only relevant for https or ssh protocols)",
            "type": "string"
          }
        },
        "required": ["protocol", "host"],
        "dependencies": {
          "branch": {
            "oneOf": [
              {
                "properties": {
                  "protocol": {
                    "enum": ["https", "ssh"]
                  }
                }
              },
              {
                "properties": {
                  "protocol": {
                    "enum": ["file"]
                  }
                },
                "not": {
                  "required": ["branch"]
                }
              }
            ]
          }
        },
        "additionalProperties": false
      }
    },
    "additionalProperties": false
  }
}

At the moment, I don't have anything in it to support flakes, but this configuration allows for that to be added very easily.

Use of this schema for the plugins also would help eliminate a lot of the URL parsing code and make it easier to scale in the future.

This would be a sample plugin:

  "include": {
    "username/repo": {
      "protocol": "https",
      "host": "gitlab.com",
      "directory": "plugin",
      "branch": "main"
    }
  }
Bee-Mar commented 2 months ago

@angelside @agate @adamdicarlo0 @bketelsen does anyone have interest in entertaining this idea?