feature: add weak-compatible to dependency check (#171)

diff --git a/assets/compatibility/Apache-2.0.yaml b/assets/compatibility/Apache-2.0.yaml
index 752f871..4111a24 100644
--- a/assets/compatibility/Apache-2.0.yaml
+++ b/assets/compatibility/Apache-2.0.yaml
@@ -89,3 +89,22 @@
   - CPOL-1.02
   - NPL-1.0
   - NPL-1.1
+
+weak-compatible:
+  - CDDL-1.0
+  - CDDL-1.1
+  - CPL-1.0
+  - EPL-1.0
+  - EPL-2.0
+  - ErlPL-1.1
+  - IPA
+  - IPL-1.0
+  - LicenseRef-scancode-ubuntu-font-1.0
+  - LicenseRef-scancode-unrar
+  - MPL-1.0
+  - MPL-1.1
+  - MPL-2.0
+  - OFL-1.1
+  - OSL-3.0
+  - Ruby
+  - SPL-1.0
\ No newline at end of file
diff --git a/commands/deps_check.go b/commands/deps_check.go
index 8073d0b..87aab07 100644
--- a/commands/deps_check.go
+++ b/commands/deps_check.go
@@ -26,6 +26,15 @@
 	"github.com/apache/skywalking-eyes/pkg/deps"
 )
 
+var weakCompatible bool
+
+func init() {
+	DepsCheckCommand.PersistentFlags().BoolVarP(&weakCompatible, "weak-compatible", "w", false,
+		"if set to true, treat the weak-compatible licenses as compatible in dependencies check. "+
+			"Note: when set to true, make sure to manually confirm that weak-compatible licenses "+
+			"are used under the required conditions.")
+}
+
 var DepsCheckCommand = &cobra.Command{
 	Use:     "check",
 	Aliases: []string{"c"},
@@ -34,7 +43,7 @@
 		var errors []error
 		configDeps := Config.Dependencies()
 		for _, header := range Config.Headers() {
-			if err := deps.Check(header.License.SpdxID, configDeps); err != nil {
+			if err := deps.Check(header.License.SpdxID, configDeps, weakCompatible); err != nil {
 				errors = append(errors, err)
 			}
 		}
diff --git a/pkg/deps/check.go b/pkg/deps/check.go
index f5c663a..04e8301 100644
--- a/pkg/deps/check.go
+++ b/pkg/deps/check.go
@@ -30,8 +30,9 @@
 )
 
 type CompatibilityMatrix struct {
-	Compatible   []string `yaml:"compatible"`
-	Incompatible []string `yaml:"incompatible"`
+	Compatible     []string `yaml:"compatible"`
+	Incompatible   []string `yaml:"incompatible"`
+	WeakCompatible []string `yaml:"weak-compatible"`
 }
 
 var matrices = make(map[string]CompatibilityMatrix)
@@ -63,7 +64,7 @@
 	}
 }
 
-func Check(mainLicenseSpdxID string, config *ConfigDeps) error {
+func Check(mainLicenseSpdxID string, config *ConfigDeps, weakCompatible bool) error {
 	matrix := matrices[mainLicenseSpdxID]
 
 	report := Report{}
@@ -71,7 +72,7 @@
 		return nil
 	}
 
-	return CheckWithMatrix(mainLicenseSpdxID, &matrix, &report)
+	return CheckWithMatrix(mainLicenseSpdxID, &matrix, &report, weakCompatible)
 }
 
 func compare(list []string, spdxID string) bool {
@@ -99,16 +100,22 @@
 	return false
 }
 
