diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..c48ae9d --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,30 @@ +version: 2 +jobs: + build: + machine: + docker_layer_caching: true + steps: + - checkout + - run: + command: | + make version + if [[ "$CIRCLE_BRANCH" == "release" ]]; then + export PACKAGECLOUD_REPOSITORY=dokku/dokku + make .env.docker + fi + - run: make circleci + - run: make build-docker-image + - run: + command: | + make build-in-docker + [[ -d build ]] && sudo chown -R circleci:circleci build + - run: make validate-in-docker + - store_artifacts: + path: build + destination: build + - run: + command: | + if [[ "$CIRCLE_BRANCH" == "release" ]]; then + make release-in-docker + fi + make release-packagecloud-in-docker diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2156300 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +sshcommand.bak diff --git a/CHANGELOG.md b/CHANGELOG.md index 29afcb2..028a540 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,16 @@ All notable changes to this project will be documented in this file. ### Changed +## [0.8.0] - 2019-08-10 +### Fixed +- @fruitl00p delete_user is now portable + +### Added +- @D1ceWard Added arch linux support +- @josegonzalez Move to circleci 2.0 +- @josegonzalez Run tests in docker +- @josegonzalez Release packages via CI +- @josegonzalez Add version command ## [0.7.0] - 2017-03-22 ### Fixed @@ -103,7 +113,9 @@ All notable changes to this project will be documented in this file. - @michaelshobbs update build image in README - @jvanbaarsen Only add SSH key if it doesn't already exists -[unreleased]: https://github.com/dokku/sshcommand/compare/v0.6.0...HEAD +[unreleased]: https://github.com/dokku/sshcommand/compare/v0.8.0...HEAD +[0.8.0]: https://github.com/dokku/sshcommand/compare/v0.7.0...v0.8.0 +[0.7.0]: https://github.com/dokku/sshcommand/compare/v0.6.0...v0.7.0 [0.6.0]: https://github.com/dokku/sshcommand/compare/v0.5.0...v0.6.0 [0.5.0]: https://github.com/dokku/sshcommand/compare/v0.4.0...v0.5.0 [0.4.0]: https://github.com/dokku/sshcommand/compare/v0.3.0...v0.4.0 diff --git a/Dockerfile.build b/Dockerfile.build new file mode 100644 index 0000000..22e34ac --- /dev/null +++ b/Dockerfile.build @@ -0,0 +1,6 @@ +FROM golang:1.12.0-stretch +RUN apt-get update \ + && apt install apt-transport-https build-essential curl gnupg2 lintian rpm rsync rubygems-integration ruby-dev ruby software-properties-common sudo -qy \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* +RUN gem install --no-ri --no-rdoc --quiet rake fpm package_cloud diff --git a/Dockerfile.test b/Dockerfile.test deleted file mode 100644 index 3fbe6b8..0000000 --- a/Dockerfile.test +++ /dev/null @@ -1,10 +0,0 @@ -FROM gcc:6.1 -ENV DEBIAN_FRONTEND noninteractive -ENV DEBCONF_NONINTERACTIVE_SEEN true - -RUN apt-get update && apt-get install -qq -y software-properties-common sudo - -ADD . /app -WORKDIR /app - -RUN make -e ci-dependencies diff --git a/Makefile b/Makefile index f994951..7f619c7 100644 --- a/Makefile +++ b/Makefile @@ -1,64 +1,214 @@ -.PHONY: ci-dependencies shellcheck bats install lint unit-tests test build-test-container test-in-docker -SYSTEM := $(shell sh -c 'uname -s 2>/dev/null') +.PHONY: ci-dependencies shellcheck bats install lint unit-tests test NAME = sshcommand -VERSION = 0.7.0 +EMAIL = sshcommand@josediazgonzalez.com +MAINTAINER = dokku +MAINTAINER_NAME = Jose Diaz-Gonzalez +REPOSITORY = sshcommand +HARDWARE = $(shell uname -m) +SYSTEM_NAME = $(shell uname -s | tr '[:upper:]' '[:lower:]') +BASE_VERSION ?= 0.8.0 +IMAGE_NAME ?= $(MAINTAINER)/$(REPOSITORY) +PACKAGECLOUD_REPOSITORY ?= dokku/dokku-betafish -ci-dependencies: shellcheck bats - -shellcheck: -ifneq ($(shell shellcheck --version > /dev/null 2>&1 ; echo $$?),0) -ifeq ($(SYSTEM),Darwin) - brew install shellcheck +ifeq ($(CIRCLE_BRANCH),release) + VERSION ?= $(BASE_VERSION) + DOCKER_IMAGE_VERSION = $(VERSION) else - sudo add-apt-repository 'deb http://archive.ubuntu.com/ubuntu trusty-backports main restricted universe multiverse' - sudo apt-get update && sudo -E apt-get install -y -qq shellcheck -endif + VERSION = $(shell echo "${BASE_VERSION}")build+$(shell git rev-parse --short HEAD) + DOCKER_IMAGE_VERSION = $(shell echo "${BASE_VERSION}")build-$(shell git rev-parse --short HEAD) endif -bats: -ifneq ($(shell bats --version > /dev/null 2>&1 ; echo $$?),0) -ifeq ($(SYSTEM),Darwin) - brew install bats -else - sudo mkdir -p /usr/local - git clone https://github.com/sstephenson/bats.git /tmp/bats - cd /tmp/bats && sudo ./install.sh /usr/local - rm -rf /tmp/bats -endif -endif +version: + @sed -i.bak 's/SSHCOMMAND_VERSION=""/SSHCOMMAND_VERSION="$(VERSION)"/' sshcommand && rm sshcommand.bak + @echo "$(CIRCLE_BRANCH)" + @echo "$(VERSION)" + @./sshcommand version + + +define PACKAGE_DESCRIPTION +Turn SSH into a thin client specifically for your app +Simplifies running a single command over SSH, and +manages authorized keys (ACL) and users in order to do so. +endef + +export PACKAGE_DESCRIPTION + +LIST = build release release-packagecloud validate +targets = $(addsuffix -in-docker, $(LIST)) + +.env.docker: + @rm -f .env.docker + @touch .env.docker + @echo "CIRCLE_BRANCH=$(CIRCLE_BRANCH)" >> .env.docker + @echo "GITHUB_ACCESS_TOKEN=$(GITHUB_ACCESS_TOKEN)" >> .env.docker + @echo "IMAGE_NAME=$(IMAGE_NAME)" >> .env.docker + @echo "PACKAGECLOUD_REPOSITORY=$(PACKAGECLOUD_REPOSITORY)" >> .env.docker + @echo "PACKAGECLOUD_TOKEN=$(PACKAGECLOUD_TOKEN)" >> .env.docker + @echo "VERSION=$(VERSION)" >> .env.docker + +build: pre-build + @$(MAKE) build/darwin/$(NAME) + @$(MAKE) build/linux/$(NAME) + @$(MAKE) build/deb/$(NAME)_$(VERSION)_amd64.deb + @$(MAKE) build/rpm/$(NAME)-$(VERSION)-1.x86_64.rpm + +build-docker-image: + docker build --rm -q -f Dockerfile.build -t $(IMAGE_NAME):build . + +$(targets): %-in-docker: .env.docker + docker run \ + --env-file .env.docker \ + --rm \ + --volume /var/lib/docker:/var/lib/docker \ + --volume /var/run/docker.sock:/var/run/docker.sock:ro \ + --volume ${PWD}:/src/github.com/$(MAINTAINER)/$(REPOSITORY) \ + --workdir /src/github.com/$(MAINTAINER)/$(REPOSITORY) \ + $(IMAGE_NAME):build make -e $(@:-in-docker=) + +build/darwin/$(NAME): + chmod +x sshcommand + mkdir -p build/darwin + cp -f sshcommand build/darwin/sshcommand + +build/linux/$(NAME): + chmod +x sshcommand + mkdir -p build/linux + cp -f sshcommand build/linux/sshcommand + +build/deb/$(NAME)_$(VERSION)_amd64.deb: build/linux/$(NAME) + chmod 644 LICENSE + export SOURCE_DATE_EPOCH=$(shell git log -1 --format=%ct) \ + && mkdir -p build/deb \ + && fpm \ + --architecture amd64 \ + --category admin \ + --description "$$PACKAGE_DESCRIPTION" \ + --input-type dir \ + --license 'MIT License' \ + --maintainer "$(MAINTAINER_NAME) <$(EMAIL)>" \ + --name $(NAME) \ + --output-type deb \ + --package build/deb/$(NAME)_$(VERSION)_amd64.deb \ + --url "https://github.com/$(MAINTAINER)/$(REPOSITORY)" \ + --vendor "" \ + --version $(VERSION) \ + --verbose \ + build/linux/$(NAME)=/usr/bin/$(NAME) \ + LICENSE=/usr/share/doc/$(NAME)/copyright + +build/rpm/$(NAME)-$(VERSION)-1.x86_64.rpm: build/linux/$(NAME) + chmod 644 LICENSE + export SOURCE_DATE_EPOCH=$(shell git log -1 --format=%ct) \ + && mkdir -p build/rpm \ + && fpm \ + --architecture x86_64 \ + --category admin \ + --description "$$PACKAGE_DESCRIPTION" \ + --input-type dir \ + --license 'MIT License' \ + --maintainer "$(MAINTAINER_NAME) <$(EMAIL)>" \ + --name $(NAME) \ + --output-type rpm \ + --package build/rpm/$(NAME)-$(VERSION)-1.x86_64.rpm \ + --rpm-os linux \ + --url "https://github.com/$(MAINTAINER)/$(REPOSITORY)" \ + --vendor "" \ + --version $(VERSION) \ + --verbose \ + build/linux/$(NAME)=/usr/bin/$(NAME) \ + LICENSE=/usr/share/doc/$(NAME)/copyright + +clean: + rm -rf build release validation -install: - @echo setting up... - cp ./sshcommand /usr/local/bin - chmod +x /usr/local/bin +circleci: + docker version + rm -f ~/.gitconfig -lint: +bin/gh-release: + mkdir -p bin + curl -o bin/gh-release.tgz -sL https://github.com/progrium/gh-release/releases/download/v2.2.1/gh-release_2.2.1_$(SYSTEM_NAME)_$(HARDWARE).tgz + tar xf bin/gh-release.tgz -C bin + chmod +x bin/gh-release + +release: bin/gh-release + rm -rf release && mkdir release + tar -zcf release/$(NAME)_$(VERSION)_linux_$(HARDWARE).tgz -C build/linux $(NAME) + tar -zcf release/$(NAME)_$(VERSION)_darwin_$(HARDWARE).tgz -C build/darwin $(NAME) + cp build/deb/$(NAME)_$(VERSION)_amd64.deb release/$(NAME)_$(VERSION)_amd64.deb + cp build/rpm/$(NAME)-$(VERSION)-1.x86_64.rpm release/$(NAME)-$(VERSION)-1.x86_64.rpm + bin/gh-release create $(MAINTAINER)/$(REPOSITORY) $(VERSION) $(shell git rev-parse --abbrev-ref HEAD) + +release-packagecloud: + @$(MAKE) release-packagecloud-deb + @$(MAKE) release-packagecloud-rpm + +release-packagecloud-deb: build/deb/$(NAME)_$(VERSION)_amd64.deb + package_cloud push $(PACKAGECLOUD_REPOSITORY)/ubuntu/trusty build/deb/$(NAME)_$(VERSION)_amd64.deb + package_cloud push $(PACKAGECLOUD_REPOSITORY)/ubuntu/utopic build/deb/$(NAME)_$(VERSION)_amd64.deb + package_cloud push $(PACKAGECLOUD_REPOSITORY)/ubuntu/vivid build/deb/$(NAME)_$(VERSION)_amd64.deb + package_cloud push $(PACKAGECLOUD_REPOSITORY)/ubuntu/wily build/deb/$(NAME)_$(VERSION)_amd64.deb + package_cloud push $(PACKAGECLOUD_REPOSITORY)/ubuntu/xenial build/deb/$(NAME)_$(VERSION)_amd64.deb + package_cloud push $(PACKAGECLOUD_REPOSITORY)/ubuntu/yakkety build/deb/$(NAME)_$(VERSION)_amd64.deb + package_cloud push $(PACKAGECLOUD_REPOSITORY)/ubuntu/zesty build/deb/$(NAME)_$(VERSION)_amd64.deb + package_cloud push $(PACKAGECLOUD_REPOSITORY)/ubuntu/artful build/deb/$(NAME)_$(VERSION)_amd64.deb + package_cloud push $(PACKAGECLOUD_REPOSITORY)/ubuntu/bionic build/deb/$(NAME)_$(VERSION)_amd64.deb + package_cloud push $(PACKAGECLOUD_REPOSITORY)/debian/wheezy build/deb/$(NAME)_$(VERSION)_amd64.deb + package_cloud push $(PACKAGECLOUD_REPOSITORY)/debian/jessie build/deb/$(NAME)_$(VERSION)_amd64.deb + package_cloud push $(PACKAGECLOUD_REPOSITORY)/debian/stretch build/deb/$(NAME)_$(VERSION)_amd64.deb + package_cloud push $(PACKAGECLOUD_REPOSITORY)/debian/buster build/deb/$(NAME)_$(VERSION)_amd64.deb + +release-packagecloud-rpm: build/rpm/$(NAME)-$(VERSION)-1.x86_64.rpm + package_cloud push $(PACKAGECLOUD_REPOSITORY)/el/7 build/rpm/$(NAME)-$(VERSION)-1.x86_64.rpm + +validate: test + mkdir -p validation + lintian build/deb/$(NAME)_$(VERSION)_amd64.deb || true + dpkg-deb --info build/deb/$(NAME)_$(VERSION)_amd64.deb + dpkg -c build/deb/$(NAME)_$(VERSION)_amd64.deb + cd validation && ar -x ../build/deb/$(NAME)_$(VERSION)_amd64.deb + cd validation && rpm2cpio ../build/rpm/$(NAME)-$(VERSION)-1.x86_64.rpm > $(NAME)-$(VERSION)-1.x86_64.cpio + ls -lah build/deb build/rpm validation + sha1sum build/deb/$(NAME)_$(VERSION)_amd64.deb + sha1sum build/rpm/$(NAME)-$(VERSION)-1.x86_64.rpm + +test: lint unit-tests + +lint: shellcheck bats @echo linting... # SC2034: VAR appears unused - https://github.com/koalaman/shellcheck/wiki/SC2034 # desc is used to declare the description of the function @$(QUIET) find . -not -path '*/\.*' | xargs file | egrep "shell|bash" | awk '{ print $$1 }' | sed 's/://g' | xargs shellcheck -e SC2034 -unit-tests: +unit-tests: /usr/local/bin/sshcommand @echo running unit tests... - @$(QUIET) bats tests/unit + @mkdir -p test-results/bats + @$(QUIET) TERM=linux bats --formatter bats-format-junit -e -T -o test-results/bats tests/unit -test: lint unit-tests +pre-build: + true -build-test-container: - @echo building test container... - docker build -t sshcommand_test -f Dockerfile.test . +/usr/local/bin/sshcommand: + @echo installing sshcommand + cp ./sshcommand /usr/local/bin/sshcommand + chmod +x /usr/local/bin/sshcommand -test-in-docker: -ifneq ($(shell docker inspect sshcommand_test > /dev/null 2>&1 ; echo $$?),0) - $(MAKE) build-test-container +shellcheck: +ifneq ($(shell shellcheck --version >/dev/null 2>&1 ; echo $$?),0) +ifeq ($(SYSTEM_NAME),darwin) + brew install shellcheck +else + sudo apt-get update -qq && sudo apt-get install -qq -y shellcheck +endif endif - docker run -ti --rm -v ${PWD}:/app -w /app --hostname='box223' sshcommand_test make ci-dependencies install test - -deps: - go get -u github.com/progrium/gh-release/... -release: deps - rm -rf release && mkdir release - tar -zcf release/$(NAME)_$(VERSION).tgz . - gh-release create dokku/$(NAME) $(VERSION) \ - $(shell git rev-parse --abbrev-ref HEAD) v$(VERSION) +bats: +ifeq ($(SYSTEM_NAME),darwin) +ifneq ($(shell bats --version >/dev/null 2>&1 ; echo $$?),0) + brew install bats-core +endif +else + git clone https://github.com/josegonzalez/bats-core.git /tmp/bats + cd /tmp/bats && sudo ./install.sh /usr/local + rm -rf /tmp/bats +endif diff --git a/README.md b/README.md index 377226c..9bbcf45 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ sshcommand acl-add # Adds named SSH key to user fro sshcommand acl-remove # Removes SSH key by name sshcommand list # Lists SSH user keys by name sshcommand help # Shows help information +sshcommand version # Shows version ``` ## Example diff --git a/circle.yml b/circle.yml deleted file mode 100644 index e492081..0000000 --- a/circle.yml +++ /dev/null @@ -1,13 +0,0 @@ -dependencies: - override: - - make -e ci-dependencies - - sudo make -e install -test: - override: - - sudo make -e test - -deployment: - release: - branch: release - commands: - - make release diff --git a/sshcommand b/sshcommand index 99b2730..cf71089 100755 --- a/sshcommand +++ b/sshcommand @@ -7,6 +7,8 @@ if [[ -f /etc/defaults/sshcommand ]]; then source /etc/defaults/sshcommand fi +declare SSHCOMMAND_VERSION="" + cmd-help() { declare desc="Shows help information for a command" declare args="$*" @@ -68,6 +70,10 @@ fn-adduser() { debian*|ubuntu|raspbian*) adduser --disabled-password --gecos "" "$l_user" ;; + arch) + useradd -m -s /bin/bash "$l_user" + usermod -L -aG "$l_user" "$l_user" + ;; *) useradd -m -s /bin/bash "$l_user" groupadd "$l_user" @@ -190,13 +196,19 @@ sshcommand-help() { return 0 fi - echo "sshcommand" + echo "sshcommand ${SSHCOMMAND_VERSION}" echo "" printf " %-10s %-30s %s\n" "create" "$(fn-args "sshcommand-create")" "$(fn-desc "sshcommand-create")" printf " %-10s %-30s %s\n" "acl-add" "$(fn-args "sshcommand-acl-add")" "$(fn-desc "sshcommand-acl-add")" printf " %-10s %-30s %s\n" "acl-remove" "$(fn-args "sshcommand-acl-remove")" "$(fn-desc "sshcommand-acl-remove")" printf " %-10s %-30s %s\n" "list" "$(fn-args "sshcommand-list")" "$(fn-desc "sshcommand-list")" printf " %-10s %-30s %s\n" "help" "$(fn-args "sshcommand-help")" "$(fn-desc "sshcommand-help")" + printf " %-10s %-30s %s\n" "version" "$(fn-args "sshcommand-version")" "$(fn-desc "sshcommand-version")" +} + +sshcommand-version() { + declare desc="Shows version" + echo "sshcommand ${SSHCOMMAND_VERSION}" } main() { @@ -215,6 +227,7 @@ main() { fi } +# shellcheck disable=SC2128 if [[ "$0" == "$BASH_SOURCE" ]]; then main "$@" fi diff --git a/tests/unit/fixtures/os/arch-os-release b/tests/unit/fixtures/os/arch-os-release new file mode 100644 index 0000000..d28fdf2 --- /dev/null +++ b/tests/unit/fixtures/os/arch-os-release @@ -0,0 +1,8 @@ +NAME="Arch Linux" +PRETTY_NAME="Arch Linux" +ID=arch +ID_LIKE=archlinux +ANSI_COLOR="0;36" +HOME_URL="https://www.archlinux.org/" +SUPPORT_URL="https://bbs.archlinux.org/" +BUG_REPORT_URL="https://bugs.archlinux.org/" diff --git a/tests/unit/functions.bats b/tests/unit/functions.bats index 5d4701b..e0cc8a7 100644 --- a/tests/unit/functions.bats +++ b/tests/unit/functions.bats @@ -22,6 +22,12 @@ load test_helper echo "status: "$status assert_output "alpine" assert_success + + SSHCOMMAND_OSRELEASE=$BATS_TEST_DIRNAME/fixtures/os/arch-os-release run "fn-print-os-id" + echo "output: "$output + echo "status: "$status + assert_output "arch" + assert_success } @test "(fn) print-os-id (invalid path)" { diff --git a/tests/unit/test_helper.bash b/tests/unit/test_helper.bash index 661c409..9c4bc37 100644 --- a/tests/unit/test_helper.bash +++ b/tests/unit/test_helper.bash @@ -98,7 +98,7 @@ create_user() { } delete_user() { - deluser --remove-home $TEST_USER + userdel --remove $TEST_USER } create_test_key() {