• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

astronomer / astro-cli / 27420483466

12 Jun 2026 02:00PM UTC coverage: 45.091% (+5.3%) from 39.756%
27420483466

Pull #2132

github

web-flow
Merge 454c868d6 into f328416b4
Pull Request #2132: Migrate release process to GitHub Actions with RC support and post-release automation

25417 of 56368 relevant lines covered (45.09%)

7.99 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.63
/cloud/deployment/deployment_variable.go
1
package deployment
2

3
import (
4
        "bufio"
5
        "fmt"
6
        "io"
7
        "os"
8
        "slices"
9
        "strconv"
10
        "strings"
11

12
        "github.com/pkg/errors"
13

14
        "github.com/astronomer/astro-cli/astro-client-v1"
15
        "github.com/astronomer/astro-cli/pkg/printutil"
16
)
17

18
var (
19
        errVarBool         = false
20
        errVarCreateUpdate = errors.New(
21
                "there was an error while creating or updating one or more of the environment variables. Check the command output above for more information",
22
        )
23
)
24

25
const maskedSecret = "****"
26

27
func VariableList(deploymentID, variableKey, ws, envFile, deploymentName string, useEnvFile bool, astroV1Client astrov1.APIClient, out io.Writer) error {
6✔
28
        environmentVariablesObjects := []astrov1.DeploymentEnvironmentVariable{}
6✔
29

6✔
30
        // get deployment
6✔
31
        currentDeployment, err := GetDeployment(ws, deploymentID, deploymentName, false, nil, astroV1Client)
6✔
32
        if err != nil {
8✔
33
                return err
2✔
34
        }
2✔
35

36
        if currentDeployment.EnvironmentVariables != nil {
8✔
37
                environmentVariablesObjects = *currentDeployment.EnvironmentVariables
4✔
38
        }
4✔
39
        if variableKey != "" {
7✔
40
                environmentVariablesObjects = slices.DeleteFunc(environmentVariablesObjects, func(v astrov1.DeploymentEnvironmentVariable) bool {
6✔
41
                        return v.Key != variableKey
3✔
42
                })
3✔
43
        }
44

45
        // open env file
46
        if useEnvFile {
5✔
47
                err = writeVarToFile(environmentVariablesObjects, envFile)
1✔
48
                if err != nil {
2✔
49
                        fmt.Fprintln(out, errors.Wrap(err, "unable to write environment variables to file"))
1✔
50
                }
1✔
51
        }
52
        if len(environmentVariablesObjects) == 0 {
6✔
53
                fmt.Fprintln(out, "\nNo variables found")
2✔
54
                return nil
2✔
55
        }
2✔
56

57
        makeVarTable(environmentVariablesObjects).Print(out)
2✔
58

2✔
59
        return nil
2✔
60
}
61

62
func makeVarTable(vars []astrov1.DeploymentEnvironmentVariable) *printutil.Table {
6✔
63
        table := printutil.Table{
6✔
64
                Padding:        []int{5, 30, 30, 50},
6✔
65
                DynamicPadding: true,
6✔
66
                Header:         []string{"#", "KEY", "VALUE", "SECRET"},
6✔
67
        }
6✔
68
        for i, variable := range vars {
16✔
69
                var value string
10✔
70

10✔
71
                if variable.IsSecret {
16✔
72
                        value = maskedSecret
6✔
73
                } else if variable.Value != nil {
14✔
74
                        value = *variable.Value
4✔
75
                }
4✔
76
                table.AddRow([]string{strconv.Itoa(i + 1), variable.Key, value, strconv.FormatBool(variable.IsSecret)}, false)
10✔
77
        }
78
        return &table
6✔
79
}
80

