Skip to content

Commit b8ba735

Browse files
authored
Merge pull request #339 from Bedrock-OSS/develop
Update 1.7.0
2 parents faecfea + 29ab6e1 commit b8ba735

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1272
-77
lines changed

main.go

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ the new filter is available in the Regolith.
166166
`
167167

168168
func main() {
169+
169170
// Schedule error handling
170171
var err error
171172
defer func() {
@@ -220,14 +221,19 @@ func main() {
220221
}
221222
subcommands := make([]*cobra.Command, 0)
222223

224+
// Add --env flag to root command
225+
var envFile string
226+
rootCmd.PersistentFlags().StringVar(&envFile, "env", "", "Path to a custom .env file to load")
227+
223228
var force bool
224229
// regolith init
225230
cmdInit := &cobra.Command{
226231
Use: "init",
227232
Short: "Initializes a Regolith project in current directory",
228233
Long: regolithInitDesc,
229234
Run: func(cmd *cobra.Command, _ []string) {
230-
err = regolith.Init(burrito.PrintStackTrace, force)
235+
env, _ := cmd.Flags().GetString("env")
236+
err = regolith.Init(burrito.PrintStackTrace, force, env)
231237
},
232238
}
233239
cmdInit.Flags().BoolVarP(
@@ -249,7 +255,8 @@ func main() {
249255
if cmd.Flags().Lookup("profile").Changed && len(profiles) == 0 {
250256
profiles = append(profiles, "default")
251257
}
252-
err = regolith.Install(filters, force || update, resolverRefresh, filterRefresh, profiles, burrito.PrintStackTrace)
258+
env, _ := cmd.Flags().GetString("env")
259+
err = regolith.Install(filters, force || update, resolverRefresh, filterRefresh, profiles, burrito.PrintStackTrace, env)
253260
},
254261
}
255262
cmdInstall.Flags().BoolVarP(
@@ -270,7 +277,8 @@ func main() {
270277
Short: "Installs all nonexistent or outdated filters defined in filterDefinitions list",
271278
Long: regolithInstallAllDesc,
272279
Run: func(cmd *cobra.Command, _ []string) {
273-
err = regolith.InstallAll(force, update, burrito.PrintStackTrace, filterRefresh)
280+
env, _ := cmd.Flags().GetString("env")
281+
err = regolith.InstallAll(force, update, burrito.PrintStackTrace, filterRefresh, env)
274282
},
275283
}
276284
cmdInstallAll.Flags().BoolVarP(
@@ -288,10 +296,13 @@ func main() {
288296
Long: regolithRunDesc,
289297
Run: func(cmd *cobra.Command, args []string) {
290298
var profile string
299+
var extraFilterArgs []string
291300
if len(args) != 0 {
292301
profile = args[0]
302+
extraFilterArgs = args[1:]
293303
}
294-
err = regolith.Run(profile, burrito.PrintStackTrace)
304+
env, _ := cmd.Flags().GetString("env")
305+
err = regolith.Run(profile, extraFilterArgs, burrito.PrintStackTrace, env)
295306
},
296307
}
297308
subcommands = append(subcommands, cmdRun)
@@ -303,10 +314,13 @@ func main() {
303314
Long: regolithWatchDesc,
304315
Run: func(cmd *cobra.Command, args []string) {
305316
var profile string
317+
var extraFilterArgs []string
306318
if len(args) != 0 {
307319
profile = args[0]
320+
extraFilterArgs = args[1:]
308321
}
309-
err = regolith.Watch(profile, burrito.PrintStackTrace)
322+
env, _ := cmd.Flags().GetString("env")
323+
err = regolith.Watch(profile, extraFilterArgs, burrito.PrintStackTrace, env)
310324
},
311325
}
312326
subcommands = append(subcommands, cmdWatch)
@@ -323,7 +337,8 @@ func main() {
323337
}
324338
filter := args[0]
325339
filterArgs := args[1:] // First arg is the filter name
326-
err = regolith.ApplyFilter(filter, filterArgs, burrito.PrintStackTrace)
340+
env, _ := cmd.Flags().GetString("env")
341+
err = regolith.ApplyFilter(filter, filterArgs, burrito.PrintStackTrace, env)
327342
},
328343
}
329344
subcommands = append(subcommands, cmdApplyFilter)
@@ -334,13 +349,12 @@ func main() {
334349
Short: " Print or modify the user configuration.",
335350
Long: regolithConfigDesc,
336351
Run: func(cmd *cobra.Command, args []string) {
337-
regolith.InitLogging(burrito.PrintStackTrace)
338-
defer regolith.ShutdownLogging()
339352
full, _ := cmd.Flags().GetBool("full")
340353
delete, _ := cmd.Flags().GetBool("delete")
341354
append, _ := cmd.Flags().GetBool("append")
342355
index, _ := cmd.Flags().GetInt("index")
343-
err = regolith.ManageConfig(burrito.PrintStackTrace, full, delete, append, index, args)
356+
env, _ := cmd.Flags().GetString("env")
357+
err = regolith.ManageConfig(burrito.PrintStackTrace, full, delete, append, index, args, env)
344358
},
345359
}
346360
cmdConfig.Flags().BoolP("full", "f", false, "When printing, prints the full configuration including default values.")
@@ -356,7 +370,8 @@ func main() {
356370
Short: "Cleans Regolith cache",
357371
Long: regolithCleanDesc,
358372
Run: func(cmd *cobra.Command, _ []string) {
359-
err = regolith.Clean(burrito.PrintStackTrace, userCache, filterCache)
373+
env, _ := cmd.Flags().GetString("env")
374+
err = regolith.Clean(burrito.PrintStackTrace, userCache, filterCache, env)
360375
},
361376
}
362377
cmdClean.Flags().BoolVarP(
@@ -373,7 +388,8 @@ func main() {
373388
Short: "Updates cached resolver repositories",
374389
Long: regolithUpdateResolversDesc,
375390
Run: func(cmd *cobra.Command, _ []string) {
376-
err = regolith.UpdateResolvers(burrito.PrintStackTrace)
391+
env, _ := cmd.Flags().GetString("env")
392+
err = regolith.UpdateResolvers(burrito.PrintStackTrace, env)
377393
},
378394
}
379395
subcommands = append(subcommands, cmdUpdateResolvers)

regolith/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"golang.org/x/mod/semver"
88
)
99

10-
const latestCompatibleVersion = "1.6.0"
10+
const latestCompatibleVersion = "1.7.0"
1111

1212
const StandardLibraryUrl = "github.com/Bedrock-OSS/regolith-filters"
1313
const ConfigFilePath = "config.json"

regolith/env_loader.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package regolith
2+
3+
import (
4+
"bufio"
5+
"os"
6+
"path/filepath"
7+
"strings"
8+
9+
"github.com/Bedrock-OSS/go-burrito/burrito"
10+
)
11+
12+
// loadEnvFileFromArg loads environment variables from a .env file specified by the env argument.
13+
// If env is empty, loads from ".env" in the current directory.
14+
// Variables already present in the environment are not overwritten (standard priority).
15+
// Returns an error if the file cannot be read (other than not existing).
16+
func loadEnvFileFromArg(env string) error {
17+
envPath := ".env"
18+
if env != "" {
19+
envPath = env
20+
}
21+
return LoadEnvFileFromPath(envPath)
22+
}
23+
24+
// LoadEnvFileFromPath loads environment variables from a .env file at a specified path.
25+
// Variables already present in the environment are not overwritten (standard priority).
26+
// Returns an error if the file cannot be read (other than not existing).
27+
func LoadEnvFileFromPath(envFilePath string) error {
28+
// Resolve the path to be absolute
29+
absPath, err := filepath.Abs(envFilePath)
30+
if err != nil {
31+
return burrito.WrapErrorf(err, filepathAbsError, envFilePath)
32+
}
33+
34+
// Check if the file exists
35+
if _, err := os.Stat(absPath); os.IsNotExist(err) {
36+
// File doesn't exist, which is fine - silently return
37+
return nil
38+
} else if err != nil {
39+
return burrito.WrapErrorf(err, osStatErrorAny, absPath)
40+
}
41+
42+
// Open the .env file
43+
file, err := os.Open(absPath)
44+
if err != nil {
45+
return burrito.WrapErrorf(err, osOpenError, absPath)
46+
}
47+
defer file.Close()
48+
49+
// Parse and load environment variables
50+
scanner := bufio.NewScanner(file)
51+
52+
for scanner.Scan() {
53+
line := scanner.Text()
54+
55+
// Skip empty lines and comments
56+
line = strings.TrimSpace(line)
57+
if line == "" || strings.HasPrefix(line, "#") {
58+
continue
59+
}
60+
61+
// Parse key=value pair
62+
parts := strings.SplitN(line, "=", 2)
63+
if len(parts) != 2 {
64+
continue // Skip malformed lines
65+
}
66+
67+
key := strings.TrimSpace(parts[0])
68+
value := strings.TrimSpace(parts[1])
69+
70+
// Remove quotes if present
71+
if len(value) >= 2 {
72+
if (strings.HasPrefix(value, "\"") && strings.HasSuffix(value, "\"")) ||
73+
(strings.HasPrefix(value, "'") && strings.HasSuffix(value, "'")) {
74+
value = value[1 : len(value)-1]
75+
}
76+
}
77+
78+
// Only set the variable if it's not already set (standard priority)
79+
if _, exists := os.LookupEnv(key); !exists {
80+
err := os.Setenv(key, value)
81+
if err != nil {
82+
return burrito.WrapErrorf(
83+
err,
84+
"Failed to set environment variable:\nKey: %s\nValue: %s",
85+
key, value,
86+
)
87+
}
88+
}
89+
}
90+
91+
if err := scanner.Err(); err != nil {
92+
return burrito.WrapErrorf(err, fileReadError, absPath)
93+
}
94+
95+
return nil
96+
}

regolith/errors.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,4 +261,11 @@ const (
261261

262262
updatedFilesDumpError = "Failed to update the list of the files edited by Regolith." +
263263
"This may cause the next run to fail."
264+
265+
invalidArgumentModeError = "The extraArguments property of a filter is invalid:\n" +
266+
"Current value: %q\n" +
267+
"Valid values are: %s"
268+
269+
loadEnvFileFromArgError = "Failed to the file with environment variables:\n" +
270+
"File path: %s"
264271
)

regolith/evaluator.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package regolith
22

33
import (
4+
"os"
45
"runtime"
6+
"strings"
57

68
"github.com/Bedrock-OSS/go-burrito/burrito"
79
"github.com/stirante/go-simple-eval/eval"
@@ -51,6 +53,13 @@ func prepareScope(ctx RunContext) map[string]any {
5153
if ctx.IsInWatchMode() {
5254
mode = "watch"
5355
}
56+
// Collect all environment variables
57+
envVars := make(map[string]any)
58+
for _, env := range os.Environ() {
59+
if pair := strings.SplitN(env, "=", 2); len(pair) == 2 {
60+
envVars[pair[0]] = pair[1]
61+
}
62+
}
5463
return map[string]any{
5564
"os": runtime.GOOS,
5665
"arch": runtime.GOARCH,
@@ -61,6 +70,8 @@ func prepareScope(ctx RunContext) map[string]any {
6170
"settings": ctx.Settings,
6271
"project": projectData,
6372
"mode": mode,
73+
"nested": ctx.Parent != nil,
6474
"initial": ctx.Initial,
75+
"env": envVars,
6576
}
6677
}

regolith/export.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func GetExportPaths(
2626
if semver.Compare(vFormatVersion, "v1.4.0") < 0 {
2727
bpPath, rpPath, err = getExportPathsV1_2_0(
2828
exportTarget, bpName, rpName)
29-
} else if semver.Compare(vFormatVersion, "v1.6.0") <= 0 {
29+
} else if semver.Compare(vFormatVersion, "v1.7.0") <= 0 {
3030
bpPath, rpPath, err = getExportPathsV1_4_0(
3131
exportTarget, bpName, rpName)
3232
} else {

regolith/filter.go

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ type FilterDefinition struct {
1212
}
1313

1414
type Filter struct {
15-
Id string `json:"filter,omitempty"`
16-
Description string `json:"name,omitempty"`
17-
Disabled bool `json:"disabled,omitempty"`
18-
Arguments []string `json:"arguments,omitempty"`
19-
Settings map[string]any `json:"settings,omitempty"`
20-
When string `json:"when,omitempty"`
15+
Id string `json:"filter,omitempty"`
16+
Description string `json:"name,omitempty"`
17+
Disabled bool `json:"disabled,omitempty"`
18+
Arguments []string `json:"arguments,omitempty"`
19+
Settings map[string]any `json:"settings,omitempty"`
20+
When string `json:"when,omitempty"`
21+
ExtraArgumentsMode string `json:"extraArguments,omitempty"`
2122
}
2223

2324
type RunContext struct {
@@ -28,6 +29,7 @@ type RunContext struct {
2829
Parent *RunContext
2930
DotRegolithPath string
3031
Settings map[string]any
32+
ExtraArguments []string
3133

3234
// interruption is a channel used to receive notifications about changes
3335
// in the source files, in order to trigger a restart of the program in
@@ -154,6 +156,17 @@ func filterFromObject(obj map[string]any, id string) (*Filter, error) {
154156
id = parsedId
155157
}
156158
filter.Id = id
159+
160+
// extraArguments mode
161+
extraArguments, ok := obj["extraArguments"]
162+
if ok {
163+
extraArguments, ok := extraArguments.(string)
164+
if !ok {
165+
return nil, burrito.WrappedErrorf(jsonPropertyTypeError, "extraArguments", "string")
166+
}
167+
filter.ExtraArgumentsMode = extraArguments
168+
}
169+
157170
return filter, nil
158171
}
159172

@@ -190,6 +203,10 @@ type FilterRunner interface {
190203
// IsUsingDataExport returns whether the filter wants its data to be
191204
// exported back to the data folder after running the profile.
192205
IsUsingDataExport(dotRegolithPath string, ctx RunContext) (bool, error)
206+
207+
// AddExtraArguments adds additional arguments to the filter according to
208+
// the method provided in the filter runner settings
209+
AddExtraArguments(extraArguments []string) error
193210
}
194211

195212
func (f *Filter) CopyArguments(parent *RemoteFilter) {
@@ -234,6 +251,22 @@ func (f *Filter) IsUsingDataExport(_ string, _ RunContext) (bool, error) {
234251
return false, nil
235252
}
236253

254+
func (f *Filter) AddExtraArguments(extraArguments []string) error {
255+
switch f.ExtraArgumentsMode {
256+
case "", "ignore":
257+
case "override":
258+
f.Arguments = extraArguments
259+
case "append":
260+
f.Arguments = append(f.Arguments, extraArguments...)
261+
default:
262+
return burrito.WrappedErrorf(
263+
invalidArgumentModeError,
264+
// current value; valid values
265+
f.ExtraArgumentsMode, "ignore, override, append")
266+
}
267+
return nil
268+
}
269+
237270
type filterInstallerFactory struct {
238271
constructor func(string, map[string]any) (FilterInstaller, error)
239272
name string
@@ -317,11 +350,31 @@ func FilterInstallerFromObject(id string, obj map[string]any) (FilterInstaller,
317350
}
318351

319352
func FilterRunnerFromObjectAndDefinitions(
320-
obj map[string]any, filterDefinitions map[string]FilterInstaller,
353+
obj map[string]any,
354+
filterDefinitions map[string]FilterInstaller,
355+
isInAsyncFilter bool,
321356
) (FilterRunner, error) {
322357
profile, ok := obj["profile"].(string)
323358
if ok {
324-
return &ProfileFilter{Profile: profile}, nil
359+
// For profile filters, we pass the profile name as the ID since there's no "filter" property
360+
basicFilter, err := filterFromObject(obj, profile)
361+
if err != nil {
362+
return nil, burrito.WrapError(err, filterFromObjectError)
363+
}
364+
return &ProfileFilter{
365+
Filter: *basicFilter,
366+
Profile: profile,
367+
}, nil
368+
}
369+
if !isInAsyncFilter {
370+
_, ok := obj["asyncFilters"]
371+
if ok {
372+
asyncFilter, err := AsyncFilterFromObject(obj, filterDefinitions)
373+
if err != nil {
374+
return nil, burrito.PassError(err)
375+
}
376+
return asyncFilter, nil
377+
}
325378
}
326379
filterObj, ok := obj["filter"]
327380
if !ok {

0 commit comments

Comments
 (0)