diff --git a/.circleci/config.yml b/.circleci/config.yml index ab807924..1cdd0115 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,43 +1,73 @@ version: 2 jobs: - build: + test: docker: - image: circleci/golang:1.10 working_directory: /go/src/github.com/segmentio/chamber steps: - checkout - run: - name: Build + name: Test command: | - make govendor dist + make test + + dist: + docker: + - image: circleci/golang:1.10 + working_directory: /go/src/github.com/segmentio/chamber + steps: + - checkout + - run: + name: Install nfpm, rpmbuild + command: | + sudo make -f Makefile.tools nfpm-debian rpmbuild-debian + - run: + name: Make distributables + command: | + make -f Makefile.release dist - persist_to_workspace: root: . paths: ['dist/*'] - release: + publish: docker: - image: circleci/golang:1.10 working_directory: /go/src/github.com/segmentio/chamber steps: - checkout - attach_workspace: { at: . } + - run: + name: Install tools + command: | + make -f Makefile.tools github-release + # this is all for package_cloud :/ + sudo apt update -q + sudo apt install -yq ruby ruby-dev build-essential + # fixes https://askubuntu.com/questions/872399/error-failed-to-build-gem-native-extension-when-trying-to-download-rubocop + sudo gem install rake + sudo make -f Makefile.tools package_cloud - run: name: Release command: | - make release + make -f Makefile.release publish workflows: version: 2 - build-release: + test-dist-publish: jobs: - - build - - release: + - test + - dist: + # needed to ensure dist happens on tag events + filters: + tags: + only: /.*/ + - publish: requires: - - build + - dist filters: - # release on branch push event + # never publish from a branch event branches: ignore: /.*/ - # release only on tag push events like vX[.Y.Z...] + # release only on tag push events like vX[.Y.Z...][-whatever] tags: - only: /v[0-9]+(\.[0-9]+)*/ + only: /v[0-9]+(\.[0-9]+)*(-[a-zA-Z0-9-]+)?/ diff --git a/.gitignore b/.gitignore index d44ae57f..d429a7e0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.sw[a-z] vendor/*/ dist/ +packagecloud.conf.json diff --git a/Makefile b/Makefile index f3e351bd..4886e999 100644 --- a/Makefile +++ b/Makefile @@ -1,56 +1,33 @@ +# Goals: +# - user can build binaries on their system without having to install special tools +# - user can fork the canonical repo and expect to be able to run CircleCI checks +# +# This makefile is meant for humans + VERSION := $(shell git describe --tags --always --dirty="-dev") LDFLAGS := -ldflags='-X "main.Version=$(VERSION)"' -release: gh-release clean dist +test: | govendor govendor sync - github-release release \ - --security-token $$GH_LOGIN \ - --user segmentio \ - --repo chamber \ - --tag $(VERSION) \ - --name $(VERSION) - - github-release upload \ - --security-token $$GH_LOGIN \ - --user segmentio \ - --repo chamber \ - --tag $(VERSION) \ - --name chamber-$(VERSION)-darwin-amd64 \ - --file dist/chamber-$(VERSION)-darwin-amd64 - - github-release upload \ - --security-token $$GH_LOGIN \ - --user segmentio \ - --repo chamber \ - --tag $(VERSION) \ - --name chamber-$(VERSION)-linux-amd64 \ - --file dist/chamber-$(VERSION)-linux-amd64 - - github-release upload \ - --security-token $$GH_LOGIN \ - --user segmentio \ - --repo chamber \ - --tag $(VERSION) \ - --name chamber-$(VERSION).sha256sums \ - --file dist/chamber-$(VERSION).sha256sums + go test -v ./... + +all: dist/chamber-$(VERSION)-darwin-amd64 dist/chamber-$(VERSION)-linux-amd64 clean: rm -rf ./dist -dist: - mkdir dist +dist/: + mkdir -p dist + +dist/chamber-$(VERSION)-darwin-amd64: | govendor dist/ govendor sync - GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build $(LDFLAGS) -o dist/chamber-$(VERSION)-darwin-amd64 - GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build $(LDFLAGS) -o dist/chamber-$(VERSION)-linux-amd64 - @which sha256sum 2>&1 > /dev/null || ( \ - echo 'missing sha256sum; install on MacOS with `brew install coreutils && ln -s $$(which gsha256sum) /usr/local/bin/sha256sum`' ; \ - exit 1; \ - ) - cd dist && \ - sha256sum chamber-$(VERSION)-* > chamber-$(VERSION).sha256sums - -gh-release: - go get -u github.com/aktau/github-release + GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build $(LDFLAGS) -o $@ + +dist/chamber-$(VERSION)-linux-amd64: | govendor dist/ + govendor sync + GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build $(LDFLAGS) -o $@ govendor: go get -u github.com/kardianos/govendor + +.PHONY: clean all govendor diff --git a/Makefile.release b/Makefile.release new file mode 100644 index 00000000..1d7ec540 --- /dev/null +++ b/Makefile.release @@ -0,0 +1,122 @@ +# Goals: +# - Linux releases can be published to Github automatically by CircleCI +# +# This Makefile is meant for machines + +include Makefile + +# set --pre-release if not tagged or tree is dirty or there's a `-` in the tag +ifneq (,$(findstring -,$(VERSION))) + GITHUB_RELEASE_FLAGS := "--pre-release" + PACKAGECLOUD_NAME_SUFFIX := "-prerelease" +endif + +PACKAGECLOUD_DEB_DISTROS := \ + debian/stretch \ + ubuntu/trusty \ + ubuntu/xenial \ + ubuntu/bionic + +PACKAGECLOUD_RPM_DISTROS := \ + fedora/27 \ + fedora/28 + +publish: publish-github publish-packagecloud + +publish-github: publish-github-darwin publish-github-linux publish-github-deb publish-github-rpm publish-github-sha256sums + +publish-packagecloud: publish-packagecloud-deb publish-packagecloud-rpm + +github-release: + github-release release \ + --security-token $$GH_LOGIN \ + --user segmentio \ + --repo chamber \ + $(GITHUB_RELEASE_FLAGS) \ + --tag $(VERSION) \ + --name $(VERSION) + +publish-github-darwin: dist/chamber-$(VERSION)-darwin-amd64 | github-release + github-release upload \ + --security-token $$GH_LOGIN \ + --user segmentio \ + --repo chamber \ + --tag $(VERSION) \ + --name chamber-$(VERSION)-darwin-amd64 \ + --file $< + +publish-github-linux: dist/chamber-$(VERSION)-linux-amd64 | github-release + github-release upload \ + --security-token $$GH_LOGIN \ + --user segmentio \ + --repo chamber \ + --tag $(VERSION) \ + --name chamber-$(VERSION)-linux-amd64 \ + --file $< + +publish-github-deb: dist/chamber_$(VERSION)_amd64.deb | github-release + github-release upload \ + --security-token $$GH_LOGIN \ + --user segmentio \ + --repo chamber \ + --tag $(VERSION) \ + --name chamber_$(VERSION)_amd64.deb \ + --file $< + +publish-github-rpm: dist/chamber_$(VERSION)_amd64.rpm | github-release + github-release upload \ + --security-token $$GH_LOGIN \ + --user segmentio \ + --repo chamber \ + --tag $(VERSION) \ + --name chamber_$(VERSION)_amd64.rpm \ + --file $< + +publish-github-sha256sums: dist/chamber-$(VERSION).sha256sums | github-release + github-release upload \ + --security-token $$GH_LOGIN \ + --user segmentio \ + --repo chamber \ + --tag $(VERSION) \ + --name chamber-$(VERSION).sha256sums \ + --file dist/chamber-$(VERSION).sha256sums + +packagecloud.conf.json: + @echo "{\"url\":\"https://packagecloud.io\",\"token\":\"$${PACKAGECLOUD_TOKEN}\"}" > $@ + +# package_cloud prints the last 4 chars of our token :( +# so we attempt to filter that out + +publish-packagecloud-deb: dist/chamber_$(VERSION)_amd64.deb packagecloud.conf.json + @for v in $(PACKAGECLOUD_DEB_DISTROS); do \ + package_cloud push --config packagecloud.conf.json segment/chamber$(PACKAGECLOUD_NAME_SUFFIX)/$$v $< | \ + grep -v 'with token:' ; \ + done + +publish-packagecloud-rpm: dist/chamber_$(VERSION)_amd64.rpm packagecloud.conf.json + @for v in $(PACKAGECLOUD_RPM_DISTROS); do \ + package_cloud push --config packagecloud.conf.json segment/chamber$(PACKAGECLOUD_NAME_SUFFIX)/$$v $< | \ + grep -v 'with token:' ; \ + done + +dist: dist/chamber-$(VERSION)-darwin-amd64 dist/chamber-$(VERSION)-linux-amd64 dist/chamber_$(VERSION)_amd64.deb dist/chamber_$(VERSION)_amd64.rpm dist/chamber-$(VERSION).sha256sums + +dist/chamber-$(VERSION).sha256sums: dist/chamber-$(VERSION)-darwin-amd64 dist/chamber-$(VERSION)-linux-amd64 dist/chamber_$(VERSION)_amd64.deb dist/chamber_$(VERSION)_amd64.rpm + sha256sum $^ | sed 's|dist/||g' > $@ + +dist/nfpm-$(VERSION).yaml: | dist/ + sed -e "s/\$${VERSION}/$(VERSION)/g" -e "s|\$${DIST_BIN}|dist/chamber-$(VERSION)-linux-amd64|g" < nfpm.yaml.tmpl > $@ + +dist/chamber_$(VERSION)_amd64.deb: dist/nfpm-$(VERSION).yaml dist/chamber-$(VERSION)-linux-amd64 + nfpm -f $< pkg --target $@ + +dist/chamber_$(VERSION)_amd64.rpm: dist/nfpm-$(VERSION).yaml dist/chamber-$(VERSION)-linux-amd64 + nfpm -f $< pkg --target $@ + +.PHONY: \ + publish-github \ + publish-github-linux \ + publish-github-rpm \ + publish-github-deb \ + publish-github-darwin \ + github-release diff --git a/Makefile.tools b/Makefile.tools new file mode 100644 index 00000000..3598a283 --- /dev/null +++ b/Makefile.tools @@ -0,0 +1,37 @@ +# Tools installation recipes +# +# These are fragile, non-portable, and often require root +# +NFPM_VERSION := 0.9.3 +#from https://github.com/goreleaser/nfpm/releases/download/v0.9.3/nfpm_0.9.3_checksums.txt +NFPM_SHA256 := f875ac060a30ec5c164e5444a7278322b276707493fa0ced6bfdd56640f0a6ea + +nfpm-debian: + cd /tmp && \ + curl -Ls https://github.com/goreleaser/nfpm/releases/download/v${NFPM_VERSION}/nfpm_${NFPM_VERSION}_Linux_x86_64.tar.gz > nfpm.tar.gz && \ + echo "${NFPM_SHA256} nfpm.tar.gz" | \ + sha256sum -c && \ + tar xzvf nfpm.tar.gz && \ + mv nfpm /usr/local/bin + +rpmbuild-debian: + apt update -q && apt install rpm -yq + +rpmbuild-darwin: + brew install rpm + +sha256sum-darwin: + brew install coreutils && ln -s $$(which gsha256sum) /usr/local/bin/sha256sum` + +github-release: + go get -u github.com/aktau/github-release + +package_cloud: + gem install package_cloud + +.PHONY: nfpm-debian \ + rpmbuild-debian \ + rpmbuild-darwin \ + sha256sum-darwin \ + github-release \ + package_cloud diff --git a/nfpm.yaml.tmpl b/nfpm.yaml.tmpl new file mode 100644 index 00000000..6de7da05 --- /dev/null +++ b/nfpm.yaml.tmpl @@ -0,0 +1,19 @@ +name: "chamber" +arch: "amd64" +platform: "linux" +version: "${VERSION}" +section: "default" +priority: "extra" +provides: +- chamber +vendor: 'Segment, Inc.' +maintainer: tooling-team@segment.com +homepage: "https://github.com/segmentio/chamber" +license: "MIT" +# IMHO packages should install to /usr/bin +bindir: /usr/bin +files: + "${DIST_BIN}": "/usr/bin/chamber" +description: > + Chamber is a tool for managing secrets. Currently it does so by storing + secrets in SSM Parameter Store, an AWS service for storing secrets.