-func CheckWithMatrix(mainLicenseSpdxID string, matrix *CompatibilityMatrix, report *Report) error {
+func compareCompatible(matrix *CompatibilityMatrix, spdxID string, weakCompatible bool) bool {
+	if weakCompatible {
+		return compare(matrix.Compatible, spdxID) || compare(matrix.WeakCompatible, spdxID)
+	}
+	return compare(matrix.Compatible, spdxID)
+}
+
+func CheckWithMatrix(mainLicenseSpdxID string, matrix *CompatibilityMatrix, report *Report, weakCompatible bool) error {
 	var incompatibleResults []*Result
 	var unknownResults []*Result
 	for _, result := range append(report.Resolved, report.Skipped...) {
 		operator, spdxIDs := parseLicenseExpression(result.LicenseSpdxID)
-
 		switch operator {
 		case LicenseOperatorAND:
 			if compareAll(spdxIDs, func(spdxID string) bool {
-				return compare(matrix.Compatible, spdxID)
+				return compareCompatible(matrix, spdxID, weakCompatible)
 			}) {
 				continue
 			}
@@ -120,7 +127,7 @@
 
 		case LicenseOperatorOR:
 			if compareAny(spdxIDs, func(spdxID string) bool {
-				return compare(matrix.Compatible, spdxID)
+				return compareCompatible(matrix, spdxID, weakCompatible)
 			}) {
 				continue
 			}
@@ -134,6 +141,9 @@
 			if compatible := compare(matrix.Compatible, spdxIDs[0]); compatible {
 				continue
 			}
+			if weakCompatible && compare(matrix.WeakCompatible, spdxIDs[0]) {
+				continue
+			}
 			if incompatible := compare(matrix.Incompatible, spdxIDs[0]); incompatible {
 				incompatibleResults = append(incompatibleResults, result)
 				continue
diff --git a/pkg/deps/check_test.go b/pkg/deps/check_test.go
index db4a250..2799991 100644
--- a/pkg/deps/check_test.go
+++ b/pkg/deps/check_test.go
@@ -18,9 +18,10 @@
 package deps_test
 
 import (
-	"github.com/apache/skywalking-eyes/pkg/deps"
 	"strings"
 	"testing"
+
+	"github.com/apache/skywalking-eyes/pkg/deps"
 )
 
 var TestMatrix = deps.CompatibilityMatrix{
@@ -52,6 +53,9 @@
 		"GPL-2.0-only",
 		"GPL-2.0-or-later",
 	},
+	WeakCompatible: []string{
+		"MPL-2.0",
+	},
 }
 
 func TestCheckWithMatrix(t *testing.T) {
@@ -62,7 +66,7 @@
 				LicenseSpdxID: "Apache-2.0",
 			},
 		},
-	}); err != nil {
+	}, false); err != nil {
 		t.Errorf("Shouldn't return error")
 	}
 
@@ -77,7 +81,7 @@
 				LicenseSpdxID: "LGPL-2.0",
 			},
 		},
-	}); err == nil {
+	}, false); err == nil {
 		t.Errorf("Should return error")
 	} else if !strings.Contains(err.Error(), "Bar        | LGPL-2.0") {
 		t.Errorf("Should return error and contains dependency Bar, now is `%s`", err.Error())
@@ -96,7 +100,7 @@
 				LicenseSpdxID: "Unknown",
 			},
 		},
-	}); err == nil {
+	}, false); err == nil {
 		t.Errorf("Should return error")
 	} else if !strings.Contains(err.Error(), "Bar        | Unknown") {
 		t.Errorf("Should return error and has dependency Bar, now is `%s`", err.Error())
@@ -109,7 +113,7 @@
 				LicenseSpdxID: "Apache-2.0 OR MIT",
 			},
 		},
-	}); err != nil {
+	}, false); err != nil {
 		t.Errorf("Shouldn't return error")
 	}
 
@@ -120,7 +124,7 @@
 				LicenseSpdxID: "GPL-3.0 and GPL-3.0-or-later",
 			},
 		},
-	}); err == nil {
+	}, false); err == nil {
 		t.Errorf("Should return error")
 	}
 
@@ -131,7 +135,7 @@
 				LicenseSpdxID: "LGPL-2.1-only AND MIT AND BSD-2-Clause",
 			},
 		},
-	}); err == nil {
+	}, false); err == nil {
 		t.Errorf("Should return error")
 	}
 
@@ -142,7 +146,29 @@
 				LicenseSpdxID: "GPL-2.0-or-later WITH Bison-exception-2.2",
 			},
 		},
-	}); err == nil {
+	}, false); err == nil {
 		t.Errorf("Should return error")
 	}
+
+	if err := deps.CheckWithMatrix("Apache-2.0", &TestMatrix, &deps.Report{
+		Resolved: []*deps.Result{
+			{
+				Dependency:    "Foo",
+				LicenseSpdxID: "MPL-2.0",
+			},
+		},
+	}, false); err == nil {
+		t.Errorf("Should return error since weak-compatible is turned off")
+	}
+
+	if err := deps.CheckWithMatrix("Apache-2.0", &TestMatrix, &deps.Report{
+		Resolved: []*deps.Result{
+			{
+				Dependency:    "Bar",
+				LicenseSpdxID: "MPL-2.0",
+			},
+		},
+	}, true); err != nil {
+		t.Errorf("Shouldn't return error")
+	}
 }