-
Notifications
You must be signed in to change notification settings - Fork 12
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
Feature/registry alias #273
base: main
Are you sure you want to change the base?
Conversation
Add .buffrs/config.toml registries and hierarchical packages
Bumps [gix-path](https://github.com/Byron/gitoxide) from 0.10.7 to 0.10.10. - [Release notes](https://github.com/Byron/gitoxide/releases) - [Changelog](https://github.com/Byron/gitoxide/blob/main/CHANGELOG.md) - [Commits](GitoxideLabs/gitoxide@gix-path-v0.10.7...gix-path-v0.10.10) --- updated-dependencies: - dependency-name: gix-path dependency-type: indirect ... Signed-off-by: dependabot[bot] <[email protected]>
# Conflicts: # Cargo.lock # Cargo.toml # src/main.rs # src/manifest.rs # src/registry/mod.rs # tests/cmd/publish/in # tests/cmd/publish/out
# Conflicts: # Cargo.lock
…kage # Conflicts: # Cargo.lock
@mara-schulke : some of the unit tests are failing due to the change in the manifest version (0.9 → 0.10). I'm fixing this now and will update. |
Hi this is great thank you so much! One note before I'd start a detailed review: The proto rust module is not necessary as this is covered by Tonic itself: https://docs.rs/tonic-build/latest/tonic_build/struct.Config.html#method.include_file Could you maybe revert that command? Once done I'm happy to review and merge this asap! |
Im not entirely done with reviewing but I've commented some points of concern above so they can be already addressed |
You should not invoke the CLI level code in a build.rs as doing network requests as part of your build process is going to yield you flaky builds I'm not keen on re introducing this pattern (this was actually once possible with buffrs - it turned out to be causing all sorts of issues). Scheduling the installation step of your protos is better done by using (or better integrating buffrs into) a proper build system for your project like nix, bazel etc. We have done this at Helsing and it works great, incl caching etc. |
What a joke... I wasn't aware of this. Of course. a5651c1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is definitely going in the right direction although I feel like this is loosening the type safety and semantic guarantees we currently provide. I'm happy to have another chat about this to get it over the line!
config_path: Option<PathBuf>, | ||
|
||
/// Default registry alias to use if none is specified | ||
default_registry: Option<String>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Last new type request: Could we use a registry name new type to ensure that this string is infact a valid registry name?
I would suggest using a similar convention as with package names
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could basically derive / share a lot of logic with the PackageName type
/// - None -> alias://<default> | ||
pub fn parse_registry_arg(&self, registry: &Option<String>) -> miette::Result<RegistryRef> { | ||
match registry { | ||
Some(registry) => RegistryRef::from_str(registry), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: .parse is more idiomatic imo
} | ||
|
||
impl Config { | ||
/// Create a new configuration with default values |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment lies
Could you roughly follow the public api semantics from the manifest / cache?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you give me specifics?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes sorry.
So this function will do IO although the comment says it will create a new one with default values!
With regards to the common pattern I was referring to the Manifest
struct for example
/// A URL to a registry | ||
Url(RegistryUri), | ||
/// An alias to a registry | ||
Alias(String), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my understand you have two types:
RegistryRef (a reference, potentially aliased registry) and RegistryUri the uri version, independent of its origin
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean we could express the Alias as Alias(String, Option<RegistryUri>)
?
I found it safer to not use the option, but a third type. But for aliases, we need to remember the alias name and URL at all times, as, depending on the context, we do need to be able to access the alias, even if resolved.
What could be done is to split this enum into two types:
enum RawRegistryRef {
Url(RegistryUri),
Alias(String),
};
enum RegistryRef {
Url(RegistryUri),
Alias(String, RegistryUri),
};
The former is returned just after parsing the config files / command lines, and the latter is the result of resolving the aliases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well I'm talking about:
enum RegistryRef {
Uri(Uri)
Alias(RegistryName)
}
impl RegistryRef {
fn resolve(config: &Config) -> Result<RegistryUri> {
//
}
}
struct RegistryUri(Uri);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need to remember aliases here?
Like you can do the resolving as late as possible (and still keep the original registry ref around)
/// An alias to a registry | ||
Alias(String), | ||
/// A resolved alias to a registry | ||
ResolvedAlias { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thus this case seems both type unsafe and unnecessary to me as you would want to go from RegistryRef to RegistryUri during alias resolution
/// Get the raw URL of the registry with any alias resolved | ||
/// | ||
/// # Arguments | ||
/// * `config` - The configuration to use to resolve the alias |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ie this could be typesafe!
} | ||
|
||
/// Serializer for resolved RegistryUris | ||
pub fn serialize_resolved<S>(&self, serializer: S) -> Result<S::Ok, S::Error> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This aswell.
/// | ||
/// # Arguments | ||
/// * `url` - The URL to check | ||
pub fn sanity_check_url(url: &Url) -> miette::Result<()> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't make this part of the public api
Okay, let's cut any refactorings or feature changes to get it merged asap. If you could tackle the code quality topics I've raised I would be glad. Once you are happy please give me another go and I'll have a look! |
This PR introduces a whole set of features which are all related to implement a comprehensive build workflow.
Important
This PR bumps the Proto.toml
edition
to 0.10.buffrs --insecure ...
buffrs install --only-dependencies
buffrs install --generate-buf-yaml <file> [<prefix>]
package
andpublish
CLI code moved to cli.rsbuffrs --insecure ...
The
-k
/--insecure
general flag skips SSL validation during operations. Useful for environments with self-signed certificates or testing scenarios, such a Docker containers.buffrs install --only-dependencies
Adding this flag during
buffrs install
(e.g.,buffrs install --only-dependencies
) installs only the vendor, while leaving a package's own proto files untouched.buffrs install --generate-buf-yaml <file> [<prefix>]
Adding this flag during
buffrs install
(e.g.,buffrs install --generate-buf-yaml
) generates a buf.yaml file in the proto directory matching installed dependencies during dependency resolution. This enables seamless use ofbuf
for linting and generating proxies/stubs from proto files.The flag will either create a new
buf.yaml
file from scratch or update an existing one with the latest dependencies.IDE extensions, such as the Buf Linter for Visual Studio Code, will readily pick up the buf.yaml file and provide linting capabilities. A typical buf.yaml file looks like this:
Repository Configuration File (repo-root/.buffrs/config.toml)
A new configuration file,
.buffrs/config.toml
, can be added to a repository to specify various options for thebuffrs
tool. This file is optional and can be used to set default values for commands, such asbuffrs install
, or to specify registry aliases and a default registry.Note
There was a lot of discussion about the location and name of the configuration file. In particular, it was suggested that it should be placed at
$HOME/.config/buffrs.toml
. It is true that there is a general move to collect configuration files in$HOME/.config/
, but this does not apply to this case, because the purpose of the configuration file is to specify options for a specific repository. Therefore, it makes sense to place the configuration file in the root of the repository.Further research provided no indication that a common configuration folder is used for repositories in a similar fashion as for
$HOME
directory. This was confirmed by Mara Schulke. Therefore, this PR keeps the file at its original location.The configuration has the following structure:
edition
: Specifies the edition of the configuration file. This field is mandatory and must be set to the current edition of the configuration file, which mirrors the edition of theProto.toml
file.registries
: Specifies registry aliases. The key is the alias, and the value is the actual registry URL.registry
: Specifies the default registry to use when no registry is specified on the command line.command
: Specifies default arguments for thebuffrs
tool using thedefault_args
field. Thedefault_args
field is an array of default arguments.commands.<command>
: Specifies default arguments for a specific command. Thedefault_args
field is an array of default arguments.Registry Aliases
If configured in the configuration file, registry aliases can be used anywhere a registry URL is expected. This simplifies the use of registries by providing a human-readable alias instead of a full URL.
Aliases on the Command Line
Aliases can be used on the command line by specifying the
--registry
flag with the alias name. For example:Aliases in Proto.toml
The
registry
field in Proto.toml now supports aliases. For instance:Alias resolution during
package
andpublish
Buffrs resolves registry aliases when packing or publishing to an upstream repository. To ensure compatibility, the original Proto.toml is preserved as Proto.toml.orig, while the normalized version is used during operations. This mirrors Cargo's behavior.
Example:
Original Proto.toml:
Generated Proto.toml:
Improved Path Dependency Handling
buffrs
already supports path dependencies, e.g.This PR adds the following new features:
Nested Path Dependencies
Proto packages may now specify a path dependency that itself has path dependencies, improving fast turnaround times during development.
Path Dependency and Registry Dependency
Similar to Cargo, Proto packages may now specify a path dependency and a registry dependency for the same package. This is useful for development scenarios where a package references a local package, but, once published, needs to reference a registry package.
When publishing, the path dependency is dropped, and only the registry dependency is maintained during alias resolution. The original Proto.toml is preserved as Proto.toml.orig.
Even during development, the version constraint will be checked against version found at the local path.
Code Refactoring
CLI code moved to cli.rsThe CLI code formerly inmain.rs
has been moved tocli.rs
, and and is invoked frommain.rs
through acli::run()
function. The main purpose of this change is to allowbuffrs
to be invoked from build.rs scripts simply by declaringbuffrs
as adev-dependency
inCargo.toml
, without having to install the binary itself.