@@ -18,20 +18,24 @@ import (
1818 "context"
1919 "errors"
2020 "fmt"
21+ "log/slog"
2122 "maps"
2223 "slices"
2324
25+ modulev1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/module/v1"
2426 "buf.build/go/app/appcmd"
2527 "buf.build/go/app/appext"
2628 "buf.build/go/standard/xslices"
2729 "buf.build/go/standard/xstrings"
30+ "connectrpc.com/connect"
2831 "github.com/bufbuild/buf/private/buf/bufcli"
2932 "github.com/bufbuild/buf/private/buf/bufctl"
3033 "github.com/bufbuild/buf/private/buf/buffetch"
3134 "github.com/bufbuild/buf/private/bufpkg/bufanalysis"
3235 "github.com/bufbuild/buf/private/bufpkg/bufcheck"
3336 "github.com/bufbuild/buf/private/bufpkg/bufconfig"
3437 "github.com/bufbuild/buf/private/bufpkg/bufimage"
38+ "github.com/bufbuild/buf/private/bufpkg/bufregistryapi/bufregistryapimodule"
3539 "github.com/bufbuild/buf/private/pkg/syserror"
3640 "github.com/bufbuild/buf/private/pkg/wasm"
3741 "github.com/spf13/pflag"
@@ -236,9 +240,15 @@ func run(
236240 return err
237241 }
238242 }
243+ clientConfig , err := bufcli .NewConnectClientConfig (container )
244+ if err != nil {
245+ return err
246+ }
247+ moduleServiceProvider := bufregistryapimodule .NewClientProvider (clientConfig )
239248 if flags .AgainstRegistry {
240249 for _ , imageWithConfig := range imageWithConfigs {
241- if imageWithConfig .ModuleFullName () == nil {
250+ moduleFullName := imageWithConfig .ModuleFullName ()
251+ if moduleFullName == nil {
242252 if imageWithConfig .ModuleOpaqueID () == "" {
243253 // This can occur in the case of a [buffetch.MessageRef], where we resolve the message
244254 // ref directly from the bucket without building the [bufmodule.Module]. In that case,
@@ -251,9 +261,42 @@ func run(
251261 imageWithConfig .ModuleOpaqueID (),
252262 )
253263 }
264+ // Check commits exist for the module on the default label before we try to get the against image.
265+ // TODO: remove this check once we have error details to indicate that the against input
266+ // has no commits on the default label. We use the API directly here to avoid issues of conflating
267+ // dependency errors to empty module errors.
268+ commitServiceClient := moduleServiceProvider .V1CommitServiceClient (moduleFullName .Registry ())
269+ if _ , err := commitServiceClient .GetCommits (
270+ ctx ,
271+ connect .NewRequest (
272+ & modulev1.GetCommitsRequest {
273+ ResourceRefs : []* modulev1.ResourceRef {
274+ {
275+ Value : & modulev1.ResourceRef_Name_ {
276+ Name : & modulev1.ResourceRef_Name {
277+ Owner : moduleFullName .Owner (),
278+ Module : moduleFullName .Name (),
279+ },
280+ },
281+ },
282+ },
283+ },
284+ ),
285+ ); err != nil {
286+ if connect .CodeOf (err ) == connect .CodeFailedPrecondition {
287+ // This error occurs when the against input is a module that has no commits on the default branch.
288+ // We ignore this case to support new modulues that have just been created in the registry.
289+ container .Logger ().DebugContext (
290+ ctx , "ignoring empty module without commits on the default branch" ,
291+ slog .String ("module" , imageWithConfig .ModuleFullName ().String ()),
292+ )
293+ continue
294+ }
295+ return err
296+ }
254297 againstImage , err := controller .GetImage (
255298 ctx ,
256- imageWithConfig . ModuleFullName () .String (),
299+ moduleFullName .String (),
257300 bufctl .WithTargetPaths (externalPaths , flags .ExcludePaths ),
258301 bufctl .WithConfigOverride (flags .AgainstConfig ),
259302 )
0 commit comments