authelia/cmd/authelia-gen/cmd_adr.go

158 lines
3.6 KiB
Go

package main
import (
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"
"time"
"github.com/spf13/cobra"
)
func newADRCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "adr",
Short: "Generate an Architecture Decision Record",
DisableAutoGenTag: true,
}
cmd.AddCommand(newADRAddCmd())
return cmd
}
func newADRAddCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "add",
Short: "Add an Architecture Decision Record",
RunE: adrAddRunE,
DisableAutoGenTag: true,
}
cmd.Flags().String("title", "", "sets the title of the record")
cmd.Flags().String("status", "", "sets the status of the record")
cmd.Flags().String("context", "", "sets the context of the record")
cmd.Flags().String("proposed-design", "", "sets the proposed design of the record")
cmd.Flags().String("decision", "", "sets the decision of the record")
cmd.Flags().String("consequences", "", "sets the consequences of the record")
cmd.Flags().IntSlice("related-adrs", nil, "sets the related adrs of the record")
return cmd
}
//nolint:gocyclo
func adrAddRunE(cmd *cobra.Command, args []string) (err error) {
var adrs string
if adrs, err = getPFlagPath(cmd.Flags(), cmdFlagRoot, cmdFlagDocs, cmdFlagDocsContent, cmdFlagDocsADR); err != nil {
return err
}
c := filepath.Join(adrs, ".adr.config.json")
var raw []byte
if raw, err = os.ReadFile(c); err != nil {
return fmt.Errorf("error opening adr config: %w", err)
}
var config ArchitectureDesignRecordConfig
if err = json.Unmarshal(raw, &config); err != nil {
return fmt.Errorf("error parsing adr config: %w", err)
}
data := &ArchitectureDesignRecordTmpl{
ADR: config.NextID,
Weight: 1000 + config.NextID,
Date: time.Now().Format(dateFmtYAML),
DateISO: time.Now().Format(time.DateOnly),
DateHuman: time.Now().Format("January 2, 2006"),
}
if data.Title, err = cmd.Flags().GetString("title"); err != nil {
return err
}
if data.Status, err = cmd.Flags().GetString("status"); err != nil {
return err
}
if data.Context, err = cmd.Flags().GetString("context"); err != nil {
return err
}
if data.ProposedDesign, err = cmd.Flags().GetString("proposed-design"); err != nil {
return err
}
if data.Decision, err = cmd.Flags().GetString("decision"); err != nil {
return err
}
if data.Consequences, err = cmd.Flags().GetString("consequences"); err != nil {
return err
}
if data.RelatedADRs, err = cmd.Flags().GetIntSlice("related-adrs"); err != nil {
return err
}
for _, related := range data.RelatedADRs {
if related >= config.NextID {
return fmt.Errorf("related adr %d does not exist yet", related)
}
}
fp := filepath.Join(adrs, fmt.Sprintf("%d.md", data.ADR))
var f *os.File
if f, err = os.Create(fp); err != nil {
return fmt.Errorf("error opening file for adr: %w", err)
}
defer f.Close()
if err = tmplADR.Execute(f, data); err != nil {
return fmt.Errorf("error executing template: %w", err)
}
config.NextID += 1
if raw, err = json.Marshal(config); err != nil {
return fmt.Errorf("error serializing config: %w", err)
}
if err = os.WriteFile(c, raw, 0600); err != nil {
return fmt.Errorf("error writing config: %w", err)
}
gitadd := exec.Command("git", "add", fp)
return gitadd.Run()
}
type ArchitectureDesignRecordConfig struct {
NextID int `json:"next_id"`
}
type ArchitectureDesignRecordTmpl struct {
ADR int
Weight int
Date string
DateISO string
DateHuman string
Title string
Status string
Context string
ProposedDesign string
Decision string
Consequences string
RelatedADRs []int
}