Compare commits
	
		
			109 Commits
		
	
	
		
			v0.0.3
			...
			eb443bd494
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | eb443bd494 | ||
|   | 9132c85c5f | ||
|   | 7f18bf0ec8 | ||
|   | 35c03a241d | ||
|   | 8b7c180c3f | ||
|   | ff85246aca | ||
|   | 6aff6492ae | ||
|   | 6b2d3092e3 | ||
|   | f5c6c234bd | ||
|   | 17026f90b8 | ||
|   | bf323b8729 | ||
|   | e55e4eabdc | ||
|   | bc835cba55 | ||
|   | 98b7132065 | ||
|   | 3d59448764 | ||
|   | 2a829c0ed2 | ||
|   | 4f2c27bbc2 | ||
|   | b03d7257ae | ||
|   | f042d742db | ||
|   | ad9a378b7f | ||
|   | 172d4632fe | ||
|   | 93e17a47f9 | ||
|   | c6ff96b7f6 | ||
|   | 7622c01418 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 9ba62064d2 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | f314a5399e | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 699fa1181c | ||
|   | 9f34cc3e55 | ||
|   | 917f8b81df | ||
|   | 78e7f475f3 | ||
|   | dfde1f50eb | ||
|   | 35093a99f9 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 96947ea2bd | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | aef31a66e3 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 950981a11d | ||
|   | 5878fc908f | ||
|   | abb6d70bee | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | b03ad1c124 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | d398e64fcf | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 3710327b67 | ||
|   | d47d818ab7 | ||
|   | 7435be3541 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 11da0c97f9 | ||
|   | ec73feb854 | ||
|   | cdeb36bbf9 | ||
|   | c209399d24 | ||
|   | 952a6e3250 | ||
|   | 82ebdbe3ed | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 2cd029d317 | ||
|   | e0dbae8ff0 | ||
|   | 3e84ad0651 | ||
|   | 8a92fcdb1e | ||
|   | 6cd4f0cace | ||
|   | 43abfa778d | ||
|   | c8e0cef94a | ||
|   | d47875703f | ||
|   | a4e63f0f1a | ||
|   | 7cc0f645c7 | ||
|   | dcb457bb6f | ||
|   | 11c56b52d3 | ||
|   | 51b937b31f | ||
|   | 98930d398c | ||
|   | 9ec0623f29 | ||
|   | 7f8a7c1019 | ||
|   | 2ce642f289 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 6291b9e86b | ||
|   | 6d1fc191a8 | ||
|   | 233f762873 | ||
|   | b3f8d37ead | ||
|   | f57f59fba9 | ||
|   | 8a54b39459 | ||
|   | eb319b796f | ||
|   | 3c3575eb49 | ||
|   | edc8ec9139 | ||
|   | 167d6d7ff4 | ||
|   | ecd6a3623b | ||
|   | 31b514c281 | ||
|   | 5924b2b6d4 | ||
|   | a2fea1040d | ||
|   | 8535291767 | ||
|   | faff4f4218 | ||
|   | ddd9176502 | ||
|   | 326e14ddd1 | ||
|   | 0329cffdaa | ||
|   | 6df9245376 | ||
|   | 4df1959b05 | ||
|   | 1c43a9662a | ||
|   | 2949c755a2 | ||
|   | aefa39daef | ||
|   | 2305e4000a | ||
|   | c51573a06a | ||
|   | d068cd7f84 | ||
|   | 8ba3cfe760 | ||
|   | 1a6b426141 | ||
|   | 8b3eebcc8d | ||
|   | 861f2e0e7b | ||
|   | 6971270956 | ||
|   | bac6c9e026 | ||
|   | b04405242e | ||
|   | 5cb36bda99 | ||
|   | 6c5771fab8 | ||
|   | 193fd4eaa9 | ||
|   | a5de8af6d5 | ||
|   | 671c934c80 | ||
|   | 8da6e3d335 | ||
|   | 196ea3f88f | ||
|   | 034b0ad00c | ||
|   | 95e250284b | ||
|   | a593d18cb8 | 
							
								
								
									
										13
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
										Normal 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
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| version: 2 | ||||
| updates: | ||||
|   - package-ecosystem: github-actions | ||||
|     directory: / | ||||
|     schedule: | ||||
|       interval: weekly | ||||
|   - package-ecosystem: gomod | ||||
|     directory: / | ||||
|     schedule: | ||||
|       interval: weekly | ||||
							
								
								
									
										39
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										39
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,39 +0,0 @@ | ||||
| name: scp files | ||||
| on: [push] | ||||
| jobs: | ||||
|  | ||||
|   build: | ||||
|     name: Build | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|     - uses: actions/checkout@master | ||||
|     - name: copy file via ssh password | ||||
|       uses: appleboy/scp-action@master | ||||
|       with: | ||||
|         host: ${{ secrets.HOST }} | ||||
|         username: ${{ secrets.USERNAME }} | ||||
|         password: ${{ secrets.PASSWORD }} | ||||
|         port: ${{ secrets.PORT }} | ||||
|         source: "tests/a.txt,tests/b.txt" | ||||
|         target: "test" | ||||
|  | ||||
|     - name: copy file via ssh key | ||||
|       uses: appleboy/scp-action@master | ||||
|       with: | ||||
|         host: ${{ secrets.HOST }} | ||||
|         username: ${{ secrets.USERNAME }} | ||||
|         key: ${{ secrets.KEY }} | ||||
|         port: ${{ secrets.PORT }} | ||||
|         source: "tests/a.txt,tests/b.txt" | ||||
|         target: "test" | ||||
|  | ||||
|     - name: remove the specified number of leading path elements | ||||
|       uses: appleboy/scp-action@master | ||||
|       with: | ||||
|         host: ${{ secrets.HOST }} | ||||
|         username: ${{ secrets.USERNAME }} | ||||
|         key: ${{ secrets.KEY }} | ||||
|         port: ${{ secrets.PORT }} | ||||
|         source: "tests/a.txt,tests/b.txt" | ||||
|         target: "foobar" | ||||
|         strip_components: 1 | ||||
							
								
								
									
										33
									
								
								.github/workflows/goreleaser.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								.github/workflows/goreleaser.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| name: Goreleaser | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     tags: | ||||
|       - "*" | ||||
|  | ||||
| permissions: | ||||
|   contents: write | ||||
|  | ||||
| jobs: | ||||
|   goreleaser: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v4 | ||||
|         with: | ||||
|           fetch-depth: 0 | ||||
|  | ||||
|       - name: Setup go | ||||
|         uses: actions/setup-go@v5 | ||||
|         with: | ||||
|           go-version: "^1" | ||||
|  | ||||
|       - name: Run GoReleaser | ||||
|         uses: goreleaser/goreleaser-action@v6 | ||||
|         with: | ||||
|           # either 'goreleaser' (default) or 'goreleaser-pro' | ||||
|           distribution: goreleaser | ||||
|           version: latest | ||||
|           args: release --clean | ||||
|         env: | ||||
|           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||
							
								
								
									
										150
									
								
								.github/workflows/stable.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								.github/workflows/stable.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,150 @@ | ||||
