Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9e42380
[dmt] implement remote lint
riptide-01 Jul 14, 2026
ab6e838
divide by a files
riptide-01 Jul 14, 2026
4fa494f
[dmt] add documentation linter with README validation
riptide-01 Jul 14, 2026
e8ff040
fix lint
riptide-01 Jul 14, 2026
437f3c0
fix
riptide-01 Jul 14, 2026
1ee267c
add release linting
riptide-01 Jul 14, 2026
0e5a4bc
fix lint
riptide-01 Jul 14, 2026
22fd06c
rm debug
riptide-01 Jul 14, 2026
19004ab
add test
riptide-01 Jul 14, 2026
936415d
complete docs linter
riptide-01 Jul 14, 2026
9053be5
add layour linter
riptide-01 Jul 14, 2026
53c2727
add layout linter
riptide-01 Jul 14, 2026
96564bb
fix
riptide-01 Jul 14, 2026
0ed7b24
update cutTagFromImagePath to handle unsupported digest formats; adju…
riptide-01 Jul 14, 2026
6406c73
remove CyrillicInEnglishRule to streamline linter functionality
riptide-01 Jul 14, 2026
29fb05e
add documentation
riptide-01 Jul 14, 2026
77b4727
Enhance layout linter to include module.yaml and version.json checks;…
riptide-01 Jul 14, 2026
7cf108c
Add new rules to layout linter for templates, charts, digests, Chart.…
riptide-01 Jul 14, 2026
351bb5a
make doc linter configurable
riptide-01 Jul 15, 2026
5932b76
rm trash arch
riptide-01 Jul 15, 2026
a0dc966
fix
riptide-01 Jul 15, 2026
cf151be
add comment for digests not supported
riptide-01 Jul 16, 2026
0c9699d
add remote linting support
riptide-01 Jul 16, 2026
91650ca
bump
riptide-01 Jul 16, 2026
f5d8482
add linters to remote
riptide-01 Jul 16, 2026
d0fae4e
divide interface by release and bundle linters
riptide-01 Jul 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion cmd/dmt/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/deckhouse/dmt/internal/bootstrap"
"github.com/deckhouse/dmt/internal/flags"
"github.com/deckhouse/dmt/internal/fsutils"
remotelint "github.com/deckhouse/dmt/internal/remote-lint"
"github.com/deckhouse/dmt/internal/render"
"github.com/deckhouse/dmt/internal/test"
"github.com/deckhouse/dmt/internal/version"
Expand Down Expand Up @@ -268,7 +269,20 @@ func runTests(dir string, opts ...test.Option) error {
return nil
}

func lintCmdFunc(_ *cobra.Command, args []string) {
func lintCmdFunc(cmd *cobra.Command, args []string) {
if flags.Remote != "" {
opts := &remotelint.RemoteLintOptions{
Login: flags.RemoteLogin,
Password: flags.RemotePassword,
}
if err := remotelint.RunRemoteLint(cmd.Context(), flags.Remote, opts); err != nil {
log.Error("Error running remote lint", log.Err(err))
os.Exit(1)
}

return
}

var dirs = args[0:]

if len(dirs) == 0 {
Expand Down
8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/Masterminds/sprig/v3 v3.3.0
github.com/bmatcuk/doublestar v1.3.4
github.com/deckhouse/deckhouse/pkg/log v0.2.1
github.com/deckhouse/deckhouse/pkg/registry v0.0.0-20260714071459-349ceee5aa36
github.com/fatih/color v1.19.0
github.com/go-openapi/spec v0.22.4
github.com/gobwas/glob v0.2.3
Expand Down Expand Up @@ -62,11 +63,15 @@ require (
github.com/aws/aws-sdk-go v1.55.6 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dennwc/varint v1.0.0 // indirect
github.com/djherbis/buffer v1.2.0 // indirect
github.com/djherbis/nio/v3 v3.0.1 // indirect
github.com/docker/cli v29.2.0+incompatible // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker-credential-helpers v0.9.3 // indirect
github.com/edsrzf/mmap-go v1.2.0 // indirect
github.com/emicklei/go-restful/v3 v3.11.2 // indirect
github.com/envoyproxy/go-control-plane/envoy v1.32.3 // indirect
Expand Down Expand Up @@ -125,6 +130,7 @@ require (
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.116.0 // indirect
github.com/open-telemetry/opentelemetry-collector-contrib/processor/deltatocumulativeprocessor v0.116.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect
Expand All @@ -137,13 +143,15 @@ require (
github.com/samber/lo v1.49.1 // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.7.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/vbatts/tar-split v0.12.1 // indirect
github.com/werf/common-go v0.0.0-20251113140850-a1a98e909e9b // indirect
github.com/werf/lockgate v0.1.1 // indirect
github.com/werf/logboek v0.6.1 // indirect
Expand Down
25 changes: 21 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 h1:QVw89YDxXxEe+l8gU8ETbOasdwEV+avkR75ZzsVV9WI=
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8=
github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
Expand All @@ -67,6 +69,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckhouse/deckhouse/pkg/log v0.2.1 h1:7SSD+QJPnziAO3l8ycgRwN5wlQeC312Tf7f2Wa/hWDg=
github.com/deckhouse/deckhouse/pkg/log v0.2.1/go.mod h1:pbAxTSDcPmwyl3wwKDcEB3qdxHnRxqTV+J0K+sha8bw=
github.com/deckhouse/deckhouse/pkg/registry v0.0.0-20260714071459-349ceee5aa36 h1:BHMxY2s8X/MvN2mlM58gP0AwzHCpHgDBZPG8TiOG5mQ=
github.com/deckhouse/deckhouse/pkg/registry v0.0.0-20260714071459-349ceee5aa36/go.mod h1:KDf44MqEif8jAKCehKJqOg0k4sJcnetKJKDGd0IFQjI=
github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE=
github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
Expand All @@ -82,8 +86,14 @@ github.com/djherbis/nio/v3 v3.0.1 h1:6wxhnuppteMa6RHA4L81Dq7ThkZH8SwnDzXDYy95vB4
github.com/djherbis/nio/v3 v3.0.1/go.mod h1:Ng4h80pbZFMla1yKzm61cF0tqqilXZYrogmWgZxOcmg=
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/docker/cli v29.2.0+incompatible h1:9oBd9+YM7rxjZLfyMGxjraKBKE4/nVyvVfN4qNl9XRM=
github.com/docker/cli v29.2.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v27.4.1+incompatible h1:ZJvcY7gfwHn1JF48PfbyXg7Jyt9ZCWDW+GGXOIxEwp4=
github.com/docker/docker v27.4.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
Expand Down Expand Up @@ -251,8 +261,8 @@ github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2E
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs=
github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw=
github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU=
github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
Expand Down Expand Up @@ -355,8 +365,8 @@ github.com/prometheus/sigv4 v0.1.1 h1:UJxjOqVcXctZlwDjpUpZ2OiMWJdFijgSofwLzO1Xk0
github.com/prometheus/sigv4 v0.1.1/go.mod h1:RAmWVKqx0bwi0Qm4lrKMXFM0nhpesBcenfCtz9qRyH8=
github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
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/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
Expand All @@ -370,6 +380,8 @@ github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30 h1:yoKAVkEVwAqbGbR8n87rHQ1dul
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30/go.mod h1:sH0u6fq6x4R5M7WxkoQFY/o7UaiItec0o1LinLCJNq8=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
Expand Down Expand Up @@ -407,6 +419,8 @@ github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JT
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo=
github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs=
github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI=
github.com/werf/common-go v0.0.0-20251113140850-a1a98e909e9b h1:58850oFrnw5Jy5YaB8QifXz75qpGotfx6qqZ9Q2my1A=
Expand Down Expand Up @@ -519,6 +533,7 @@ golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
Expand Down Expand Up @@ -567,6 +582,8 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
helm.sh/helm/v3 v3.18.5 h1:Cc3Z5vd6kDrZq9wO9KxKLNEickiTho6/H/dBNRVSos4=
helm.sh/helm/v3 v3.18.5/go.mod h1:L/dXDR2r539oPlFP1PJqKAC1CUgqHJDLkxKpDGrWnyg=
k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8=
Expand Down
13 changes: 10 additions & 3 deletions internal/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,12 @@ const (
)

var (
LintersLimit int
LogLevel string
LinterName string
Remote string
RemoteLogin string
RemotePassword string
LintersLimit int
LogLevel string
LinterName string
)

var (
Expand Down Expand Up @@ -62,6 +65,10 @@ func InitDefaultFlagSet() *pflag.FlagSet {
func InitLintFlagSet() *pflag.FlagSet {
lint := pflag.NewFlagSet("lint", pflag.ContinueOnError)

lint.StringVarP(&Remote, "remote", "r", "", "lint registry artifact, e.g. 'registry.example.com/my-module:v0.0.1'")
lint.StringVar(&RemoteLogin, "login", "", "login for the registry, used when --remote is set")
lint.StringVar(&RemotePassword, "password", "", "password for the registry, used when --remote is set")

lint.IntVarP(&LintersLimit, "parallel", "p", numThreads, "number of threads for parallel processing")

lint.StringVar(&LinterName, "linter", "", "linter name to run")
Expand Down
6 changes: 5 additions & 1 deletion internal/manager/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,11 @@ func getLintersForModule(cfg *pkg.LintersSettings, errList *errors.LintRuleError
}

func (m *Manager) PrintResult() {
errs := m.errors.GetErrors()
PrintResult(m.errors)
}

func PrintResult(errorList *errors.LintRuleErrorsList) {
errs := errorList.GetErrors()

if len(errs) == 0 {
return
Expand Down
4 changes: 2 additions & 2 deletions internal/module/bilingual_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import (

func TestRemapOpenAPIBilingualRuleLevel(t *testing.T) {
t.Run("defaults to error", func(t *testing.T) {
settings := remapLinterSettings(&config.LintersSettings{}, &global.Linters{})
settings := RemapLinterSettings(&config.LintersSettings{}, &global.Linters{})

require.Equal(t, pkg.Error, *settings.OpenAPI.Rules.BilingualRule.GetLevel())
})

t.Run("uses global warning level", func(t *testing.T) {
settings := remapLinterSettings(&config.LintersSettings{}, &global.Linters{
settings := RemapLinterSettings(&config.LintersSettings{}, &global.Linters{
OpenAPI: global.OpenAPILinterConfig{
Rules: global.OpenAPIRules{
BilingualRule: global.RuleConfig{Impact: pkg.Warn.String()},
Expand Down
6 changes: 3 additions & 3 deletions internal/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,10 @@ func (m *Module) GetModuleConfig() *pkg.LintersSettings {
return m.linterConfig
}

// remapLinterSettings converts configuration settings from the config package format
// RemapLinterSettings converts configuration settings from the config package format
// to the pkg package format, mapping both rule-level configurations and exclusion rules
// across all linter domains (Container, Image, NoCyrillic, OpenAPI, Templates, RBAC, Hooks, Module).
func remapLinterSettings(configSettings *config.LintersSettings, globalConfig *global.Linters) *pkg.LintersSettings {
func RemapLinterSettings(configSettings *config.LintersSettings, globalConfig *global.Linters) *pkg.LintersSettings {
linterSettings := &pkg.LintersSettings{}

// Step 1: Configure linter-level impact settings
Expand Down Expand Up @@ -543,7 +543,7 @@ func NewModule(path string, vals *chartutil.Values, globalSchema *spec.Schema, r

cfg.LintersSettings.MergeGlobal(&rootConfig.GlobalSettings.Linters)

module.linterConfig = remapLinterSettings(&cfg.LintersSettings, &rootConfig.GlobalSettings.Linters)
module.linterConfig = RemapLinterSettings(&cfg.LintersSettings, &rootConfig.GlobalSettings.Linters)

return module, nil
}
Expand Down
134 changes: 134 additions & 0 deletions internal/remote-lint/extract.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package remotelint

import (
"archive/tar"
"context"
"fmt"
"io"
"os"
"path/filepath"
"strings"

"github.com/deckhouse/deckhouse/pkg/registry"
)

// ExtractImage extracts the image to a temporary directory and returns the path to the directory
func ExtractImage(ctx context.Context, image registry.Image) (string, error) {
tempDir, err := os.MkdirTemp("", "dmt-*")
if err != nil {
return "", fmt.Errorf("failed to create temp directory: %w", err)
}

rc := image.Extract()
defer rc.Close()

err = extract(ctx, rc, tempDir)
if err != nil {
return "", fmt.Errorf("failed to extract image: %w", err)
}

return tempDir, nil
}

func extract(ctx context.Context, rc io.ReadCloser, target string) error {
tr := tar.NewReader(rc)

for {
if err := ctx.Err(); err != nil {
return err
}

hdr, err := tr.Next()
if err == io.EOF {
break
}

if err != nil {
return fmt.Errorf("read tar: %w", err)
}

target, err := safeJoin(target, hdr.Name)
if err != nil {
return err
}

switch hdr.Typeflag {
case tar.TypeDir:
if err = os.MkdirAll(target, os.FileMode(hdr.Mode)); err != nil {
return fmt.Errorf("mkdir %q: %w", hdr.Name, err)
}
case tar.TypeReg:
if err = writeRegularFile(target, tr, os.FileMode(hdr.Mode)); err != nil {
return fmt.Errorf("write file %q: %w", hdr.Name, err)
}
case tar.TypeSymlink:
if filepath.IsAbs(hdr.Linkname) || !staysWithin(target, filepath.Dir(target), hdr.Linkname) {
return fmt.Errorf("symlink %q escapes output directory", hdr.Name)
}

if err = os.Symlink(hdr.Linkname, target); err != nil {
return fmt.Errorf("create symlink %q: %w", hdr.Name, err)
}
case tar.TypeLink:
linkTarget, err := safeJoin(target, hdr.Linkname)
if err != nil {
return err
}

if err = os.Link(linkTarget, target); err != nil {
return fmt.Errorf("create hardlink %q: %w", hdr.Name, err)
}
}
}

return nil
}

// writeRegularFile writes one regular tar entry and limits restored permissions to owner bits.
func writeRegularFile(target string, src io.Reader, mode os.FileMode) error {
if err := os.MkdirAll(filepath.Dir(target), 0o700); err != nil {
return fmt.Errorf("create parent directory: %w", err)
}

out, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, mode&0o700)
if err != nil {
return fmt.Errorf("create file: %w", err)
}

if _, err = io.Copy(out, src); err != nil {
closeErr := out.Close()
if closeErr != nil {
return fmt.Errorf("copy file: %w; close file: %v", err, closeErr)
}

return fmt.Errorf("copy file: %w", err)
}

if err = out.Close(); err != nil {
return fmt.Errorf("close file: %w", err)
}

return nil
}

// safeJoin joins name under root and rejects absolute paths or parent-directory escapes.
func safeJoin(root, name string) (string, error) {
if filepath.IsAbs(name) {
return "", fmt.Errorf("path %q escapes output directory", name)
}

target := filepath.Join(root, name)
if !staysWithin(root, root, name) {
return "", fmt.Errorf("path %q escapes output directory", name)
}

return target, nil
}

// staysWithin reports whether name resolves under root when interpreted relative to base.
func staysWithin(root, base, name string) bool {
target := filepath.Clean(filepath.Join(base, name))
rel, err := filepath.Rel(root, target)

return err == nil && rel != ".." && !strings.HasPrefix(rel, ".."+string(filepath.Separator))
}
Loading
Loading