├── .dockerignore ├── .drone.jsonnet ├── .drone.windows.jsonnet ├── .drone.windows.yml ├── .drone.yml ├── .github ├── issue_template.md ├── pull_request_template.md └── settings.yml ├── .gitignore ├── LICENSE ├── README.md ├── docker ├── Dockerfile.linux.amd64 ├── Dockerfile.linux.arm ├── Dockerfile.linux.arm64 ├── Dockerfile.windows.1803 ├── Dockerfile.windows.1809 └── manifest.tmpl ├── go.mod ├── go.sum ├── main.go ├── main_test.go └── pipeline.libsonnet /.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !release/ 3 | -------------------------------------------------------------------------------- /.drone.jsonnet: -------------------------------------------------------------------------------- 1 | local pipeline = import 'pipeline.libsonnet'; 2 | local name = 'drone-rsync'; 3 | 4 | [ 5 | pipeline.test('linux', 'amd64'), 6 | pipeline.build(name, 'linux', 'amd64'), 7 | pipeline.build(name, 'linux', 'arm64'), 8 | pipeline.build(name, 'linux', 'arm'), 9 | pipeline.notifications(depends_on=[ 10 | 'linux-amd64', 11 | 'linux-arm64', 12 | 'linux-arm', 13 | ]), 14 | ] 15 | -------------------------------------------------------------------------------- /.drone.windows.jsonnet: -------------------------------------------------------------------------------- 1 | local pipeline = import 'pipeline.libsonnet'; 2 | local name = 'drone-rsync'; 3 | 4 | [ 5 | pipeline.test('windows', 'amd64', '1803'), 6 | pipeline.build(name, 'windows', 'amd64', '1803'), 7 | pipeline.build(name, 'windows', 'amd64', '1809'), 8 | pipeline.notifications('windows', 'amd64', '1809', ['windows-1803', 'windows-1809']), 9 | ] 10 | -------------------------------------------------------------------------------- /.drone.windows.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: pipeline 3 | name: testing 4 | 5 | platform: 6 | os: windows 7 | arch: amd64 8 | version: 1803 9 | 10 | steps: 11 | - name: vet 12 | pull: always 13 | image: golang:1.11-windowsservercore-1803 14 | commands: 15 | - go vet ./... 16 | environment: 17 | GO111MODULE: on 18 | volumes: 19 | - name: gopath 20 | path: C:\\gopath 21 | 22 | - name: test 23 | pull: always 24 | image: golang:1.11-windowsservercore-1803 25 | commands: 26 | - go test -cover ./... 27 | environment: 28 | GO111MODULE: on 29 | volumes: 30 | - name: gopath 31 | path: C:\\gopath 32 | 33 | volumes: 34 | - name: gopath 35 | temp: {} 36 | 37 | trigger: 38 | ref: 39 | - refs/heads/master 40 | - "refs/tags/**" 41 | - "refs/pull/**" 42 | 43 | --- 44 | kind: pipeline 45 | name: windows-1803 46 | 47 | platform: 48 | os: windows 49 | arch: amd64 50 | version: 1803 51 | 52 | steps: 53 | - name: build-push 54 | pull: always 55 | image: golang:1.11-windowsservercore-1803 56 | commands: 57 | - "go build -v -ldflags \"-X main.version=${DRONE_COMMIT_SHA:0:8}\" -a -tags netgo -o release/windows/amd64/drone-rsync.exe" 58 | environment: 59 | CGO_ENABLED: 0 60 | GO111MODULE: on 61 | when: 62 | event: 63 | exclude: 64 | - tag 65 | 66 | - name: build-tag 67 | pull: always 68 | image: golang:1.11-windowsservercore-1803 69 | commands: 70 | - "go build -v -ldflags \"-X main.version=${DRONE_TAG##v}\" -a -tags netgo -o release/windows/amd64/drone-rsync.exe" 71 | environment: 72 | CGO_ENABLED: 0 73 | GO111MODULE: on 74 | when: 75 | event: 76 | - tag 77 | 78 | - name: executable 79 | pull: always 80 | image: golang:1.11-windowsservercore-1803 81 | commands: 82 | - ./release/windows/amd64/drone-rsync.exe --help 83 | 84 | - name: dryrun 85 | pull: always 86 | image: plugins/docker:windows-1803 87 | settings: 88 | daemon_off: true 89 | dockerfile: docker/Dockerfile.windows.1803 90 | dry_run: true 91 | password: 92 | from_secret: docker_password 93 | repo: plugins/rsync 94 | tags: windows-1803 95 | username: 96 | from_secret: docker_username 97 | volumes: 98 | - name: docker_pipe 99 | path: \\\\.\\pipe\\docker_engine 100 | when: 101 | event: 102 | - pull_request 103 | 104 | - name: publish 105 | pull: always 106 | image: plugins/docker:windows-1803 107 | settings: 108 | auto_tag: true 109 | auto_tag_suffix: windows-1803 110 | daemon_off: true 111 | dockerfile: docker/Dockerfile.windows.1803 112 | password: 113 | from_secret: docker_password 114 | repo: plugins/rsync 115 | username: 116 | from_secret: docker_username 117 | volumes: 118 | - name: docker_pipe 119 | path: \\\\.\\pipe\\docker_engine 120 | when: 121 | event: 122 | exclude: 123 | - pull_request 124 | 125 | volumes: 126 | - name: docker_pipe 127 | host: 128 | path: \\\\.\\pipe\\docker_engine 129 | 130 | trigger: 131 | ref: 132 | - refs/heads/master 133 | - "refs/tags/**" 134 | - "refs/pull/**" 135 | 136 | depends_on: 137 | - testing 138 | 139 | --- 140 | kind: pipeline 141 | name: windows-1809 142 | 143 | platform: 144 | os: windows 145 | arch: amd64 146 | version: 1809 147 | 148 | steps: 149 | - name: build-push 150 | pull: always 151 | image: golang:1.11-windowsservercore-1809 152 | commands: 153 | - "go build -v -ldflags \"-X main.version=${DRONE_COMMIT_SHA:0:8}\" -a -tags netgo -o release/windows/amd64/drone-rsync.exe" 154 | environment: 155 | CGO_ENABLED: 0 156 | GO111MODULE: on 157 | when: 158 | event: 159 | exclude: 160 | - tag 161 | 162 | - name: build-tag 163 | pull: always 164 | image: golang:1.11-windowsservercore-1809 165 | commands: 166 | - "go build -v -ldflags \"-X main.version=${DRONE_TAG##v}\" -a -tags netgo -o release/windows/amd64/drone-rsync.exe" 167 | environment: 168 | CGO_ENABLED: 0 169 | GO111MODULE: on 170 | when: 171 | event: 172 | - tag 173 | 174 | - name: executable 175 | pull: always 176 | image: golang:1.11-windowsservercore-1809 177 | commands: 178 | - ./release/windows/amd64/drone-rsync.exe --help 179 | 180 | - name: dryrun 181 | pull: always 182 | image: plugins/docker:windows-1809 183 | settings: 184 | daemon_off: true 185 | dockerfile: docker/Dockerfile.windows.1809 186 | dry_run: true 187 | password: 188 | from_secret: docker_password 189 | repo: plugins/rsync 190 | tags: windows-1809 191 | username: 192 | from_secret: docker_username 193 | volumes: 194 | - name: docker_pipe 195 | path: \\\\.\\pipe\\docker_engine 196 | when: 197 | event: 198 | - pull_request 199 | 200 | - name: publish 201 | pull: always 202 | image: plugins/docker:windows-1809 203 | settings: 204 | auto_tag: true 205 | auto_tag_suffix: windows-1809 206 | daemon_off: true 207 | dockerfile: docker/Dockerfile.windows.1809 208 | password: 209 | from_secret: docker_password 210 | repo: plugins/rsync 211 | username: 212 | from_secret: docker_username 213 | volumes: 214 | - name: docker_pipe 215 | path: \\\\.\\pipe\\docker_engine 216 | when: 217 | event: 218 | exclude: 219 | - pull_request 220 | 221 | volumes: 222 | - name: docker_pipe 223 | host: 224 | path: \\\\.\\pipe\\docker_engine 225 | 226 | trigger: 227 | ref: 228 | - refs/heads/master 229 | - "refs/tags/**" 230 | - "refs/pull/**" 231 | 232 | depends_on: 233 | - testing 234 | 235 | --- 236 | kind: pipeline 237 | name: notifications 238 | 239 | platform: 240 | os: windows 241 | arch: amd64 242 | version: 1809 243 | 244 | steps: 245 | - name: manifest 246 | pull: always 247 | image: plugins/manifest 248 | settings: 249 | auto_tag: true 250 | ignore_missing: true 251 | password: 252 | from_secret: docker_password 253 | spec: docker/manifest.tmpl 254 | username: 255 | from_secret: docker_username 256 | 257 | - name: microbadger 258 | pull: always 259 | image: plugins/webhook 260 | settings: 261 | urls: 262 | from_secret: microbadger_url 263 | 264 | trigger: 265 | ref: 266 | - refs/heads/master 267 | - "refs/tags/**" 268 | 269 | depends_on: 270 | - windows-1803 271 | - windows-1809 272 | 273 | ... 274 | -------------------------------------------------------------------------------- /.drone.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: pipeline 3 | name: testing 4 | 5 | platform: 6 | os: linux 7 | arch: amd64 8 | 9 | steps: 10 | - name: vet 11 | pull: always 12 | image: golang:1.11 13 | commands: 14 | - go vet ./... 15 | environment: 16 | GO111MODULE: on 17 | volumes: 18 | - name: gopath 19 | path: /go 20 | 21 | - name: test 22 | pull: always 23 | image: golang:1.11 24 | commands: 25 | - go test -cover ./... 26 | environment: 27 | GO111MODULE: on 28 | volumes: 29 | - name: gopath 30 | path: /go 31 | 32 | volumes: 33 | - name: gopath 34 | temp: {} 35 | 36 | trigger: 37 | ref: 38 | - refs/heads/master 39 | - "refs/tags/**" 40 | - "refs/pull/**" 41 | 42 | --- 43 | kind: pipeline 44 | name: linux-amd64 45 | 46 | platform: 47 | os: linux 48 | arch: amd64 49 | 50 | steps: 51 | - name: build-push 52 | pull: always 53 | image: golang:1.11 54 | commands: 55 | - "go build -v -ldflags \"-X main.version=${DRONE_COMMIT_SHA:0:8}\" -a -tags netgo -o release/linux/amd64/drone-rsync" 56 | environment: 57 | CGO_ENABLED: 0 58 | GO111MODULE: on 59 | when: 60 | event: 61 | exclude: 62 | - tag 63 | 64 | - name: build-tag 65 | pull: always 66 | image: golang:1.11 67 | commands: 68 | - "go build -v -ldflags \"-X main.version=${DRONE_TAG##v}\" -a -tags netgo -o release/linux/amd64/drone-rsync" 69 | environment: 70 | CGO_ENABLED: 0 71 | GO111MODULE: on 72 | when: 73 | event: 74 | - tag 75 | 76 | - name: executable 77 | pull: always 78 | image: golang:1.11 79 | commands: 80 | - ./release/linux/amd64/drone-rsync --help 81 | 82 | - name: dryrun 83 | pull: always 84 | image: plugins/docker:linux-amd64 85 | settings: 86 | daemon_off: false 87 | dockerfile: docker/Dockerfile.linux.amd64 88 | dry_run: true 89 | password: 90 | from_secret: docker_password 91 | repo: plugins/rsync 92 | tags: linux-amd64 93 | username: 94 | from_secret: docker_username 95 | when: 96 | event: 97 | - pull_request 98 | 99 | - name: publish 100 | pull: always 101 | image: plugins/docker:linux-amd64 102 | settings: 103 | auto_tag: true 104 | auto_tag_suffix: linux-amd64 105 | daemon_off: false 106 | dockerfile: docker/Dockerfile.linux.amd64 107 | password: 108 | from_secret: docker_password 109 | repo: plugins/rsync 110 | username: 111 | from_secret: docker_username 112 | when: 113 | event: 114 | exclude: 115 | - pull_request 116 | 117 | trigger: 118 | ref: 119 | - refs/heads/master 120 | - "refs/tags/**" 121 | - "refs/pull/**" 122 | 123 | depends_on: 124 | - testing 125 | 126 | --- 127 | kind: pipeline 128 | name: linux-arm64 129 | 130 | platform: 131 | os: linux 132 | arch: arm64 133 | 134 | steps: 135 | - name: build-push 136 | pull: always 137 | image: golang:1.11 138 | commands: 139 | - "go build -v -ldflags \"-X main.version=${DRONE_COMMIT_SHA:0:8}\" -a -tags netgo -o release/linux/arm64/drone-rsync" 140 | environment: 141 | CGO_ENABLED: 0 142 | GO111MODULE: on 143 | when: 144 | event: 145 | exclude: 146 | - tag 147 | 148 | - name: build-tag 149 | pull: always 150 | image: golang:1.11 151 | commands: 152 | - "go build -v -ldflags \"-X main.version=${DRONE_TAG##v}\" -a -tags netgo -o release/linux/arm64/drone-rsync" 153 | environment: 154 | CGO_ENABLED: 0 155 | GO111MODULE: on 156 | when: 157 | event: 158 | - tag 159 | 160 | - name: executable 161 | pull: always 162 | image: golang:1.11 163 | commands: 164 | - ./release/linux/arm64/drone-rsync --help 165 | 166 | - name: dryrun 167 | pull: always 168 | image: plugins/docker:linux-arm64 169 | settings: 170 | daemon_off: false 171 | dockerfile: docker/Dockerfile.linux.arm64 172 | dry_run: true 173 | password: 174 | from_secret: docker_password 175 | repo: plugins/rsync 176 | tags: linux-arm64 177 | username: 178 | from_secret: docker_username 179 | when: 180 | event: 181 | - pull_request 182 | 183 | - name: publish 184 | pull: always 185 | image: plugins/docker:linux-arm64 186 | settings: 187 | auto_tag: true 188 | auto_tag_suffix: linux-arm64 189 | daemon_off: false 190 | dockerfile: docker/Dockerfile.linux.arm64 191 | password: 192 | from_secret: docker_password 193 | repo: plugins/rsync 194 | username: 195 | from_secret: docker_username 196 | when: 197 | event: 198 | exclude: 199 | - pull_request 200 | 201 | trigger: 202 | ref: 203 | - refs/heads/master 204 | - "refs/tags/**" 205 | - "refs/pull/**" 206 | 207 | depends_on: 208 | - testing 209 | 210 | --- 211 | kind: pipeline 212 | name: linux-arm 213 | 214 | platform: 215 | os: linux 216 | arch: arm 217 | 218 | steps: 219 | - name: build-push 220 | pull: always 221 | image: golang:1.11 222 | commands: 223 | - "go build -v -ldflags \"-X main.version=${DRONE_COMMIT_SHA:0:8}\" -a -tags netgo -o release/linux/arm/drone-rsync" 224 | environment: 225 | CGO_ENABLED: 0 226 | GO111MODULE: on 227 | when: 228 | event: 229 | exclude: 230 | - tag 231 | 232 | - name: build-tag 233 | pull: always 234 | image: golang:1.11 235 | commands: 236 | - "go build -v -ldflags \"-X main.version=${DRONE_TAG##v}\" -a -tags netgo -o release/linux/arm/drone-rsync" 237 | environment: 238 | CGO_ENABLED: 0 239 | GO111MODULE: on 240 | when: 241 | event: 242 | - tag 243 | 244 | - name: executable 245 | pull: always 246 | image: golang:1.11 247 | commands: 248 | - ./release/linux/arm/drone-rsync --help 249 | 250 | - name: dryrun 251 | pull: always 252 | image: plugins/docker:linux-arm 253 | settings: 254 | daemon_off: false 255 | dockerfile: docker/Dockerfile.linux.arm 256 | dry_run: true 257 | password: 258 | from_secret: docker_password 259 | repo: plugins/rsync 260 | tags: linux-arm 261 | username: 262 | from_secret: docker_username 263 | when: 264 | event: 265 | - pull_request 266 | 267 | - name: publish 268 | pull: always 269 | image: plugins/docker:linux-arm 270 | settings: 271 | auto_tag: true 272 | auto_tag_suffix: linux-arm 273 | daemon_off: false 274 | dockerfile: docker/Dockerfile.linux.arm 275 | password: 276 | from_secret: docker_password 277 | repo: plugins/rsync 278 | username: 279 | from_secret: docker_username 280 | when: 281 | event: 282 | exclude: 283 | - pull_request 284 | 285 | trigger: 286 | ref: 287 | - refs/heads/master 288 | - "refs/tags/**" 289 | - "refs/pull/**" 290 | 291 | depends_on: 292 | - testing 293 | 294 | --- 295 | kind: pipeline 296 | name: notifications 297 | 298 | platform: 299 | os: linux 300 | arch: amd64 301 | 302 | steps: 303 | - name: manifest 304 | pull: always 305 | image: plugins/manifest 306 | settings: 307 | auto_tag: true 308 | ignore_missing: true 309 | password: 310 | from_secret: docker_password 311 | spec: docker/manifest.tmpl 312 | username: 313 | from_secret: docker_username 314 | 315 | - name: microbadger 316 | pull: always 317 | image: plugins/webhook 318 | settings: 319 | urls: 320 | from_secret: microbadger_url 321 | 322 | trigger: 323 | ref: 324 | - refs/heads/master 325 | - "refs/tags/**" 326 | 327 | depends_on: 328 | - linux-amd64 329 | - linux-arm64 330 | - linux-arm 331 | 332 | ... 333 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drone-plugins/drone-rsync/cf3eefecae41f28203f1367dba97cd17e7939c03/.github/pull_request_template.md -------------------------------------------------------------------------------- /.github/settings.yml: -------------------------------------------------------------------------------- 1 | repository: 2 | name: drone-rsync 3 | description: Drone plugin for deploying artifacts using rsync 4 | homepage: http://plugins.drone.io/drone-plugins/drone-rsync 5 | topics: drone, drone-plugin 6 | 7 | private: false 8 | has_issues: true 9 | has_wiki: false 10 | has_downloads: false 11 | 12 | default_branch: master 13 | 14 | allow_squash_merge: true 15 | allow_merge_commit: true 16 | allow_rebase_merge: true 17 | 18 | labels: 19 | - name: bug 20 | color: d73a4a 21 | description: Something isn't working 22 | - name: duplicate 23 | color: cfd3d7 24 | description: This issue or pull request already exists 25 | - name: enhancement 26 | color: a2eeef 27 | description: New feature or request 28 | - name: good first issue 29 | color: 7057ff 30 | description: Good for newcomers 31 | - name: help wanted 32 | color: 008672 33 | description: Extra attention is needed 34 | - name: invalid 35 | color: e4e669 36 | description: This doesn't seem right 37 | - name: question 38 | color: d876e3 39 | description: Further information is requested 40 | - name: renovate 41 | color: e99695 42 | description: Automated action from Renovate 43 | - name: wontfix 44 | color: ffffff 45 | description: This will not be worked on 46 | 47 | teams: 48 | - name: Admins 49 | permission: admin 50 | - name: Captain 51 | permission: admin 52 | - name: Maintainers 53 | permission: push 54 | 55 | branches: 56 | - name: master 57 | protection: 58 | required_pull_request_reviews: 59 | required_approving_review_count: 1 60 | dismiss_stale_reviews: false 61 | require_code_owner_reviews: false 62 | dismissal_restrictions: 63 | teams: 64 | - Admins 65 | - Captain 66 | required_status_checks: 67 | strict: true 68 | contexts: 69 | - continuous-integration/drone/pr 70 | enforce_admins: false 71 | restrictions: 72 | users: [] 73 | teams: [] 74 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | 26 | release/ 27 | vendor/ 28 | 29 | coverage.out 30 | drone-rsync 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # drone-rsync 2 | 3 | [![Build Status](http://cloud.drone.io/api/badges/drone-plugins/drone-rsync/status.svg)](http://cloud.drone.io/drone-plugins/drone-rsync) 4 | [![Gitter chat](https://badges.gitter.im/drone/drone.png)](https://gitter.im/drone/drone) 5 | [![Join the discussion at https://discourse.drone.io](https://img.shields.io/badge/discourse-forum-orange.svg)](https://discourse.drone.io) 6 | [![Drone questions at https://stackoverflow.com](https://img.shields.io/badge/drone-stackoverflow-orange.svg)](https://stackoverflow.com/questions/tagged/drone.io) 7 | [![](https://images.microbadger.com/badges/image/plugins/rsync.svg)](https://microbadger.com/images/plugins/rsync "Get your own image badge on microbadger.com") 8 | [![Go Doc](https://godoc.org/github.com/drone-plugins/drone-rsync?status.svg)](http://godoc.org/github.com/drone-plugins/drone-rsync) 9 | [![Go Report](https://goreportcard.com/badge/github.com/drone-plugins/drone-rsync)](https://goreportcard.com/report/github.com/drone-plugins/drone-rsync) 10 | 11 | > Warning: This plugin has not been migrated to Drone >= 0.5 yet, you are not able to use it with a current Drone version until somebody volunteers to update the plugin structure to the new format. 12 | 13 | Drone plugin to deploy or update a project via Rsync. For the usage information and a listing of the available options please take a look at [the docs](http://plugins.drone.io/drone-plugins/drone-rsync/). 14 | 15 | ## Build 16 | 17 | Build the binary with the following command: 18 | 19 | ```console 20 | export GOOS=linux 21 | export GOARCH=amd64 22 | export CGO_ENABLED=0 23 | export GO111MODULE=on 24 | 25 | go build -v -a -tags netgo -o release/linux/amd64/drone-rsync 26 | ``` 27 | 28 | ## Docker 29 | 30 | Build the Docker image with the following command: 31 | 32 | ```console 33 | docker build \ 34 | --label org.label-schema.build-date=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \ 35 | --label org.label-schema.vcs-ref=$(git rev-parse --short HEAD) \ 36 | --file docker/Dockerfile.linux.amd64 --tag plugins/rsync . 37 | ``` 38 | 39 | ## Usage 40 | 41 | ```console 42 | docker run --rm \ 43 | -e PLUGIN_USER=root \ 44 | -e PLUGIN_HOST=test.drone.io \ 45 | -e PLUGIN_PORT=22 \ 46 | -e PLUGIN_SOURCE=dist/ \ 47 | -e PLUGIN_TARGET=/path/on/server \ 48 | -e PLUGIN_DELETE=false \ 49 | -e PLUGIN_RECURSIVE=false \ 50 | -v $(pwd):$(pwd) \ 51 | -w $(pwd) \ 52 | plugins/rsync 53 | ``` 54 | -------------------------------------------------------------------------------- /docker/Dockerfile.linux.amd64: -------------------------------------------------------------------------------- 1 | FROM plugins/base:linux-amd64 2 | 3 | LABEL maintainer="Drone.IO Community " \ 4 | org.label-schema.name="Drone Rsync" \ 5 | org.label-schema.vendor="Drone.IO Community" \ 6 | org.label-schema.schema-version="1.0" 7 | 8 | RUN apk add --no-cache openssh-client rsync 9 | 10 | ADD release/linux/amd64/drone-rsync /bin/ 11 | ENTRYPOINT ["/bin/drone-rsync"] 12 | -------------------------------------------------------------------------------- /docker/Dockerfile.linux.arm: -------------------------------------------------------------------------------- 1 | FROM plugins/base:linux-arm 2 | 3 | LABEL maintainer="Drone.IO Community " \ 4 | org.label-schema.name="Drone Rsync" \ 5 | org.label-schema.vendor="Drone.IO Community" \ 6 | org.label-schema.schema-version="1.0" 7 | 8 | RUN apk add --no-cache openssh-client rsync 9 | 10 | ADD release/linux/arm/drone-rsync /bin/ 11 | ENTRYPOINT ["/bin/drone-rsync"] 12 | -------------------------------------------------------------------------------- /docker/Dockerfile.linux.arm64: -------------------------------------------------------------------------------- 1 | FROM plugins/base:linux-arm64 2 | 3 | LABEL maintainer="Drone.IO Community " \ 4 | org.label-schema.name="Drone Rsync" \ 5 | org.label-schema.vendor="Drone.IO Community" \ 6 | org.label-schema.schema-version="1.0" 7 | 8 | RUN apk add --no-cache openssh-client rsync 9 | 10 | ADD release/linux/arm64/drone-rsync /bin/ 11 | ENTRYPOINT ["/bin/drone-rsync"] 12 | -------------------------------------------------------------------------------- /docker/Dockerfile.windows.1803: -------------------------------------------------------------------------------- 1 | # escape=` 2 | FROM plugins/base:windows-1803 3 | 4 | LABEL maintainer="Drone.IO Community " ` 5 | org.label-schema.name="Drone Rsync" ` 6 | org.label-schema.vendor="Drone.IO Community" ` 7 | org.label-schema.schema-version="1.0" 8 | 9 | ADD release/windows/amd64/drone-rsync.exe C:/bin/drone-rsync.exe 10 | ENTRYPOINT [ "C:\\bin\\drone-rsync.exe" ] 11 | -------------------------------------------------------------------------------- /docker/Dockerfile.windows.1809: -------------------------------------------------------------------------------- 1 | # escape=` 2 | FROM plugins/base:windows-1809 3 | 4 | LABEL maintainer="Drone.IO Community " ` 5 | org.label-schema.name="Drone Rsync" ` 6 | org.label-schema.vendor="Drone.IO Community" ` 7 | org.label-schema.schema-version="1.0" 8 | 9 | ADD release/windows/amd64/drone-rsync.exe C:/bin/drone-rsync.exe 10 | ENTRYPOINT [ "C:\\bin\\drone-rsync.exe" ] 11 | -------------------------------------------------------------------------------- /docker/manifest.tmpl: -------------------------------------------------------------------------------- 1 | image: plugins/rsync:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}} 2 | {{#if build.tags}} 3 | tags: 4 | {{#each build.tags}} 5 | - {{this}} 6 | {{/each}} 7 | {{/if}} 8 | manifests: 9 | - 10 | image: plugins/rsync:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64 11 | platform: 12 | architecture: amd64 13 | os: linux 14 | - 15 | image: plugins/rsync:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64 16 | platform: 17 | architecture: arm64 18 | os: linux 19 | variant: v8 20 | - 21 | image: plugins/rsync:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm 22 | platform: 23 | architecture: arm 24 | os: linux 25 | variant: v7 26 | - 27 | image: plugins/rsync:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-1803 28 | platform: 29 | architecture: amd64 30 | os: windows 31 | version: 1803 32 | - 33 | image: plugins/rsync:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-1809 34 | platform: 35 | architecture: amd64 36 | os: windows 37 | version: 1809 38 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/drone-plugins/drone-rsync 2 | 3 | require ( 4 | github.com/drone/drone-go v0.0.0-20160502151758-eaa41f7836a1 5 | golang.org/x/crypto v0.0.0-20190211082320-193df9c0f06f 6 | golang.org/x/net v0.0.0-20190206195111-65e2d4e15006 // indirect 7 | golang.org/x/oauth2 v0.0.0-20190211080530-99b60b757ec1 // indirect 8 | golang.org/x/sys v0.0.0-20190211082325-3b5209105503 // indirect 9 | ) 10 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/drone/drone-go v0.0.0-20160502151758-eaa41f7836a1 h1:2fZ6NZF8Z37FLn5NIElsW3OELMY2xzQ2XPuXJmnAowE= 3 | github.com/drone/drone-go v0.0.0-20160502151758-eaa41f7836a1/go.mod h1:qVb1k1w9X5jgoGyLtbnfWNnd4XZfAwokxBmiutbpGqw= 4 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 5 | golang.org/x/crypto v0.0.0-20190211082320-193df9c0f06f h1:VvmIGh3I9z21SWnZh045de1pQskHBb/MGadaRcsifzo= 6 | golang.org/x/crypto v0.0.0-20190211082320-193df9c0f06f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 7 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 8 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 9 | golang.org/x/net v0.0.0-20190206195111-65e2d4e15006 h1:qGQCmRbjmnj+9f2jYFcvX5jObMHAVfm8YYY+ZJ9TVds= 10 | golang.org/x/net v0.0.0-20190206195111-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 11 | golang.org/x/oauth2 v0.0.0-20190211080530-99b60b757ec1 h1:459HUHOnAvrO6W2Pk/IKJoCyDBjv6X/eSGrXUE4fcM0= 12 | golang.org/x/oauth2 v0.0.0-20190211080530-99b60b757ec1/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 13 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 14 | golang.org/x/sys v0.0.0-20190211082325-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 15 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 16 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 17 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "net" 7 | "os" 8 | "os/exec" 9 | "os/user" 10 | "path" 11 | "path/filepath" 12 | "strconv" 13 | "strings" 14 | 15 | "github.com/drone/drone-go/drone" 16 | "github.com/drone/drone-go/plugin" 17 | "golang.org/x/crypto/ssh" 18 | ) 19 | 20 | type Rsync struct { 21 | Hosts drone.StringSlice `json:"host"` 22 | User string `json:"user"` 23 | Port int `json:"port"` 24 | Source string `json:"source"` 25 | Target string `json:"target"` 26 | Delete bool `json:"delete"` 27 | Recursive bool `json:"recursive"` 28 | Include drone.StringSlice `json:"include"` 29 | Exclude drone.StringSlice `json:"exclude"` 30 | Filter drone.StringSlice `json:"filter"` 31 | Commands []string `json:"commands"` 32 | } 33 | 34 | var ( 35 | version = "unknown" 36 | ) 37 | 38 | func main() { 39 | fmt.Printf("Drone Rsync Plugin built from %s\n", version) 40 | 41 | w := new(drone.Workspace) 42 | v := new(Rsync) 43 | plugin.Param("workspace", w) 44 | plugin.Param("vargs", v) 45 | if err := plugin.Parse(); err != nil { 46 | fmt.Println("Rsync: unable to parse invalid plugin input.") 47 | os.Exit(1) 48 | } 49 | if err := rsync(w, v); err != nil { 50 | fmt.Printf("Rsync: %s\n", err) 51 | os.Exit(1) 52 | } 53 | } 54 | 55 | func rsync(w *drone.Workspace, v *Rsync) error { 56 | // write the rsa private key if provided 57 | if err := writeKey(w); err != nil { 58 | return err 59 | } 60 | 61 | // default values 62 | if v.Port == 0 { 63 | v.Port = 22 64 | } 65 | if len(v.User) == 0 { 66 | v.User = "root" 67 | } 68 | if len(v.Source) == 0 { 69 | v.Source = "./" 70 | } 71 | 72 | // execute for each host 73 | for _, host := range v.Hosts.Slice() { 74 | // sync the files on the remote machine 75 | rs := v.buildRsync(host, w.Path) 76 | rs.Stderr = os.Stderr 77 | rs.Stdout = os.Stdout 78 | trace(rs) 79 | err := rs.Run() 80 | if err != nil { 81 | return err 82 | } 83 | 84 | // continue if no commands 85 | if len(v.Commands) == 0 { 86 | continue 87 | } 88 | 89 | // execute commands on remote server (reboot instance, etc) 90 | if err := v.run(w.Keys, host); err != nil { 91 | return err 92 | } 93 | } 94 | 95 | return nil 96 | } 97 | 98 | // Build rsync command 99 | func (rs *Rsync) buildRsync(host, root string) *exec.Cmd { 100 | 101 | var args []string 102 | args = append(args, "-az") 103 | 104 | // append recursive flag 105 | if rs.Recursive { 106 | args = append(args, "-r") 107 | } 108 | 109 | // append delete flag 110 | if rs.Delete { 111 | args = append(args, "--del") 112 | } 113 | 114 | // append custom ssh parameters 115 | args = append(args, "-e") 116 | args = append(args, fmt.Sprintf("ssh -p %d -o UserKnownHostsFile=/dev/null -o LogLevel=quiet -o StrictHostKeyChecking=no", rs.Port)) 117 | 118 | // append filtering rules 119 | for _, pattern := range rs.Include.Slice() { 120 | args = append(args, fmt.Sprintf("--include=%s", pattern)) 121 | } 122 | for _, pattern := range rs.Exclude.Slice() { 123 | args = append(args, fmt.Sprintf("--exclude=%s", pattern)) 124 | } 125 | for _, pattern := range rs.Filter.Slice() { 126 | args = append(args, fmt.Sprintf("--filter=%s", pattern)) 127 | } 128 | 129 | args = append(args, rs.globSource(root)...) 130 | args = append(args, fmt.Sprintf("%s@%s:%s", rs.User, host, rs.Target)) 131 | 132 | return exec.Command("rsync", args...) 133 | } 134 | 135 | // Run commands on the remote host 136 | func (rs *Rsync) run(keys *drone.Key, host string) error { 137 | 138 | // join the host and port if necessary 139 | addr := net.JoinHostPort(host, strconv.Itoa(rs.Port)) 140 | 141 | // trace command used for debugging in the build logs 142 | fmt.Printf("$ ssh %s@%s -p %d\n", rs.User, addr, rs.Port) 143 | 144 | signer, err := ssh.ParsePrivateKey([]byte(keys.Private)) 145 | if err != nil { 146 | return fmt.Errorf("Error parsing private key. %s.", err) 147 | } 148 | 149 | config := &ssh.ClientConfig{ 150 | User: rs.User, 151 | Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)}, 152 | } 153 | 154 | client, err := ssh.Dial("tcp", addr, config) 155 | if err != nil { 156 | return fmt.Errorf("Error dialing server. %s.", err) 157 | } 158 | 159 | session, err := client.NewSession() 160 | if err != nil { 161 | return fmt.Errorf("Error starting ssh session. %s.", err) 162 | } 163 | defer session.Close() 164 | 165 | session.Stdout = os.Stdout 166 | session.Stderr = os.Stderr 167 | return session.Run(strings.Join(rs.Commands, "\n")) 168 | } 169 | 170 | // globSource returns the names of all files matching the source pattern. 171 | // If there are no matches or an error occurs, the original source string is 172 | // returned. 173 | // 174 | // If the source path is not absolute the root path will be prepended to the 175 | // source path prior to matching. 176 | func (rs *Rsync) globSource(root string) []string { 177 | src := rs.Source 178 | if !path.IsAbs(rs.Source) { 179 | src = path.Join(root, rs.Source) 180 | } 181 | srcs, err := filepath.Glob(src) 182 | if err != nil || len(srcs) == 0 { 183 | return []string{rs.Source} 184 | } 185 | sep := fmt.Sprintf("%c", os.PathSeparator) 186 | if strings.HasSuffix(rs.Source, sep) { 187 | // Add back the trailing slash removed by path.Join() 188 | for i := range srcs { 189 | srcs[i] += sep 190 | } 191 | } 192 | return srcs 193 | } 194 | 195 | // Trace writes each command to standard error (preceded by a ‘$ ’) before it 196 | // is executed. Used for debugging your build. 197 | func trace(cmd *exec.Cmd) { 198 | fmt.Println("$", strings.Join(cmd.Args, " ")) 199 | } 200 | 201 | // Writes the RSA private key 202 | func writeKey(in *drone.Workspace) error { 203 | if in.Keys == nil || len(in.Keys.Private) == 0 { 204 | return nil 205 | } 206 | home := "/root" 207 | u, err := user.Current() 208 | if err == nil { 209 | home = u.HomeDir 210 | } 211 | sshpath := filepath.Join(home, ".ssh") 212 | if err := os.MkdirAll(sshpath, 0700); err != nil { 213 | return err 214 | } 215 | confpath := filepath.Join(sshpath, "config") 216 | privpath := filepath.Join(sshpath, "id_rsa") 217 | ioutil.WriteFile(confpath, []byte("StrictHostKeyChecking no\n"), 0700) 218 | return ioutil.WriteFile(privpath, []byte(in.Keys.Private), 0600) 219 | } 220 | -------------------------------------------------------------------------------- /main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // import ( 4 | // "encoding/json" 5 | // "fmt" 6 | // "io/ioutil" 7 | // "os" 8 | // "path/filepath" 9 | // "strings" 10 | // "testing" 11 | 12 | // "github.com/drone/drone-go/drone" 13 | // ) 14 | 15 | // var testdata = []struct { 16 | // host string 17 | // root string 18 | // rs Rsync 19 | // exp []string 20 | // err bool 21 | // }{ 22 | // { 23 | // "localhost", 24 | // ".", 25 | // Rsync{ 26 | // User: "drone", 27 | // Source: "testdata/*.txt", 28 | // Target: "/home/drone/testdata", 29 | // }, 30 | // []string{ 31 | // "rsync", 32 | // "-az", 33 | // "-e", 34 | // "ssh -p 0 -o UserKnownHostsFile=/dev/null -o LogLevel=quiet -o StrictHostKeyChecking=no", 35 | // "testdata/bar.txt", 36 | // "testdata/foo.txt", 37 | // "drone@localhost:/home/drone/testdata", 38 | // }, 39 | // false, 40 | // }, 41 | // { 42 | // "localhost", 43 | // ".", 44 | // Rsync{ 45 | // User: "drone", 46 | // Source: "testdata/foo*", 47 | // Target: "/home/drone/testdata", 48 | // }, 49 | // []string{ 50 | // "rsync", 51 | // "-az", 52 | // "-e", 53 | // "ssh -p 0 -o UserKnownHostsFile=/dev/null -o LogLevel=quiet -o StrictHostKeyChecking=no", 54 | // "testdata/foo", 55 | // "testdata/foo.txt", 56 | // "drone@localhost:/home/drone/testdata", 57 | // }, 58 | // false, 59 | // }, 60 | // { 61 | // "localhost", 62 | // ".", 63 | // Rsync{ 64 | // User: "drone", 65 | // Source: "testdata/bar-*.x86_64.rpm", 66 | // Target: "/home/drone/testdata", 67 | // }, 68 | // []string{ 69 | // "rsync", 70 | // "-az", 71 | // "-e", 72 | // "ssh -p 0 -o UserKnownHostsFile=/dev/null -o LogLevel=quiet -o StrictHostKeyChecking=no", 73 | // "testdata/bar-0.0.30+g4cdc188-1.x86_64.rpm", 74 | // "drone@localhost:/home/drone/testdata", 75 | // }, 76 | // false, 77 | // }, 78 | // { 79 | // "localhost", 80 | // ".", 81 | // Rsync{ 82 | // User: "drone", 83 | // Source: "notthere/*.txt", 84 | // Target: "/home/drone/testdata", 85 | // }, 86 | // []string{ 87 | // "rsync", 88 | // "-az", 89 | // "-e", 90 | // "ssh -p 0 -o UserKnownHostsFile=/dev/null -o LogLevel=quiet -o StrictHostKeyChecking=no", 91 | // "notthere/*.txt", 92 | // "drone@localhost:/home/drone/testdata", 93 | // }, 94 | // true, 95 | // }, 96 | // { 97 | // "localhost", 98 | // ".", 99 | // Rsync{ 100 | // User: "drone", 101 | // Source: "testdata/", 102 | // Target: "/home/drone/testdata", 103 | // Recursive: true, 104 | // Delete: true, 105 | // }, 106 | // []string{ 107 | // "rsync", 108 | // "-az", 109 | // "-r", 110 | // "--del", 111 | // "-e", 112 | // "ssh -p 0 -o UserKnownHostsFile=/dev/null -o LogLevel=quiet -o StrictHostKeyChecking=no", 113 | // "testdata/", 114 | // "drone@localhost:/home/drone/testdata", 115 | // }, 116 | // false, 117 | // }, 118 | // { 119 | // "localhost", 120 | // ".", 121 | // Rsync{ 122 | // User: "drone", 123 | // Source: "testdata/foo.txt", 124 | // Target: "/home/drone/testdata", 125 | // }, 126 | // []string{ 127 | // "rsync", 128 | // "-az", 129 | // "-e", 130 | // "ssh -p 0 -o UserKnownHostsFile=/dev/null -o LogLevel=quiet -o StrictHostKeyChecking=no", 131 | // "testdata/foo.txt", 132 | // "drone@localhost:/home/drone/testdata", 133 | // }, 134 | // false, 135 | // }, 136 | // { 137 | // "localhost", 138 | // ".", 139 | // Rsync{ 140 | // User: "drone", 141 | // Source: "testdata/bar.txt", 142 | // Target: "/home/drone/testdata", 143 | // }, 144 | // []string{ 145 | // "rsync", 146 | // "-az", 147 | // "-e", 148 | // "ssh -p 0 -o UserKnownHostsFile=/dev/null -o LogLevel=quiet -o StrictHostKeyChecking=no", 149 | // "testdata/bar.txt", 150 | // "drone@localhost:/home/drone/testdata", 151 | // }, 152 | // false, 153 | // }, 154 | // { 155 | // "localhost", 156 | // ".", 157 | // Rsync{ 158 | // User: "drone", 159 | // Source: abs("testdata/bar.txt"), 160 | // Target: "/home/drone/testdata", 161 | // }, 162 | // []string{ 163 | // "rsync", 164 | // "-az", 165 | // "-e", 166 | // "ssh -p 0 -o UserKnownHostsFile=/dev/null -o LogLevel=quiet -o StrictHostKeyChecking=no", 167 | // abs("testdata/bar.txt"), 168 | // "drone@localhost:/home/drone/testdata", 169 | // }, 170 | // false, 171 | // }, 172 | // { 173 | // "localhost", 174 | // ".", 175 | // Rsync{ 176 | // User: "drone", 177 | // Target: "/home/drone/testdata", 178 | // Source: "./", 179 | // Include: ss([]string{"testdata/"}), 180 | // Exclude: ss([]string{"*.txt", "*.rpm"}), 181 | // }, 182 | // []string{ 183 | // "rsync", 184 | // "-az", 185 | // "-e", 186 | // "ssh -p 0 -o UserKnownHostsFile=/dev/null -o LogLevel=quiet -o StrictHostKeyChecking=no", 187 | // "--include=testdata/", 188 | // "--exclude=*.txt", 189 | // "--exclude=*.rpm", 190 | // "./", 191 | // "drone@localhost:/home/drone/testdata", 192 | // }, 193 | // false, 194 | // }, 195 | // { 196 | // "localhost", 197 | // ".", 198 | // Rsync{ 199 | // User: "drone", 200 | // Source: "./", 201 | // Target: "/home/drone/testdata", 202 | // Filter: ss([]string{"+ testdata/", "- testdata/*.txt", "- testdata/*.rpm"}), 203 | // }, 204 | // []string{ 205 | // "rsync", 206 | // "-az", 207 | // "-e", 208 | // "ssh -p 0 -o UserKnownHostsFile=/dev/null -o LogLevel=quiet -o StrictHostKeyChecking=no", 209 | // "--filter=+ testdata/", 210 | // "--filter=- testdata/*.txt", 211 | // "--filter=- testdata/*.rpm", 212 | // "./", 213 | // "drone@localhost:/home/drone/testdata", 214 | // }, 215 | // false, 216 | // }, 217 | // } 218 | 219 | // func TestRsync(t *testing.T) { 220 | // if len(os.Getenv("DRONE")) == 0 { 221 | // t.Skip("Skipping unless run under Drone CI") 222 | // } 223 | // w := drone.Workspace{ 224 | // Keys: readKey("testdata/id_rsa"), 225 | // Path: os.Getenv("DRONE_DIR"), 226 | // } 227 | // for i, data := range testdata { 228 | // v := data.rs 229 | // v.Hosts = ss([]string{data.host}) 230 | // err := rsync(&w, &v) 231 | // if err != nil { 232 | // if !data.err { 233 | // t.Errorf("Case %d: %s", i, err) 234 | // } 235 | // } else { 236 | // if data.err { 237 | // t.Errorf("Case %d: %s", i, err) 238 | // } 239 | // } 240 | // } 241 | // } 242 | 243 | // func TestBuildRsync(t *testing.T) { 244 | // for i, data := range testdata { 245 | // c := data.rs.buildRsync(data.host, data.root) 246 | // if len(c.Args) != len(data.exp) { 247 | // t.Fatalf("Case %d: Expected %d, got %d", i, len(data.exp), len(c.Args)) 248 | // } 249 | // for j := range c.Args { 250 | // if c.Args[j] != data.exp[j] { 251 | // t.Fatalf("Case %d:\nExpected:\n\t%s\nGot:\n\t%s", j, strings.Join(data.exp, " "), strings.Join(c.Args, " ")) 252 | // } 253 | // } 254 | // } 255 | // } 256 | 257 | // func abs(path string) string { 258 | // s, err := filepath.Abs(path) 259 | // if err != nil { 260 | // panic(err) 261 | // } 262 | // return s 263 | // } 264 | 265 | // func ss(args []string) drone.StringSlice { 266 | // j, err := json.Marshal(args) 267 | // if err != nil { 268 | // panic(err) 269 | // } 270 | // s := drone.StringSlice{} 271 | // err = s.UnmarshalJSON(j) 272 | // if err != nil { 273 | // panic(err) 274 | // } 275 | // return s 276 | // } 277 | 278 | // func readKey(priv string) *drone.Key { 279 | // pubKey, err := ioutil.ReadFile(fmt.Sprintf("%s.pub", priv)) 280 | // if err != nil { 281 | // panic(err) 282 | // } 283 | // privKey, err := ioutil.ReadFile(priv) 284 | // if err != nil { 285 | // panic(err) 286 | // } 287 | // return &drone.Key{ 288 | // Public: string(pubKey[:]), 289 | // Private: string(privKey[:]), 290 | // } 291 | // } 292 | -------------------------------------------------------------------------------- /pipeline.libsonnet: -------------------------------------------------------------------------------- 1 | local windows_pipe = '\\\\\\\\.\\\\pipe\\\\docker_engine'; 2 | local windows_pipe_volume = 'docker_pipe'; 3 | local test_pipeline_name = 'testing'; 4 | 5 | local windows(os) = os == 'windows'; 6 | 7 | local golang_image(os, version) = 8 | 'golang:' + '1.11' + if windows(os) then '-windowsservercore-' + version else ''; 9 | 10 | { 11 | test(os='linux', arch='amd64', version=''):: 12 | local is_windows = windows(os); 13 | local golang = golang_image(os, version); 14 | local volumes = if is_windows then [{name: 'gopath', path: 'C:\\\\gopath'}] else [{name: 'gopath', path: '/go',}]; 15 | { 16 | kind: 'pipeline', 17 | name: test_pipeline_name, 18 | platform: { 19 | os: os, 20 | arch: arch, 21 | version: if std.length(version) > 0 then version, 22 | }, 23 | steps: [ 24 | { 25 | name: 'vet', 26 | image: golang, 27 | pull: 'always', 28 | environment: { 29 | GO111MODULE: 'on', 30 | }, 31 | commands: [ 32 | 'go vet ./...', 33 | ], 34 | volumes: volumes, 35 | }, 36 | { 37 | name: 'test', 38 | image: golang, 39 | pull: 'always', 40 | environment: { 41 | GO111MODULE: 'on', 42 | }, 43 | commands: [ 44 | 'go test -cover ./...', 45 | ], 46 | volumes: volumes, 47 | }, 48 | ], 49 | trigger: { 50 | ref: [ 51 | 'refs/heads/master', 52 | 'refs/tags/**', 53 | 'refs/pull/**', 54 | ], 55 | }, 56 | volumes: [{name: 'gopath', temp: {}}] 57 | }, 58 | 59 | build(name, os='linux', arch='amd64', version=''):: 60 | local is_windows = windows(os); 61 | local tag = if is_windows then os + '-' + version else os + '-' + arch; 62 | local file_suffix = std.strReplace(tag, '-', '.'); 63 | local volumes = if is_windows then [{ name: windows_pipe_volume, path: windows_pipe }] else []; 64 | local golang = golang_image(os, version); 65 | local plugin_repo = 'plugins/' + std.splitLimit(name, '-', 1)[1]; 66 | local extension = if is_windows then '.exe' else ''; 67 | { 68 | kind: 'pipeline', 69 | name: tag, 70 | platform: { 71 | os: os, 72 | arch: arch, 73 | version: if std.length(version) > 0 then version, 74 | }, 75 | steps: [ 76 | { 77 | name: 'build-push', 78 | image: golang, 79 | pull: 'always', 80 | environment: { 81 | CGO_ENABLED: '0', 82 | GO111MODULE: 'on', 83 | }, 84 | commands: [ 85 | 'go build -v -ldflags "-X main.version=${DRONE_COMMIT_SHA:0:8}" -a -tags netgo -o release/' + os + '/' + arch + '/' + name + extension, 86 | ], 87 | when: { 88 | event: { 89 | exclude: ['tag'], 90 | }, 91 | }, 92 | }, 93 | { 94 | name: 'build-tag', 95 | image: golang, 96 | pull: 'always', 97 | environment: { 98 | CGO_ENABLED: '0', 99 | GO111MODULE: 'on', 100 | }, 101 | commands: [ 102 | 'go build -v -ldflags "-X main.version=${DRONE_TAG##v}" -a -tags netgo -o release/' + os + '/' + arch + '/' + name + extension, 103 | ], 104 | when: { 105 | event: ['tag'], 106 | }, 107 | }, 108 | { 109 | name: 'executable', 110 | image: golang, 111 | pull: 'always', 112 | commands: [ 113 | './release/' + os + '/' + arch + '/' + name + extension + ' --help', 114 | ], 115 | }, 116 | { 117 | name: 'dryrun', 118 | image: 'plugins/docker:' + tag, 119 | pull: 'always', 120 | settings: { 121 | dry_run: true, 122 | tags: tag, 123 | dockerfile: 'docker/Dockerfile.' + file_suffix, 124 | daemon_off: if is_windows then 'true' else 'false', 125 | repo: plugin_repo, 126 | username: { from_secret: 'docker_username' }, 127 | password: { from_secret: 'docker_password' }, 128 | }, 129 | volumes: if std.length(volumes) > 0 then volumes, 130 | when: { 131 | event: ['pull_request'], 132 | }, 133 | }, 134 | { 135 | name: 'publish', 136 | image: 'plugins/docker:' + tag, 137 | pull: 'always', 138 | settings: { 139 | auto_tag: true, 140 | auto_tag_suffix: tag, 141 | daemon_off: if is_windows then 'true' else 'false', 142 | dockerfile: 'docker/Dockerfile.' + file_suffix, 143 | repo: plugin_repo, 144 | username: { from_secret: 'docker_username' }, 145 | password: { from_secret: 'docker_password' }, 146 | }, 147 | volumes: if std.length(volumes) > 0 then volumes, 148 | when: { 149 | event: { 150 | exclude: ['pull_request'], 151 | }, 152 | }, 153 | }, 154 | ], 155 | trigger: { 156 | ref: [ 157 | 'refs/heads/master', 158 | 'refs/tags/**', 159 | 'refs/pull/**', 160 | ], 161 | }, 162 | depends_on: [test_pipeline_name], 163 | volumes: if is_windows then [{ name: windows_pipe_volume, host: { path: windows_pipe } }], 164 | }, 165 | 166 | notifications(os='linux', arch='amd64', version='', depends_on=[]):: 167 | { 168 | kind: 'pipeline', 169 | name: 'notifications', 170 | platform: { 171 | os: os, 172 | arch: arch, 173 | version: if std.length(version) > 0 then version, 174 | }, 175 | steps: [ 176 | { 177 | name: 'manifest', 178 | image: 'plugins/manifest', 179 | pull: 'always', 180 | settings: { 181 | username: { from_secret: 'docker_username' }, 182 | password: { from_secret: 'docker_password' }, 183 | spec: 'docker/manifest.tmpl', 184 | ignore_missing: true, 185 | auto_tag: true, 186 | }, 187 | }, 188 | { 189 | name: 'microbadger', 190 | image: 'plugins/webhook', 191 | pull: 'always', 192 | settings: { 193 | urls: { from_secret: 'microbadger_url' }, 194 | }, 195 | }, 196 | ], 197 | trigger: { 198 | ref: [ 199 | 'refs/heads/master', 200 | 'refs/tags/**', 201 | ], 202 | }, 203 | depends_on: depends_on, 204 | }, 205 | } 206 | --------------------------------------------------------------------------------