From 002ea5b1cbd63e19de71a1100649c15563dd36b1 Mon Sep 17 00:00:00 2001 From: Aleksandr Britvin Date: Thu, 15 May 2025 01:54:45 +0200 Subject: [PATCH 01/18] WIP #83 TestScript --- cmd/launchr/{launchr.go => main.go} | 0 gen.go | 2 +- go.mod | 2 + go.sum | 4 + internal/launchr/filepath.go | 10 +++ internal/launchr/filepath_test.go | 2 +- internal/launchr/types.go | 1 + internal/launchr/version.go | 24 +++--- pkg/action/action.go | 2 +- plugins/builder/builder.go | 4 +- plugins/builder/environment.go | 29 +++---- test/plugins/genaction/go.mod | 7 ++ test/plugins/genaction/plugin.go | 74 +++++++++++++++++ test/t_test.go | 44 ++++++++++ test/testdata/build/build.txtar | 54 +++++++++++++ test/testdata/build/version.txtar | 3 + test/testdata/common/discovery_basic.txtar | 80 +++++++++++++++++++ .../common/discovery_config_naming.txtar | 16 ++++ test/testdata/common/input.txtar | 1 + test/testdata/common/terminal.txtar | 1 + test/testdata/runtime/docker.txtar | 1 + test/testdata/runtime/shell.txtar | 1 + 22 files changed, 332 insertions(+), 30 deletions(-) rename cmd/launchr/{launchr.go => main.go} (100%) create mode 100644 test/plugins/genaction/go.mod create mode 100644 test/plugins/genaction/plugin.go create mode 100644 test/t_test.go create mode 100644 test/testdata/build/build.txtar create mode 100644 test/testdata/build/version.txtar create mode 100644 test/testdata/common/discovery_basic.txtar create mode 100644 test/testdata/common/discovery_config_naming.txtar create mode 100644 test/testdata/common/input.txtar create mode 100644 test/testdata/common/terminal.txtar create mode 100644 test/testdata/runtime/docker.txtar create mode 100644 test/testdata/runtime/shell.txtar diff --git a/cmd/launchr/launchr.go b/cmd/launchr/main.go similarity index 100% rename from cmd/launchr/launchr.go rename to cmd/launchr/main.go diff --git a/gen.go b/gen.go index ddc8103..a836804 100644 --- a/gen.go +++ b/gen.go @@ -20,7 +20,7 @@ func (app *appImpl) gen() error { // Set absolute paths. config.WorkDir = launchr.MustAbs(config.WorkDir) config.BuildDir = launchr.MustAbs(config.BuildDir) - // Change working directory to the selected. + // Change the working directory to the selected. err = os.Chdir(config.WorkDir) if err != nil { return err diff --git a/go.mod b/go.mod index 659d5ab..ad425cd 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/moby/sys/signal v0.7.1 github.com/moby/term v0.5.2 github.com/pterm/pterm v0.12.80 + github.com/rogpeppe/go-internal v1.14.1 github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 @@ -70,6 +71,7 @@ require ( golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect golang.org/x/term v0.29.0 // indirect golang.org/x/time v0.7.0 // indirect + golang.org/x/tools v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect gotest.tools/v3 v3.5.1 // indirect diff --git a/go.sum b/go.sum index 51587de..c06f621 100644 --- a/go.sum +++ b/go.sum @@ -329,6 +329,8 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -523,6 +525,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/launchr/filepath.go b/internal/launchr/filepath.go index a594108..5a384cc 100644 --- a/internal/launchr/filepath.go +++ b/internal/launchr/filepath.go @@ -157,6 +157,16 @@ func MkdirTemp(pattern string) (string, error) { if dirPath == "" { return "", fmt.Errorf("failed to create temp directory") } + return dirPath, nil +} + +// MkdirTempWithCleanup creates a temporary directory with MkdirTemp. +// The temp directory is removed when the app terminates. +func MkdirTempWithCleanup(pattern string) (string, error) { + dirPath, err := MkdirTemp(pattern) + if err != nil { + return "", err + } // Make sure the dir is cleaned on finish. RegisterCleanupFn(func() error { diff --git a/internal/launchr/filepath_test.go b/internal/launchr/filepath_test.go index 8128b55..6943f62 100644 --- a/internal/launchr/filepath_test.go +++ b/internal/launchr/filepath_test.go @@ -11,7 +11,7 @@ import ( func TestMkdirTemp(t *testing.T) { t.Parallel() - dir, err := MkdirTemp("test") + dir, err := MkdirTempWithCleanup("test") require.NoError(t, err) require.NotEmpty(t, dir) stat, err := os.Stat(dir) diff --git a/internal/launchr/types.go b/internal/launchr/types.go index 01530e7..f95052d 100644 --- a/internal/launchr/types.go +++ b/internal/launchr/types.go @@ -91,6 +91,7 @@ type AppVersion struct { CoreVersion string CoreReplace string Plugins []string + PluginsRepl []string } // PluginInfo provides information about the plugin and is used as a unique data to identify a plugin. diff --git a/internal/launchr/version.go b/internal/launchr/version.go index 8f3a20f..fba835c 100644 --- a/internal/launchr/version.go +++ b/internal/launchr/version.go @@ -43,13 +43,14 @@ func NewVersion(name, ver, bwith string, plugins PluginsMap) *AppVersion { buildInfo, _ := debug.ReadBuildInfo() // Add self as a dependency to get version for it also. buildInfo.Deps = append(buildInfo.Deps, &buildInfo.Main) - // Check core version when built or used in a plugin. + // Check a core version when built or used in a plugin. var coreRep string coreVer, coreRep := getCoreInfo(ver, buildInfo) if bwith == "" { ver = coreVer } + plver, plrepl := getPluginModules(plugins, buildInfo) return &AppVersion{ Name: name, Version: ver, @@ -58,7 +59,8 @@ func NewVersion(name, ver, bwith string, plugins PluginsMap) *AppVersion { CoreVersion: coreVer, CoreReplace: coreRep, BuiltWith: bwith, - Plugins: getPluginModules(plugins, buildInfo), + Plugins: plver, + PluginsRepl: plrepl, } } @@ -101,12 +103,13 @@ func getCoreInfo(v string, bi *debug.BuildInfo) (ver string, repl string) { return } -func getPluginModules(plugins PluginsMap, bi *debug.BuildInfo) []string { +func getPluginModules(plugins PluginsMap, bi *debug.BuildInfo) (res []string, repl []string) { if bi == nil { - return nil + return } - res := make([]string, 0, len(plugins)) + res = make([]string, 0, len(plugins)) + repl = make([]string, 0, len(plugins)) for pi := range plugins { if strings.HasPrefix(pi.pkgPath, PkgPath) { // Do not include info about the default package. @@ -116,15 +119,18 @@ func getPluginModules(plugins PluginsMap, bi *debug.BuildInfo) []string { // Path may be empty on "go run". if d.Path != "" && strings.HasPrefix(pi.pkgPath, d.Path) { s := fmt.Sprintf("%s %s", pi.pkgPath, d.Version) + r := s if d.Replace != nil { - s = fmt.Sprintf("%s => %s %s", s, d.Replace.Path, d.Replace.Version) + r = fmt.Sprintf("%s => %s %s", r, d.Replace.Path, d.Replace.Version) } res = append(res, s) + repl = append(res, r) } } } sort.Strings(res) - return res + sort.Strings(repl) + return } var versionTmpl = template.Must(template.New("version").Parse(versionTmplStr)) @@ -140,9 +146,9 @@ Core version: {{.CoreVersion}} {{- if .CoreReplace}} Core replace: {{.CoreReplace}} {{- end}} -{{- if .Plugins}} +{{- if .PluginsRepl}} Plugins: - {{- range .Plugins}} + {{- range .PluginsRepl}} - {{.}} {{- end}} {{end}}` diff --git a/pkg/action/action.go b/pkg/action/action.go index 7f65579..2ccb0d9 100644 --- a/pkg/action/action.go +++ b/pkg/action/action.go @@ -153,7 +153,7 @@ func (a *Action) syncToDisk() (err error) { // Export to a temporary path. // Make sure the path doesn't have semicolons, because Docker bind doesn't like it. tmpDirName := strings.Replace(a.ID, ":", "_", -1) - tmpDir, err := launchr.MkdirTemp(tmpDirName) + tmpDir, err := launchr.MkdirTempWithCleanup(tmpDirName) if err != nil { return } diff --git a/plugins/builder/builder.go b/plugins/builder/builder.go index bbfd3cf..265407f 100644 --- a/plugins/builder/builder.go +++ b/plugins/builder/builder.go @@ -77,7 +77,7 @@ type buildVars struct { Cwd string } -// NewBuilder creates build environment. +// NewBuilder creates a build environment. func NewBuilder(opts *BuildOptions) (*Builder, error) { wd, err := os.Getwd() if err != nil { @@ -94,7 +94,7 @@ func (b *Builder) Build(ctx context.Context, streams launchr.Streams) error { launchr.Term().Info().Printfln("Starting to build %s", b.PkgName) // Prepare build environment dir and go executable. var err error - b.env, err = newBuildEnvironment(streams) + b.env, err = newBuildEnvironment(streams, b.Debug) if err != nil { return err } diff --git a/plugins/builder/environment.go b/plugins/builder/environment.go index 58ab6bd..3a353cf 100644 --- a/plugins/builder/environment.go +++ b/plugins/builder/environment.go @@ -58,8 +58,14 @@ type buildEnvironment struct { streams launchr.Streams } -func newBuildEnvironment(streams launchr.Streams) (*buildEnvironment, error) { - tmpDir, err := launchr.MkdirTemp("build_") +func newBuildEnvironment(streams launchr.Streams, debug bool) (*buildEnvironment, error) { + var err error + var tmpDir string + if !debug { + tmpDir, err = launchr.MkdirTempWithCleanup("build_") + } else { + tmpDir, err = launchr.MkdirTemp("build_") + } if err != nil { return nil, err } @@ -103,18 +109,9 @@ func (env *buildEnvironment) CreateModFile(ctx context.Context, opts *BuildOptio } // Download core. - var coreRepl bool - for repl := range opts.ModReplace { - if strings.HasPrefix(opts.CorePkg.Path, repl) { - coreRepl = true - break - } - } - if !coreRepl { - err = env.execGoGet(ctx, opts.CorePkg.String()) - if err != nil { - return err - } + err = env.execGoGet(ctx, opts.CorePkg.String()) + if err != nil { + return err } // Download plugins. @@ -122,7 +119,7 @@ nextPlugin: for _, p := range opts.Plugins { // Do not get plugins of module subpath. for repl := range opts.ModReplace { - if strings.HasPrefix(p.Path, repl) { + if p.Path != repl && strings.HasPrefix(p.Path, repl) { continue nextPlugin } } @@ -160,7 +157,7 @@ func (env *buildEnvironment) execGoGet(ctx context.Context, args ...string) erro } func (env *buildEnvironment) RunCmd(ctx context.Context, cmd *exec.Cmd) error { - launchr.Log().Debug("executing shell", "cmd", cmd) + launchr.Log().Debug("executing shell", "cmd", cmd, "pwd", cmd.Dir) err := cmd.Start() if err != nil { return err diff --git a/test/plugins/genaction/go.mod b/test/plugins/genaction/go.mod new file mode 100644 index 0000000..abdd3b4 --- /dev/null +++ b/test/plugins/genaction/go.mod @@ -0,0 +1,7 @@ +module example.com/genaction + +go 1.24.1 + +replace github.com/launchrctl/launchr => ../../../ + +require github.com/launchrctl/launchr v0.0.0 diff --git a/test/plugins/genaction/plugin.go b/test/plugins/genaction/plugin.go new file mode 100644 index 0000000..929a544 --- /dev/null +++ b/test/plugins/genaction/plugin.go @@ -0,0 +1,74 @@ +package genaction + +import ( + "context" + "os" + "path/filepath" + + "github.com/launchrctl/launchr" + "github.com/launchrctl/launchr/pkg/action" +) + +// pluginTemplate is a go file that will be generated and included in the build. +const pluginTemplate = `package main +import ( + _ "embed" + my "{{.Pkg}}" +) +//go:embed {{.Yaml}} +var y []byte +func init() { my.ActionYaml = y }` + +// ActionYaml is a yaml content that will be set from an embedded file in [pluginTemplate]. +var ActionYaml []byte + +func init() { + launchr.RegisterPlugin(&Plugin{}) +} + +// Plugin is a test plugin declaration. +type Plugin struct{} + +// PluginInfo implements [launchr.Plugin] interface. +func (p *Plugin) PluginInfo() launchr.PluginInfo { + return launchr.PluginInfo{} +} + +// Generate implements [launchr.GeneratePlugin] interface. +func (p *Plugin) Generate(config launchr.GenerateConfig) error { + launchr.Term().Info().Printfln("Generating genaction...") + + actionyaml := "action.yaml" + const yaml = "{ runtime: plugin, action: { title: My plugin } }" + type tplvars struct { + Pkg string + Yaml string + } + + tpl := launchr.Template{Tmpl: pluginTemplate, Data: tplvars{ + Pkg: "example.com/genaction", + Yaml: actionyaml, + }} + err := tpl.WriteFile(filepath.Join(config.BuildDir, "genaction.gen.go")) + if err != nil { + return err + } + + err = os.WriteFile(filepath.Join(config.BuildDir, actionyaml), []byte(yaml), 0600) + if err != nil { + return err + } + + return nil +} + +// DiscoverActions implements [launchr.ActionDiscoveryPlugin] interface. +func (p *Plugin) DiscoverActions(_ context.Context) ([]*action.Action, error) { + a := action.NewFromYAML("genaction:example", ActionYaml) + a.SetRuntime(action.NewFnRuntime(func(_ context.Context, a *action.Action) error { + launchr.Term().Println("hello world") + return nil + })) + + return []*action.Action{a}, nil +} diff --git a/test/t_test.go b/test/t_test.go new file mode 100644 index 0000000..31e6d39 --- /dev/null +++ b/test/t_test.go @@ -0,0 +1,44 @@ +package test + +import ( + "testing" + + "github.com/rogpeppe/go-internal/testscript" + + "github.com/launchrctl/launchr" +) + +func TestMain(m *testing.M) { + testscript.Main(m, map[string]func(){ + "launchr": launchr.RunAndExit, + }) +} + +// TestBuild tests how binary builds and outputs version. +func TestBuild(t *testing.T) { + t.Parallel() + testscript.Run(t, testscript.Params{ + Dir: "testdata/build", + RequireExplicitExec: true, + RequireUniqueNames: true, + Setup: func(env *testscript.Env) error { + repoPath := launchr.MustAbs("../") + env.Vars = append( + env.Vars, + "REPO_PATH="+repoPath, + "CORE_PKG="+launchr.PkgPath, + ) + return nil + }, + }) +} + +func TestCommon(t *testing.T) { + t.Parallel() + testscript.Run(t, testscript.Params{ + Dir: "testdata/common", + RequireExplicitExec: true, + RequireUniqueNames: true, + ContinueOnError: true, + }) +} diff --git a/test/testdata/build/build.txtar b/test/testdata/build/build.txtar new file mode 100644 index 0000000..9c105f0 --- /dev/null +++ b/test/testdata/build/build.txtar @@ -0,0 +1,54 @@ +# DO NOT USE IT AS A REFERENCE! +# This is a special test case +# where we build the bin from the source. +# See other files for examples. + +# Test 1: Check the version string when built with ldflags +env APP_NAME=myapp +env APP_VERSION='v1.1.0-testscript' +env APP_BUILT_WITH='testscript v1.0.0' +env ARCH_RGX=[a-z0-9]+/[a-z0-9]+ +env APP_VERSION_SHORT=$APP_NAME' version '${APP_VERSION@R}' '$ARCH_RGX + +# Build the binary. +env HOME=$TMPDIR +env APP_LDFLAGS=-X' '"$CORE_PKG.name=$APP_NAME"' -X '"$CORE_PKG.version=$APP_VERSION"' -X '"$CORE_PKG.builtWith=$APP_BUILT_WITH" +exec go build -C $REPO_PATH -ldflags $APP_LDFLAGS -o $WORK/$APP_NAME ./cmd/launchr + +# Test 1: Check version output. +exec ./$APP_NAME --version +stdout ^$APP_VERSION_SHORT'\nBuilt with '${APP_BUILT_WITH@R}\z$ +! stderr . + +# Test 2: Build a new binary using the old, check the version string. +# Replace the core to always build from the latest. +env APP_NAME_2=${APP_NAME}new +env APP_VERSION_2='v1.2.0-testscript' +env APP_VERSION_CORE='Core version: v.*\nCore replace: '${CORE_PKG@R}' v.* => '${REPO_PATH@R}' \(devel\)' +env APP_VERSION_FULL=$APP_NAME_2' version '$APP_VERSION_2' '$ARCH_RGX'\nBuilt with '${APP_VERSION_SHORT}'\n'$APP_VERSION_CORE + +exec ./$APP_NAME build --no-cache --tag nethttpomithttp2 -n $APP_NAME_2 -o $APP_NAME_2 -r $CORE_PKG=$REPO_PATH --build-version $APP_VERSION_2 + +exec ./$APP_NAME_2 --version +stdout ^$APP_VERSION_FULL'\z$' +! stderr . + +# Test 3: Build a new binary with incorrect app name. +! exec ./$APP_NAME build -n under_score -o under_score --build-version invalid +stdout 'invalid application name "under_score"' + +# Test 4: Build with plugins and replace. +# Add 1 arbitrary repository as a plugin, we need to test a public source but prevent possible build errors. +# We will may have a bit broken version, but it's ok for the test. +env APP_PLUGIN_1=golang.org/x/term +# Add 1 test plugin from test data with replace. +env APP_PLUGIN_2=example.com/genaction@v1.1.1 +exec ./$APP_NAME build -n $APP_NAME_2 -o $APP_NAME_2 -r $CORE_PKG=$REPO_PATH -p $APP_PLUGIN_1 -p $APP_PLUGIN_2 -r $APP_PLUGIN_2=$REPO_PATH/test/plugins/genaction --build-version $APP_VERSION_2 + +exec ./$APP_NAME_2 --version +stdout ^$APP_VERSION_FULL'\nPlugins:\n - example\.com/genaction v1\.1\.1\n - example\.com/genaction v1\.1\.1 => '$REPO_PATH'/test/genaction \(devel\)\n\z$' +! stderr . + +# Test 5: Check the generated action is included and works well. +exec ./$APP_NAME_2 genaction:example +stdout 'hello world' diff --git a/test/testdata/build/version.txtar b/test/testdata/build/version.txtar new file mode 100644 index 0000000..c72e5df --- /dev/null +++ b/test/testdata/build/version.txtar @@ -0,0 +1,3 @@ +# TODO: Separate build.txtar + +# TODO: Test config dir according to application name \ No newline at end of file diff --git a/test/testdata/common/discovery_basic.txtar b/test/testdata/common/discovery_basic.txtar new file mode 100644 index 0000000..cd17d24 --- /dev/null +++ b/test/testdata/common/discovery_basic.txtar @@ -0,0 +1,80 @@ +exec launchr --help + +# Actions are grouped and sorted. +stdout '^\s+Actions:\n\s+bar\s+$' + +# Valid discovered actions +stdout '^\s+bar\s+bar$' +stdout '^\s+foo\s+foo$' +stdout '^\s+foo\.bar\.baz:fred\s+fred$' +stdout '^\s+foo-bar_baz:waldo!fred:thud\.1\s+valid special chars' +stdout '^\s+foo\.bar\.baz:waldo\s+waldo$' + +# Actions that must not appear +! stdout '^\s+foo-bar_baz:waldo.fred\s+invalid special chars$' +! stdout '^\s+(.)hidden:foo\s+foo hidden skipped$' +! stdout '^\s+(.)hidden:bar\s+bar hidden skipped$' +! stdout '^\s+foo\.bar\.baz:incorrect\s+incorrect actions path$' +! stdout '^\s+foo\.bar\.baz:subdir.*$' + +! stderr . + +-- actions/foo/action.yaml -- +action: + title: foo +runtime: + type: container + image: alpine + command: [/bin/sh, ls] + +-- actions/bar/action.yaml -- +action: + title: bar +runtime: + type: shell + script: ls -al + +-- foo-bar_baz/actions/waldo!fred:thud.1/action.yaml -- +action: { title: valid special chars } +runtime: plugin + +-- foo-bar_baz/actions/waldo fred/action.yaml -- +action: { title: invalid special chars } +runtime: plugin + +-- foo/bar/baz/actions/waldo/action.yaml -- +action: + title: waldo +runtime: plugin + +-- foo/bar/baz/actions/fred/action.yaml -- +action: + title: fred +runtime: plugin + +-- foo/bar/baz/actions/broken/action.yaml -- +action: + title: broken +runtime: + type: container + # missing container properties. + +-- .hidden/actions/foo/action.yaml -- +action: + title: foo hidden skipped +runtime: plugin + +-- .hidden/actions/bar/action.yaml -- +action: + title: bar hidden skipped +runtime: plugin + +-- foo/bar/baz/myactions/incorrect/action.yaml -- +action: + title: incorrect actions path +runtime: plugin + +-- foo/bar/baz/actions/subdir/foo/action.yaml -- +action: + title: foo incorrect pos of yaml in subdir +runtime: plugin diff --git a/test/testdata/common/discovery_config_naming.txtar b/test/testdata/common/discovery_config_naming.txtar new file mode 100644 index 0000000..8225b63 --- /dev/null +++ b/test/testdata/common/discovery_config_naming.txtar @@ -0,0 +1,16 @@ +exec launchr --help +stdout '^\s+foo\.baz\.bar-bar:waldo-fred-thud\s+foo$' +! stderr . + +-- foo/bar/baz/bar/bar_bar/actions/waldo-fred_thud/action.yaml -- +action: + title: foo +runtime: plugin + +-- .launchr/config.yaml -- +launchrctl: + actions_naming: + - search: ".bar." + replace: "." + - search: "_" + replace: "-" \ No newline at end of file diff --git a/test/testdata/common/input.txtar b/test/testdata/common/input.txtar new file mode 100644 index 0000000..6286849 --- /dev/null +++ b/test/testdata/common/input.txtar @@ -0,0 +1 @@ +# TODO Test commands with different input types and mandatory + basic jsonschema validation \ No newline at end of file diff --git a/test/testdata/common/terminal.txtar b/test/testdata/common/terminal.txtar new file mode 100644 index 0000000..81d1681 --- /dev/null +++ b/test/testdata/common/terminal.txtar @@ -0,0 +1 @@ +# TODO Test terminal log level, log format and quiet mode \ No newline at end of file diff --git a/test/testdata/runtime/docker.txtar b/test/testdata/runtime/docker.txtar new file mode 100644 index 0000000..1352806 --- /dev/null +++ b/test/testdata/runtime/docker.txtar @@ -0,0 +1 @@ +# TODO Test docker runtime \ No newline at end of file diff --git a/test/testdata/runtime/shell.txtar b/test/testdata/runtime/shell.txtar new file mode 100644 index 0000000..5c5d8e4 --- /dev/null +++ b/test/testdata/runtime/shell.txtar @@ -0,0 +1 @@ +# TODO Test shell runtime \ No newline at end of file From 3c5f002bcbc900d37b663bfe285c99e0ec4f37a8 Mon Sep 17 00:00:00 2001 From: Aleksandr Britvin Date: Sat, 17 May 2025 23:05:27 +0200 Subject: [PATCH 02/18] WIP #83 TestScript --- .github/workflows/test.yaml | 37 +++++++++++++ Makefile | 2 +- main_test.go | 64 ++++++++++++++++++++++ test/README.md | 3 + test/t_test.go | 44 --------------- test/testdata/common/discovery_basic.txtar | 2 +- test/testdata/common/processors.txtar | 1 + 7 files changed, 107 insertions(+), 46 deletions(-) create mode 100644 .github/workflows/test.yaml create mode 100644 main_test.go create mode 100644 test/README.md delete mode 100644 test/t_test.go create mode 100644 test/testdata/common/processors.txtar diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..a4e539d --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,37 @@ +name: Run tests +on: + push: + branches: + - '**' + pull_request: + branches: + - '**' + +jobs: + test: + name: Test on ${{ matrix.os }} + strategy: + matrix: + include: + - os: ubuntu-latest + arch: amd64 + - os: ubuntu-latest + arch: arm64 + - os: macos-latest + arch: amd64 + - os: macos-latest + arch: arm64 + - os: windows-latest + arch: amd64 + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 'stable' + architecture: ${{ matrix.arch }} + + - name: Test + run: go test ./... diff --git a/Makefile b/Makefile index 2e9a3cb..9c17cc9 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ deps: .PHONY: test test: $(info Running tests...) - go test ./... + go test -short ./... # Build launchr .PHONY: build diff --git a/main_test.go b/main_test.go new file mode 100644 index 0000000..252e0d8 --- /dev/null +++ b/main_test.go @@ -0,0 +1,64 @@ +package launchr + +import ( + "testing" + + "github.com/rogpeppe/go-internal/testscript" +) + +func TestMain(m *testing.M) { + testscript.Main(m, map[string]func(){ + "launchr": RunAndExit, + }) +} + +// TODO: Implement test groups build/runtime/unit +// TestScriptBuild tests how binary builds and outputs version. +func TestScriptBuild(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + testscript.Run(t, testscript.Params{ + Dir: "test/testdata/build", + RequireExplicitExec: true, + RequireUniqueNames: true, + Setup: func(env *testscript.Env) error { + repoPath := MustAbs("./") + env.Vars = append( + env.Vars, + "REPO_PATH="+repoPath, + "CORE_PKG="+PkgPath, + ) + return nil + }, + }) +} + +func TestScriptCommon(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + t.Parallel() + type testCase struct { + name string + files []string + } + commonDir := "test/testdata/common" + tests := []testCase{ + {"action discovery basic", []string{commonDir + "/discovery_basic.txtar"}}, + {"action discovery config naming", []string{commonDir + "/discovery_config_naming.txtar"}}, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + testscript.Run(t, testscript.Params{ + Files: tt.files, + RequireExplicitExec: true, + RequireUniqueNames: true, + ContinueOnError: true, + }) + }) + } + +} diff --git a/test/README.md b/test/README.md new file mode 100644 index 0000000..1f554f2 --- /dev/null +++ b/test/README.md @@ -0,0 +1,3 @@ +# Integration tests + +This directory contains integration tests and their test data. \ No newline at end of file diff --git a/test/t_test.go b/test/t_test.go deleted file mode 100644 index 31e6d39..0000000 --- a/test/t_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package test - -import ( - "testing" - - "github.com/rogpeppe/go-internal/testscript" - - "github.com/launchrctl/launchr" -) - -func TestMain(m *testing.M) { - testscript.Main(m, map[string]func(){ - "launchr": launchr.RunAndExit, - }) -} - -// TestBuild tests how binary builds and outputs version. -func TestBuild(t *testing.T) { - t.Parallel() - testscript.Run(t, testscript.Params{ - Dir: "testdata/build", - RequireExplicitExec: true, - RequireUniqueNames: true, - Setup: func(env *testscript.Env) error { - repoPath := launchr.MustAbs("../") - env.Vars = append( - env.Vars, - "REPO_PATH="+repoPath, - "CORE_PKG="+launchr.PkgPath, - ) - return nil - }, - }) -} - -func TestCommon(t *testing.T) { - t.Parallel() - testscript.Run(t, testscript.Params{ - Dir: "testdata/common", - RequireExplicitExec: true, - RequireUniqueNames: true, - ContinueOnError: true, - }) -} diff --git a/test/testdata/common/discovery_basic.txtar b/test/testdata/common/discovery_basic.txtar index cd17d24..7bce8d0 100644 --- a/test/testdata/common/discovery_basic.txtar +++ b/test/testdata/common/discovery_basic.txtar @@ -1,7 +1,7 @@ exec launchr --help # Actions are grouped and sorted. -stdout '^\s+Actions:\n\s+bar\s+$' +stdout '^\s+Actions:\n\s+bar\s+' # Valid discovered actions stdout '^\s+bar\s+bar$' diff --git a/test/testdata/common/processors.txtar b/test/testdata/common/processors.txtar new file mode 100644 index 0000000..4c69908 --- /dev/null +++ b/test/testdata/common/processors.txtar @@ -0,0 +1 @@ +# Test processors \ No newline at end of file From d9b4b747e720ec0c8ab34c1cf4ec323796c02fd8 Mon Sep 17 00:00:00 2001 From: Aleksandr Britvin Date: Sat, 17 May 2025 23:09:53 +0200 Subject: [PATCH 03/18] WIP #83 TestScript --- .github/workflows/test.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index a4e539d..faf22cd 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -9,7 +9,7 @@ on: jobs: test: - name: Test on ${{ matrix.os }} + name: Test on ${{ matrix.os }} / ${{ matrix.arch }} strategy: matrix: include: @@ -31,7 +31,6 @@ jobs: uses: actions/setup-go@v5 with: go-version: 'stable' - architecture: ${{ matrix.arch }} - name: Test run: go test ./... From f783f78c3bdd0be3566b89143c2b3969dd9de23d Mon Sep 17 00:00:00 2001 From: Aleksandr Britvin Date: Sat, 17 May 2025 23:20:18 +0200 Subject: [PATCH 04/18] WIP #83 TestScript --- .github/workflows/test.yaml | 3 +++ main_test.go | 28 ++++++---------------------- test/testdata/build/build.txtar | 2 +- 3 files changed, 10 insertions(+), 23 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index faf22cd..6369f43 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -32,5 +32,8 @@ jobs: with: go-version: 'stable' + - name: Prepare dependencies + run: go mod download + - name: Test run: go test ./... diff --git a/main_test.go b/main_test.go index 252e0d8..01dda8c 100644 --- a/main_test.go +++ b/main_test.go @@ -39,26 +39,10 @@ func TestScriptCommon(t *testing.T) { t.Skip("skipping test in short mode.") } t.Parallel() - type testCase struct { - name string - files []string - } - commonDir := "test/testdata/common" - tests := []testCase{ - {"action discovery basic", []string{commonDir + "/discovery_basic.txtar"}}, - {"action discovery config naming", []string{commonDir + "/discovery_config_naming.txtar"}}, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - testscript.Run(t, testscript.Params{ - Files: tt.files, - RequireExplicitExec: true, - RequireUniqueNames: true, - ContinueOnError: true, - }) - }) - } - + testscript.Run(t, testscript.Params{ + Dir: "test/testdata/common", + RequireExplicitExec: true, + RequireUniqueNames: true, + ContinueOnError: true, + }) } diff --git a/test/testdata/build/build.txtar b/test/testdata/build/build.txtar index 9c105f0..27c3732 100644 --- a/test/testdata/build/build.txtar +++ b/test/testdata/build/build.txtar @@ -46,7 +46,7 @@ env APP_PLUGIN_2=example.com/genaction@v1.1.1 exec ./$APP_NAME build -n $APP_NAME_2 -o $APP_NAME_2 -r $CORE_PKG=$REPO_PATH -p $APP_PLUGIN_1 -p $APP_PLUGIN_2 -r $APP_PLUGIN_2=$REPO_PATH/test/plugins/genaction --build-version $APP_VERSION_2 exec ./$APP_NAME_2 --version -stdout ^$APP_VERSION_FULL'\nPlugins:\n - example\.com/genaction v1\.1\.1\n - example\.com/genaction v1\.1\.1 => '$REPO_PATH'/test/genaction \(devel\)\n\z$' +stdout ^$APP_VERSION_FULL'\nPlugins:\n - example\.com/genaction v1\.1\.1\n - example\.com/genaction v1\.1\.1 => '$REPO_PATH'/test/plugins/genaction \(devel\)\n\z$' ! stderr . # Test 5: Check the generated action is included and works well. From bbca4a6a42e1d852f12a18b4efa8518d192f8beb Mon Sep 17 00:00:00 2001 From: Aleksandr Britvin Date: Sat, 17 May 2025 23:28:56 +0200 Subject: [PATCH 05/18] WIP #83 TestScript --- .github/workflows/test.yaml | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 6369f43..77df629 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -9,22 +9,34 @@ on: jobs: test: - name: Test on ${{ matrix.os }} / ${{ matrix.arch }} + name: Test on ${{ matrix.name }} strategy: matrix: include: - - os: ubuntu-latest - arch: amd64 - - os: ubuntu-latest - arch: arm64 - - os: macos-latest - arch: amd64 - - os: macos-latest - arch: arm64 - - os: windows-latest - arch: amd64 + - name: Linux / AMD64 + os: ubuntu-latest + - name: Linux / ARM64 + os: ubuntu-latest-arm64 + - name: MacOS / ARM64 + os: macos-latest + - name: Windows / AMD64 + os: windows-latest + - name: Windows / ARM64 + os: windows-latest-arm64 runs-on: ${{ matrix.os }} steps: + - name: Show OS and architecture info + run: | + echo "OS: ${{ runner.os }}" + echo "Architecture: ${{ runner.arch }}" + if [ "${{ runner.os }}" = "Windows" ]; then + echo "%OS%" + echo "%PROCESSOR_ARCHITECTURE%" + else + echo "$OSTYPE" + echo "$(uname -m)" + fi + - uses: actions/checkout@v4 - name: Set up Go From 2ff58a46baa08cb486fa6b848ee2a96fc1b0e5f7 Mon Sep 17 00:00:00 2001 From: Aleksandr Britvin Date: Sun, 18 May 2025 00:46:09 +0200 Subject: [PATCH 06/18] WIP #83 TestScript --- .github/actions/os-info/README.md | 28 ++++++++++++++++++++ .github/actions/os-info/action.yml | 41 ++++++++++++++++++++++++++++++ .github/workflows/test.yaml | 18 +++++-------- 3 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 .github/actions/os-info/README.md create mode 100644 .github/actions/os-info/action.yml diff --git a/.github/actions/os-info/README.md b/.github/actions/os-info/README.md new file mode 100644 index 0000000..26c225d --- /dev/null +++ b/.github/actions/os-info/README.md @@ -0,0 +1,28 @@ +# OS Info GitHub Action + +This action detects and outputs information about the current operating system and architecture directly to stdout. + +## Information Provided + +The action outputs the following information directly to the console: + +| Information | Description | +|-------------|-------------| +| OS | The operating system (Linux, macOS, Windows) | +| Architecture | The architecture (amd64, arm64, etc.) | +| OS Version | The OS version or distribution | + +## Example Usage + +```yaml +jobs: + example-job: + runs-on: ubuntu-latest + steps: + - name: Get OS Info + uses: launchrctl/launchr/.github/actions/os-info@main + # The action will output OS information directly to the console + # No need to capture or use outputs in subsequent steps + + - uses: actions/checkout@v4 +``` diff --git a/.github/actions/os-info/action.yml b/.github/actions/os-info/action.yml new file mode 100644 index 0000000..6e9aa3b --- /dev/null +++ b/.github/actions/os-info/action.yml @@ -0,0 +1,41 @@ +name: 'OS Info' +description: 'Get information about the current operating system and architecture' + +runs: + using: "composite" + steps: + - name: OS and Architecture (Linux) + if: runner.os == 'Linux' + shell: bash + run: | + # Set OS + echo "OS Type: Linux" + echo "Architecture: $(uname -m)" + echo "Kernel version: $(uname -r)" + if [ -f /etc/os-release ]; then + . /etc/os-release + echo "OS Version: $NAME $VERSION_ID" + else + echo "OS Version: unknown" + fi + + - name: OS and Architecture (macOS) + if: runner.os == 'macOS' + shell: bash + run: | + echo "OS: macOS" + echo "Architecture: $(uname -m)" + # Get OS Version + OS_VERSION="$(sw_vers -productName) $(sw_vers -productVersion)" + echo "OS Version: $OS_VERSION" + + - name: OS and Architecture (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: | + $arch = [System.Environment]::GetEnvironmentVariable("PROCESSOR_ARCHITECTURE") + $winVer = [System.Environment]::OSVersion.Version.ToString() + + Write-Host "OS: Windows" + Write-Host "Architecture: $arch" + Write-Host "OS Version: Windows $winVer" diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 77df629..699893d 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -21,24 +21,18 @@ jobs: os: macos-latest - name: Windows / AMD64 os: windows-latest + continue-on-error: true - name: Windows / ARM64 os: windows-latest-arm64 + continue-on-error: true runs-on: ${{ matrix.os }} + continue-on-error: ${{ matrix.continue-on-error || false }} steps: - - name: Show OS and architecture info - run: | - echo "OS: ${{ runner.os }}" - echo "Architecture: ${{ runner.arch }}" - if [ "${{ runner.os }}" = "Windows" ]; then - echo "%OS%" - echo "%PROCESSOR_ARCHITECTURE%" - else - echo "$OSTYPE" - echo "$(uname -m)" - fi - - uses: actions/checkout@v4 + - name: Get OS Info + uses: ./.github/actions/os-info + - name: Set up Go uses: actions/setup-go@v5 with: From 0bc397a3ba8baff62c78fbb1b67a6feb50d46802 Mon Sep 17 00:00:00 2001 From: Aleksandr Britvin Date: Sun, 18 May 2025 01:02:37 +0200 Subject: [PATCH 07/18] WIP #83 TestScript --- .github/workflows/test.yaml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 699893d..bef0361 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -1,4 +1,4 @@ -name: Run tests +name: Tests on: push: branches: @@ -6,6 +6,7 @@ on: pull_request: branches: - '**' + workflow_call: jobs: test: @@ -16,21 +17,21 @@ jobs: - name: Linux / AMD64 os: ubuntu-latest - name: Linux / ARM64 - os: ubuntu-latest-arm64 + os: ubuntu-24.04-arm - name: MacOS / ARM64 os: macos-latest - name: Windows / AMD64 os: windows-latest continue-on-error: true - name: Windows / ARM64 - os: windows-latest-arm64 + os: windows-11-arm continue-on-error: true runs-on: ${{ matrix.os }} continue-on-error: ${{ matrix.continue-on-error || false }} steps: - uses: actions/checkout@v4 - - name: Get OS Info + - name: OS Info uses: ./.github/actions/os-info - name: Set up Go @@ -42,4 +43,5 @@ jobs: run: go mod download - name: Test - run: go test ./... + run: | + go test ./... From 46c8b3dba4db08e19997326e353e98daf7a7edd6 Mon Sep 17 00:00:00 2001 From: Aleksandr Britvin Date: Sun, 18 May 2025 13:04:59 +0200 Subject: [PATCH 08/18] WIP #83 TestScript --- main_test.go | 10 +++++----- pkg/action/discover.go | 3 +-- pkg/action/discover_test.go | 4 ++++ pkg/action/yaml.discovery.go | 2 +- test/testdata/common/discovery_basic.txtar | 20 +++++++++++++++++--- 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/main_test.go b/main_test.go index 01dda8c..7ae4a5d 100644 --- a/main_test.go +++ b/main_test.go @@ -1,6 +1,7 @@ package launchr import ( + "runtime" "testing" "github.com/rogpeppe/go-internal/testscript" @@ -12,11 +13,13 @@ func TestMain(m *testing.M) { }) } -// TODO: Implement test groups build/runtime/unit // TestScriptBuild tests how binary builds and outputs version. func TestScriptBuild(t *testing.T) { if testing.Short() { - t.Skip("skipping test in short mode.") + t.Skip("skipping test in short mode") + } + if runtime.GOOS == "windows" { + t.Skip("skipping test on Windows") } testscript.Run(t, testscript.Params{ Dir: "test/testdata/build", @@ -35,9 +38,6 @@ func TestScriptBuild(t *testing.T) { } func TestScriptCommon(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } t.Parallel() testscript.Run(t, testscript.Params{ Dir: "test/testdata/common", diff --git a/pkg/action/discover.go b/pkg/action/discover.go index 445aebb..5ac2c67 100644 --- a/pkg/action/discover.go +++ b/pkg/action/discover.go @@ -7,7 +7,6 @@ import ( "os" "path/filepath" "sort" - "strings" "sync" "time" @@ -16,7 +15,7 @@ import ( const actionsDirname = "actions" -var actionsSubdir = strings.Join([]string{"", actionsDirname, ""}, string(filepath.Separator)) +var actionsSubdir = filepath.FromSlash("/" + actionsDirname + "/") // DiscoveryPlugin is a launchr plugin to discover actions. type DiscoveryPlugin interface { diff --git a/pkg/action/discover_test.go b/pkg/action/discover_test.go index b98bddd..29dff0c 100644 --- a/pkg/action/discover_test.go +++ b/pkg/action/discover_test.go @@ -120,6 +120,10 @@ func Test_Discover_isValid(t *testing.T) { {"incorrect hidden subdir path", "1/2/.github/actions/3/action.yml", false}, // Invalid hidden subdirectory. {"nested action", "1/2/actions/3/4/5/action.yaml", false}, // There is a deeper nesting in actions directory. {"root action", "actions/verb/action.yaml", true}, // Actions are located in root. + {"special chars action in root", "actions/foo!bar/action.yaml", false}, // Actions are located in root and with special characters. + {"special chars action 1", "?/actions/foo/action.yaml", false}, // Actions are located in root and with special characters. + {"special chars action 2", "foo/actions/foo<>bar/action.yaml", false}, // Actions are located in root and with special characters. + {"special chars action 3", "foo/!<>/actions/foo\\bar/action.yaml", false}, // Actions are located in root and with special characters. {"root myactions", "myactions/verb/action.yaml", false}, // Actions are located in dir ending with actions. {"dir", "1/2/actions/3", false}, // A directory is given. } diff --git a/pkg/action/yaml.discovery.go b/pkg/action/yaml.discovery.go index f633d8d..d57e729 100644 --- a/pkg/action/yaml.discovery.go +++ b/pkg/action/yaml.discovery.go @@ -10,7 +10,7 @@ import ( var ( // rgxYamlFilepath is a regex for a yaml path with unix and windows support. - rgxYamlFilepath = regexp.MustCompile(`(^actions|.*[\\/]actions)[\\/][^\\/]+[\\/]action\.y(a)?ml$`) + rgxYamlFilepath = regexp.MustCompile(`(^actions|[^!<>:"|?*]+[\\/]actions)[\\/][^\\/!<>:"|?*]+[\\/]action\.y(a)?ml$`) // rgxYamlRootFile is a regex for a yaml file located in root dir only. rgxYamlRootFile = regexp.MustCompile(`^action\.y(a)?ml$`) ) diff --git a/test/testdata/common/discovery_basic.txtar b/test/testdata/common/discovery_basic.txtar index 7bce8d0..1e22202 100644 --- a/test/testdata/common/discovery_basic.txtar +++ b/test/testdata/common/discovery_basic.txtar @@ -7,11 +7,13 @@ stdout '^\s+Actions:\n\s+bar\s+' stdout '^\s+bar\s+bar$' stdout '^\s+foo\s+foo$' stdout '^\s+foo\.bar\.baz:fred\s+fred$' -stdout '^\s+foo-bar_baz:waldo!fred:thud\.1\s+valid special chars' +stdout '^\s+foo-bar_baz:waldo-fred.1\s+valid special chars' stdout '^\s+foo\.bar\.baz:waldo\s+waldo$' # Actions that must not appear ! stdout '^\s+foo-bar_baz:waldo.fred\s+invalid special chars$' +! stdout '^\s+foo-bar_baz:waldo\s+invalid special chars$' +! stdout '^\s+waldo.fred\s+invalid special chars$' ! stdout '^\s+(.)hidden:foo\s+foo hidden skipped$' ! stdout '^\s+(.)hidden:bar\s+bar hidden skipped$' ! stdout '^\s+foo\.bar\.baz:incorrect\s+incorrect actions path$' @@ -34,11 +36,23 @@ runtime: type: shell script: ls -al --- foo-bar_baz/actions/waldo!fred:thud.1/action.yaml -- +-- foo-bar_baz/actions/waldo-fred.1/action.yaml -- action: { title: valid special chars } runtime: plugin --- foo-bar_baz/actions/waldo fred/action.yaml -- +-- foo-bar_baz/actions/waldo\ fred/action.yaml -- +action: { title: invalid special chars } +runtime: plugin + +-- foo-bar_baz/actions/waldo!fred/action.yaml -- +action: { title: invalid special chars } +runtime: plugin + +-- actions/waldo*fred/action.yaml -- +action: { title: invalid special chars } +runtime: plugin + +-- actions/waldo\\fred/action.yaml -- action: { title: invalid special chars } runtime: plugin From 9c88be3d61512bfef429f8a8df632e430426b325 Mon Sep 17 00:00:00 2001 From: Aleksandr Britvin Date: Sun, 18 May 2025 15:12:50 +0200 Subject: [PATCH 09/18] WIP #83 TestScript --- internal/launchr/lockedfile_windows.go | 2 +- pkg/action/discover_test.go | 10 ++++++---- pkg/action/yaml.discovery.go | 5 +++-- test/testdata/common/discovery_basic.txtar | 17 +++++++---------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/internal/launchr/lockedfile_windows.go b/internal/launchr/lockedfile_windows.go index 8113bae..419c6c1 100644 --- a/internal/launchr/lockedfile_windows.go +++ b/internal/launchr/lockedfile_windows.go @@ -31,7 +31,7 @@ func (f *LockedFile) unlock() { ol := new(windows.Overlapped) err := windows.UnlockFileEx(windows.Handle(f.file.Fd()), 0, allBytes, allBytes, ol) if err != nil { - Log().Warn("unlock is called on a not locked file: %s", err) + Log().Warn("unlock is called on a not locked file", "err", err) } f.locked = false } diff --git a/pkg/action/discover_test.go b/pkg/action/discover_test.go index 29dff0c..37d1572 100644 --- a/pkg/action/discover_test.go +++ b/pkg/action/discover_test.go @@ -120,10 +120,12 @@ func Test_Discover_isValid(t *testing.T) { {"incorrect hidden subdir path", "1/2/.github/actions/3/action.yml", false}, // Invalid hidden subdirectory. {"nested action", "1/2/actions/3/4/5/action.yaml", false}, // There is a deeper nesting in actions directory. {"root action", "actions/verb/action.yaml", true}, // Actions are located in root. - {"special chars action in root", "actions/foo!bar/action.yaml", false}, // Actions are located in root and with special characters. - {"special chars action 1", "?/actions/foo/action.yaml", false}, // Actions are located in root and with special characters. - {"special chars action 2", "foo/actions/foo<>bar/action.yaml", false}, // Actions are located in root and with special characters. - {"special chars action 3", "foo/!<>/actions/foo\\bar/action.yaml", false}, // Actions are located in root and with special characters. + {"special chars action in root 1", "actions/foo bar/action.yaml", false}, // Actions are located in root and with special characters. + {"special chars action in root 2", "actions/foo!bar/action.yaml", false}, // Actions are located in root and with special characters. + {"special chars action 1", "?/actions/foo/action.yaml", false}, // Actions with special characters. + {"special chars action 2", "foo/actions/foo<>bar/action.yaml", false}, // Actions with special characters. + {"special chars action 3", "foo/!<>/actions/foo\\bar/action.yaml", false}, // Actions with special characters. + {"special chars action 4", "foo bar/actions/baz/action.yaml", false}, // Actions with special characters. {"root myactions", "myactions/verb/action.yaml", false}, // Actions are located in dir ending with actions. {"dir", "1/2/actions/3", false}, // A directory is given. } diff --git a/pkg/action/yaml.discovery.go b/pkg/action/yaml.discovery.go index d57e729..b124e0f 100644 --- a/pkg/action/yaml.discovery.go +++ b/pkg/action/yaml.discovery.go @@ -4,13 +4,14 @@ import ( "bufio" "bytes" "io" + "path/filepath" "regexp" "sync" ) var ( // rgxYamlFilepath is a regex for a yaml path with unix and windows support. - rgxYamlFilepath = regexp.MustCompile(`(^actions|[^!<>:"|?*]+[\\/]actions)[\\/][^\\/!<>:"|?*]+[\\/]action\.y(a)?ml$`) + rgxYamlFilepath = regexp.MustCompile(`^(actions|[^\s!<>:"|?*]+/actions)/[^\s!<>:"|?*/]+/action\.y(a)?ml$`) // rgxYamlRootFile is a regex for a yaml file located in root dir only. rgxYamlRootFile = regexp.MustCompile(`^action\.y(a)?ml$`) ) @@ -28,7 +29,7 @@ type YamlDiscoveryStrategy struct { // IsValid implements [DiscoveryStrategy]. func (y YamlDiscoveryStrategy) IsValid(path string) bool { - return y.TargetRgx.MatchString(path) + return y.TargetRgx.MatchString(filepath.ToSlash(path)) } // Loader implements [DiscoveryStrategy]. diff --git a/test/testdata/common/discovery_basic.txtar b/test/testdata/common/discovery_basic.txtar index 1e22202..a6fd5b6 100644 --- a/test/testdata/common/discovery_basic.txtar +++ b/test/testdata/common/discovery_basic.txtar @@ -1,3 +1,8 @@ +[unix] mkdir foo-bar_baz/actions/waldo*fred +[unix] mkdir actions/waldo*fred +[unix] cp 'foo-bar_baz/actions/waldo fred/action.yaml' foo-bar_baz/actions/waldo*fred/action.yaml +[unix] cp 'actions/waldo fred/action.yaml' actions/waldo*fred/action.yaml + exec launchr --help # Actions are grouped and sorted. @@ -40,19 +45,11 @@ runtime: action: { title: valid special chars } runtime: plugin --- foo-bar_baz/actions/waldo\ fred/action.yaml -- -action: { title: invalid special chars } -runtime: plugin - --- foo-bar_baz/actions/waldo!fred/action.yaml -- -action: { title: invalid special chars } -runtime: plugin - --- actions/waldo*fred/action.yaml -- +-- foo-bar_baz/actions/waldo fred/action.yaml -- action: { title: invalid special chars } runtime: plugin --- actions/waldo\\fred/action.yaml -- +-- actions/waldo fred/action.yaml -- action: { title: invalid special chars } runtime: plugin From 9f4c6a70845df07a0b667838f06a0e88a3066d83 Mon Sep 17 00:00:00 2001 From: Aleksandr Britvin Date: Sun, 18 May 2025 23:21:24 +0200 Subject: [PATCH 10/18] WIP #83 TestScript --- .github/workflows/test.yaml | 12 ++++++++++-- internal/launchr/filepath.go | 25 ++++++++++++++++++++++++- internal/launchr/filepath_unix.go | 13 +------------ pkg/action/action_test.go | 4 ++-- pkg/action/loader.go | 8 ++++---- 5 files changed, 41 insertions(+), 21 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index bef0361..ded3648 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -7,6 +7,12 @@ on: branches: - '**' workflow_call: + run: + description: 'Custom command to run' + default: | + go test ./... + required: false + type: string jobs: test: @@ -18,6 +24,8 @@ jobs: os: ubuntu-latest - name: Linux / ARM64 os: ubuntu-24.04-arm + - name: MacOS / AMD64 + os: macos-13 - name: MacOS / ARM64 os: macos-latest - name: Windows / AMD64 @@ -43,5 +51,5 @@ jobs: run: go mod download - name: Test - run: | - go test ./... + id: run-tests + run: ${{ inputs.run }} diff --git a/internal/launchr/filepath.go b/internal/launchr/filepath.go index 5a384cc..6b50e6e 100644 --- a/internal/launchr/filepath.go +++ b/internal/launchr/filepath.go @@ -7,6 +7,7 @@ import ( osuser "os/user" "path/filepath" "reflect" + "strings" ) // MustAbs returns absolute filepath and panics on error. @@ -62,7 +63,20 @@ func EnsurePath(parts ...string) error { // IsHiddenPath checks if a path is hidden path. func IsHiddenPath(path string) bool { - return isHiddenPath(path) + return isDotPath(path) || isHiddenPath(path) +} + +func isDotPath(path string) bool { + if path == "." { + return false + } + dirs := strings.Split(path, string(filepath.Separator)) + for _, v := range dirs { + if v[0] == '.' { + return true + } + } + return false } // IsSystemPath checks if a path is a system path. @@ -175,3 +189,12 @@ func MkdirTempWithCleanup(pattern string) (string, error) { return dirPath, nil } + +// EscapePathString escapes characters that may be +// incorrectly treated as a string like backshash "\" in a Windows path. +func EscapePathString(s string) string { + if filepath.Separator == '/' { + return s + } + return strings.Replace(s, "\\", "\\\\", -1) +} diff --git a/internal/launchr/filepath_unix.go b/internal/launchr/filepath_unix.go index 9d0241b..676beee 100644 --- a/internal/launchr/filepath_unix.go +++ b/internal/launchr/filepath_unix.go @@ -4,7 +4,6 @@ package launchr import ( "path/filepath" - "strings" ) var skipRootDirs = []string{ @@ -46,17 +45,7 @@ var skipUserDirs = []string{ } func isHiddenPath(path string) bool { - if path == "." { - return false - } - dirs := strings.Split(path, string(filepath.Separator)) - for _, v := range dirs { - if v[0] == '.' { - return true - } - } - - return false + return isDotPath(path) } func isRootPath(path string) bool { diff --git a/pkg/action/action_test.go b/pkg/action/action_test.go index dfa8379..4fa182c 100644 --- a/pkg/action/action_test.go +++ b/pkg/action/action_test.go @@ -32,8 +32,8 @@ func Test_Action(t *testing.T) { // Test dir assert.Equal(filepath.Dir(act.fpath), act.Dir()) - act.fpath = "test/file/path/action.yaml" - assert.Equal("test/file/path", act.Dir()) + act.fpath = filepath.FromSlash("test/file/path/action.yaml") + assert.Equal(filepath.FromSlash("test/file/path"), act.Dir()) // Test arguments and options. inputArgs := InputParams{"arg1": "arg1", "arg2": "arg2", "arg-1": "arg-1", "arg_12": "arg_12_enum1"} diff --git a/pkg/action/loader.go b/pkg/action/loader.go index 9c01a55..75dded9 100644 --- a/pkg/action/loader.go +++ b/pkg/action/loader.go @@ -187,13 +187,13 @@ func addPredefinedVariables(data map[string]any, a *Action) { data["current_uid"] = s[0] data["current_gid"] = s[1] } - data["current_working_dir"] = a.wd // app working directory - data["actions_base_dir"] = a.fs.Realpath() // root directory where the action was found - data["action_dir"] = a.Dir() // directory of action file + data["current_working_dir"] = launchr.EscapePathString(a.wd) // app working directory + data["actions_base_dir"] = launchr.EscapePathString(a.fs.Realpath()) // root directory where the action was found + data["action_dir"] = launchr.EscapePathString(a.Dir()) // directory of action file // Get the path of the executable on the host. bin, err := os.Executable() if err != nil { bin = launchr.Version().Name } - data["current_bin"] = bin + data["current_bin"] = launchr.EscapePathString(bin) } From b55219bbf5ce4635c74f15edbb22f78f30329ffc Mon Sep 17 00:00:00 2001 From: Aleksandr Britvin Date: Mon, 19 May 2025 01:36:13 +0200 Subject: [PATCH 11/18] WIP #83 TestScript --- .github/workflows/ci.yaml | 12 ++++++++ .../workflows/{test.yaml => test-suite.yaml} | 30 +++++++++++++------ 2 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/ci.yaml rename .github/workflows/{test.yaml => test-suite.yaml} (73%) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..36b016e --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,12 @@ +name: CI +on: + push: + branches: + - '**' + pull_request: + branches: + - '**' + +jobs: + run-tests: + uses: ./.github/workflows/test-suite.yaml diff --git a/.github/workflows/test.yaml b/.github/workflows/test-suite.yaml similarity index 73% rename from .github/workflows/test.yaml rename to .github/workflows/test-suite.yaml index ded3648..3bb6130 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test-suite.yaml @@ -1,13 +1,7 @@ -name: Tests +name: Test suite on: - push: - branches: - - '**' - pull_request: - branches: - - '**' workflow_call: - run: + test-run: description: 'Custom command to run' default: | go test ./... @@ -52,4 +46,22 @@ jobs: - name: Test id: run-tests - run: ${{ inputs.run }} + run: ${{ inputs.test-run }} + + lint: + name: Lint code + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 'stable' + + - name: Prepare dependencies + run: go mod download + + - name: Test + id: run-tests + run: make lint From 9b57aa56d4022660106edd00b877e54ae587bff9 Mon Sep 17 00:00:00 2001 From: Aleksandr Britvin Date: Mon, 19 May 2025 01:37:27 +0200 Subject: [PATCH 12/18] WIP #83 TestScript --- .github/workflows/test-suite.yaml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test-suite.yaml b/.github/workflows/test-suite.yaml index 3bb6130..3b40a24 100644 --- a/.github/workflows/test-suite.yaml +++ b/.github/workflows/test-suite.yaml @@ -1,12 +1,13 @@ name: Test suite on: workflow_call: - test-run: - description: 'Custom command to run' - default: | - go test ./... - required: false - type: string + inputs: + test-run: + description: 'Custom command to run' + default: | + go test ./... + required: false + type: string jobs: test: From d79a0ce7f45627073cec5254a21bc4c577a74be2 Mon Sep 17 00:00:00 2001 From: Aleksandr Britvin Date: Mon, 19 May 2025 01:51:17 +0200 Subject: [PATCH 13/18] WIP #83 TestScript --- .github/workflows/ci.yaml | 1 + .github/workflows/test-suite.yaml | 14 +++++++------- internal/launchr/filepath.go | 2 +- pkg/action/test_utils.go | 9 +++++---- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 36b016e..c551fc3 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -9,4 +9,5 @@ on: jobs: run-tests: + name: Test uses: ./.github/workflows/test-suite.yaml diff --git a/.github/workflows/test-suite.yaml b/.github/workflows/test-suite.yaml index 3b40a24..4d655f9 100644 --- a/.github/workflows/test-suite.yaml +++ b/.github/workflows/test-suite.yaml @@ -15,18 +15,18 @@ jobs: strategy: matrix: include: - - name: Linux / AMD64 + - name: Linux (amd64) os: ubuntu-latest - - name: Linux / ARM64 + - name: Linux (arm64) os: ubuntu-24.04-arm - - name: MacOS / AMD64 + - name: MacOS (amd64) os: macos-13 - - name: MacOS / ARM64 + - name: MacOS (arm64) os: macos-latest - - name: Windows / AMD64 + - name: Windows (arm64) os: windows-latest - continue-on-error: true - - name: Windows / ARM64 + continue-on-error: true # TODO: Windows is not well supported + - name: Windows (arm64) os: windows-11-arm continue-on-error: true runs-on: ${{ matrix.os }} diff --git a/internal/launchr/filepath.go b/internal/launchr/filepath.go index 6b50e6e..4714b66 100644 --- a/internal/launchr/filepath.go +++ b/internal/launchr/filepath.go @@ -70,7 +70,7 @@ func isDotPath(path string) bool { if path == "." { return false } - dirs := strings.Split(path, string(filepath.Separator)) + dirs := strings.Split(filepath.ToSlash(path), "/") for _, v := range dirs { if v[0] == '.' { return true diff --git a/pkg/action/test_utils.go b/pkg/action/test_utils.go index 08f0218..13a918d 100644 --- a/pkg/action/test_utils.go +++ b/pkg/action/test_utils.go @@ -7,8 +7,9 @@ import ( "testing" "testing/fstest" - "github.com/docker/docker/pkg/namesgenerator" "github.com/stretchr/testify/assert" + + "github.com/launchrctl/launchr/pkg/driver" ) type genPathType int @@ -22,13 +23,13 @@ const ( func genActionPath(d int, pathType genPathType) string { elems := make([]string, 0, d+3) for i := 0; i < d; i++ { - elems = append(elems, namesgenerator.GetRandomName(0)) + elems = append(elems, driver.GetRandomName(0)) } switch pathType { case genPathTypeValid: - elems = append(elems, actionsDirname, namesgenerator.GetRandomName(0)) + elems = append(elems, actionsDirname, driver.GetRandomName(0)) case genPathTypeGHActions: - elems = append(elems, ".github", actionsDirname, namesgenerator.GetRandomName(0)) + elems = append(elems, ".github", actionsDirname, driver.GetRandomName(0)) case genPathTypeArbitrary: // Do nothing. default: From f245414349c642df7d49447b4522e173a144cbf3 Mon Sep 17 00:00:00 2001 From: Aleksandr Britvin Date: Sun, 25 May 2025 15:27:27 +0200 Subject: [PATCH 14/18] WIP #83 Fix windows test --- pkg/action/action_test.go | 18 ++++-------------- pkg/action/discover.go | 20 ++++++++++++++++---- pkg/action/test_utils.go | 4 ++++ 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/pkg/action/action_test.go b/pkg/action/action_test.go index 4fa182c..1df5bf4 100644 --- a/pkg/action/action_test.go +++ b/pkg/action/action_test.go @@ -3,7 +3,6 @@ package action import ( "context" "fmt" - "io/fs" "os" "path/filepath" "strings" @@ -101,20 +100,11 @@ func Test_Action(t *testing.T) { func Test_Action_NewYAMLFromFS(t *testing.T) { t.Parallel() - // Prepare FS. - fsys := genFsTestMapActions(1, validFullYaml, genPathTypeArbitrary) - // Get first key to make subdir. - var key string - for key = range fsys { - // There is only 1 entry, we get the only key. - break - } - - // Create action. - subfs, _ := fs.Sub(fsys, filepath.Dir(key)) - a, err := NewYAMLFromFS("test", subfs) - require.NotNil(t, a) + // Create action in memory FS. + fsys := genFsTestMapActions(1, validFullYaml, genPathTypeRoot) + a, err := NewYAMLFromFS("test", fsys) require.NoError(t, err) + require.NotNil(t, a) assert.Equal(t, "test", a.ID) require.NoError(t, a.EnsureLoaded()) assert.Equal(t, "Title", a.ActionDef().Title) diff --git a/pkg/action/discover.go b/pkg/action/discover.go index 5ac2c67..c0951f6 100644 --- a/pkg/action/discover.go +++ b/pkg/action/discover.go @@ -182,6 +182,19 @@ func (ad *Discovery) Discover(ctx context.Context) ([]*Action, error) { // Traverse the FS. chFiles, chErr := ad.findFiles(ctx) + + // Check traversing the tree didn't have error. + // Usually no error, because we check for permissions. + var discoverErr error + errDone := make(chan struct{}) + go func() { + defer close(errDone) + if err := <-chErr; err != nil { + discoverErr = err + } + }() + + // Process files. for f := range chFiles { wg.Add(1) go func(f string) { @@ -195,10 +208,9 @@ func (ad *Discovery) Discover(ctx context.Context) ([]*Action, error) { } wg.Wait() - // Check traversing the tree didn't have error. - // Usually no error, because we check for permissions. - if err := <-chErr; err != nil { - return nil, err + // Wait for error handling to complete + if <-errDone; discoverErr != nil { + return nil, discoverErr } // Sort alphabetically. diff --git a/pkg/action/test_utils.go b/pkg/action/test_utils.go index 13a918d..9c6c34a 100644 --- a/pkg/action/test_utils.go +++ b/pkg/action/test_utils.go @@ -18,9 +18,13 @@ const ( genPathTypeValid genPathType = iota // genPathTypeValid is a valid actions path genPathTypeArbitrary // genPathTypeArbitrary is a random string without actions directory. genPathTypeGHActions // genPathTypeGHActions is an incorrect hidden path but with actions directory. + genPathTypeRoot // genPathTypeRoot is a path in root. ) func genActionPath(d int, pathType genPathType) string { + if pathType == genPathTypeRoot { + d = 0 + } elems := make([]string, 0, d+3) for i := 0; i < d; i++ { elems = append(elems, driver.GetRandomName(0)) From 8a0af49a92ce882e98e79967555effda4b6a2164 Mon Sep 17 00:00:00 2001 From: Aleksandr Britvin Date: Mon, 19 May 2025 16:15:11 +0200 Subject: [PATCH 15/18] WIP #83 TestScript --- .github/workflows/ci.yaml | 4 ++-- .../{test-suite.yaml => common-tests.yaml} | 19 +++++-------------- docs/test.md | 12 ++++++++++++ 3 files changed, 19 insertions(+), 16 deletions(-) rename .github/workflows/{test-suite.yaml => common-tests.yaml} (79%) create mode 100644 docs/test.md diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c551fc3..2c02e11 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -8,6 +8,6 @@ on: - '**' jobs: - run-tests: + common-tests: name: Test - uses: ./.github/workflows/test-suite.yaml + uses: ./.github/workflows/common-tests.yaml diff --git a/.github/workflows/test-suite.yaml b/.github/workflows/common-tests.yaml similarity index 79% rename from .github/workflows/test-suite.yaml rename to .github/workflows/common-tests.yaml index 4d655f9..d15196c 100644 --- a/.github/workflows/test-suite.yaml +++ b/.github/workflows/common-tests.yaml @@ -1,17 +1,10 @@ -name: Test suite +name: Test on: workflow_call: - inputs: - test-run: - description: 'Custom command to run' - default: | - go test ./... - required: false - type: string jobs: test: - name: Test on ${{ matrix.name }} + name: Test ${{ matrix.name }} strategy: matrix: include: @@ -23,7 +16,7 @@ jobs: os: macos-13 - name: MacOS (arm64) os: macos-latest - - name: Windows (arm64) + - name: Windows (amd64) os: windows-latest continue-on-error: true # TODO: Windows is not well supported - name: Windows (arm64) @@ -47,7 +40,8 @@ jobs: - name: Test id: run-tests - run: ${{ inputs.test-run }} + run: | + go test ./... lint: name: Lint code @@ -60,9 +54,6 @@ jobs: with: go-version: 'stable' - - name: Prepare dependencies - run: go mod download - - name: Test id: run-tests run: make lint diff --git a/docs/test.md b/docs/test.md new file mode 100644 index 0000000..bde0783 --- /dev/null +++ b/docs/test.md @@ -0,0 +1,12 @@ +# Application test + +[//]: # (TODO: lint) +[//]: # (TODO: go test unit) +[//]: # (TODO: testscript in go) +[//]: # (TODO: testscript separaterly) +[//]: # (TODO: Reusing GitHub workflow) +[//]: # (TODO: Local tests of other OS + Linux: win/macos - docker container dockur/windows and dockur/macos. lima for other linux distro. + MacOS: win - UTM free, Parallels paid. Linux - lima. + Windows: WSL2 for linux + dockur/macos for macos. + ) From eb91b2677494655f808d889532f3a9e83671c8b4 Mon Sep 17 00:00:00 2001 From: Aleksandr Britvin Date: Sun, 25 May 2025 15:33:14 +0200 Subject: [PATCH 16/18] WIP #83 Adjust gha --- .github/workflows/common-tests.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/common-tests.yaml b/.github/workflows/common-tests.yaml index d15196c..a5dc3f4 100644 --- a/.github/workflows/common-tests.yaml +++ b/.github/workflows/common-tests.yaml @@ -2,6 +2,9 @@ name: Test on: workflow_call: +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: test: name: Test ${{ matrix.name }} From 65153e8c52de92de402e9d6202da2ef481f976af Mon Sep 17 00:00:00 2001 From: Aleksandr Britvin Date: Sun, 25 May 2025 17:48:01 +0200 Subject: [PATCH 17/18] WIP #83 Adjust gha --- .github/workflows/debug.yml | 55 +++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 .github/workflows/debug.yml diff --git a/.github/workflows/debug.yml b/.github/workflows/debug.yml new file mode 100644 index 0000000..4a7583f --- /dev/null +++ b/.github/workflows/debug.yml @@ -0,0 +1,55 @@ +name: Debug with SSH Access + +on: + workflow_dispatch: + inputs: + os: + description: 'Operating System' + required: true + default: 'Ubuntu LTS (amd64)' + type: choice + options: + - 'Ubuntu LTS (amd64)' + - 'Ubuntu LTS (arm64)' + - 'macOS Latest (arm64)' + - 'macOS 13 (amd64)' + - 'Windows Latest (amd64)' + - 'Windows Latest (arm64)' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +jobs: + debug: + name: Debug Environment + runs-on: >- + ${{ + { + 'Ubuntu LTS (amd64)': 'ubuntu-latest', + 'Ubuntu LTS (arm64)': 'ubuntu-24.04-arm', + 'macOS Latest (arm64)': 'macos-latest', + 'macOS 13 (amd64)': 'macos-13', + 'Windows Latest (amd64)': 'windows-latest' + 'Windows Latest (arm64)': 'windows-11-arm' + }[github.event.inputs.os] + }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 'stable' + + - name: Install dependencies + run: | + go mod download + go install github.com/go-delve/delve/cmd/dlv@latest + + - name: Setup debug session + uses: mxschmitt/action-tmate@v3 + with: + limit-access-to-actor: true + timeout-minutes: 30 From 0c38122d63ba5cd041126b49c1577120a5efbd9f Mon Sep 17 00:00:00 2001 From: Aleksandr Britvin Date: Sun, 25 May 2025 18:10:28 +0200 Subject: [PATCH 18/18] WIP #83 Adjust gha --- .github/workflows/ci.yaml | 9 ++++++--- .github/workflows/debug.yml | 3 --- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2c02e11..080c4c5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -3,9 +3,12 @@ on: push: branches: - '**' - pull_request: - branches: - - '**' + paths-ignore: + - 'README.md' + - 'LICENSE' + - '.gitignore' + - 'example/**' + - 'docs/**' jobs: common-tests: diff --git a/.github/workflows/debug.yml b/.github/workflows/debug.yml index 4a7583f..5824cea 100644 --- a/.github/workflows/debug.yml +++ b/.github/workflows/debug.yml @@ -16,9 +16,6 @@ on: - 'Windows Latest (amd64)' - 'Windows Latest (arm64)' -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true jobs: debug: name: Debug Environment