Import first rev of project template

master
Tim Hockin 2016-09-20 21:15:39 -07:00
parent 869a91ef59
commit 43e119bda6
8 changed files with 335 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/bin
/.go
/.push-*
/.container-*

24
Dockerfile Normal file
View File

@ -0,0 +1,24 @@
# Copyright 2016 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.
FROM alpine:3.4
MAINTAINER Tim Hockin <thockin@google.com>
ARG ARCH
ADD bin/${ARCH}/myapp /myapp
USER nobody:nobody
ENTRYPOINT ["/myapp"]

139
Makefile Normal file
View File

@ -0,0 +1,139 @@
# Copyright 2016 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.
# The binary to build (just the basename).
BIN := myapp
# This repo's root import path (under GOPATH).
PKG := github.com/thockin/go-build-template
# Where to push the docker image.
REGISTRY ?= thockin
# Which architecture to build - see $(ALL_ARCH) for options.
ARCH ?= amd64
###
### These variables should not need tweaking.
###
SRC_DIRS := cmd pkg # directories which hold app source (not vendored)
ALL_ARCH := amd64 arm arm64 ppc64le # TODO: base image for non-x86 archs?
IMAGE := $(REGISTRY)/$(BIN)-$(ARCH)
BUILD_IMAGE ?= golang:1.7-alpine
VERSION :=
TAG := $(shell git describe --abbrev=0 --tags HEAD 2>/dev/null)
COMMIT := $(shell git rev-parse HEAD)
ifeq ($(TAG),)
VERSION := unknown-$(COMMIT)
else
ifeq ($(COMMIT), $(shell git rev-list -n1 $(TAG)))
VERSION := $(TAG)
else
VERSION := $(TAG)-$(COMMIT)
endif
endif
DIRTY := $(shell test -z "$$(git diff --shortstat 2>/dev/null)" || echo -dirty)
VERSION := $(VERSION)$(DIRTY)
# If you want to build all binaries, see the 'all-build' rule.
# If you want to build all containers, see the 'all-container' rule.
# If you want to build AND push all containers, see the 'all-push' rule.
all: build
build-%:
@$(MAKE) --no-print-directory ARCH=$* build
container-%:
@$(MAKE) --no-print-directory ARCH=$* container
push-%:
@$(MAKE) --no-print-directory ARCH=$* push
all-build: $(addprefix build-, $(ALL_ARCH))
all-container: $(addprefix container-, $(ALL_ARCH))
all-push: $(addprefix push-, $(ALL_ARCH))
build: bin/$(ARCH)/$(BIN)
bin/$(ARCH)/$(BIN): build-dirs
@echo "building: $@"
@docker run \
-ti \
-u $$(id -u):$$(id -g) \
-v $$(pwd)/.go:/go \
-v $$(pwd):/go/src/$(PKG) \
-v $$(pwd)/bin/$(ARCH):/go/bin \
-v $$(pwd)/.go/std/$(ARCH):/usr/local/go/pkg/linux_$(ARCH)_static \
-w /go/src/$(PKG) \
$(BUILD_IMAGE) \
/bin/sh -c " \
ARCH=$(ARCH) \
VERSION=$(VERSION) \
PKG=$(PKG) \
./build/build.sh \
"
DOTFILE_IMAGE = $(subst /,_,$(IMAGE))-$(VERSION)
container: .container-$(DOTFILE_IMAGE) container-name
.container-$(DOTFILE_IMAGE): bin/$(ARCH)/$(BIN) Dockerfile
@docker build -t $(IMAGE):$(VERSION) --build-arg ARCH=$(ARCH) .
@docker images -q $(IMAGE):$(VERSION) > $@
container-name:
@echo "container: $(IMAGE):$(VERSION)"
push: .push-$(DOTFILE_IMAGE) push-name
.push-$(DOTFILE_IMAGE): .container-$(DOTFILE_IMAGE)
@gcloud docker push $(IMAGE):$(VERSION)
@docker images -q $(IMAGE):$(VERSION) > $@
push-name:
@echo "pushed: $(IMAGE):$(VERSION)"
version:
@echo $(VERSION)
test: build-dirs
@docker run \
-ti \
-u $$(id -u):$$(id -g) \
-v $$(pwd)/.go:/go \
-v $$(pwd):/go/src/$(PKG) \
-v $$(pwd)/bin/$(ARCH):/go/bin \
-v $$(pwd)/.go/std/$(ARCH):/usr/local/go/pkg/linux_$(ARCH)_static \
-w /go/src/$(PKG) \
$(BUILD_IMAGE) \
/bin/sh -c " \
./build/test.sh $(SRC_DIRS) \
"
build-dirs:
@mkdir -p bin/$(ARCH)
@mkdir -p .go/src/$(PKG) .go/pkg .go/bin .go/std/$(ARCH)
clean: container-clean bin-clean
container-clean:
rm -rf .container-* .push-*
bin-clean:
rm -rf .go bin

