Repository: k1LoW/tbls
Pull request #517 (2023-10-07 08:51:10)

feat:requireViewpoints
## Description
Fixes https://github.com/k1LoW/tbls/issues/516

## [Type of change](https://github.com/embeddedartistry/templates/blob/master/oss_docs/PULL_REQUEST_TEMPLATE.md#type-of-change)

 New feature (non-breaking change which adds functionality)

## [How Has This Been Tested?](https://github.com/embeddedartistry/templates/blob/master/oss_docs/PULL_REQUEST_TEMPLATE.md#how-has-this-been-tested)

- Added unit test codes, based on existing test codes.
- Tested locally with my codebase with a table (https://github.com/macoto1995/redwood-graphile-worker)
  - set `requireViewpoints` enabled and checked 
    - lint passed when viewpoints are set
    - throws an error when no viewpoint was set


Patch:
diff --git a/README.md b/README.md
index e5b96dd..76f8836 100644
--- a/README.md
+++ b/README.md
@@ -801,6 +801,11 @@ lint:
     enabled: true
     exclude:
       - schema_migrations
+  # checks if tables are included in at leaset one viewpoint
+  requireViewpoints: 
+    enabled: true
+    exclued:
+      - schema_migrations
 ```
 
 ### Filter tables
diff --git a/config/lint.go b/config/lint.go
index c7462bc..822bcee 100644
--- a/config/lint.go
+++ b/config/lint.go
@@ -23,6 +23,7 @@ type Lint struct {
 	DuplicateRelations       DuplicateRelations       `yaml:"duplicateRelations"`
 	RequireForeignKeyIndex   RequireForeignKeyIndex   `yaml:"requireForeignKeyIndex"`
 	LabelStyleBigQuery       LabelStyleBigQuery       `yaml:"labelStyleBigQuery"`
+	RequireViewpoints        RequireViewpoints        `yaml:"requireViewpoints"`
 }
 
 // RuleWarn is struct of Rule error
@@ -664,3 +665,48 @@ func checkLabelStyleBigQuery(label string) bool {
 	}
 	return true
 }
+
+// RequireViewpoints checks if the table is included in any viewpoints.
+type RequireViewpoints struct {
+	Enabled bool     `yaml:"enabled"`
+	Exclude []string `yaml:"exclude"`
+}
+
+// IsEnabled return Rule is enabled or not
+func (r RequireViewpoints) IsEnabled() bool {
+	return r.Enabled
+}
+
+// Check if the table is included in any viewpoints.
+func (r RequireViewpoints) Check(s *schema.Schema, exclude []string) []RuleWarn {
+	warns := []RuleWarn{}
+	if !r.IsEnabled() {
+		return warns
+	}
+	msgFmt := "table `%s` is not included in any viewpoints."
+
+T:
+	for _, t := range s.Tables {
+		if match(exclude, t.Name) {
+			continue
+		}
+
+		if match(r.Exclude, t.Name) {
+			continue
+		}
+
+		for _, v := range s.Viewpoints {
+			for _, vt := range v.Tables {
+				if vt == t.Name {
+					continue T
+				}
+			}
+		}
+		warns = append(warns, RuleWarn{
+			Target:  t.Name,
+			Message: fmt.Sprintf(msgFmt, t.Name),
+		})
+	}
+
+	return warns
+}


Test patch:
diff --git a/config/lint_test.go b/config/lint_test.go
index 69ee807..041a799 100644
--- a/config/lint_test.go
+++ b/config/lint_test.go
@@ -642,6 +642,15 @@ func newTestSchema(t *testing.T) *schema.Schema {
 			Name:            "testdriver",
 			DatabaseVersion: "1.0.0",
 		},
+		Viewpoints: []*schema.Viewpoint{
+			&schema.Viewpoint{
+				Name: "testviewpoint",
+				Desc: "testviewpoint desc",
+				Tables: []string{
+					"table_c", // table_a and table_b is not included
+				},
+			},
+		},
 	}
 	return s
 }
@@ -679,3 +688,32 @@ func newTestNoRelationSchema(t *testing.T) *schema.Schema {
 	s.Relations = nil
 	return s
 }
+
+func TestRequireViewpoints(t *testing.T) {
+	tests := []struct {
+		enabled     bool
+		lintExclude []string
+		exclude     []string
+		want        int
+	}{
+		{true, []string{}, []string{}, 2},
+		{false, []string{}, []string{}, 0},
+		{true, []string{"table_a"}, []string{}, 1},
+		{true, []string{"*_a"}, []string{}, 1},
+		{true, []string{}, []string{"table_b"}, 1},
+	}
+
+	for i, tt := range tests {
+		r := RequireViewpoints{
+			Enabled: tt.enabled,
+			Exclude: tt.exclude,
+		}
+		s := newTestSchema(t)
+
+		s.Tables[0].Type = "VIEW"
+		warns := r.Check(s, tt.lintExclude)
+		if len(warns) != tt.want {
+			t.Errorf("TestRequireViewpoints(%d): got %v\nwant %v", i, len(warns), tt.want)
+		}
+	}
+}