diff --git a/.gitignore b/.gitignore index a23bb285..dc3e5a85 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ _testmain.go # Project specific weavedns/weavedns +releases diff --git a/Makefile b/Makefile index 982b6e8c..5482f582 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ # If you can use docker without being root, you can do "make SUDO=" SUDO=sudo +WEAVE_VERSION=git-$(shell git rev-parse --short=12 HEAD) WEAVER_EXE=weaver/weaver WEAVEDNS_EXE=weavedns/weavedns WEAVER_IMAGE=zettio/weave @@ -15,7 +16,7 @@ all: $(WEAVER_EXPORT) $(WEAVEDNS_EXPORT) $(WEAVER_EXE) $(WEAVEDNS_EXE): go get -tags netgo ./$(shell dirname $@) - go build -ldflags '-extldflags "-static"' -tags netgo -o $@ ./$(shell dirname $@) + go build -ldflags '-extldflags "-static"' -ldflags "-X main.version $(WEAVE_VERSION)" -tags netgo -o $@ ./$(shell dirname $@) @strings $@ | grep cgo_stub\\\.go >/dev/null || { \ rm $@; \ echo "\nYour go standard library was built without the 'netgo' build tag."; \ @@ -40,14 +41,6 @@ $(WEAVEDNS_EXPORT): weavedns/Dockerfile $(WEAVEDNS_EXE) tests: cd nameserver; go test -tags netgo -publish: $(WEAVER_EXPORT) tests - $(SUDO) docker tag $(WEAVER_IMAGE) $(WEAVER_IMAGE):git-`git rev-parse --short=12 HEAD` - $(SUDO) docker push $(WEAVER_IMAGE):latest - $(SUDO) docker push $(WEAVER_IMAGE):git-`git rev-parse --short=12 HEAD` - $(SUDO) docker tag $(WEAVEDNS_IMAGE) $(WEAVEDNS_IMAGE):git-`git rev-parse --short=12 HEAD` - $(SUDO) docker push $(WEAVEDNS_IMAGE):latest - $(SUDO) docker push $(WEAVEDNS_IMAGE):git-`git rev-parse --short=12 HEAD` - clean: -$(SUDO) docker rmi $(WEAVER_IMAGE) $(WEAVEDNS_IMAGE) rm -f $(WEAVER_EXE) $(WEAVEDNS_EXE) $(WEAVER_EXPORT) $(WEAVEDNS_EXPORT) diff --git a/bin/release b/bin/release new file mode 100755 index 00000000..9d5026da --- /dev/null +++ b/bin/release @@ -0,0 +1,198 @@ +#! /bin/bash + +set -e + +PWD=`pwd` +GITHUB_USER=zettio +DOCKERHUB_USER=zettio +RELEASE_NAME="Weave" +RELEASE_DESCRIPTION="Weaving Containers into Applications" + +setup() { + ## Get the new version number from the most recent tag + if ! LATEST_TAG=$(git describe --abbrev=0 --match='v*' 2>/dev/null) ; then + echo "Could not find an annotated 'v*' version tag." >&2 + exit 1 + fi + LATEST_TAG_SHA=$(git rev-parse $LATEST_TAG) + LATEST_RELEASE_SHA=$(git rev-parse latest_release) + VERSION=${LATEST_TAG#v} + # NB does not check that this tag is on master + RELEASE_DIR=./releases/$LATEST_TAG +} + +build() { + setup + + echo "== Clone repo at $LATEST_TAG for version $VERSION" + if [ -d $RELEASE_DIR ]; then + echo -e "\u2757 Release directory $RELEASE_DIR already exists, you may want to" >&2 + echo -e "\trm -rf $RELEASE_DIR" >&2 + exit 1 + fi + + ## Clone the repo at the tag and go there + mkdir -p releases + git clone -q -b $LATEST_TAG . $RELEASE_DIR 2>/dev/null + cd $RELEASE_DIR + + ## Check that the top changelog entry is this version + if ! latest_changelog=$(grep -o "== Release [0-9].*" -m1 ./CHANGELOG.md) || \ + ! [ `echo "$latest_changelog" | grep -o '[0-9][^ ]*'` == "$VERSION" ]; then + echo -e "\u2757 Latest changelog entry \"$latest_changelog\" does not match the release version $VERSION" >&2 + exit 1 + fi + + echo + echo "== Build and test" + + ## Inject the version numbers and build the distributables + ## (library versions?) + sed -i "/SCRIPT_VERSION=/ c\SCRIPT_VERSION=\"$VERSION\"" ./weave + make \ + WEAVE_VERSION=$VERSION \ + WEAVER_IMAGE=$DOCKERHUB_USER/weave \ + WEAVEDNS_IMAGE=$DOCKERHUB_USER/weavedns + + if make tests; then + echo -e '\u2713 Tests pass' + else + echo -e "\u2757 Tests failed, probably best not publish this one" >&2 + exit 1 + fi + + ## Run tests with the distributables, including version check + v=$(./weaver/weaver --version | grep -o '[0-9].*') + if ! [ "$v" == "$VERSION" ]; then + echo "Version of distributable "$v" does not match release version $VERSION" >&2 + exit 1 + fi + + echo -e '\u2713 Build OK' + echo '** Release artefacts in' $RELEASE_DIR +} + +publish() { + setup + cd $PWD/$RELEASE_DIR + + echo "== Sanity checks" + + if ! which github-release >/dev/null; then + echo "Please install git-release:" >&2 + echo -e "\tgo get github.com/aktau/github-release" >&2 + echo "and create a git token per https://github.com/aktau/github-release" >&2 + exit 1 + fi + + if ! [ $(git rev-list -1 $LATEST_TAG) == $(git rev-list -1 latest_release) ]; then + echo -e "\u2757 The tag latest_release does not point to the same commit as $LATEST_TAG" + exit 1 + fi + + ## Check that the tag exists by looking at github + if ! curl -sSf https://api.github.com/repos/$GITHUB_USER/weave/git/tags/$LATEST_TAG_SHA >/dev/null 2>&1; then + echo -e "\u2757 Tag $LATEST_TAG is not on GitHub, or is not the same as the local tag" >&2 + echo -e "\thttps://github.com/$GITHUB_USER/weave/tags" >&2 + echo "You may need to" >&2 + echo -e "\tgit push git@github.com:$GITHUB_USER/weave $LATEST_TAG" + exit 1 + fi + + ## Check that the 'latest_release' tag exists by looking at github + if ! curl -sSf https://api.github.com/repos/$GITHUB_USER/weave/git/tags/$LATEST_RELEASE_SHA >/dev/null 2>&1; then + echo -e "\u2757 Tag latest_release is not on GitHub, or is not the same as the local tag" >&2 + echo -e "\thttps://github.com/$GITHUB_USER/weave/tags" >&2 + echo "You may need to" >&2 + echo -e "\tgit tag -af latest_release" + echo -e "\tgit push -f git@github.com:$GITHUB_USER/weave latest_release" + exit 1 + fi + + echo -e "\u2713 Tag $LATEST_TAG exists in GitHub repo $GITHUB_USER/weave" + + ## Check that the version doesn't already exist by looking at github + ## releases + if github-release info --user $GITHUB_USER --repo weave --tag $LATEST_TAG >/dev/null 2>&1; then + echo -e "\u2757 Release $LATEST_TAG already exists on GitHub" >&2 + echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/$LATEST_TAG" >&2 + exit 1 + fi + + echo '** Sanity checks OK for publishing tag' $LATEST_TAG as $DOCKERHUB_USER/weave:$VERSION + + echo == Tagging $DOCKERHUB_USER/weave and $DOCKERHUB_USER/weavedns as $VERSION + docker tag $DOCKERHUB_USER/weave $DOCKERHUB_USER/weave:$VERSION + docker tag $DOCKERHUB_USER/weavedns $DOCKERHUB_USER/weavedns:$VERSION + + docker push $DOCKERHUB_USER/weave:$VERSION + echo "** Pushed $DOCKERHUB_USER/weave:$VERSION to docker hub" + docker push $DOCKERHUB_USER/weavedns:$VERSION + echo "** Pushed $DOCKERHUB_USER/weavedns:$VERSION to docker hub" + + echo "== Creating GitHub release $RELEASE_NAME $VERSION" + # This cannot be done as a draft because of a bug in + # github-release: https://github.com/aktau/github-release/issues/7 + github-release release \ + --user $GITHUB_USER \ + --repo weave \ + --tag $LATEST_TAG \ + --name "$RELEASE_NAME $VERSION" \ + --description "$RELEASE_DESCRIPTION" + + github-release upload \ + --user $GITHUB_USER \ + --repo weave \ + --tag $LATEST_TAG \ + --name "weave" \ + --file "./weave" + + echo "** Published release $RELEASE_NAME $VERSION" + echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/$LATEST_TAG" + + if github-release info --user $GITHUB_USER --repo weave \ + --tag latest_release >/dev/null 2>&1; then + github-release delete \ + --user $GITHUB_USER \ + --repo weave \ + --tag latest_release + fi + + github-release release \ + --user $GITHUB_USER \ + --repo weave \ + --tag latest_release \ + --name "$RELEASE_NAME latest ($VERSION)" \ + --description "$RELEASE_DESCRIPTION" + + github-release upload \ + --user $GITHUB_USER \ + --repo weave \ + --tag latest_release \ + --name "weave" \ + --file "./weave" + + echo "** Published $RELEASE_NAME as latest_release at" + echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/latest_release" +} + +usage() { + echo "Usage:" + echo -e "\t./bin/release build" + echo "-- Build artefacts for the latest version tag" + echo -e "\t./bin/release publish" + echo "-- Publish the artefacts for the latest tag to GitHub and DockerHub" +} + +case "$1" in + build) + build + ;; + publish) + publish + ;; + *) + echo "Unknown command \"$1\"" + usage + ;; +esac diff --git a/site/troubleshooting.md b/site/troubleshooting.md index c1ec0f61..af455f70 100644 --- a/site/troubleshooting.md +++ b/site/troubleshooting.md @@ -56,6 +56,7 @@ reports on the current status of the weave router. This produces output like: ```` +weave router 0.7.0 Our name is 7a:f4:56:87:76:3b Sniffing traffic on &{39 65535 ethwe ae:e3:07:9c:8c:d4 up|broadcast|multicast} MACs: diff --git a/weave b/weave index 663e6cb8..88fc10bd 100755 --- a/weave +++ b/weave @@ -1,6 +1,8 @@ #!/bin/sh set -e +SCRIPT_VERSION="(unreleased version)" + usage() { echo "Usage:" echo "weave launch [-password | -passwordfile ] ..." @@ -390,6 +392,15 @@ uname -s -r | sed -n 's|^\([^ ]*\) \([0-9]\+\)\.\([0-9]\+\).*|\1 \2 \3|p' | { fi } +ask_version() { + if ! DOCKERIMAGE=$(docker inspect --format='{{ .Image }}' $1 2>/dev/null) ; then + if ! DOCKERIMAGE=$(docker inspect --format='{{ .Id }}' $2 2>/dev/null) ; then + echo "Unable to find $2 image." >&2 + fi + fi + [ -n "$DOCKERIMAGE" ] && docker run --rm $DOCKERIMAGE --version +} + if ! command_exists ip ; then echo "ERROR: ip utility is missing. Please install it." >&2 exit 1 @@ -484,14 +495,9 @@ case "$COMMAND" in ;; version) [ $# -eq 0 ] || usage - # Try the running container first; if no luck try the image - if ! DOCKERIMAGE=$(docker inspect --format='{{ .Image }}' $CONTAINER_NAME 2>/dev/null) ; then - if ! DOCKERIMAGE=$(docker inspect --format='{{ .Id }}' $IMAGE 2>/dev/null) ; then - echo "Unable to find $IMAGE image." >&2 - exit 1 - fi - fi - docker images --no-trunc | grep $DOCKERIMAGE | grep -v latest | tr -s ' ' | cut -d ' ' -f 2 + echo weave script $SCRIPT_VERSION + ask_version $CONTAINER_NAME $IMAGE + ask_version $DNS_CONTAINER_NAME $DNS_IMAGE ;; run) [ $# -gt 0 ] || usage diff --git a/weavedns/main.go b/weavedns/main.go index b06e7f1b..ab5ecbd4 100644 --- a/weavedns/main.go +++ b/weavedns/main.go @@ -2,24 +2,30 @@ package main import ( "flag" + "fmt" weavedns "github.com/zettio/weave/nameserver" weavenet "github.com/zettio/weave/net" + "io" "io/ioutil" "net" "os" ) +var version = "(unreleased version)" + func main() { var ( - ifaceName string - apiPath string - dnsPort int - httpPort int - wait int - watch bool - debug bool + justVersion bool + ifaceName string + apiPath string + dnsPort int + httpPort int + wait int + watch bool + debug bool ) + flag.BoolVar(&justVersion, "version", false, "print version and exit") flag.StringVar(&ifaceName, "iface", "", "name of interface to use for multicast") flag.StringVar(&apiPath, "api", "unix:///var/run/docker.sock", "Path to Docker API socket") flag.IntVar(&wait, "wait", 0, "number of seconds to wait for interface to be created and come up") @@ -29,6 +35,11 @@ func main() { flag.BoolVar(&debug, "debug", false, "output debugging info to stderr") flag.Parse() + if justVersion { + io.WriteString(os.Stdout, fmt.Sprintf("weave DNS %s\n", version)) + os.Exit(0) + } + debugOut := ioutil.Discard if debug { debugOut = os.Stderr diff --git a/weaver/main.go b/weaver/main.go index 177f14ba..ac24973d 100644 --- a/weaver/main.go +++ b/weaver/main.go @@ -18,6 +18,8 @@ import ( "syscall" ) +var version = "(unreleased version)" + func main() { log.SetPrefix(weave.Protocol + " ") @@ -32,17 +34,19 @@ func main() { runtime.GOMAXPROCS(procs) var ( - ifaceName string - routerName string - password string - wait int - debug bool - prof string - peers []string - connLimit int - bufSz int + justVersion bool + ifaceName string + routerName string + password string + wait int + debug bool + prof string + peers []string + connLimit int + bufSz int ) + flag.BoolVar(&justVersion, "version", false, "print version and exit") flag.StringVar(&ifaceName, "iface", "", "name of interface to read from") flag.StringVar(&routerName, "name", "", "name of router (defaults to MAC)") flag.StringVar(&password, "password", "", "network password") @@ -54,6 +58,11 @@ func main() { flag.Parse() peers = flag.Args() + if justVersion { + io.WriteString(os.Stdout, fmt.Sprintf("weave router %s\n", version)) + os.Exit(0) + } + options := make(map[string]string) flag.Visit(func(f *flag.Flag) { value := f.Value.String() @@ -127,6 +136,7 @@ func main() { func handleHttp(router *weave.Router) { http.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) { + io.WriteString(w, fmt.Sprintln("weave router", version)) io.WriteString(w, router.Status()) }) http.HandleFunc("/connect", func(w http.ResponseWriter, r *http.Request) {