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

mlange-42 / modo / 13180577064

06 Feb 2025 02:07PM CUT coverage: 73.089% (-1.0%) from 74.08%
13180577064

Pull #212

github

web-flow
Merge 98d3dc552 into 1566231bf
Pull Request #212: Add tests for CLI commands

36 of 54 new or added lines in 6 files covered. (66.67%)

2314 of 3166 relevant lines covered (73.09%)

40.88 hits per line

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

68.42
/internal/cmd/build.go
1
package cmd
2

3
import (
4
        "fmt"
5
        "os"
6
        "time"
7

8
        "github.com/mlange-42/modo/internal/document"
9
        "github.com/mlange-42/modo/internal/format"
10
        "github.com/spf13/cobra"
11
        "github.com/spf13/viper"
12
)
13

14
func buildCommand() (*cobra.Command, error) {
4✔
15
        v := viper.New()
4✔
16
        var config string
4✔
17
        var watch bool
4✔
18

4✔
19
        var cwd string
4✔
20

4✔
21
        root := &cobra.Command{
4✔
22
                Use:   "build [PATH]",
4✔
23
                Short: "Build documentation from 'mojo doc' JSON",
4✔
24
                Long: `Build documentation from 'mojo doc' JSON.
4✔
25

4✔
26
Builds based on the 'modo.yaml' file in the current directory if no path is given.
4✔
27
The flags listed below overwrite the settings from that file.
4✔
28

4✔
29
Complete documentation at https://mlange-42.github.io/modo/`,
4✔
30
                Example: `  modo init hugo                 # set up a project, e.g. for Hugo
4✔
31
  modo build                     # build the docs`,
4✔
32
                Args:         cobra.MaximumNArgs(1),
4✔
33
                SilenceUsage: true,
4✔
34
                PreRunE: func(cmd *cobra.Command, args []string) error {
6✔
35
                        var err error
2✔
36
                        if err = checkConfigFile(config); err != nil {
2✔
37
                                return err
×
38
                        }
×
39
                        if cwd, err = mountProject(v, config, args); err != nil {
2✔
40
                                return err
×
41
                        }
×
42
                        return nil
2✔
43
                },
44
                RunE: func(cmd *cobra.Command, args []string) error {
2✔
45
                        start := time.Now()
2✔
46

2✔
47
                        cliArgs, err := document.ConfigFromViper(v)
2✔
48
                        if err != nil {
2✔
49
                                return err
×
50
                        }
×
51
                        if err := runBuild(cliArgs); err != nil {
2✔
52
                                return err
×
53
                        }
×
54
                        if watch {
2✔
55
                                return watchAndRun(cliArgs, runBuild)
×
56
                        }
×
57

58
                        if err := os.Chdir(cwd); err != nil {
2✔
NEW
59
                                return err
×
NEW
60
                        }
×
61

62
                        fmt.Printf("Completed in %.1fms 🧯\n", float64(time.Since(start).Microseconds())/1000.0)
2✔
63
                        return nil
2✔
64
                },
65
        }
66

67
        root.Flags().StringVarP(&config, "config", "c", defaultConfigFile, "Config file in the working directory to use")
4✔
68
        root.Flags().StringSliceP("input", "i", []string{}, "'mojo doc' JSON file to process. Reads from STDIN if not specified.\nIf a single directory is given, it is processed recursively")
4✔
69
        root.Flags().StringP("output", "o", "", "Output folder for generated Markdown files")
4✔
70
        root.Flags().StringP("tests", "t", "", "Target folder to extract doctests for 'mojo test'.\nSee also command 'modo test' (default no doctests)")
4✔
71
        root.Flags().StringP("format", "f", "plain", "Output format. One of (plain|mdbook|hugo)")
4✔
72
        root.Flags().BoolP("exports", "e", false, "Process according to 'Exports:' sections in packages")
4✔
73
        root.Flags().BoolP("short-links", "s", false, "Render shortened link labels, stripping packages and modules")
4✔
74
        root.Flags().BoolP("report-missing", "M", false, "Report missing docstings and coverage")
4✔
75
        root.Flags().BoolP("case-insensitive", "C", false, "Build for systems that are not case-sensitive regarding file names.\nAppends hyphen (-) to capitalized file names")
4✔
76
        root.Flags().BoolP("strict", "S", false, "Strict mode. Errors instead of warnings")
4✔
77
        root.Flags().BoolP("dry-run", "D", false, "Dry-run without any file output. Disables post-processing scripts")
4✔
78
        root.Flags().BoolP("bare", "B", false, "Don't run pre- and post-processing scripts")
4✔
79
        root.Flags().BoolVarP(&watch, "watch", "W", false, "Re-run on changes of sources and documentation files.\nDisables post-processing scripts after running them once")
4✔
80
        root.Flags().StringSliceP("templates", "T", []string{}, "Optional directories with templates for (partial) overwrite.\nSee folder assets/templates in the repository")
4✔
81

4✔
82
        root.Flags().SortFlags = false
4✔
83
        root.MarkFlagFilename("config", "yaml")
4✔
84
        root.MarkFlagFilename("input", "json")
4✔
85
        root.MarkFlagDirname("output")
4✔
86
        root.MarkFlagDirname("tests")
4✔
87
        root.MarkFlagDirname("templates")
4✔
88

4✔
89
        err := bindFlags(v, root.Flags())
4✔
90
        if err != nil {
4✔
91
                return nil, err
×
92
        }
×
93
        return root, nil
4✔
94
}
95

