Skip to content

Commit 71690af

Browse files
authored
Merge pull request #122 from sachinkumarsingh092/include-spellcheck-boilerplate-tests
Add spelling and boilerplate checks
2 parents 2bb7525 + 981be3f commit 71690af

10 files changed

+405
-0
lines changed

Diff for: boilerplate/boilerplate.Dockerfile.txt

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright YEAR The Kubernetes Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.

Diff for: boilerplate/boilerplate.Makefile.txt

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright YEAR The Kubernetes Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.

Diff for: boilerplate/boilerplate.bzl.txt

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright YEAR The Kubernetes Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.

Diff for: boilerplate/boilerplate.go.txt

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
Copyright YEAR The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/

Diff for: boilerplate/boilerplate.py

+202
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
#!/usr/bin/env python
2+
3+
# Copyright 2019 The Kubernetes Authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
from __future__ import print_function
18+
19+
import argparse
20+
import difflib
21+
import glob
22+
import json
23+
import mmap
24+
import os
25+
import re
26+
import sys
27+
from datetime import date
28+
29+
parser = argparse.ArgumentParser()
30+
parser.add_argument(
31+
"filenames",
32+
help="list of files to check, all files if unspecified",
33+
nargs='*')
34+
35+
# Rootdir defaults to the directory **above** the repo-infra dir.
36+
rootdir = os.path.dirname(__file__) + "./../../../"
37+
rootdir = os.path.abspath(rootdir)
38+
parser.add_argument(
39+
"--rootdir", default=rootdir, help="root directory to examine")
40+
41+
default_boilerplate_dir = os.path.join(rootdir, "csi-driver-nfs/hack/boilerplate")
42+
43+
parser.add_argument(
44+
"--boilerplate-dir", default=default_boilerplate_dir)
45+
46+
parser.add_argument(
47+
"-v", "--verbose",
48+
help="give verbose output regarding why a file does not pass",
49+
action="store_true")
50+
51+
args = parser.parse_args()
52+
53+
verbose_out = sys.stderr if args.verbose else open("/dev/null", "w")
54+
55+
def get_refs():
56+
refs = {}
57+
58+
for path in glob.glob(os.path.join(args.boilerplate_dir, "boilerplate.*.txt")):
59+
extension = os.path.basename(path).split(".")[1]
60+
61+
ref_file = open(path, 'r')
62+
ref = ref_file.read().splitlines()
63+
ref_file.close()
64+
refs[extension] = ref
65+
66+
return refs
67+
68+
def file_passes(filename, refs, regexs):
69+
try:
70+
f = open(filename, 'r')
71+
except Exception as exc:
72+
print("Unable to open %s: %s" % (filename, exc), file=verbose_out)
73+
return False
74+
75+
data = f.read()
76+
f.close()
77+
78+
basename = os.path.basename(filename)
79+
extension = file_extension(filename)
80+
if extension != "":
81+
ref = refs[extension]
82+
else:
83+
ref = refs[basename]
84+
85+
# remove build tags from the top of Go files
86+
if extension == "go":
87+
p = regexs["go_build_constraints"]
88+
(data, found) = p.subn("", data, 1)
89+
90+
# remove shebang from the top of shell files
91+
if extension == "sh" or extension == "py":
92+
p = regexs["shebang"]
93+
(data, found) = p.subn("", data, 1)
94+
95+
data = data.splitlines()
96+
97+
# if our test file is smaller than the reference it surely fails!
98+
if len(ref) > len(data):
99+
print('File %s smaller than reference (%d < %d)' %
100+
(filename, len(data), len(ref)),
101+
file=verbose_out)
102+
return False
103+
104+
# trim our file to the same number of lines as the reference file
105+
data = data[:len(ref)]
106+
107+
p = regexs["year"]
108+
for d in data:
109+
if p.search(d):
110+
print('File %s is missing the year' % filename, file=verbose_out)
111+
return False
112+
113+
# Replace all occurrences of the regex "CURRENT_YEAR|...|2016|2015|2014" with "YEAR"
114+
p = regexs["date"]
115+
for i, d in enumerate(data):
116+
(data[i], found) = p.subn('YEAR', d)
117+
if found != 0:
118+
break
119+
120+
# if we don't match the reference at this point, fail
121+
if ref != data:
122+
print("Header in %s does not match reference, diff:" % filename, file=verbose_out)
123+
if args.verbose:
124+
print(file=verbose_out)
125+
for line in difflib.unified_diff(ref, data, 'reference', filename, lineterm=''):
126+
print(line, file=verbose_out)
127+
print(file=verbose_out)
128+
return False
129+
130+
return True
131+
132+
def file_extension(filename):
133+
return os.path.splitext(filename)[1].split(".")[-1].lower()
134+
135+
skipped_dirs = ['Godeps', 'third_party', '_gopath', '_output', '.git',
136+
'cluster/env.sh', 'vendor', 'test/e2e/generated/bindata.go',
137+
'repo-infra/verify/boilerplate/test', '.glide']
138+
139+
def normalize_files(files):
140+
newfiles = []
141+
for pathname in files:
142+
if any(x in pathname for x in skipped_dirs):
143+
continue
144+
newfiles.append(pathname)
145+
return newfiles
146+
147+
def get_files(extensions):
148+
files = []
149+
if len(args.filenames) > 0:
150+
files = args.filenames
151+
else:
152+
for root, dirs, walkfiles in os.walk(args.rootdir):
153+
# don't visit certain dirs. This is just a performance improvement
154+
# as we would prune these later in normalize_files(). But doing it
155+
# cuts down the amount of filesystem walking we do and cuts down
156+
# the size of the file list
157+
for d in skipped_dirs:
158+
if d in dirs:
159+
dirs.remove(d)
160+
161+
for name in walkfiles:
162+
pathname = os.path.join(root, name)
163+
files.append(pathname)
164+
165+
files = normalize_files(files)
166+
167+
outfiles = []
168+
for pathname in files:
169+
basename = os.path.basename(pathname)
170+
extension = file_extension(pathname)
171+
if extension in extensions or basename in extensions:
172+
outfiles.append(pathname)
173+
return outfiles
174+
175+
def get_regexs():
176+
regexs = {}
177+
# Search for "YEAR" which exists in the boilerplate, but shouldn't in the real thing
178+
regexs["year"] = re.compile( 'YEAR' )
179+
# dates can be 2014, 2015, 2016, ..., CURRENT_YEAR, company holder names can be anything
180+
years = range(2014, date.today().year + 1)
181+
regexs["date"] = re.compile( '(%s)' % "|".join(map(lambda l: str(l), years)) )
182+
# strip // +build \n\n build constraints
183+
regexs["go_build_constraints"] = re.compile(r"^(// \+build.*\n)+\n", re.MULTILINE)
184+
# strip #!.* from shell scripts
185+
regexs["shebang"] = re.compile(r"^(#!.*\n)\n*", re.MULTILINE)
186+
return regexs
187+
188+
189+
190+
def main():
191+
regexs = get_regexs()
192+
refs = get_refs()
193+
filenames = get_files(refs.keys())
194+
195+
for filename in filenames:
196+
if not file_passes(filename, refs, regexs):
197+
print(filename, file=sys.stdout)
198+
199+
return 0
200+
201+
if __name__ == "__main__":
202+
sys.exit(main())

