Lots of changes to the website

This commit is contained in:
Blake Ridgway
2026-03-27 07:57:13 -05:00
parent 617624c179
commit 7e7480ecf9
33 changed files with 1539 additions and 184 deletions

View File

@@ -0,0 +1,111 @@
// Package changelog manages the infrastructure changelog log.
package changelog
import (
"encoding/json"
"fmt"
"os"
"sort"
"time"
)
// Categories available for changelog entries.
var Categories = []string{"hardware", "network", "software", "migration"}
// Entry is a single changelog entry.
type Entry struct {
ID string `json:"id"`
Date string `json:"date"` // YYYY-MM-DD
Title string `json:"title"`
Description string `json:"description"`
Category string `json:"category"` // hardware, network, software, migration
}
// Log holds all changelog entries.
type Log struct {
Entries []Entry `json:"entries"`
}
// Load reads the changelog from path. Returns an empty log if the file does not exist.
func Load(path string) (*Log, error) {
raw, err := os.ReadFile(path)
if err != nil {
if os.IsNotExist(err) {
return &Log{}, nil
}
return nil, err
}
var l Log
if err := json.Unmarshal(raw, &l); err != nil {
return nil, err
}
sort.Slice(l.Entries, func(i, j int) bool {
return l.Entries[i].Date > l.Entries[j].Date
})
return &l, nil
}
// save writes the log to path without sorting (internal use).
func save(path string, l *Log) error {
raw, err := json.MarshalIndent(l, "", " ")
if err != nil {
return err
}
return os.WriteFile(path, raw, 0644)
}
// Add appends a new entry and saves.
func Add(path string, e Entry) error {
l, err := Load(path)
if err != nil {
return err
}
e.ID = fmt.Sprintf("%d", time.Now().UnixNano())
l.Entries = append(l.Entries, e)
return save(path, l)
}
// Update replaces an entry by ID and saves.
func Update(path string, e Entry) error {
l, err := Load(path)
if err != nil {
return err
}
for i, entry := range l.Entries {
if entry.ID == e.ID {
l.Entries[i] = e
return save(path, l)
}
}
return fmt.Errorf("entry %s not found", e.ID)
}
// Delete removes an entry by ID and saves.
func Delete(path string, id string) error {
l, err := Load(path)
if err != nil {
return err
}
kept := l.Entries[:0]
for _, e := range l.Entries {
if e.ID != id {
kept = append(kept, e)
}
}
l.Entries = kept
return save(path, l)
}
// Get returns a single entry by ID.
func Get(path string, id string) (*Entry, error) {
l, err := Load(path)
if err != nil {
return nil, err
}
for _, e := range l.Entries {
if e.ID == id {
return &e, nil
}
}
return nil, fmt.Errorf("entry %s not found", id)
}