refactor: use version-specific URLs for documentation references (#6966)

Signed-off-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
Teppei Fukuda
2024-06-20 14:41:43 +04:00
committed by GitHub
parent e493fc931a
commit 30bcb95350
9 changed files with 165 additions and 78 deletions

View File

@@ -3,6 +3,7 @@ package commands
import (
"context"
"errors"
"fmt"
"slices"
"sort"
"strings"
@@ -20,6 +21,7 @@ import (
"github.com/aquasecurity/trivy/pkg/flag"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/version/doc"
)
var allSupportedServicesFunc = awsScanner.AllSupportedServices
@@ -140,7 +142,8 @@ func Run(ctx context.Context, opt flag.Options) error {
var err error
defer func() {
if errors.Is(err, context.DeadlineExceeded) {
log.Warn("Provide a higher timeout value, see https://aquasecurity.github.io/trivy/latest/docs/configuration/")
// e.g. https://aquasecurity.github.io/trivy/latest/docs/configuration/
log.WarnContext(ctx, fmt.Sprintf("Provide a higher timeout value, see %s", doc.URL("/docs/configuration/", "")))
}
}()

View File

@@ -11,7 +11,6 @@ import (
"github.com/spf13/viper"
"golang.org/x/xerrors"
"github.com/aquasecurity/go-version/pkg/semver"
"github.com/aquasecurity/trivy-db/pkg/db"
tcache "github.com/aquasecurity/trivy/pkg/cache"
"github.com/aquasecurity/trivy/pkg/commands/operation"
@@ -33,6 +32,7 @@ import (
"github.com/aquasecurity/trivy/pkg/scanner"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/utils/fsutils"
"github.com/aquasecurity/trivy/pkg/version/doc"
)
// TargetKind represents what kind of artifact Trivy scans
@@ -46,8 +46,6 @@ const (
TargetImageArchive TargetKind = "archive"
TargetSBOM TargetKind = "sbom"
TargetVM TargetKind = "vm"
devVersion = "dev"
)
var (
@@ -397,7 +395,8 @@ func Run(ctx context.Context, opts flag.Options, targetKind TargetKind) (err err
defer func() {
if errors.Is(err, context.DeadlineExceeded) {
log.Warn("Provide a higher timeout value, see https://aquasecurity.github.io/trivy/latest/docs/configuration/")
// e.g. https://aquasecurity.github.io/trivy/latest/docs/configuration/
log.WarnContext(ctx, fmt.Sprintf("Provide a higher timeout value, see %s", doc.URL("/docs/configuration/", "")))
}
}()
@@ -593,10 +592,10 @@ func initScannerConfig(opts flag.Options, cacheClient cache.Cache) (ScannerConfi
// Do not load config file for secret scanning
if opts.Scanners.Enabled(types.SecretScanner) {
ver := canonicalVersion(opts.AppVersion)
log.Info("Secret scanning is enabled")
log.Info("If your scanning is slow, please try '--scanners vuln' to disable secret scanning")
log.Infof("Please see also https://aquasecurity.github.io/trivy/%s/docs/scanner/secret/#recommendation for faster secret detection", ver)
// e.g. https://aquasecurity.github.io/trivy/latest/docs/scanner/secret/#recommendation
log.Infof("Please see also %s for faster secret detection", doc.URL("/docs/scanner/secret/", "recommendation"))
} else {
opts.SecretConfigPath = ""
}
@@ -694,20 +693,3 @@ func scan(ctx context.Context, opts flag.Options, initializeScanner InitializeSc
}
return report, nil
}
func canonicalVersion(ver string) string {
if ver == devVersion {
return ver
}
v, err := semver.Parse(ver)
if err != nil {
return devVersion
}
// Replace pre-release with "dev"
// e.g. v0.34.0-beta1+snapshot-1
if v.IsPreRelease() || v.Metadata() != "" {
return devVersion
}
// Add "v" prefix and cut a patch number, "0.34.0" => "v0.34" for the url
return fmt.Sprintf("v%d.%d", v.Major(), v.Minor())
}

View File

@@ -1,48 +0,0 @@
package artifact
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestCanonicalVersion(t *testing.T) {
tests := []struct {
title string
input string
want string
}{
{
title: "good way",
input: "0.34.0",
want: "v0.34",
},
{
title: "version with v - isn't right semver version",
input: "v0.34.0",
want: devVersion,
},
{
title: "dev version",
input: devVersion,
want: devVersion,
},
{
title: "pre-release",
input: "v0.34.0-beta1+snapshot-1",
want: devVersion,
},
{
title: "no version",
input: "",
want: devVersion,
},
}
for _, test := range tests {
t.Run(test.title, func(t *testing.T) {
got := canonicalVersion(test.input)
require.Equal(t, test.want, got)
})
}
}

View File

@@ -16,6 +16,7 @@ import (
"github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/oci"
"github.com/aquasecurity/trivy/pkg/version/doc"
)
const (
@@ -188,7 +189,8 @@ func (c *Client) initOCIArtifact(opt types.RegistryOptions) (*oci.Artifact, erro
for _, diagnostic := range terr.Errors {
// For better user experience
if diagnostic.Code == transport.DeniedErrorCode || diagnostic.Code == transport.UnauthorizedErrorCode {
log.Warn("See https://aquasecurity.github.io/trivy/latest/docs/references/troubleshooting/#db")
// e.g. https://aquasecurity.github.io/trivy/latest/docs/references/troubleshooting/#db
log.Warnf("See %s", doc.URL("/docs/references/troubleshooting/", "db"))
break
}
}

View File

@@ -3,6 +3,7 @@ package commands
import (
"context"
"errors"
"fmt"
"github.com/spf13/viper"
"golang.org/x/xerrors"
@@ -18,6 +19,7 @@ import (
"github.com/aquasecurity/trivy/pkg/k8s/scanner"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/version/doc"
)
// Run runs a k8s scan
@@ -39,7 +41,8 @@ func Run(ctx context.Context, args []string, opts flag.Options) error {
defer func() {
cancel()
if errors.Is(err, context.DeadlineExceeded) {
log.WarnContext(ctx, "Provide a higher timeout value, see https://aquasecurity.github.io/trivy/latest/docs/configuration/")
// e.g. https://aquasecurity.github.io/trivy/latest/docs/configuration
log.WarnContext(ctx, fmt.Sprintf("Provide a higher timeout value, see %s", doc.URL("/docs/configuration/", "")))
}
}()
opts.K8sVersion = cluster.GetClusterVersion()

View File

@@ -1,8 +1,6 @@
package app
var (
ver = "dev"
)
var ver = "dev"
func Version() string {
return ver

49
pkg/version/doc/doc.go Normal file
View File

@@ -0,0 +1,49 @@
package doc
import (
"fmt"
"net/url"
"path"
"strings"
"github.com/aquasecurity/go-version/pkg/semver"
"github.com/aquasecurity/trivy/pkg/version/app"
)
const devVersion = "dev"
// BaseURL returns the base URL for the versioned documentation
func BaseURL(ver string) *url.URL {
ver = canonicalVersion(ver)
return &url.URL{
Scheme: "https",
Host: "aquasecurity.github.io",
Path: path.Join("trivy", ver),
}
}
// URL returns the URL for the versioned documentation with the given path
func URL(rawPath, fragment string) string {
base := BaseURL(app.Version())
base.Path = path.Join(base.Path, rawPath)
base.Fragment = fragment
return base.String()
}
func canonicalVersion(ver string) string {
if ver == devVersion {
return ver
}
ver = strings.TrimPrefix(ver, "v")
v, err := semver.Parse(ver)
if err != nil {
return devVersion
}
// Replace pre-release with "dev"
// e.g. v0.34.0-beta1+snapshot-1
if v.IsPreRelease() || v.Metadata() != "" {
return devVersion
}
// Add "v" prefix and cut a patch number, "0.34.0" => "v0.34" for the URL
return fmt.Sprintf("v%d.%d", v.Major(), v.Minor())
}

View File

@@ -0,0 +1,96 @@
package doc_test
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/version/doc"
)
func TestBaseURL(t *testing.T) {
tests := []struct {
name string
ver string
want string
}{
{
name: "dev",
ver: "dev",
want: "https://aquasecurity.github.io/trivy/dev",
},
{
name: "semver",
ver: "0.52.0",
want: "https://aquasecurity.github.io/trivy/v0.52",
},
{
name: "with v prefix",
ver: "v0.52.0",
want: "https://aquasecurity.github.io/trivy/v0.52",
},
{
name: "pre-release",
ver: "0.52.0-beta1",
want: "https://aquasecurity.github.io/trivy/dev",
},
{
name: "non-semver",
ver: "1",
want: "https://aquasecurity.github.io/trivy/dev",
},
{
name: "empty",
ver: "",
want: "https://aquasecurity.github.io/trivy/dev",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := doc.BaseURL(tt.ver)
require.Equal(t, tt.want, got.String())
})
}
}
func TestURL(t *testing.T) {
tests := []struct {
name string
rawPath string
fragment string
want string
}{
{
name: "path without slash",
rawPath: "foo",
want: "https://aquasecurity.github.io/trivy/dev/foo",
},
{
name: "path with leading slash",
rawPath: "/foo",
want: "https://aquasecurity.github.io/trivy/dev/foo",
},
{
name: "path with slash",
rawPath: "foo/bar",
want: "https://aquasecurity.github.io/trivy/dev/foo/bar",
},
{
name: "path with fragment",
rawPath: "foo",
fragment: "bar",
want: "https://aquasecurity.github.io/trivy/dev/foo#bar",
},
{
name: "empty",
rawPath: "",
want: "https://aquasecurity.github.io/trivy/dev",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := doc.URL(tt.rawPath, tt.fragment)
require.Equal(t, tt.want, got)
})
}
}

View File

@@ -12,6 +12,7 @@ import (
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/version/doc"
)
var (
@@ -51,7 +52,8 @@ var SuperSet = wire.NewSet(
// Show warning if we use severity from another vendor
// cf. https://github.com/aquasecurity/trivy/issues/6714
var onceWarn = sync.OnceFunc(func() {
log.Warn("Using severities from other vendors for some vulnerabilities. Read https://aquasecurity.github.io/trivy/latest/docs/scanner/vulnerability/#severity-selection for details.")
// e.g. https://aquasecurity.github.io/trivy/latest/docs/scanner/vulnerability/#severity-selection
log.Warnf("Using severities from other vendors for some vulnerabilities. Read %s for details.", doc.URL("/docs/scanner/vulnerability/", "severity-selection"))
})
// Client manipulates vulnerabilities