Skip to content

Commit bbf67d8

Browse files
Adding new functions and updating Update and Delete methods.
1 parent 7fdd7d8 commit bbf67d8

File tree

1 file changed

+136
-14
lines changed

1 file changed

+136
-14
lines changed

harness/variables.go

Lines changed: 136 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package harness
22

33
import (
4+
"bufio"
45
"fmt"
56
"os"
67
"path/filepath"
@@ -20,28 +21,45 @@ const (
2021
// MetadataFile is the key for the file that stores metadata associated with an error, such as details about the error's source or context.
2122
MetadataFile = "ERROR_METADATA_FILE"
2223

23-
// DroneOutputFile is the key for the file where output can exported and utilized in the subsequent steps in Harness CI pipeline.
24+
// DroneOutputFile is the key for the file where outputs can be exported and utilized in the subsequent steps in Harness CI pipeline.
2425
DroneOutputFile = "DRONE_OUTPUT"
26+
27+
// HarnessOutputSecretFile is the key for the file where secrets can be exported and utilized in the subsequent steps in Harness CI pipeline.
28+
HarnessOutputSecretFile = "HARNESS_OUTPUT_SECRET_FILE"
2529
)
2630

27-
// SetSecret sets a new secret by adding it to the DRONE_OUTPUT file
31+
// SetSecret sets a new secret by adding it to the HARNESS_OUTPUT_SECRET_FILE file
2832
func SetSecret(name, value string) error {
29-
return WriteEnvToOutputFile(DroneOutputFile, name, value)
33+
return WriteEnvToOutputFile(HarnessOutputSecretFile, name, value)
3034
}
3135

32-
// UpdateSecret updates an existing secret with a new value in the DRONE_OUTPUT file
36+
// UpdateSecret overwrites the value of an existing secret.
3337
func UpdateSecret(name, value string) error {
34-
return WriteEnvToOutputFile(DroneOutputFile, name, value)
38+
return UpdateOrRemoveKeyValue(HarnessOutputSecretFile, name, value, false)
3539
}
3640

37-
// DeleteSecret removes a secret by setting it to an empty value in the DRONE_OUTPUT file
41+
// DeleteSecret removes a secret from the file entirely.
3842
func DeleteSecret(name string) error {
39-
return WriteEnvToOutputFile(DroneOutputFile, name, "")
43+
return UpdateOrRemoveKeyValue(HarnessOutputSecretFile, name, "", true)
4044
}
4145

42-
// SetError sets the error message and error code, writing them to the CI_ERROR_METADATA file
43-
// SetError sets the error message, error code, and error category, writing them to the CI_ERROR_METADATA file
44-
func SetError(message, code, category string) error {
46+
// SetOutput sets a new secret by adding it to the DRONE_OUTPUT file
47+
func SetOutput(name, value string) error {
48+
return WriteEnvToOutputFile(DroneOutputFile, name, value)
49+
}
50+
51+
// UpdateOutput overwrites the value of an existing output.
52+
func UpdateOutput(name, value string) error {
53+
return UpdateOrRemoveKeyValue(DroneOutputFile, name, value, false)
54+
}
55+
56+
// DeleteOutput removes an output from the file entirely.
57+
func DeleteOutput(name string) error {
58+
return UpdateOrRemoveKeyValue(DroneOutputFile, name, "", true)
59+
}
60+
61+
// SetErrorMetadata sets the error message, error code, and error category, writing them to the CI_ERROR_METADATA file
62+
func SetErrorMetadata(message, code, category string) error {
4563
// Write the error message
4664
if err := WriteEnvToOutputFile(MetadataFile, ErrorMessageKey, message); err != nil {
4765
return err
@@ -76,17 +94,17 @@ func WriteEnvToOutputFile(envVar, key, value string) error {
7694
// Write in .env format (KEY=VALUE)
7795
content = fmt.Sprintf("%s=%s\n", key, value)
7896
} else if ext == ".out" {
79-
// Write in .out format (export KEY="VALUE")
80-
content = fmt.Sprintf("%s \"%s\"\n", key, value)
97+
// Write in .out format (KEY VALUE)
98+
content = fmt.Sprintf("%s %s\n", key, value)
8199
} else {
82100
return fmt.Errorf("unsupported file extension: %s", ext)
83101
}
84102

85-
return writeToFile(filePath, content)
103+
return WriteToFile(filePath, content)
86104
}
87105

88106
// Helper function to append content to the file
89-
func writeToFile(filename, content string) error {
107+
func WriteToFile(filename, content string) error {
90108
f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
91109
if err != nil {
92110
return fmt.Errorf("failed to open file: %w", err)
@@ -100,3 +118,107 @@ func writeToFile(filename, content string) error {
100118

101119
return nil
102120
}
121+
122+
123+
// UpdateOrRemoveKeyValue updates or deletes a key-value pair in the specified file.
124+
func UpdateOrRemoveKeyValue(envVar, key, newValue string, delete bool) error {
125+
// Get the file path from the environment variable
126+
filePath := os.Getenv(envVar)
127+
if filePath == "" {
128+
return fmt.Errorf("environment variable %s is not set", envVar)
129+
}
130+
131+
// Determine the file extension to handle formats
132+
ext := strings.ToLower(filepath.Ext(filePath))
133+
134+
// Read the file contents into memory
135+
lines, err := ReadLines(filePath)
136+
if err != nil {
137+
return fmt.Errorf("failed to read file: %w", err)
138+
}
139+
140+
// Process lines
141+
var updatedLines []string
142+
found := false
143+
for _, line := range lines {
144+
k, v := ParseKeyValue(line, ext)
145+
if k == key {
146+
found = true
147+
if delete {
148+
continue // Skip the line to delete it
149+
}
150+
updatedLines = append(updatedLines, FormatKeyValue(k, newValue, ext))
151+
} else {
152+
updatedLines = append(updatedLines, FormatKeyValue(k, v, ext))
153+
}
154+
}
155+
156+
// Append new key-value if not found and not deleting
157+
if !found && !delete {
158+
updatedLines = append(updatedLines, FormatKeyValue(key, newValue, ext))
159+
}
160+
161+
// Write updated lines back to the file
162+
return WriteLines(filePath, updatedLines)
163+
}
164+
165+
// Helper function to read lines from a file.
166+
func ReadLines(filename string) ([]string, error) {
167+
file, err := os.Open(filename)
168+
if err != nil {
169+
return nil, err
170+
}
171+
defer file.Close()
172+
173+
var lines []string
174+
scanner := bufio.NewScanner(file)
175+
for scanner.Scan() {
176+
lines = append(lines, scanner.Text())
177+
}
178+
return lines, scanner.Err()
179+
}
180+
181+
// Helper function to write lines to a file.
182+
func WriteLines(filename string, lines []string) error {
183+
file, err := os.Create(filename)
184+
if err != nil {
185+
return fmt.Errorf("failed to create file: %w", err)
186+
}
187+
defer file.Close()
188+
189+
for _, line := range lines {
190+
_, err := file.WriteString(line + "\n")
191+
if err != nil {
192+
return fmt.Errorf("failed to write to file: %w", err)
193+
}
194+
}
195+
return nil
196+
}
197+
198+
// Helper function to parse a line into key and value, considering file format.
199+
func ParseKeyValue(line, ext string) (string, string) {
200+
if ext == ".env" {
201+
parts := strings.SplitN(line, "=", 2)
202+
if len(parts) == 2 {
203+
return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])
204+
}
205+
return strings.TrimSpace(parts[0]), ""
206+
} else if ext == ".out" {
207+
parts := strings.Fields(line)
208+
if len(parts) == 2 {
209+
return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])
210+
}
211+
return strings.TrimSpace(parts[0]), ""
212+
}
213+
return "", ""
214+
}
215+
216+
// Helper function to format a key-value pair as a line, considering file format.
217+
func FormatKeyValue(key, value, ext string) string {
218+
if ext == ".env" {
219+
return fmt.Sprintf("%s=%s", key, value)
220+
} else if ext == ".out" {
221+
return fmt.Sprintf("%s %s", key, value)
222+
}
223+
return ""
224+
}

0 commit comments

Comments
 (0)