package main import ( "bytes" "context" "fmt" "os" "path/filepath" "text/template" "git.unistack.org/unistack-org/pkgdash/internal/modules" yamlcodec "go.unistack.org/micro-codec-yaml/v4" envconfig "go.unistack.org/micro-config-env/v4" fileconfig "go.unistack.org/micro-config-file/v4" "go.unistack.org/micro/v4/config" "go.unistack.org/micro/v4/logger" "go.unistack.org/micro/v4/options" "golang.org/x/mod/modfile" "golang.org/x/mod/module" ) // https://docs.github.com/ru/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file var ( DefaultPullRequestTitle = `Bump {{.Name}} from {{.VersionOld}} to {{.VersionNew}}` DefaultPullRequestBody = `Bumps {{.Name}} from {{.VersionOld}} to {{.VersionNew}}.` ) type Config struct { PullRequestTitle string `json:"pull_request_title" yaml:"pull_request_title"` PullRequestBody string `json:"pull_request_body" yaml:"pull_request_body"` } var ( configFiles = []string{ "dependabot.yml", "pkgdash.yml", "pkgdash.yaml", } configDirs = []string{ ".gitea", ".github", ".gitlab", } repoMgmt = map[string]string{ ".gitea": "gitea", ".gogs": "gogs", ".github": "github", ".gitlab": "gitlab", } ) type Data struct { Modules []module.Version } func main() { var err error ctx, cancel := context.WithCancel(context.Background()) defer cancel() cfg := &Config{} if err = config.Load(ctx, []config.Config{ config.NewConfig( config.Struct(cfg), ), envconfig.NewConfig( config.Struct(cfg), ), }, config.LoadOverride(true), ); err != nil { logger.Fatalf(ctx, "failed to load config: %v", err) } for _, configDir := range configDirs { for _, configFile := range configFiles { c := fileconfig.NewConfig( config.AllowFail(true), config.Struct(cfg), options.Codec(yamlcodec.NewCodec()), fileconfig.Path(filepath.Join(configDir, configFile)), ) if err = c.Load(ctx, config.LoadOverride(true)); err != nil { logger.Fatalf(ctx, "failed to load config: %v", err) } } } path := "." if len(os.Args) > 1 { path = os.Args[1] } name, err := modules.FindModFile(path) if err != nil { panic(err) } buf, err := os.ReadFile(name) if err != nil { panic(err) } mfile, err := modfile.Parse(name, buf, nil) if err != nil { panic(err) } mvs := make(map[string]modules.Update) updateOptions := modules.UpdateOptions{ Pre: false, Major: false, Cached: true, OnUpdate: func(u modules.Update) { if u.Err != nil { logger.Errorf(ctx, "%s: failed: %v", u.Module.Path, u.Err) return } mvs[u.Module.Path] = u }, } for _, req := range mfile.Require { updateOptions.Modules = append(updateOptions.Modules, req.Mod) } modules.Updates(updateOptions) data := &Data{Modules: updateOptions.Modules} tplTitle, err := template.New("pull_request_title").Parse(cfg.PullRequestTitle) if err != nil { logger.Fatalf(ctx, "failed to parse template: %v", err) } wTitle := bytes.NewBuffer(nil) if err = tplTitle.Execute(wTitle, data); err != nil { logger.Fatalf(ctx, "failed to execute template: %v", err) } tplBody, err := template.New("pull_request_title").Parse(cfg.PullRequestTitle) if err != nil { logger.Fatalf(ctx, "failed to parse template: %v", err) } wBody := bytes.NewBuffer(nil) if err = tplBody.Execute(wBody, data); err != nil { logger.Fatalf(ctx, "failed to execute template: %v", err) } for path, u := range mvs { fmt.Printf("%s from %s to %s\n", path, u.Module.Version, u.Version) } } func getRepoMgmt() string { for _, configDir := range configDirs { _, err := os.Stat(configDir) if err != nil { continue } if name, ok := repoMgmt[configDir]; ok { return name } } return "unknown" } func giteaPullRequest(mods []module.Version) { }