Blog Changelog

2022-11-20

Für das neue Design meines Blogs wollte ich eine Art Changelog mit einbauen. Da die Sourcen meines Blogs in einem Git Repo wohnen, ist es nahe liegend die Git Commit Histrory dafür zu verwenden. Also benötige ich ein Tool welches die Commit History in ein JSON Format konvertiert, um es anschließend mit einem Hugo Data Template zu verarbeiten.

Ich habe ein paar Tools auf Github gefunden die jedoch so komplex sind, das alleine das lesen der drölfzig Start oder Konfiguration Parameter längert dauert, als das Tool gleich selbst zu schreiben.

Im wesentlichen iteriert man einfach über die Git History und füllt eine eigene Struktur,


import (
	"github.com/go-git/go-git/v5"
)

type Commit struct {
	Time         time.Time
	ID           string
	Author       string
	Message      string
	ChangedFiles []string
}

// <snip>

commits := []Commit{}

err = history.ForEach(func(c *object.Commit) error {

	commit := Commit{
		ID:      c.ID().String(),
		Author:  c.Author.Name,
		Time:    c.Author.When,
		Message: strings.TrimRight(c.Message, "\n"),
	}

	if len(c.ParentHashes) > 0 {
		if parent, err := r.CommitObject(c.ParentHashes[0]); err == nil {
			if patch, err := parent.Patch(c); err == nil {
				for _, p := range patch.FilePatches() {
					if from, to := p.Files(); from != nil {
						commit.ChangedFiles = append(commit.ChangedFiles, from.Path())
					} else if to != from {
						commit.ChangedFiles = append(commit.ChangedFiles, to.Path())
					}
				}
			}
		}
	}

	commits = append(commits, commit)

	return nil
})

sortiert das so erzeugt Array nach Datum und marshalt das JSON Objekt.

sort.Slice(commits, func(i, j int) bool {
	return commits[i].Time.Unix() > commits[j].Time.Unix()
})

if out, err := json.MarshalIndent(commits, "", "  "); err == nil {
	fmt.Println(string(out))
}

Keine 100 Zeilen Code später war mein Konverter fertig. Vor dem finalen bauen des Blogs lasse ich ein Script automatisch laufen, welches dann die JSON Datei erzeugt.

changelog > ./data/_changelog.json

Und mit Hilfe von Hugo Data Templates baue ich die Changelog Seite.

{{ range $.Site.Data._changelog }}
	<ul class="history">
		<li>{{ time.Format "2006-01-02 15:04:05 Z07:00" .Time }}</li>
		<li>{{ .Message }}</li>
		<ul>
			{{ range .ChangedFiles}}
			<li>{{ . }}</li>
			{{ end}}
		</ul>
	</ul>
{{ end }}

Die Sourcen befinden sich auf Github.