Compare commits

...

53 Commits

Author SHA1 Message Date
Bo-Yi.Wu 0745e13d39 test: refactor plugin_test.go file and optimize code
- Remove the `TestSetPasswordAndKey` function from `plugin_test.go`

Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2023-04-09 17:06:03 +08:00
Bo-Yi.Wu f1301199ca fix: refactor error handling and panic statements
- Remove error message for setting password and key at the same time
- Replace `errMissingHost` error check with a panic statement

ref: https://github.com/appleboy/scp-action/issues/86

Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2023-04-09 17:03:48 +08:00
Bo-Yi Wu 6fd87e0460 refactor: add dereference flag (#169)
- Add a `--dereference` flag to use with tar

fix https://github.com/appleboy/drone-scp/issues/112
2023-04-09 15:49:32 +08:00
Bo-Yi.Wu cf09357b85 build: refactor buildArgs function argument
- Change argument from `-xf` to `-zxf` in `buildArgs` function

Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2023-04-09 13:39:39 +08:00
Bo-Yi Wu 9bfb71b9ef build: compress build artifacts using gzip (#168)
- Change the compression format from `tar` to `tar.gz`
- Replace the flag `-cf` with `-zcf` in the `buildArgs` function

fix https://github.com/appleboy/drone-scp/issues/123
2023-04-09 12:38:12 +08:00
Bo-Yi.Wu 9d8fc691c1 refactor: refactor testing functions for consistency
- Replace `trimPath` with `trimValues` in `TestTrimElement` function

Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2023-04-09 12:14:31 +08:00
Bo-Yi Wu 244d28d58a test: check ignore list function working or not. (#167)
Modify the assert function call to use trimValues instead of trimPath
2023-04-09 12:12:53 +08:00
Bo-Yi.Wu 42d07ba823 test: refactor test function names for clarity
- Change function name from `trimPath` to `trimValues` in `TestTrimElement` test

Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2023-04-09 09:51:08 +08:00
Bo-Yi.Wu dd5f3b500f refactor: refactor configuration file handling
- Remove the `trimPath` function
- Change `trimPath(p.Config.Source)` to `trimValues(p.Config.Source)`

Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2023-04-09 09:50:39 +08:00
Bo-Yi.Wu 95b01590dc refactor: refactor host configuration handling
- Replace the iteration over `p.Config.Host` with `trimValues(p.Config.Host)`
- Replace `len(p.Config.Host)` with `len(hosts)`
- Replace iteration over `p.Config.Host` with `for _, host := range hosts`
- Add `trimValues` function to trim spaces and empty values of a string slice

Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2023-04-09 09:13:21 +08:00
Bo-Yi.Wu c42b26f044 build: update build process for cross-platform compatibility
- Update the container to `golang:1.20-alpine`
- Add a new file `.goreleaser.yaml`
- Modify `.goreleaser.yaml` to include additional builds and flags for cross-compiling and building the binary
- Add a new checksum file to the release archives

Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2023-04-09 08:16:45 +08:00
Bo-Yi Wu 244b0a9e58 refactor: handling functions for cross-platform compatibility (#166)
- Change the `rmcmd` and `mkdircmd` functions to accept an OS parameter
- Remove `command_windows.go` file
- Modify `removeDestFile` and `Exec` functions to use the OS parameter
- Add OS detection logic to `removeAllDestFile` and `Exec` functions
- Modify `TestRemoveDestFile` function to use the OS parameter

fix https://github.com/appleboy/drone-scp/pull/119
2023-04-09 08:14:05 +08:00
Bo-Yi.Wu 8b578d1df8 chore: refactor Dockerfile for improved security
- Remove `.hadolint.yaml` from the project
- Add open container labels to the Dockerfile

Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2023-04-09 06:52:54 +08:00
Bo-Yi.Wu ea5c04f515 ci: update setup-go action version in workflows
- Update `setup-go` action to version 4 in 3 workflows

Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2023-04-09 06:50:46 +08:00
Bo-Yi Wu f4da147fda chore: upgrade dependencies in go.mod file
- Delete `.github/workflows/binary.yml` file.
- Upgrade `github.com/appleboy/com` from `v0.1.6` to `v0.1.7` in `go.mod`.
- Upgrade `github.com/fatih/color` from `v1.14.1` to `v1.15.0` in `go.mod`.
- Upgrade `github.com/urfave/cli/v2` from `v2.24.4` to `v2.25.1` in `go.mod`.
- Upgrade `golang.org/x/crypto` from `v0.6.0` to `v0.8.0` in `go.mod`.
- Upgrade `github.com/mattn/go-isatty` from `v0.0.17` to `v0.0.18` in `go.mod`.

Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2023-04-08 11:18:30 +08:00
dependabot[bot] 54bc4f9c50 chore(deps): bump github.com/stretchr/testify from 1.8.1 to 1.8.2 (#157)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-03 23:20:52 +08:00
Bo-Yi Wu 2f24f092e0 chore(docker): update plugin name 2023-02-27 13:58:56 +08:00
Bo-Yi Wu c66c78f88f fix: lint error 2023-02-27 13:24:12 +08:00
Bo-Yi Wu 9723eea384 chore(CI): build docker image with multiple platform 2023-02-27 11:56:42 +08:00
dependabot[bot] 14ec2704bd chore(deps): bump github.com/urfave/cli/v2 from 2.24.3 to 2.24.4 (#156)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-23 13:15:47 +08:00
dependabot[bot] a1482e89a3 chore(deps): bump docker/build-push-action from 3 to 4 (#154)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-12 14:26:12 +08:00
Bo-Yi.Wu 9bf9ed00a4 chore(deps): upgrade go module
Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2023-02-12 09:36:06 +08:00
Bo-Yi Wu 6bc14e020b chore(deps): upgrade go package 2023-02-03 17:22:02 +08:00
Bo-Yi Wu c309cf901d chore(command): support windows (#153) 2023-02-03 17:12:57 +08:00
Bo-Yi Wu 4c5df18366 chore(deps): upgrade action package 2023-02-02 13:43:54 +08:00
Bo-Yi Wu 5ec7c1ddf8 chore(deps): upgrade go package 2023-02-02 13:42:33 +08:00
Bo-Yi Wu 1c9314ed83 chore(CI): latest tag for linux and amd64 2023-01-03 10:33:55 +08:00
Bo-Yi.Wu 5672c1219f chore(CI): add strategy in docker build
Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2023-01-01 15:16:45 +08:00
Bo-Yi.Wu 9d29c82de6 docs: add new badge
Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2022-12-29 21:31:02 +08:00
Bo-Yi.Wu 1f8d333b42 chore(CI): add hadolint config
Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2022-12-29 21:28:29 +08:00
Bo-Yi.Wu 50338d5bb1 chore(deps): update
Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2022-12-29 21:16:31 +08:00
teutates 6d8c114979 feat(tar): add unlink-first flag (#141) 2022-12-29 21:15:21 +08:00
Bo-Yi.Wu c5c8b4021f chore(cli): add alias
Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2022-12-29 21:13:47 +08:00
Bo-Yi.Wu 4a81a55a53 chore(lint): fix warning.
Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2022-12-29 21:10:16 +08:00
Bo-Yi.Wu 9aef844da2 chore(CI): remove drone config
Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2022-12-29 21:08:06 +08:00
Bo-Yi.Wu 6a4996cd63 chore(CI): update makefile
Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
2022-12-29 21:05:12 +08:00
Bo-Yi Wu 5053fc6aee chore(CI): migrate to GitHub Actions 2022-12-29 16:08:32 +08:00
Bo-Yi Wu 55cde9a13c fix: missing installed version 2022-06-15 21:51:42 +08:00
Bo-Yi Wu 7a31e10541 chore(go1.18): build tag 2022-06-15 15:29:09 +08:00
Bo-Yi Wu 8f4c7fa15b fix(ssh): OpenSSH 8.8+ RSA keys incompatibility (#136) 2022-06-15 15:28:13 +08:00
Bo-Yi Wu 8ed049422b chore(binary): unsupported GOOS/GOARCH pair darwin/386
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2021-10-23 18:43:22 +08:00
Bo-Yi Wu 731b24356e chore(lint): check removeAllDestFile
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2021-10-23 18:30:17 +08:00
Bo-Yi Wu 2d05265e3d chore(deploy): disbale testing
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2021-10-23 18:28:09 +08:00
Bo-Yi Wu 6ddf21aca4 chore(action): wrong variable name
see https://github.com/appleboy/scp-action/issues/30

Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2021-10-23 18:23:13 +08:00
Bo-Yi Wu 8c5cba51c2 chore(go): upgrade go module
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2021-10-23 18:17:23 +08:00
Bo-Yi Wu 1b33947d29 chore: upgrade to go.16
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2021-06-18 08:52:35 +08:00
Bo-Yi Wu 35f7b2f6af chore: upgrade to go1.15
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2020-09-25 22:13:34 +08:00
Bo-Yi Wu f0867af189 chore: remove auto load .env file
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2020-06-15 15:55:32 +08:00
Bo-Yi Wu 4457897da5 chore: Support UseInsecureCipher (#115) 2020-05-24 14:17:43 +08:00
Bo-Yi Wu 6d6124e8d8 docs: add fingerprint 2020-05-21 23:13:26 +08:00
Bo-Yi Wu f4fff01bdb chore: missing Ciphers in removeAllDestFile 2020-05-21 23:09:53 +08:00
Bo-Yi Wu ac8ff855ae chore: update ssh server 2020-05-21 23:09:10 +08:00
Bo-Yi Wu 2ff51f00ff chore: support Fingerprint (#114) 2020-05-21 23:08:17 +08:00
29 changed files with 1012 additions and 1104 deletions
-16
View File
@@ -1,16 +0,0 @@
local pipeline = import 'pipeline.libsonnet';
local name = 'drone-scp';
[
pipeline.test,
pipeline.build(name, 'linux', 'amd64'),
pipeline.build(name, 'linux', 'arm64'),
pipeline.build(name, 'linux', 'arm'),
pipeline.release,
pipeline.notifications(depends_on=[
'linux-amd64',
'linux-arm64',
'linux-arm',
'release-binary',
]),
]
-365
View File
@@ -1,365 +0,0 @@
---
kind: pipeline
name: testing
platform:
os: linux
arch: amd64
steps:
- name: vet
pull: always
image: golang:1.14
commands:
- make vet
volumes:
- name: gopath
path: /go
- name: lint
pull: always
image: golang:1.14
commands:
- make lint
volumes:
- name: gopath
path: /go
- name: misspell
pull: always
image: golang:1.14
commands:
- make misspell-check
volumes:
- name: gopath
path: /go
- name: test
pull: always
image: golang:1.14-alpine
commands:
- apk add git make curl perl bash build-base zlib-dev ucl-dev
- make ssh-server
- make test
- make coverage
volumes:
- name: gopath
path: /go
- name: codecov
pull: always
image: robertstettner/drone-codecov
settings:
token:
from_secret: codecov_token
volumes:
- name: gopath
temp: {}
---
kind: pipeline
name: linux-amd64
platform:
os: linux
arch: amd64
steps:
- name: build-push
pull: always
image: golang:1.14
commands:
- "go build -v -ldflags '-X main.build=${DRONE_BUILD_NUMBER}' -a -o release/linux/amd64/drone-scp"
environment:
CGO_ENABLED: 0
when:
event:
exclude:
- tag
- name: build-tag
pull: always
image: golang:1.14
commands:
- "go build -v -ldflags '-X main.version=${DRONE_TAG##v} -X main.build=${DRONE_BUILD_NUMBER}' -a -o release/linux/amd64/drone-scp"
environment:
CGO_ENABLED: 0
when:
event:
- tag
- name: executable
pull: always
image: golang:1.14
commands:
- ./release/linux/amd64/drone-scp --help
- name: dryrun
pull: always
image: plugins/docker:linux-amd64
settings:
cache_from: appleboy/drone-scp
dockerfile: docker/Dockerfile.linux.amd64
dry_run: true
repo: appleboy/drone-scp
tags: linux-amd64
when:
event:
- pull_request
- name: publish
pull: always
image: plugins/docker:linux-amd64
settings:
auto_tag: true
auto_tag_suffix: linux-amd64
cache_from: appleboy/drone-scp
daemon_off: false
dockerfile: docker/Dockerfile.linux.amd64
password:
from_secret: docker_password
repo: appleboy/drone-scp
username:
from_secret: docker_username
when:
event:
exclude:
- pull_request
trigger:
ref:
- refs/heads/master
- "refs/pull/**"
- "refs/tags/**"
depends_on:
- testing
---
kind: pipeline
name: linux-arm64
platform:
os: linux
arch: arm64
steps:
- name: build-push
pull: always
image: golang:1.14
commands:
- "go build -v -ldflags '-X main.build=${DRONE_BUILD_NUMBER}' -a -o release/linux/arm64/drone-scp"
environment:
CGO_ENABLED: 0
when:
event:
exclude:
- tag
- name: build-tag
pull: always
image: golang:1.14
commands:
- "go build -v -ldflags '-X main.version=${DRONE_TAG##v} -X main.build=${DRONE_BUILD_NUMBER}' -a -o release/linux/arm64/drone-scp"
environment:
CGO_ENABLED: 0
when:
event:
- tag
- name: executable
pull: always
image: golang:1.14
commands:
- ./release/linux/arm64/drone-scp --help
- name: dryrun
pull: always
image: plugins/docker:linux-arm64
settings:
cache_from: appleboy/drone-scp
dockerfile: docker/Dockerfile.linux.arm64
dry_run: true
repo: appleboy/drone-scp
tags: linux-arm64
when:
event:
- pull_request
- name: publish
pull: always
image: plugins/docker:linux-arm64
settings:
auto_tag: true
auto_tag_suffix: linux-arm64
cache_from: appleboy/drone-scp
daemon_off: false
dockerfile: docker/Dockerfile.linux.arm64
password:
from_secret: docker_password
repo: appleboy/drone-scp
username:
from_secret: docker_username
when:
event:
exclude:
- pull_request
trigger:
ref:
- refs/heads/master
- "refs/pull/**"
- "refs/tags/**"
depends_on:
- testing
---
kind: pipeline
name: linux-arm
platform:
os: linux
arch: arm
steps:
- name: build-push
pull: always
image: golang:1.14
commands:
- "go build -v -ldflags '-X main.build=${DRONE_BUILD_NUMBER}' -a -o release/linux/arm/drone-scp"
environment:
CGO_ENABLED: 0
when:
event:
exclude:
- tag
- name: build-tag
pull: always
image: golang:1.14
commands:
- "go build -v -ldflags '-X main.version=${DRONE_TAG##v} -X main.build=${DRONE_BUILD_NUMBER}' -a -o release/linux/arm/drone-scp"
environment:
CGO_ENABLED: 0
when:
event:
- tag
- name: executable
pull: always
image: golang:1.14
commands:
- ./release/linux/arm/drone-scp --help
- name: dryrun
pull: always
image: plugins/docker:linux-arm
settings:
cache_from: appleboy/drone-scp
dockerfile: docker/Dockerfile.linux.arm
dry_run: true
repo: appleboy/drone-scp
tags: linux-arm
when:
event:
- pull_request
- name: publish
pull: always
image: plugins/docker:linux-arm
settings:
auto_tag: true
auto_tag_suffix: linux-arm
cache_from: appleboy/drone-scp
daemon_off: false
dockerfile: docker/Dockerfile.linux.arm
password:
from_secret: docker_password
repo: appleboy/drone-scp
username:
from_secret: docker_username
when:
event:
exclude:
- pull_request
trigger:
ref:
- refs/heads/master
- "refs/pull/**"
- "refs/tags/**"
depends_on:
- testing
---
kind: pipeline
name: release-binary
platform:
os: linux
arch: amd64
steps:
- name: build-all-binary
pull: always
image: golang:1.14
commands:
- make release
when:
event:
- tag
- name: deploy-all-binary
pull: always
image: plugins/github-release
settings:
api_key:
from_secret: github_release_api_key
files:
- "dist/release/*"
when:
event:
- tag
trigger:
ref:
- "refs/tags/**"
depends_on:
- testing
---
kind: pipeline
name: notifications
platform:
os: linux
arch: amd64
steps:
- name: manifest
pull: always
image: plugins/manifest
settings:
ignore_missing: true
password:
from_secret: docker_password
spec: docker/manifest.tmpl
username:
from_secret: docker_username
trigger:
ref:
- refs/heads/master
- "refs/tags/**"
depends_on:
- linux-amd64
- linux-arm64
- linux-arm
- release-binary
...
-42
View File
@@ -1,42 +0,0 @@
# unifying the coding style for different editors and IDEs => editorconfig.org
; indicate this is the root of the project
root = true
###########################################################
; common
###########################################################
[*]
charset = utf-8
end_of_line = LF
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2
###########################################################
; make
###########################################################
[Makefile]
indent_style = tab
[makefile]
indent_style = tab
###########################################################
; markdown
###########################################################
[*.md]
trim_trailing_whitespace = false
###########################################################
; golang
###########################################################
[*.go]
indent_style = tab
+13
View File
@@ -0,0 +1,13 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: ['https://www.paypal.me/appleboy46']
+10
View File
@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
- package-ecosystem: gomod
directory: /
schedule:
interval: weekly
+54
View File
@@ -0,0 +1,54 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '41 23 * * 6'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'go' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
+77
View File
@@ -0,0 +1,77 @@
name: Docker Image
on:
push:
branches:
- master
tags:
- 'v*'
pull_request:
branches:
- 'master'
jobs:
build-docker:
runs-on: ubuntu-latest
steps:
- name: Setup go
uses: actions/setup-go@v4
with:
go-version: '^1'
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Build binary
run : |
make build_linux_amd64
make build_linux_arm
make build_linux_arm64
-
name: Set up QEMU
uses: docker/setup-qemu-action@v2
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
-
name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
-
name: Docker meta
id: docker-meta
uses: docker/metadata-action@v4
with:
images: |
${{ github.repository }}
ghcr.io/${{ github.repository }}
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
-
name: Build and push
uses: docker/build-push-action@v4
with:
context: .
platforms: linux/amd64,linux/arm,linux/arm64
file: docker/Dockerfile
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.docker-meta.outputs.tags }}
labels: ${{ steps.docker-meta.outputs.labels }}
+35
View File
@@ -0,0 +1,35 @@
name: Goreleaser
on:
push:
tags:
- '*'
permissions:
contents: write
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
-
name: Setup go
uses: actions/setup-go@v4
with:
go-version: '^1'
-
name: Run GoReleaser
uses: goreleaser/goreleaser-action@v4
with:
# either 'goreleaser' (default) or 'goreleaser-pro'
distribution: goreleaser
version: latest
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+45
View File
@@ -0,0 +1,45 @@
name: Lint and Testing
on:
push:
pull_request:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Setup go
uses: actions/setup-go@v4
with:
go-version: '^1'
- name: Checkout repository
uses: actions/checkout@v3
- name: Setup golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: latest
args: --verbose
- uses: hadolint/hadolint-action@v3.1.0
name: hadolint for Dockerfile
with:
dockerfile: docker/Dockerfile
testing:
runs-on: ubuntu-latest
container: golang:1.20-alpine
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: setup sshd server
run: |
apk add git make curl perl bash build-base zlib-dev ucl-dev
make ssh-server
- name: testing
run: |
make test
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
+84
View File
@@ -0,0 +1,84 @@
before:
hooks:
- go mod tidy
builds:
- env:
- CGO_ENABLED=0
goos:
- darwin
- linux
- windows
- freebsd
goarch:
- amd64
- arm
- arm64
goarm:
- "5"
- "6"
- "7"
ignore:
- goos: darwin
goarch: arm
- goos: darwin
goarch: ppc64le
- goos: darwin
goarch: s390x
- goos: windows
goarch: ppc64le
- goos: windows
goarch: s390x
- goos: windows
goarch: arm
goarm: "5"
- goos: windows
goarch: arm
goarm: "6"
- goos: windows
goarch: arm
goarm: "7"
- goos: windows
goarch: arm64
- goos: freebsd
goarch: ppc64le
- goos: freebsd
goarch: s390x
- goos: freebsd
goarch: arm
goarm: "5"
- goos: freebsd
goarch: arm
goarm: "6"
- goos: freebsd
goarch: arm
goarm: "7"
- goos: freebsd
goarch: arm64
flags:
- -trimpath
ldflags:
- -s -w
- -X main.Version={{.Version}}
binary: >-
{{ .ProjectName }}-
{{- if .IsSnapshot }}{{ .Branch }}-
{{- else }}{{- .Version }}-{{ end }}
{{- .Os }}-
{{- if eq .Arch "amd64" }}amd64
{{- else if eq .Arch "amd64_v1" }}amd64
{{- else if eq .Arch "386" }}386
{{- else }}{{ .Arch }}{{ end }}
{{- if .Arm }}-{{ .Arm }}{{ end }}
no_unique_dist_dir: true
archives:
- format: binary
name_template: "{{ .Binary }}"
allow_different_binary_count: true
checksum:
name_template: 'checksums.txt'
snapshot:
name_template: "{{ incpatch .Version }}"
-25
View File
@@ -1,25 +0,0 @@
ignoreGeneratedHeader = false
severity = "warning"
confidence = 0.8
errorCode = 1
warningCode = 1
[rule.blank-imports]
[rule.context-as-argument]
[rule.context-keys-type]
[rule.dot-imports]
[rule.error-return]
[rule.error-strings]
[rule.error-naming]
[rule.exported]
[rule.if-return]
[rule.increment-decrement]
[rule.var-naming]
[rule.var-declaration]
[rule.package-comments]
[rule.range]
[rule.receiver-naming]
[rule.time-naming]
[rule.unexported-return]
[rule.indent-error-flow]
[rule.errorf]
+6
View File
@@ -207,6 +207,9 @@ key
passphrase passphrase
: The purpose of the passphrase is usually to encrypt the private key. : The purpose of the passphrase is usually to encrypt the private key.
fingerprint
: fingerprint SHA256 of the host public key, default is to skip verification
target target
: folder path of target host : folder path of target host
@@ -255,6 +258,9 @@ proxy_key_path
proxy_passphrase proxy_passphrase
: The purpose of the passphrase is usually to encrypt the private key. : The purpose of the passphrase is usually to encrypt the private key.
proxy_fingerprint
: fingerprint SHA256 of the host public key, default is to skip verification
## Template Reference ## Template Reference
repo.owner repo.owner
+96 -68
View File
@@ -1,17 +1,19 @@
DIST := dist DIST := dist
EXECUTABLE := drone-scp EXECUTABLE := drone-scp
GOFMT ?= gofmt "-s" GOFMT ?= gofumpt -l
DIST := dist
DIST_DIRS := $(DIST)/binaries $(DIST)/release
GO ?= go GO ?= go
SHASUM ?= shasum -a 256
GOFILES := $(shell find . -name "*.go" -type f)
HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" )
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
XGO_VERSION := go-1.19.x
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11
# for dockerhub LINUX_ARCHS ?= linux/amd64,linux/arm64
DEPLOY_ACCOUNT := appleboy DARWIN_ARCHS ?= darwin-10.12/amd64,darwin-10.12/arm64
DEPLOY_IMAGE := $(EXECUTABLE) WINDOWS_ARCHS ?= windows/*
TARGETS ?= linux darwin windows
ARCHS ?= amd64 386
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)
@@ -19,77 +21,68 @@ else
EXTLDFLAGS = EXTLDFLAGS =
endif endif
ifeq ($(HAS_GO), GO)
GOPATH ?= $(shell $(GO) env GOPATH)
export PATH := $(GOPATH)/bin:$(PATH)
CGO_EXTRA_CFLAGS := -DSQLITE_MAX_VARIABLE_NUMBER=32766
CGO_CFLAGS ?= $(shell $(GO) env CGO_CFLAGS) $(CGO_EXTRA_CFLAGS)
endif
ifeq ($(OS), Windows_NT)
GOFLAGS := -v -buildmode=exe
EXECUTABLE ?= $(EXECUTABLE).exe
else ifeq ($(OS), Windows)
GOFLAGS := -v -buildmode=exe
EXECUTABLE ?= $(EXECUTABLE).exe
else
GOFLAGS := -v
EXECUTABLE ?= $(EXECUTABLE)
endif
ifneq ($(DRONE_TAG),) ifneq ($(DRONE_TAG),)
VERSION ?= $(DRONE_TAG) VERSION ?= $(DRONE_TAG)
else else
VERSION ?= $(shell git describe --tags --always || git rev-parse --short HEAD) VERSION ?= $(shell git describe --tags --always || git rev-parse --short HEAD)
endif endif
TAGS ?=
LDFLAGS ?= -X 'main.Version=$(VERSION)'
all: build all: build
fmt: fmt:
$(GOFMT) -w $(SOURCES) @hash gofumpt > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) install mvdan.cc/gofumpt; \
fi
$(GOFMT) -w $(GOFILES)
vet: vet:
$(GO) vet ./... $(GO) vet ./...
lint:
@hash revive > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) get -u github.com/mgechev/revive; \
fi
revive -config .revive.toml ./... || exit 1
.PHONY: misspell-check
misspell-check:
@hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) get -u github.com/client9/misspell/cmd/misspell; \
fi
misspell -error $(SOURCES)
.PHONY: misspell
misspell:
@hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) get -u github.com/client9/misspell/cmd/misspell; \
fi
misspell -w $(SOURCES)
.PHONY: fmt-check .PHONY: fmt-check
fmt-check: fmt-check:
@diff=$$($(GOFMT) -d $(SOURCES)); \ @hash gofumpt > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) install mvdan.cc/gofumpt; \
fi
@diff=$$($(GOFMT) -d $(GOFILES)); \
if [ -n "$$diff" ]; then \ if [ -n "$$diff" ]; then \
echo "Please run 'make fmt' and commit the result:"; \ echo "Please run 'make fmt' and commit the result:"; \
echo "$${diff}"; \ echo "$${diff}"; \
exit 1; \ exit 1; \
fi; fi;
test: fmt-check test:
@$(GO) test -v -cover -coverprofile coverage.txt ./... && echo "\n==>\033[32m Ok\033[m\n" || exit 1 @$(GO) test -v -cover -coverprofile coverage.txt ./... && echo "\n==>\033[32m Ok\033[m\n" || exit 1
install: $(SOURCES) install: $(GOFILES)
$(GO) install -v -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' $(GO) install -v -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)'
build: $(EXECUTABLE) build: $(EXECUTABLE)
$(EXECUTABLE): $(SOURCES) $(EXECUTABLE): $(GOFILES)
$(GO) build -v -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' -o $@ $(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="$(ARCHS)" -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;)
build_linux_amd64: build_linux_amd64:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GO) build -a -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' -o release/linux/amd64/$(DEPLOY_IMAGE) CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GO) build -a -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' -o release/linux/amd64/$(DEPLOY_IMAGE)
@@ -102,37 +95,72 @@ build_linux_arm64:
build_linux_arm: build_linux_arm:
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 $(GO) build -a -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' -o release/linux/arm/$(DEPLOY_IMAGE) CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 $(GO) build -a -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' -o release/linux/arm/$(DEPLOY_IMAGE)
docker_image:
docker build -t $(DEPLOY_ACCOUNT)/$(DEPLOY_IMAGE) .
docker: docker_image
docker_deploy:
ifeq ($(tag),)
@echo "Usage: make $@ tag=<tag>"
@exit 1
endif
# deploy image
docker tag $(DEPLOY_ACCOUNT)/$(DEPLOY_IMAGE):latest $(DEPLOY_ACCOUNT)/$(DEPLOY_IMAGE):$(tag)
docker push $(DEPLOY_ACCOUNT)/$(DEPLOY_IMAGE):$(tag)
ssh-server: ssh-server:
adduser -h /home/drone-scp -s /bin/bash -D -S drone-scp adduser -h /home/drone-scp -s /bin/sh -D -S drone-scp
echo drone-scp:1234 | chpasswd echo drone-scp:1234 | chpasswd
mkdir -p /home/drone-scp/.ssh mkdir -p /home/drone-scp/.ssh
chmod 700 /home/drone-scp/.ssh chmod 700 /home/drone-scp/.ssh
cat tests/.ssh/id_rsa.pub >> /home/drone-scp/.ssh/authorized_keys cat tests/.ssh/id_rsa.pub >> /home/drone-scp/.ssh/authorized_keys
cat tests/.ssh/test.pub >> /home/drone-scp/.ssh/authorized_keys cat tests/.ssh/test.pub >> /home/drone-scp/.ssh/authorized_keys
chmod 600 /home/drone-scp/.ssh/authorized_keys
chown -R drone-scp /home/drone-scp/.ssh chown -R drone-scp /home/drone-scp/.ssh
# install ssh and start server
apk add --update openssh openrc apk add --update openssh openrc
rm -rf /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_dsa_key rm -rf /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_dsa_key
sed -i 's/^#PubkeyAuthentication yes/PubkeyAuthentication yes/g' /etc/ssh/sshd_config
sed -i 's/AllowTcpForwarding no/AllowTcpForwarding yes/g' /etc/ssh/sshd_config sed -i 's/AllowTcpForwarding no/AllowTcpForwarding yes/g' /etc/ssh/sshd_config
./tests/entrypoint.sh /usr/sbin/sshd -D & ./tests/entrypoint.sh /usr/sbin/sshd -D &
coverage: coverage:
sed -i '/main.go/d' coverage.txt sed -i '/main.go/d' coverage.txt
.PHONY: deps-backend
deps-backend:
$(GO) mod download
$(GO) install $(GXZ_PAGAGE)
$(GO) install $(XGO_PACKAGE)
.PHONY: release
release: release-linux release-darwin release-windows release-copy release-compress release-check
$(DIST_DIRS):
mkdir -p $(DIST_DIRS)
.PHONY: release-windows
release-windows: | $(DIST_DIRS)
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets '$(WINDOWS_ARCHS)' -out $(EXECUTABLE)-$(VERSION) .
ifeq ($(CI),true)
cp -r /build/* $(DIST)/binaries/
endif
.PHONY: release-linux
release-linux: | $(DIST_DIRS)
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets '$(LINUX_ARCHS)' -out $(EXECUTABLE)-$(VERSION) .
ifeq ($(CI),true)
cp -r /build/* $(DIST)/binaries/
endif
.PHONY: release-darwin
release-darwin: | $(DIST_DIRS)
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets '$(DARWIN_ARCHS)' -out $(EXECUTABLE)-$(VERSION) .
ifeq ($(CI),true)
cp -r /build/* $(DIST)/binaries/
endif
.PHONY: release-copy
release-copy: | $(DIST_DIRS)
cd $(DIST); for file in `find . -type f -name "*"`; do cp $${file} ./release/; done;
.PHONY: release-check
release-check: | $(DIST_DIRS)
cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "checksumming $${file}" && $(SHASUM) `echo $${file} | sed 's/^..//'` > $${file}.sha256; done;
.PHONY: release-compress
release-compress: | $(DIST_DIRS)
cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "compressing $${file}" && $(GO) run $(GXZ_PAGAGE) -k -9 $${file}; done;
clean: clean:
$(GO) clean -x -i ./... $(GO) clean -x -i ./...
rm -rf coverage.txt $(EXECUTABLE) $(DIST) rm -rf coverage.txt $(EXECUTABLE) $(DIST)
version:
@echo $(VERSION)
+1 -2
View File
@@ -1,11 +1,10 @@
# drone-scp # drone-scp
[![GoDoc](https://godoc.org/github.com/appleboy/drone-scp?status.svg)](https://godoc.org/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](https://cloud.drone.io/api/badges/appleboy/drone-scp/status.svg)](https://cloud.drone.io/appleboy/drone-scp) [![Lint and Testing](https://github.com/appleboy/drone-scp/actions/workflows/lint.yml/badge.svg)](https://github.com/appleboy/drone-scp/actions/workflows/lint.yml)
[![codecov](https://codecov.io/gh/appleboy/drone-scp/branch/master/graph/badge.svg)](https://codecov.io/gh/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) [![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/) [![Docker Pulls](https://img.shields.io/docker/pulls/appleboy/drone-scp.svg)](https://hub.docker.com/r/appleboy/drone-scp/)
[![micro badger](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")
Copy files and artifacts via SSH using a binary, docker or [Drone CI](http://docs.drone.io/). Copy files and artifacts via SSH using a binary, docker or [Drone CI](http://docs.drone.io/).
+22
View File
@@ -0,0 +1,22 @@
package main
func rmcmd(os, target string) string {
switch os {
case "windows":
return "DEL /F /S " + target
case "unix":
return "rm -rf " + target
}
return ""
}
func mkdircmd(os, target string) string {
switch os {
case "windows":
return "if not exist " + target + " mkdir " + target
case "unix":
return "mkdir -p " + target
}
return ""
}
+20
View File
@@ -0,0 +1,20 @@
FROM alpine:3.17
ARG TARGETOS
ARG TARGETARCH
LABEL maintainer="Bo-Yi Wu <appleboy.tw@gmail.com>" \
org.label-schema.name="SCP Plugin" \
org.label-schema.vendor="Bo-Yi Wu" \
org.label-schema.schema-version="1.0"
LABEL org.opencontainers.image.source=https://github.com/appleboy/drone-scp
LABEL org.opencontainers.image.description="Copy files and artifacts via SSH"
LABEL org.opencontainers.image.licenses=MIT
RUN apk add --no-cache ca-certificates=20220614-r4 && \
rm -rf /var/cache/apk/*
COPY release/${TARGETOS}/${TARGETARCH}/drone-scp /bin/
ENTRYPOINT ["/bin/drone-scp"]
-12
View File
@@ -1,12 +0,0 @@
FROM plugins/base:linux-amd64
LABEL maintainer="Bo-Yi Wu <appleboy.tw@gmail.com>" \
org.label-schema.name="Drone SCP" \
org.label-schema.vendor="Bo-Yi Wu" \
org.label-schema.schema-version="1.0"
RUN apk add --no-cache ca-certificates && \
rm -rf /var/cache/apk/*
COPY release/linux/amd64/drone-scp /bin/
ENTRYPOINT ["/bin/drone-scp"]
-12
View File
@@ -1,12 +0,0 @@
FROM plugins/base:linux-arm
LABEL maintainer="Bo-Yi Wu <appleboy.tw@gmail.com>" \
org.label-schema.name="Drone SCP" \
org.label-schema.vendor="Bo-Yi Wu" \
org.label-schema.schema-version="1.0"
RUN apk add --no-cache ca-certificates && \
rm -rf /var/cache/apk/*
COPY release/linux/arm/drone-scp /bin/
ENTRYPOINT ["/bin/drone-scp"]
-12
View File
@@ -1,12 +0,0 @@
FROM plugins/base:linux-arm64
LABEL maintainer="Bo-Yi Wu <appleboy.tw@gmail.com>" \
org.label-schema.name="Drone SCP" \
org.label-schema.vendor="Bo-Yi Wu" \
org.label-schema.schema-version="1.0"
RUN apk add --no-cache ca-certificates && \
rm -rf /var/cache/apk/*
COPY release/linux/arm64/drone-scp /bin/
ENTRYPOINT ["/bin/drone-scp"]
-10
View File
@@ -1,10 +0,0 @@
FROM microsoft/nanoserver:10.0.14393.1884
LABEL maintainer="Bo-Yi Wu <appleboy.tw@gmail.com>" \
org.label-schema.name="Drone SCP" \
org.label-schema.vendor="Bo-Yi Wu" \
org.label-schema.schema-version="1.0"
COPY drone-scp.exe /drone-scp.exe
ENTRYPOINT [ "\\drone-scp.exe" ]
-25
View File
@@ -1,25 +0,0 @@
image: appleboy/drone-scp:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
{{#if build.tags}}
tags:
{{#each build.tags}}
- {{this}}
{{/each}}
{{/if}}
manifests:
-
image: appleboy/drone-scp:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
platform:
architecture: amd64
os: linux
-
image: appleboy/drone-scp:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
platform:
architecture: arm64
os: linux
variant: v8
-
image: appleboy/drone-scp:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
platform:
architecture: arm
os: linux
variant: v7
+22 -7
View File
@@ -1,12 +1,27 @@
module github.com/appleboy/drone-scp module github.com/appleboy/drone-scp
go 1.14 go 1.20
require ( require (
github.com/appleboy/com v0.0.6 github.com/appleboy/com v0.1.7
github.com/appleboy/easyssh-proxy v1.3.4 github.com/appleboy/easyssh-proxy v1.3.9
github.com/fatih/color v1.9.0 github.com/fatih/color v1.15.0
github.com/joho/godotenv v1.3.0 github.com/joho/godotenv v1.5.1
github.com/stretchr/testify v1.5.1 github.com/stretchr/testify v1.8.2
github.com/urfave/cli/v2 v2.2.0 github.com/urfave/cli/v2 v2.25.1
golang.org/x/crypto v0.8.0
)
require (
github.com/ScaleFT/sshkeys v1.2.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/sys v0.7.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
) )
+47 -32
View File
@@ -1,48 +1,63 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/ScaleFT/sshkeys v0.0.0-20200327173127-6142f742bca5/go.mod h1:gxOHeajFfvGQh/fxlC8oOKBe23xnnJTif00IFFbiT+o=
github.com/ScaleFT/sshkeys v0.0.0-20181112160850-82451a803681 h1:JS2rl38kZmHgWa0xINSaSYH0Whtvem64/4+Ef0+Y5pE= github.com/ScaleFT/sshkeys v1.2.0 h1:5BRp6rTVIhJzXT3VcUQrKgXR8zWA3sOsNeuyW15WUA8=
github.com/ScaleFT/sshkeys v0.0.0-20181112160850-82451a803681/go.mod h1:WfDateMPQ/55dPbZRp5Zxrux5WiEaHsjk9puUhz0KgY= github.com/ScaleFT/sshkeys v1.2.0/go.mod h1:gxOHeajFfvGQh/fxlC8oOKBe23xnnJTif00IFFbiT+o=
github.com/appleboy/com v0.0.6 h1:l8cZ0aQJU/SWyL79ciYAJeqV835PRdlZ6efiPhus5Ic= github.com/appleboy/com v0.1.7 h1:4lYTFNoMAAXGGIC8lDxVg/NY+1aXbYqfAWN05cZhd0M=
github.com/appleboy/com v0.0.6/go.mod h1:jnufjIC3opMlReyPPPye+8JqNvUzLm25o7h6SOy8nv0= github.com/appleboy/com v0.1.7/go.mod h1:JUK+oH0SXCLRH57pDMJx6VWVsm8CPdajalmRSWwamBE=
github.com/appleboy/easyssh-proxy v1.3.4 h1:yNgzsJ9qaDNGzQILDXEK4boioJMmUUaTUsxYtCTSGqo= github.com/appleboy/easyssh-proxy v1.3.9 h1:b+sVSTz+cVFvfA23HQywMMpm0s5g3gH7jYdBcQqaCQI=
github.com/appleboy/easyssh-proxy v1.3.4/go.mod h1:Kk57I3w7OCafOjp5kgZFvxk2fO8Tca5CriBTOsbSbjY= github.com/appleboy/easyssh-proxy v1.3.9/go.mod h1:G1eQomBEME7NWKA3hE49s5HsT44S5fn0aBxX7k9Yjug=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a h1:saTgr5tMLFnmy/yg3qDTft4rE5DY2uJ/cCxCe3q0XTU= github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a h1:saTgr5tMLFnmy/yg3qDTft4rE5DY2uJ/cCxCe3q0XTU=
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a/go.mod h1:Bw9BbhOJVNR+t0jCqx2GC6zv0TGBsShs56Y3gfSCvl0= github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a/go.mod h1:Bw9BbhOJVNR+t0jCqx2GC6zv0TGBsShs56Y3gfSCvl0=
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/urfave/cli/v2 v2.25.1 h1:zw8dSP7ghX0Gmm8vugrs6q9Ku0wzweqPyshy+syu9Gw=
github.com/urfave/cli/v2 v2.25.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876 h1:sKJQZMuxjOAR/Uo2LBfU90onWEf1dF4C+0hPJCc9Mpc= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+84 -44
View File
@@ -7,7 +7,6 @@ import (
"github.com/appleboy/easyssh-proxy" "github.com/appleboy/easyssh-proxy"
"github.com/joho/godotenv" "github.com/joho/godotenv"
_ "github.com/joho/godotenv/autoload"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
@@ -22,12 +21,10 @@ func main() {
_ = godotenv.Load(filename) _ = godotenv.Load(filename)
} }
defaultCiphers := []string{"aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc"}
app := cli.NewApp() app := cli.NewApp()
app.Name = "Drone SCP" app.Name = "Drone SCP"
app.Usage = "Copy files and artifacts via SSH." app.Usage = "Copy files and artifacts via SSH."
app.Copyright = "Copyright (c) 2019 Bo-Yi Wu" app.Copyright = "Copyright (c) 2020 Bo-Yi Wu"
app.Version = Version app.Version = Version
app.Authors = []*cli.Author{ app.Authors = []*cli.Author{
{ {
@@ -39,24 +36,28 @@ func main() {
app.Version = Version app.Version = Version
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{
&cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "host, H", Name: "host",
Aliases: []string{"H"},
Usage: "Server host", Usage: "Server host",
EnvVars: []string{"PLUGIN_HOST", "SCP_HOST", "SSH_HOST", "HOST", "INPUT_HOST"}, EnvVars: []string{"PLUGIN_HOST", "SCP_HOST", "SSH_HOST", "HOST", "INPUT_HOST"},
FilePath: ".host", FilePath: ".host",
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "port, P", Name: "port",
Aliases: []string{"P"},
Value: "22", Value: "22",
Usage: "Server port, default to 22", Usage: "Server port, default to 22",
EnvVars: []string{"PLUGIN_PORT", "SCP_PORT", "SSH_PORT", "PORT", "INPUT_PORT"}, EnvVars: []string{"PLUGIN_PORT", "SCP_PORT", "SSH_PORT", "PORT", "INPUT_PORT"},
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "username, u", Name: "username",
Aliases: []string{"u"},
Usage: "Server username", Usage: "Server username",
EnvVars: []string{"PLUGIN_USERNAME", "PLUGIN_USER", "SCP_USERNAME", "SSH_USERNAME", "USERNAME", "INPUT_USERNAME"}, EnvVars: []string{"PLUGIN_USERNAME", "PLUGIN_USER", "SCP_USERNAME", "SSH_USERNAME", "USERNAME", "INPUT_USERNAME"},
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "password, p", Name: "password",
Aliases: []string{"p"},
Usage: "Password for password-based authentication", Usage: "Password for password-based authentication",
EnvVars: []string{"PLUGIN_PASSWORD", "SCP_PASSWORD", "SSH_PASSWORD", "PASSWORD", "INPUT_PASSWORD"}, EnvVars: []string{"PLUGIN_PASSWORD", "SCP_PASSWORD", "SSH_PASSWORD", "PASSWORD", "INPUT_PASSWORD"},
}, },
@@ -64,7 +65,16 @@ func main() {
Name: "ciphers", Name: "ciphers",
Usage: "The allowed cipher algorithms. If unspecified then a sensible", Usage: "The allowed cipher algorithms. If unspecified then a sensible",
EnvVars: []string{"PLUGIN_CIPHERS", "SSH_CIPHERS", "CIPHERS", "INPUT_CIPHERS"}, EnvVars: []string{"PLUGIN_CIPHERS", "SSH_CIPHERS", "CIPHERS", "INPUT_CIPHERS"},
Value: cli.NewStringSlice(defaultCiphers...), },
&cli.BoolFlag{
Name: "useInsecureCipher",
Usage: "include more ciphers with use_insecure_cipher",
EnvVars: []string{"PLUGIN_USE_INSECURE_CIPHER", "SSH_USE_INSECURE_CIPHER", "USE_INSECURE_CIPHER", "INPUT_USE_INSECURE_CIPHER"},
},
&cli.StringFlag{
Name: "fingerprint",
Usage: "fingerprint SHA256 of the host public key, default is to skip verification",
EnvVars: []string{"PLUGIN_FINGERPRINT", "SSH_FINGERPRINT", "FINGERPRINT", "INPUT_FINGERPRINT"},
}, },
&cli.DurationFlag{ &cli.DurationFlag{
Name: "timeout", Name: "timeout",
@@ -79,7 +89,8 @@ func main() {
Value: 10 * time.Minute, Value: 10 * time.Minute,
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "ssh-key, k", Name: "ssh-key",
Aliases: []string{"k"},
Usage: "ssh private key", Usage: "ssh private key",
EnvVars: []string{"PLUGIN_SSH_KEY,", "PLUGIN_KEY", "SCP_KEY", "SSH_KEY", "KEY", "INPUT_KEY"}, EnvVars: []string{"PLUGIN_SSH_KEY,", "PLUGIN_KEY", "SCP_KEY", "SSH_KEY", "KEY", "INPUT_KEY"},
}, },
@@ -89,22 +100,26 @@ func main() {
EnvVars: []string{"PLUGIN_SSH_PASSPHRASE", "PLUGIN_PASSPHRASE", "SSH_PASSPHRASE", "PASSPHRASE", "INPUT_PASSPHRASE"}, EnvVars: []string{"PLUGIN_SSH_PASSPHRASE", "PLUGIN_PASSPHRASE", "SSH_PASSPHRASE", "PASSPHRASE", "INPUT_PASSPHRASE"},
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "key-path, i", Name: "key-path",
Aliases: []string{"i"},
Usage: "ssh private key path", Usage: "ssh private key path",
EnvVars: []string{"PLUGIN_KEY_PATH", "SCP_KEY_PATH", "SSH_KEY_PATH", "INPUT_KEY_PATH"}, EnvVars: []string{"PLUGIN_KEY_PATH", "SCP_KEY_PATH", "SSH_KEY_PATH", "INPUT_KEY_PATH"},
}, },
&cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "target, t", Name: "target",
Aliases: []string{"t"},
Usage: "Target path on the server", Usage: "Target path on the server",
EnvVars: []string{"PLUGIN_TARGET", "SCP_TARGET", "TARGET", "INPUT_TARGET"}, EnvVars: []string{"PLUGIN_TARGET", "SCP_TARGET", "TARGET", "INPUT_TARGET"},
}, },
&cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "source, s", Name: "source",
Aliases: []string{"s"},
Usage: "scp file list", Usage: "scp file list",
EnvVars: []string{"PLUGIN_SOURCE", "SCP_SOURCE", "SOURCE", "INPUT_SOURCE"}, EnvVars: []string{"PLUGIN_SOURCE", "SCP_SOURCE", "SOURCE", "INPUT_SOURCE"},
}, },
&cli.BoolFlag{ &cli.BoolFlag{
Name: "rm, r", Name: "rm",
Aliases: []string{"r"},
Usage: "remove target folder before upload data", Usage: "remove target folder before upload data",
EnvVars: []string{"PLUGIN_RM", "SCP_RM", "RM", "INPUT_RM"}, EnvVars: []string{"PLUGIN_RM", "SCP_RM", "RM", "INPUT_RM"},
}, },
@@ -164,7 +179,7 @@ func main() {
&cli.StringFlag{ &cli.StringFlag{
Name: "proxy.ssh-key", Name: "proxy.ssh-key",
Usage: "private ssh key of proxy", Usage: "private ssh key of proxy",
EnvVars: []string{"PLUGIN_PROXY_SSH_KEY", "PLUGIN_PROXY_KEY", "PROXY_SSH_KEY", "PROXY_KEY", "INPUT_PROXY_SSH_KEY"}, EnvVars: []string{"PLUGIN_PROXY_SSH_KEY", "PLUGIN_PROXY_KEY", "PROXY_SSH_KEY", "PROXY_KEY", "INPUT_PROXY_KEY"},
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "proxy.ssh-passphrase", Name: "proxy.ssh-passphrase",
@@ -174,7 +189,7 @@ func main() {
&cli.StringFlag{ &cli.StringFlag{
Name: "proxy.key-path", Name: "proxy.key-path",
Usage: "ssh private key path of proxy", Usage: "ssh private key path of proxy",
EnvVars: []string{"PLUGIN_PROXY_KEY_PATH", "PROXY_SSH_KEY_PATH", "INPUT_PROXY_SSH_KEY_PATH"}, EnvVars: []string{"PLUGIN_PROXY_KEY_PATH", "PROXY_SSH_KEY_PATH", "INPUT_PROXY_KEY_PATH"},
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "proxy.username", Name: "proxy.username",
@@ -196,7 +211,16 @@ func main() {
Name: "proxy.ciphers", Name: "proxy.ciphers",
Usage: "The allowed cipher algorithms. If unspecified then a sensible", Usage: "The allowed cipher algorithms. If unspecified then a sensible",
EnvVars: []string{"PLUGIN_PROXY_CIPHERS", "PROXY_SSH_CIPHERS", "PROXY_CIPHERS", "INPUT_PROXY_CIPHERS"}, EnvVars: []string{"PLUGIN_PROXY_CIPHERS", "PROXY_SSH_CIPHERS", "PROXY_CIPHERS", "INPUT_PROXY_CIPHERS"},
Value: cli.NewStringSlice(defaultCiphers...), },
&cli.BoolFlag{
Name: "proxy.useInsecureCipher",
Usage: "include more ciphers with use_insecure_cipher",
EnvVars: []string{"PLUGIN_PROXY_USE_INSECURE_CIPHER", "SSH_PROXY_USE_INSECURE_CIPHER", "PROXY_USE_INSECURE_CIPHER", "INPUT_PROXY_USE_INSECURE_CIPHER"},
},
&cli.StringFlag{
Name: "proxy.fingerprint",
Usage: "fingerprint SHA256 of the host public key, default is to skip verification",
EnvVars: []string{"PLUGIN_PROXY_FINGERPRINT", "SSH_PROXY_FINGERPRINT", "PROXY_FINGERPRINT", "INPUT_PROXY_FINGERPRINT"},
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "proxy.port", Name: "proxy.port",
@@ -235,6 +259,16 @@ func main() {
Usage: "use --overwrite flag with tar", Usage: "use --overwrite flag with tar",
EnvVars: []string{"PLUGIN_OVERWRITE", "SCP_OVERWRITE", "INPUT_OVERWRITE"}, EnvVars: []string{"PLUGIN_OVERWRITE", "SCP_OVERWRITE", "INPUT_OVERWRITE"},
}, },
&cli.BoolFlag{
Name: "unlink.first",
Usage: "use --unlink-first flag with tar",
EnvVars: []string{"PLUGIN_UNLINK_FIRST", "SCP_UNLINK_FIRST", "INPUT_UNLINK_FIRST"},
},
&cli.BoolFlag{
Name: "tar.dereference",
Usage: "use --dereference flag with tar",
EnvVars: []string{"PLUGIN_TAR_DEREFERENCE", "SCP_TAR_DEREFERENCE", "INPUT_TAR_DEREFERENCE"},
},
} }
// Override a template // Override a template
@@ -292,34 +326,40 @@ func run(c *cli.Context) error {
Link: c.String("build.link"), Link: c.String("build.link"),
}, },
Config: Config{ Config: Config{
Host: c.StringSlice("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"),
Passphrase: c.String("ssh-passphrase"), Passphrase: c.String("ssh-passphrase"),
Timeout: c.Duration("timeout"), Fingerprint: c.String("fingerprint"),
CommandTimeout: c.Duration("command.timeout"), Timeout: c.Duration("timeout"),
Key: c.String("ssh-key"), CommandTimeout: c.Duration("command.timeout"),
KeyPath: c.String("key-path"), Key: c.String("ssh-key"),
Target: c.StringSlice("target"), KeyPath: c.String("key-path"),
Source: c.StringSlice("source"), Target: c.StringSlice("target"),
Remove: c.Bool("rm"), Source: c.StringSlice("source"),
Debug: c.Bool("debug"), Remove: c.Bool("rm"),
StripComponents: c.Int("strip.components"), Debug: c.Bool("debug"),
TarExec: c.String("tar.exec"), StripComponents: c.Int("strip.components"),
TarTmpPath: c.String("tar.tmp-path"), TarExec: c.String("tar.exec"),
Overwrite: c.Bool("overwrite"), TarTmpPath: c.String("tar.tmp-path"),
Ciphers: c.StringSlice("ciphers"), Overwrite: c.Bool("overwrite"),
UnlinkFirst: c.Bool("unlink.first"),
Ciphers: c.StringSlice("ciphers"),
UseInsecureCipher: c.Bool("useInsecureCipher"),
TarDereference: c.Bool("tar.dereference"),
Proxy: easyssh.DefaultConfig{ Proxy: easyssh.DefaultConfig{
Key: c.String("proxy.ssh-key"), Key: c.String("proxy.ssh-key"),
Passphrase: c.String("proxy.ssh-passphrase"), Passphrase: c.String("proxy.ssh-passphrase"),
KeyPath: c.String("proxy.key-path"), Fingerprint: c.String("proxy.fingerprint"),
User: c.String("proxy.username"), KeyPath: c.String("proxy.key-path"),
Password: c.String("proxy.password"), User: c.String("proxy.username"),
Server: c.String("proxy.host"), Password: c.String("proxy.password"),
Port: c.String("proxy.port"), Server: c.String("proxy.host"),
Timeout: c.Duration("proxy.timeout"), Port: c.String("proxy.port"),
Ciphers: c.StringSlice("proxy.ciphers"), Timeout: c.Duration("proxy.timeout"),
Ciphers: c.StringSlice("proxy.ciphers"),
UseInsecureCipher: c.Bool("proxy.useInsecureCipher"),
}, },
}, },
} }
+1
View File
@@ -1,3 +1,4 @@
//go:build !windows
// +build !windows // +build !windows
package main package main
+1
View File
@@ -1,3 +1,4 @@
//go:build windows
// +build windows // +build windows
package main package main
-256
View File
@@ -1,256 +0,0 @@
{
test:: {
kind: 'pipeline',
name: 'testing',
platform: {
os: 'linux',
arch: 'amd64',
},
steps: [
{
name: 'vet',
image: 'golang:1.14',
pull: 'always',
commands: [
'make vet',
],
volumes: [
{
name: 'gopath',
path: '/go',
},
],
},
{
name: 'lint',
image: 'golang:1.14',
pull: 'always',
commands: [
'make lint',
],
volumes: [
{
name: 'gopath',
path: '/go',
},
],
},
{
name: 'misspell',
image: 'golang:1.14',
pull: 'always',
commands: [
'make misspell-check',
],
volumes: [
{
name: 'gopath',
path: '/go',
},
],
},
{
name: 'test',
image: 'golang:1.14-alpine',
pull: 'always',
commands: [
'apk add git make curl perl bash build-base zlib-dev ucl-dev',
'make ssh-server',
'make test',
'make coverage',
],
volumes: [
{
name: 'gopath',
path: '/go',
},
],
},
{
name: 'codecov',
image: 'robertstettner/drone-codecov',
pull: 'always',
settings: {
token: { 'from_secret': 'codecov_token' },
},
},
],
volumes: [
{
name: 'gopath',
temp: {},
},
],
},
build(name, os='linux', arch='amd64'):: {
kind: 'pipeline',
name: os + '-' + arch,
platform: {
os: os,
arch: arch,
},
steps: [
{
name: 'build-push',
image: 'golang:1.14',
pull: 'always',
environment: {
CGO_ENABLED: '0',
},
commands: [
'go build -v -ldflags \'-X main.build=${DRONE_BUILD_NUMBER}\' -a -o release/' + os + '/' + arch + '/' + name,
],
when: {
event: {
exclude: [ 'tag' ],
},
},
},
{
name: 'build-tag',
image: 'golang:1.14',
pull: 'always',
environment: {
CGO_ENABLED: '0',
},
commands: [
'go build -v -ldflags \'-X main.version=${DRONE_TAG##v} -X main.build=${DRONE_BUILD_NUMBER}\' -a -o release/' + os + '/' + arch + '/' + name,
],
when: {
event: [ 'tag' ],
},
},
{
name: 'executable',
image: 'golang:1.14',
pull: 'always',
commands: [
'./release/' + os + '/' + arch + '/' + name + ' --help',
],
},
{
name: 'dryrun',
image: 'plugins/docker:' + os + '-' + arch,
pull: 'always',
settings: {
daemon_off: false,
dry_run: true,
tags: os + '-' + arch,
dockerfile: 'docker/Dockerfile.' + os + '.' + arch,
repo: 'appleboy/' + name,
cache_from: 'appleboy/' + name,
},
when: {
event: [ 'pull_request' ],
},
},
{
name: 'publish',
image: 'plugins/docker:' + os + '-' + arch,
pull: 'always',
settings: {
daemon_off: 'false',
auto_tag: true,
auto_tag_suffix: os + '-' + arch,
dockerfile: 'docker/Dockerfile.' + os + '.' + arch,
repo: 'appleboy/' + name,
cache_from: 'appleboy/' + name,
username: { 'from_secret': 'docker_username' },
password: { 'from_secret': 'docker_password' },
},
when: {
event: {
exclude: [ 'pull_request' ],
},
},
},
],
depends_on: [
'testing',
],
trigger: {
ref: [
'refs/heads/master',
'refs/pull/**',
'refs/tags/**',
],
},
},
release:: {
kind: 'pipeline',
name: 'release-binary',
platform: {
os: 'linux',
arch: 'amd64',
},
steps: [
{
name: 'build-all-binary',
image: 'golang:1.14',
pull: 'always',
commands: [
'make release'
],
when: {
event: [ 'tag' ],
},
},
{
name: 'deploy-all-binary',
image: 'plugins/github-release',
pull: 'always',
settings: {
files: [ 'dist/release/*' ],
api_key: { 'from_secret': 'github_release_api_key' },
},
when: {
event: [ 'tag' ],
},
},
],
depends_on: [
'testing',
],
trigger: {
ref: [
'refs/tags/**',
],
},
},
notifications(os='linux', arch='amd64', depends_on=[]):: {
kind: 'pipeline',
name: 'notifications',
platform: {
os: os,
arch: arch,
},
steps: [
{
name: 'manifest',
image: 'plugins/manifest',
pull: 'always',
settings: {
username: { from_secret: 'docker_username' },
password: { from_secret: 'docker_password' },
spec: 'docker/manifest.tmpl',
ignore_missing: true,
},
},
],
depends_on: depends_on,
trigger: {
ref: [
'refs/heads/master',
'refs/tags/**',
],
},
},
signature(key):: {
kind: 'signature',
hmac: key,
}
}
+157 -124
View File
@@ -3,7 +3,6 @@ package main
import ( import (
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
@@ -20,7 +19,6 @@ import (
var ( var (
errMissingHost = errors.New("Error: missing server host") errMissingHost = errors.New("Error: missing server host")
errMissingPasswordOrKey = errors.New("Error: can't connect without a private SSH key or password") errMissingPasswordOrKey = errors.New("Error: can't connect without a private SSH key or password")
errSetPasswordandKey = errors.New("can't set password and key at the same time")
errMissingSourceOrTarget = errors.New("missing source or target config") errMissingSourceOrTarget = errors.New("missing source or target config")
) )
@@ -45,25 +43,29 @@ 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
Passphrase string Passphrase string
KeyPath string Fingerprint string
Timeout time.Duration KeyPath string
CommandTimeout time.Duration Timeout time.Duration
Target []string CommandTimeout time.Duration
Source []string Target []string
Remove bool Source []string
StripComponents int Remove bool
TarExec string StripComponents int
TarTmpPath string TarExec string
Proxy easyssh.DefaultConfig TarTmpPath string
Debug bool Proxy easyssh.DefaultConfig
Overwrite bool Debug bool
Ciphers []string Overwrite bool
UnlinkFirst bool
Ciphers []string
UseInsecureCipher bool
TarDereference bool
} }
// Plugin values. // Plugin values.
@@ -84,27 +86,12 @@ func (e copyError) Error() string {
return fmt.Sprintf("error copy file to dest: %s, error message: %s\n", e.host, e.message) return fmt.Sprintf("error copy file to dest: %s, error message: %s\n", e.host, e.message)
} }
func trimPath(keys []string) []string {
var newKeys []string
for _, value := range keys {
value = strings.Trim(value, " ")
if len(value) == 0 {
continue
}
newKeys = append(newKeys, value)
}
return newKeys
}
func globList(paths []string) fileList { func globList(paths []string) fileList {
var list fileList var list fileList
for _, pattern := range paths { for _, pattern := range paths {
ignore := false ignore := false
pattern = strings.Trim(pattern, " ") pattern = strings.TrimSpace(pattern)
if string(pattern[0]) == "!" { if string(pattern[0]) == "!" {
pattern = pattern[1:] pattern = pattern[1:]
ignore = true ignore = true
@@ -125,21 +112,6 @@ func globList(paths []string) fileList {
return list return list
} }
func buildArgs(tar string, files fileList) []string {
args := []string{}
if len(files.Ignore) > 0 {
for _, v := range files.Ignore {
args = append(args, "--exclude")
args = append(args, v)
}
}
args = append(args, "-cf")
args = append(args, getRealPath(tar))
args = append(args, files.Source...)
return args
}
func (p Plugin) log(host string, message ...interface{}) { func (p Plugin) log(host string, message ...interface{}) {
if count := len(p.Config.Host); count == 1 { if count := len(p.Config.Host); count == 1 {
fmt.Printf("%s", fmt.Sprintln(message...)) fmt.Printf("%s", fmt.Sprintln(message...))
@@ -148,10 +120,9 @@ func (p Plugin) log(host string, message ...interface{}) {
} }
} }
func (p *Plugin) removeDestFile(ssh *easyssh.MakeConfig) error { func (p *Plugin) removeDestFile(os string, ssh *easyssh.MakeConfig) error {
p.log(ssh.Server, "remove file", p.DestFile) p.log(ssh.Server, "remove file", p.DestFile)
_, errStr, _, err := ssh.Run(fmt.Sprintf("rm -rf %s", p.DestFile), p.Config.CommandTimeout) _, errStr, _, err := ssh.Run(rmcmd(os, p.DestFile), p.Config.CommandTimeout)
if err != nil { if err != nil {
return err return err
} }
@@ -164,30 +135,47 @@ func (p *Plugin) removeDestFile(ssh *easyssh.MakeConfig) error {
} }
func (p *Plugin) removeAllDestFile() error { func (p *Plugin) removeAllDestFile() error {
for _, host := range p.Config.Host { for _, host := range trimValues(p.Config.Host) {
ssh := &easyssh.MakeConfig{ ssh := &easyssh.MakeConfig{
Server: host, Server: host,
User: p.Config.Username, User: p.Config.Username,
Password: p.Config.Password, Password: p.Config.Password,
Port: p.Config.Port, Port: p.Config.Port,
Key: p.Config.Key, Key: p.Config.Key,
KeyPath: p.Config.KeyPath, KeyPath: p.Config.KeyPath,
Passphrase: p.Config.Passphrase, Passphrase: p.Config.Passphrase,
Timeout: p.Config.Timeout, Timeout: p.Config.Timeout,
Ciphers: p.Config.Ciphers,
Fingerprint: p.Config.Fingerprint,
UseInsecureCipher: p.Config.UseInsecureCipher,
Proxy: easyssh.DefaultConfig{ Proxy: easyssh.DefaultConfig{
Server: p.Config.Proxy.Server, Server: p.Config.Proxy.Server,
User: p.Config.Proxy.User, User: p.Config.Proxy.User,
Password: p.Config.Proxy.Password, Password: p.Config.Proxy.Password,
Port: p.Config.Proxy.Port, Port: p.Config.Proxy.Port,
Key: p.Config.Proxy.Key, Key: p.Config.Proxy.Key,
KeyPath: p.Config.Proxy.KeyPath, KeyPath: p.Config.Proxy.KeyPath,
Passphrase: p.Config.Proxy.Passphrase, Passphrase: p.Config.Proxy.Passphrase,
Timeout: p.Config.Proxy.Timeout, Timeout: p.Config.Proxy.Timeout,
Ciphers: p.Config.Proxy.Ciphers,
Fingerprint: p.Config.Proxy.Fingerprint,
UseInsecureCipher: p.Config.Proxy.UseInsecureCipher,
}, },
} }
_, _, _, err := ssh.Run("ver", p.Config.CommandTimeout)
systemType := "unix"
if err == nil {
systemType = "windows"
}
_, _, _, err = ssh.Run("uname", p.Config.CommandTimeout)
if err == nil {
systemType = "unix"
}
// remove tar file // remove tar file
err := p.removeDestFile(ssh) err = p.removeDestFile(systemType, ssh)
if err != nil { if err != nil {
return err return err
} }
@@ -201,12 +189,33 @@ type fileList struct {
Source []string Source []string
} }
func (p *Plugin) buildArgs(target string) []string { func (p *Plugin) buildTarArgs(src string) []string {
files := globList(trimValues(p.Config.Source))
args := []string{}
if len(files.Ignore) > 0 {
for _, v := range files.Ignore {
args = append(args, "--exclude")
args = append(args, v)
}
}
if p.Config.TarDereference {
args = append(args, "--dereference")
}
args = append(args, "-zcf")
args = append(args, getRealPath(src))
args = append(args, files.Source...)
return args
}
func (p *Plugin) buildUnTarArgs(target string) []string {
args := []string{} args := []string{}
args = append(args, args = append(args,
p.Config.TarExec, p.Config.TarExec,
"-xf", "-zxf",
p.DestFile, p.DestFile,
) )
@@ -219,6 +228,10 @@ func (p *Plugin) buildArgs(target string) []string {
args = append(args, "--overwrite") args = append(args, "--overwrite")
} }
if p.Config.UnlinkFirst {
args = append(args, "--unlink-first")
}
args = append(args, args = append(args,
"-C", "-C",
target, target,
@@ -229,35 +242,28 @@ func (p *Plugin) buildArgs(target string) []string {
// Exec executes the plugin. // Exec executes the plugin.
func (p *Plugin) Exec() error { func (p *Plugin) Exec() error {
if len(p.Config.Host) == 0 {
return errMissingHost
}
if len(p.Config.Key) == 0 && len(p.Config.Password) == 0 && len(p.Config.KeyPath) == 0 { if len(p.Config.Key) == 0 && len(p.Config.Password) == 0 && len(p.Config.KeyPath) == 0 {
return errMissingPasswordOrKey return errMissingPasswordOrKey
} }
if len(p.Config.Key) != 0 && len(p.Config.Password) != 0 {
return errSetPasswordandKey
}
if len(p.Config.Source) == 0 || len(p.Config.Target) == 0 { if len(p.Config.Source) == 0 || len(p.Config.Target) == 0 {
return errMissingSourceOrTarget return errMissingSourceOrTarget
} }
files := globList(trimPath(p.Config.Source)) hosts := trimValues(p.Config.Host)
p.DestFile = fmt.Sprintf("%s.tar", random.String(10)) if len(hosts) == 0 {
return errMissingHost
}
p.DestFile = fmt.Sprintf("%s.tar.gz", random.String(10))
// create a temporary file for the archive // create a temporary file for the archive
dir, err := ioutil.TempDir("", "") dir := os.TempDir()
if err != nil { src := filepath.Join(dir, p.DestFile)
return err
}
tar := filepath.Join(dir, p.DestFile)
// run archive command // run archive command
fmt.Println("tar all files into " + tar) fmt.Println("tar all files into " + src)
args := buildArgs(tar, files) args := p.buildTarArgs(src)
cmd := exec.Command(p.Config.TarExec, args...) cmd := exec.Command(p.Config.TarExec, args...)
if p.Config.Debug { if p.Config.Debug {
fmt.Println("$", strings.Join(cmd.Args, " ")) fmt.Println("$", strings.Join(cmd.Args, " "))
@@ -272,60 +278,73 @@ func (p *Plugin) Exec() error {
wg.Add(len(p.Config.Host)) wg.Add(len(p.Config.Host))
errChannel := make(chan error) errChannel := make(chan error)
finished := make(chan struct{}) finished := make(chan struct{})
for _, host := range p.Config.Host { for _, host := range hosts {
go func(host string) { go func(host string) {
defer wg.Done()
// Create MakeConfig instance with remote username, server address and path to private key. // Create MakeConfig instance with remote username, server address and path to private key.
ssh := &easyssh.MakeConfig{ ssh := &easyssh.MakeConfig{
Server: host, Server: host,
User: p.Config.Username, User: p.Config.Username,
Password: p.Config.Password, Password: p.Config.Password,
Port: p.Config.Port, Port: p.Config.Port,
Key: p.Config.Key, Key: p.Config.Key,
KeyPath: p.Config.KeyPath, KeyPath: p.Config.KeyPath,
Passphrase: p.Config.Passphrase, Passphrase: p.Config.Passphrase,
Timeout: p.Config.Timeout, Timeout: p.Config.Timeout,
Ciphers: p.Config.Ciphers, Ciphers: p.Config.Ciphers,
Fingerprint: p.Config.Fingerprint,
UseInsecureCipher: p.Config.UseInsecureCipher,
Proxy: easyssh.DefaultConfig{ Proxy: easyssh.DefaultConfig{
Server: p.Config.Proxy.Server, Server: p.Config.Proxy.Server,
User: p.Config.Proxy.User, User: p.Config.Proxy.User,
Password: p.Config.Proxy.Password, Password: p.Config.Proxy.Password,
Port: p.Config.Proxy.Port, Port: p.Config.Proxy.Port,
Key: p.Config.Proxy.Key, Key: p.Config.Proxy.Key,
KeyPath: p.Config.Proxy.KeyPath, KeyPath: p.Config.Proxy.KeyPath,
Passphrase: p.Config.Proxy.Passphrase, Passphrase: p.Config.Proxy.Passphrase,
Timeout: p.Config.Proxy.Timeout, Timeout: p.Config.Proxy.Timeout,
Ciphers: p.Config.Proxy.Ciphers, Ciphers: p.Config.Proxy.Ciphers,
Fingerprint: p.Config.Proxy.Fingerprint,
UseInsecureCipher: p.Config.Proxy.UseInsecureCipher,
}, },
} }
_, _, _, err := ssh.Run("ver", p.Config.CommandTimeout)
systemType := "unix"
if err == nil {
systemType = "windows"
}
_, _, _, err = ssh.Run("uname", p.Config.CommandTimeout)
if err == nil {
systemType = "unix"
}
// upload file to the tmp path // upload file to the tmp path
p.DestFile = fmt.Sprintf("%s%s", p.Config.TarTmpPath, p.DestFile) p.DestFile = fmt.Sprintf("%s%s", p.Config.TarTmpPath, p.DestFile)
// Call Scp method with file you want to upload to remote server. // Call Scp method with file you want to upload to remote server.
p.log(host, "scp file to server.") p.log(host, "scp file to server.")
err := ssh.Scp(tar, p.DestFile) err = ssh.Scp(src, p.DestFile)
if err != nil { if err != nil {
errChannel <- copyError{host, err.Error()} errChannel <- copyError{host, err.Error()}
return return
} }
for _, target := range p.Config.Target { for _, target := range p.Config.Target {
// remove target before upload data // remove target folder before upload data
if p.Config.Remove { if p.Config.Remove {
p.log(host, "Remove target folder:", target) p.log(host, "Remove target folder:", target)
_, _, _, err := ssh.Run(fmt.Sprintf("rm -rf %s", target), p.Config.CommandTimeout) _, _, _, err := ssh.Run(rmcmd(systemType, target), p.Config.CommandTimeout)
if err != nil { if err != nil {
errChannel <- err errChannel <- err
return return
} }
} }
// mkdir path
p.log(host, "create folder", target) p.log(host, "create folder", target)
_, errStr, _, err := ssh.Run(fmt.Sprintf("mkdir -p %s", target), p.Config.CommandTimeout) _, errStr, _, err := ssh.Run(mkdircmd(systemType, target), p.Config.CommandTimeout)
if err != nil { if err != nil {
errChannel <- err errChannel <- err
return return
@@ -338,7 +357,7 @@ func (p *Plugin) Exec() error {
// untar file // untar file
p.log(host, "untar file", p.DestFile) p.log(host, "untar file", p.DestFile)
commamd := strings.Join(p.buildArgs(target), " ") commamd := strings.Join(p.buildUnTarArgs(target), " ")
if p.Config.Debug { if p.Config.Debug {
fmt.Println("$", commamd) fmt.Println("$", commamd)
} }
@@ -359,14 +378,11 @@ func (p *Plugin) Exec() error {
} }
// remove tar file // remove tar file
err = p.removeDestFile(ssh) err = p.removeDestFile(systemType, ssh)
if err != nil { if err != nil {
errChannel <- err errChannel <- err
return return
} }
wg.Done()
}(host) }(host)
} }
@@ -383,7 +399,9 @@ func (p *Plugin) Exec() error {
c.Println("drone-scp error: ", err) c.Println("drone-scp error: ", err)
if _, ok := err.(copyError); !ok { if _, ok := err.(copyError); !ok {
fmt.Println("drone-scp rollback: remove all target tmp file") fmt.Println("drone-scp rollback: remove all target tmp file")
p.removeAllDestFile() if err := p.removeAllDestFile(); err != nil {
return err
}
} }
return err return err
} }
@@ -395,3 +413,18 @@ func (p *Plugin) Exec() error {
return nil return nil
} }
func trimValues(keys []string) []string {
var newKeys []string
for _, value := range keys {
value = strings.TrimSpace(value)
if len(value) == 0 {
continue
}
newKeys = append(newKeys, value)
}
return newKeys
}
+237 -52
View File
@@ -1,6 +1,7 @@
package main package main
import ( import (
"log"
"os" "os"
"os/exec" "os/exec"
"os/user" "os/user"
@@ -11,6 +12,7 @@ import (
"github.com/appleboy/easyssh-proxy" "github.com/appleboy/easyssh-proxy"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"golang.org/x/crypto/ssh"
) )
func TestMissingAllConfig(t *testing.T) { func TestMissingAllConfig(t *testing.T) {
@@ -49,35 +51,18 @@ func TestMissingSourceConfig(t *testing.T) {
assert.NotNil(t, err) assert.NotNil(t, err)
} }
func TestSetPasswordAndKey(t *testing.T) {
plugin := Plugin{
Config: Config{
Host: []string{"example.com"},
Username: "ubuntu",
Port: "443",
Password: "1234",
Key: "test",
},
}
err := plugin.Exec()
assert.NotNil(t, err)
assert.Equal(t, errSetPasswordandKey, err)
}
func TestTrimElement(t *testing.T) { func TestTrimElement(t *testing.T) {
var input, result []string var input, result []string
input = []string{"1", " ", "3"} input = []string{"1", " ", "3"}
result = []string{"1", "3"} result = []string{"1", "3"}
assert.Equal(t, result, trimPath(input)) assert.Equal(t, result, trimValues(input))
input = []string{"1", "2"} input = []string{"1", "2"}
result = []string{"1", "2"} result = []string{"1", "2"}
assert.Equal(t, result, trimPath(input)) assert.Equal(t, result, trimValues(input))
} }
func TestSCPFileFromPublicKey(t *testing.T) { func TestSCPFileFromPublicKey(t *testing.T) {
@@ -169,6 +154,90 @@ func TestSCPFileFromPublicKeyWithPassphrase(t *testing.T) {
} }
} }
func TestWrongFingerprint(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",
KeyPath: "./tests/.ssh/id_rsa",
Source: []string{"tests/a.txt", "tests/b.txt"},
Target: []string{filepath.Join(u.HomeDir, "/test2")},
CommandTimeout: 60 * time.Second,
TarExec: "tar",
Fingerprint: "wrong",
},
}
err = plugin.Exec()
log.Println(err)
assert.NotNil(t, err)
}
func getHostPublicKeyFile(keypath string) (ssh.PublicKey, error) {
var pubkey ssh.PublicKey
var err error
buf, err := os.ReadFile(keypath)
if err != nil {
return nil, err
}
pubkey, _, _, _, err = ssh.ParseAuthorizedKey(buf)
if err != nil {
return nil, err
}
return pubkey, nil
}
func TestSCPFileFromPublicKeyWithFingerprint(t *testing.T) {
if os.Getenv("SSH_AUTH_SOCK") != "" {
if err := exec.Command("eval", "`ssh-agent -k`").Run(); err != nil {
t.Fatalf("exec: %v", err)
}
}
u, err := user.Lookup("drone-scp")
if err != nil {
t.Fatalf("Lookup: %v", err)
}
hostKey, err := getHostPublicKeyFile("/etc/ssh/ssh_host_rsa_key.pub")
assert.NoError(t, err)
plugin := Plugin{
Config: Config{
Host: []string{"localhost"},
Username: "drone-scp",
Port: "22",
KeyPath: "./tests/.ssh/id_rsa",
Fingerprint: ssh.FingerprintSHA256(hostKey),
Source: []string{"tests/a.txt", "tests/b.txt"},
Target: []string{filepath.Join(u.HomeDir, "/test2")},
CommandTimeout: 60 * time.Second,
TarExec: "tar",
},
}
err = plugin.Exec()
assert.Nil(t, err)
// check file exist
if _, err := os.Stat(filepath.Join(u.HomeDir, "/test2/tests/a.txt")); os.IsNotExist(err) {
t.Fatalf("SCP-error: %v", err)
}
if _, err := os.Stat(filepath.Join(u.HomeDir, "/test2/tests/b.txt")); os.IsNotExist(err) {
t.Fatalf("SCP-error: %v", err)
}
}
func TestSCPWildcardFileList(t *testing.T) { func TestSCPWildcardFileList(t *testing.T) {
if os.Getenv("SSH_AUTH_SOCK") != "" { if os.Getenv("SSH_AUTH_SOCK") != "" {
if err := exec.Command("eval", "`ssh-agent -k`").Run(); err != nil { if err := exec.Command("eval", "`ssh-agent -k`").Run(); err != nil {
@@ -284,6 +353,40 @@ func TestStripComponentsFlag(t *testing.T) {
} }
} }
func TestUseInsecureCipherFlag(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",
KeyPath: "tests/.ssh/id_rsa",
Source: []string{"tests/global/*"},
StripComponents: 2,
Target: []string{filepath.Join(u.HomeDir, "123")},
CommandTimeout: 60 * time.Second,
TarExec: "tar",
UseInsecureCipher: true,
},
}
err = plugin.Exec()
assert.Nil(t, err)
// check file exist
if _, err := os.Stat(filepath.Join(u.HomeDir, "123/c.txt")); os.IsNotExist(err) {
t.Fatalf("SCP-error: %v", err)
}
if _, err := os.Stat(filepath.Join(u.HomeDir, "123/d.txt")); os.IsNotExist(err) {
t.Fatalf("SCP-error: %v", err)
}
}
func TestIgnoreList(t *testing.T) { func TestIgnoreList(t *testing.T) {
if os.Getenv("SSH_AUTH_SOCK") != "" { if os.Getenv("SSH_AUTH_SOCK") != "" {
if err := exec.Command("eval", "`ssh-agent -k`").Run(); err != nil { if err := exec.Command("eval", "`ssh-agent -k`").Run(); err != nil {
@@ -315,12 +418,12 @@ func TestIgnoreList(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
// check file exist // check file exist
if _, err := os.Stat(filepath.Join(u.HomeDir, "ignore/c.txt")); err == nil { if _, err := os.Stat(filepath.Join(u.HomeDir, "ignore/c.txt")); !os.IsNotExist(err) {
t.Fatal("c.txt file exist") t.Fatal("c.txt file exist")
} }
// check file exist // check file exist
if _, err := os.Stat(filepath.Join(u.HomeDir, "ignore/e.txt")); err == nil { if _, err := os.Stat(filepath.Join(u.HomeDir, "ignore/e.txt")); !os.IsNotExist(err) {
t.Fatal("c.txt file exist") t.Fatal("c.txt file exist")
} }
@@ -452,25 +555,6 @@ func TestGlobList(t *testing.T) {
assert.Equal(t, expectIgnores, result.Ignore) assert.Equal(t, expectIgnores, result.Ignore)
} }
func TestBuildArgs(t *testing.T) {
list := fileList{
Source: []string{"tests/a.txt", "tests/b.txt", "tests/c.txt"},
Ignore: []string{"tests/a.txt", "tests/b.txt"},
}
result := buildArgs("test.tar.gz", list)
expects := []string{"--exclude", "tests/a.txt", "--exclude", "tests/b.txt", "-cf", "test.tar.gz", "tests/a.txt", "tests/b.txt", "tests/c.txt"}
assert.Equal(t, expects, result)
list = fileList{
Source: []string{"tests/a.txt", "tests/b.txt"},
}
result = buildArgs("test.tar.gz", list)
expects = []string{"-cf", "test.tar.gz", "tests/a.txt", "tests/b.txt"}
assert.Equal(t, expects, result)
}
func TestRemoveDestFile(t *testing.T) { func TestRemoveDestFile(t *testing.T) {
ssh := &easyssh.MakeConfig{ ssh := &easyssh.MakeConfig{
Server: "localhost", Server: "localhost",
@@ -487,18 +571,29 @@ func TestRemoveDestFile(t *testing.T) {
DestFile: "/etc/resolv.conf", DestFile: "/etc/resolv.conf",
} }
_, _, _, err := ssh.Run("ver", plugin.Config.CommandTimeout)
systemType := "unix"
if err == nil {
systemType = "windows"
}
_, _, _, err = ssh.Run("uname", plugin.Config.CommandTimeout)
if err == nil {
systemType = "unix"
}
// ssh io timeout // ssh io timeout
err := plugin.removeDestFile(ssh) err = plugin.removeDestFile(systemType, ssh)
assert.Error(t, err) assert.Error(t, err)
ssh.Timeout = 0 ssh.Timeout = 0
// permission denied // permission denied
err = plugin.removeDestFile(ssh) err = plugin.removeDestFile(systemType, ssh)
assert.Error(t, err) assert.Error(t, err)
} }
func TestPlugin_buildArgs(t *testing.T) { func TestPlugin_buildUnTarArgs(t *testing.T) {
type fields struct { type fields struct {
Repo Repo Repo Repo
Build Build Build Build
@@ -518,30 +613,32 @@ func TestPlugin_buildArgs(t *testing.T) {
name: "default command", name: "default command",
fields: fields{ fields: fields{
Config: Config{ Config: Config{
Overwrite: false, Overwrite: false,
TarExec: "tar", UnlinkFirst: false,
TarExec: "tar",
}, },
DestFile: "foo.tar", DestFile: "foo.tar.gz",
}, },
args: args{ args: args{
target: "foo", target: "foo",
}, },
want: []string{"tar", "-xf", "foo.tar", "-C", "foo"}, want: []string{"tar", "-zxf", "foo.tar.gz", "-C", "foo"},
}, },
{ {
name: "strip components", name: "strip components",
fields: fields{ fields: fields{
Config: Config{ Config: Config{
Overwrite: false, Overwrite: false,
UnlinkFirst: false,
TarExec: "tar", TarExec: "tar",
StripComponents: 2, StripComponents: 2,
}, },
DestFile: "foo.tar", DestFile: "foo.tar.gz",
}, },
args: args{ args: args{
target: "foo", target: "foo",
}, },
want: []string{"tar", "-xf", "foo.tar", "--strip-components", "2", "-C", "foo"}, want: []string{"tar", "-zxf", "foo.tar.gz", "--strip-components", "2", "-C", "foo"},
}, },
{ {
name: "overwrite", name: "overwrite",
@@ -550,13 +647,30 @@ func TestPlugin_buildArgs(t *testing.T) {
TarExec: "tar", TarExec: "tar",
StripComponents: 2, StripComponents: 2,
Overwrite: true, Overwrite: true,
UnlinkFirst: false,
}, },
DestFile: "foo.tar", DestFile: "foo.tar.gz",
}, },
args: args{ args: args{
target: "foo", target: "foo",
}, },
want: []string{"tar", "-xf", "foo.tar", "--strip-components", "2", "--overwrite", "-C", "foo"}, want: []string{"tar", "-zxf", "foo.tar.gz", "--strip-components", "2", "--overwrite", "-C", "foo"},
},
{
name: "unlink first",
fields: fields{
Config: Config{
TarExec: "tar",
StripComponents: 2,
Overwrite: true,
UnlinkFirst: true,
},
DestFile: "foo.tar.gz",
},
args: args{
target: "foo",
},
want: []string{"tar", "-zxf", "foo.tar.gz", "--strip-components", "2", "--overwrite", "--unlink-first", "-C", "foo"},
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@@ -567,9 +681,80 @@ func TestPlugin_buildArgs(t *testing.T) {
Config: tt.fields.Config, Config: tt.fields.Config,
DestFile: tt.fields.DestFile, DestFile: tt.fields.DestFile,
} }
if got := p.buildArgs(tt.args.target); !reflect.DeepEqual(got, tt.want) { if got := p.buildUnTarArgs(tt.args.target); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Plugin.buildArgs() = %v, want %v", got, tt.want) t.Errorf("Plugin.buildArgs() = %v, want %v", got, tt.want)
} }
}) })
} }
} }
func TestPlugin_buildTarArgs(t *testing.T) {
type fields struct {
Config Config
}
type args struct {
src string
}
tests := []struct {
name string
fields fields
args args
want []string
}{
{
name: "default command",
fields: fields{
Config: Config{
TarExec: "tar",
},
},
args: args{
src: "foo.tar.gz",
},
want: []string{"-zcf", "foo.tar.gz"},
},
{
name: "ignore list",
fields: fields{
Config: Config{
TarExec: "tar",
Source: []string{
"tests/*.txt",
"!tests/a.txt",
},
},
},
args: args{
src: "foo.tar.gz",
},
want: []string{"--exclude", "tests/a.txt", "-zcf", "foo.tar.gz", "tests/a.txt", "tests/b.txt"},
},
{
name: "dereference flag",
fields: fields{
Config: Config{
TarExec: "tar",
TarDereference: true,
Source: []string{
"tests/*.txt",
"!tests/a.txt",
},
},
},
args: args{
src: "foo.tar.gz",
},
want: []string{"--exclude", "tests/a.txt", "--dereference", "-zcf", "foo.tar.gz", "tests/a.txt", "tests/b.txt"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := &Plugin{
Config: tt.fields.Config,
}
if got := p.buildTarArgs(tt.args.src); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Plugin.buildTarArgs() = %v, want %v", got, tt.want)
}
})
}
}