| name: v1 version | ||||
| on: [push] | ||||
| jobs: | ||||
|   testing: | ||||
|     name: test scp action | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: checkout | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: copy file via ssh password | ||||
|         uses: appleboy/scp-action@v1 | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           password: ${{ secrets.PASSWORD }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: "tests/a.txt,tests/b.txt" | ||||
|           target: "test" | ||||
|  | ||||
|       - name: copy file via ssh key | ||||
|         uses: appleboy/scp-action@v1 | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           key: ${{ secrets.KEY }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: "tests/a.txt,tests/b.txt" | ||||
|           target: "test" | ||||
|  | ||||
|       - name: remove the specified number of leading path elements | ||||
|         uses: appleboy/scp-action@v1 | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           key: ${{ secrets.KEY }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: "tests/a.txt,tests/b.txt" | ||||
|           target: "foobar" | ||||
|           strip_components: 1 | ||||
|  | ||||
|       - name: ssh key with passphrase | ||||
|         uses: appleboy/scp-action@v1 | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           key: ${{ secrets.SSH2 }} | ||||
|           passphrase: ${{ secrets.PASSPHRASE }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: "tests/a.txt,tests/b.txt" | ||||
|           target: "test" | ||||
|  | ||||
|       - name: use insecure cipher | ||||
|         uses: appleboy/scp-action@v1 | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           key: ${{ secrets.SSH2 }} | ||||
|           passphrase: ${{ secrets.PASSPHRASE }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: "tests/a.txt,tests/b.txt" | ||||
|           target: "test" | ||||
|           use_insecure_cipher: true | ||||
|  | ||||
|   deploy: | ||||
|     name: test deploy artifact | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: checkout | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - run: echo hello > world.txt | ||||
|  | ||||
|       - uses: actions/upload-artifact@v4 | ||||
|         with: | ||||
|           name: my-artifact | ||||
|           path: world.txt | ||||
|  | ||||
|       - uses: actions/download-artifact@v5 | ||||
|         with: | ||||
|           name: my-artifact | ||||
|           path: distfiles | ||||
|  | ||||
|       - name: copy file to server | ||||
|         uses: appleboy/scp-action@v1 | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           key: ${{ secrets.KEY }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: distfiles/* | ||||
|           target: test | ||||
|  | ||||
|   changes: | ||||
|     name: test changed-files | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: checkout | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: Get changed files | ||||
|         id: changed-files | ||||
|         uses: tj-actions/changed-files@v45 | ||||
|         with: | ||||
|           since_last_remote_commit: true | ||||
|           separator: "," | ||||
|  | ||||
|       - name: copy file to server | ||||
|         uses: appleboy/scp-action@v1 | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           key: ${{ secrets.KEY }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: ${{ steps.changed-files.outputs.all_changed_files }} | ||||
|           target: test | ||||
|  | ||||
|   target: | ||||
|     name: test target folder | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: checkout | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: copy file to server | ||||
|         uses: appleboy/scp-action@v1 | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           key: ${{ secrets.KEY }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: tests/a.txt,tests/b.txt | ||||
|           target: foobar foobar   1234 | ||||
|  | ||||
|   multipleHost: | ||||
|     name: test Multiple Host | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: checkout | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: copy file to server | ||||
|         uses: appleboy/scp-action@v1 | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }}:${{ secrets.PORT }},${{ secrets.HOST }}:${{ secrets.PORT }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           key: ${{ secrets.KEY }} | ||||
|           port: 1024 | ||||
|           source: tests/a.txt,tests/b.txt | ||||
|           target: foobar | ||||
							
								
								
									
										150
									
								
								.github/workflows/testing.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								.github/workflows/testing.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,150 @@ | ||||
| name: lint and test | ||||
| on: [push] | ||||
| jobs: | ||||
|   testing: | ||||
|     name: test scp action | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: checkout | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: copy file via ssh password | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           password: ${{ secrets.PASSWORD }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: "tests/a.txt,tests/b.txt" | ||||
|           target: "test" | ||||
|  | ||||
|       - name: copy file via ssh key | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           key: ${{ secrets.KEY }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: "tests/a.txt,tests/b.txt" | ||||
|           target: "test" | ||||
|  | ||||
|       - name: remove the specified number of leading path elements | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           key: ${{ secrets.KEY }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: "tests/a.txt,tests/b.txt" | ||||
|           target: "foobar" | ||||
|           strip_components: 1 | ||||
|  | ||||
|       - name: ssh key with passphrase | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           key: ${{ secrets.SSH2 }} | ||||
|           passphrase: ${{ secrets.PASSPHRASE }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: "tests/a.txt,tests/b.txt" | ||||
|           target: "test" | ||||
|  | ||||
|       - name: use insecure cipher | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           key: ${{ secrets.SSH2 }} | ||||
|           passphrase: ${{ secrets.PASSPHRASE }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: "tests/a.txt,tests/b.txt" | ||||
|           target: "test" | ||||
|           use_insecure_cipher: true | ||||
|  | ||||
|   deploy: | ||||
|     name: test deploy artifact | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: checkout | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - run: echo hello > world.txt | ||||
|  | ||||
|       - uses: actions/upload-artifact@v4 | ||||
|         with: | ||||
|           name: my-artifact | ||||
|           path: world.txt | ||||
|  | ||||
|       - uses: actions/download-artifact@v5 | ||||
|         with: | ||||
|           name: my-artifact | ||||
|           path: distfiles | ||||
|  | ||||
|       - name: copy file to server | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           key: ${{ secrets.KEY }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: distfiles/* | ||||
|           target: test | ||||
|  | ||||
|   changes: | ||||
|     name: test changed-files | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: checkout | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: Get changed files | ||||
|         id: changed-files | ||||
|         uses: tj-actions/changed-files@v46 | ||||
|         with: | ||||
|           since_last_remote_commit: true | ||||
|           separator: "," | ||||
|  | ||||
|       - name: copy file to server | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           key: ${{ secrets.KEY }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: ${{ steps.changed-files.outputs.all_changed_files }} | ||||
|           target: test | ||||
|  | ||||
|   target: | ||||
|     name: test target folder | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: checkout | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: copy file to server | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           key: ${{ secrets.KEY }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: tests/a.txt,tests/b.txt | ||||
|           target: foobar foobar   1234 | ||||
|  | ||||
|   multipleHost: | ||||
|     name: test Multiple Host | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: checkout | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: copy file to server | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }}:${{ secrets.PORT }},${{ secrets.HOST }}:${{ secrets.PORT }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           key: ${{ secrets.KEY }} | ||||
|           port: 1024 | ||||
|           source: tests/a.txt,tests/b.txt | ||||
|           target: foobar | ||||
							
								
								
									
										28
									
								
								.goreleaser.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								.goreleaser.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| builds: | ||||
|   - # If true, skip the build. | ||||
|     # Useful for library projects. | ||||
|     # Default is false | ||||
|     skip: true | ||||
|  | ||||
| changelog: | ||||
|   use: github | ||||
|   groups: | ||||
|     - title: Features | ||||
|       regexp: "^.*feat[(\\w)]*:+.*$" | ||||
|       order: 0 | ||||
|     - title: "Bug fixes" | ||||
|       regexp: "^.*fix[(\\w)]*:+.*$" | ||||
|       order: 1 | ||||
|     - title: "Enhancements" | ||||
|       regexp: "^.*chore[(\\w)]*:+.*$" | ||||
|       order: 2 | ||||
|     - title: "Refactor" | ||||
|       regexp: "^.*refactor[(\\w)]*:+.*$" | ||||
|       order: 3 | ||||
|     - title: "Build process updates" | ||||
|       regexp: ^.*?(build|ci)(\(.+\))??!?:.+$ | ||||
|       order: 4 | ||||
|     - title: "Documentation updates" | ||||
|       regexp: ^.*?docs?(\(.+\))??!?:.+$ | ||||
|       order: 4 | ||||
|     - title: Others | ||||
| @@ -1,5 +0,0 @@ | ||||
| FROM appleboy/drone-scp:1.5.3-linux-amd64 | ||||
|  | ||||
| ADD entrypoint.sh /entrypoint.sh | ||||
| RUN chmod +x /entrypoint.sh | ||||
| ENTRYPOINT ["/entrypoint.sh"] | ||||
							
								
								
									
										387
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										387
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,135 +1,348 @@ | ||||
| # 🚀 SCP for GitHub Actions | ||||
|  | ||||
| [GitHub Action](https://developer.github.com/actions/) for copying files and artifacts via SSH. | ||||
| [繁體中文](README.zh-tw.md) | [简体中文](README.zh-cn.md) | ||||
|  | ||||
|  | ||||
| [GitHub Action](https://github.com/features/actions) for copying files and artifacts via SSH. | ||||
|  | ||||
| [](https://github.com/appleboy/scp-action/actions) | ||||
| [](https://github.com/appleboy/scp-action/actions/workflows/stable.yml) | ||||
| [](https://github.com/appleboy/scp-action/actions/workflows/testing.yml) | ||||
|  | ||||
| ## Usage | ||||
| > **Note:** Only supports **Linux** [docker](https://www.docker.com/) containers. | ||||
|  | ||||
| copy files and artifacts via SSH as blow. | ||||
| --- | ||||
|  | ||||
| ## ✨ Features | ||||
|  | ||||
| - ✅ Copy files and artifacts to one or multiple remote servers via SSH | ||||
| - ✅ Supports both SSH key and password authentication | ||||
| - ✅ Full SSH Proxy (jump host) support | ||||
| - ✅ Handles Linux ↔ Windows path conversion | ||||
| - ✅ Integrates with GitHub Artifacts workflow | ||||
| - ✅ Incremental and differential file transfer | ||||
| - ✅ Rich configuration options for advanced use cases | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 📦 Table of Contents | ||||
|  | ||||
| - [🚀 SCP for GitHub Actions](#-scp-for-github-actions) | ||||
|   - [✨ Features](#-features) | ||||
|   - [📦 Table of Contents](#-table-of-contents) | ||||
|   - [🚀 Quick Start](#-quick-start) | ||||
|   - [⚙️ Configuration](#️-configuration) | ||||
|     - [🔌 Connection Settings](#-connection-settings) | ||||
|     - [📁 File Transfer Settings](#-file-transfer-settings) | ||||
|     - [🌐 Proxy Settings](#-proxy-settings) | ||||
|   - [🛡️ Best Practices \& Security](#️-best-practices--security) | ||||
|   - [🖥️ Cross-Platform Notes](#️-cross-platform-notes) | ||||
|   - [💡 Usage Examples](#-usage-examples) | ||||
|     - [🧩 Scenario Guide](#-scenario-guide) | ||||
|       - [Example 1: Basic SSH Password](#example-1-basic-ssh-password) | ||||
|       - [Example 2: Multi-server](#example-2-multi-server) | ||||
|       - [Example 3: Changed Files Only](#example-3-changed-files-only) | ||||
|       - [Example 4: Artifacts Integration](#example-4-artifacts-integration) | ||||
|       - [Example 5: Windows Server](#example-5-windows-server) | ||||
|   - [🗝️ SSH Key Setup](#️-ssh-key-setup) | ||||
|   - [🧰 Common Error Codes](#-common-error-codes) | ||||
|   - [🔄 Workflow Diagram](#-workflow-diagram) | ||||
|   - [FAQ \& Troubleshooting](#faq--troubleshooting) | ||||
|   - [📝 License](#-license) | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🚀 Quick Start | ||||
|  | ||||
| Copy files and artifacts via SSH in your GitHub Actions workflow: | ||||
|  | ||||
| ```yaml | ||||
| - name: copy file via ssh password | ||||
|   uses: appleboy/scp-action@master | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     password: ${{ secrets.PASSWORD }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     source: "tests/a.txt,tests/b.txt" | ||||
|     target: "test" | ||||
| name: scp files | ||||
| on: [push] | ||||
| jobs: | ||||
|   build: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|       - name: Copy files via SSH | ||||
|         uses: appleboy/scp-action@v1 | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           password: ${{ secrets.PASSWORD }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: "tests/a.txt,tests/b.txt" | ||||
|           target: your_server_target_folder_path | ||||
| ``` | ||||
|  | ||||
| ## Input variables | ||||
| --- | ||||
|  | ||||
| see the [action.yml](./action.yml) file for more detail imformation. | ||||
| ## ⚙️ Configuration | ||||
|  | ||||
| * host - scp remote host | ||||
| * port - scp remote port | ||||
| * username - scp username | ||||
| * password - scp password | ||||
| * timeout - timeout for ssh to remote host | ||||
| * command_timeout - timeout for scp command | ||||
| * key - content of ssh private key. ex raw content of ~/.ssh/id_rsa | ||||
| * key_path - path of ssh private key | ||||
| * target - target path on the server | ||||
| * source - scp file list | ||||
| * rm - remove target folder before upload data | ||||
| * strip_components - remove the specified number of leading path elements. | ||||
| * overwrite - use `--overwrite` flag with tar | ||||
| * tar_tmp_path - temporary path for tar file on the dest host | ||||
| ### 🔌 Connection Settings | ||||
|  | ||||
| ### Example | ||||
| | Variable        | Description                                  | Default | Required | | ||||
| | --------------- | -------------------------------------------- | ------- | -------- | | ||||
| | host            | Remote host(s), comma-separated for multiple | -       | ✓        | | ||||
| | port            | SSH port                                     | 22      |          | | ||||
| | username        | SSH username                                 | -       | ✓        | | ||||
| | password        | SSH password (prefer SSH key for security)   | -       |          | | ||||
| | key             | SSH private key content                      | -       |          | | ||||
| | key_path        | Path to SSH private key file                 | -       |          | | ||||
| | passphrase      | Passphrase for SSH private key               | -       |          | | ||||
| | fingerprint     | SHA256 fingerprint for host key verification | -       |          | | ||||
| | protocol        | IP protocol: 'tcp', 'tcp4', or 'tcp6'        | tcp     |          | | ||||
| | timeout         | SSH connection timeout                       | 30s     |          | | ||||
| | command_timeout | SCP command timeout                          | 10m     |          | | ||||
|  | ||||
| Copy file via ssh password | ||||
| ### 📁 File Transfer Settings | ||||
|  | ||||
| | Variable         | Description                                             | Default | Security Note          | | ||||
| | ---------------- | ------------------------------------------------------- | ------- | ---------------------- | | ||||
| | source           | Local files/directories to transfer (comma-separated)   | -       | Use explicit paths     | | ||||
| | target           | Target directory on remote server (must be a directory) | -       | Avoid root directories | | ||||
| | rm               | Remove target directory before upload                   | -       | Use with caution       | | ||||
| | strip_components | Remove leading path elements when extracting            | -       |                        | | ||||
| | overwrite        | Overwrite existing files with tar                       | -       |                        | | ||||
| | tar_dereference  | Follow symlinks with tar                                | -       |                        | | ||||
| | tar_tmp_path     | Temp path for tar file on destination                   | -       |                        | | ||||
| | tar_exec         | Path to tar executable on destination                   | tar     |                        | | ||||
| | debug            | Enable debug output                                     | -       |                        | | ||||
| | curl_insecure    | Use --insecure with curl                                | false   | Not recommended        | | ||||
| | capture_stdout   | Capture command stdout as action output                 | false   |                        | | ||||
| | version          | Version of drone-scp to use                             | -       |                        | | ||||
|  | ||||
| ### 🌐 Proxy Settings | ||||
|  | ||||
| | Variable                  | Description                          | Default | Required | | ||||
| | ------------------------- | ------------------------------------ | ------- | -------- | | ||||
| | proxy_host                | SSH proxy host                       | -       |          | | ||||
| | proxy_port                | SSH proxy port                       | 22      |          | | ||||
| | proxy_username            | SSH proxy username                   | -       |          | | ||||
| | proxy_password            | SSH proxy password                   | -       |          | | ||||
| | proxy_key                 | SSH proxy private key content        | -       |          | | ||||
| | proxy_key_path            | Path to SSH proxy private key file   | -       |          | | ||||
| | proxy_passphrase          | Passphrase for SSH proxy private key | -       |          | | ||||
| | proxy_fingerprint         | SHA256 fingerprint for proxy host    | -       |          | | ||||
| | proxy_use_insecure_cipher | Enable less secure ciphers for proxy | -       |          | | ||||
| | proxy_timeout             | SSH proxy connection timeout         | 30s     |          | | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🛡️ Best Practices & Security | ||||
|  | ||||
| - **Prefer SSH key authentication** over passwords for better security. | ||||
| - Store all sensitive values (host, username, password, key) in **GitHub Secrets**. | ||||
| - Regularly **rotate deployment keys** (suggested every 90 days). | ||||
| - Restrict write permissions on the target server directory. | ||||
| - Enable host key fingerprint verification to prevent MITM attacks. | ||||
| - Avoid using root as the SSH user. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🖥️ Cross-Platform Notes | ||||
|  | ||||
| | Scenario         | Linux Server   | Windows Server          | | ||||
| | ---------------- | -------------- | ----------------------- | | ||||
| | Path Format      | `/path/to/dir` | `/c/path/to/dir`        | | ||||
| | Required Setting | None           | `tar_dereference: true` | | ||||
| | Permissions      | Preserved      | May require manual ACL  | | ||||
| | Shell            | bash (default) | Git Bash via OpenSSH    | | ||||
|  | ||||
| > 🚩 **Important:**   | ||||
| > When copying to Windows servers: | ||||
| > | ||||
| > - Install Git for Windows and set OpenSSH default shell to Git Bash | ||||
| > - Use Unix-style target paths (e.g., `/c/Users/...`) | ||||
| > - Enable `tar_dereference` for symlink handling | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 💡 Usage Examples | ||||
|  | ||||
| ### 🧩 Scenario Guide | ||||
|  | ||||
| - **Basic file transfer** → [Example 1](#example-1-basic-ssh-password) | ||||
| - **Multi-server deployment** → [Example 2](#example-2-multi-server) | ||||
| - **Incremental/changed files only** → [Example 3](#example-3-changed-files-only) | ||||
| - **Artifacts integration** → [Example 4](#example-4-artifacts-integration) | ||||
| - **Windows server setup** → [Example 5](#example-5-windows-server) | ||||
|  | ||||
| --- | ||||
|  | ||||
| #### Example 1: Basic SSH Password | ||||
|  | ||||
| ```yaml | ||||
| - name: copy file via ssh password | ||||
|   uses: appleboy/scp-action@master | ||||
| - name: Copy file via SSH password | ||||
|   uses: appleboy/scp-action@v1 | ||||
|   with: | ||||
|     host: example.com | ||||
|     username: foo | ||||
|     password: bar | ||||
|     port: 22 | ||||
|     source: "tests/a.txt,tests/b.txt" | ||||
|     target: "test" | ||||
|     target: your_server_target_folder_path | ||||
| ``` | ||||
|  | ||||
| Copy file via ssh key | ||||
| #### Example 2: Multi-server | ||||
|  | ||||
| ```yaml | ||||
| - name: copy file via ssh key | ||||
|   uses: appleboy/scp-action@master | ||||
|   env: | ||||
|     HOST: ${{ secrets.HOST }} | ||||
|     USERNAME: ${{ secrets.USERNAME }} | ||||
|     PORT: ${{ secrets.PORT }} | ||||
|     KEY: ${{ secrets.KEY }} | ||||
| - name: Copy to multiple servers | ||||
|   uses: appleboy/scp-action@v1 | ||||
|   with: | ||||
|     source: "tests/a.txt,tests/b.txt" | ||||
|     target: "test" | ||||
| ``` | ||||
|  | ||||
| Example configuration for ignore list: | ||||
|  | ||||
| ```yaml | ||||
| - name: copy file via ssh key | ||||
|   uses: appleboy/scp-action@master | ||||
|   env: | ||||
|     HOST: ${{ secrets.HOST }} | ||||
|     USERNAME: ${{ secrets.USERNAME }} | ||||
|     PORT: ${{ secrets.PORT }} | ||||
|     KEY: ${{ secrets.KEY }} | ||||
|   with: | ||||
|     source: "tests/*.txt,!tests/a.txt" | ||||
|     target: "test" | ||||
| ``` | ||||
|  | ||||
| Example configuration for multiple server | ||||
|  | ||||
| ```diff | ||||
| - name: copy file via ssh password | ||||
|   uses: appleboy/scp-action@master | ||||
|   with: | ||||
| -   host: "example.com" | ||||
| +   host: "foo.com,bar.com" | ||||
|     host: "foo.com,bar.com" | ||||
|     username: foo | ||||
|     password: bar | ||||
|     port: 22 | ||||
|     source: "tests/a.txt,tests/b.txt" | ||||
|     target: "test" | ||||
|     target: your_server_target_folder_path | ||||
| ``` | ||||
|  | ||||
| remove the specified number of leading path elements | ||||
| #### Example 3: Changed Files Only | ||||
|  | ||||
| ```yaml | ||||
| - name: remove the specified number of leading path elements | ||||
|   uses: appleboy/scp-action@master | ||||
| - name: Get changed files | ||||
|   id: changed-files | ||||
|   uses: tj-actions/changed-files@v35 | ||||
|   with: | ||||
|     since_last_remote_commit: true | ||||
|     separator: "," | ||||
|  | ||||
| - name: Copy changed files to server | ||||
|   uses: appleboy/scp-action@v1 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     key: ${{ secrets.KEY }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     source: "tests/a.txt,tests/b.txt" | ||||
|     target: "foobar" | ||||
|     strip_components: 1 | ||||
|     source: ${{ steps.changed-files.outputs.all_changed_files }} | ||||
|     target: your_server_target_folder_path | ||||
| ``` | ||||
|  | ||||
| old target structure: | ||||
| #### Example 4: Artifacts Integration | ||||
|  | ||||
| ```yaml | ||||
| - uses: actions/upload-artifact@v4 | ||||
|   with: | ||||
|     name: my-artifact | ||||
|     path: world.txt | ||||
|  | ||||
| - uses: actions/download-artifact@v4 | ||||
|   with: | ||||
|     name: my-artifact | ||||
|     path: distfiles | ||||
|  | ||||
| - name: Copy artifact to server | ||||
|   uses: appleboy/scp-action@v1 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     key: ${{ secrets.KEY }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     source: distfiles/* | ||||
|     target: your_server_target_folder_path | ||||
| ``` | ||||
|  | ||||
| #### Example 5: Windows Server | ||||
|  | ||||
| ```yaml | ||||
| - name: Copy to Windows | ||||
|   uses: appleboy/scp-action@v1 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     key: ${{ secrets.SSH_PRIVATE_KEY }} | ||||
|     port: 22 | ||||
|     source: "your_source_path" | ||||
|     target: "/c/path/to/target/" | ||||
|     tar_dereference: true | ||||
|     rm: true | ||||
| ``` | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🗝️ SSH Key Setup | ||||
|  | ||||
| 1. **Generate SSH Key** (on your local machine): | ||||
|  | ||||
|    ```bash | ||||
|    # RSA | ||||
|    ssh-keygen -t rsa -b 4096 -C "your_email@example.com" | ||||
|    # ED25519 | ||||
|    ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" | ||||
|    ``` | ||||
|  | ||||
| 2. **Add Public Key to Server**: | ||||
|  | ||||
|    ```bash | ||||
|    cat .ssh/id_rsa.pub | ssh user@host 'cat >> .ssh/authorized_keys' | ||||
|    # or for ed25519 | ||||
|    cat .ssh/id_ed25519.pub | ssh user@host 'cat >> .ssh/authorized_keys' | ||||
|    ``` | ||||
|  | ||||
| 3. **Copy Private Key Content to GitHub Secrets**: | ||||
|  | ||||
|    ```bash | ||||
|    clip < ~/.ssh/id_rsa | ||||
|    # or | ||||
|    clip < ~/.ssh/id_ed25519 | ||||
|    ``` | ||||
|  | ||||
| > See [SSH login without password](http://www.linuxproblem.org/art_9.html) for more details. | ||||
|  | ||||
| **OpenSSH Note:**   | ||||
| If you see `ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey]`, ensure your key algorithm is supported.   | ||||
| On Ubuntu 20.04+, add to `/etc/ssh/sshd_config` or `/etc/ssh/sshd_config.d/`: | ||||
|  | ||||
| ```sh | ||||
| foobar | ||||
|   └── tests | ||||
|     ├── a.txt | ||||
|     └── b.txt | ||||
| CASignatureAlgorithms +ssh-rsa | ||||
| ``` | ||||
|  | ||||
| new target structure: | ||||
| Or use ed25519 keys, which are accepted by default. | ||||
|  | ||||
| ```sh | ||||
| foobar | ||||
|   ├── a.txt | ||||
|   └── b.txt | ||||
| --- | ||||
|  | ||||
| ## 🧰 Common Error Codes | ||||
|  | ||||
| | Error Code     | Possible Cause               | Solution                                      | | ||||
| | -------------- | ---------------------------- | --------------------------------------------- | | ||||
| | `ECONNREFUSED` | Wrong port / firewall blocks | Check port and firewall settings              | | ||||
| | `ENOENT`       | Source file not found        | Use absolute path or check checkout step      | | ||||
| | `EAUTH`        | Authentication failed        | Check key format and permissions (PEM format) | | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🔄 Workflow Diagram | ||||
|  | ||||
| ```mermaid | ||||
| sequenceDiagram | ||||
|     participant G as GitHub Runner | ||||
|     participant S as Target Server | ||||
|     G->>S: Establish SSH connection | ||||
|     S-->>G: Authenticate credentials | ||||
|     G->>S: (Optional) Remove target directory | ||||
|     G->>G: Archive source files | ||||
|     G->>S: Transfer archive | ||||
|     S->>S: Extract and process files | ||||
|     S-->>G: Return result | ||||
| ``` | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## FAQ & Troubleshooting | ||||
|  | ||||
| - **Q: Why does authentication fail?**   | ||||
|   A: Check SSH key format, permissions, and that the key is added to the server. | ||||
|  | ||||
| - **Q: How do I copy only changed files?**   | ||||
|   A: Use `tj-actions/changed-files` to get changed files and pass to `source`. | ||||
|  | ||||
| - **Q: How to deploy to multiple servers?**   | ||||
|   A: Use comma-separated host list: `host: "foo.com,bar.com"` | ||||
|  | ||||
| - **Q: How to copy to Windows?**   | ||||
|   A: Set up Git Bash, use Unix-style paths, and enable `tar_dereference`. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 📝 License | ||||
|  | ||||
| MIT License | ||||
|   | ||||
							
								
								
									
										348
									
								
								README.zh-cn.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										348
									
								
								README.zh-cn.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,348 @@ | ||||
| # 🚀 GitHub Actions 的 SCP | ||||
|  | ||||
| [English](README.md) | [繁體中文](README.zh-tw.md) | ||||
|  | ||||
| [GitHub Action](https://github.com/features/actions) 用于通过 SSH 复制文件和构建产物。 | ||||
|  | ||||
| [](https://github.com/appleboy/scp-action/actions/workflows/stable.yml) | ||||
| [](https://github.com/appleboy/scp-action/actions/workflows/testing.yml) | ||||
|  | ||||
| > **注意:** 仅支持 **Linux** [docker](https://www.docker.com/) 容器。 | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## ✨ 功能特性 | ||||
|  | ||||
| - ✅ 通过 SSH 将文件和产物复制到一台或多台远程服务器 | ||||
| - ✅ 支持 SSH 密钥和密码认证 | ||||
| - ✅ 完全支持 SSH 代理(跳板机) | ||||
| - ✅ 处理 Linux ↔ Windows 路径转换 | ||||
| - ✅ 集成 GitHub Artifacts 工作流 | ||||
| - ✅ 支持增量与差异文件传输 | ||||
| - ✅ 丰富的高级配置选项 | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 📦 目录 | ||||
|  | ||||
| - [🚀 GitHub Actions 的 SCP](#-github-actions-的-scp) | ||||
|   - [✨ 功能特性](#-功能特性) | ||||
|   - [📦 目录](#-目录) | ||||
|   - [🚀 快速开始](#-快速开始) | ||||
|   - [⚙️ 配置说明](#️-配置说明) | ||||
|     - [🔌 连接设置](#-连接设置) | ||||
|     - [📁 文件传输设置](#-文件传输设置) | ||||
|     - [🌐 代理设置](#-代理设置) | ||||
|   - [🛡️ 最佳实践与安全性](#️-最佳实践与安全性) | ||||
|   - [🖥️ 跨平台注意事项](#️-跨平台注意事项) | ||||
|   - [💡 使用示例](#-使用示例) | ||||
|     - [🧩 场景导览](#-场景导览) | ||||
|       - [示例 1:基本 SSH 密码](#示例-1基本-ssh-密码) | ||||
|       - [示例 2:多台服务器](#示例-2多台服务器) | ||||
|       - [示例 3:仅传输变更文件](#示例-3仅传输变更文件) | ||||
|       - [示例 4:集成 Artifacts](#示例-4集成-artifacts) | ||||
|       - [示例 5:Windows 服务器](#示例-5windows-服务器) | ||||
|   - [🗝️ SSH 密钥设置](#️-ssh-密钥设置) | ||||
|   - [🧰 常见错误代码](#-常见错误代码) | ||||
|   - [🔄 工作流程图](#-工作流程图) | ||||
|   - [FAQ 与故障排查](#faq-与故障排查) | ||||
|   - [📝 许可证](#-许可证) | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🚀 快速开始 | ||||
|  | ||||
| 在 GitHub Actions 工作流中通过 SSH 复制文件和产物: | ||||
|  | ||||
| ```yaml | ||||
| name: scp files | ||||
| on: [push] | ||||
| jobs: | ||||
|   build: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|       - name: 通过 SSH 复制文件 | ||||
|         uses: appleboy/scp-action@v1 | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           password: ${{ secrets.PASSWORD }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: "tests/a.txt,tests/b.txt" | ||||
|           target: your_server_target_folder_path | ||||
| ``` | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## ⚙️ 配置说明 | ||||
|  | ||||
| ### 🔌 连接设置 | ||||
|  | ||||
| | 变量            | 说明                             | 默认值 | 必填 | | ||||
| | --------------- | -------------------------------- | ------ | ---- | | ||||
| | host            | 远程主机(多台用逗号分隔)       | -      | ✓    | | ||||
| | port            | SSH 端口                         | 22     |      | | ||||
| | username        | SSH 用户名                       | -      | ✓    | | ||||
| | password        | SSH 密码(建议优先使用密钥认证) | -      |      | | ||||
| | key             | SSH 私钥内容                     | -      |      | | ||||
| | key_path        | SSH 私钥文件路径                 | -      |      | | ||||
| | passphrase      | SSH 私钥密码                     | -      |      | | ||||
| | fingerprint     | 主机密钥 SHA256 指纹验证         | -      |      | | ||||
| | protocol        | IP 协议:'tcp'、'tcp4' 或 'tcp6' | tcp    |      | | ||||
| | timeout         | SSH 连接超时                     | 30s    |      | | ||||
| | command_timeout | SCP 命令超时                     | 10m    |      | | ||||
|  | ||||
| ### 📁 文件传输设置 | ||||
|  | ||||
| | 变量             | 说明                              | 默认值 | 安全性说明     | | ||||
| | ---------------- | --------------------------------- | ------ | -------------- | | ||||
| | source           | 本地要传输的文件/目录(逗号分隔) | -      | 请使用明确路径 | | ||||
| | target           | 远程目标目录(必须为目录)        | -      | 避免使用根目录 | | ||||
| | rm               | 上传前移除目标目录                | -      | 谨慎使用       | | ||||
| | strip_components | 传输时移除前置路径元素            | -      |                | | ||||
| | overwrite        | 使用 tar 覆盖现有文件             | -      |                | | ||||
| | tar_dereference  | tar 传输时跟随符号链接            | -      |                | | ||||
| | tar_tmp_path     | 目标端 tar 临时文件路径           | -      |                | | ||||
| | tar_exec         | 目标端 tar 执行文件路径           | tar    |                | | ||||
| | debug            | 启用调试输出                      | -      |                | | ||||
| | curl_insecure    | curl 使用 --insecure              | false  | 不推荐         | | ||||
| | capture_stdout   | 将命令 stdout 作为 action 输出    | false  |                | | ||||
| | version          | 指定 drone-scp 版本               | -      |                | | ||||
|  | ||||
| ### 🌐 代理设置 | ||||
|  | ||||
| | 变量                      | 说明                       | 默认值 | 必填 | | ||||
| | ------------------------- | -------------------------- | ------ | ---- | | ||||
| | proxy_host                | SSH 代理主机               | -      |      | | ||||
| | proxy_port                | SSH 代理端口               | 22     |      | | ||||
| | proxy_username            | SSH 代理用户名             | -      |      | | ||||
| | proxy_password            | SSH 代理密码               | -      |      | | ||||
| | proxy_key                 | SSH 代理私钥内容           | -      |      | | ||||
| | proxy_key_path            | SSH 代理私钥文件路径       | -      |      | | ||||
| | proxy_passphrase          | SSH 代理私钥密码           | -      |      | | ||||
| | proxy_fingerprint         | 代理主机 SHA256 指纹验证   | -      |      | | ||||
| | proxy_use_insecure_cipher | 启用较不安全的代理加密算法 | -      |      | | ||||
| | proxy_timeout             | SSH 代理连接超时           | 30s    |      | | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🛡️ 最佳实践与安全性 | ||||
|  | ||||
| - **建议优先使用 SSH 密钥认证**,提升安全性。 | ||||
| - 将所有敏感信息(host、username、password、key)存放于 **GitHub Secrets**。 | ||||
| - 定期**更换部署密钥**(建议每 90 天一次)。 | ||||
| - 限制目标服务器目录的写入权限。 | ||||
| - 启用主机密钥指纹验证以防止中间人攻击。 | ||||
| - 避免使用 root 用户登录 SSH。 | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🖥️ 跨平台注意事项 | ||||
|  | ||||
| | 场景     | Linux 服务器   | Windows 服务器          | | ||||
| | -------- | -------------- | ----------------------- | | ||||
| | 路径格式 | `/path/to/dir` | `/c/path/to/dir`        | | ||||
| | 必要设置 | 无             | `tar_dereference: true` | | ||||
| | 权限     | 保留           | 可能需手动设置 ACL      | | ||||
| | Shell    | bash(默认)   | Git Bash(OpenSSH)     | | ||||
|  | ||||
| > 🚩 **重要提醒:**   | ||||
| > 复制到 Windows 服务器时: | ||||
| > | ||||
| > - 安装 Git for Windows 并将 OpenSSH 默认 shell 设为 Git Bash | ||||
| > - 使用类 Unix 目标路径(如 `/c/Users/...`) | ||||
| > - 启用 `tar_dereference` 处理符号链接 | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 💡 使用示例 | ||||
|  | ||||
| ### 🧩 场景导览 | ||||
|  | ||||
| - **基本文件传输** → [示例 1](#示例-1基本-ssh-密码) | ||||
| - **多台服务器部署** → [示例 2](#示例-2多台服务器) | ||||
| - **仅传输变更文件** → [示例 3](#示例-3仅传输变更文件) | ||||
| - **集成 Artifacts** → [示例 4](#示例-4集成-artifacts) | ||||
| - **Windows 服务器设置** → [示例 5](#示例-5windows-服务器) | ||||
|  | ||||
| --- | ||||
|  | ||||
| #### 示例 1:基本 SSH 密码 | ||||
|  | ||||
| ```yaml | ||||
| - name: 通过 SSH 密码复制文件 | ||||
|   uses: appleboy/scp-action@v1 | ||||
|   with: | ||||
|     host: example.com | ||||
|     username: foo | ||||
|     password: bar | ||||
|     port: 22 | ||||
|     source: "tests/a.txt,tests/b.txt" | ||||
|     target: your_server_target_folder_path | ||||
| ``` | ||||
|  | ||||
| #### 示例 2:多台服务器 | ||||
|  | ||||
| ```yaml | ||||
| - name: 复制到多台服务器 | ||||
|   uses: appleboy/scp-action@v1 | ||||
|   with: | ||||
|     host: "foo.com,bar.com" | ||||
|     username: foo | ||||
|     password: bar | ||||
|     port: 22 | ||||
|     source: "tests/a.txt,tests/b.txt" | ||||
|     target: your_server_target_folder_path | ||||
| ``` | ||||
|  | ||||
| #### 示例 3:仅传输变更文件 | ||||
|  | ||||
| ```yaml | ||||
| - name: 获取变更文件 | ||||
|   id: changed-files | ||||
|   uses: tj-actions/changed-files@v35 | ||||
|   with: | ||||
|     since_last_remote_commit: true | ||||
|     separator: "," | ||||
|  | ||||
| - name: 复制变更文件到服务器 | ||||
|   uses: appleboy/scp-action@v1 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     key: ${{ secrets.KEY }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     source: ${{ steps.changed-files.outputs.all_changed_files }} | ||||
|     target: your_server_target_folder_path | ||||
| ``` | ||||
|  | ||||
| #### 示例 4:集成 Artifacts | ||||
|  | ||||
| ```yaml | ||||
| - uses: actions/upload-artifact@v4 | ||||
|   with: | ||||
|     name: my-artifact | ||||
|     path: world.txt | ||||
|  | ||||
| - uses: actions/download-artifact@v4 | ||||
|   with: | ||||
|     name: my-artifact | ||||
|     path: distfiles | ||||
|  | ||||
| - name: 复制 artifact 到服务器 | ||||
|   uses: appleboy/scp-action@v1 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     key: ${{ secrets.KEY }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     source: distfiles/* | ||||
|     target: your_server_target_folder_path | ||||
| ``` | ||||
|  | ||||
| #### 示例 5:Windows 服务器 | ||||
|  | ||||
| ```yaml | ||||
| - name: 复制到 Windows | ||||
|   uses: appleboy/scp-action@v1 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     key: ${{ secrets.SSH_PRIVATE_KEY }} | ||||
|     port: 22 | ||||
|     source: "your_source_path" | ||||
|     target: "/c/path/to/target/" | ||||
|     tar_dereference: true | ||||
|     rm: true | ||||
| ``` | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🗝️ SSH 密钥设置 | ||||
|  | ||||
| 1. **生成 SSH 密钥**(在本地执行): | ||||
|  | ||||
|    ```bash | ||||
|    # RSA | ||||
|    ssh-keygen -t rsa -b 4096 -C "your_email@example.com" | ||||
|    # ED25519 | ||||
|    ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" | ||||
|    ``` | ||||
|  | ||||
| 2. **将公钥添加到服务器**: | ||||
|  | ||||
|    ```bash | ||||
|    cat .ssh/id_rsa.pub | ssh user@host 'cat >> .ssh/authorized_keys' | ||||
|    # 或 ed25519 | ||||
|    cat .ssh/id_ed25519.pub | ssh user@host 'cat >> .ssh/authorized_keys' | ||||
|    ``` | ||||
|  | ||||
| 3. **将私钥内容复制到 GitHub Secrets**: | ||||
|  | ||||
|    ```bash | ||||
|    clip < ~/.ssh/id_rsa | ||||
|    # 或 | ||||
|    clip < ~/.ssh/id_ed25519 | ||||
|    ``` | ||||
|  | ||||
| > 更多细节请参考 [SSH 免密登录](http://www.linuxproblem.org/art_9.html)。 | ||||
|  | ||||
| **OpenSSH 注意事项:**   | ||||
| 如遇到 `ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey]`,请确认密钥算法已被支持。   | ||||
| Ubuntu 20.04+ 可在 `/etc/ssh/sshd_config` 或 `/etc/ssh/sshd_config.d/` 添加: | ||||
|  | ||||
| ```sh | ||||
| CASignatureAlgorithms +ssh-rsa | ||||
| ``` | ||||
|  | ||||
| 或使用 ed25519 密钥(默认支持)。 | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🧰 常见错误代码 | ||||
|  | ||||
| | 错误代码       | 可能原因            | 解决方法                          | | ||||
| | -------------- | ------------------- | --------------------------------- | | ||||
| | `ECONNREFUSED` | 端口错误/防火墙阻挡 | 检查端口和防火墙设置              | | ||||
| | `ENOENT`       | 找不到源文件        | 使用绝对路径或检查 checkout 步骤  | | ||||
| | `EAUTH`        | 认证失败            | 检查密钥格式和权限(需 PEM 格式) | | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🔄 工作流程图 | ||||
|  | ||||
| ```mermaid | ||||
| sequenceDiagram | ||||
|     participant G as GitHub Runner | ||||
|     participant S as Target Server | ||||
|     G->>S: 建立 SSH 连接 | ||||
|     S-->>G: 验证凭证 | ||||
|     G->>S: (可选)移除目标目录 | ||||
|     G->>G: 打包源文件 | ||||
|     G->>S: 传输打包文件 | ||||
|     S->>S: 解压和处理文件 | ||||
|     S-->>G: 返回结果 | ||||
| ``` | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## FAQ 与故障排查 | ||||
|  | ||||
| - **Q: 为什么认证失败?**   | ||||
|   A: 请检查 SSH 密钥格式、权限,以及密钥是否已添加到服务器。 | ||||
|  | ||||
| - **Q: 如何只复制变更文件?**   | ||||
|   A: 使用 `tj-actions/changed-files` 获取变更文件并传递给 `source`。 | ||||
|  | ||||
| - **Q: 如何部署到多台服务器?**   | ||||
|   A: `host` 参数用逗号分隔多台主机,例如:`host: "foo.com,bar.com"` | ||||
|  | ||||
| - **Q: 如何复制到 Windows?**   | ||||
|   A: 设置 Git Bash,使用类 Unix 路径,并启用 `tar_dereference`。 | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 📝 许可证 | ||||
|  | ||||
| MIT License | ||||
							
								
								
									
										348
									
								
								README.zh-tw.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										348
									
								
								README.zh-tw.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,348 @@ | ||||
| # 🚀 GitHub Actions 的 SCP | ||||
|  | ||||
| [English](README.md) | [简体中文](README.zh-cn.md) | ||||
|  | ||||
| [GitHub Action](https://github.com/features/actions) 用於透過 SSH 複製檔案與產物。 | ||||
|  | ||||
| [](https://github.com/appleboy/scp-action/actions/workflows/stable.yml) | ||||
| [](https://github.com/appleboy/scp-action/actions/workflows/testing.yml) | ||||
|  | ||||
| > **注意:** 只支援 **Linux** [docker](https://www.docker.com/) 容器。 | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## ✨ 功能特色 | ||||
|  | ||||
| - ✅ 透過 SSH 將檔案與產物複製到一台或多台遠端伺服器 | ||||
| - ✅ 支援 SSH 金鑰與密碼驗證 | ||||
| - ✅ 完整支援 SSH Proxy(跳板機) | ||||
| - ✅ 處理 Linux ↔ Windows 路徑轉換 | ||||
| - ✅ 整合 GitHub Artifacts 工作流程 | ||||
| - ✅ 支援增量與差異檔案傳輸 | ||||
| - ✅ 豐富的進階設定選項 | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 📦 目錄 | ||||
|  | ||||
| - [🚀 GitHub Actions 的 SCP](#-github-actions-的-scp) | ||||
|   - [✨ 功能特色](#-功能特色) | ||||
|   - [📦 目錄](#-目錄) | ||||
|   - [🚀 快速開始](#-快速開始) | ||||
|   - [⚙️ 設定說明](#️-設定說明) | ||||
|     - [🔌 連線設定](#-連線設定) | ||||
|     - [📁 檔案傳輸設定](#-檔案傳輸設定) | ||||
|     - [🌐 Proxy 設定](#-proxy-設定) | ||||
|   - [🛡️ 最佳實踐與安全性](#️-最佳實踐與安全性) | ||||
|   - [🖥️ 跨平台注意事項](#️-跨平台注意事項) | ||||
|   - [💡 使用範例](#-使用範例) | ||||
|     - [🧩 情境導覽](#-情境導覽) | ||||
|       - [範例 1:基本 SSH 密碼](#範例-1基本-ssh-密碼) | ||||
|       - [範例 2:多台伺服器](#範例-2多台伺服器) | ||||
|       - [範例 3:僅傳送變更檔案](#範例-3僅傳送變更檔案) | ||||
|       - [範例 4:整合 Artifacts](#範例-4整合-artifacts) | ||||
|       - [範例 5:Windows 伺服器](#範例-5windows-伺服器) | ||||
|   - [🗝️ SSH 金鑰設定](#️-ssh-金鑰設定) | ||||
|   - [🧰 常見錯誤代碼](#-常見錯誤代碼) | ||||
|   - [🔄 工作流程圖](#-工作流程圖) | ||||
|   - [FAQ 與疑難排解](#faq-與疑難排解) | ||||
|   - [📝 授權條款](#-授權條款) | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🚀 快速開始 | ||||
|  | ||||
| 在 GitHub Actions 工作流程中透過 SSH 複製檔案與產物: | ||||
|  | ||||
| ```yaml | ||||
| name: scp files | ||||
| on: [push] | ||||
| jobs: | ||||
|   build: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|       - name: 透過 SSH 複製檔案 | ||||
|         uses: appleboy/scp-action@v1 | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           password: ${{ secrets.PASSWORD }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           source: "tests/a.txt,tests/b.txt" | ||||
|           target: your_server_target_folder_path | ||||
| ``` | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## ⚙️ 設定說明 | ||||
|  | ||||
| ### 🔌 連線設定 | ||||
|  | ||||
| | 變數            | 說明                                 | 預設值 | 必填 | | ||||
| | --------------- | ------------------------------------ | ------ | ---- | | ||||
| | host            | 遠端主機(多台以逗號分隔)           | -      | ✓    | | ||||
| | port            | SSH 連接埠                           | 22     |      | | ||||
| | username        | SSH 使用者名稱                       | -      | ✓    | | ||||
| | password        | SSH 密碼(建議使用金鑰以提升安全性) | -      |      | | ||||
| | key             | SSH 私鑰內容                         | -      |      | | ||||
| | key_path        | SSH 私鑰檔案路徑                     | -      |      | | ||||
| | passphrase      | SSH 私鑰密碼                         | -      |      | | ||||
| | fingerprint     | 主機金鑰 SHA256 指紋驗證             | -      |      | | ||||
| | protocol        | IP 協定:'tcp'、'tcp4' 或 'tcp6'     | tcp    |      | | ||||
| | timeout         | SSH 連線逾時                         | 30s    |      | | ||||
| | command_timeout | SCP 指令逾時                         | 10m    |      | | ||||
|  | ||||
| ### 📁 檔案傳輸設定 | ||||
|  | ||||
| | 變數             | 說明                              | 預設值 | 安全性說明     | | ||||
| | ---------------- | --------------------------------- | ------ | -------------- | | ||||
| | source           | 本地要傳送的檔案/目錄(逗號分隔) | -      | 請使用明確路徑 | | ||||
| | target           | 遠端目標目錄(必須為目錄)        | -      | 避免使用根目錄 | | ||||
| | rm               | 上傳前移除目標目錄                | -      | 請小心使用     | | ||||
| | strip_components | 傳送時移除前置路徑元素            | -      |                | | ||||
| | overwrite        | 使用 tar 覆蓋現有檔案             | -      |                | | ||||
| | tar_dereference  | tar 傳送時跟隨符號連結            | -      |                | | ||||
| | tar_tmp_path     | 目標端 tar 暫存檔路徑             | -      |                | | ||||
| | tar_exec         | 目標端 tar 執行檔路徑             | tar    |                | | ||||
| | debug            | 啟用除錯輸出                      | -      |                | | ||||
| | curl_insecure    | curl 使用 --insecure              | false  | 不建議         | | ||||
| | capture_stdout   | 將指令 stdout 作為 action 輸出    | false  |                | | ||||
| | version          | 指定 drone-scp 版本               | -      |                | | ||||
|  | ||||
| ### 🌐 Proxy 設定 | ||||
|  | ||||
| | 變數                      | 說明                            | 預設值 | 必填 | | ||||
| | ------------------------- | ------------------------------- | ------ | ---- | | ||||
| | proxy_host                | SSH Proxy 主機                  | -      |      | | ||||
| | proxy_port                | SSH Proxy 連接埠                | 22     |      | | ||||
| | proxy_username            | SSH Proxy 使用者名稱            | -      |      | | ||||
| | proxy_password            | SSH Proxy 密碼                  | -      |      | | ||||
| | proxy_key                 | SSH Proxy 私鑰內容              | -      |      | | ||||
| | proxy_key_path            | SSH Proxy 私鑰檔案路徑          | -      |      | | ||||
| | proxy_passphrase          | SSH Proxy 私鑰密碼              | -      |      | | ||||
| | proxy_fingerprint         | Proxy 主機 SHA256 指紋驗證      | -      |      | | ||||
| | proxy_use_insecure_cipher | 啟用較不安全的 Proxy 加密演算法 | -      |      | | ||||
| | proxy_timeout             | SSH Proxy 連線逾時              | 30s    |      | | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🛡️ 最佳實踐與安全性 | ||||
|  | ||||
| - **建議優先使用 SSH 金鑰驗證**,提升安全性。 | ||||
| - 將所有敏感資訊(host、username、password、key)存放於 **GitHub Secrets**。 | ||||
| - 定期**更換部署金鑰**(建議每 90 天一次)。 | ||||
| - 限制目標伺服器目錄的寫入權限。 | ||||
| - 啟用主機金鑰指紋驗證以防止中間人攻擊。 | ||||
| - 避免使用 root 帳號登入 SSH。 | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🖥️ 跨平台注意事項 | ||||
|  | ||||
| | 情境     | Linux 伺服器   | Windows 伺服器          | | ||||
| | -------- | -------------- | ----------------------- | | ||||
| | 路徑格式 | `/path/to/dir` | `/c/path/to/dir`        | | ||||
| | 必要設定 | 無             | `tar_dereference: true` | | ||||
| | 權限     | 保留           | 可能需手動設定 ACL      | | ||||
| | Shell    | bash (預設)    | Git Bash(OpenSSH)     | | ||||
|  | ||||
| > 🚩 **重要提醒:**   | ||||
| > 複製到 Windows 伺服器時: | ||||
| > | ||||
| > - 安裝 Git for Windows 並將 OpenSSH 預設 shell 設為 Git Bash | ||||
| > - 使用 Unix 風格目標路徑(如 `/c/Users/...`) | ||||
| > - 啟用 `tar_dereference` 處理符號連結 | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 💡 使用範例 | ||||
|  | ||||
| ### 🧩 情境導覽 | ||||
|  | ||||
| - **基本檔案傳輸** → [範例 1](#範例-1基本-ssh-密碼) | ||||
| - **多台伺服器部署** → [範例 2](#範例-2多台伺服器) | ||||
| - **僅傳送變更檔案** → [範例 3](#範例-3僅傳送變更檔案) | ||||
| - **整合 Artifacts** → [範例 4](#範例-4整合-artifacts) | ||||
| - **Windows 伺服器設定** → [範例 5](#範例-5windows-伺服器) | ||||
|  | ||||
| --- | ||||
|  | ||||
| #### 範例 1:基本 SSH 密碼 | ||||
|  | ||||
| ```yaml | ||||
| - name: 透過 SSH 密碼複製檔案 | ||||
|   uses: appleboy/scp-action@v1 | ||||
|   with: | ||||
|     host: example.com | ||||
|     username: foo | ||||
|     password: bar | ||||
|     port: 22 | ||||
|     source: "tests/a.txt,tests/b.txt" | ||||
|     target: your_server_target_folder_path | ||||
| ``` | ||||
|  | ||||
| #### 範例 2:多台伺服器 | ||||
|  | ||||
| ```yaml | ||||
| - name: 複製到多台伺服器 | ||||
|   uses: appleboy/scp-action@v1 | ||||
|   with: | ||||
|     host: "foo.com,bar.com" | ||||
|     username: foo | ||||
|     password: bar | ||||
|     port: 22 | ||||
|     source: "tests/a.txt,tests/b.txt" | ||||
|     target: your_server_target_folder_path | ||||
| ``` | ||||
|  | ||||
| #### 範例 3:僅傳送變更檔案 | ||||
|  | ||||
| ```yaml | ||||
| - name: 取得變更檔案 | ||||
|   id: changed-files | ||||
|   uses: tj-actions/changed-files@v35 | ||||
|   with: | ||||
|     since_last_remote_commit: true | ||||
|     separator: "," | ||||
|  | ||||
| - name: 複製變更檔案到伺服器 | ||||
|   uses: appleboy/scp-action@v1 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     key: ${{ secrets.KEY }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     source: ${{ steps.changed-files.outputs.all_changed_files }} | ||||
|     target: your_server_target_folder_path | ||||
| ``` | ||||
|  | ||||
| #### 範例 4:整合 Artifacts | ||||
|  | ||||
| ```yaml | ||||
| - uses: actions/upload-artifact@v4 | ||||
|   with: | ||||
|     name: my-artifact | ||||
|     path: world.txt | ||||
|  | ||||
| - uses: actions/download-artifact@v4 | ||||
|   with: | ||||
|     name: my-artifact | ||||
|     path: distfiles | ||||
|  | ||||
| - name: 複製 artifact 到伺服器 | ||||
|   uses: appleboy/scp-action@v1 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     key: ${{ secrets.KEY }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     source: distfiles/* | ||||
|     target: your_server_target_folder_path | ||||
| ``` | ||||
|  | ||||
| #### 範例 5:Windows 伺服器 | ||||
|  | ||||
| ```yaml | ||||
| - name: 複製到 Windows | ||||
|   uses: appleboy/scp-action@v1 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     key: ${{ secrets.SSH_PRIVATE_KEY }} | ||||
|     port: 22 | ||||
|     source: "your_source_path" | ||||
|     target: "/c/path/to/target/" | ||||
|     tar_dereference: true | ||||
|     rm: true | ||||
| ``` | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🗝️ SSH 金鑰設定 | ||||
|  | ||||
| 1. **產生 SSH 金鑰**(於本地端執行): | ||||
|  | ||||
|    ```bash | ||||
|    # RSA | ||||
|    ssh-keygen -t rsa -b 4096 -C "your_email@example.com" | ||||
|    # ED25519 | ||||
|    ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" | ||||
|    ``` | ||||
|  | ||||
| 2. **將公鑰加入伺服器**: | ||||
|  | ||||
|    ```bash | ||||
|    cat .ssh/id_rsa.pub | ssh user@host 'cat >> .ssh/authorized_keys' | ||||
|    # 或 ed25519 | ||||
|    cat .ssh/id_ed25519.pub | ssh user@host 'cat >> .ssh/authorized_keys' | ||||
|    ``` | ||||
|  | ||||
| 3. **將私鑰內容複製到 GitHub Secrets**: | ||||
|  | ||||
|    ```bash | ||||
|    clip < ~/.ssh/id_rsa | ||||
|    # 或 | ||||
|    clip < ~/.ssh/id_ed25519 | ||||
|    ``` | ||||
|  | ||||
| > 更多細節請參考 [SSH 無密碼登入](http://www.linuxproblem.org/art_9.html)。 | ||||
|  | ||||
| **OpenSSH 注意事項:**   | ||||
| 若出現 `ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey]`,請確認金鑰演算法支援。   | ||||
| Ubuntu 20.04+ 可於 `/etc/ssh/sshd_config` 或 `/etc/ssh/sshd_config.d/` 加入: | ||||
|  | ||||
| ```sh | ||||
| CASignatureAlgorithms +ssh-rsa | ||||
| ``` | ||||
|  | ||||
| 或改用 ed25519 金鑰(預設支援)。 | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🧰 常見錯誤代碼 | ||||
|  | ||||
| | 錯誤代碼       | 可能原因              | 解決方式                          | | ||||
| | -------------- | --------------------- | --------------------------------- | | ||||
| | `ECONNREFUSED` | 連接埠錯誤/防火牆阻擋 | 檢查連接埠與防火牆設定            | | ||||
| | `ENOENT`       | 找不到來源檔案        | 請用絕對路徑或檢查 checkout 步驟  | | ||||
| | `EAUTH`        | 驗證失敗              | 檢查金鑰格式與權限(需 PEM 格式) | | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🔄 工作流程圖 | ||||
|  | ||||
| ```mermaid | ||||
| sequenceDiagram | ||||
|     participant G as GitHub Runner | ||||
|     participant S as Target Server | ||||
|     G->>S: 建立 SSH 連線 | ||||
|     S-->>G: 驗證憑證 | ||||
|     G->>S: (可選)移除目標目錄 | ||||
|     G->>G: 封存來源檔案 | ||||
|     G->>S: 傳送封存檔 | ||||
|     S->>S: 解壓與處理檔案 | ||||
|     S-->>G: 回傳結果 | ||||
| ``` | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## FAQ 與疑難排解 | ||||
|  | ||||
| - **Q: 為什麼驗證失敗?**   | ||||
|   A: 請檢查 SSH 金鑰格式、權限,以及金鑰是否已加入伺服器。 | ||||
|  | ||||
| - **Q: 如何只複製變更檔案?**   | ||||
|   A: 使用 `tj-actions/changed-files` 取得變更檔案並傳給 `source`。 | ||||
|  | ||||
| - **Q: 如何部署到多台伺服器?**   | ||||
|   A: `host` 參數用逗號分隔多台主機,例如:`host: "foo.com,bar.com"` | ||||
|  | ||||
| - **Q: 如何複製到 Windows?**   | ||||
|   A: 設定 Git Bash,使用 Unix 風格路徑,並啟用 `tar_dereference`。 | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 📝 授權條款 | ||||
|  | ||||
| MIT License | ||||
							
								
								
									
										147
									
								
								action.yml
									
									
									
									
									
								
							
							
						
						
									
										147
									
								
								action.yml
									
									
									
									
									
								
							| @@ -1,43 +1,142 @@ | ||||
| name: 'SCP Command to Transfer Files' | ||||
| description: 'How to Use SCP Command to Transfer Files/Folders in Linux' | ||||
| author: 'Bo-Yi Wu' | ||||
| name: "SCP Command to Transfer Files" | ||||
| description: "Easily transfer files and folders using the SCP command in Linux." | ||||
| author: "Bo-Yi Wu" | ||||
| inputs: | ||||
|   host: | ||||
|     description: 'scp remote host' | ||||
|     description: "Remote host address for SCP (e.g., example.com or 192.168.1.1)." | ||||
|   port: | ||||
|     description: 'scp remote port' | ||||
|     description: "Remote SSH port for SCP. Default: 22." | ||||
|     default: "22" | ||||
|   username: | ||||
|     description: 'scp username' | ||||
|     description: "Username for SSH authentication." | ||||
|   password: | ||||
|     description: 'scp password' | ||||
|     description: "Password for SSH authentication (not recommended; use SSH keys if possible)." | ||||
|   protocol: | ||||
|     description: "IP protocol to use. Valid values: 'tcp', 'tcp4', or 'tcp6'. Default: tcp." | ||||
|     default: "tcp" | ||||
|   timeout: | ||||
|     description: 'timeout for ssh to remote host' | ||||
|     description: "Timeout for establishing SSH connection to the remote host. Default: 30s." | ||||
|     default: "30s" | ||||
|   command_timeout: | ||||
|     description: 'timeout for scp command' | ||||
|     default: "1m" | ||||
|     description: "Timeout for the SCP command execution. Default: 10m." | ||||
|     default: "10m" | ||||
|   key: | ||||
|     description: 'content of ssh private key. ex raw content of ~/.ssh/id_rsa' | ||||
|     description: "Content of the SSH private key (e.g., the raw content of ~/.ssh/id_rsa)." | ||||
|   key_path: | ||||
|     description: 'path of ssh private key' | ||||
|     description: "Path to the SSH private key file." | ||||
|   passphrase: | ||||
|     description: "Passphrase for the SSH private key, if required." | ||||
|   fingerprint: | ||||
|     description: "SHA256 fingerprint of the host's public key. If not set, host key verification is skipped (not recommended for production)." | ||||
|   use_insecure_cipher: | ||||
|     description: "Enable additional, less secure ciphers for compatibility. Not recommended unless required." | ||||
|   target: | ||||
|     description: 'target path on the server' | ||||
|     description: "Target directory path on the remote server. Must be a directory." | ||||
|   source: | ||||
|     description: 'scp file list' | ||||
|     description: "List of files or directories to transfer (local paths)." | ||||
|   rm: | ||||
|     description: 'remove target folder before upload data' | ||||
|     description: "Remove the target directory on the server before uploading new data." | ||||
|   debug: | ||||
|     description: "Enable debug messages for troubleshooting." | ||||
|   strip_components: | ||||
|     description: 'remove the specified number of leading path elements' | ||||
|     default: 0 | ||||
|     description: "Remove the specified number of leading path elements when extracting files." | ||||
|   overwrite: | ||||
|     description: 'use `--overwrite` flag with tar' | ||||
|     default: false | ||||
|     description: "Use the --overwrite flag with tar to overwrite existing files." | ||||
|   tar_dereference: | ||||
|     description: "Use the --dereference flag with tar to follow symlinks." | ||||
|   tar_tmp_path: | ||||
|     description: 'temporary path for tar file on the dest host' | ||||
|     description: "Temporary path for the tar file on the destination host." | ||||
|   tar_exec: | ||||
|     description: "Path to the tar executable on the destination host. Default: tar." | ||||
|     default: "tar" | ||||
|   proxy_host: | ||||
|     description: "Remote host address for SSH proxy." | ||||
|   proxy_port: | ||||
|     description: "SSH proxy port. Default: 22." | ||||
|     default: "22" | ||||
|   proxy_username: | ||||
|     description: "Username for SSH proxy authentication." | ||||
|   proxy_password: | ||||
|     description: "Password for SSH proxy authentication." | ||||
|   proxy_passphrase: | ||||
|     description: "Passphrase for the SSH proxy private key, if required." | ||||
|   proxy_timeout: | ||||
|     description: "Timeout for establishing SSH connection to the proxy host. Default: 30s." | ||||
|     default: "30s" | ||||
|   proxy_key: | ||||
|     description: "Content of the SSH proxy private key (e.g., the raw content of ~/.ssh/id_rsa)." | ||||
|   proxy_key_path: | ||||
|     description: "Path to the SSH proxy private key file." | ||||
|   proxy_fingerprint: | ||||
|     description: "SHA256 fingerprint of the proxy host's public key. If not set, host key verification is skipped (not recommended for production)." | ||||
|   proxy_use_insecure_cipher: | ||||
|     description: "Enable additional, less secure ciphers for the proxy connection. Not recommended unless required." | ||||
|   curl_insecure: | ||||
|     description: "When true, uses the --insecure option with curl for insecure downloads." | ||||
|     default: "false" | ||||
|   capture_stdout: | ||||
|     description: "When true, captures and returns standard output from the commands as action output." | ||||
|     default: "false" | ||||
|   version: | ||||
|     description: | | ||||
|       The version of drone-scp to use. | ||||
|  | ||||
| outputs: | ||||
|   stdout: | ||||
|     description: "Standard output of the executed commands when capture_stdout is enabled." | ||||
|     value: ${{ steps.entrypoint.outputs.stdout }} | ||||
|  | ||||
| runs: | ||||
|   using: 'docker' | ||||
|   image: 'Dockerfile' | ||||
|   using: "composite" | ||||
|   steps: | ||||
|     - name: Set GitHub Path | ||||
|       run: echo "$GITHUB_ACTION_PATH" >> $GITHUB_PATH | ||||
|       shell: bash | ||||
|       env: | ||||
|         GITHUB_ACTION_PATH: ${{ github.action_path }} | ||||
|     - id: entrypoint | ||||
|       name: Run entrypoint.sh | ||||
|       run: entrypoint.sh | ||||
|       shell: bash | ||||
|       env: | ||||
|         GITHUB_ACTION_PATH: ${{ github.action_path }} | ||||
|         INPUT_HOST: ${{ inputs.host }} | ||||
|         INPUT_PORT: ${{ inputs.port }} | ||||
|         INPUT_PROTOCOL: ${{ inputs.protocol }} | ||||
|         INPUT_USERNAME: ${{ inputs.username }} | ||||
|         INPUT_PASSWORD: ${{ inputs.password }} | ||||
|         INPUT_PASSPHRASE: ${{ inputs.passphrase }} | ||||
|         INPUT_KEY: ${{ inputs.key }} | ||||
|         INPUT_KEY_PATH: ${{ inputs.key_path }} | ||||
|         INPUT_FINGERPRINT: ${{ inputs.fingerprint }} | ||||
|         INPUT_PROXY_HOST: ${{ inputs.proxy_host }} | ||||
|         INPUT_PROXY_PORT: ${{ inputs.proxy_port }} | ||||
|         INPUT_PROXY_USERNAME: ${{ inputs.proxy_username }} | ||||
|         INPUT_PROXY_PASSWORD: ${{ inputs.proxy_password }} | ||||
|         INPUT_PROXY_PASSPHRASE: ${{ inputs.proxy_passphrase }} | ||||
|         INPUT_PROXY_KEY: ${{ inputs.proxy_key }} | ||||
|         INPUT_PROXY_KEY_PATH: ${{ inputs.proxy_key_path }} | ||||
|         INPUT_PROXY_FINGERPRINT: ${{ inputs.proxy_fingerprint }} | ||||
|         INPUT_USE_INSECURE_CIPHER: ${{ inputs.use_insecure_cipher }} | ||||
|         INPUT_CIPHER: ${{ inputs.cipher }} | ||||
|         INPUT_PROXY_USE_INSECURE_CIPHER: ${{ inputs.proxy_use_insecure_cipher }} | ||||
|         INPUT_PROXY_CIPHER: ${{ inputs.proxy_cipher }} | ||||
|         INPUT_DEBUG: ${{ inputs.debug }} | ||||
|         INPUT_TIMEOUT: ${{ inputs.timeout }} | ||||
|         INPUT_COMMAND_TIMEOUT: ${{ inputs.command_timeout }} | ||||
|         INPUT_TARGET: ${{ inputs.target }} | ||||
|         INPUT_SOURCE: ${{ inputs.source }} | ||||
|         INPUT_RM: ${{ inputs.rm }} | ||||
|         INPUT_STRIP_COMPONENTS: ${{ inputs.strip_components }} | ||||
|         INPUT_OVERWRITE: ${{ inputs.overwrite }} | ||||
|         INPUT_TAR_DEREFERENCE: ${{ inputs.tar_dereference }} | ||||
|         INPUT_TAR_TMP_PATH: ${{ inputs.tar_tmp_path }} | ||||
|         INPUT_TAR_EXEC: ${{ inputs.tar_exec }} | ||||
|         INPUT_PROXY_TIMEOUT: ${{ inputs.proxy_timeout }} | ||||
|         INPUT_CAPTURE_STDOUT: ${{ inputs.capture_stdout }} | ||||
|         INPUT_CURL_INSECURE: ${{ inputs.curl_insecure }} | ||||
|         DRONE_SCP_VERSION: ${{ inputs.version }} | ||||
|  | ||||
| branding: | ||||
|   icon: 'copy' | ||||
|   color: 'gray-dark' | ||||
|   icon: "copy" | ||||
|   color: "gray-dark" | ||||
|   | ||||
| @@ -1,9 +1,60 @@ | ||||
| #!/bin/sh | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| set -eu | ||||
| set -euo pipefail | ||||
|  | ||||
| export GITHUB="true" | ||||
|  | ||||
| [ -n "$INPUT_STRIP_COMPONENTS" ] && export INPUT_STRIP_COMPONENTS=$((INPUT_STRIP_COMPONENTS + 0)) | ||||
| GITHUB_ACTION_PATH="${GITHUB_ACTION_PATH%/}" | ||||
| DRONE_SCP_RELEASE_URL="${DRONE_SCP_RELEASE_URL:-https://github.com/appleboy/drone-scp/releases/download}" | ||||
| DRONE_SCP_VERSION="${DRONE_SCP_VERSION:-1.8.0}" | ||||
|  | ||||
| sh -c "/bin/drone-scp $*" | ||||
| function log_error() { | ||||
|   echo "$1" >&2 | ||||
|   exit "$2" | ||||
| } | ||||
|  | ||||
| function detect_client_info() { | ||||
|   CLIENT_PLATFORM="${SCP_CLIENT_OS:-$(uname -s | tr '[:upper:]' '[:lower:]')}" | ||||
|   CLIENT_ARCH="${SCP_CLIENT_ARCH:-$(uname -m)}" | ||||
|  | ||||
|   case "${CLIENT_PLATFORM}" in | ||||
|   darwin | linux | windows) ;; | ||||
|   *) log_error "Unknown or unsupported platform: ${CLIENT_PLATFORM}. Supported platforms are Linux, Darwin, and Windows." 2 ;; | ||||
|   esac | ||||
|  | ||||
|   case "${CLIENT_ARCH}" in | ||||
|   x86_64* | i?86_64* | amd64*) CLIENT_ARCH="amd64" ;; | ||||
|   aarch64* | arm64*) CLIENT_ARCH="arm64" ;; | ||||
|   *) log_error "Unknown or unsupported architecture: ${CLIENT_ARCH}. Supported architectures are x86_64, i686, and arm64." 3 ;; | ||||
|   esac | ||||
| } | ||||
|  | ||||
| detect_client_info | ||||
| DOWNLOAD_URL_PREFIX="${DRONE_SCP_RELEASE_URL}/v${DRONE_SCP_VERSION}" | ||||
| CLIENT_BINARY="drone-scp-${DRONE_SCP_VERSION}-${CLIENT_PLATFORM}-${CLIENT_ARCH}" | ||||
| TARGET="${GITHUB_ACTION_PATH}/${CLIENT_BINARY}" | ||||
| echo "Downloading ${CLIENT_BINARY} from ${DOWNLOAD_URL_PREFIX}" | ||||
| INSECURE_OPTION="" | ||||
| if [[ "${INPUT_CURL_INSECURE}" == 'true' ]]; then | ||||
|   INSECURE_OPTION="--insecure" | ||||
| fi | ||||
|  | ||||
| if [[ ! -x "${TARGET}" ]]; then | ||||
|   curl -fsSL --retry 5 --keepalive-time 2 ${INSECURE_OPTION} "${DOWNLOAD_URL_PREFIX}/${CLIENT_BINARY}" -o "${TARGET}" | ||||
|   chmod +x "${TARGET}" | ||||
| else | ||||
|   echo "Binary ${CLIENT_BINARY} already exists and is executable, skipping download." | ||||
| fi | ||||
|  | ||||
| echo "======= CLI Version Information =======" | ||||
| "${TARGET}" --version | ||||
| echo "=======================================" | ||||
| if [[ "${INPUT_CAPTURE_STDOUT}" == 'true' ]]; then | ||||
|   { | ||||
|     echo 'stdout<<EOF' | ||||
|     "${TARGET}" "$@" | tee -a "${GITHUB_OUTPUT}" | ||||
|     echo 'EOF' | ||||
|   } >>"${GITHUB_OUTPUT}" | ||||
| else | ||||
|   "${TARGET}" "$@" | ||||
| fi | ||||
|   | ||||
| @@ -1 +1,2 @@ | ||||
| foo | ||||
| foobar | ||||
|   | ||||
| @@ -1 +1,2 @@ | ||||
| bar | ||||
| foobar | ||||
|   | ||||
| @@ -1 +1,3 @@ | ||||
| c | ||||
| foobar | ||||
| test1234 | ||||
|   | ||||
| @@ -1 +1,3 @@ | ||||
| d | ||||
| foobar | ||||
| foobar | ||||
|   | ||||
		Reference in New Issue
	
	Block a user