@@ -3,10 +3,12 @@ package dependabot
3
3
import (
4
4
"bufio"
5
5
"encoding/json"
6
+ "errors"
7
+ "fmt"
6
8
"strings"
7
9
8
10
dependabot "github.com/paulvollmer/dependabot-config-go"
9
- "gopkg.in/yaml.v2 "
11
+ "gopkg.in/yaml.v3 "
10
12
)
11
13
12
14
type UpdateDependabotConfigResponse struct {
@@ -27,29 +29,79 @@ type UpdateDependabotConfigRequest struct {
27
29
Content string
28
30
}
29
31
32
+ // getIndentation returns the indentation level of the first list found in a given YAML string.
33
+ // If the YAML string is empty or invalid, or if no list is found, it returns an error.
34
+ func getIndentation (dependabotConfig string ) (int , error ) {
35
+ // Initialize an empty YAML node
36
+ t := yaml.Node {}
37
+
38
+ // Unmarshal the YAML string into the node
39
+ err := yaml .Unmarshal ([]byte (dependabotConfig ), & t )
40
+ if err != nil {
41
+ return 0 , fmt .Errorf ("unable to parse yaml: %w" , err )
42
+ }
43
+
44
+ // Retrieve the top node of the YAML document
45
+ topNode := t .Content
46
+ if len (topNode ) == 0 {
47
+ return 0 , errors .New ("file provided is empty or invalid" )
48
+ }
49
+
50
+ // Check for the first list and its indentation level
51
+ for _ , n := range topNode [0 ].Content {
52
+ if n .Value == "" && n .Tag == "!!seq" {
53
+ // Return the column of the first list found
54
+ return n .Column , nil
55
+ }
56
+ }
57
+
58
+ // Return an error if no list was found
59
+ return 0 , errors .New ("no list found in yaml" )
60
+ }
61
+
62
+ // UpdateDependabotConfig is used to update dependabot configuration and returns an UpdateDependabotConfigResponse.
30
63
func UpdateDependabotConfig (dependabotConfig string ) (* UpdateDependabotConfigResponse , error ) {
31
64
var updateDependabotConfigRequest UpdateDependabotConfigRequest
32
- json .Unmarshal ([]byte (dependabotConfig ), & updateDependabotConfigRequest )
65
+
66
+ // Handle error in json unmarshalling
67
+ err := json .Unmarshal ([]byte (dependabotConfig ), & updateDependabotConfigRequest )
68
+ if err != nil {
69
+ return nil , fmt .Errorf ("failed to unmarshal JSON from dependabotConfig: %v" , err )
70
+ }
71
+
33
72
inputConfigFile := []byte (updateDependabotConfigRequest .Content )
34
73
configMetadata := dependabot .New ()
35
- err : = configMetadata .Unmarshal (inputConfigFile )
74
+ err = configMetadata .Unmarshal (inputConfigFile )
36
75
if err != nil {
37
- return nil , err
76
+ return nil , fmt . Errorf ( "failed to unmarshal dependabot config: %v" , err )
38
77
}
39
78
79
+ indentation := 3
80
+
40
81
response := new (UpdateDependabotConfigResponse )
41
82
response .FinalOutput = updateDependabotConfigRequest .Content
42
83
response .OriginalInput = updateDependabotConfigRequest .Content
43
84
response .IsChanged = false
44
85
86
+ // Using strings.Builder for efficient string concatenation
87
+ var finalOutput strings.Builder
88
+ finalOutput .WriteString (response .FinalOutput )
89
+
45
90
if updateDependabotConfigRequest .Content == "" {
46
91
if len (updateDependabotConfigRequest .Ecosystems ) == 0 {
47
92
return response , nil
48
93
}
49
- response . FinalOutput = "version: 2\n updates:"
94
+ finalOutput . WriteString ( "version: 2\n updates:" )
50
95
} else {
51
- response .FinalOutput += "\n "
96
+ if ! strings .HasSuffix (response .FinalOutput , "\n " ) {
97
+ finalOutput .WriteString ("\n " )
98
+ }
99
+ indentation , err = getIndentation (string (inputConfigFile ))
100
+ if err != nil {
101
+ return nil , fmt .Errorf ("failed to get indentation: %v" , err )
102
+ }
52
103
}
104
+
53
105
for _ , Update := range updateDependabotConfigRequest .Ecosystems {
54
106
updateAlreadyExist := false
55
107
for _ , update := range configMetadata .Updates {
@@ -58,37 +110,56 @@ func UpdateDependabotConfig(dependabotConfig string) (*UpdateDependabotConfigRes
58
110
break
59
111
}
60
112
}
61
- if ! updateAlreadyExist {
62
- item := dependabot.Update {}
63
- item .PackageEcosystem = Update .PackageEcosystem
64
- item .Directory = Update .Directory
65
113
66
- schedule := dependabot.Schedule {}
67
- schedule .Interval = Update .Interval
68
-
69
- item .Schedule = schedule
70
- items := []dependabot.Update {}
71
- items = append (items , item )
114
+ if ! updateAlreadyExist {
115
+ item := dependabot.Update {
116
+ PackageEcosystem : Update .PackageEcosystem ,
117
+ Directory : Update .Directory ,
118
+ Schedule : dependabot.Schedule {Interval : Update .Interval },
119
+ }
120
+ items := []dependabot.Update {item }
72
121
addedItem , err := yaml .Marshal (items )
73
- data := string (addedItem )
122
+ if err != nil {
123
+ return nil , fmt .Errorf ("failed to marshal update items: %v" , err )
124
+ }
74
125
75
- data = addIndentation (data )
126
+ data , err : = addIndentation (string ( addedItem ), indentation )
76
127
if err != nil {
77
- return nil , err
128
+ return nil , fmt . Errorf ( "failed to add indentation: %v" , err )
78
129
}
79
- response . FinalOutput = response . FinalOutput + data
130
+ finalOutput . WriteString ( data )
80
131
response .IsChanged = true
81
132
}
82
133
}
83
134
135
+ // Set FinalOutput to the built string
136
+ response .FinalOutput = finalOutput .String ()
137
+
84
138
return response , nil
85
139
}
86
140
87
- func addIndentation (data string ) string {
141
+ // addIndentation adds a certain number of spaces to the start of each line in the input string.
142
+ // It returns a new string with the added indentation.
143
+ func addIndentation (data string , indentation int ) (string , error ) {
88
144
scanner := bufio .NewScanner (strings .NewReader (data ))
89
- finalData := "\n "
145
+ var finalData strings.Builder
146
+
147
+ // Create the indentation string
148
+ spaces := strings .Repeat (" " , indentation - 1 )
149
+
150
+ finalData .WriteString ("\n " )
151
+
152
+ // Add indentation to each line
90
153
for scanner .Scan () {
91
- finalData += " " + scanner .Text () + "\n "
154
+ finalData .WriteString (spaces )
155
+ finalData .WriteString (scanner .Text ())
156
+ finalData .WriteString ("\n " )
157
+ }
158
+
159
+ // Check for scanning errors
160
+ if err := scanner .Err (); err != nil {
161
+ return "" , fmt .Errorf ("error during scanning: %w" , err )
92
162
}
93
- return finalData
163
+
164
+ return finalData .String (), nil
94
165
}
0 commit comments