Skip to content
This repository has been archived by the owner on Jan 29, 2025. It is now read-only.

Commit

Permalink
Update repo-infra
Browse files Browse the repository at this point in the history
  • Loading branch information
wongma7 committed Jun 1, 2017
1 parent 3ad19c9 commit 1ae0fa4
Show file tree
Hide file tree
Showing 10 changed files with 389 additions and 11 deletions.
5 changes: 5 additions & 0 deletions repo-infra/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

/bazel-*
19 changes: 19 additions & 0 deletions repo-infra/.travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
language: go

go:
- master

before_install:
- go get -u github.com/alecthomas/gometalinter

install:
- gometalinter --install
- go get -u github.com/bazelbuild/buildifier/buildifier

build:
- true

script:
- verify/verify-boilerplate.sh --rootdir="${TRAVIS_BUILD_DIR}" -v
- verify/verify-go-src.sh --rootdir "${TRAVIS_BUILD_DIR}" -v
- buildifier -mode=check $(find . -name BUILD -o -name '*.bzl' -type f)
2 changes: 1 addition & 1 deletion repo-infra/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This repository contains repository infrastructure tools for use in
`kubernetes` and `kubernetes-incubator` repositories. Examples:

- Boilerplate verification
- Gofmt verification
- Go source code quality verification
- Golang build infrastructure

---
Expand Down
86 changes: 81 additions & 5 deletions repo-infra/defs/build.bzl
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
def _gcs_upload_impl(ctx):
targets = []
for target in ctx.files.data:
targets.append(target.short_path)
output_lines = []
for t in ctx.attr.data:
label = str(t.label)
upload_path=ctx.attr.upload_paths.get(label, "")
for f in t.files:
output_lines.append("%s\t%s" % (f.short_path, upload_path))

ctx.file_action(
output = ctx.outputs.targets,
content = "\n".join(targets),
content = "\n".join(output_lines),
)

