Skip to content

Commit f711c2d

Browse files
committed
#24 Allow to define multiple discovery directories. (#25)
1 parent 5d0524a commit f711c2d

File tree

14 files changed

+90
-79
lines changed

14 files changed

+90
-79
lines changed

app.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package launchr
33
import (
44
"errors"
55
"fmt"
6-
"io/fs"
76
"os"
87
"path/filepath"
98
"reflect"
@@ -33,7 +32,7 @@ type appImpl struct {
3332
actionMngr action.Manager
3433
pluginMngr PluginManager
3534
config Config
36-
regFS []fs.FS
35+
mFS []ManagedFS
3736
}
3837

3938
// getPluginByType returns specific plugins from the app.
@@ -70,8 +69,8 @@ func (app *appImpl) Name() string { return name }
7069
func (app *appImpl) GetWD() string { return app.workDir }
7170
func (app *appImpl) Streams() cli.Streams { return app.streams }
7271

73-
func (app *appImpl) AddDiscoveryFS(fs fs.FS) { app.regFS = append(app.regFS, fs) }
74-
func (app *appImpl) GetDiscoveryFS() []fs.FS { return app.regFS }
72+
func (app *appImpl) RegisterFS(fs ManagedFS) { app.mFS = append(app.mFS, fs) }
73+
func (app *appImpl) GetRegisteredFS() []ManagedFS { return app.mFS }
7574

7675
func (app *appImpl) AddService(s Service) {
7776
info := s.ServiceInfo()
@@ -112,12 +111,12 @@ func (app *appImpl) init() error {
112111
var err error
113112
// Set working dir and config dir.
114113
app.cfgDir = "." + name
115-
app.workDir, err = filepath.Abs("./")
114+
app.workDir, err = filepath.Abs(".")
116115
if err != nil {
117116
return err
118117
}
119-
app.regFS = make([]fs.FS, 0, 4)
120-
app.AddDiscoveryFS(os.DirFS(app.workDir))
118+
app.mFS = make([]ManagedFS, 0, 4)
119+
app.RegisterFS(action.NewDiscoveryFS(os.DirFS(app.workDir), app.GetWD()))
121120
// Prepare dependencies.
122121
app.streams = cli.StandardStreams()
123122
app.services = make(map[ServiceInfo]Service)
@@ -142,7 +141,7 @@ func (app *appImpl) init() error {
142141

143142
// Discover actions.
144143
for _, p := range getPluginByType[ActionDiscoveryPlugin](app) {
145-
for _, fs := range app.GetDiscoveryFS() {
144+
for _, fs := range app.GetRegisteredFS() {
146145
actions, err := p.DiscoverActions(fs)
147146
if err != nil {
148147
return err

internal/launchr/tools.go

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"os"
77
"path/filepath"
88
"reflect"
9-
"strings"
109
)
1110

1211
// GetFsAbsPath returns absolute path for a FS struct.
@@ -44,41 +43,3 @@ func GetTypePkgPathName(v interface{}) (string, string) {
4443
}
4544
return t.PkgPath(), t.Name()
4645
}
47-
48-
// ToCamelCase converts a string to CamelCase.
49-
// @todo reference module and license.
50-
func ToCamelCase(s string, capFirst bool) string {
51-
s = strings.TrimSpace(s)
52-
if s == "" {
53-
return s
54-
}
55-
56-
n := strings.Builder{}
57-
n.Grow(len(s))
58-
capNext := capFirst
59-
for i, v := range []byte(s) {
60-
vIsCap := v >= 'A' && v <= 'Z'
61-
vIsLow := v >= 'a' && v <= 'z'
62-
if capNext {
63-
if vIsLow {
64-
v += 'A'
65-
v -= 'a'
66-
}
67-
} else if i == 0 {
68-
if vIsCap {
69-
v += 'a'
70-
v -= 'A'
71-
}
72-
}
73-
if vIsCap || vIsLow {
74-
n.WriteByte(v)
75-
capNext = false
76-
} else if vIsNum := v >= '0' && v <= '9'; vIsNum {
77-
n.WriteByte(v)
78-
capNext = true
79-
} else {
80-
capNext = v == '_' || v == ' ' || v == '-' || v == '.'
81-
}
82-
}
83-
return n.String()
84-
}

internal/launchr/types.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@ type App interface {
2626
// GetService retrieves a service of type v and assigns it to v.
2727
// Panics if a service is not found.
2828
GetService(v interface{})
29-
// AddDiscoveryFS registers a File System for discovery of actions in launchr.
30-
AddDiscoveryFS(fs fs.FS)
31-
// GetDiscoveryFS returns an array of registered File Systems for action discovery.
32-
GetDiscoveryFS() []fs.FS
29+
// RegisterFS registers a File System in launchr.
30+
// It may be a FS for action discovery, see action.DiscoveryFS.
31+
RegisterFS(fs ManagedFS)
32+
// GetRegisteredFS returns an array of registered File Systems.
33+
GetRegisteredFS() []ManagedFS
3334
}
3435

3536
// AppVersion stores application version.
@@ -146,3 +147,9 @@ type Service interface {
146147
func InitServiceInfo(si *ServiceInfo, s Service) {
147148
si.pkgPath, si.typeName = GetTypePkgPathName(s)
148149
}
150+
151+
// ManagedFS is a common interface for FS registered in launchr.
152+
type ManagedFS interface {
153+
fs.FS
154+
FS() fs.FS
155+
}

pkg/action/action.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,14 @@ func (a *Action) Reset() { a.def = nil }
6868
// GetInput returns action input.
6969
func (a *Action) GetInput() Input { return a.input }
7070

71+
// WorkDir returns action working directory.
72+
func (a *Action) WorkDir() string { return a.wd }
73+
7174
// Filepath returns action file path.
7275
func (a *Action) Filepath() string { return a.fpath }
7376

7477
// Dir returns an action file directory.
75-
func (a *Action) Dir() string { return filepath.Dir(filepath.Join(a.wd, a.Filepath())) }
78+
func (a *Action) Dir() string { return filepath.Dir(a.Filepath()) }
7679

7780
// SetRunEnvironment sets environment to run the action.
7881
func (a *Action) SetRunEnvironment(env RunEnvironment) { a.env = env }

pkg/action/action_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ func Test_Action(t *testing.T) {
1313
assert := assert.New(t)
1414
// Prepare an action.
1515
fs := _getFsMapActions(1, validFullYaml, true)
16-
ad := NewYamlDiscovery(fs)
16+
ad := NewYamlDiscovery(NewDiscoveryFS(fs, ""))
1717
actions, err := ad.Discover()
1818
assert.NoError(err)
1919
assert.NotEmpty(actions)

pkg/action/discover.go

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,25 @@ var actionsSubdir = strings.Join([]string{"", actionsDirname, ""}, string(filepa
2020
// DiscoveryPlugin is a launchr plugin to discover actions.
2121
type DiscoveryPlugin interface {
2222
launchr.Plugin
23-
DiscoverActions(fs fs.FS) ([]*Action, error)
23+
DiscoverActions(fs launchr.ManagedFS) ([]*Action, error)
24+
}
25+
26+
// DiscoveryFS is a file system to discover actions.
27+
type DiscoveryFS struct {
28+
fs fs.FS
29+
wd string
30+
}
31+
32+
// NewDiscoveryFS creates a DiscoveryFS given fs - a filesystem to discover
33+
// and wd - working directory for an action, leave empty for current path.
34+
func NewDiscoveryFS(fs fs.FS, wd string) DiscoveryFS { return DiscoveryFS{fs, wd} }
35+
36+
// FS implements launchr.ManagedFS.
37+
func (f DiscoveryFS) FS() fs.FS { return f.fs }
38+
39+
// Open implements fs.FS and decorates the managed fs.
40+
func (f DiscoveryFS) Open(name string) (fs.File, error) {
41+
return f.FS().Open(name)
2442
}
2543

2644
// FileLoadFn is a type for loading a file.
@@ -34,15 +52,15 @@ type DiscoveryStrategy interface {
3452

3553
// Discovery defines a common functionality for discovering action files.
3654
type Discovery struct {
37-
fs fs.FS
38-
cwd string
39-
s DiscoveryStrategy
55+
fs DiscoveryFS
56+
fsDir string
57+
s DiscoveryStrategy
4058
}
4159

4260
// NewDiscovery creates an instance of action discovery.
43-
func NewDiscovery(fs fs.FS, ds DiscoveryStrategy) *Discovery {
44-
cwd := launchr.GetFsAbsPath(fs)
45-
return &Discovery{fs, cwd, ds}
61+
func NewDiscovery(fs DiscoveryFS, ds DiscoveryStrategy) *Discovery {
62+
fsDir := launchr.GetFsAbsPath(fs)
63+
return &Discovery{fs, fsDir, ds}
4664
}
4765

4866
func (ad *Discovery) isValid(path string, d fs.DirEntry) bool {
@@ -123,7 +141,7 @@ func (ad *Discovery) parseFile(f string) *Action {
123141
if id == "" {
124142
panic(fmt.Errorf("action id cannot be empty, file %q", f))
125143
}
126-
a := NewAction(id, ad.cwd, f)
144+
a := NewAction(id, absPath(ad.fs.wd), filepath.Join(ad.fsDir, f))
127145
a.Loader = ad.s.Loader(
128146
func() (fs.File, error) { return ad.fs.Open(f) },
129147
envProcessor{},

pkg/action/discover_test.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"testing/fstest"
99

1010
"github.com/moby/moby/pkg/namesgenerator"
11+
"github.com/stretchr/testify/assert"
1112
)
1213

1314
func Test_Discover(t *testing.T) {
@@ -44,7 +45,7 @@ func Test_Discover(t *testing.T) {
4445

4546
t.Run(tt.name, func(t *testing.T) {
4647
t.Parallel()
47-
ad := NewYamlDiscovery(tt.fs)
48+
ad := NewYamlDiscovery(NewDiscoveryFS(tt.fs, ""))
4849
actions, err := ad.Discover()
4950
if err != nil {
5051
t.Errorf("unexpected error %v", err)
@@ -56,6 +57,27 @@ func Test_Discover(t *testing.T) {
5657
}
5758
}
5859

60+
func Test_Discover_ActionWD(t *testing.T) {
61+
// Test if working directory is correctly set to actions on discovery.
62+
tfs := _getFsMapActions(1, validEmptyVersionYaml, true)
63+
var expFPath string
64+
for expFPath = range tfs {
65+
break
66+
}
67+
expectedWD := "expectedWD"
68+
ad := NewYamlDiscovery(NewDiscoveryFS(tfs, expectedWD))
69+
actions, err := ad.Discover()
70+
assert.NoError(t, err)
71+
assert.Equal(t, expFPath, actions[0].fpath)
72+
assert.Equal(t, absPath(expectedWD), actions[0].wd)
73+
74+
ad = NewYamlDiscovery(NewDiscoveryFS(tfs, ""))
75+
actions, err = ad.Discover()
76+
assert.NoError(t, err)
77+
assert.Equal(t, expFPath, actions[0].fpath)
78+
assert.Equal(t, absPath(""), actions[0].wd)
79+
}
80+
5981
type dirEntry string
6082

6183
func (d dirEntry) DirEntry() fs.DirEntry {
@@ -94,7 +116,7 @@ func Test_Discover_isValid(t *testing.T) {
94116
}
95117

96118
// Run tests.
97-
ad := NewYamlDiscovery(fstest.MapFS{})
119+
ad := NewYamlDiscovery(NewDiscoveryFS(fstest.MapFS{}, ""))
98120
for _, tt := range tts {
99121
tt := tt
100122
t.Run(tt.name, func(t *testing.T) {

pkg/action/env.container.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ func (c *containerEnv) Execute(ctx context.Context, a *Action) (err error) {
158158
if c.useVolWD {
159159
// @todo test somehow.
160160
cli.Println(`Flag "--%s" is set. Copying the working directory inside the container.`, containerFlagUseVolumeWD)
161-
err = c.copyDirToContainer(ctx, cid, ".", containerHostMount)
161+
err = c.copyDirToContainer(ctx, cid, a.WorkDir(), containerHostMount)
162162
if err != nil {
163163
return err
164164
}
@@ -229,7 +229,7 @@ func (c *containerEnv) Execute(ctx context.Context, a *Action) (err error) {
229229
// Copy back the result from the volume.
230230
// @todo it's a bad implementation considering consequential runs, need to find a better way to sync with remote.
231231
if c.useVolWD {
232-
path := absPath(".")
232+
path := a.WorkDir()
233233
cli.Println(`Flag "--%s" is set. Copying back the result of the action run.`, containerFlagUseVolumeWD)
234234
err = c.copyFromContainer(ctx, cid, containerHostMount, filepath.Dir(path), filepath.Base(path))
235235
defer func() {
@@ -384,7 +384,7 @@ func (c *containerEnv) containerCreate(ctx context.Context, a *Action, opts *typ
384384
}
385385
} else {
386386
createOpts.Binds = []string{
387-
absPath(".") + ":" + containerHostMount,
387+
absPath(a.WorkDir()) + ":" + containerHostMount,
388388
absPath(a.Dir()) + ":" + containerActionMount,
389389
}
390390
}

pkg/action/env.container_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ func testContainerAction(aconf *DefAction) *Action {
7474
ID: "test",
7575
Loader: &Definition{Action: aconf},
7676
fpath: "my/action/test/action.yaml",
77+
wd: absPath("test"),
7778
}
7879
}
7980

@@ -292,7 +293,7 @@ func Test_ContainerExec_containerCreate(t *testing.T) {
292293

293294
eqCfg := *runCfg
294295
eqCfg.Binds = []string{
295-
absPath(".") + ":" + containerHostMount,
296+
absPath(a.WorkDir()) + ":" + containerHostMount,
296297
absPath(a.Dir()) + ":" + containerActionMount,
297298
}
298299
eqCfg.WorkingDir = containerHostMount
@@ -522,7 +523,7 @@ func Test_ContainerExec(t *testing.T) {
522523
NetworkMode: types.NetworkModeHost,
523524
ExtraHosts: actConf.ExtraHosts,
524525
Binds: []string{
525-
absPath(".") + ":" + containerHostMount,
526+
absPath(act.WorkDir()) + ":" + containerHostMount,
526527
absPath(act.Dir()) + ":" + containerActionMount,
527528
},
528529
WorkingDir: containerHostMount,

pkg/action/yaml.discovery.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
var rgxYamlFile = regexp.MustCompile(`^action\.(yaml|yml)$`)
1313

1414
// NewYamlDiscovery is an implementation of discovery for searching yaml files.
15-
func NewYamlDiscovery(fs fs.FS) *Discovery {
15+
func NewYamlDiscovery(fs DiscoveryFS) *Discovery {
1616
return NewDiscovery(fs, YamlDiscoveryStrategy{TargetRgx: rgxYamlFile})
1717
}
1818

0 commit comments

Comments
 (0)