81
// this function modifies a deployment's environment variable object
82
// it is used to create and update deployment's environment variables
83
func VariableModify(
84
        deploymentID, variableKey, variableValue, ws, envFile, deploymentName string,
85
        variableList []string,
86
        useEnvFile, makeSecret, updateVars bool,
87
        astroV1Client astrov1.APIClient,
88
        out io.Writer,
89
) error {
9✔
90
        environmentVariablesObjects := []astrov1.DeploymentEnvironmentVariable{}
9✔
91

9✔
92
        // get deployment
9✔
93
        currentDeployment, err := GetDeployment(ws, deploymentID, deploymentName, false, nil, astroV1Client)
9✔
94
        if err != nil {
12✔
95
                return err
3✔
96
        }
3✔
97

98
        // build query input
99
        oldEnvironmentVariables := []astrov1.DeploymentEnvironmentVariable{}
6✔
100
        if currentDeployment.EnvironmentVariables != nil {
12✔
101
                oldEnvironmentVariables = *currentDeployment.EnvironmentVariables
6✔
102
        }
6✔
103

104
        newEnvironmentVariables := make([]astrov1.DeploymentEnvironmentVariableRequest, 0)
6✔
105
        oldKeyList := make([]string, 0)
6✔
106

6✔
107
        // add old variables to update
6✔
108
        for i := range oldEnvironmentVariables {
16✔
109
                oldEnvironmentVariable := astrov1.DeploymentEnvironmentVariableRequest{
10✔
110
                        IsSecret: oldEnvironmentVariables[i].IsSecret,
10✔
111
                        Key:      oldEnvironmentVariables[i].Key,
10✔
112
                        Value:    oldEnvironmentVariables[i].Value,
10✔
113
                }
10✔
114
                newEnvironmentVariables = append(newEnvironmentVariables, oldEnvironmentVariable)
10✔
115
                oldKeyList = append(oldKeyList, oldEnvironmentVariables[i].Key)
10✔
116
        }
10✔
117

118
        // add new variable from flag
119
        if variableKey != "" && variableValue != "" {
9✔
120
                newEnvironmentVariables = addVariable(oldKeyList, oldEnvironmentVariables, newEnvironmentVariables, variableKey, variableValue, updateVars, makeSecret, out)
3✔
121
        }
3✔
122
        if variableValue == "" && variableKey != "" {
7✔
123
                fmt.Fprintf(out, "Variable with key %s not created or updated\nYou must provide a variable value", variableKey)
1✔
124
                errVarBool = true
1✔
125
        }
1✔
126
        if variableValue != "" && variableKey == "" {
7✔
127
                fmt.Fprintf(out, "Variable with value %s not created or updated with flags\nYou must provide a variable key", variableValue)
1✔
128
                errVarBool = true
1✔
129
        }
1✔
130
        // add new variables from list of variables provided through args
131
        if len(variableList) > 0 {
6✔
132
                newEnvironmentVariables = addVariablesFromArgs(oldKeyList, oldEnvironmentVariables, newEnvironmentVariables, variableList, updateVars, makeSecret, out)
×
133
        }
×
134
        // add new variables from file
135
        if useEnvFile {
6✔
136
                newEnvironmentVariables = addVariablesFromFile(envFile, oldKeyList, oldEnvironmentVariables, newEnvironmentVariables, updateVars, makeSecret)
×
137
        }
×
138

139
        // update deployment
140
        err = Update(currentDeployment.Id, "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 0, 0, []astrov1.WorkerQueueRequest{}, []astrov1.HybridWorkerQueueRequest{}, newEnvironmentVariables, nil, nil, nil, false, astroV1Client)
6✔
141
        if err != nil {
7✔
142
                return err
1✔
143
        }
1✔
144
        deployment, err := GetDeploymentByID("", currentDeployment.Id, astroV1Client)
5✔
145
        if err != nil {
5✔
146
                return err
×
147
        }
×
148
        if deployment.EnvironmentVariables != nil {
10✔
149
                environmentVariablesObjects = *deployment.EnvironmentVariables
5✔
150
        }
5✔
151

152
        if len(environmentVariablesObjects) == 0 {
6✔
153
                fmt.Fprintln(out, "\nNo variables for this Deployment")
1✔
154
        } else {
5✔
155
                fmt.Fprintln(out, "\nUpdated list of your Deployment's variables:")
4✔
156
                makeVarTable(environmentVariablesObjects).Print(out)
4✔
157
        }
4✔
158
        if errVarBool {
8✔
159
                return errVarCreateUpdate
3✔
160
        }
3✔
161

162
        return nil
2✔
163
}
164

165
func contains(elems []string, v string) (exist bool, num int) {
16✔
166
        for i, s := range elems {
32✔
167
                if v == s {
26✔
168
                        return true, i
10✔
169
                }
10✔
170
        }
171
        return false, 0
6✔
172
}
173

174
// readLines reads a whole file into memory and returns a slice of its lines.
175
func readLines(path string) ([]string, error) {
5✔
176
        file, err := os.Open(path)
5✔
177
        if err != nil {
5✔
178
                return nil, err
×
179
        }
×
180
        defer file.Close()
5✔
181

5✔
182
        var lines []string
5✔
183
        scanner := bufio.NewScanner(file)
5✔
184
        for scanner.Scan() {
10✔
185
                lines = append(lines, scanner.Text())
5✔
186
        }
5✔
187
        return lines, scanner.Err()
5✔
188
}
189

190
// writes vars from cloud into a file
191
func writeVarToFile(environmentVariablesObjects []astrov1.DeploymentEnvironmentVariable, envFile string) error {
3✔
192
        f, err := os.OpenFile(envFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) //nolint:mnd
3✔
193
        if err != nil {
4✔
194
                return err
1✔
195
        }
1✔
196

197
        defer f.Close()
2✔
198

2✔
199
        for _, variable := range environmentVariablesObjects {
4✔
200
                var value string
2✔
201
                if variable.IsSecret {
3✔
202
                        value = " # secret"
1✔
203
                } else if variable.Value != nil {
3✔
204
                        value = *variable.Value
1✔
205
                }
1✔
206
                _, err := f.WriteString("\n" + variable.Key + "=" + value)
2✔
207
                if err != nil {
2✔
208
                        fmt.Fprintf(os.Stderr, "unable to write variable %s to file:\n%s\n", variable.Key, err)
×
209
                }
×
210
        }
211
        fmt.Printf("\nThe following environment variables were saved to the file %s,\nsecret environment variables were saved only with a key:\n\n", envFile)
2✔
212
        return nil
2✔
213
}
214

215
// Add variables
216
func addVariable(oldKeyList []string, oldEnvironmentVariables []astrov1.DeploymentEnvironmentVariable, newEnvironmentVariables []astrov1.DeploymentEnvironmentVariableRequest, variableKey, variableValue string, updateVars, makeSecret bool, out io.Writer) []astrov1.DeploymentEnvironmentVariableRequest {
9✔
217
        var newEnvironmentVariable astrov1.DeploymentEnvironmentVariableRequest
9✔
218
        exist, num := contains(oldKeyList, variableKey)
9✔
219
        switch {
9✔
220
        case exist && !updateVars: // don't update variable
4✔
221
                fmt.Fprintf(out, "key %s already exists, skipping creation. Use the update command to update existing variables\n", variableKey)
4✔
222
        case exist && updateVars: // update variable
3✔
223
                fmt.Fprintf(out, "updating variable %s \n", variableKey)
3✔
224
                secret := makeSecret
3✔
225
                if !makeSecret { // you can only make variables secret a user can't make them not secret
6✔
226
                        secret = oldEnvironmentVariables[num].IsSecret
3✔
227
                }
3✔
228
                newEnvironmentVariable = astrov1.DeploymentEnvironmentVariableRequest{
3✔
229
                        IsSecret: secret,
3✔
230
                        Key:      oldEnvironmentVariables[num].Key,
3✔
231
                        Value:    &variableValue,
3✔
232
                }
3✔
233
                newEnvironmentVariables[num] = newEnvironmentVariable
3✔
234
        default:
2✔
235
                newFileEnvironmentVariable := astrov1.DeploymentEnvironmentVariableRequest{
2✔
236
                        IsSecret: makeSecret,
2✔
237
                        Key:      variableKey,
2✔
238
                        Value:    &variableValue,
2✔
239
                }
2✔
240
                newEnvironmentVariables = append(newEnvironmentVariables, newFileEnvironmentVariable)
2✔
241
                fmt.Printf("adding variable %s\n", variableKey)
2✔
242
        }
243
        return newEnvironmentVariables
9✔
244
}
245

246
func addVariablesFromArgs(oldKeyList []string, oldEnvironmentVariables []astrov1.DeploymentEnvironmentVariable, newEnvironmentVariables []astrov1.DeploymentEnvironmentVariableRequest, variableList []string, updateVars, makeSecret bool, out io.Writer) []astrov1.DeploymentEnvironmentVariableRequest {
4✔
247
        var key string
4✔
248
        var val string
4✔
249
        // validate each key-value pair and add it to the new variables list
4✔
250
        for i := range variableList {
12✔
251
                // split pair
8✔
252
                pair := strings.SplitN(variableList[i], "=", 2)
8✔
253
                if len(pair) == 2 {
14✔
254
                        key = pair[0]
6✔
255
                        val = pair[1]
6✔
256
                        if key == "" || val == "" {
8✔
257
                                fmt.Printf("Input %s has blank key or value\n", variableList[i])
2✔
258
                                errVarBool = true
2✔
259
                                continue
2✔
260
                        }
261
                } else {
2✔
262
                        fmt.Printf("Input %s is not a valid key value pair, should be of the form key=value\n", variableList[i])
2✔
263
                        errVarBool = true
2✔
264
                        continue
2✔
265
                }
266
                newEnvironmentVariables = addVariable(oldKeyList, oldEnvironmentVariables, newEnvironmentVariables, key, val, updateVars, makeSecret, out)
4✔
267
        }
268
        return newEnvironmentVariables
4✔
269
}
270

271
// Add variables from file
272
func addVariablesFromFile(envFile string, oldKeyList []string, oldEnvironmentVariables []astrov1.DeploymentEnvironmentVariable, newEnvironmentVariables []astrov1.DeploymentEnvironmentVariableRequest, updateVars, makeSecret bool) []astrov1.DeploymentEnvironmentVariableRequest {
4✔
273
        newKeyList := make([]string, 0)
4✔
274
        vars, err := readLines(envFile)
4✔
275
        if err != nil {
4✔
276
                fmt.Printf("unable to read file %s :\n", envFile)
×
277
                fmt.Println(err)
×
278
        }
×
279
        for i := range vars {
8✔
280
                if strings.HasPrefix(vars[i], "#") {
4✔
281
                        continue
×
282
                }
283
                if vars[i] == "" {
4✔
284
                        continue
×
285
                }
286
                if len(strings.SplitN(vars[i], "=", 2)) == 1 { //nolint:mnd
5✔
287
                        fmt.Printf("%s is an improperly formatted variable, no variable created\n", vars[i])
1✔
288
                        errVarBool = true
1✔
289
                        continue
1✔
290
                }
291
                key := strings.SplitN(vars[i], "=", 2)[0]   //nolint:mnd
3✔
292
                value := strings.SplitN(vars[i], "=", 2)[1] //nolint:mnd
3✔
293
                if key == "" {
3✔
294
                        fmt.Printf("empty key! skipping creating variable with key: %s\n", key)
×
295
                        errVarBool = true
×
296
                        continue
×
297
                }
298
                if value == "" {
3✔
299
                        fmt.Printf("empty value! skipping creating variable with key: %s\n", key)
×
300
                        errVarBool = true
×
301
                        continue
×
302
                }
303
                // check if key is listed twice in file
304
                existFile, _ := contains(newKeyList, key)
3✔
305
                if existFile {
3✔
306
                        fmt.Printf("key %s already exists within the file specified, skipping creation\n", key)
×
307
                        errVarBool = true
×
308
                        continue
×
309
                }
310

311
                fmt.Printf("Cleaning quotes and whitespaces from variable %s", key)
3✔
312
                value = strings.Trim(value, `"`)
3✔
313
                value = strings.Trim(value, `'`)
3✔
314
                value = strings.TrimSpace(value)
3✔
315

3✔
316
                // check if key already exists
3✔
317
                exist, num := contains(oldKeyList, key)
3✔
318
                if exist {
5✔
319
                        if !updateVars { // only update a variable if a user specifys
3✔
320
                                fmt.Printf("key %s already exists skipping creation use the --update flag to update old variables\n", key)
1✔
321
                                errVarBool = true
1✔
322
                                continue
1✔
323
                        }
324
                        // update variable
325
                        fmt.Printf("updating variable %s \n", key)
1✔
326
                        secret := makeSecret
1✔
327
                        if !makeSecret { // you can only make variables secret a user can't make them not secret
2✔
328
                                secret = oldEnvironmentVariables[num].IsSecret
1✔
329
                        }
1✔
330

331
                        newEnvironmentVariables[num] = astrov1.DeploymentEnvironmentVariableRequest{
1✔
332
                                IsSecret: secret,
1✔
333
                                Key:      oldEnvironmentVariables[num].Key,
1✔
334
                                Value:    &value,
1✔
335
                        }
1✔
336
                        newKeyList = append(newKeyList, key)
1✔
337
                        continue
1✔
338
                }
339
                newFileEnvironmentVariable := astrov1.DeploymentEnvironmentVariableRequest{
1✔
340
                        IsSecret: makeSecret,
1✔
341
                        Key:      key,
1✔
342
                        Value:    &value,
1✔
343
                }
1✔
344
                newEnvironmentVariables = append(newEnvironmentVariables, newFileEnvironmentVariable)
1✔
345
                newKeyList = append(newKeyList, key)
1✔
346
                fmt.Printf("adding variable %s\n", key)
1✔
347
        }
348
        return newEnvironmentVariables
4✔
349
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc