Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 1 addition & 11 deletions pkg/linters/module/rules/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@ package rules
import (
errs "errors"
"io"
"os"

"github.com/deckhouse/dmt/internal/fsutils"
"github.com/deckhouse/dmt/internal/logger"
"github.com/deckhouse/dmt/internal/module"
"github.com/deckhouse/dmt/pkg"
"github.com/deckhouse/dmt/pkg/errors"
Expand Down Expand Up @@ -53,7 +51,7 @@ type LicenseRule struct {
func (r *LicenseRule) CheckFiles(mod *module.Module, errorList *errors.LintRuleErrorsList) {
errorList = errorList.WithRule(r.GetName())

files := fsutils.GetFiles(mod.GetPath(), false, filterFiles)
files := fsutils.GetFiles(mod.GetPath(), true, filterFiles)
for _, fileName := range files {
name := fsutils.Rel(mod.GetPath(), fileName)

Expand All @@ -74,14 +72,6 @@ func (r *LicenseRule) CheckFiles(mod *module.Module, errorList *errors.LintRuleE
}

func filterFiles(rootPath, path string) bool {
f, err := os.Stat(path)
if err != nil {
logger.DebugF("Error getting file info: %v", err)
return false
}
if f.IsDir() {
return false
}
path = fsutils.Rel(rootPath, path)
if fileToCheckRe.MatchString(path) && !fileToSkipRe.MatchString(path) {
return true
Expand Down
62 changes: 56 additions & 6 deletions pkg/linters/module/rules/license_library.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ import (
"errors"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
)

var CELicenseRe = regexp.MustCompile(`(?s)[/#{!-]*(\s)*Copyright 202[1-9] Flant JSC[-!}\n#/]*
var CELicenseRe = regexp.MustCompile(`(?s)[/#{!-]*(\s)*Copyright 202[1-9] Flant C?JSC[-!}\n#/]*
[/#{!-]*(\s)*Licensed under the Apache License, Version 2\.0 \(the "License"\);[-!}\n]*
[/#{!-]*(\s)*you may not use this file except in compliance with the License\.[-!}\n]*
[/#{!-]*(\s)*You may obtain a copy of the License at[-!}\n#/]*
Expand All @@ -34,6 +36,8 @@ var CELicenseRe = regexp.MustCompile(`(?s)[/#{!-]*(\s)*Copyright 202[1-9] Flant
[/#{!-]*(\s)*See the License for the specific language governing permissions and[-!}\n]*
[/#{!-]*(\s)*limitations under the License\.[-!}\n]*`)

var EELicenseRe = regexp.MustCompile(`(?s)[/#{!-]*(\s)*Copyright 202[1-9] Flant JSC[\t ]*\n([\t ]*\n)*[#{!-]*(\s)*Licensed under the Deckhouse Platform Enterprise Edition \(EE\) license\. See https://github\.com/deckhouse/deckhouse/blob/main/ee/LICENSE;[-!}\n]*`)

var fileToCheckRe = regexp.MustCompile(
`\.go$|/[^.]+$|\.sh$|\.lua$|\.py$`,
)
Expand All @@ -48,7 +52,32 @@ var flantRe = regexp.MustCompile(`Flant|Deckhouse`)

const bufSize int = 1024

// checkFileCopyright returns true if file is readable and has no copyright information in it.
// LicenseType represents the type of license expected for a file
type LicenseType int

const (
LicenseTypeCE LicenseType = iota
LicenseTypeEE
)

// getLicenseType determines the expected license type based on the file path
// Files in directories starting with "ee" should have EE license, others should have CE license
func getLicenseType(filePath string) LicenseType {
// Split the path into components
pathComponents := strings.Split(filePath, string(filepath.Separator))

// Check if any directory in the path starts with "ee"
for _, component := range pathComponents {
if strings.EqualFold(component, "ee") {
return LicenseTypeEE
}
}

return LicenseTypeCE
}

// checkFileCopyright returns true if file is readable and has the correct copyright information.
// It now checks for the appropriate license type based on the file path.
func checkFileCopyright(fName string) (bool, error) {
// Original script 'validate_copyright.sh' used 'head -n 10'.
// Here we just read first 1024 bytes.
Expand All @@ -62,17 +91,38 @@ func checkFileCopyright(fName string) (bool, error) {
return true, errors.New("generated code or other license")
}

// Check Flant license if file contains keywords.
if flantRe.Match(headBuf) {
return true, nil
// Determine expected license type based on file path
licenseType := getLicenseType(fName)

// Check for the appropriate license type
switch licenseType {
case LicenseTypeCE:
// Check for CE license (Apache 2.0)
if CELicenseRe.Match(headBuf) {
return true, nil
}
// Check if file contains Flant keywords but no proper license
if flantRe.Match(headBuf) {
return false, errors.New("file contains Flant references but missing proper CE license header")
}
case LicenseTypeEE:
// Check for EE license
if EELicenseRe.Match(headBuf) {
return true, nil
}
// Check if file contains Flant keywords but no proper license
if flantRe.Match(headBuf) {
return false, errors.New("file contains Flant references but missing proper EE license header")
}
}

// Skip file with some other copyright
if copyrightRe.Match(headBuf) {
return true, errors.New("contains other license")
}

return false, errors.New("no copyright or license information")
return false, fmt.Errorf("no copyright or license information found (expected %s license)",
map[LicenseType]string{LicenseTypeCE: "CE", LicenseTypeEE: "EE"}[licenseType])
}

func readFileHead(fName string, size int) ([]byte, error) {
Expand Down
Loading