-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix Dependabot config indentation issue #2141
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,10 +3,12 @@ package dependabot | |
import ( | ||
"bufio" | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"strings" | ||
|
||
dependabot "github.com/paulvollmer/dependabot-config-go" | ||
"gopkg.in/yaml.v2" | ||
"gopkg.in/yaml.v3" | ||
) | ||
|
||
type UpdateDependabotConfigResponse struct { | ||
|
@@ -27,29 +29,79 @@ type UpdateDependabotConfigRequest struct { | |
Content string | ||
} | ||
|
||
// getIndentation returns the indentation level of the first list found in a given YAML string. | ||
// If the YAML string is empty or invalid, or if no list is found, it returns an error. | ||
func getIndentation(dependabotConfig string) (int, error) { | ||
// Initialize an empty YAML node | ||
t := yaml.Node{} | ||
|
||
// Unmarshal the YAML string into the node | ||
err := yaml.Unmarshal([]byte(dependabotConfig), &t) | ||
if err != nil { | ||
return 0, fmt.Errorf("unable to parse yaml: %w", err) | ||
} | ||
|
||
// Retrieve the top node of the YAML document | ||
topNode := t.Content | ||
if len(topNode) == 0 { | ||
return 0, errors.New("file provided is empty or invalid") | ||
} | ||
|
||
// Check for the first list and its indentation level | ||
for _, n := range topNode[0].Content { | ||
if n.Value == "" && n.Tag == "!!seq" { | ||
// Return the column of the first list found | ||
return n.Column, nil | ||
} | ||
} | ||
|
||
// Return an error if no list was found | ||
return 0, errors.New("no list found in yaml") | ||
} | ||
|
||
// UpdateDependabotConfig is used to update dependabot configuration and returns an UpdateDependabotConfigResponse. | ||
func UpdateDependabotConfig(dependabotConfig string) (*UpdateDependabotConfigResponse, error) { | ||
var updateDependabotConfigRequest UpdateDependabotConfigRequest | ||
json.Unmarshal([]byte(dependabotConfig), &updateDependabotConfigRequest) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
// Handle error in json unmarshalling | ||
err := json.Unmarshal([]byte(dependabotConfig), &updateDependabotConfigRequest) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to unmarshal JSON from dependabotConfig: %v", err) | ||
} | ||
|
||
inputConfigFile := []byte(updateDependabotConfigRequest.Content) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
configMetadata := dependabot.New() | ||
err := configMetadata.Unmarshal(inputConfigFile) | ||
err = configMetadata.Unmarshal(inputConfigFile) | ||
if err != nil { | ||
return nil, err | ||
return nil, fmt.Errorf("failed to unmarshal dependabot config: %v", err) | ||
} | ||
|
||
indentation := 3 | ||
|
||
response := new(UpdateDependabotConfigResponse) | ||
response.FinalOutput = updateDependabotConfigRequest.Content | ||
response.OriginalInput = updateDependabotConfigRequest.Content | ||
response.IsChanged = false | ||
|
||
// Using strings.Builder for efficient string concatenation | ||
var finalOutput strings.Builder | ||
finalOutput.WriteString(response.FinalOutput) | ||
|
||
if updateDependabotConfigRequest.Content == "" { | ||
if len(updateDependabotConfigRequest.Ecosystems) == 0 { | ||
return response, nil | ||
} | ||
response.FinalOutput = "version: 2\nupdates:" | ||
finalOutput.WriteString("version: 2\nupdates:") | ||
} else { | ||
response.FinalOutput += "\n" | ||
if !strings.HasSuffix(response.FinalOutput, "\n") { | ||
finalOutput.WriteString("\n") | ||
} | ||
indentation, err = getIndentation(string(inputConfigFile)) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get indentation: %v", err) | ||
} | ||
} | ||
|
||
for _, Update := range updateDependabotConfigRequest.Ecosystems { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
updateAlreadyExist := false | ||
for _, update := range configMetadata.Updates { | ||
|
@@ -58,37 +110,56 @@ func UpdateDependabotConfig(dependabotConfig string) (*UpdateDependabotConfigRes | |
break | ||
} | ||
} | ||
if !updateAlreadyExist { | ||
item := dependabot.Update{} | ||
item.PackageEcosystem = Update.PackageEcosystem | ||
item.Directory = Update.Directory | ||
|
||
schedule := dependabot.Schedule{} | ||
schedule.Interval = Update.Interval | ||
|
||
item.Schedule = schedule | ||
items := []dependabot.Update{} | ||
items = append(items, item) | ||
if !updateAlreadyExist { | ||
item := dependabot.Update{ | ||
PackageEcosystem: Update.PackageEcosystem, | ||
Directory: Update.Directory, | ||
Schedule: dependabot.Schedule{Interval: Update.Interval}, | ||
} | ||
items := []dependabot.Update{item} | ||
addedItem, err := yaml.Marshal(items) | ||
data := string(addedItem) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to marshal update items: %v", err) | ||
} | ||
|
||
data = addIndentation(data) | ||
data, err := addIndentation(string(addedItem), indentation) | ||
if err != nil { | ||
return nil, err | ||
return nil, fmt.Errorf("failed to add indentation: %v", err) | ||
} | ||
response.FinalOutput = response.FinalOutput + data | ||
finalOutput.WriteString(data) | ||
response.IsChanged = true | ||
} | ||
} | ||
|
||
// Set FinalOutput to the built string | ||
response.FinalOutput = finalOutput.String() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
return response, nil | ||
} | ||
|
||
func addIndentation(data string) string { | ||
// addIndentation adds a certain number of spaces to the start of each line in the input string. | ||
// It returns a new string with the added indentation. | ||
func addIndentation(data string, indentation int) (string, error) { | ||
scanner := bufio.NewScanner(strings.NewReader(data)) | ||
finalData := "\n" | ||
var finalData strings.Builder | ||
|
||
// Create the indentation string | ||
spaces := strings.Repeat(" ", indentation-1) | ||
|
||
finalData.WriteString("\n") | ||
|
||
// Add indentation to each line | ||
for scanner.Scan() { | ||
finalData += " " + scanner.Text() + "\n" | ||
finalData.WriteString(spaces) | ||
finalData.WriteString(scanner.Text()) | ||
finalData.WriteString("\n") | ||
} | ||
|
||
// Check for scanning errors | ||
if err := scanner.Err(); err != nil { | ||
return "", fmt.Errorf("error during scanning: %w", err) | ||
} | ||
return finalData | ||
|
||
return finalData.String(), nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
version: 2 | ||
updates: | ||
- package-ecosystem: github-actions | ||
directory: "/" | ||
schedule: | ||
interval: daily |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
version: 2 | ||
updates: | ||
- package-ecosystem: github-actions | ||
directory: "/" | ||
schedule: | ||
interval: daily | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,4 @@ updates: | |
# Files stored in `app` directory | ||
directory: "/app" | ||
schedule: | ||
interval: "daily" | ||
interval: "daily" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
version: 2 | ||
updates: | ||
- package-ecosystem: github-actions | ||
directory: "/" | ||
schedule: | ||
interval: daily | ||
|
||
- package-ecosystem: npm | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
directory: /sample | ||
schedule: | ||
interval: daily | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
version: 2 | ||
updates: | ||
- package-ecosystem: github-actions | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
directory: "/" | ||
schedule: | ||
interval: daily | ||
|
||
- package-ecosystem: npm | ||
directory: /sample | ||
schedule: | ||
interval: daily |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current library being used is from an older version of YAML. The new library is YAML V3, see 'gopkg.in/yaml.v3'. Replace the current import path with 'gopkg.in/yaml.v3' code line:gopkg.in/yaml.v2