From 91ba62672de774d317c2a38be60ed1b391eaf747 Mon Sep 17 00:00:00 2001 From: Andrew Rynhard Date: Sun, 13 Jan 2019 08:28:37 -0800 Subject: [PATCH] feat: add license header policy Signed-off-by: Andrew Rynhard --- .conform.yaml | 7 ++ README.md | 14 +++- cmd/enforce.go | 15 +--- cmd/root.go | 15 +--- cmd/version.go | 15 +--- hack/LICENSE_HEADER.txt | 3 + internal/constants/constants.go | 4 + internal/enforcer/enforcer.go | 6 ++ internal/git/git.go | 4 + internal/policy/commit/commit.go | 4 + .../conventionalcommit/conventionalcommit.go | 4 + .../conventionalcommit_test.go | 4 + internal/policy/license/license.go | 81 +++++++++++++++++++ internal/policy/policy.go | 4 + internal/policy/policy_options.go | 4 + internal/policy/version/version.go | 4 + main.go | 15 +--- 17 files changed, 154 insertions(+), 49 deletions(-) create mode 100644 hack/LICENSE_HEADER.txt create mode 100644 internal/policy/license/license.go diff --git a/.conform.yaml b/.conform.yaml index df3ac09a..c829808e 100644 --- a/.conform.yaml +++ b/.conform.yaml @@ -16,3 +16,10 @@ policies: scopes: - policy - '*' +- type: license + spec: + includeSuffixes: + - .go + excludeSuffixes: + # - .go + headerFile: ./hack/LICENSE_HEADER.txt diff --git a/README.md b/README.md index bd13d5e1..636ad691 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ Some of the policies included are: - Developer Certificate of Origin - GPG signature - **Conventional Commits**: Enforce [conventional commits](https://www.conventionalcommits.org) for all commit messages. +- **License Headers**: Enforce license headers on source code files. ## Getting Started @@ -41,12 +42,23 @@ policies: - "type" scopes: - "scope" +- type: license + spec: + includeSuffixes: + - .ext + excludeSuffixes: + - .exclude-ext-prefix.ext + headerFile: ./hack/LICENSE_HEADER.txt ``` In the same directory, run: ```bash -conform enforce +$ conform enforce +POLICY STATUS MESSAGE +commit PASS +conventionalCommit PASS +license PASS ``` ### License diff --git a/cmd/enforce.go b/cmd/enforce.go index eb8d0680..78f4cae9 100644 --- a/cmd/enforce.go +++ b/cmd/enforce.go @@ -1,15 +1,6 @@ -// Copyright © 2017 NAME HERE -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package cmd diff --git a/cmd/root.go b/cmd/root.go index 3bd17397..20b93f05 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,15 +1,6 @@ -// Copyright © 2017 NAME HERE -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package cmd diff --git a/cmd/version.go b/cmd/version.go index 432768db..115bc1de 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -1,15 +1,6 @@ -// Copyright © 2017 NAME HERE -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package cmd diff --git a/hack/LICENSE_HEADER.txt b/hack/LICENSE_HEADER.txt new file mode 100644 index 00000000..e0032240 --- /dev/null +++ b/hack/LICENSE_HEADER.txt @@ -0,0 +1,3 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 9d02cc50..5d8e7920 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -1,3 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + package constants const ( diff --git a/internal/enforcer/enforcer.go b/internal/enforcer/enforcer.go index 947d2397..ab6e2294 100644 --- a/internal/enforcer/enforcer.go +++ b/internal/enforcer/enforcer.go @@ -1,3 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + package enforcer import ( @@ -9,6 +13,7 @@ import ( "github.com/autonomy/conform/internal/policy" "github.com/autonomy/conform/internal/policy/commit" "github.com/autonomy/conform/internal/policy/conventionalcommit" + "github.com/autonomy/conform/internal/policy/license" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" @@ -31,6 +36,7 @@ type PolicyDeclaration struct { var policyMap = map[string]policy.Policy{ "commit": &commit.Commit{}, "conventionalCommit": &conventionalcommit.Conventional{}, + "license": &license.License{}, // "version": &version.Version{}, } diff --git a/internal/git/git.go b/internal/git/git.go index c099b6f8..87d4999f 100644 --- a/internal/git/git.go +++ b/internal/git/git.go @@ -1,3 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + package git import ( diff --git a/internal/policy/commit/commit.go b/internal/policy/commit/commit.go index 67e1c4f5..95da8d86 100644 --- a/internal/policy/commit/commit.go +++ b/internal/policy/commit/commit.go @@ -1,3 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + package commit import ( diff --git a/internal/policy/conventionalcommit/conventionalcommit.go b/internal/policy/conventionalcommit/conventionalcommit.go index 4a661799..8ea63353 100644 --- a/internal/policy/conventionalcommit/conventionalcommit.go +++ b/internal/policy/conventionalcommit/conventionalcommit.go @@ -1,3 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + package conventionalcommit import ( diff --git a/internal/policy/conventionalcommit/conventionalcommit_test.go b/internal/policy/conventionalcommit/conventionalcommit_test.go index c3242636..4f6dd0d7 100644 --- a/internal/policy/conventionalcommit/conventionalcommit_test.go +++ b/internal/policy/conventionalcommit/conventionalcommit_test.go @@ -1,3 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + package conventionalcommit import ( diff --git a/internal/policy/license/license.go b/internal/policy/license/license.go new file mode 100644 index 00000000..df5816a8 --- /dev/null +++ b/internal/policy/license/license.go @@ -0,0 +1,81 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package license + +import ( + "bytes" + "io/ioutil" + "os" + "path/filepath" + "strings" + + "github.com/autonomy/conform/internal/policy" + "github.com/pkg/errors" +) + +// License implements the policy.Policy interface and enforces source code +// license headers. +type License struct { + // IncludeSuffixes is the regex used to find files that the licenese policy + // should be applied to. + IncludeSuffixes []string `mapstructure:"includeSuffixes"` + // ExcludeSuffixes is the Suffixes used to find files that the licenese policy + // should not be applied to. + ExcludeSuffixes []string `mapstructure:"excludeSuffixes"` + // LicenseHeaderFile is the path to the license header file. + LicenseHeaderFile string `mapstructure:"headerFile"` +} + +// Compliance implements the policy.Policy.Compliance function. +func (l *License) Compliance(options *policy.Options) (report policy.Report) { + var err error + + report = policy.Report{} + + var value []byte + if value, err = ioutil.ReadFile(l.LicenseHeaderFile); err != nil { + report.Errors = append(report.Errors, errors.Errorf("Failed to open %s", l.LicenseHeaderFile)) + } + + err = filepath.Walk(".", func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if info.Mode().IsRegular() { + // Skip excluded suffixes. + for _, suffix := range l.ExcludeSuffixes { + if strings.HasSuffix(info.Name(), suffix) { + continue + } + } + // Check files matching the included suffixes. + for _, suffix := range l.IncludeSuffixes { + if strings.HasSuffix(info.Name(), suffix) { + var contents []byte + if contents, err = ioutil.ReadFile(path); err != nil { + report.Errors = append(report.Errors, errors.Errorf("Failed to open %s", path)) + return nil + } + ValidateLicenseHeader(&report, info.Name(), contents, value) + } + } + } + return nil + }) + if err != nil { + report.Errors = append(report.Errors, errors.Errorf("Failed to walk directory: %v", err)) + } + + return report +} + +// ValidateLicenseHeader checks the header of a file and ensures it contains the +// provided value. +func ValidateLicenseHeader(report *policy.Report, name string, contents, value []byte) { + if bytes.HasPrefix(contents, value) { + return + } + report.Errors = append(report.Errors, errors.Errorf("File %s does not contain a license header", name)) +} diff --git a/internal/policy/policy.go b/internal/policy/policy.go index 5ab06209..2c5983ac 100644 --- a/internal/policy/policy.go +++ b/internal/policy/policy.go @@ -1,3 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + package policy // Report summarizes the compliance of a policy. diff --git a/internal/policy/policy_options.go b/internal/policy/policy_options.go index ba8b4002..8e1d388b 100644 --- a/internal/policy/policy_options.go +++ b/internal/policy/policy_options.go @@ -1,3 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + package policy // Option is a functional option used to pass in arguments to a Policy. diff --git a/internal/policy/version/version.go b/internal/policy/version/version.go index a634a82c..4ec958f8 100644 --- a/internal/policy/version/version.go +++ b/internal/policy/version/version.go @@ -1,3 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + package version // Version defines the version policy to use and the options specific to the diff --git a/main.go b/main.go index 0c4004f1..aa84b672 100644 --- a/main.go +++ b/main.go @@ -1,15 +1,6 @@ -// Copyright © 2017 NAME HERE -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package main