github.com/mentimeter/morty@v1.2.2-0.20221012065510-5596adecd154/mortems/mortems.go (about) 1 package mortems 2 3 import ( 4 _ "embed" 5 "encoding/json" 6 "fmt" 7 "strings" 8 ) 9 10 //go:embed install_morty 11 var installScriptContent string 12 13 type MortemCollector struct { 14 Repo RepoFileService 15 Reporter ReportingService 16 previousMortems []MortemData 17 nextMortems []MortemData 18 } 19 20 func NewMortemCollector(fileService RepoFileService) MortemCollector { 21 return MortemCollector{fileService, nil, []MortemData{}, []MortemData{}} 22 } 23 24 func NewMortemReportingCollector(fileService RepoFileService, reportingService ReportingService) MortemCollector { 25 return MortemCollector{fileService, reportingService, []MortemData{}, []MortemData{}} 26 } 27 28 func (m *MortemCollector) Check() (RepoFiles, error) { 29 newFiles := RepoFiles{} 30 31 existingFiles, err := m.Repo.GetFiles() 32 if err != nil { 33 return RepoFiles{}, err 34 } 35 36 templatePath := "post-mortems/template.md" 37 templateFile := existingFiles.GetFile(templateContent) 38 39 if templateFile == nil || templateFile.GetContent() != templateContent { 40 newFiles.AddFile(templatePath, templateContent) 41 } 42 43 howToPath := "post-mortems/README.md" 44 howToFile := existingFiles.GetFile(howToPath) 45 46 if howToFile == nil || howToFile.GetContent() != howToContent { 47 newFiles.AddFile(howToPath, howToContent) 48 } 49 50 installScriptPath := "install_morty" 51 installScriptFile := existingFiles.GetFile(installScriptPath) 52 53 if installScriptFile == nil || installScriptFile.GetContent() != installScriptContent { 54 newFiles.AddExecutableFile(installScriptPath, installScriptContent) 55 } 56 57 databasePath := "mortems.json" 58 modifiedDatabase := false 59 60 databaseFile := existingFiles.GetFile(databasePath) 61 if databaseFile == nil { 62 modifiedDatabase = true 63 databaseFile = &File{ 64 Path: databasePath, 65 Mode: "100644", 66 Type: "blob", 67 Content: "[]", 68 } 69 } 70 71 databaseBytes := []byte(databaseFile.GetContent()) 72 73 err = json.Unmarshal(databaseBytes, &m.previousMortems) 74 if err != nil { 75 return RepoFiles{}, fmt.Errorf("could not load database from file: %w", err) 76 } 77 78 for _, file := range existingFiles.Files { 79 if strings.HasPrefix(file.GetPath(), "post-mortems/") && 80 !strings.HasPrefix(file.GetPath(), "post-mortems/images/") && 81 file.GetPath() != howToPath && 82 file.GetPath() != templatePath { 83 modifiedDatabase = true 84 85 mortem, err := NewMortemData(file.GetContent(), file.GetPath()) 86 if err != nil { 87 return RepoFiles{}, fmt.Errorf("could not parse data from mortem %s: %w", file.GetPath(), err) 88 } 89 90 m.nextMortems = append(m.nextMortems, mortem) 91 } 92 } 93 94 readmePath := "README.md" 95 readmeFile := existingFiles.GetFile(readmePath) 96 readmeContent := GenerateReadme(m.nextMortems) 97 98 if readmeFile == nil || readmeFile.GetContent() != readmeContent { 99 newFiles.AddFile(readmePath, readmeContent) 100 } 101 102 databaseBytes, err = json.Marshal(m.nextMortems) 103 if err != nil { 104 return RepoFiles{}, fmt.Errorf("could not marshal database to json: %w", err) 105 } 106 107 databaseString := string(databaseBytes) 108 109 if modifiedDatabase { 110 newFiles.AddFile(databasePath, databaseString) 111 } 112 113 return newFiles, nil 114 115 } 116 117 func (m *MortemCollector) Collect() error { 118 newFiles, err := m.Check() 119 if err != nil { 120 return fmt.Errorf("could not check files, there might be a parsing error: %w", err) 121 } 122 123 if m.Reporter != nil { 124 toReport := diffMortems(m.previousMortems, m.nextMortems) 125 for _, report := range toReport { 126 127 m.Reporter.ReportSeverity(report.Severity) 128 m.Reporter.ReportDetect(report.Detect, report.Severity) 129 m.Reporter.ReportResolve(report.Resolve, report.Severity) 130 m.Reporter.ReportDowntime(report.Downtime, report.Severity) 131 } 132 } 133 134 if newFiles.Size() > 0 { 135 err := m.Repo.CommitNewFiles(&newFiles) 136 if err != nil { 137 return fmt.Errorf("could not commit new files: %w", err) 138 } 139 } 140 141 return nil 142 } 143 144 func diffMortems(old []MortemData, new []MortemData) []MortemData { 145 diff := []MortemData{} 146 for _, newMortem := range new { 147 exists := false 148 for _, oldMortem := range old { 149 if oldMortem == newMortem { 150 exists = true 151 } 152 } 153 if !exists { 154 diff = append(diff, newMortem) 155 } 156 } 157 158 return diff 159 }