Diff for: boilerplate/boilerplate.py.txt

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright YEAR The Kubernetes Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.

Diff for: boilerplate/boilerplate.sh.txt

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright YEAR The Kubernetes Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.

Diff for: build.make

+15
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,18 @@ test-shellcheck:
275275
.PHONY: check-go-version-%
276276
check-go-version-%:
277277
./release-tools/verify-go-version.sh "$*"
278+
279+
# Test for spelling errors.
280+
.PHONY: test-spelling
281+
test: test-spelling
282+
test-spelling:
283+
@ echo; echo "### $@:"
284+
@ ./release-tools/verify-spelling.sh
285+
286+
# Test the boilerplates of the files.
287+
.PHONY: test-boilerplate
288+
test: test-boilerplate
289+
test-boilerplate:
290+
@ echo; echo "### $@:"
291+
@ ./release-tools/verify-boilerplate.sh
292+

Diff for: verify-boilerplate.sh

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/bin/bash
2+
3+
# Copyright 2014 The Kubernetes Authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
set -o errexit
18+
set -o nounset
19+
set -o pipefail
20+
21+
echo "Verifying boilerplate"
22+
23+
if [[ -z "$(command -v python)" ]]; then
24+
echo "Cannot find python. Make link to python3..."
25+
update-alternatives --install /usr/bin/python python /usr/bin/python3 1
26+
fi
27+
28+
REPO_ROOT=$(dirname "${BASH_SOURCE[0]}")
29+
30+
boilerDir="${REPO_ROOT}/boilerplate"
31+
boiler="${boilerDir}/boilerplate.py"
32+
33+
files_need_boilerplate=("$("${boiler}" --rootdir="${REPO_ROOT}" --verbose)")
34+
35+
# Run boilerplate.py unit tests
36+
unitTestOut="$(mktemp)"
37+
trap cleanup EXIT
38+
cleanup() {
39+
rm "${unitTestOut}"
40+
}
41+
42+
# Run boilerplate check
43+
if [[ ${#files_need_boilerplate[@]} -gt 0 ]]; then
44+
for file in "${files_need_boilerplate[@]}"; do
45+
echo "Boilerplate header is wrong for: ${file}"
46+
done
47+
48+
exit 1
49+
fi
50+
51+
echo "Done"

0 commit comments

Comments
 (0)