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

mlange-42 / modo / 13179389384

06 Feb 2025 01:02PM CUT coverage: 56.505% (-17.6%) from 74.08%
13179389384

Pull #212

github

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

1772 of 3136 relevant lines covered (56.51%)

21.11 hits per line

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

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

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

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

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

×
18
        root := &cobra.Command{
×
19
                Use:   "build [PATH]",
×
20
                Short: "Build documentation from 'mojo doc' JSON",
×
21
                Long: `Build documentation from 'mojo doc' JSON.
×
22

×
23
Builds based on the 'modo.yaml' file in the current directory if no path is given.
×
24
The flags listed below overwrite the settings from that file.
×
25

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

×
43
                        cliArgs, err := document.ConfigFromViper(v)
×
44
                        if err != nil {
×
45
                                return err
×
46
                        }
×
47
                        if err := runBuild(cliArgs); err != nil {
×
48
                                return err
×
49
                        }
×
50
                        if watch {
×
51
                                return watchAndRun(cliArgs, runBuild)
×
52
                        }
×
53

54
                        fmt.Printf("Completed in %.1fms 🧯\n", float64(time.Since(start).Microseconds())/1000.0)
×
55
                        return nil
×
56
                },
57
        }
58

59
        root.Flags().StringVarP(&config, "config", "c", defaultConfigFile, "Config file in the working directory to use")
×
60
        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")
×
61
        root.Flags().StringP("output", "o", "", "Output folder for generated Markdown files")
×
62
        root.Flags().StringP("tests", "t", "", "Target folder to extract doctests for 'mojo test'.\nSee also command 'modo test' (default no doctests)")
×
63
        root.Flags().StringP("format", "f", "plain", "Output format. One of (plain|mdbook|hugo)")
×
64
        root.Flags().BoolP("exports", "e", false, "Process according to 'Exports:' sections in packages")
×
65
        root.Flags().BoolP("short-links", "s", false, "Render shortened link labels, stripping packages and modules")
×
66
        root.Flags().BoolP("report-missing", "M", false, "Report missing docstings and coverage")
×
67
        root.Flags().BoolP("case-insensitive", "C", false, "Build for systems that are not case-sensitive regarding file names.\nAppends hyphen (-) to capitalized file names")
×
68
        root.Flags().BoolP("strict", "S", false, "Strict mode. Errors instead of warnings")
×
69
        root.Flags().BoolP("dry-run", "D", false, "Dry-run without any file output. Disables post-processing scripts")
×
70
        root.Flags().BoolP("bare", "B", false, "Don't run pre- and post-processing scripts")
×
71
        root.Flags().BoolVarP(&watch, "watch", "W", false, "Re-run on changes of sources and documentation files.\nDisables post-processing scripts after running them once")
×
72
        root.Flags().StringSliceP("templates", "T", []string{}, "Optional directories with templates for (partial) overwrite.\nSee folder assets/templates in the repository")
×
73

×
74
        root.Flags().SortFlags = false
×
75
        root.MarkFlagFilename("config", "yaml")
×
76
        root.MarkFlagFilename("input", "json")
×
77
        root.MarkFlagDirname("output")
×
78
        root.MarkFlagDirname("tests")
×
79
        root.MarkFlagDirname("templates")
×
80

×
81
        err := bindFlags(v, root.Flags())
×
82
        if err != nil {
×
83
                return nil, err
×
84
        }
×
85
        return root, nil
×
86
}
87

88
func runBuild(args *document.Config) error {
×
89
        if args.OutputDir == "" {
×
90
                return fmt.Errorf("no output path given")
×
91
        }
×
92

93
        if !args.Bare {
×
94
                if err := runPreBuildCommands(args); err != nil {
×
95
                        return err
×
96
                }
×
97
        }
98

99
        formatter, err := format.GetFormatter(args.RenderFormat)
×
100
        if err != nil {
×
101
                return err
×
102
        }
×
103

104
        if err := runFilesOrDir(runBuildOnce, args, formatter); err != nil {
×
105
                return err
×
106
        }
×
107

108
        if !args.Bare && !args.DryRun {
×
109
                if err := runPostBuildCommands(args); err != nil {
×
110
                        return err
×
111
                }
×
112
        }
113

114
        return nil
×
115
}
116

117
func runBuildOnce(file string, args *document.Config, form document.Formatter, subdir string, isFile, isDir bool) error {
×
118
        if isDir {
×
119
                if err := document.ExtractTestsMarkdown(args, form, file, true); err != nil {
×
120
                        return err
×
121
                }
×
122
                return runDir(file, args, form, runBuildOnce)
×
123
        }
124
        docs, err := readDocs(file)
×
125
        if err != nil {
×
126
                return err
×
127
        }
×
128
        err = document.Render(docs, args, form, subdir)
×
129
        if err != nil {
×
130
                return err
×
131
        }
×
132
        return nil
×
133
}
134

135
func runPreBuildCommands(cfg *document.Config) error {
×
136
        if err := runCommands(cfg.PreRun); err != nil {
×
137
                return commandError("pre-run", err)
×
138
        }
×
139
        if err := runCommands(cfg.PreBuild); err != nil {
×
140
                return commandError("pre-build", err)
×
141
        }
×
142
        if cfg.TestOutput != "" {
×
143
                if err := runCommands(cfg.PreTest); err != nil {
×
144
                        return commandError("pre-test", err)
×
145
                }
×
146
        }
147
        return nil
×
148
}
149

150
func runPostBuildCommands(cfg *document.Config) error {
×
151
        if cfg.TestOutput != "" {
×
152
                if err := runCommands(cfg.PostTest); err != nil {
×
153
                        return commandError("post-test", err)
×
154
                }
×
155
        }
156
        if err := runCommands(cfg.PostBuild); err != nil {
×
157
                return commandError("post-build", err)
×
158
        }
×
159
        if err := runCommands(cfg.PostRun); err != nil {
×
160
                return commandError("post-run", err)
×
161
        }
×
162
        return nil
×
163
}
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