Skip to content

Commit a9699e4

Browse files
committed
- add way to filter packages in arbitrary directory.
- update --packages to use only package name; added another filter to filter by package dirs. - Added auto discovery of package for configurable depth. - Added flag to exclude dirs from filter process.
1 parent f997640 commit a9699e4

File tree

7 files changed

+215
-112
lines changed

7 files changed

+215
-112
lines changed

cmd/filter.go

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ func setupFilterCommand() *cobraext.Command {
3232
// add filter flags to the command (input, code owner, kibana version, categories)
3333
filter.SetFilterFlags(cmd)
3434

35-
// add the output package name flag to the command
36-
cmd.Flags().BoolP(cobraext.FilterOutputPackageNameFlagName, cobraext.FilterOutputPackageNameFlagShorthand, false, cobraext.FilterOutputPackageNameFlagDescription)
35+
// add the output package name and absolute path flags to the command
36+
cmd.Flags().BoolP(cobraext.FilterOutputPackageNameFlagName, "", false, cobraext.FilterOutputPackageNameFlagDescription)
37+
cmd.Flags().BoolP(cobraext.FilterOutputAbsolutePathFlagName, "", false, cobraext.FilterOutputAbsolutePathFlagDescription)
3738

3839
return cobraext.NewCommand(cmd, cobraext.ContextPackage)
3940
}
@@ -49,15 +50,30 @@ func filterCommandAction(cmd *cobra.Command, args []string) error {
4950
return fmt.Errorf("getting output package name flag failed: %w", err)
5051
}
5152

52-
if err = printPkgList(filtered, printPackageName, os.Stdout); err != nil {
53+
outputAbsolutePath, err := cmd.Flags().GetBool("output-absolute-path")
54+
if err != nil {
55+
return fmt.Errorf("getting output absolute path flag failed: %w", err)
56+
}
57+
58+
if err = printPkgList(filtered, printPackageName, outputAbsolutePath, os.Stdout); err != nil {
5359
return fmt.Errorf("printing JSON failed: %w", err)
5460
}
5561

5662
return nil
5763
}
5864

