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

hmerritt / reactenv / 21911899119

11 Feb 2026 03:44PM UTC coverage: 26.739%. First build
21911899119

push

github

web-flow
Merge pull request #4 from hmerritt/dev

Refactor occurrence finder algorithm to fix edge cases

## Changes
- Refactor occurrence finder algorithm to fix edge cases
- `FindOccurrences` returns an error, and it will fail `run` command
- Test `reactenv` logic
- GitHub actions testing

58 of 68 new or added lines in 2 files covered. (85.29%)

173 of 647 relevant lines covered (26.74%)

0.31 hits per line

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

0.0
/command/run.go
1
package command
2

3
import (
4
        "fmt"
5
        "os"
6
        "regexp"
7
        "strings"
8

9
        "github.com/hmerritt/reactenv/reactenv"
10
        "github.com/hmerritt/reactenv/ui"
11
)
12

13
type RunCommand struct {
14
        *BaseCommand
15
}
16

17
func (c *RunCommand) Synopsis() string {
×
18
        return "Inject environment variables into a built react app"
×
19
}
×
20

21
func (c *RunCommand) Help() string {
×
22
        jsInfo := c.UI.Colorize(".js", c.UI.InfoColor)
×
23
        helpText := fmt.Sprintf(`
×
24
Usage: reactenv run [options] PATH
×
NEW
25

×
26
Inject environment variables into a built react app.
×
27

×
28
Example:
×
29
  $ reactenv run ./dist/assets
×
30

×
31
    dist/assets
×
32
    ├── index.css
×
33
    ├── index-csxw0qbp%s
×
34
    ├── login.lazy-b839zm%s
×
35
    └── user.lazy-c7942lh%s  <- Runs on all %s files in PATH
×
36
`, jsInfo, jsInfo, jsInfo, jsInfo)
×
37

×
38
        return strings.TrimSpace(helpText)
×
39
}
×
40

41
func (c *RunCommand) Flags() *FlagMap {
×
42
        return GetFlagMap(FlagNamesGlobal)
×
43
}
×
44

45
func (c *RunCommand) Run(args []string) int {
×
46
        duration := ui.InitDuration(c.UI)
×
47

×
48
        args = c.Flags().Parse(c.UI, args)
×
49

×
50
        if len(args) == 0 {
×
51
                c.UI.Error("No asset PATH entered.")
×
52
                c.exitWithHelp()
×
53
        }
×
54

55
        pathToAssets := args[0]
×
56

×
57
        if _, err := os.Stat(pathToAssets); os.IsNotExist(err) {
×
58
                c.UI.Error(fmt.Sprintf("File PATH '%s' does not exist.", pathToAssets))
×
59
                c.exitWithHelp()
×
60
        }
×
61

62
        // @TODO: Add flag to specify matcher
63
        fileMatchExpression := `.*\.js`
×
64
        _, err := regexp.Compile(fileMatchExpression)
×
65

×
66
        if err != nil {
×
67
                c.UI.Error(fmt.Sprintf("File match expression '%s' is not valid.\n", fileMatchExpression))
×
68
                c.UI.Error(fmt.Sprintf("%v", err))
×
69
                c.exitWithHelp()
×
70
        }
×
71

72
        renv := reactenv.NewReactenv(c.UI)
×
73

×
74
        err = renv.FindFiles(pathToAssets, fileMatchExpression)
×
75

×
76
        if err != nil {
×
77
                c.UI.Error(fmt.Sprintf("Error reading files in PATH '%s'.\n", pathToAssets))
×
78
                c.UI.Error(fmt.Sprintf("%v", err))
×
79
                os.Exit(1)
×
80
        }
×
81

82
        if len(renv.Files) == 0 {
×
83
                c.UI.Error(fmt.Sprintf("No files found in path '%s' using matcher '%s'", pathToAssets, fileMatchExpression))
×
84
                os.Exit(1)
×
85
        }
×
86

NEW
87
        err = renv.FindOccurrences()
×
NEW
88

×
NEW
89
        if err != nil {
×
NEW
90
                c.UI.Error(fmt.Sprintf("There was an error while searching for __reactenv variables in the %d '%s' files within '%s', therefore nothing was injected.\n", renv.FilesMatchTotal, fileMatchExpression, pathToAssets))
×
NEW
91
                c.UI.Error(fmt.Sprintf("%v", err))
×
NEW
92
                os.Exit(1)
×
NEW
93
        }
×
94

95
        if renv.OccurrencesTotal == 0 {
×
96
                c.UI.Warn(ui.WrapAtLength(fmt.Sprintf("No reactenv environment variables were found in any of the %d '%s' files within '%s', therefore nothing was injected.\n", renv.FilesMatchTotal, fileMatchExpression, pathToAssets), 0))
×
97
                c.UI.Warn(ui.WrapAtLength("Possible causes:", 4))
×
98
                c.UI.Warn(ui.WrapAtLength("  - reactenv has already ran on these files", 4))
×
99
                c.UI.Warn(ui.WrapAtLength("  - Environment variables were not replaced with `__reactenv.<name>` during build", 4))
×
100
                c.UI.Warn("")
×
101
                duration.In(c.UI.WarnColor, "")
×
102
                return 1
×
103
        }
×
104

105
        c.UI.Output(
×
106
                fmt.Sprintf(
×
107
                        "Found %d reactenv environment %s in %d/%d matching files:",
×
108
                        renv.OccurrencesTotal,
×
109
                        ui.Pluralize("variable", renv.OccurrencesTotal),
×
110
                        len(renv.Files),
×
111
                        renv.FilesMatchTotal,
×
112
                ),
×
113
        )
×
114
        for fileIndex, fileOccurrencesTotal := range renv.OccurrencesByFile {
×
115
                c.UI.Output(
×
116
                        fmt.Sprintf(
×
117
                                "  - %4dx in %s",
×
118
                                len(fileOccurrencesTotal.Occurrences),
×
119
                                (*renv.Files[fileIndex]).Name(),
×
120
                        ),
×
121
                )
×
122
        }
×
123
        c.UI.Output("")
×
124

×
125
        c.UI.Output(fmt.Sprintf("Environment %s checklist (ticked if value has been set):", ui.Pluralize("variable", renv.OccurrencesTotal)))
×
126
        envValuesMissing := 0
×
127
        for occurrenceKey := range renv.OccurrenceKeys {
×
128
                check := "✅"
×
129
                if _, ok := renv.OccurrenceKeysReplacement[occurrenceKey]; !ok {
×
130
                        check = "❌"
×
131
                        envValuesMissing++
×
132
                }
×
133
                c.UI.Output(fmt.Sprintf("  - %4s %s", check, occurrenceKey))
×
134
        }
135
        c.UI.Output("")
×
136

×
137
        if envValuesMissing > 0 {
×
138
                c.UI.Error(fmt.Sprintf("Environment %s not set. See above checklist for missing values.", ui.Pluralize("variable", envValuesMissing)))
×
139
                os.Exit(1)
×
140
        }
×
141

142
        renv.ReplaceOccurrences()
×
143

×
144
        duration.In(c.UI.SuccessColor, fmt.Sprintf("Injected all environment variables"))
×
145
        return 0
×
146
}
147

148
func (c *RunCommand) exitWithHelp() {
×
149
        c.UI.Output("\nSee 'reactenv run --help'.")
×
150
        os.Exit(1)
×
151
}
×
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