feat(plugin): specify plugin version (#6683)

Signed-off-by: knqyf263 <knqyf263@gmail.com>
Co-authored-by: DmitriyLewen <dmitriy.lewen@smartforce.io>
This commit is contained in:
Teppei Fukuda
2024-05-17 13:29:19 +04:00
committed by GitHub
parent a944f0e4c5
commit d6dc56732b
26 changed files with 368 additions and 154 deletions

View File

@@ -130,6 +130,16 @@ The following rules will apply in deciding which platform to select:
After determining platform, Trivy will download the execution file from `uri` and store it in the plugin cache. After determining platform, Trivy will download the execution file from `uri` and store it in the plugin cache.
When the plugin is called via Trivy CLI, `bin` command will be executed. When the plugin is called via Trivy CLI, `bin` command will be executed.
#### Tagging plugin repositories
If you are hosting your plugin in a Git repository, it is strongly recommended to tag your releases with a version number.
By tagging your releases, Trivy can install specific versions of your plugin.
```bash
$ trivy plugin install referrer@v0.3.0
```
When tagging versions, you must follow [the Semantic Versioning][semver] and prefix the tag with `v`, like `v1.2.3`.
#### Plugin arguments/flags #### Plugin arguments/flags
The plugin is responsible for handling flags and arguments. The plugin is responsible for handling flags and arguments.
Any arguments are passed to the plugin from the `trivy` command. Any arguments are passed to the plugin from the `trivy` command.

View File

@@ -40,6 +40,8 @@ $ trivy plugin install referrer
This command will download the plugin and install it in the plugin cache. This command will download the plugin and install it in the plugin cache.
Trivy adheres to the XDG specification, so the location depends on whether XDG_DATA_HOME is set. Trivy adheres to the XDG specification, so the location depends on whether XDG_DATA_HOME is set.
Trivy will now search XDG_DATA_HOME for the location of the Trivy plugins cache. Trivy will now search XDG_DATA_HOME for the location of the Trivy plugins cache.
The preference order is as follows: The preference order is as follows:
@@ -56,6 +58,15 @@ $ trivy plugin install github.com/aquasecurity/trivy-plugin-kubectl
$ trivy plugin install myplugin.tar.gz $ trivy plugin install myplugin.tar.gz
``` ```
If the plugin's Git repository is [properly tagged](./developer-guide.md#tagging-plugin-repositories), you can specify the version to install like this:
```bash
$ trivy plugin install referrer@v0.3.0
```
!!! note
The leading `v` in the version is required. Also, the version must follow the [Semantic Versioning](https://semver.org/).
Under the hood Trivy leverages [go-getter][go-getter] to download plugins. Under the hood Trivy leverages [go-getter][go-getter] to download plugins.
This means the following protocols are supported for downloading plugins: This means the following protocols are supported for downloading plugins:

View File

@@ -6,6 +6,19 @@ Install a plugin
trivy plugin install NAME | URL | FILE_PATH trivy plugin install NAME | URL | FILE_PATH
``` ```
### Examples
```
# Install a plugin from the plugin index
$ trivy plugin install referrer
# Specify the version of the plugin to install
$ trivy plugin install referrer@v0.3.0
# Install a plugin from a URL
$ trivy plugin install github.com/aquasecurity/trivy-plugin-referrer
```
### Options ### Options
``` ```

View File

@@ -727,6 +727,14 @@ func NewPluginCommand() *cobra.Command {
Use: "install NAME | URL | FILE_PATH", Use: "install NAME | URL | FILE_PATH",
Aliases: []string{"i"}, Aliases: []string{"i"},
Short: "Install a plugin", Short: "Install a plugin",
Example: ` # Install a plugin from the plugin index
$ trivy plugin install referrer
# Specify the version of the plugin to install
$ trivy plugin install referrer@v0.3.0
# Install a plugin from a URL
$ trivy plugin install github.com/aquasecurity/trivy-plugin-referrer`,
SilenceErrors: true, SilenceErrors: true,
SilenceUsage: true, SilenceUsage: true,
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,

View File

@@ -4,7 +4,6 @@ package repo
import ( import (
"context" "context"
"github.com/aquasecurity/trivy/pkg/fanal/walker"
"net/http/httptest" "net/http/httptest"
"testing" "testing"
@@ -16,6 +15,7 @@ import (
_ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/secret" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/secret"
"github.com/aquasecurity/trivy/pkg/fanal/artifact" "github.com/aquasecurity/trivy/pkg/fanal/artifact"
"github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/cache"
"github.com/aquasecurity/trivy/pkg/fanal/walker"
) )
func setupGitServer() (*httptest.Server, error) { func setupGitServer() (*httptest.Server, error) {

View File

@@ -24,6 +24,7 @@ type Index struct {
Version int `yaml:"version"` Version int `yaml:"version"`
Plugins []struct { Plugins []struct {
Name string `yaml:"name"` Name string `yaml:"name"`
Version string `yaml:"version"`
Maintainer string `yaml:"maintainer"` Maintainer string `yaml:"maintainer"`
Summary string `yaml:"summary"` Summary string `yaml:"summary"`
Repository string `yaml:"repository"` Repository string `yaml:"repository"`

View File

@@ -51,7 +51,7 @@ func TestManager_Search(t *testing.T) {
want: `NAME DESCRIPTION MAINTAINER OUTPUT want: `NAME DESCRIPTION MAINTAINER OUTPUT
foo A foo plugin aquasecurity ✓ foo A foo plugin aquasecurity ✓
bar A bar plugin aquasecurity bar A bar plugin aquasecurity
test A test plugin aquasecurity test_plugin A test plugin aquasecurity
`, `,
}, },
{ {

View File

@@ -13,6 +13,7 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"github.com/aquasecurity/go-version/pkg/semver"
"github.com/aquasecurity/trivy/pkg/downloader" "github.com/aquasecurity/trivy/pkg/downloader"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/log"
@@ -30,14 +31,20 @@ var (
type ManagerOption func(indexer *Manager) type ManagerOption func(indexer *Manager)
func WithWriter(w io.Writer) ManagerOption { func WithWriter(w io.Writer) ManagerOption {
return func(indexer *Manager) { return func(manager *Manager) {
indexer.w = w manager.w = w
}
}
func WithLogger(logger *log.Logger) ManagerOption {
return func(manager *Manager) {
manager.logger = logger
} }
} }
func WithIndexURL(indexURL string) ManagerOption { func WithIndexURL(indexURL string) ManagerOption {
return func(indexer *Manager) { return func(manager *Manager) {
indexer.indexURL = indexURL manager.indexURL = indexURL
} }
} }
@@ -88,17 +95,18 @@ func Update(ctx context.Context) error { return defaultManager(
func Search(ctx context.Context, keyword string) error { return defaultManager().Search(ctx, keyword) } func Search(ctx context.Context, keyword string) error { return defaultManager().Search(ctx, keyword) }
// Install installs a plugin // Install installs a plugin
func (m *Manager) Install(ctx context.Context, name string, opts Options) (Plugin, error) { func (m *Manager) Install(ctx context.Context, arg string, opts Options) (Plugin, error) {
src := m.tryIndex(ctx, name) input := m.parseArg(ctx, arg)
input.name = m.tryIndex(ctx, input.name)
// If the plugin is already installed, it skips installing the plugin. // If the plugin is already installed, it skips installing the plugin.
if p, installed := m.isInstalled(ctx, src); installed { if p, installed := m.isInstalled(ctx, input.name, input.version); installed {
m.logger.InfoContext(ctx, "The plugin is already installed", log.String("name", p.Name)) m.logger.InfoContext(ctx, "The plugin is already installed", log.String("name", p.Name))
return p, nil return p, nil
} }
m.logger.InfoContext(ctx, "Installing the plugin...", log.String("src", src)) m.logger.InfoContext(ctx, "Installing the plugin...", log.String("src", input.name))
return m.install(ctx, src, opts) return m.install(ctx, input.String(), opts)
} }
func (m *Manager) install(ctx context.Context, src string, opts Options) (Plugin, error) { func (m *Manager) install(ctx context.Context, src string, opts Options) (Plugin, error) {
@@ -129,7 +137,8 @@ func (m *Manager) install(ctx context.Context, src string, opts Options) (Plugin
return Plugin{}, xerrors.Errorf("yaml encode error: %w", err) return Plugin{}, xerrors.Errorf("yaml encode error: %w", err)
} }
m.logger.InfoContext(ctx, "Plugin successfully installed", log.String("name", plugin.Name)) m.logger.InfoContext(ctx, "Plugin successfully installed",
log.String("name", plugin.Name), log.String("version", plugin.Version))
return plugin, nil return plugin, nil
} }
@@ -340,16 +349,45 @@ func (m *Manager) loadMetadata(dir string) (Plugin, error) {
return plugin, nil return plugin, nil
} }
func (m *Manager) isInstalled(ctx context.Context, url string) (Plugin, bool) { func (m *Manager) isInstalled(ctx context.Context, url, version string) (Plugin, bool) {
installedPlugins, err := m.LoadAll(ctx) installedPlugins, err := m.LoadAll(ctx)
if err != nil { if err != nil {
return Plugin{}, false return Plugin{}, false
} }
for _, plugin := range installedPlugins { for _, plugin := range installedPlugins {
if plugin.Repository == url { if plugin.Repository == url && (version == "" || plugin.Version == version) {
return plugin, true return plugin, true
} }
} }
return Plugin{}, false return Plugin{}, false
} }
// Input represents the user-specified Input.
type Input struct {
name string
version string
}
func (i *Input) String() string {
if i.version != "" {
// cf. https://github.com/hashicorp/go-getter/blob/268c11cae8cf0d9374783e06572679796abe9ce9/README.md#git-git
return i.name + "?ref=v" + i.version
}
return i.name
}
func (m *Manager) parseArg(ctx context.Context, arg string) Input {
before, after, found := strings.Cut(arg, "@v")
if !found {
return Input{name: arg}
} else if _, err := semver.Parse(after); err != nil {
m.logger.DebugContext(ctx, "Unable to identify the plugin version", log.String("name", arg), log.Err(err))
return Input{name: arg}
}
// cf. https://github.com/hashicorp/go-getter/blob/268c11cae8cf0d9374783e06572679796abe9ce9/README.md#git-git
return Input{
name: before,
version: after,
}
}

View File

@@ -1,16 +1,15 @@
//go:build unix
package plugin_test package plugin_test
import ( import (
"archive/zip"
"bytes" "bytes"
"context" "context"
"fmt"
"github.com/aquasecurity/trivy/pkg/clock" "github.com/aquasecurity/trivy/pkg/clock"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/utils/fsutils"
v1 "github.com/google/go-containerregistry/pkg/v1" v1 "github.com/google/go-containerregistry/pkg/v1"
"log/slog" "log/slog"
"net/http"
"net/http/httptest"
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
@@ -24,11 +23,40 @@ import (
"github.com/aquasecurity/trivy/pkg/plugin" "github.com/aquasecurity/trivy/pkg/plugin"
) )
func setupInstalledPlugin(t *testing.T, homeDir string, p plugin.Plugin) {
pluginDir := filepath.Join(homeDir, ".trivy", "plugins", p.Name)
// Create the test plugin directory
err := os.MkdirAll(pluginDir, os.ModePerm)
require.NoError(t, err)
// write the plugin name
pluginMetadata := fmt.Sprintf(`name: "%s"
repository: "%s"
version: "%s"
usage: test
description: test
platforms:
- selector:
os: linux
arch: amd64
uri: ./test.sh
bin: ./test.sh
installed:
platform:
os: linux
arch: amd64`, p.Name, p.Repository, p.Version)
err = os.WriteFile(filepath.Join(pluginDir, "plugin.yaml"), []byte(pluginMetadata), os.ModePerm)
require.NoError(t, err)
}
func TestManager_Run(t *testing.T) { func TestManager_Run(t *testing.T) {
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
// the test.sh script can't be run on windows so skipping // the test.sh script can't be run on windows so skipping
t.Skip("Test satisfied adequately by Linux tests") t.Skip("Test satisfied adequately by Linux tests")
} }
type fields struct { type fields struct {
Name string Name string
Repository string Repository string
@@ -183,110 +211,6 @@ func TestManager_Run(t *testing.T) {
} }
} }
func TestManager_Install(t *testing.T) {
if runtime.GOOS == "windows" {
// the test.sh script can't be run on windows so skipping
t.Skip("Test satisfied adequately by Linux tests")
}
wantPlugin := plugin.Plugin{
Name: "test_plugin",
Repository: "github.com/aquasecurity/trivy-plugin-test",
Version: "0.1.0",
Summary: "test",
Description: "test",
Platforms: []plugin.Platform{
{
Selector: &plugin.Selector{
OS: "linux",
Arch: "amd64",
},
URI: "./test.sh",
Bin: "./test.sh",
},
},
Installed: plugin.Installed{
Platform: plugin.Selector{
OS: "linux",
Arch: "amd64",
},
},
}
tests := []struct {
name string
pluginName string
want plugin.Plugin
wantFile string
wantErr string
}{
{
name: "http",
want: wantPlugin,
wantFile: ".trivy/plugins/test_plugin/test.sh",
},
{
name: "local path",
pluginName: "testdata/test_plugin",
want: wantPlugin,
wantFile: ".trivy/plugins/test_plugin/test.sh",
},
{
name: "index",
pluginName: "test",
want: wantPlugin,
wantFile: ".trivy/plugins/test_plugin/test.sh",
},
{
name: "plugin not found",
pluginName: "testdata/not_found",
wantErr: "no such file or directory",
},
{
name: "no plugin.yaml",
pluginName: "testdata/no_yaml",
wantErr: "file open error",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// The test plugin will be installed here
dst := t.TempDir()
t.Setenv("XDG_DATA_HOME", dst)
// For plugin index
fsutils.SetCacheDir("testdata")
if tt.pluginName == "" {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
zr := zip.NewWriter(w)
require.NoError(t, zr.AddFS(os.DirFS("testdata/test_plugin")))
require.NoError(t, zr.Close())
}))
t.Cleanup(ts.Close)
tt.pluginName = ts.URL + "/test_plugin.zip"
}
got, err := plugin.NewManager().Install(context.Background(), tt.pluginName, plugin.Options{
Platform: ftypes.Platform{
Platform: &v1.Platform{
Architecture: "amd64",
OS: "linux",
},
},
})
if tt.wantErr != "" {
require.ErrorContains(t, err, tt.wantErr)
return
}
assert.NoError(t, err)
assert.EqualExportedValues(t, tt.want, got)
assert.FileExists(t, filepath.Join(dst, tt.wantFile))
})
}
}
func TestManager_Uninstall(t *testing.T) { func TestManager_Uninstall(t *testing.T) {
ctx := clock.With(context.Background(), time.Date(2021, 8, 25, 12, 20, 30, 5, time.UTC)) ctx := clock.With(context.Background(), time.Date(2021, 8, 25, 12, 20, 30, 5, time.UTC))
pluginName := "test_plugin" pluginName := "test_plugin"
@@ -423,42 +347,28 @@ func TestManager_Upgrade(t *testing.T) {
t.Skip("Test satisfied adequately by Linux tests") t.Skip("Test satisfied adequately by Linux tests")
} }
pluginName := "test_plugin" pluginName := "test_plugin"
pluginVersion := "0.0.5"
tempDir := t.TempDir() tempDir := t.TempDir()
pluginDir := filepath.Join(tempDir, ".trivy", "plugins", pluginName)
t.Setenv("XDG_DATA_HOME", tempDir) t.Setenv("XDG_DATA_HOME", tempDir)
setupInstalledPlugin(t, tempDir, plugin.Plugin{
// Create the test plugin directory Name: pluginName,
err := os.MkdirAll(pluginDir, os.ModePerm) Version: pluginVersion,
require.NoError(t, err) Repository: "testdata/test_plugin",
})
// write the plugin name
pluginMetadata := `name: "test_plugin"
repository: testdata/test_plugin
version: "0.0.5"
usage: test
description: A simple test plugin
installed:
platform:
os: linux
arch: amd64`
err = os.WriteFile(filepath.Join(pluginDir, "plugin.yaml"), []byte(pluginMetadata), os.ModePerm)
require.NoError(t, err)
ctx := context.Background() ctx := context.Background()
m := plugin.NewManager() m := plugin.NewManager()
// verify initial version // verify initial version
verifyVersion(t, ctx, m, pluginName, "0.0.5") verifyVersion(t, ctx, m, pluginName, pluginVersion)
// Upgrade the existing plugin // Upgrade the existing plugin
err = m.Upgrade(ctx, nil) err := m.Upgrade(ctx, nil)
require.NoError(t, err) require.NoError(t, err)
// verify plugin updated // verify plugin updated
verifyVersion(t, ctx, m, pluginName, "0.1.0") verifyVersion(t, ctx, m, pluginName, "0.2.0")
} }
func verifyVersion(t *testing.T, ctx context.Context, m *plugin.Manager, pluginName, expectedVersion string) { func verifyVersion(t *testing.T, ctx context.Context, m *plugin.Manager, pluginName, expectedVersion string) {

View File

@@ -0,0 +1,203 @@
//go:build unix
package plugin_test
import (
"archive/zip"
"bytes"
"context"
"fmt"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"
"time"
"github.com/google/go-containerregistry/pkg/v1"
"github.com/sosedoff/gitkit" // Not work on Windows
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/clock"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/plugin"
"github.com/aquasecurity/trivy/pkg/utils/fsutils"
)
func setupGitServer() (*httptest.Server, error) {
service := gitkit.New(gitkit.Config{
Dir: "./testdata",
AutoCreate: false,
})
if err := service.Setup(); err != nil {
return nil, err
}
ts := httptest.NewServer(service)
return ts, nil
}
func TestManager_Install(t *testing.T) {
gs, err := setupGitServer()
require.NoError(t, err)
t.Cleanup(gs.Close)
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
zr := zip.NewWriter(w)
require.NoError(t, zr.AddFS(os.DirFS("testdata/test_plugin")))
require.NoError(t, zr.Close())
}))
t.Cleanup(ts.Close)
wantPlugin := plugin.Plugin{
Name: "test_plugin",
Repository: "testdata/test_plugin",
Version: "0.2.0",
Summary: "test",
Description: "test",
Platforms: []plugin.Platform{
{
Selector: &plugin.Selector{
OS: "linux",
Arch: "amd64",
},
URI: "./test.sh",
Bin: "./test.sh",
},
},
Installed: plugin.Installed{
Platform: plugin.Selector{
OS: "linux",
Arch: "amd64",
},
},
}
wantPluginWithVersion := wantPlugin
wantPluginWithVersion.Version = "0.1.0"
wantLogs := `2021-08-25T12:20:30Z INFO Installing the plugin... src="%s"
2021-08-25T12:20:30Z INFO Plugin successfully installed name="test_plugin" version="%s"
`
tests := []struct {
name string
pluginName string
installed *plugin.Plugin
want plugin.Plugin
wantFile string
wantLogs string
wantErr string
}{
{
name: "http",
pluginName: ts.URL + "/test_plugin.zip",
want: wantPlugin,
wantFile: ".trivy/plugins/test_plugin/test.sh",
wantLogs: fmt.Sprintf(wantLogs, ts.URL+"/test_plugin.zip", "0.2.0"),
},
{
name: "local path",
pluginName: "testdata/test_plugin",
want: wantPlugin,
wantFile: ".trivy/plugins/test_plugin/test.sh",
wantLogs: fmt.Sprintf(wantLogs, "testdata/test_plugin", "0.2.0"),
},
{
name: "git",
pluginName: "git::" + gs.URL + "/test_plugin.git",
want: wantPlugin,
wantFile: ".trivy/plugins/test_plugin/test.sh",
wantLogs: fmt.Sprintf(wantLogs, "git::"+gs.URL+"/test_plugin.git", "0.2.0"),
},
{
name: "with version",
pluginName: "git::" + gs.URL + "/test_plugin.git@v0.1.0",
want: wantPluginWithVersion,
wantFile: ".trivy/plugins/test_plugin/test.sh",
wantLogs: fmt.Sprintf(wantLogs, "git::"+gs.URL+"/test_plugin.git", "0.1.0"),
},
{
name: "via index",
pluginName: "test_plugin",
want: wantPlugin,
wantFile: ".trivy/plugins/test_plugin/test.sh",
wantLogs: fmt.Sprintf(wantLogs, "testdata/test_plugin", "0.2.0"),
},
{
name: "installed",
pluginName: "test_plugin",
installed: &plugin.Plugin{
Name: "test_plugin",
Repository: "testdata/test_plugin",
Version: "0.2.0",
},
want: wantPlugin,
wantLogs: "2021-08-25T12:20:30Z INFO The plugin is already installed name=\"test_plugin\"\n",
},
{
name: "different version installed",
pluginName: "test_plugin@v0.2.0",
installed: &plugin.Plugin{
Name: "test_plugin",
Repository: "testdata/test_plugin",
Version: "0.1.0",
},
want: wantPlugin,
wantLogs: fmt.Sprintf(wantLogs, "testdata/test_plugin", "0.2.0"),
},
{
name: "plugin not found",
pluginName: "testdata/not_found",
wantErr: "no such file or directory",
},
{
name: "no plugin.yaml",
pluginName: "testdata/no_yaml",
wantErr: "file open error",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// The test plugin will be installed here
dst := t.TempDir()
t.Setenv("XDG_DATA_HOME", dst)
// For plugin index
fsutils.SetCacheDir("testdata")
if tt.installed != nil {
setupInstalledPlugin(t, dst, *tt.installed)
}
var gotLogs bytes.Buffer
logger := log.New(log.NewHandler(&gotLogs, nil))
ctx := clock.With(context.Background(), time.Date(2021, 8, 25, 12, 20, 30, 5, time.UTC))
got, err := plugin.NewManager(plugin.WithLogger(logger)).Install(ctx, tt.pluginName, plugin.Options{
Platform: ftypes.Platform{
Platform: &v1.Platform{
Architecture: "amd64",
OS: "linux",
},
},
})
if tt.wantErr != "" {
require.ErrorContains(t, err, tt.wantErr)
return
}
assert.NoError(t, err)
assert.EqualExportedValues(t, tt.want, got)
if tt.wantFile != "" {
assert.FileExists(t, filepath.Join(dst, tt.wantFile))
}
assert.Equal(t, tt.wantLogs, gotLogs.String())
})
}
}

View File

@@ -9,7 +9,7 @@ plugins:
maintainer: aquasecurity maintainer: aquasecurity
summary: A bar plugin summary: A bar plugin
repository: github.com/aquasecurity/trivy-plugin-bar repository: github.com/aquasecurity/trivy-plugin-bar
- name: test - name: test_plugin
maintainer: aquasecurity maintainer: aquasecurity
summary: A test plugin summary: A test plugin
repository: testdata/test_plugin repository: testdata/test_plugin

View File

@@ -0,0 +1 @@
ref: refs/heads/main

View File

@@ -0,0 +1,8 @@
[core]
repositoryformatversion = 0
filemode = true
bare = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = /Users/teppei/src/github.com/aquasecurity/trivy/pkg/plugin/testdata/test_plugin

View File

@@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.

View File

@@ -0,0 +1,6 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

View File

@@ -0,0 +1,3 @@
xM<><4D>
<EFBFBD>0 <0C><><EFBFBD>S<EFBFBD><53>[7a}ɺ<>
<EFBFBD>#iE<69>޵(<28><>s<EFBFBD><73><EFBFBD>,>-0<><30>!b C!)<29><><EFBFBD><EFBFBD><EFBFBD>A1<41>$<24>$~h<> <0B><><08> <16><><EFBFBD><1B><><EFBFBD>AI

View File

@@ -0,0 +1,4 @@
# pack-refs with: peeled fully-peeled sorted
d78abde66b1d35bdac65402f0e2cddf3a96cd377 refs/heads/main
929b4718db99b64a38b4e8c3ec8e673976821c08 refs/tags/v0.1.0
d78abde66b1d35bdac65402f0e2cddf3a96cd377 refs/tags/v0.2.0

View File

View File

@@ -1,6 +1,6 @@
name: "test_plugin" name: "test_plugin"
repository: github.com/aquasecurity/trivy-plugin-test repository: testdata/test_plugin
version: "0.1.0" version: "0.2.0"
summary: test summary: test
description: test description: test
platforms: platforms:
@@ -9,6 +9,3 @@ platforms:
arch: amd64 arch: amd64
uri: ./test.sh uri: ./test.sh
bin: ./test.sh bin: ./test.sh
# for testing
_goos: linux
_goarch: amd64