5965
func filterPackage(cmd *cobra.Command) ([]packages.PackageDirNameAndManifest, error) {
60-
filters := filter.NewFilterRegistry()
66+
depth, err := cmd.Flags().GetInt(cobraext.FilterDepthFlagName)
67+
if err != nil {
68+
return nil, fmt.Errorf("getting depth flag failed: %w", err)
69+
}
70+
71+
excludeDirs, err := cmd.Flags().GetString(cobraext.FilterExcludeDirFlagName)
72+
if err != nil {
73+
return nil, fmt.Errorf("getting exclude-dir flag failed: %w", err)
74+
}
75+
76+
filters := filter.NewFilterRegistry(depth, excludeDirs)
6177

6278
if err := filters.Parse(cmd); err != nil {
6379
return nil, fmt.Errorf("parsing filter options failed: %w", err)
@@ -75,7 +91,7 @@ func filterPackage(cmd *cobra.Command) ([]packages.PackageDirNameAndManifest, er
7591
return filtered, nil
7692
}
7793

78-
func printPkgList(pkgs []packages.PackageDirNameAndManifest, printPackageName bool, w io.Writer) error {
94+
func printPkgList(pkgs []packages.PackageDirNameAndManifest, printPackageName bool, outputAbsolutePath bool, w io.Writer) error {
7995
enc := json.NewEncoder(w)
8096
enc.SetEscapeHTML(false)
8197
if len(pkgs) == 0 {
@@ -87,6 +103,10 @@ func printPkgList(pkgs []packages.PackageDirNameAndManifest, printPackageName bo
87103
for _, pkg := range pkgs {
88104
names = append(names, pkg.Manifest.Name)
89105
}
106+
} else if outputAbsolutePath {
107+
for _, pkg := range pkgs {
108+
names = append(names, pkg.Path)
109+
}
90110
} else {
91111
for _, pkg := range pkgs {
92112
names = append(names, pkg.DirName)

cmd/foreach.go

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"io"
1010
"os"
1111
"os/exec"
12-
"path/filepath"
1312
"slices"
1413
"strings"
1514
"sync"
@@ -20,7 +19,6 @@ import (
2019
"github.com/elastic/elastic-package/internal/filter"
2120
"github.com/elastic/elastic-package/internal/logger"
2221
"github.com/elastic/elastic-package/internal/multierror"
23-
"github.com/elastic/elastic-package/internal/packages"
2422
)
2523

2624
const foreachLongDescription = `Execute a command for each package matching the given filter criteria.
@@ -60,7 +58,7 @@ func setupForeachCommand() *cobraext.Command {
6058
filter.SetFilterFlags(cmd)
6159

6260
// Add pool size flag
63-
cmd.Flags().IntP(cobraext.ForeachPoolSizeFlagName, "", 1, cobraext.ForeachPoolSizeFlagDescription)
61+
cmd.Flags().IntP(cobraext.ForeachPoolSizeFlagName, cobraext.ForeachPoolSizeFlagShorthand, 1, cobraext.ForeachPoolSizeFlagDescription)
6462

6563
return cobraext.NewCommand(cmd, cobraext.ContextPackage)
6664
}
@@ -75,12 +73,6 @@ func foreachCommandAction(cmd *cobra.Command, args []string) error {
7573
return fmt.Errorf("validating sub command failed: %w", err)
7674
}
7775

78-
// Find integration root
79-
root, err := packages.MustFindIntegrationRoot()
80-
if err != nil {
81-
return fmt.Errorf("can't find integration root: %w", err)
82-
}
83-
8476
// reuse filterPackage from cmd/filter.go
8577
filtered, err := filterPackage(cmd)
8678
if err != nil {
@@ -92,31 +84,30 @@ func foreachCommandAction(cmd *cobra.Command, args []string) error {
9284
errs := multierror.Error{}
9385
successes := 0
9486

95-
packageChan := make(chan string, poolSize)
87+
packagePathChan := make(chan string, poolSize)
9688

9789
for range poolSize {
9890
wg.Add(1)
99-
go func(packageChan <-chan string) {
91+
go func(packagePathChan <-chan string) {
10092
defer wg.Done()
101-
for packageName := range packageChan {
102-
path := filepath.Join(root, "packages", packageName)
103-
err := executeCommand(args, path)
93+
for packagePath := range packagePathChan {
94+
err := executeCommand(args, packagePath)
10495

10596
mu.Lock()
10697
if err != nil {
107-
errs = append(errs, fmt.Errorf("executing command for package %s failed: %w", packageName, err))
98+
errs = append(errs, fmt.Errorf("executing command for package %s failed: %w", packagePath, err))
10899
} else {
109100
successes++
110101
}
111102
mu.Unlock()
112103
}
113-
}(packageChan)
104+
}(packagePathChan)
114105
}
115106

116107
for _, pkg := range filtered {
117-
packageChan <- pkg.DirName
108+
packagePathChan <- pkg.Path
118109
}
119-
close(packageChan)
110+
close(packagePathChan)
120111

121112
wg.Wait()
122113

internal/cobraext/flags.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,32 +136,46 @@ const (
136136
FailFastFlagName = "fail-fast"
137137
FailFastFlagDescription = "fail immediately if any file requires updates (do not overwrite)"
138138

139-
FilterCategoriesFlagName = "category"
139+
FilterCategoriesFlagName = "categories"
140140
FilterCategoriesFlagDescription = "integration categories to filter by (comma-separated values)"
141141

142-
FilterCodeOwnerFlagName = "code-owner"
142+
FilterCodeOwnerFlagName = "code-owners"
143143
FilterCodeOwnerFlagDescription = "code owners to filter by (comma-separated values)"
144144

145-
FilterPackageTypeFlagName = "package-type"
145+
FilterPackageTypeFlagName = "package-types"
146146
FilterPackageTypeFlagDescription = "package types to filter by (comma-separated values)"
147147

148-
FilterInputFlagName = "input"
148+
FilterInputFlagName = "inputs"
149149
FilterInputFlagDescription = "name of the inputs to filter by (comma-separated values)"
150150

151151
FilterKibanaVersionFlagName = "kibana-version"
152152
FilterKibanaVersionFlagDescription = "kibana version to filter by (semver)"
153153

154+
FilterOutputAbsolutePathFlagName = "output-absolute-path"
155+
FilterOutputAbsolutePathFlagDescription = "output the absolute path of the package"
156+
154157
FilterOutputPackageNameFlagName = "output-package-name"
155-
FilterOutputPackageNameFlagShorthand = "p"
156158
FilterOutputPackageNameFlagDescription = "print the package name instead of the directory name in the output"
157159

160+
FilterPackageDirNameFlagName = "package-dirs"
161+
FilterPackageDirNameFlagDescription = "package directories to filter by (comma-separated values)"
162+
158163
FilterPackagesFlagName = "packages"
159164
FilterPackagesFlagDescription = "package names to filter by (comma-separated values)"
160165

161166
FilterSpecVersionFlagName = "spec-version"
162167
FilterSpecVersionFlagDescription = "Package spec version to filter by (semver)"
163168

169+
FilterDepthFlagName = "depth"
170+
FilterDepthFlagDescription = "maximum depth to search for packages (default: 2)"
171+
FilterDepthFlagDefault = 2
172+
FilterDepthFlagShorthand = "d"
173+
174+
FilterExcludeDirFlagName = "exclude-dirs"
175+
FilterExcludeDirFlagDescription = "comma-separated list of directories to exclude from search"
176+
164177
ForeachPoolSizeFlagName = "parallel"
178+
ForeachPoolSizeFlagShorthand = "p"
165179
ForeachPoolSizeFlagDescription = "Number of subcommands to execute in parallel (defaults to serial execution)"
166180

167181
GenerateTestResultFlagName = "generate"

internal/filter/packagedirname.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
// or more contributor license agreements. Licensed under the Elastic License;
3+
// you may not use this file except in compliance with the Elastic License.
4+
5+
package filter
6+
7+
import (
8+
"fmt"
9+
10+
"github.com/gobwas/glob"
11+
"github.com/spf13/cobra"
12+
13+
"github.com/elastic/elastic-package/internal/cobraext"
14+
"github.com/elastic/elastic-package/internal/packages"
15+
)
16+
17+
type PackageDirNameFlag struct {
18+
FilterFlagBase
19+
20+
patterns []glob.Glob
21+
}
22+
23+
func (f *PackageDirNameFlag) Parse(cmd *cobra.Command) error {
24+
packageDirNamePatterns, err := cmd.Flags().GetString(cobraext.FilterPackageDirNameFlagName)
25+
if err != nil {
26+
return cobraext.FlagParsingError(err, cobraext.FilterPackageDirNameFlagName)
27+
}
28+
29+
patterns := splitAndTrim(packageDirNamePatterns, ",")
30+
for _, patternString := range patterns {
31+
pattern, err := glob.Compile(patternString)
32+
if err != nil {
33+
return fmt.Errorf("invalid package dir name pattern: %s: %w", patternString, err)
34+
}
35+
f.patterns = append(f.patterns, pattern)
36+
}
37+
38+
if len(f.patterns) > 0 {
39+
f.isApplied = true
40+
}
41+
42+
return nil
43+
}
44+
45+
func (f *PackageDirNameFlag) Validate() error {
46+
return nil
47+
}
48+
49+
func (f *PackageDirNameFlag) Matches(dirName string, manifest *packages.PackageManifest) bool {
50+
for _, pattern := range f.patterns {
51+
if pattern.Match(dirName) {
52+
return true
53+
}
54+
}
55+
return false
56+
}
57+
58+
func (f *PackageDirNameFlag) ApplyTo(pkgs []packages.PackageDirNameAndManifest) ([]packages.PackageDirNameAndManifest, error) {
59+
filtered := make([]packages.PackageDirNameAndManifest, 0, len(pkgs))
60+
for _, pkg := range pkgs {
61+
if f.Matches(pkg.DirName, pkg.Manifest) {
62+
filtered = append(filtered, pkg)
63+
}
64+
}
65+
return filtered, nil
66+
}
67+
68+
func initPackageDirNameFlag() *PackageDirNameFlag {
69+
return &PackageDirNameFlag{
70+
FilterFlagBase: FilterFlagBase{
71+
name: cobraext.FilterPackageDirNameFlagName,
72+
description: cobraext.FilterPackageDirNameFlagDescription,
73+
shorthand: "",
74+
defaultValue: "",
75+
},
76+
}
77+
}

internal/filter/packagename.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func (f *PackageNameFlag) Validate() error {
4848

4949
func (f *PackageNameFlag) Matches(dirName string, manifest *packages.PackageManifest) bool {
5050
for _, pattern := range f.patterns {
51-
if pattern.Match(dirName) {
51+
if pattern.Match(manifest.Name) {
5252
return true
5353
}
5454
}

internal/filter/registry.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ package filter
66

77
import (
88
"fmt"
9+
"os"
910

1011
"github.com/spf13/cobra"
1112

13+
"github.com/elastic/elastic-package/internal/cobraext"
1214
"github.com/elastic/elastic-package/internal/logger"
1315
"github.com/elastic/elastic-package/internal/multierror"
1416
"github.com/elastic/elastic-package/internal/packages"
@@ -18,27 +20,35 @@ var registry = []Filter{
1820
initCategoryFlag(),
1921
initCodeOwnerFlag(),
2022
initInputFlag(),
23+
initPackageDirNameFlag(),
2124
initPackageNameFlag(),
2225
initPackageTypeFlag(),
2326
initSpecVersionFlag(),
2427
}
2528

2629
// SetFilterFlags registers all filter flags with the given command.
2730
func SetFilterFlags(cmd *cobra.Command) {
31+
cmd.Flags().IntP(cobraext.FilterDepthFlagName, cobraext.FilterDepthFlagShorthand, cobraext.FilterDepthFlagDefault, cobraext.FilterDepthFlagDescription)
32+
cmd.Flags().StringP(cobraext.FilterExcludeDirFlagName, "", "", cobraext.FilterExcludeDirFlagDescription)
33+
2834
for _, filterFlag := range registry {
2935
filterFlag.Register(cmd)
3036
}
3137
}
3238

3339
// FilterRegistry manages a collection of filters for package filtering.
3440
type FilterRegistry struct {
35-
filters []Filter
41+
filters []Filter
42+
depth int
43+
excludeDirs string
3644
}
3745

3846
// NewFilterRegistry creates a new FilterRegistry instance.
39-
func NewFilterRegistry() *FilterRegistry {
47+
func NewFilterRegistry(depth int, excludeDirs string) *FilterRegistry {
4048
return &FilterRegistry{
41-
filters: []Filter{},
49+
filters: []Filter{},
50+
depth: depth,
51+
excludeDirs: excludeDirs,
4252
}
4353
}
4454

@@ -71,12 +81,12 @@ func (r *FilterRegistry) Validate() error {
7181
}
7282

7383
func (r *FilterRegistry) Execute() (filtered []packages.PackageDirNameAndManifest, errors multierror.Error) {
74-
root, err := packages.MustFindIntegrationRoot()
84+
currentDir, err := os.Getwd()
7585
if err != nil {
76-
return nil, multierror.Error{err}
86+
return nil, multierror.Error{fmt.Errorf("getting current directory failed: %w", err)}
7787
}
7888

79-
pkgs, err := packages.ReadAllPackageManifests(root)
89+
pkgs, err := packages.ReadAllPackageManifestsFromRepo(currentDir, r.depth, r.excludeDirs)
8090
if err != nil {
8191
return nil, multierror.Error{err}
8292
}

0 commit comments

Comments
 (0)