Compare commits

...

51 Commits

Author SHA1 Message Date
Bo-Yi Wu 65e19227c4 update readme.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2017-01-02 21:26:26 +08:00
Bo-Yi Wu df18b64cb4 fix fmt command.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-31 13:30:36 +08:00
Bo-Yi Wu f987106211 support ssh agent.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-30 21:50:39 +08:00
Bo-Yi Wu eddd7a9661 [ci skip] remove windows support.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-30 15:12:36 +08:00
Bo-Yi Wu 1355c4edc1 [ci skip] add badge.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-30 13:36:39 +08:00
Bo-Yi Wu 2eb54a15ca remove create root .ssh folder.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-30 13:12:10 +08:00
Bo-Yi Wu 42540b5d45 Merge pull request #19 from appleboy/ssh
Add ssh testing.
2016-12-30 12:43:49 +08:00
Bo-Yi Wu 5f176416d7 add ssh server for alpine.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-30 12:38:44 +08:00
Bo-Yi Wu 6c2d597d31 update drone setting
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-30 11:33:57 +08:00
Bo-Yi Wu 9aa3cdb828 update travis testing.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-30 11:13:22 +08:00
Bo-Yi Wu 392c7c90e3 Add ssh testing.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-30 10:44:49 +08:00
Bo-Yi Wu a0c61bbd03 update readme.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-29 07:17:55 +08:00
Bo-Yi Wu 5a6851415d Support key path.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-29 07:16:38 +08:00
Bo-Yi Wu e4f3a180c8 add random string.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-28 15:56:17 +08:00
Bo-Yi Wu 9dbfdad07c remove ENV.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-28 14:58:51 +08:00
Bo-Yi Wu debd2db692 hide codecov token
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-28 11:54:13 +08:00
Bo-Yi Wu 5bd128025d add cache and fix repo name
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-28 11:52:36 +08:00
Bo-Yi Wu d3b4925aff add drone sign file.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-28 11:48:59 +08:00
Bo-Yi Wu 291c006b5c fix docker image name
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-28 11:45:05 +08:00
Bo-Yi Wu dd7f593c06 fix makefile.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-28 11:43:26 +08:00
Bo-Yi Wu 9559a5b600 Merge pull request #17 from appleboy/tool
Add release tool
2016-12-28 11:41:00 +08:00
Bo-Yi Wu 974cd420af add some env.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-28 11:27:23 +08:00
Bo-Yi Wu d31fe06287 add badge.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-28 11:25:35 +08:00
Bo-Yi Wu 9384d1261d add coverage command.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-28 11:23:06 +08:00
Bo-Yi Wu 43037f5cef using go latest version.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-28 11:15:49 +08:00
Bo-Yi Wu f43d0a817e remove docker from travis.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-28 11:14:56 +08:00
Bo-Yi Wu 6cb6510fed fix path.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-28 11:11:15 +08:00
Bo-Yi Wu da5dda1f0d update glide version.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-28 11:09:43 +08:00
Bo-Yi Wu 4fc0ebcd98 update tool
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-28 11:02:31 +08:00
Bo-Yi Wu e3418f8441 Merge pull request #15 from appleboy/sync
Support golang routines
2016-12-27 14:38:42 +08:00
Bo-Yi Wu d5baf6186d update readme.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-27 14:33:56 +08:00
Bo-Yi Wu f5d5e54a57 Support routines.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-27 14:33:21 +08:00
Bo-Yi Wu 031c1e4801 Merge pull request #13 from appleboy/multiple_target
support multiple target
2016-12-19 16:42:13 +08:00
Bo-Yi Wu 1bae57a838 update readme.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-19 16:30:41 +08:00
Bo-Yi Wu 91ef54d3d6 Support multiple target.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-19 16:29:38 +08:00
Bo-Yi Wu bfb8c6795c Merge pull request #12 from appleboy/multiple_host
support multiple host
2016-12-19 15:28:46 +08:00
Bo-Yi Wu 339a0d497f fix testing
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-19 15:23:16 +08:00
Bo-Yi Wu cc1520024e support multiple host
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-19 15:13:11 +08:00
Bo-Yi Wu 455b6dd7ae update check go version.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-05 11:19:52 +08:00
Bo-Yi Wu f12fc6e476 update golang testing to 1.6.4 and 1.7.4
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-05 11:12:08 +08:00
Bo-Yi Wu 807dff2951 update readme.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-05 11:10:21 +08:00
Bo-Yi Wu 8171197bad Merge pull request #10 from appleboy/rm
Support rm flag
2016-12-05 11:08:03 +08:00
Bo-Yi Wu 3277383d4f update readme
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-05 11:06:10 +08:00
Bo-Yi Wu 2bb7d842f2 support rm flag
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-12-05 11:04:11 +08:00
Bo-Yi Wu 6e7710e445 Merge pull request #6 from appleboy/bug
fix tar multiple folder or file.
2016-11-29 15:30:07 +08:00
Bo-Yi Wu 658203c26d fix tar multiple folder or file.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-11-29 15:29:03 +08:00
Bo-Yi Wu 7cd8855a53 remove --rm flag 2016-11-28 16:37:33 +08:00
Bo-Yi Wu 42851ed07b Merge pull request #4 from appleboy/cli
Support load configuration from files.
2016-11-21 11:19:36 +08:00
Bo-Yi Wu 7b90afbf37 Support load configuration from files.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-11-21 11:10:20 +08:00
Bo-Yi Wu 21d349362b update Version comment.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-11-19 22:34:54 +08:00
Bo-Yi Wu 7dfdbbde89 add version command.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2016-11-19 21:21:37 +08:00
17 changed files with 725 additions and 157 deletions
+84
View File
@@ -0,0 +1,84 @@
workspace:
base: /srv/app
path: src/github.com/appleboy/drone-scp
pipeline:
# restore the cache from an sftp server
restore_cache:
image: appleboy/drone-sftp-cache
restore: true
mount: [ .glide, vendor ]
ignore_branch: true
test:
image: appleboy/golang-testing
pull: true
environment:
TAGS: netgo
GOPATH: /srv/app
commands:
- adduser -h /home/drone-scp -s /bin/bash -D -S drone-scp
- passwd -d drone-scp
- mkdir -p /home/drone-scp/.ssh
- chmod 700 /home/drone-scp/.ssh
- cp tests/.ssh/id_rsa.pub /home/drone-scp/.ssh/authorized_keys
- chown -R drone-scp /home/drone-scp/.ssh
# install ssh and start server
- apk update && apk add openssh openrc
- rm -rf /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_dsa_key
- ./tests/entrypoint.sh /usr/sbin/sshd -D &
- make dep_install
- make vet
- make lint
- make test
- make coverage
- make build
# build binary for docker image
- make static_build
when:
event: [ push, tag, pull_request ]
release:
image: appleboy/golang-testing
pull: true
environment:
TAGS: netgo
GOPATH: /srv/app
commands:
- make release
when:
event: [ tag ]
branch: [ refs/tags/* ]
docker:
image: plugins/docker
repo: ${DRONE_REPO}
tags: [ '${DRONE_TAG}' ]
when:
event: [ tag ]
branch: [ refs/tags/* ]
docker:
image: plugins/docker
repo: ${DRONE_REPO}
tags: [ 'latest' ]
when:
event: [ push ]
branch: [ master ]
github:
image: plugins/github-release
files:
- dist/release/*
when:
event: [ tag ]
branch: [ refs/tags/* ]
# rebuild the cache on the sftp server
rebuild_cache:
image: appleboy/drone-sftp-cache
rebuild: true
mount: [ .glide, vendor ]
ignore_branch: true
when:
branch: master
+1
View File
@@ -0,0 +1 @@
eyJhbGciOiJIUzI1NiJ9.d29ya3NwYWNlOgogIGJhc2U6IC9zcnYvYXBwCiAgcGF0aDogc3JjL2dpdGh1Yi5jb20vYXBwbGVib3kvZHJvbmUtc2NwCgpwaXBlbGluZToKICAjIHJlc3RvcmUgdGhlIGNhY2hlIGZyb20gYW4gc2Z0cCBzZXJ2ZXIKICByZXN0b3JlX2NhY2hlOgogICAgaW1hZ2U6IGFwcGxlYm95L2Ryb25lLXNmdHAtY2FjaGUKICAgIHJlc3RvcmU6IHRydWUKICAgIG1vdW50OiBbIC5nbGlkZSwgdmVuZG9yIF0KICAgIGlnbm9yZV9icmFuY2g6IHRydWUKCiAgdGVzdDoKICAgIGltYWdlOiBhcHBsZWJveS9nb2xhbmctdGVzdGluZwogICAgcHVsbDogdHJ1ZQogICAgZW52aXJvbm1lbnQ6CiAgICAgIFRBR1M6IG5ldGdvCiAgICAgIEdPUEFUSDogL3Nydi9hcHAKICAgIGNvbW1hbmRzOgogICAgICAtIGFkZHVzZXIgLWggL2hvbWUvZHJvbmUtc2NwIC1zIC9iaW4vYmFzaCAtRCAtUyBkcm9uZS1zY3AKICAgICAgLSBwYXNzd2QgLWQgZHJvbmUtc2NwCiAgICAgIC0gbWtkaXIgLXAgL2hvbWUvZHJvbmUtc2NwLy5zc2gKICAgICAgLSBjaG1vZCA3MDAgL2hvbWUvZHJvbmUtc2NwLy5zc2gKICAgICAgLSBjcCB0ZXN0cy8uc3NoL2lkX3JzYS5wdWIgL2hvbWUvZHJvbmUtc2NwLy5zc2gvYXV0aG9yaXplZF9rZXlzCiAgICAgIC0gY2hvd24gLVIgZHJvbmUtc2NwIC9ob21lL2Ryb25lLXNjcC8uc3NoCiAgICAgICMgaW5zdGFsbCBzc2ggYW5kIHN0YXJ0IHNlcnZlcgogICAgICAtIGFwayB1cGRhdGUgJiYgYXBrIGFkZCBvcGVuc3NoIG9wZW5yYwogICAgICAtIHJtIC1yZiAvZXRjL3NzaC9zc2hfaG9zdF9yc2Ffa2V5IC9ldGMvc3NoL3NzaF9ob3N0X2RzYV9rZXkKICAgICAgLSAuL3Rlc3RzL2VudHJ5cG9pbnQuc2ggL3Vzci9zYmluL3NzaGQgLUQgJgogICAgICAtIG1ha2UgZGVwX2luc3RhbGwKICAgICAgLSBtYWtlIHZldAogICAgICAtIG1ha2UgbGludAogICAgICAtIG1ha2UgdGVzdAogICAgICAtIG1ha2UgY292ZXJhZ2UKICAgICAgLSBtYWtlIGJ1aWxkCiAgICAgICMgYnVpbGQgYmluYXJ5IGZvciBkb2NrZXIgaW1hZ2UKICAgICAgLSBtYWtlIHN0YXRpY19idWlsZAogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCwgdGFnLCBwdWxsX3JlcXVlc3QgXQoKICByZWxlYXNlOgogICAgaW1hZ2U6IGFwcGxlYm95L2dvbGFuZy10ZXN0aW5nCiAgICBwdWxsOiB0cnVlCiAgICBlbnZpcm9ubWVudDoKICAgICAgVEFHUzogbmV0Z28KICAgICAgR09QQVRIOiAvc3J2L2FwcAogICAgY29tbWFuZHM6CiAgICAgIC0gbWFrZSByZWxlYXNlCiAgICB3aGVuOgogICAgICBldmVudDogWyB0YWcgXQogICAgICBicmFuY2g6IFsgcmVmcy90YWdzLyogXQoKICBkb2NrZXI6CiAgICBpbWFnZTogcGx1Z2lucy9kb2NrZXIKICAgIHJlcG86ICR7RFJPTkVfUkVQT30KICAgIHRhZ3M6IFsgJyR7RFJPTkVfVEFHfScgXQogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgdGFnIF0KICAgICAgYnJhbmNoOiBbIHJlZnMvdGFncy8qIF0KCiAgZG9ja2VyOgogICAgaW1hZ2U6IHBsdWdpbnMvZG9ja2VyCiAgICByZXBvOiAke0RST05FX1JFUE99CiAgICB0YWdzOiBbICdsYXRlc3QnIF0KICAgIHdoZW46CiAgICAgIGV2ZW50OiBbIHB1c2ggXQogICAgICBicmFuY2g6IFsgbWFzdGVyIF0KCiAgZ2l0aHViOgogICAgaW1hZ2U6IHBsdWdpbnMvZ2l0aHViLXJlbGVhc2UKICAgIGZpbGVzOgogICAgICAtIGRpc3QvcmVsZWFzZS8qCiAgICB3aGVuOgogICAgICBldmVudDogWyB0YWcgXQogICAgICBicmFuY2g6IFsgcmVmcy90YWdzLyogXQoKICAjIHJlYnVpbGQgdGhlIGNhY2hlIG9uIHRoZSBzZnRwIHNlcnZlcgogIHJlYnVpbGRfY2FjaGU6CiAgICBpbWFnZTogYXBwbGVib3kvZHJvbmUtc2Z0cC1jYWNoZQogICAgcmVidWlsZDogdHJ1ZQogICAgbW91bnQ6IFsgLmdsaWRlLCB2ZW5kb3IgXQogICAgaWdub3JlX2JyYW5jaDogdHJ1ZQogICAgd2hlbjoKICAgICAgYnJhbmNoOiBtYXN0ZXIK.iJq2DIBtHk-IH2ioZdNEkFcxDj-5mtNikSX66Jdt_pM
+2
View File
@@ -25,3 +25,5 @@ _testmain.go
vendor vendor
drone-scp drone-scp
coverage.txt coverage.txt
.env
dist
+11 -34
View File
@@ -1,53 +1,30 @@
sudo: required sudo: required
language: go language: go
services:
- docker
go: go:
- 1.5.4 - 1.6.x
- 1.6.3 - 1.7.x
- 1.7.3
- tip - tip
env:
global:
- DOCKER_CACHE_FILE=${HOME}/docker/cache.tar.gz
cache: cache:
directories: directories:
- vendor - vendor
- ${HOME}/.glide - ${HOME}/.glide
- ${HOME}/docker
before_install: before_install:
- mkdir -p $GOPATH/bin - mkdir -p $GOPATH/bin
- curl https://glide.sh/get | sh - curl https://glide.sh/get | sh
- if [ -f ${DOCKER_CACHE_FILE} ]; then gunzip -c ${DOCKER_CACHE_FILE} | docker load; fi - sudo useradd -m -d /home/drone-scp -s /bin/bash drone-scp
- sudo mkdir -p /home/drone-scp/.ssh
- sudo chmod 700 /home/drone-scp/.ssh
- sudo cp tests/.ssh/id_rsa.pub /home/drone-scp/.ssh/authorized_keys
- sudo chown -R drone-scp /home/drone-scp/.ssh
install: install:
- export GO15VENDOREXPERIMENT=1 - make dep_install
- make install
script: script:
- make vet
- make lint
- make test - make test
- make docker - make build
- if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
mkdir -p $(dirname ${DOCKER_CACHE_FILE});
docker save $(docker history -q $TRAVIS_REPO_SLUG:latest | grep -v '<missing>') | gzip > ${DOCKER_CACHE_FILE};
fi
after_success:
# ignore main.go coverage
- sed -i '/main.go/d' coverage.txt
- bash <(curl -s https://codecov.io/bash) -f coverage.txt
# deploy from master
- if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_GO_VERSION" == "1.7.3" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD";
make docker_deploy tag=latest;
fi
# deploy from tag
- if [ "$TRAVIS_GO_VERSION" == "1.7.3" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_TAG" != "" ]; then
docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD";
make docker_deploy tag=$TRAVIS_TAG;
fi
+84 -15
View File
@@ -1,8 +1,17 @@
.PHONY: install build test html update docker_build docker_image docker docker_deploy clean .PHONY: test drone-scp build fmt vet errcheck lint install update release-dirs release-build release-copy release-check release coverage
VERSION := $(shell git describe --tags || git rev-parse --short HEAD) DIST := dist
DEPLOY_ACCOUNT := "appleboy" EXECUTABLE := drone-scp
DEPLOY_IMAGE := "drone-scp"
# for dockerhub
DEPLOY_ACCOUNT := appleboy
DEPLOY_IMAGE := $(EXECUTABLE)
TARGETS ?= linux darwin
PACKAGES ?= $(shell go list ./... | grep -v /vendor/)
SOURCES ?= $(shell find . -name "*.go" -type f)
TAGS ?=
LDFLAGS += -X 'main.Version=$(VERSION)'
ifneq ($(shell uname), Darwin) ifneq ($(shell uname), Darwin)
EXTLDFLAGS = -extldflags "-static" $(null) EXTLDFLAGS = -extldflags "-static" $(null)
@@ -10,36 +19,96 @@ else
EXTLDFLAGS = EXTLDFLAGS =
endif endif
install: ifneq ($(DRONE_TAG),)
glide install VERSION ?= $(DRONE_TAG)
else
VERSION ?= $(shell git describe --tags --always || git rev-parse --short HEAD)
endif
build: all: build
go build -ldflags="$(EXTLDFLAGS)-s -w -X main.Version=$(VERSION)"
fmt:
find . -name "*.go" -type f -not -path "./vendor/*" | xargs gofmt -s -w
vet:
go vet $(PACKAGES)
errcheck:
@which errcheck > /dev/null; if [ $$? -ne 0 ]; then \
go get -u github.com/kisielk/errcheck; \
fi
errcheck $(PACKAGES)
lint:
@which golint > /dev/null; if [ $$? -ne 0 ]; then \
go get -u github.com/golang/lint/golint; \
fi
for PKG in $(PACKAGES); do golint -set_exit_status $$PKG || exit 1; done;
test: test:
go test -v -coverprofile=coverage.txt for PKG in $(PACKAGES); do go test -v -cover -coverprofile $$GOPATH/src/$$PKG/coverage.txt $$PKG || exit 1; done;
html: html:
go tool cover -html=coverage.txt go tool cover -html=coverage.txt
update: dep_install:
glide install
dep_update:
glide up glide up
docker_build: install: $(SOURCES)
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -tags netgo -ldflags="-X main.Version=$(VERSION)" go install -v -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)'
build: $(EXECUTABLE)
$(EXECUTABLE): $(SOURCES)
go build -v -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' -o $@
release: release-dirs release-build release-copy release-check
release-dirs:
mkdir -p $(DIST)/binaries $(DIST)/release
release-build:
@which gox > /dev/null; if [ $$? -ne 0 ]; then \
go get -u github.com/mitchellh/gox; \
fi
gox -os="$(TARGETS)" -arch="amd64 386" -tags="$(TAGS)" -ldflags="-s -w $(LDFLAGS)" -output="$(DIST)/binaries/$(EXECUTABLE)-$(VERSION)-{{.OS}}-{{.Arch}}"
release-copy:
$(foreach file,$(wildcard $(DIST)/binaries/$(EXECUTABLE)-*),cp $(file) $(DIST)/release/$(notdir $(file));)
release-check:
cd $(DIST)/release; $(foreach file,$(wildcard $(DIST)/release/$(EXECUTABLE)-*),sha256sum $(notdir $(file)) > $(notdir $(file)).sha256;)
# for docker.
static_build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' -o $(DEPLOY_IMAGE)
docker_image: docker_image:
docker build --rm -t $(DEPLOY_ACCOUNT)/$(DEPLOY_IMAGE) . docker build -t $(DEPLOY_ACCOUNT)/$(DEPLOY_IMAGE) .
docker: docker_build docker_image docker: static_build docker_image
docker_deploy: docker_deploy:
ifeq ($(tag),) ifeq ($(tag),)
@echo "Usage: make $@ tag=<tag>" @echo "Usage: make $@ tag=<tag>"
@exit 1 @exit 1
endif endif
# deploy image
docker tag $(DEPLOY_ACCOUNT)/$(DEPLOY_IMAGE):latest $(DEPLOY_ACCOUNT)/$(DEPLOY_IMAGE):$(tag) docker tag $(DEPLOY_ACCOUNT)/$(DEPLOY_IMAGE):latest $(DEPLOY_ACCOUNT)/$(DEPLOY_IMAGE):$(tag)
docker push $(DEPLOY_ACCOUNT)/$(DEPLOY_IMAGE):$(tag) docker push $(DEPLOY_ACCOUNT)/$(DEPLOY_IMAGE):$(tag)
coverage:
sed -i '/main.go/d' coverage.txt
curl -s https://codecov.io/bash > .codecov && \
chmod +x .codecov && \
./.codecov -f coverage.txt
clean: clean:
rm -rf coverage.txt ${DEPLOY_IMAGE} go clean -x -i ./...
rm -rf coverage.txt $(EXECUTABLE) $(DIST) vendor
version:
@echo $(VERSION)
+183 -14
View File
@@ -1,25 +1,36 @@
# drone-scp # drone-scp
[![Build Status](https://travis-ci.org/appleboy/drone-scp.svg?branch=master)](https://travis-ci.org/appleboy/drone-scp) [![codecov](https://codecov.io/gh/appleboy/drone-scp/branch/master/graph/badge.svg)](https://codecov.io/gh/appleboy/drone-scp) [![Go Report Card](https://goreportcard.com/badge/github.com/appleboy/drone-scp)](https://goreportcard.com/report/github.com/appleboy/drone-scp) [![GoDoc](https://godoc.org/github.com/appleboy/drone-scp?status.svg)](https://godoc.org/github.com/appleboy/drone-scp) [![Build Status](http://drone.wu-boy.com/api/badges/appleboy/drone-scp/status.svg)](http://drone.wu-boy.com/appleboy/drone-scp) [![codecov](https://codecov.io/gh/appleboy/drone-scp/branch/master/graph/badge.svg)](https://codecov.io/gh/appleboy/drone-scp) [![Go Report Card](https://goreportcard.com/badge/github.com/appleboy/drone-scp)](https://goreportcard.com/report/github.com/appleboy/drone-scp) [![Docker Pulls](https://img.shields.io/docker/pulls/appleboy/drone-scp.svg)](https://hub.docker.com/r/appleboy/drone-scp/) [![](https://images.microbadger.com/badges/image/appleboy/drone-scp.svg)](https://microbadger.com/images/appleboy/drone-scp "Get your own image badge on microbadger.com")
[Drone](https://github.com/drone/drone) plugin to copy files and artifacts via SSH. [Drone](https://github.com/drone/drone) plugin to copy files and artifacts via SSH.
## Build ## Feature
Build the binary with the following commands: * [x] Support routines.
* [x] Support send files to multiple host.
* [x] Support send files to multiple target folder on host.
* [x] Support load ssh key from absolute path or raw body.
## Build or Download a binary
The pre-compiled binaries can be downloaded from [release page](https://github.com/appleboy/drone-scp/releases). Support the following OS type.
* Windows amd64/386
* Linux amd64/386
* Darwin amd64/386
With `Go` installed
```
$ go get -u -v github.com/appleboy/drone-scp
```
or build the binary with the following command:
``` ```
$ make build $ make build
``` ```
## Testing
Test the package with the following command:
```
$ make test
```
## Docker ## Docker
Build the docker image with the following commands: Build the docker image with the following commands:
@@ -29,7 +40,7 @@ $ make docker
``` ```
Please note incorrectly building the image for the correct x64 linux and with Please note incorrectly building the image for the correct x64 linux and with
GCO disabled will result in an error when running the Docker image: CGO disabled will result in an error when running the Docker image:
``` ```
docker: Error response from daemon: Container command docker: Error response from daemon: Container command
@@ -38,17 +49,167 @@ docker: Error response from daemon: Container command
## Usage ## Usage
There are three ways to send notification.
* [usage from binary](#usage-from-binary)
* [usage from docker](#usage-from-docker)
* [usage from drone ci](#usage-from-drone-ci)
<a name="usage-from-binary"></a>
### Usage from binary
#### Using public key
```bash
drone-scp --host=example.com \
--port=22 \
--username=appleboy \
--key-path="${HOME}/.ssh/id_rsa" \
--target=/home/appleboy/test \
--source=your_local_folder_path
```
#### Using password
```diff
drone-scp --host=example.com \
--port=22 \
--username=appleboy \
+ --password=xxxxxxx \
--target=/home/appleboy/test \
--source=your_local_folder_path
```
#### Using ssh-agent
Start your local ssh agent:
```bash
eval `ssh-agent -s`
```
Import your local public key `~/.ssh/id_rsa`
```bash
$ ssh-add
```
You don't need to add `--password` or `--key-path` arguments.
```bash
drone-scp --host=example.com \
--port=22 \
--username=appleboy \
--target=/home/appleboy/test \
--source=your_local_folder_path
```
#### Send multiple source or target folder and hosts
```diff
drone-scp --host=example1.com \
+ --host=example2.com \
--port=22 \
--username=appleboy \
--password= xxxxxxx
--target=/home/appleboy/test1 \
+ --target=/home/appleboy/test2 \
--source=your_local_folder_path_1
+ --source=your_local_folder_path_2
```
<a name="usage-from-docker"></a>
### Usage from docker
#### Using public key
```bash
docker run --rm \
-e SCP_HOST=example.com \
-e SCP_USERNAME=xxxxxxx \
-e SCP_PORT=22 \
-e SCP_KEY_PATH="${HOME}/.ssh/id_rsa"
-e SCP_SOURCE=SOURCE_FILE_LIST \
-e SCP_TARGET=TARGET_FOLDER_PATH \
-v $(pwd):$(pwd) \
-w $(pwd) \
appleboy/drone-scp
```
#### Using password
```diff
docker run --rm \
-e SCP_HOST=example.com \
-e SCP_USERNAME=xxxxxxx \
-e SCP_PORT=22 \
+ -e SCP_PASSWORD="xxxxxxx"
-e SCP_SOURCE=SOURCE_FILE_LIST \
-e SCP_TARGET=TARGET_FOLDER_PATH \
-v $(pwd):$(pwd) \
-w $(pwd) \
appleboy/drone-scp
```
#### Using ssh-agent
Start your local ssh agent:
```bash
eval `ssh-agent -s`
```
Import your local public key `~/.ssh/id_rsa`
```bash
$ ssh-add
```
You don't need to add `SCP_PASSWORD` or `SCP_KEY_PATH ` arguments.
```bash
docker run --rm \
-e SCP_HOST=example.com \
-e SCP_USERNAME=xxxxxxx \
-e SCP_PORT=22 \
-e SCP_SOURCE=SOURCE_FILE_LIST \
-e SCP_TARGET=TARGET_FOLDER_PATH \
-v $(pwd):$(pwd) \
-w $(pwd) \
appleboy/drone-scp
```
#### Send multiple source or target folder and hosts
```bash
docker run --rm \
-e SCP_HOST=example1.com,example2.com \
-e SCP_USERNAME=xxxxxxx \
-e SCP_PASSWORD=xxxxxxx \
-e SCP_PORT=22 \
-e SCP_SOURCE=SOURCE_FILE_LIST_1,SOURCE_FILE_LIST_2 \
-e SCP_TARGET=TARGET_FOLDER_PATH_1,TARGET_FOLDER_PATH_2 \
-v $(pwd):$(pwd) \
-w $(pwd) \
appleboy/drone-scp
```
<a name="usage-from-drone-ci"></a>
### Usage from drone ci
Execute from the working directory: Execute from the working directory:
``` ```bash
docker run --rm \ docker run --rm \
-e PLUGIN_HOST=http://example.com \ -e PLUGIN_HOST=example.com \
-e PLUGIN_USERNAME=xxxxxxx \ -e PLUGIN_USERNAME=xxxxxxx \
-e PLUGIN_PASSWORD=xxxxxxx \ -e PLUGIN_PASSWORD=xxxxxxx \
-e PLUGIN_PORT=xxxxxxx \ -e PLUGIN_PORT=xxxxxxx \
-e PLUGIN_KEY="$(cat ${HOME}/.ssh/id_rsa)" -e PLUGIN_KEY="$(cat ${HOME}/.ssh/id_rsa)"
-e PLUGIN_SOURCE=SOURCE_FILE_LIST \ -e PLUGIN_SOURCE=SOURCE_FILE_LIST \
-e PLUGIN_TARGET=TARGET_FOLDER_PATH \ -e PLUGIN_TARGET=TARGET_FOLDER_PATH \
-e PLUGIN_RM=false \
-e PLUGIN_DEBUG=false \
-e DRONE_REPO_OWNER=appleboy \ -e DRONE_REPO_OWNER=appleboy \
-e DRONE_REPO_NAME=go-hello \ -e DRONE_REPO_NAME=go-hello \
-e DRONE_COMMIT_SHA=e5e82b5eb3737205c25955dcc3dcacc839b7be52 \ -e DRONE_COMMIT_SHA=e5e82b5eb3737205c25955dcc3dcacc839b7be52 \
@@ -61,3 +222,11 @@ docker run --rm \
-w $(pwd) \ -w $(pwd) \
appleboy/drone-scp appleboy/drone-scp
``` ```
## Testing
Test the package with the following command:
```
$ make test
```
+26 -2
View File
@@ -8,6 +8,7 @@ import (
"bufio" "bufio"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"net" "net"
"os" "os"
"path/filepath" "path/filepath"
@@ -16,7 +17,7 @@ import (
"golang.org/x/crypto/ssh/agent" "golang.org/x/crypto/ssh/agent"
) )
// Contains main authority information. // MakeConfig Contains main authority information.
// User field should be a name of user on remote server (ex. john in ssh john@example.com). // User field should be a name of user on remote server (ex. john in ssh john@example.com).
// Server field should be a remote machine address (ex. example.com in ssh john@example.com) // Server field should be a remote machine address (ex. example.com in ssh john@example.com)
// Key is a path to private key on your local machine. // Key is a path to private key on your local machine.
@@ -27,10 +28,27 @@ type MakeConfig struct {
User string User string
Server string Server string
Key string Key string
KeyPath string
Port string Port string
Password string Password string
} }
// returns ssh.Signer from user you running app home path + cutted key path.
// (ex. pubkey,err := getKeyFile("/.ssh/id_rsa") )
func getKeyFile(keypath string) (ssh.Signer, error) {
buf, err := ioutil.ReadFile(keypath)
if err != nil {
return nil, err
}
pubkey, err := ssh.ParsePrivateKey(buf)
if err != nil {
return nil, err
}
return pubkey, nil
}
// connects to remote server using MakeConfig struct and returns *ssh.Session // connects to remote server using MakeConfig struct and returns *ssh.Session
func (ssh_conf *MakeConfig) connect() (*ssh.Session, error) { func (ssh_conf *MakeConfig) connect() (*ssh.Session, error) {
// auths holds the detected ssh auth methods // auths holds the detected ssh auth methods
@@ -46,6 +64,12 @@ func (ssh_conf *MakeConfig) connect() (*ssh.Session, error) {
defer sshAgent.Close() defer sshAgent.Close()
} }
if ssh_conf.KeyPath != "" {
if pubkey, err := getKeyFile(ssh_conf.KeyPath); err == nil {
auths = append(auths, ssh.PublicKeys(pubkey))
}
}
if ssh_conf.Key != "" { if ssh_conf.Key != "" {
signer, _ := ssh.ParsePrivateKey([]byte(ssh_conf.Key)) signer, _ := ssh.ParsePrivateKey([]byte(ssh_conf.Key))
auths = append(auths, ssh.PublicKeys(signer)) auths = append(auths, ssh.PublicKeys(signer))
@@ -107,7 +131,7 @@ func (ssh_conf *MakeConfig) Stream(command string) (output chan string, done cha
return outputChan, done, err return outputChan, done, err
} }
// Runs command on remote machine and returns its stdout as a string // Run command on remote machine and returns its stdout as a string
func (ssh_conf *MakeConfig) Run(command string) (outStr string, err error) { func (ssh_conf *MakeConfig) Run(command string) (outStr string, err error) {
outChan, doneChan, err := ssh_conf.Stream(command) outChan, doneChan, err := ssh_conf.Stream(command)
if err != nil { if err != nil {
Generated
+12 -8
View File
@@ -1,20 +1,24 @@
hash: d4830515599820a37217ef2806e6f9a3e7be66a417c46bb515fdae02b2e3b830 hash: 324c76f4ece1989f584ec84aab8252020da4dcbc20e38990465a9a0b7400f8ec
updated: 2016-10-19T16:23:55.991113936+08:00 updated: 2016-12-28T15:52:54.896825557+08:00
imports: imports:
- name: github.com/appleboy/com
version: c2e1fea1b771a26cb55774843ebd8955d723ee4e
subpackages:
- random
- name: github.com/joho/godotenv - name: github.com/joho/godotenv
version: 4ed13390c0acd2ff4e371e64d8b97c8954138243 version: a01a834e1654b4c9ca5b3ad05159445cc9c7ad08
subpackages: subpackages:
- autoload - autoload
- name: github.com/urfave/cli - name: github.com/urfave/cli
version: 55f715e28c46073d0e217e2ce8eb46b0b45e3db6 version: 0bdeddeeb0f650497d603c4ad7b20cfe685682f6
- name: golang.org/x/crypto - name: golang.org/x/crypto
version: c367d6eeb7c6158125f2f47e049f7eb7e251c09a version: c2f4947f41766b144bb09066e919466da5eddeae
subpackages: subpackages:
- ssh
- ssh/agent
- curve25519 - curve25519
- ed25519 - ed25519
- ed25519/internal/edwards25519 - ed25519/internal/edwards25519
- ssh
- ssh/agent
testImports: testImports:
- name: github.com/davecgh/go-spew - name: github.com/davecgh/go-spew
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9
@@ -25,6 +29,6 @@ testImports:
subpackages: subpackages:
- difflib - difflib
- name: github.com/stretchr/testify - name: github.com/stretchr/testify
version: 976c720a22c8eb4eb6a0b4348ad85ad12491a506 version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0
subpackages: subpackages:
- assert - assert
+6
View File
@@ -1,14 +1,20 @@
package: github.com/appleboy/drone-scp package: github.com/appleboy/drone-scp
import: import:
- package: github.com/joho/godotenv - package: github.com/joho/godotenv
version: ^1.0.0
subpackages: subpackages:
- autoload - autoload
- package: github.com/urfave/cli - package: github.com/urfave/cli
version: ^1.19.1
- package: golang.org/x/crypto - package: golang.org/x/crypto
subpackages: subpackages:
- ssh - ssh
- ssh/agent - ssh/agent
- package: github.com/appleboy/com
subpackages:
- random
testImport: testImport:
- package: github.com/stretchr/testify - package: github.com/stretchr/testify
version: ^1.1.4
subpackages: subpackages:
- assert - assert
+34 -15
View File
@@ -2,22 +2,28 @@ package main
import ( import (
"os" "os"
"runtime"
"github.com/joho/godotenv"
_ "github.com/joho/godotenv/autoload" _ "github.com/joho/godotenv/autoload"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
// Version for command line // Version set at compile-time
var Version string var Version = "v1.0.0-dev"
func init() {
runtime.GOMAXPROCS(runtime.NumCPU())
}
func main() { func main() {
app := cli.NewApp() app := cli.NewApp()
app.Name = "telegram plugin" app.Name = "scp plugin"
app.Usage = "telegram plugin" app.Usage = "scp plugin"
app.Action = run app.Action = run
app.Version = Version app.Version = Version
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{
cli.StringFlag{ cli.StringSliceFlag{
Name: "host", Name: "host",
Usage: "Server host", Usage: "Server host",
EnvVar: "PLUGIN_HOST,SCP_HOST", EnvVar: "PLUGIN_HOST,SCP_HOST",
@@ -44,20 +50,24 @@ func main() {
EnvVar: "PLUGIN_KEY,SCP_KEY", EnvVar: "PLUGIN_KEY,SCP_KEY",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "key-path",
Usage: "ssh private key path",
EnvVar: "PLUGIN_KEY_PATH,SCP_KEY_PATH",
},
cli.StringSliceFlag{
Name: "target", Name: "target",
Value: "/", Usage: "Target path on the server",
Usage: "Target path on the server, default to '/'", EnvVar: "PLUGIN_TARGET,SCP_TARGET",
EnvVar: "PLUGIN_TARGET",
}, },
cli.StringSliceFlag{ cli.StringSliceFlag{
Name: "source", Name: "source",
Usage: "scp file list", Usage: "scp file list",
EnvVar: "PLUGIN_SOURCE", EnvVar: "PLUGIN_SOURCE,SCP_SOURCE",
}, },
cli.BoolFlag{ cli.BoolFlag{
Name: "debug", Name: "rm",
Usage: "display message from command", Usage: "remove target folder before upload data",
EnvVar: "PLUGIN_DEBUG", EnvVar: "PLUGIN_RM,SCP_RM",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "repo.owner", Name: "repo.owner",
@@ -112,11 +122,19 @@ func main() {
Usage: "build link", Usage: "build link",
EnvVar: "DRONE_BUILD_LINK", EnvVar: "DRONE_BUILD_LINK",
}, },
cli.StringFlag{
Name: "env-file",
Usage: "source env file",
},
} }
app.Run(os.Args) app.Run(os.Args)
} }
func run(c *cli.Context) error { func run(c *cli.Context) error {
if c.String("env-file") != "" {
_ = godotenv.Load(c.String("env-file"))
}
plugin := Plugin{ plugin := Plugin{
Repo: Repo{ Repo: Repo{
Owner: c.String("repo.owner"), Owner: c.String("repo.owner"),
@@ -133,14 +151,15 @@ func run(c *cli.Context) error {
Link: c.String("build.link"), Link: c.String("build.link"),
}, },
Config: Config{ Config: Config{
Host: c.String("host"), Host: c.StringSlice("host"),
Port: c.String("port"), Port: c.String("port"),
Username: c.String("username"), Username: c.String("username"),
Password: c.String("password"), Password: c.String("password"),
Key: c.String("key"), Key: c.String("key"),
Target: c.String("target"), KeyPath: c.String("key-path"),
Target: c.StringSlice("target"),
Source: c.StringSlice("source"), Source: c.StringSlice("source"),
Debug: c.Bool("debug"), Remove: c.Bool("rm"),
}, },
} }
+95 -66
View File
@@ -9,7 +9,9 @@ import (
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"strings" "strings"
"sync"
"github.com/appleboy/com/random"
"github.com/appleboy/drone-scp/easyssh" "github.com/appleboy/drone-scp/easyssh"
) )
@@ -34,14 +36,15 @@ type (
// Config for the plugin. // Config for the plugin.
Config struct { Config struct {
Host string Host []string
Port string Port string
Username string Username string
Password string Password string
Key string Key string
Target string KeyPath string
Target []string
Source []string Source []string
Debug bool Remove bool
} }
// Plugin values. // Plugin values.
@@ -52,6 +55,8 @@ type (
} }
) )
var wg sync.WaitGroup
func trimPath(keys []string) []string { func trimPath(keys []string) []string {
var newKeys []string var newKeys []string
@@ -67,24 +72,23 @@ func trimPath(keys []string) []string {
return newKeys return newKeys
} }
func (p Plugin) log(host string, message ...interface{}) {
log.Printf("%s: %s", host, fmt.Sprintln(message...))
}
// Exec executes the plugin. // Exec executes the plugin.
func (p Plugin) Exec() error { func (p Plugin) Exec() error {
if len(p.Config.Host) == 0 || len(p.Config.Username) == 0 || (len(p.Config.Password) == 0 && len(p.Config.Key) == 0) { if len(p.Config.Host) == 0 || len(p.Config.Username) == 0 {
log.Println("missing ssh config (Host, Username, Password or Key)") return errors.New("missing ssh config (Host, Username)")
return errors.New("missing ssh config (Host, Username, Password or Key)")
} }
if len(p.Config.Source) == 0 { if len(p.Config.Source) == 0 || len(p.Config.Target) == 0 {
log.Println("missing source file list config") return errors.New("missing source or target config")
return errors.New("missing source file list config")
} }
files := trimPath(p.Config.Source) files := trimPath(p.Config.Source)
src := strings.Join(files, " ") dest := fmt.Sprintf("%s.tar", random.String(10))
dest := fmt.Sprintf("%s-%s.tar", p.Repo.Name, p.Build.Commit[:7])
// create a temporary file for the archive // create a temporary file for the archive
dir, err := ioutil.TempDir("", "") dir, err := ioutil.TempDir("", "")
@@ -95,70 +99,95 @@ func (p Plugin) Exec() error {
// run archive command // run archive command
log.Println("tar all files into " + tar) log.Println("tar all files into " + tar)
cmd := exec.Command("tar", "-cf", tar, src) args := append(append([]string{}, "-cf", tar), files...)
cmd := exec.Command("tar", args...)
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
return err return err
} }
// Create MakeConfig instance with remote username, server address and path to private key. wg.Add(len(p.Config.Host))
ssh := &easyssh.MakeConfig{ errChannel := make(chan error, 1)
Server: p.Config.Host, finished := make(chan bool, 1)
User: p.Config.Username, for _, host := range p.Config.Host {
Password: p.Config.Password, go func(host string) {
Port: p.Config.Port, // Create MakeConfig instance with remote username, server address and path to private key.
Key: p.Config.Key, ssh := &easyssh.MakeConfig{
Server: host,
User: p.Config.Username,
Password: p.Config.Password,
Port: p.Config.Port,
Key: p.Config.Key,
KeyPath: p.Config.KeyPath,
}
// Call Scp method with file you want to upload to remote server.
p.log(host, "scp file to server.")
err = ssh.Scp(tar)
// Handle errors
if err != nil {
errChannel <- err
}
for _, target := range p.Config.Target {
// remove target before upload data
if p.Config.Remove {
p.log(host, "Remove target folder:", target)
_, err := ssh.Run(fmt.Sprintf("rm -rf %s", target))
if err != nil {
errChannel <- err
}
}
// mkdir path
p.log(host, "create folder", target)
response, _ := ssh.Run(fmt.Sprintf("mkdir -p %s", target))
if response != "" {
errChannel <- errors.New(response)
}
// untar file
p.log(host, "untar file", dest)
_, err = ssh.Run(fmt.Sprintf("tar -xf %s -C %s", dest, target))
if err != nil {
errChannel <- err
}
}
// remove tar file
p.log(host, "remove file", dest)
_, err = ssh.Run(fmt.Sprintf("rm -rf %s", dest))
if err != nil {
errChannel <- err
}
wg.Done()
}(host)
} }
// Call Scp method with file you want to upload to remote server. go func() {
log.Println("scp file to remote server remote server.") wg.Wait()
err = ssh.Scp(tar) close(finished)
}()
// Handle errors select {
if err != nil { case <-finished:
log.Println(err.Error()) case err := <-errChannel:
return err if err != nil {
fmt.Println("drone-scp error: ", err)
return err
}
} }
// mkdir path fmt.Println("Successfully executed transfer data to all host.")
log.Println("create remote folder " + p.Config.Target)
response, err := ssh.Run(fmt.Sprintf("mkdir -p %s", p.Config.Target))
if p.Config.Debug {
log.Println(response)
}
if err != nil {
log.Println(err.Error())
return err
}
// untar file
log.Println("untar remote file " + dest)
response, err = ssh.Run(fmt.Sprintf("tar -xf %s -C %s", dest, p.Config.Target))
if p.Config.Debug {
log.Println(response)
}
if err != nil {
log.Println(err.Error())
return err
}
// remove tar file
log.Println("remove remote file " + dest)
response, err = ssh.Run(fmt.Sprintf("rm -rf %s", dest))
if p.Config.Debug {
log.Println(response)
}
if err != nil {
log.Println(err.Error())
return err
}
return nil return nil
} }
+146 -3
View File
@@ -3,10 +3,13 @@ package main
import ( import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"os"
"os/exec"
"os/user"
"testing" "testing"
) )
func TestMissingConfig(t *testing.T) { func TestMissingAllConfig(t *testing.T) {
var plugin Plugin var plugin Plugin
err := plugin.Exec() err := plugin.Exec()
@@ -17,7 +20,7 @@ func TestMissingConfig(t *testing.T) {
func TestMissingSSHConfig(t *testing.T) { func TestMissingSSHConfig(t *testing.T) {
plugin := Plugin{ plugin := Plugin{
Config: Config{ Config: Config{
Host: "example.com", Host: []string{"example.com"},
Username: "ubuntu", Username: "ubuntu",
}, },
} }
@@ -30,7 +33,7 @@ func TestMissingSSHConfig(t *testing.T) {
func TestMissingSourceConfig(t *testing.T) { func TestMissingSourceConfig(t *testing.T) {
plugin := Plugin{ plugin := Plugin{
Config: Config{ Config: Config{
Host: "example.com", Host: []string{"example.com"},
Username: "ubuntu", Username: "ubuntu",
Port: "443", Port: "443",
Password: "1234", Password: "1234",
@@ -55,3 +58,143 @@ func TestTrimElement(t *testing.T) {
assert.Equal(t, result, trimPath(input)) assert.Equal(t, result, trimPath(input))
} }
func TestSCPFileFromPublicKey(t *testing.T) {
if os.Getenv("SSH_AUTH_SOCK") != "" {
exec.Command("eval", "`ssh-agent -k`").Run()
}
u, err := user.Lookup("drone-scp")
if err != nil {
t.Fatalf("Lookup: %v", err)
}
plugin := Plugin{
Config: Config{
Host: []string{"localhost"},
Username: "drone-scp",
Port: "22",
KeyPath: "tests/.ssh/id_rsa",
Source: []string{"tests/a.txt", "tests/b.txt"},
Target: []string{u.HomeDir + "/test"},
},
}
err = plugin.Exec()
assert.Nil(t, err)
// check file exist
if _, err := os.Stat(u.HomeDir + "/test/tests/a.txt"); os.IsNotExist(err) {
t.Fatalf("SCP-error: %v", err)
}
if _, err := os.Stat(u.HomeDir + "/test/tests/b.txt"); os.IsNotExist(err) {
t.Fatalf("SCP-error: %v", err)
}
// Test -rm flag
plugin.Config.Source = []string{"tests/a.txt"}
plugin.Config.Remove = true
err = plugin.Exec()
assert.Nil(t, err)
// check file exist
if _, err := os.Stat(u.HomeDir + "/test/tests/b.txt"); os.IsExist(err) {
t.Fatalf("SCP-error: %v", err)
}
}
// func TestSCPFileFromSSHAgent(t *testing.T) {
// if os.Getenv("SSH_AUTH_SOCK") == "" {
// exec.Command("eval", "`ssh-agent -s`").Run()
// exec.Command("ssh-add", "tests/.ssh/id_rsa").Run()
// }
// u, err := user.Lookup("drone-scp")
// if err != nil {
// t.Fatalf("Lookup: %v", err)
// }
// plugin := Plugin{
// Config: Config{
// Host: []string{"localhost"},
// Username: "drone-scp",
// Port: "22",
// Source: []string{"tests/a.txt", "tests/b.txt"},
// Target: []string{u.HomeDir + "/test"},
// },
// }
// err = plugin.Exec()
// assert.Nil(t, err)
// }
// func TestSCPFileFromPassword(t *testing.T) {
// u, err := user.Lookup("drone-scp")
// if err != nil {
// t.Fatalf("Lookup: %v", err)
// }
// plugin := Plugin{
// Config: Config{
// Host: []string{"localhost"},
// Username: "drone-scp",
// Port: "22",
// Password: "1234",
// Source: []string{"tests/a.txt", "tests/b.txt"},
// Target: []string{u.HomeDir + "/test"},
// },
// }
// err = plugin.Exec()
// assert.Nil(t, err)
// }
func TestIncorrectPassword(t *testing.T) {
plugin := Plugin{
Config: Config{
Host: []string{"localhost"},
Username: "drone-scp",
Port: "22",
Password: "123456",
Source: []string{"tests/a.txt", "tests/b.txt"},
Target: []string{"/home"},
},
}
err := plugin.Exec()
assert.NotNil(t, err)
}
func TestNoPermissionCreateFolder(t *testing.T) {
plugin := Plugin{
Config: Config{
Host: []string{"localhost"},
Username: "drone-scp",
Port: "22",
KeyPath: "tests/.ssh/id_rsa",
Source: []string{"tests/a.txt", "tests/b.txt"},
Target: []string{"/etc/test"},
},
}
err := plugin.Exec()
assert.NotNil(t, err)
}
func TestSourceNotFound(t *testing.T) {
plugin := Plugin{
Config: Config{
Host: []string{"localhost"},
Username: "drone-scp",
Port: "22",
KeyPath: "tests/.ssh/id_rsa",
Source: []string{"tests/aa.txt", "tests/b.txt"},
Target: []string{"/test"},
},
}
err := plugin.Exec()
assert.NotNil(t, err)
}
+27
View File
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA4e2D/qPN08pzTac+a8ZmlP1ziJOXk45CynMPtva0rtK/RB26
VbfAF0hIJji7ltvnYnqCU9oFfvEM33cTn7T96+od8ib/Vz25YU8ZbstqtIskPuwC
bv3K0mAHgsviJyRD7yM+QKTbBQEgbGuW6gtbMKhiYfiIB4Dyj7AdS/fk3v26wDgz
7SHI5OBqu9bv1KhxQYdFEnU3PAtAqeccgzNpbH3eYLyGzuUxEIJlhpZ/uU2G9ppj
/cSrONVPiI8Ahi4RrlZjmP5l57/sq1ClGulyLpFcMw68kP5FikyqHpHJHRBNgU57
1y0Ph33SjBbs0haCIAcmreWEhGe+/OXnJe6VUQIDAQABAoIBAH97emORIm9DaVSD
7mD6DqA7c5m5Tmpgd6eszU08YC/Vkz9oVuBPUwDQNIX8tT0m0KVs42VVPIyoj874
bgZMJoucC1G8V5Bur9AMxhkShx9g9A7dNXJTmsKilRpk2TOk7wBdLp9jZoKoZBdJ
jlp6FfaazQjjKD6zsCsMATwAoRCBpBNsmT6QDN0n0bIgY0tE6YGQaDdka0dAv68G
R0VZrcJ9voT6+f+rgJLoojn2DAu6iXaM99Gv8FK91YCymbQlXXgrk6CyS0IHexN7
V7a3k767KnRbrkqd3o6JyNun/CrUjQwHs1IQH34tvkWScbseRaFehcAm6mLT93RP
muauvMECgYEA9AXGtfDMse0FhvDPZx4mx8x+vcfsLvDHcDLkf/lbyPpu97C27b/z
ia07bu5TAXesUZrWZtKA5KeRE5doQSdTOv1N28BEr8ZwzDJwfn0DPUYUOxsN2iIy
MheO5A45Ko7bjKJVkZ61Mb1UxtqCTF9mqu9R3PBdJGthWOd+HUvF460CgYEA7QRf
Z8+vpGA+eSuu29e0xgRKnRzed5zXYpcI4aERc3JzBgO4Z0er9G8l66OWVGdMfpe6
CBajC5ToIiT8zqoYxXwqJgN+glir4gJe3mm8J703QfArZiQrdk0NTi5bY7+vLLG/
knTrtpdsKih6r3kjhuPPaAsIwmMxIydFvATKjLUCgYEAh/y4EihRSk5WKC8GxeZt
oiZ58vT4z+fqnMIfyJmD5up48JuQNcokw/LADj/ODiFM7GUnWkGxBrvDA3H67WQm
49bJjs8E+BfUQFdTjYnJRlpJZ+7Zt1gbNQMf5ENw5CCchTDqEq6pN0DVf8PBnSIF
KvkXW9KvdV5J76uCAn15mDkCgYA1y8dHzbjlCz9Cy2pt1aDfTPwOew33gi7U3skS
RTerx29aDyAcuQTLfyrROBkX4TZYiWGdEl5Bc7PYhCKpWawzrsH2TNa7CRtCOh2E
R+V/84+GNNf04ALJYCXD9/ugQVKmR1XfDRCvKeFQFE38Y/dvV2etCswbKt5tRy2p
xkCe/QKBgQCkLqafD4S20YHf6WTp3jp/4H/qEy2X2a8gdVVBi1uKkGDXr0n+AoVU
ib4KbP5ovZlrjL++akMQ7V2fHzuQIFWnCkDA5c2ZAqzlM+ZN+HRG7gWur7Bt4XH1
7XC9wlRna4b3Ln8ew3q1ZcBjXwD4ppbTlmwAfQIaZTGJUgQbdsO9YA==
-----END RSA PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDh7YP+o83TynNNpz5rxmaU/XOIk5eTjkLKcw+29rSu0r9EHbpVt8AXSEgmOLuW2+dieoJT2gV+8QzfdxOftP3r6h3yJv9XPblhTxluy2q0iyQ+7AJu/crSYAeCy+InJEPvIz5ApNsFASBsa5bqC1swqGJh+IgHgPKPsB1L9+Te/brAODPtIcjk4Gq71u/UqHFBh0USdTc8C0Cp5xyDM2lsfd5gvIbO5TEQgmWGln+5TYb2mmP9xKs41U+IjwCGLhGuVmOY/mXnv+yrUKUa6XIukVwzDryQ/kWKTKoekckdEE2BTnvXLQ+HfdKMFuzSFoIgByat5YSEZ7785ecl7pVR drone-scp@localhost
View File
View File
+13
View File
@@ -0,0 +1,13 @@
#!/bin/sh
if [ ! -f "/etc/ssh/ssh_host_rsa_key" ]; then
# generate fresh rsa key
ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa
fi
if [ ! -f "/etc/ssh/ssh_host_dsa_key" ]; then
# generate fresh dsa key
ssh-keygen -f /etc/ssh/ssh_host_dsa_key -N '' -t dsa
fi
exec "$@"