Skip to content
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

feat: automatic migrate the buf configs to v2 #4494

Merged
merged 8 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- [#4289](https://github.com/ignite/cli/pull/4289), [#4423](https://github.com/ignite/cli/pull/4423), [#4432](https://github.com/ignite/cli/pull/4432) Cosmos SDK v0.52 support
- [#4477](https://github.com/ignite/cli/pull/4477) IBC v10 support
- [#4166](https://github.com/ignite/cli/issues/4166) Migrate buf config files to v2
- [#4494](https://github.com/ignite/cli/pull/4494) Automatic migrate the buf configs to v2

### Changes

Expand Down
27 changes: 25 additions & 2 deletions ignite/cmd/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"github.com/ignite/cli/v29/ignite/pkg/cliui"
"github.com/ignite/cli/v29/ignite/pkg/cliui/colors"
"github.com/ignite/cli/v29/ignite/pkg/cliui/icons"
"github.com/ignite/cli/v29/ignite/pkg/cosmosbuf"
"github.com/ignite/cli/v29/ignite/pkg/cosmosgen"
"github.com/ignite/cli/v29/ignite/pkg/errors"
"github.com/ignite/cli/v29/ignite/pkg/goanalysis"
Expand All @@ -28,13 +29,17 @@
msgMigrationPrefix = "Your blockchain config version is v%d and the latest is v%d."
msgMigrationPrompt = "Would you like to upgrade your config file to v%d"
msgMigrationBuf = "Now ignite supports the `buf.build` (https://buf.build) registry to manage the protobuf dependencies. The embed protoc binary was deprecated and, your blockchain is still using it. Would you like to upgrade and add the `buf.build` config files to `proto/` folder"
msgMigrationBufV2 = "Now ignite supports the new `buf.build` (https://buf.build) v2 configuration. Would you like to upgrade your buf files to v2 using the `buf config migrate` command"
msgMigrationBufProtoDir = "Ignite proto directory path from the chain config doesn't match the proto directory path from the chain `buf.work.yaml`. Do you want to add the proto path `%[1]v` to the directories list from the buf work file"
msgMigrationBufProtoDirs = "Chain `buf.work.yaml` file contains directories that don't exist anymore (%[1]v). Do you want to delete them"
msgMigrationAddTools = "Some required imports are missing in %s file: %s. Would you like to add them"
msgMigrationRemoveTools = "File %s contains deprecated imports: %s. Would you like to remove them"
)

var ErrProtocUnsupported = errors.New("code generation using protoc is only supported by Ignite CLI v0.26.1 or older")
var (
ErrProtocUnsupported = errors.New("code generation using protoc is only supported by Ignite CLI v0.26.1 or older")
ErrBufConfigVersionUnsupported = errors.New("buf config version must be v2")
)

// NewChain returns a command that groups sub commands related to compiling, serving
// blockchains and so on.
Expand Down Expand Up @@ -192,11 +197,29 @@

func bufMigrationPreRunHandler(cmd *cobra.Command, session *cliui.Session, appPath, protoDir string) error {
// check if the buf files exist.
hasFiles, err := chain.CheckBufFiles(appPath, protoDir)
hasFiles, needMigration, err := chain.CheckBufFiles(appPath, protoDir)
if err != nil {
return err
}

if needMigration {
if !getYes(cmd) {
if err := session.AskConfirm(msgMigrationBufV2); err != nil {
return ErrBufConfigVersionUnsupported
}
}

cacheStorage, err := newCache(cmd)

Check failure on line 212 in ignite/cmd/chain.go

View workflow job for this annotation

GitHub Actions / Lint Go code

ineffectual assignment to err (ineffassign)
b, err := cosmosbuf.New(cacheStorage, appPath)
if err != nil {
return err
}

if err := b.Migrate(cmd.Context(), protoDir); err != nil {
return err
}
}

if !hasFiles {
if !getYes(cmd) {
if err := session.AskConfirm(msgMigrationBuf); err != nil {
Expand Down
37 changes: 34 additions & 3 deletions ignite/pkg/cosmosbuf/buf.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,18 @@ const (
flagOutput = "output"
flagErrorFormat = "error-format"
flagLogFormat = "log-format"
flagWorkspace = "workspace"
flagBufGenYaml = "buf-gen-yaml"
flagIncludeImports = "include-imports"
flagIncludeWellKnownTypes = "include-wkt"
flagPath = "path"
fmtJSON = "json"
bufGenPrefix = "buf.gen."

// CMDGenerate generate command.
CMDGenerate Command = "generate"
CMDExport Command = "export"
CMDConfig Command = "config"
CMDDep Command = "dep"

specCacheNamespace = "generate.buf"
Expand All @@ -43,6 +47,7 @@ var (
commands = map[Command]struct{}{
CMDGenerate: {},
CMDExport: {},
CMDConfig: {},
CMDDep: {},
}

Expand Down Expand Up @@ -152,7 +157,7 @@ func (c Command) String() string {
// Update updates module dependencies.
// By default updates all dependencies unless one or more dependencies are specified.
func (b Buf) Update(ctx context.Context, modDir string) error {
files, err := xos.FindFilesExtension(modDir, xos.ProtoFile)
files, err := xos.FindFiles(modDir, xos.WithExtension(xos.ProtoFile))
if err != nil {
return err
}
Expand All @@ -167,9 +172,35 @@ func (b Buf) Update(ctx context.Context, modDir string) error {
return b.runCommand(ctx, cmd...)
}

// Migrate runs the buf Migrate command for the files in the app directory.
Pantani marked this conversation as resolved.
Show resolved Hide resolved
func (b Buf) Migrate(ctx context.Context, protoDir string) error {
yamlFiles, err := xos.FindFiles(protoDir, xos.WithExtension(xos.YAMLFile), xos.WithPrefix(bufGenPrefix))
if err != nil {
return err
}
ymlfiles, err := xos.FindFiles(protoDir, xos.WithExtension(xos.YMLFile), xos.WithPrefix(bufGenPrefix))
if err != nil {
return err
}
yamlFiles = append(yamlFiles, ymlfiles...)

flags := map[string]string{
flagWorkspace: ".",
}
if len(yamlFiles) > 0 {
flags[flagBufGenYaml] = strings.Join(yamlFiles, ",")
}

cmd, err := b.command(CMDConfig, flags, "migrate")
if err != nil {
return err
}
return b.runCommand(ctx, cmd...)
}

// Export runs the buf Export command for the files in the proto directory.
func (b Buf) Export(ctx context.Context, protoDir, output string) error {
files, err := xos.FindFilesExtension(protoDir, xos.ProtoFile)
files, err := xos.FindFiles(protoDir, xos.WithExtension(xos.ProtoFile))
if err != nil {
return err
}
Expand Down Expand Up @@ -202,7 +233,7 @@ func (b Buf) Generate(
}

// find all proto files into the path.
foundFiles, err := xos.FindFilesExtension(protoPath, xos.ProtoFile)
foundFiles, err := xos.FindFiles(protoPath, xos.WithExtension(xos.ProtoFile))
if err != nil || len(foundFiles) == 0 {
return err
}
Expand Down
10 changes: 3 additions & 7 deletions ignite/pkg/cosmosgen/generate_go.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ func (g *generator) protoPath() string {
}

func (g *generator) generateGoGo(ctx context.Context) error {
return g.generate(ctx, g.gogoTemplate(), g.goModPath)
}

func (g *generator) generate(ctx context.Context, template, fromPath string, excluded ...string) error {
// create a temporary dir to locate generated code under which later only some of them will be moved to the
// app's source code. this also prevents having leftover files in the app's source code or its parent dir - when
// command executed directly there - in case of an interrupt.
Expand All @@ -38,14 +34,14 @@ func (g *generator) generate(ctx context.Context, template, fromPath string, exc
ctx,
g.protoPath(),
tmp,
template,
cosmosbuf.ExcludeFiles(excluded...),
g.gogoTemplate(),
cosmosbuf.ExcludeFiles("*/module.proto"),
); err != nil {
return err
}

// move generated code for the app under the relative locations in its source code.
path := filepath.Join(tmp, fromPath)
path := filepath.Join(tmp, g.goModPath)
if _, err := os.Stat(path); err == nil {
err = copy.Copy(path, g.appPath)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion ignite/pkg/cosmosgen/generate_openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func (g *generator) generateOpenAPISpec(ctx context.Context) error {
return errors.Wrapf(err, "failed to generate openapi spec %s, probally you need to exclude some proto files", protoPath)
}

specs, err := xos.FindFilesExtension(dir, xos.JSONFile)
specs, err := xos.FindFiles(dir, xos.WithExtension(xos.JSONFile))
if err != nil {
return err
}
Expand Down
53 changes: 39 additions & 14 deletions ignite/pkg/xos/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,64 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
)

const (
JSONFile = "json"
ProtoFile = "proto"
YAMLFile = "yaml"
YMLFile = "yml"
)

func FindFiles(directory string) ([]string, error) {
type findFileOptions struct {
extension string
prefix string
}

type FindFileOptions func(o *findFileOptions)

func WithExtension(extension string) FindFileOptions {
julienrbrt marked this conversation as resolved.
Show resolved Hide resolved
return func(o *findFileOptions) {
o.extension = extension
}
}

func WithPrefix(prefix string) FindFileOptions {
return func(o *findFileOptions) {
o.prefix = prefix
}
}

// FindFiles searches for files in the specified directory based on the given options.
// It supports filtering files by extension and prefix. Returns a list of matching files or an error.
func FindFiles(directory string, options ...FindFileOptions) ([]string, error) {
opts := findFileOptions{}
for _, apply := range options {
apply(&opts)
}

files := make([]string, 0)
return files, filepath.Walk(directory, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}

if !info.IsDir() {
files = append(files, path)
// Filter by file extension if provided
if opts.extension != "" && filepath.Ext(path) != fmt.Sprintf(".%s", opts.extension) {
return nil // Skip files that don't match the extension
}
return nil
})
}

func FindFilesExtension(directory, extension string) ([]string, error) {
files := make([]string, 0)
return files, filepath.Walk(directory, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
// Filter by file prefix if provided
if opts.prefix != "" && !strings.HasPrefix(filepath.Base(path), opts.prefix) {
return nil // Skip files that don't match the prefix
}

// Add file to the result list if it is not a directory
if !info.IsDir() {
if filepath.Ext(path) == fmt.Sprintf(".%s", extension) {
files = append(files, path)
}
files = append(files, path)
}

return nil
})
}
Expand Down
68 changes: 62 additions & 6 deletions ignite/pkg/xos/files_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,44 +16,92 @@ func TestFindFiles(t *testing.T) {
name string
files []string
extension string
prefix string
want []string
err error
}{
{
name: "test 3 json files",
name: "test zero files",
files: []string{},
want: []string{},
err: nil,
},
{
name: "test one file",
files: []string{"file.json"},
want: []string{"file.json"},
err: nil,
},
{
name: "test 3 files",
files: []string{"file1.json", "file2.txt", "file3.json"},
want: []string{"file1.json", "file2.txt", "file3.json"},
err: nil,
},
{
name: "test file prefix",
files: []string{"file.prefix.test.json"},
prefix: "file.prefix",
want: []string{"file.prefix.test.json"},
err: nil,
},
{
name: "test bigger file prefix",
files: []string{"file.prefix.test.json"},
prefix: "file.prefix.test",
want: []string{"file.prefix.test.json"},
err: nil,
},
{
name: "test 3 files prefix",
files: []string{"test.file1.json", "test.file2.txt", "test.file3.json"},
prefix: "test.file",
want: []string{"test.file1.json", "test.file2.txt", "test.file3.json"},
err: nil,
},
{
name: "test 3 extension json files",
files: []string{"file1.json", "file2.txt", "file3.json", "file4.json"},
extension: "json",
want: []string{"file1.json", "file3.json", "file4.json"},
err: nil,
},
{
name: "test 3 json files with subfolder",
name: "test 3 extension json files with subfolder",
files: []string{"testdata/file1.json", "file2.txt", "foo/file3.json", "file4.json"},
extension: "json",
want: []string{"testdata/file1.json", "foo/file3.json", "file4.json"},
err: nil,
},
{
name: "test 1 txt files",
name: "test 1 extension txt files",
files: []string{"file1.json", "file2.txt", "file3.json", "file4.json"},
extension: "txt",
want: []string{"file2.txt"},
err: nil,
},
{
name: "test 1 json files",
name: "test 1 extension json files",
files: []string{"file1.json"},
extension: "json",
want: []string{"file1.json"},
err: nil,
},
{
name: "test no files",
name: "test invalid files extension",
files: []string{"file1.json", "file2.json", "file3.json", "file4.json"},
extension: "txt",
want: []string{},
err: nil,
},
{
name: "test file prefix and extension",
files: []string{"test.file1.json", "test.file2.txt", "test.file3.json"},
prefix: "test.file",
extension: "json",
want: []string{"test.file1.json", "test.file3.json"},
err: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -72,7 +120,15 @@ func TestFindFiles(t *testing.T) {
require.NoError(t, file.Close())
}

gotFiles, err := xos.FindFilesExtension(tempDir, tt.extension)
opts := make([]xos.FindFileOptions, 0)
if tt.prefix != "" {
opts = append(opts, xos.WithPrefix(tt.prefix))
}
if tt.extension != "" {
opts = append(opts, xos.WithExtension(tt.extension))
}

gotFiles, err := xos.FindFiles(tempDir, opts...)
if tt.err != nil {
require.Error(t, err)
require.ErrorIs(t, err, tt.err)
Expand Down
Loading
Loading