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

CyberDuck79 / duckfile / 18097442731

29 Sep 2025 12:46PM UTC coverage: 79.573% (+0.04%) from 79.529%
18097442731

Pull #70

github

CyberDuck79
refactor: extract writeMetadataFile helper to reduce metadata writing duplication

- Add writeMetadataFile() helper function for consistent JSON metadata writing
- Replace duplicate json.Marshal + os.WriteFile patterns in remote.go
- Reduces code duplication in template and remote metadata handling
Pull Request #70: Phase 2: Implement separated targets and remotes configurations

592 of 686 new or added lines in 9 files covered. (86.3%)

24 existing lines in 5 files now uncovered.

2758 of 3466 relevant lines covered (79.57%)

11.37 hits per line

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

89.52
/cmd/duck/list.go
1
package main
2

3
import (
4
        "fmt"
5
        "sort"
6
        "strings"
7

8
        "github.com/CyberDuck79/duckfile/internal/config"
9
        "github.com/CyberDuck79/duckfile/internal/log"
10
        "github.com/spf13/cobra"
11
)
12

13
func init() {
1✔
14
        var (
1✔
15
                listShowRemote bool
1✔
16
                listShowVars   bool
1✔
17
                listShowExec   bool
1✔
18
                listLogLevel   string
1✔
19
        )
1✔
20
        listCmd := &cobra.Command{
1✔
21
                Use:   "list",
1✔
22
                Short: "List targets defined in duck.yaml",
1✔
23
                Long: `List all targets from the duck.yaml configuration file.
1✔
24

1✔
25
Shows target names and descriptions by default. Use flags to include additional details.
1✔
26

1✔
27
FLAGS
1✔
28
  -r, --remote           Show remote template information (repo, ref, path)
1✔
29
  -v, --vars             Show template variables
1✔
30
  -e, --exec             Show execution info (binary, file flag)
1✔
31
  --log-level string     Log level: error, warn, info, debug
1✔
32

1✔
33
EXAMPLES
1✔
34
  duck list              List targets with names and descriptions
1✔
35
  duck list -r           Include remote template details
1✔
36
  duck list -v -e        Show variables and execution info`,
1✔
37
                RunE: func(cmd *cobra.Command, args []string) error {
6✔
38
                        // Check if user might have intended to execute a target named 'list'
5✔
39
                        checkForTargetConflictAndWarn("list")
5✔
40

5✔
41
                        cfg, err := loadConfig()
5✔
42
                        if err != nil {
5✔
43
                                return err
×
44
                        }
×
45

46
                        // Resolve and set log level
47
                        logLevelStr := config.ResolveLogLevel(listLogLevel, cfg)
5✔
48
                        effectiveLogLevel, err := log.ParseLevel(logLevelStr)
5✔
49
                        if err != nil {
5✔
50
                                return fmt.Errorf("invalid log level: %w", err)
×
51
                        }
×
52
                        log.SetLevel(effectiveLogLevel)
5✔
53

5✔
54
                        fmt.Printf("%-12s %-12s %-s\n", "TARGET", "BINARY", "DESCRIPTION")
5✔
55
                        printTarget := func(key string, t config.Target) {
20✔
56
                                bin := t.Binary
15✔
57
                                if bin == "" {
20✔
58
                                        bin = "-"
5✔
59
                                }
5✔
60
                                label := key
15✔
61
                                if key == cfg.Default { // mark default
20✔
62
                                        label = key + "*"
5✔
63
                                }
5✔
64
                                fmt.Printf("%-12s %-12s %-s\n", label, bin, t.Description)
15✔
65
                                if listShowRemote {
27✔
66
                                        // Resolve template configuration to handle remote references
12✔
67
                                        resolved, err := config.ResolveTemplateConfig(t.Template, cfg.Remotes, cfg.Settings)
12✔
68
                                        if err != nil {
12✔
NEW
69
                                                fmt.Printf("    repo: <error resolving remote: %v>\n", err)
×
NEW
70
                                                fmt.Printf("    ref: <error>\n")
×
NEW
71
                                                fmt.Printf("    path: %s\n", t.Template.Path)
×
72
                                        } else {
12✔
73
                                                fmt.Printf("    repo: %s\n", resolved.Repo)
12✔
74
                                                ref := resolved.Ref
12✔
75
                                                if ref == "" {
12✔
NEW
76
                                                        ref = "HEAD"
×
NEW
77
                                                }
×
78
                                                fmt.Printf("    ref: %s\n", ref)
12✔
79
                                                fmt.Printf("    path: %s\n", resolved.Path)
12✔
80
                                        }
81
                                }
82
                                if listShowVars && len(t.Variables) > 0 {
21✔
83
                                        keys := make([]string, 0, len(t.Variables))
6✔
84
                                        for k := range t.Variables {
21✔
85
                                                keys = append(keys, k)
15✔
86
                                        }
15✔
87
                                        sort.Strings(keys)
6✔
88
                                        fmt.Printf("    variables (%d):\n", len(keys))
6✔
89
                                        for _, k := range keys {
21✔
90
                                                vv := t.Variables[k]
15✔
91
                                                var origin string
15✔
92
                                                switch vv.Kind {
15✔
93
                                                case config.VarLiteral:
6✔
94
                                                        origin = "literal"
6✔
95
                                                case config.VarEnv:
3✔
96
                                                        origin = "env"
3✔
97
                                                case config.VarCmd:
3✔
98
                                                        origin = "cmd"
3✔
99
                                                case config.VarFile:
3✔
100
                                                        origin = "file"
3✔
101
                                                default:
×
102
                                                        origin = "literal"
×
103
                                                }
104
                                                fmt.Printf("      - %s (%s)\n", k, origin)
15✔
105
                                        }
106
                                }
107
                                if listShowExec && t.Binary != "" {
19✔
108
                                        fmt.Printf("    exec: %s %s <rendered> %s\n", t.Binary, t.FileFlag, strings.Join(t.Args, " "))
4✔
109
                                }
4✔
110
                        }
111
                        keys := make([]string, 0, len(cfg.Targets))
5✔
112
                        for k := range cfg.Targets {
20✔
113
                                keys = append(keys, k)
15✔
114
                        }
15✔
115
                        sort.Strings(keys)
5✔
116
                        for _, k := range keys {
20✔
117
                                printTarget(k, cfg.Targets[k])
15✔
118
                        }
15✔
119
                        return nil
5✔
120
                },
121
        }
122
        listCmd.Flags().BoolVarP(&listShowRemote, "remote", "r", false, "Show remote template configuration (repo/ref/path/delims)")
1✔
123
        listCmd.Flags().BoolVarP(&listShowVars, "vars", "v", false, "Show variable names and their kinds")
1✔
124
        listCmd.Flags().BoolVarP(&listShowExec, "exec", "e", false, "Show execution line (binary + file flag + args)")
1✔
125
        listCmd.Flags().StringVar(&listLogLevel, "log-level", "", "Set log level (error, warn, info, debug)")
1✔
126

1✔
127
        rootCmd.AddCommand(listCmd)
1✔
128
}
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