mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-09 21:17:09 +08:00
vendor: buildkit, docker/docker and docker/cli v27.0.1
diffs: - https://github.com/docker/cli/compare/v26.1.4..v27.0.1 - https://github.com/docker/docker/compare/v26.1.4..v27.0.1 - https://github.com/moby/buildkit/compare/v0.14.1...aaaf86e5470bffbb395f5c15ad4a1c152642ea30 Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
146
vendor/github.com/moby/buildkit/frontend/dockerfile/linter/linter.go
generated
vendored
Normal file
146
vendor/github.com/moby/buildkit/frontend/dockerfile/linter/linter.go
generated
vendored
Normal file
@ -0,0 +1,146 @@
|
||||
package linter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/moby/buildkit/frontend/dockerfile/parser"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Warn LintWarnFunc
|
||||
SkipRules []string
|
||||
SkipAll bool
|
||||
ReturnAsError bool
|
||||
}
|
||||
|
||||
type Linter struct {
|
||||
SkippedRules map[string]struct{}
|
||||
CalledRules []string
|
||||
SkipAll bool
|
||||
ReturnAsError bool
|
||||
Warn LintWarnFunc
|
||||
}
|
||||
|
||||
func New(config *Config) *Linter {
|
||||
toret := &Linter{
|
||||
SkippedRules: map[string]struct{}{},
|
||||
CalledRules: []string{},
|
||||
Warn: config.Warn,
|
||||
}
|
||||
toret.SkipAll = config.SkipAll
|
||||
toret.ReturnAsError = config.ReturnAsError
|
||||
for _, rule := range config.SkipRules {
|
||||
toret.SkippedRules[rule] = struct{}{}
|
||||
}
|
||||
return toret
|
||||
}
|
||||
|
||||
func (lc *Linter) Run(rule LinterRuleI, location []parser.Range, txt ...string) {
|
||||
if lc == nil || lc.Warn == nil || lc.SkipAll {
|
||||
return
|
||||
}
|
||||
rulename := rule.RuleName()
|
||||
if _, ok := lc.SkippedRules[rulename]; ok {
|
||||
return
|
||||
}
|
||||
lc.CalledRules = append(lc.CalledRules, rulename)
|
||||
rule.Run(lc.Warn, location, txt...)
|
||||
}
|
||||
|
||||
func (lc *Linter) Error() error {
|
||||
if lc == nil || !lc.ReturnAsError {
|
||||
return nil
|
||||
}
|
||||
if len(lc.CalledRules) == 0 {
|
||||
return nil
|
||||
}
|
||||
var rules []string
|
||||
uniqueRules := map[string]struct{}{}
|
||||
for _, r := range lc.CalledRules {
|
||||
uniqueRules[r] = struct{}{}
|
||||
}
|
||||
for r := range uniqueRules {
|
||||
rules = append(rules, r)
|
||||
}
|
||||
return errors.Errorf("lint violation found for rules: %s", strings.Join(rules, ", "))
|
||||
}
|
||||
|
||||
type LinterRuleI interface {
|
||||
RuleName() string
|
||||
Run(warn LintWarnFunc, location []parser.Range, txt ...string)
|
||||
}
|
||||
|
||||
type LinterRule[F any] struct {
|
||||
Name string
|
||||
Description string
|
||||
URL string
|
||||
Format F
|
||||
}
|
||||
|
||||
func (rule *LinterRule[F]) RuleName() string {
|
||||
return rule.Name
|
||||
}
|
||||
|
||||
func (rule *LinterRule[F]) Run(warn LintWarnFunc, location []parser.Range, txt ...string) {
|
||||
if len(txt) == 0 {
|
||||
txt = []string{rule.Description}
|
||||
}
|
||||
short := strings.Join(txt, " ")
|
||||
warn(rule.Name, rule.Description, rule.URL, short, location)
|
||||
}
|
||||
|
||||
func LintFormatShort(rulename, msg string, line int) string {
|
||||
msg = fmt.Sprintf("%s: %s", rulename, msg)
|
||||
if line > 0 {
|
||||
msg = fmt.Sprintf("%s (line %d)", msg, line)
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
type LintWarnFunc func(rulename, description, url, fmtmsg string, location []parser.Range)
|
||||
|
||||
func ParseLintOptions(checkStr string) (*Config, error) {
|
||||
checkStr = strings.TrimSpace(checkStr)
|
||||
if checkStr == "" {
|
||||
return &Config{}, nil
|
||||
}
|
||||
|
||||
parts := strings.SplitN(checkStr, ";", 2)
|
||||
var skipSet []string
|
||||
var errorOnWarn, skipAll bool
|
||||
for _, p := range parts {
|
||||
k, v, ok := strings.Cut(p, "=")
|
||||
if !ok {
|
||||
return nil, errors.Errorf("invalid check option %q", p)
|
||||
}
|
||||
k = strings.TrimSpace(k)
|
||||
switch k {
|
||||
case "skip":
|
||||
v = strings.TrimSpace(v)
|
||||
if v == "all" {
|
||||
skipAll = true
|
||||
} else {
|
||||
skipSet = strings.Split(v, ",")
|
||||
for i, rule := range skipSet {
|
||||
skipSet[i] = strings.TrimSpace(rule)
|
||||
}
|
||||
}
|
||||
case "error":
|
||||
v, err := strconv.ParseBool(strings.TrimSpace(v))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse check option %q", p)
|
||||
}
|
||||
errorOnWarn = v
|
||||
default:
|
||||
return nil, errors.Errorf("invalid check option %q", k)
|
||||
}
|
||||
}
|
||||
return &Config{
|
||||
SkipRules: skipSet,
|
||||
SkipAll: skipAll,
|
||||
ReturnAsError: errorOnWarn,
|
||||
}, nil
|
||||
}
|
127
vendor/github.com/moby/buildkit/frontend/dockerfile/linter/ruleset.go
generated
vendored
Normal file
127
vendor/github.com/moby/buildkit/frontend/dockerfile/linter/ruleset.go
generated
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
package linter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
RuleStageNameCasing = LinterRule[func(string) string]{
|
||||
Name: "StageNameCasing",
|
||||
Description: "Stage names should be lowercase",
|
||||
URL: "https://docs.docker.com/go/dockerfile/rule/stage-name-casing/",
|
||||
Format: func(stageName string) string {
|
||||
return fmt.Sprintf("Stage name '%s' should be lowercase", stageName)
|
||||
},
|
||||
}
|
||||
RuleFromAsCasing = LinterRule[func(string, string) string]{
|
||||
Name: "FromAsCasing",
|
||||
Description: "The 'as' keyword should match the case of the 'from' keyword",
|
||||
URL: "https://docs.docker.com/go/dockerfile/rule/from-as-casing/",
|
||||
Format: func(from, as string) string {
|
||||
return fmt.Sprintf("'%s' and '%s' keywords' casing do not match", as, from)
|
||||
},
|
||||
}
|
||||
RuleNoEmptyContinuation = LinterRule[func() string]{
|
||||
Name: "NoEmptyContinuation",
|
||||
Description: "Empty continuation lines will become errors in a future release",
|
||||
URL: "https://docs.docker.com/go/dockerfile/rule/no-empty-continuation/",
|
||||
Format: func() string {
|
||||
return "Empty continuation line"
|
||||
},
|
||||
}
|
||||
RuleConsistentInstructionCasing = LinterRule[func(string, string) string]{
|
||||
Name: "ConsistentInstructionCasing",
|
||||
Description: "All commands within the Dockerfile should use the same casing (either upper or lower)",
|
||||
URL: "https://docs.docker.com/go/dockerfile/rule/consistent-instruction-casing/",
|
||||
Format: func(violatingCommand, correctCasing string) string {
|
||||
return fmt.Sprintf("Command '%s' should match the case of the command majority (%s)", violatingCommand, correctCasing)
|
||||
},
|
||||
}
|
||||
RuleDuplicateStageName = LinterRule[func(string) string]{
|
||||
Name: "DuplicateStageName",
|
||||
Description: "Stage names should be unique",
|
||||
URL: "https://docs.docker.com/go/dockerfile/rule/duplicate-stage-name/",
|
||||
Format: func(stageName string) string {
|
||||
return fmt.Sprintf("Duplicate stage name %q, stage names should be unique", stageName)
|
||||
},
|
||||
}
|
||||
RuleReservedStageName = LinterRule[func(string) string]{
|
||||
Name: "ReservedStageName",
|
||||
Description: "Reserved words should not be used as stage names",
|
||||
URL: "https://docs.docker.com/go/dockerfile/rule/reserved-stage-name/",
|
||||
Format: func(reservedStageName string) string {
|
||||
return fmt.Sprintf("Stage name should not use the same name as reserved stage %q", reservedStageName)
|
||||
},
|
||||
}
|
||||
RuleJSONArgsRecommended = LinterRule[func(instructionName string) string]{
|
||||
Name: "JSONArgsRecommended",
|
||||
Description: "JSON arguments recommended for ENTRYPOINT/CMD to prevent unintended behavior related to OS signals",
|
||||
URL: "https://docs.docker.com/go/dockerfile/rule/json-args-recommended/",
|
||||
Format: func(instructionName string) string {
|
||||
return fmt.Sprintf("JSON arguments recommended for %s to prevent unintended behavior related to OS signals", instructionName)
|
||||
},
|
||||
}
|
||||
RuleMaintainerDeprecated = LinterRule[func() string]{
|
||||
Name: "MaintainerDeprecated",
|
||||
Description: "The MAINTAINER instruction is deprecated, use a label instead to define an image author",
|
||||
URL: "https://docs.docker.com/go/dockerfile/rule/maintainer-deprecated/",
|
||||
Format: func() string {
|
||||
return "Maintainer instruction is deprecated in favor of using label"
|
||||
},
|
||||
}
|
||||
RuleUndefinedArgInFrom = LinterRule[func(string, string) string]{
|
||||
Name: "UndefinedArgInFrom",
|
||||
Description: "FROM command must use declared ARGs",
|
||||
URL: "https://docs.docker.com/go/dockerfile/rule/undefined-arg-in-from/",
|
||||
Format: func(baseArg, suggest string) string {
|
||||
out := fmt.Sprintf("FROM argument '%s' is not declared", baseArg)
|
||||
if suggest != "" {
|
||||
out += fmt.Sprintf(" (did you mean %s?)", suggest)
|
||||
}
|
||||
return out
|
||||
},
|
||||
}
|
||||
RuleWorkdirRelativePath = LinterRule[func(workdir string) string]{
|
||||
Name: "WorkdirRelativePath",
|
||||
Description: "Relative workdir without an absolute workdir declared within the build can have unexpected results if the base image changes",
|
||||
URL: "https://docs.docker.com/go/dockerfile/rule/workdir-relative-path/",
|
||||
Format: func(workdir string) string {
|
||||
return fmt.Sprintf("Relative workdir %q can have unexpected results if the base image changes", workdir)
|
||||
},
|
||||
}
|
||||
RuleUndefinedVar = LinterRule[func(string, string) string]{
|
||||
Name: "UndefinedVar",
|
||||
Description: "Variables should be defined before their use",
|
||||
URL: "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
|
||||
Format: func(arg, suggest string) string {
|
||||
out := fmt.Sprintf("Usage of undefined variable '$%s'", arg)
|
||||
if suggest != "" {
|
||||
out += fmt.Sprintf(" (did you mean $%s?)", suggest)
|
||||
}
|
||||
return out
|
||||
},
|
||||
}
|
||||
RuleMultipleInstructionsDisallowed = LinterRule[func(instructionName string) string]{
|
||||
Name: "MultipleInstructionsDisallowed",
|
||||
Description: "Multiple instructions of the same type should not be used in the same stage",
|
||||
URL: "https://docs.docker.com/go/dockerfile/rule/multiple-instructions-disallowed/",
|
||||
Format: func(instructionName string) string {
|
||||
return fmt.Sprintf("Multiple %s instructions should not be used in the same stage because only the last one will be used", instructionName)
|
||||
},
|
||||
}
|
||||
RuleLegacyKeyValueFormat = LinterRule[func(cmdName string) string]{
|
||||
Name: "LegacyKeyValueFormat",
|
||||
Description: "Legacy key/value format with whitespace separator should not be used",
|
||||
URL: "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
|
||||
Format: func(cmdName string) string {
|
||||
return fmt.Sprintf("\"%s key=value\" should be used instead of legacy \"%s key value\" format", cmdName, cmdName)
|
||||
},
|
||||
}
|
||||
RuleInvalidBaseImagePlatform = LinterRule[func(string, string, string) string]{
|
||||
Name: "InvalidBaseImagePlatform",
|
||||
Description: "Base image platform does not match expected target platform",
|
||||
Format: func(image, expected, actual string) string {
|
||||
return fmt.Sprintf("Base image %s was pulled with platform %q, expected %q for current build", image, actual, expected)
|
||||
},
|
||||
}
|
||||
)
|
Reference in New Issue
Block a user