34
README.md Normal file
View File

@ -0,0 +1,34 @@
# Go app template build environment
This is a skeleton project for a Go application, which captures the best build
techniques I have learned to date. It uses a Makefile to drive the build (the
universal API to software projects) and a Dockerfile to build a docker image.
This has only been tested on Linux, and depends on Docker to build.
## Customizing it
To use this, simply copy these files and make the following changes:
Makefile:
- change `BIN` to your binary name
- change `PKG` to the Go import path of this repo
- change `REGISTRY` to the Docker registry you want to use
- maybe change `SRC_DIRS` if youuse some other layout
Dockerfile:
- change all `myapp` to your binary name
## Building
Run `make` or `make build` to compile your app. This will use a Docker image
to build your app, with the current directory volume-mounted into place. This
will store incremental state for the fastest possible build.
Run `make container` to build the container image. It will calculate the image
tag based on the most recent git tag, and whether the repo is "dirty" since
that tag (see `make version`).
Run `make push` to push the container image to `REGISTRY`.
Run `make clean` to clean up.

40
build/build.sh Executable file
View File

@ -0,0 +1,40 @@
#!/bin/sh
#
# Copyright 2016 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
if [ -z "${PKG}" ]; then
echo "PKG must be set"
exit 1
fi
if [ -z "${ARCH}" ]; then
echo "ARCH must be set"
exit 1
fi
if [ -z "${VERSION}" ]; then
echo "VERSION must be set"
exit 1
fi
export CGO_ENABLED=0
export GOARCH="${ARCH}"
go install \
-installsuffix "static" \
-ldflags "-X ${PKG}/pkg/version.VERSION=${VERSION}" \
./...

52
build/test.sh Executable file
View File

@ -0,0 +1,52 @@
#!/bin/sh
#
# Copyright 2016 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
export CGO_ENABLED=0
TARGETS=$(for d in "$@"; do echo ./$d/...; done)
echo "Running tests:"
go test -i -installsuffix "static" ${TARGETS}
go test -installsuffix "static" ${TARGETS}
echo
echo -n "Checking gofmt: "
ERRS=$(find "$@" -type f -name \*.go | xargs gofmt -l 2>&1 || true)
if [ -n "${ERRS}" ]; then
echo "FAIL - the following files need to be gofmt'ed:"
for e in ${ERRS}; do
echo " $e"
done
echo
exit 1
fi
echo "PASS"
echo
echo -n "Checking go vet: "
ERRS=$(go vet ${TARGETS} 2>&1 || true)
if [ -n "${ERRS}" ]; then
echo "FAIL"
echo "${ERRS}"
echo
exit 1
fi
echo "PASS"
echo

23
cmd/myapp/main.go Normal file
View File

@ -0,0 +1,23 @@
/*
Copyright 2016 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.
*/
package main
import "log"
func main() {
log.Printf("hello, world!")
}

19
pkg/version/version.go Normal file
View File

@ -0,0 +1,19 @@
/*
Copyright 2016 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.
*/
package version
var VERSION = "UNKNOWN"