ctx.file_action(
Expand All @@ -20,10 +23,18 @@ def _gcs_upload_impl(ctx):
return struct(
runfiles = ctx.runfiles(
files = ctx.files.data + ctx.files.uploader +
[ctx.version_file, ctx.outputs.targets]
[ctx.info_file, ctx.version_file, ctx.outputs.targets]
)
)

# Adds an executable rule to upload the specified artifacts to GCS.
#
# The keys in upload_paths must match the elaborated targets exactly; i.e.,
# one must specify "//foo/bar:bar" and not just "//foo/bar".
#
# Both the upload_paths and the path supplied on the commandline can include
# Python format strings which will be replaced by values from the workspace status,
# e.g. gs://my-bucket-{BUILD_USER}/stash/{STABLE_BUILD_SCM_REVISION}
gcs_upload = rule(
attrs = {
"data": attr.label_list(
Expand All @@ -34,10 +45,75 @@ gcs_upload = rule(
default = Label("//defs:gcs_uploader"),
allow_files = True,
),
# TODO: combine with 'data' when label_keyed_string_dict is supported in Bazel
"upload_paths": attr.string_dict(
allow_empty = True,
),
},
executable = True,
outputs = {
"targets": "%{name}-targets.txt",
},
implementation = _gcs_upload_impl,
)

# Computes the md5sum of the provided src file, saving it in a file named 'name'.
def md5sum(name, src, visibility=None):
native.genrule(
name = name + "_genmd5sum",
srcs = [src],
outs = [name],
# Currently each go_binary target has two outputs (the binary and the library),
# so we hash both but only save the hash for the binary.
cmd = "for f in $(SRCS); do if command -v md5 >/dev/null; then md5 -q $$f>$@; else md5sum $$f | awk '{print $$1}' > $@; fi; done",
message = "Computing md5sum",
visibility = visibility,
)

# Computes the sha1sum of the provided src file, saving it in a file named 'name'.
def sha1sum(name, src, visibility=None):
native.genrule(
name = name + "_gensha1sum",
srcs = [src],
outs = [name],
# Currently each go_binary target has two outputs (the binary and the library),
# so we hash both but only save the hash for the binary.
cmd = "command -v sha1sum >/dev/null && cmd=sha1sum || cmd='shasum -a1'; for f in $(SRCS); do $$cmd $$f | awk '{print $$1}' > $@; done",
message = "Computing sha1sum",
visibility = visibility,
)

# Creates 3+N rules based on the provided targets:
# * A filegroup with just the provided targets (named 'name')
# * A filegroup containing all of the md5 and sha1 hash files ('name-hashes')
# * A filegroup containing both of the above ('name-and-hashes')
# * All of the necessary md5sum and sha1sum rules
def release_filegroup(name, srcs, visibility=None):
hashes = []
for src in srcs:
parts = src.split(":")
if len(parts) > 1:
basename = parts[1]
else:
basename = src.split("/")[-1]

md5sum(name=basename + ".md5", src=src, visibility=visibility)
hashes.append(basename + ".md5")
sha1sum(name=basename + ".sha1", src=src, visibility=visibility)
hashes.append(basename + ".sha1")

native.filegroup(
name = name,
srcs = srcs,
visibility = visibility,
)
native.filegroup(
name = name + "-hashes",
srcs = hashes,
visibility = visibility,
)
native.filegroup(
name = name + "-and-hashes",
srcs = [name, name + "-hashes"],
visibility = visibility,
)
40 changes: 35 additions & 5 deletions repo-infra/defs/gcs_uploader.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,59 @@
import sys
import tempfile

def _workspace_status_dict(root):
d = {}
for f in ("stable-status.txt", "volatile-status.txt"):
with open(os.path.join(root, f)) as info_file:
for info_line in info_file:
info_line = info_line.strip("\n")
key, value = info_line.split(" ")
d[key] = value
return d

def main(argv):
scratch = tempfile.mkdtemp(prefix="bazel-gcs.")
atexit.register(lambda: shutil.rmtree(scratch))

workspace_status = _workspace_status_dict(argv.root)
with open(argv.manifest) as manifest:
for artifact in manifest:
artifact = artifact.strip()
artifact = artifact.strip("\n")
src_file, dest_dir = artifact.split("\t")
dest_dir = dest_dir.format(**workspace_status)
scratch_dest_dir = os.path.join(scratch, dest_dir)
try:
os.makedirs(os.path.join(scratch, os.path.dirname(artifact)))
os.makedirs(scratch_dest_dir)
except (OSError):
# skip directory already exists errors
pass
os.symlink(os.path.join(argv.root, artifact), os.path.join(scratch, artifact))

sys.exit(subprocess.call(["gsutil", "-m", "rsync", "-C", "-r", scratch, argv.gcs_path]))
src = os.path.join(argv.root, src_file)
dest = os.path.join(scratch_dest_dir, os.path.basename(src_file))
os.symlink(src, dest)

ret = 0
uploaded_paths = []
for gcs_path in argv.gcs_paths:
gcs_path = gcs_path.format(**workspace_status)
local_path = None
if gcs_path.startswith("file://"):
local_path = gcs_path[len("file://"):]
elif "://" not in gcs_path:
local_path = gcs_path
if local_path and not os.path.exists(local_path):
os.makedirs(local_path)
ret |= subprocess.call(["gsutil", "-m", "rsync", "-C", "-r", scratch, gcs_path])
uploaded_paths.append(gcs_path)
print "Uploaded to %s" % " ".join(uploaded_paths)
sys.exit(ret)


if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Upload build targets to GCS.')

parser.add_argument("--manifest", required=True, help="path to manifest of targets")
parser.add_argument("--root", required=True, help="path to root of workspace")
parser.add_argument("gcs_path", help="path in gcs to push targets")
parser.add_argument("gcs_paths", nargs="+", help="path in gcs to push targets")

main(parser.parse_args())
52 changes: 52 additions & 0 deletions repo-infra/verify/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Verification scripts

Collection of scripts that verifies that a project meets requirements set for kubernetes related projects. The scripts are to be invoked depending on the needs via CI tooling, such as Travis CI. See main Readme file on how to integrate the repo-infra in your project.

The scripts are currently being migrated from the main kubernetes repository. If your project requires additional set of verifications, consider creating an issue/PR on repo-infra to avoid code duplication across multiple projects.

If repo-infra is integrated at the root of your project as git submodule at path: `/repo-infra`,
then scripts can be invoked as `repo-infra/verify/verify-*.sh`

travis.yaml example:

```
dist: trusty
os:
- linux
language: go
go:
- 1.8
before_install:
- go get -u github.com/alecthomas/gometalinter
install:
- gometalinter --install
script:
- repo-infra/verify/verify-go-src.sh -v
- repo-infra/verify/verify-boilerplate.sh
# OR with vendoring
# - vendor/github.com/kubernetes/repo-infra/verify-go-src.sh --rootdir=$(pwd) -v
```

## Verify boilerplate

Verifies that the boilerplate for various formats (go files, Makefile, etc.) is included in each file: `verify-boilerplate.sh`.

## Verify go source code

Runs a set of scripts on the go source code excluding vendored files: `verify-go-src.sh`. Expects `gometalinter` tooling installed (see travis file above)

With git submodule from your repo root: `repo-infra/verify/verify-go-src.sh -v`

With vendoring: `vendor/repo-infra/verify/verify-go-src.sh -v --rootdir $(pwd)`

Checks include:

1. gofmt
2. gometalinter
3. govet
34 changes: 34 additions & 0 deletions repo-infra/verify/go-tools/verify-gofmt.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/bash
# Copyright 2017 The Kubernetes Authors.
#
# 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.

set -o errexit
set -o nounset
set -o pipefail

find_files() {
find . -not \( \
\( \
-wholename '*/vendor/*' \
\) -prune \
\) -name '*.go'
}

GOFMT="gofmt -s"
bad_files=$(find_files | xargs $GOFMT -l)
if [[ -n "${bad_files}" ]]; then
echo "!!! '$GOFMT' needs to be run on the following files: "
echo "${bad_files}"
exit 1
fi
31 changes: 31 additions & 0 deletions repo-infra/verify/go-tools/verify-gometalinter.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash
# Copyright 2017 The Kubernetes Authors.
#
# 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.

set -o errexit
set -o nounset
set -o pipefail

for d in $(find . -type d -not -iwholename '*.git*' -a -not -iname '.tool' -a -not -iwholename '*vendor*'); do
gometalinter --deadline=50s --vendor \
--cyclo-over=50 --dupl-threshold=100 \
--exclude=".*should not use dot imports \(golint\)$" \
--disable-all \
--enable=vet \
--enable=deadcode \
--enable=golint \
--enable=vetshadow \
--enable=gocyclo \
--tests "${d}"
done
20 changes: 20 additions & 0 deletions repo-infra/verify/go-tools/verify-govet.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash
# Copyright 2017 The Kubernetes Authors.
#
# 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.

set -o errexit
set -o nounset
set -o pipefail

go vet -v $(go list ./... | grep -v /vendor/)
Loading

0 comments on commit 1ae0fa4

Please sign in to comment.