96
func runBuild(args *document.Config) error {
2✔
97
        if args.OutputDir == "" {
2✔
98
                return fmt.Errorf("no output path given")
×
99
        }
×
100

101
        if !args.Bare {
4✔
102
                if err := runPreBuildCommands(args); err != nil {
2✔
103
                        return err
×
104
                }
×
105
        }
106

107
        formatter, err := format.GetFormatter(args.RenderFormat)
2✔
108
        if err != nil {
2✔
109
                return err
×
110
        }
×
111

112
        if err := runFilesOrDir(runBuildOnce, args, formatter); err != nil {
2✔
113
                return err
×
114
        }
×
115

116
        if !args.Bare && !args.DryRun {
4✔
117
                if err := runPostBuildCommands(args); err != nil {
2✔
118
                        return err
×
119
                }
×
120
        }
121

122
        return nil
2✔
123
}
124

125
func runBuildOnce(file string, args *document.Config, form document.Formatter, subdir string, isFile, isDir bool) error {
4✔
126
        if isDir {
6✔
127
                if err := document.ExtractTestsMarkdown(args, form, file, true); err != nil {
2✔
128
                        return err
×
129
                }
×
130
                return runDir(file, args, form, runBuildOnce)
2✔
131
        }
132
        docs, err := readDocs(file)
2✔
133
        if err != nil {
2✔
134
                return err
×
135
        }
×
136
        err = document.Render(docs, args, form, subdir)
2✔
137
        if err != nil {
2✔
138
                return err
×
139
        }
×
140
        return nil
2✔
141
}
142

143
func runPreBuildCommands(cfg *document.Config) error {
2✔
144
        if err := runCommands(cfg.PreRun); err != nil {
2✔
145
                return commandError("pre-run", err)
×
146
        }
×
147
        if err := runCommands(cfg.PreBuild); err != nil {
2✔
148
                return commandError("pre-build", err)
×
149
        }
×
150
        if cfg.TestOutput != "" {
4✔
151
                if err := runCommands(cfg.PreTest); err != nil {
2✔
152
                        return commandError("pre-test", err)
×
153
                }
×
154
        }
155
        return nil
2✔
156
}
157

158
func runPostBuildCommands(cfg *document.Config) error {
2✔
159
        if cfg.TestOutput != "" {
4✔
160
                if err := runCommands(cfg.PostTest); err != nil {
2✔
161
                        return commandError("post-test", err)
×
162
                }
×
163
        }
164
        if err := runCommands(cfg.PostBuild); err != nil {
2✔
165
                return commandError("post-build", err)
×
166
        }
×
167
        if err := runCommands(cfg.PostRun); err != nil {
2✔
168
                return commandError("post-run", err)
×
169
        }
×
170
        return nil
2✔
171
}
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

© 2025 Coveralls, Inc