func run()

in cmd/changelogger/main.go [105:220]


func run(cfg config) error {
	// config Validation
	if err := validateConfig(cfg); err != nil {
		return &appError{err: err, code: 1}
	}

	// Template parsing

	tplBytes, err := os.ReadFile(cfg.template)
	if err != nil {
		return &appError{
			err:  fmt.Errorf("failed opening template file: %w", err),
			code: 2,
		}
	}

	funcMap := template.FuncMap{
		"GitHubTracker": func(id string) string {
			baseURL := strings.TrimSuffix(cfg.baseURL, "/")
			return fmt.Sprintf("%s/issues/%s", baseURL, id)
		},
		"Version": func() string { return cfg.version },
		"Env":     os.Getenv,
	}
	tpl, err := template.New("changelog").Funcs(funcMap).Parse(string(tplBytes))
	if err != nil {
		return &appError{
			err:  fmt.Errorf("failed parsing template file contents: %w", err),
			code: 3,
		}
	}

	// Trim version prefix and walk the path.

	cleanVersion := cfg.version
	if strings.HasPrefix(cleanVersion, "v") {
		cleanVersion = strings.Replace(cleanVersion, "v", "", 1)
	}

	var changes changelogger.Changes
	changeValErr := multierror.NewPrefixed("invalid changelog entries")
	dir := filepath.Join(cfg.dir, cleanVersion)
	if err := filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if info.IsDir() {
			return nil
		}

		b, err := os.ReadFile(path)
		if err != nil {
			return fmt.Errorf("failed opening file %s: %w", path, err)
		}

		var change changelogger.Change
		if err := yaml.Unmarshal(b, &change); err != nil {
			return fmt.Errorf("failed decoding yaml file %s: %w", path, err)
		}

		// If there's no reference set in the file, use the file name.
		if change.Ref == "" {
			change.Ref = strings.Replace(info.Name(),
				filepath.Ext(info.Name()), "", 1,
			)
		}

		if !reflect.DeepEqual(change, changelogger.Change{}) {
			changes = append(changes, change)
		}

		if validateErr := change.Validate(info.Name()); validateErr != nil {
			changeValErr = changeValErr.Append(validateErr)
		}

		return nil
	}); err != nil {
		return &appError{
			err:  fmt.Errorf("failed walking the specified path: %w", err),
			code: 4,
		}
	}
	sort.Sort(changes)

	if len(changes) == 0 {
		return &appError{
			err:  fmt.Errorf("folder %s has no changelog files", dir),
			code: 5,
		}
	}

	if err := changeValErr.ErrorOrNil(); err != nil {
		return &appError{
			err:  err,
			code: 7,
		}
	}

	buf := new(bytes.Buffer)
	if err := tpl.Execute(buf, changes); err != nil {
		return &appError{
			err:  fmt.Errorf("failed executing the changelog template: %w", err),
			code: 8,
		}
	}

	if _, err := io.Copy(cfg.out, buf); err != nil {
		return &appError{
			err:  fmt.Errorf("failed copying the template output: %w", err),
			code: 9,
		}
	}

	return nil
}