diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 354d485..86751ff 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -60,3 +60,11 @@ jobs: echo "Previous step result: ${{ steps.invalid_schema_test.outcome }}" echo "Expected the invalid schema test to fail, but it succeeded" exit 1 + + # This step should succeed, because the check that would fail is disabled + - name: Run SQLite schema lint action with invalid schema + id: invalid_schema_test + uses: ./ + with: + schema-file: 'test_schemas/failure-no-strict.sql' + require_strict: false diff --git a/action.yml b/action.yml index 2078759..d7f6cc2 100644 --- a/action.yml +++ b/action.yml @@ -1,10 +1,34 @@ # action.yml name: SQLite schema lint description: Enforce constraints on SQLite schemas + inputs: schema-file: description: SQL schema file to lint required: true + + # List of checks + require_not_null: + description: Enforce that all columns should be marked as `not null` unless they are foreign keys. + required: false + default: true + require_strict: + description: Enforce that all tables should be marked as `strict`. + required: false + default: true + forbid_int_type: + description: Enforce that all columns should use `integer` type instead of `int`. + required: false + default: true + require_explicit_primary_key: + description: Enforce that all tables must have a primary key. + required: false + default: true + require_indexes_for_foreign_keys: + description: Enforce that columns referenced by foreign keys must have indexes. + required: false + default: true + runs: using: 'docker' image: 'Dockerfile' diff --git a/cmd/main.go b/cmd/main.go index fea381c..45611e9 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -3,6 +3,7 @@ package main import ( "fmt" "os" + "strings" _ "github.com/mattn/go-sqlite3" @@ -18,7 +19,7 @@ const ( func main() { // Check if a filepath argument is provided if len(os.Args) < 2 { - fmt.Println("Please provide a filepath as the first argument.") + fmt.Println(RED + "Please provide a filepath as the first argument." + RESET) os.Exit(1) } @@ -37,6 +38,10 @@ func main() { is_failure := false // Execute each check against the database for _, check := range checks.Checks { + // Checks can be disabled via Github config / environment variables + if !is_check_enabled(check) { + continue + } results, err := check.Execute(db) if err != nil { panic(err) @@ -58,3 +63,22 @@ func main() { } fmt.Println(GREEN + "Success" + RESET) } + +// github_actions_input_env_var converts an input name to the corresponding +// environment variable name used by GitHub Actions. +func github_actions_input_env_var(name string) string { + // GitHub normalizes both hyphens and underscores to underscores, then uppercases the name + normalized := strings.NewReplacer("-", "_", " ", "_").Replace(name) + return "INPUT_" + strings.ToUpper(normalized) +} + +// Setting the environment variable INPUT_REQUIRE_NOT_NULL="false" disables the "require_not_null" check +func is_check_enabled(c checks.Check) bool { + val, is_set := os.LookupEnv(github_actions_input_env_var(c.Name)) + if !is_set { + // Enable all checks by default + return true + } + // Anything except "false" is true + return val != "false" +}