Compare commits

...

121 Commits

Author SHA1 Message Date
github-actions
2cc5b27bf3 chore(release): 6.0.3 [skip ci]
## [6.0.3](https://github.com/easingthemes/ssh-deploy/compare/v6.0.2...v6.0.3) (2026-04-02)

### Bug Fixes

* keep @semantic-release/github plugin for GitHub Releases ([0cffff4](0cffff4878))
* update major version tag as post-release step ([6306dda](6306ddad7c))
2026-04-02 21:50:15 +00:00
Dragan Filipović
066a59ba0d Merge pull request #213 from easingthemes/fix/update-major-tag-on-release
fix: update major version tag as post-release step
2026-04-02 23:49:42 +02:00
Dragan Filipovic
0cffff4878 fix: keep @semantic-release/github plugin for GitHub Releases
This plugin creates proper GitHub Release pages with changelogs,
which is valuable independently of workflow triggering.
2026-04-02 23:48:36 +02:00
Dragan Filipovic
6306ddad7c fix: update major version tag as post-release step
Move major tag update (e.g. v6) into the release workflow as a
conditional step, gated on semantic-release actually publishing.
This avoids the GITHUB_TOKEN limitation where events from the
default token don't trigger separate workflows.

Also reverts @semantic-release/github from .releaserc since we no
longer rely on the release event to trigger a separate workflow.
2026-04-02 23:47:01 +02:00
github-actions
ffb309fccf chore(release): 6.0.2 [skip ci]
## [6.0.2](https://github.com/easingthemes/ssh-deploy/compare/v6.0.1...v6.0.2) (2026-04-02)

### Bug Fixes

* add @semantic-release/github plugin to create GitHub Releases ([9e4918b](9e4918b4e1))
2026-04-02 21:41:16 +00:00
Dragan Filipović
0f3da31792 Merge pull request #212 from easingthemes/fix/add-github-release-plugin
fix: add @semantic-release/github plugin to create GitHub Releases
2026-04-02 23:40:48 +02:00
Dragan Filipovic
9e4918b4e1 fix: add @semantic-release/github plugin to create GitHub Releases
The update-major-tag workflow triggers on `release: published`, but
semantic-release was only creating git tags (via @semantic-release/git)
without creating actual GitHub Release objects. This meant the workflow
never fired.
2026-04-02 23:40:00 +02:00
github-actions
5d8aeab1a5 chore(release): 6.0.1 [skip ci]
## [6.0.1](https://github.com/easingthemes/ssh-deploy/compare/v6.0.0...v6.0.1) (2026-04-02)

### Bug Fixes

* upgrade devDependencies and migrate to eslint 10 flat config ([c88faf5](c88faf5656))
2026-04-02 21:32:53 +00:00
Dragan Filipović
0f723444d0 Merge pull request #211 from easingthemes/chore/upgrade-devdeps-eslint10
chore: upgrade devDependencies and migrate to eslint 10 flat config
2026-04-02 23:32:28 +02:00
Dragan Filipovic
c88faf5656 fix: upgrade devDependencies and migrate to eslint 10 flat config
- Upgrade eslint 8.31 → 10.1 with new flat config (eslint.config.js)
- Upgrade @vercel/ncc 0.36 → 0.38.4
- Replace eslint-config-airbnb-base + eslint-plugin-import with @eslint/js + @stylistic/eslint-plugin
- Remove stale overrides in package.json (word-wrap, semver)
- Remove obsolete eslint-disable comments from source files
- Add { cause } to rethrown error in rsyncCli.js
- Add .gitignore and CLAUDE.md
- Resolves all 3 npm audit vulnerabilities (flatted, minimatch, js-yaml)
2026-04-02 23:31:02 +02:00
github-actions
d346ae8045 chore(release): 6.0.0 [skip ci]
# [6.0.0](https://github.com/easingthemes/ssh-deploy/compare/v5.1.2...v6.0.0) (2026-04-02)

* feat!: replace rsyncwrapper with direct child_process.spawn ([b11fb7f](b11fb7f911))
* feat!: replace rsyncwrapper with local rsync module ([71b8eb3](71b8eb300f))

### Bug Fixes

* add proc.on('error') handler to prevent hanging on spawn failure ([c81b43c](c81b43c5bf))

### BREAKING CHANGES

* rsyncwrapper dependency removed, rsync command is now
constructed and executed via a local module using child_process.spawn.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* rsyncwrapper dependency removed, rsync command is now
constructed and executed directly via child_process.spawn.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 21:21:22 +00:00
Dragan Filipović
7a10983690 Merge pull request #209 from easingthemes/refactor/remove-rsyncwrapper
feat!: replace rsyncwrapper with direct child_process.spawn
2026-04-02 23:20:52 +02:00
Dragan Filipovic
aea56817cd Merge remote-tracking branch 'origin/main' into refactor/remove-rsyncwrapper 2026-04-02 23:19:51 +02:00
Dragan Filipovic
a4b077c853 chore: revert e2e-manual to use published action 2026-04-02 23:19:12 +02:00
Dragan Filipovic
33880d2926 test: use local action in e2e-manual for branch testing 2026-04-02 23:17:55 +02:00
Dragan Filipovic
c81b43c5bf fix: add proc.on('error') handler to prevent hanging on spawn failure 2026-04-02 23:09:25 +02:00
Dragan Filipovic
71b8eb300f feat!: replace rsyncwrapper with local rsync module
Add src/rsync.js as a drop-in replacement for rsyncwrapper, using
child_process.spawn directly. Only implements the options this project
uses. Single line change in rsyncCli.js to swap the import.

BREAKING CHANGE: rsyncwrapper dependency removed, rsync command is now
constructed and executed via a local module using child_process.spawn.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 23:03:21 +02:00
Dragan Filipovic
76668b2cd6 chore: add workflow to auto-update major version tag on release
Adds update-major-tag.yml that triggers on any published release and
force-updates the major version tag (e.g., v6) to point to the latest
release (e.g., v6.0.1). Enables users to pin to @v6 instead of full
version numbers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:59:30 +02:00
Dragan Filipovic
be39df3f93 chore: update GitHub Actions to latest major versions
- actions/checkout v4 → v6
- actions/setup-node v4 → v6
- cycjimmy/semantic-release-action v4 → v6 (pinned semantic_version: 24)
- github/codeql-action v3 → v4
- actions/stale v9 (already latest)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:56:10 +02:00
Dragan Filipovic
b11fb7f911 feat!: replace rsyncwrapper with direct child_process.spawn
Remove the outdated rsyncwrapper dependency (unmaintained, uses
deprecated util._extend) and replace with a built-in buildRsyncCommand()
+ spawn implementation. Zero runtime dependencies.

BREAKING CHANGE: rsyncwrapper dependency removed, rsync command is now
constructed and executed directly via child_process.spawn.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:50:21 +02:00
github-actions
922253577e chore(release): 5.1.2 [skip ci]
## [5.1.2](https://github.com/easingthemes/ssh-deploy/compare/v5.1.1...v5.1.2) (2026-04-02)

### Bug Fixes

* update Node.js runtime from 20 to 24 ([681efb5](681efb59f1)), closes [#207](https://github.com/easingthemes/ssh-deploy/issues/207)
2026-04-02 20:41:50 +00:00
Dragan Filipović
1326d0a611 Merge pull request #208 from easingthemes/fix/node24-compatibility
fix: update Node.js runtime from 20 to 24
2026-04-02 22:41:26 +02:00
Dragan Filipovic
681efb59f1 fix: update Node.js runtime from 20 to 24
GitHub Actions is deprecating Node.js 20 runners starting June 2, 2026.
Update action runtime and CI workflows to Node.js 24.

Closes #207

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:40:21 +02:00
Dragan Filipović
2644554bce Update stale.yml
Some checks failed
Build / build (20.x, ubuntu-latest) (push) Has been cancelled
e2e Test / e2e (push) Has been cancelled
e2e Test / e2e-v3 (push) Has been cancelled
Release / Test, Build and Release (20.x, ubuntu-latest) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Failing after 8m10s
Close stale issues / stale (push) Failing after 14m57s
2026-02-10 21:38:30 +01:00
github-actions
a1aa0b6cf9 chore(release): 5.1.1 [skip ci]
## [5.1.1](https://github.com/easingthemes/ssh-deploy/compare/v5.1.0...v5.1.1) (2024-07-24)

### Bug Fixes

* Update README.md ([f007431](f007431332))
2024-07-24 17:04:53 +00:00
Dragan Filipović
f007431332 fix: Update README.md 2024-07-24 19:04:28 +02:00
github-actions
ece05a2275 chore(release): 5.1.0 [skip ci]
# [5.1.0](https://github.com/easingthemes/ssh-deploy/compare/v5.0.3...v5.1.0) (2024-07-24)

### Features

* Add deleteFile function to helpers module ([1befdb1](1befdb1c6b))
* apply deleteFile function to remoteCmd ([b82eced](b82eced457))
2024-07-24 16:55:35 +00:00
Dragan Filipović
b99511bf85 Merge pull request #184 from Armadillidiid/feat/delete-script-after-exec
Feature: Delete Script After Execution
2024-07-24 18:55:06 +02:00
Emmanuel Isenah
b82eced457 feat: apply deleteFile function to remoteCmd 2024-03-17 22:21:09 +01:00
Emmanuel Isenah
1befdb1c6b feat: Add deleteFile function to helpers module 2024-03-17 22:19:34 +01:00
github-actions
01a39e3348 chore(release): 5.0.3 [skip ci]
## [5.0.3](https://github.com/easingthemes/ssh-deploy/compare/v5.0.2...v5.0.3) (2024-02-27)

### Bug Fixes

* trigger automated release ([4d8bbf0](4d8bbf0deb))
2024-02-27 08:58:54 +00:00
Dragan Filipović
f517598798 Merge pull request #180 from alekw/main
fix: Update actions to Node.js 20
2024-02-27 09:58:22 +01:00
Aleksander Wolak
4d8bbf0deb fix: trigger automated release 2024-02-26 23:55:50 +01:00
Aleksander Wolak
428f2b152b fix own action version 2024-02-26 23:48:33 +01:00
github-actions
8c3965fd5f chore(release): 5.0.2 [skip ci]
## [5.0.2](https://github.com/easingthemes/ssh-deploy/compare/v5.0.1...v5.0.2) (2024-02-18)

### Bug Fixes

* added the missing declarations [#177](https://github.com/easingthemes/ssh-deploy/issues/177) ([bb271fe](bb271fe4c6))
* Fix default values used incorrectly. ([a1b383f](a1b383f560))
2024-02-18 17:44:58 +00:00
Dragan Filipović
186d0277e9 Merge pull request #178 from skyArony/fix-#177
fix: added the missing declarations #177
2024-02-18 18:44:30 +01:00
skyArony
a1b383f560 fix: Fix default values used incorrectly. 2024-02-18 22:43:02 +08:00
Aleksander Wolak
d42d2576ab further fixes 2024-02-16 01:06:08 +01:00
Aleksander Wolak
bed42ef321 further fixes 2024-02-16 00:56:27 +01:00
Aleksander Wolak
07d369f5c8 update well known actions 2024-02-16 00:53:05 +01:00
skyArony
bb271fe4c6 fix: added the missing declarations #177 2024-02-02 16:31:41 +08:00
github-actions
3b7118ee8b chore(release): 5.0.1 [skip ci]
## [5.0.1](https://github.com/easingthemes/ssh-deploy/compare/v5.0.0...v5.0.1) (2024-01-31)

### Bug Fixes

* Add info for Permission denied issue. ([845b578](845b578606))
2024-01-31 01:00:14 +00:00
Dragan Filipović
845b578606 fix: Add info for Permission denied issue. 2024-01-31 01:59:36 +01:00
Dragan Filipović
725ce37b9f Update stale to 90 days 2024-01-18 21:46:42 +01:00
github-actions
16bb35ed0b chore(release): 5.0.0 [skip ci]
# [5.0.0](https://github.com/easingthemes/ssh-deploy/compare/v4.1.10...v5.0.0) (2023-12-12)

* Merge pull request #173 from jeromelachaud/main ([ac1908e](ac1908e5d2)), closes [#173](https://github.com/easingthemes/ssh-deploy/issues/173)

### BREAKING CHANGES

* update to use nodeJS v20
* update to use nodeJS v20
2023-12-12 21:29:39 +00:00
Dragan Filipović
ac1908e5d2 Merge pull request #173 from jeromelachaud/main
BREAKING CHANGE: update to use nodeJS v20

BREAKING CHANGE: update to use nodeJS v20
2023-12-12 22:29:07 +01:00
Jerome Lachaud
d77e3dfdc8 BREAKING CHANGE: update to use nodeJS v20 2023-10-25 13:19:20 +00:00
github-actions
aa1c48118d chore(release): 4.1.10 [skip ci]
## [4.1.10](https://github.com/easingthemes/ssh-deploy/compare/v4.1.9...v4.1.10) (2023-09-30)

### Bug Fixes

* normalize line endings in SSH key for the underlying OS ([3f5d9aa](3f5d9aab1a))
2023-09-30 15:13:25 +00:00
Dragan Filipović
448aa45aa1 Merge pull request #156 from mansandersson/fix-key-line-endings
Normalize line endings in SSH key for the underlying OS
2023-09-30 17:12:46 +02:00
Måns Andersson
3f5d9aab1a fix: normalize line endings in SSH key for the underlying OS 2023-09-28 20:05:00 +02:00
github-actions
2942523001 chore(release): 4.1.9 [skip ci]
## [4.1.9](https://github.com/easingthemes/ssh-deploy/compare/v4.1.8...v4.1.9) (2023-09-24)

### Bug Fixes

* add compiled file ([627ac29](627ac29ece))
* add uuid for ssh scripts ([66f6e4b](66f6e4b367))
2023-09-24 15:37:24 +00:00
Dragan Filipović
ef20db4468 Merge pull request #167 from easingthemes/feature/#131-use-unique-file-name-for-scripts
fix: add uuid for ssh scripts
2023-09-24 17:36:52 +02:00
Dragan Filipovic
627ac29ece fix: add compiled file 2023-09-24 17:35:00 +02:00
Dragan Filipovic
66f6e4b367 fix: add uuid for ssh scripts 2023-09-24 17:29:49 +02:00
Dragan Filipović
d91ea7e0f7 Merge pull request #144 from shoshins/70-no-private-key-password-option
#70 - There is no Password option for Rsync SSH. Documentation is up…
2023-09-24 17:16:11 +02:00
Dragan Filipović
28d946e487 Merge pull request #154 from olivertappin/main
Correct typo in README.md
2023-09-24 16:58:48 +02:00
Dragan Filipović
3ab5951ec1 Merge pull request #141 from dbryan0516/remote-cmd-error
Added SCRIPT_BEFORE_REQUIRED and SCRIPT_AFTER_REQUIRED flags
2023-09-24 16:58:09 +02:00
Dragan Filipović
cf583aab4f Merge pull request #153 from Triloworld/patch-2
Update README.md
2023-08-03 19:18:58 +02:00
Oliver Tappin
8ba86462c0 Correct typo in README.md 2023-06-28 20:36:01 +01:00
Patryk Padus
e7f0312c8c Update README.md
In reference of this issue and comment: https://github.com/easingthemes/ssh-deploy/issues/149
2023-06-23 14:52:23 +02:00
Sergey Shoshin
35ccd2ccc4 #70 - There is no Password option for Rsync SSH. Documentation is updated 2023-04-25 18:11:13 +04:00
Dylan Bryan
ed53b09c84 Added build file 2023-04-18 17:33:08 -04:00
Dylan Bryan
f9797b28d5 Added SCRIPT_BEFORE_REQUIRED and SCRIPT_AFTER_REQUIRED flags for error throwing on remote cmd errors 2023-04-18 17:24:01 -04:00
github-actions
3884c8554f chore(release): 4.1.8 [skip ci]
## [4.1.8](https://github.com/easingthemes/ssh-deploy/compare/v4.1.7...v4.1.8) (2023-02-21)

### Bug Fixes

* rebuild and update readme ([98025d6](98025d680e))
2023-02-21 22:13:02 +00:00
Dragan Filipović
168ff9f4b8 Merge pull request #124 from easingthemes/bugfix/rebuild
fix: rebuild and update readme
2023-02-21 23:12:21 +01:00
Dragan Filipovic
98025d680e fix: rebuild and update readme 2023-02-21 23:11:54 +01:00
Dragan Filipović
88cc5ade97 Merge pull request #123 from sdelfi/fix/update-dist
chore: build dist
2023-02-21 23:06:19 +01:00
Stanislav Salnikov
ad7eefb5ae chore: build dist 2023-02-21 23:03:40 +01:00
github-actions
54dca654be chore(release): 4.1.7 [skip ci]
## [4.1.7](https://github.com/easingthemes/ssh-deploy/compare/v4.1.6...v4.1.7) (2023-02-21)

### Bug Fixes

* [#120](https://github.com/easingthemes/ssh-deploy/issues/120) check undefined data ([2fbb060](2fbb06015d))
2023-02-21 21:36:50 +00:00
Dragan Filipović
b0ee052eb0 Merge pull request #122 from easingthemes/bugfix/#120-inputs-string-bug
fix: #120 check undefined data
2023-02-21 22:36:10 +01:00
Dragan Filipovic
2fbb06015d fix: #120 check undefined data 2023-02-21 22:35:05 +01:00
github-actions
51b2009841 chore(release): 4.1.6 [skip ci]
## [4.1.6](https://github.com/easingthemes/ssh-deploy/compare/v4.1.5...v4.1.6) (2023-02-21)

### Bug Fixes

* [#118](https://github.com/easingthemes/ssh-deploy/issues/118) check undefined default values rebuild ([54f8b6c](54f8b6c60b))
2023-02-21 17:02:47 +00:00
Dragan Filipović
530a3691f2 Merge pull request #121 from easingthemes/bugfix/#118-default-value-check
Bugfix/#118 default value check
2023-02-21 18:02:04 +01:00
Dragan Filipovic
509caf1bb9 Merge branch 'main' into bugfix/#118-default-value-check 2023-02-21 18:01:00 +01:00
Dragan Filipovic
54f8b6c60b fix: #118 check undefined default values rebuild 2023-02-21 18:00:23 +01:00
github-actions
d9d134f8e5 chore(release): 4.1.5 [skip ci]
## [4.1.5](https://github.com/easingthemes/ssh-deploy/compare/v4.1.4...v4.1.5) (2023-02-21)

### Bug Fixes

* [#118](https://github.com/easingthemes/ssh-deploy/issues/118) check undefined default values ([f0c02fb](f0c02fb2a5))
2023-02-21 16:12:23 +00:00
Dragan Filipović
e7b2312bc9 Merge pull request #119 from easingthemes/bugfix/#118-default-value-check
fix: #118 check undefined default values
2023-02-21 17:11:53 +01:00
Dragan Filipovic
f0c02fb2a5 fix: #118 check undefined default values 2023-02-21 17:10:24 +01:00
github-actions
ae4970d4cf chore(release): 4.1.4 [skip ci]
## [4.1.4](https://github.com/easingthemes/ssh-deploy/compare/v4.1.3...v4.1.4) (2023-02-21)

### Bug Fixes

* [#113](https://github.com/easingthemes/ssh-deploy/issues/113) limit ssh script input ([5894f5e](5894f5e290))
2023-02-21 16:03:56 +00:00
Dragan Filipovic
5894f5e290 fix: #113 limit ssh script input 2023-02-21 17:03:16 +01:00
github-actions
c381b885db chore(release): 4.1.3 [skip ci]
## [4.1.3](https://github.com/easingthemes/ssh-deploy/compare/v4.1.2...v4.1.3) (2023-02-21)

### Bug Fixes

* [#113](https://github.com/easingthemes/ssh-deploy/issues/113) limit ssh script output - rebuild ([756a522](756a522533))
2023-02-21 15:56:09 +00:00
Dragan Filipovic
756a522533 fix: #113 limit ssh script output - rebuild 2023-02-21 16:55:32 +01:00
github-actions
45cee3db2e chore(release): 4.1.2 [skip ci]
## [4.1.2](https://github.com/easingthemes/ssh-deploy/compare/v4.1.1...v4.1.2) (2023-02-21)

### Bug Fixes

* [#113](https://github.com/easingthemes/ssh-deploy/issues/113) limit ssh script output ([59827af](59827af83c))
2023-02-21 15:54:41 +00:00
Dragan Filipovic
59827af83c fix: #113 limit ssh script output 2023-02-21 16:53:56 +01:00
github-actions
adb1a2ce99 chore(release): 4.1.1 [skip ci]
## [4.1.1](https://github.com/easingthemes/ssh-deploy/compare/v4.1.0...v4.1.1) (2023-02-21)

### Bug Fixes

* fix default TARGET ([4d08634](4d086346af))
2023-02-21 14:37:18 +00:00
Dragan Filipovic
4d086346af fix: fix default TARGET 2023-02-21 15:36:29 +01:00
Dragan Filipovic
056fb0fea7 [e2e] use main for latest tests 2023-02-21 14:50:41 +01:00
Dragan Filipovic
d7e6989d58 [e2e] rebuild: log default values 2023-02-21 14:46:17 +01:00
Dragan Filipovic
0fb307eb41 [e2e] log default values 2023-02-21 14:43:52 +01:00
Dragan Filipovic
a7b7e1e49d [e2e] add default values test 2023-02-21 14:38:27 +01:00
github-actions
e995cb4b7b chore(release): 4.1.0 [skip ci]
# [4.1.0](https://github.com/easingthemes/ssh-deploy/compare/v4.0.5...v4.1.0) (2023-02-19)

### Features

* add ssh port from VARs, fix package-lock ([808b002](808b0020d4))
2023-02-19 17:30:20 +00:00
Dragan Filipovic
808b0020d4 feat: add ssh port from VARs, fix package-lock 2023-02-19 18:29:35 +01:00
Dragan Filipović
d5e1f75798 Merge pull request #116 from Cascade-Lab/sb-fix-host-scan-port
Use custom port for host scan
2023-02-19 18:25:20 +01:00
Sebastian Blesgen
a1e01b2fad Use custom port for host scan 2023-02-10 18:55:53 +01:00
github-actions
164a3e861e chore(release): 4.0.5 [skip ci]
## [4.0.5](https://github.com/easingthemes/ssh-deploy/compare/v4.0.4...v4.0.5) (2023-01-06)

### Bug Fixes

* fix manual release action ([245b7a9](245b7a9d2f))
2023-01-06 20:51:37 +00:00
Dragan Filipović
426f06d922 Merge pull request #106 from easingthemes/manual-release
fix: fix manual release action
2023-01-06 21:50:57 +01:00
Dragan Filipovic
245b7a9d2f fix: fix manual release action 2023-01-06 21:50:25 +01:00
Dragan Filipović
4c8eee72bd Merge pull request #105 from npiasecki/fix-remote-port
Add remote port
2023-01-05 20:21:22 +01:00
Nicholas Piasecki
0a1df91f97 Add remote port 2023-01-04 12:18:09 -05:00
github-actions
845b7f6f1f chore(release): 4.0.4 [skip ci]
## [4.0.4](https://github.com/easingthemes/ssh-deploy/compare/v4.0.3...v4.0.4) (2023-01-03)

### Bug Fixes

* update sub dependencies ([2a32c8d](2a32c8dcde))
2023-01-03 22:41:11 +00:00
Dragan Filipovic
2a32c8dcde fix: update sub dependencies 2023-01-03 23:40:24 +01:00
github-actions
0b63b85565 chore(release): 4.0.3 [skip ci]
## [4.0.3](https://github.com/easingthemes/ssh-deploy/compare/v4.0.2...v4.0.3) (2023-01-03)

### Bug Fixes

* update v3 e2e test ([450bf42](450bf423f3))
2023-01-03 22:16:09 +00:00
Dragan Filipovic
450bf423f3 fix: update v3 e2e test 2023-01-03 23:15:21 +01:00
github-actions
affc58a8b7 chore(release): 4.0.2 [skip ci]
## [4.0.2](https://github.com/easingthemes/ssh-deploy/compare/v4.0.1...v4.0.2) (2023-01-03)

### Bug Fixes

* add githubWorkspace as default source root ([3ef66d0](3ef66d0be9))
2023-01-03 22:08:02 +00:00
github-actions
8c12d45929 patch: Trigger Manual Release 2023-01-03 22:07:41 +00:00
Dragan Filipović
85987f4567 Merge pull request #101 from easingthemes/bugfix/src-dir
fix: add githubWorkspace as default source root
2023-01-03 23:05:33 +01:00
Dragan Filipovic
3ef66d0be9 fix: add githubWorkspace as default source root 2023-01-03 23:02:41 +01:00
github-actions
79363f2b74 chore(release): 4.0.1 [skip ci]
## [4.0.1](https://github.com/easingthemes/ssh-deploy/compare/v4.0.0...v4.0.1) (2023-01-03)

### Bug Fixes

* fix default source if empty ([9f191f4](9f191f4263))
2023-01-03 20:57:09 +00:00
Dragan Filipović
7c21074882 Merge pull request #99 from easingthemes/bugfix/fix-empty-src
fix: fix default source if empty
2023-01-03 21:56:33 +01:00
Dragan Filipovic
9f191f4263 fix: fix default source if empty 2023-01-03 21:55:45 +01:00
Dragan Filipovic
006cf3021d Add v3 e2e 2023-01-03 19:29:28 +01:00
github-actions
8be4106fce chore(release): 4.0.0 [skip ci]
# [4.0.0](https://github.com/easingthemes/ssh-deploy/compare/v3.4.3...v4.0.0) (2023-01-03)

### Bug Fixes

* rebuild ([2169399](2169399fef))

### Performance Improvements

* update default rsync options ([2be7efb](2be7efb376))

### BREAKING CHANGES

* Default rsync options updated to speed up default deployments.
from `rltgoDzvO` to `-rlgoDzvc -i`
2023-01-03 08:34:27 +00:00
Dragan Filipović
7c9b40539e Merge pull request #96 from easingthemes/feature/default-rsync-options
feat: update default rsync options
2023-01-03 09:33:49 +01:00
Dragan Filipovic
2169399fef fix: rebuild 2023-01-03 09:25:16 +01:00
Dragan Filipovic
2be7efb376 perf: update default rsync options
BREAKING CHANGE: Default rsync options updated to speed up default deployments.
from `rltgoDzvO` to `-rlgoDzvc -i`
2023-01-03 09:21:19 +01:00
Dragan Filipovic
e6e41a57ec Merge branch 'temp3' 2023-01-03 03:39:52 +01:00
github-actions
c8d57ec8b4 chore(release): 3.4.3 [skip ci]
## [3.4.3](https://github.com/easingthemes/ssh-deploy/compare/v3.4.2...v3.4.3) (2023-01-03)

### Bug Fixes

* move e2e tests typo branch name ([6d3554b](6d3554b01e))
2023-01-03 03:38:43 +01:00
github-actions
8bf58fb293 chore(release): 3.4.3 [skip ci]
## [3.4.3](https://github.com/easingthemes/ssh-deploy/compare/v3.4.2...v3.4.3) (2023-01-03)

### Bug Fixes

* move e2e tests typo branch name ([6d3554b](6d3554b01e))
2023-01-03 02:29:31 +00:00
Dragan Filipovic
6d3554b01e fix: move e2e tests typo branch name 2023-01-03 03:28:39 +01:00
github-actions
8ad0b68b03 chore(release): 3.4.2 [skip ci]
## [3.4.2](https://github.com/easingthemes/ssh-deploy/compare/v3.4.1...v3.4.2) (2023-01-03)

### Bug Fixes

* Update changelog ([765f5ff](765f5ffd31))
2023-01-03 02:26:00 +00:00
Dragan Filipovic
765f5ffd31 fix: Update changelog 2023-01-03 03:25:23 +01:00
25 changed files with 1332 additions and 2590 deletions

View File

@@ -1,25 +0,0 @@
module.exports = {
env: {
commonjs: true,
es6: true,
node: true
},
extends: [
'airbnb-base'
],
globals: {
Atomics: 'readonly',
SharedArrayBuffer: 'readonly'
},
parserOptions: {
ecmaVersion: 2018
},
rules: {
'comma-dangle': [
'error',
'never'
],
'no-console': 'off',
'object-curly-newline': 'off'
}
};

View File

@@ -14,13 +14,13 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest] os: [ubuntu-latest]
node-version: [16.x] node-version: [24.x]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v6
- name: Setup Node.js ${{ matrix.node-version }} - name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3 uses: actions/setup-node@v6
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
- name: Install dependencies - name: Install dependencies

View File

@@ -31,11 +31,11 @@ jobs:
language: [ 'javascript' ] language: [ 'javascript' ]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v6
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v2 uses: github/codeql-action/init@v4
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
@@ -44,4 +44,4 @@ jobs:
npm run build --if-present npm run build --if-present
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2 uses: github/codeql-action/analyze@v4

View File

@@ -6,7 +6,7 @@ on:
ARGS: ARGS:
description: 'ARGS' description: 'ARGS'
required: true required: true
default: '-rltgoDzvO --delete --chmod=ugo+rwX --progress' default: '-rlgoDzvc -i --delete --chmod=ugo+rwX --progress'
EXCLUDE: EXCLUDE:
description: 'EXCLUDE' description: 'EXCLUDE'
required: true required: true
@@ -27,7 +27,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v6
# ---------------------------------------------------------------- # ----------------------------------------------------------------
# START E2E Test Specific - steps # START E2E Test Specific - steps

View File

@@ -15,7 +15,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v6
# : --------------------------------------------------------------- # : ---------------------------------------------------------------
# : START E2E Test Specific - steps # : START E2E Test Specific - steps
@@ -74,7 +74,7 @@ jobs:
- name: set shared ENV variables for multi target deployment - name: set shared ENV variables for multi target deployment
run: | run: |
echo "ARGS=-rltgoDzvOR --delete --chmod=ugo+rwX --progress" >> $GITHUB_ENV echo "ARGS=-rlgoDzvcR -i --delete --chmod=ugo+rwX --progress" >> $GITHUB_ENV
echo "SSH_CMD_ARGS=-o StrictHostKeyChecking=no, -o UserKnownHostsFile=/dev/null" >> $GITHUB_ENV echo "SSH_CMD_ARGS=-o StrictHostKeyChecking=no, -o UserKnownHostsFile=/dev/null" >> $GITHUB_ENV
echo "SOURCE=test_project/ test_project2/" >> $GITHUB_ENV echo "SOURCE=test_project/ test_project2/" >> $GITHUB_ENV
echo "EXCLUDE=skip_dir/, /node_modules/" >> $GITHUB_ENV echo "EXCLUDE=skip_dir/, /node_modules/" >> $GITHUB_ENV
@@ -95,8 +95,85 @@ jobs:
TARGET: /var/www/html/${{ env.TEST_USER }} TARGET: /var/www/html/${{ env.TEST_USER }}
- name: e2e Test ssh-deploy action - Target 2 - name: e2e Test ssh-deploy action - Target 2
uses: easingthemes/ssh-deploy@feature/multi-src uses: easingthemes/ssh-deploy@main
env: env:
# Shared ENV Vars created in previous steps # Shared ENV Vars created in previous steps
REMOTE_USER: ${{ env.TEST_USER2 }} REMOTE_USER: ${{ env.TEST_USER2 }}
TARGET: /var/www/html/${{ env.TEST_USER2 }} TARGET: /var/www/html/${{ env.TEST_USER2 }}
- name: e2e Test ssh-deploy action - Default values
uses: easingthemes/ssh-deploy@main
env:
# Shared ENV Vars created in previous steps
REMOTE_USER: ${{ env.TEST_USER }}
e2e-v3:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
# : ---------------------------------------------------------------
# : START E2E Test Specific - steps
# : ----------------------------------------------------------------
- name: E2E Test Specific - Clean up old test files
run: |
docker stop ssh-host-container || true && docker rm ssh-host-container || true
- name: E2E Test Specific - Create ssh keys
run: |
echo $HOME
ls -la $HOME
ssh-keygen -m PEM -t rsa -b 4096 -f "$HOME/.ssh/id_rsa" -N ""
eval `ssh-agent -s`
ssh-add "$HOME/.ssh/id_rsa"
ssh-add -l
echo "SSH_PRIVATE_KEY<<EOF" >> $GITHUB_ENV
cat $HOME/.ssh/id_rsa >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: E2E Test Specific - Build Host Server Image
working-directory: ${{ env.TEST_HOST_DOCKER }}
run: |
docker build \
-t ssh-host-image . \
--build-arg SSH_PUB_KEY="$(cat $HOME/.ssh/id_rsa.pub)"
docker run -d -p 8822:22 --name=ssh-host-container ssh-host-image
docker exec ssh-host-container sh -c "hostname --ip-address" > ip.txt
echo "REMOTE_HOST<<EOF" >> $GITHUB_ENV
cat ip.txt >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
shell: bash
- name: E2E Test Specific - Create project file
run: |
mkdir test_project2 && cd "$_"
truncate -s 5MB info2.txt
cd ../
mkdir test_project && cd "$_"
touch index.html
date +"%Y-%m-%d %H:%M:%S,%3N" >> index.html
truncate -s 50MB image.svg
truncate -s 5MB info.txt
truncate -s 500MB big_file.txt
mkdir skip_dir && cd "$_"
truncate -s 5MB text_in_skip_dir.txt
cd ../
cat index.html
echo "test_project:" && ls -lR
echo "skip_dir:" && ls -lR skip_dir
# ----------------------------------------------------------------
# END E2E Test Specific - steps
# ----------------------------------------------------------------
- name: e2e Test ssh-deploy action - Target 1
uses: easingthemes/ssh-deploy@main
env:
# Shared ENV Vars created in previous steps
REMOTE_USER: ${{ env.TEST_USER }}
TARGET: /var/www/html/${{ env.TEST_USER }}
SOURCE: test_project/
EXCLUDE: skip_dir/, /node_modules/
ARGS: -rlgoDzvcO

View File

@@ -6,11 +6,10 @@ on:
description: 'Version' description: 'Version'
type: choice type: choice
required: true required: true
default: patch default: fix
options: options:
- patch - fix
- minor - feat
- major
dryRun: dryRun:
description: 'DryRun' description: 'DryRun'
type: boolean type: boolean
@@ -50,9 +49,9 @@ jobs:
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@v3 uses: actions/checkout@v6
- name: Setup Node.js ${{ matrix.NODE_VERSION }} - name: Setup Node.js ${{ matrix.NODE_VERSION }}
uses: actions/setup-node@v3 uses: actions/setup-node@v6
with: with:
node-version: ${{ matrix.NODE_VERSION }} node-version: ${{ matrix.NODE_VERSION }}
- name: Commit trigger - name: Commit trigger
@@ -64,9 +63,10 @@ jobs:
run: npm run build --if-present run: npm run build --if-present
- name: Run Tests - name: Run Tests
run: npm test --if-present run: npm test --if-present
- name: Publish npm package - name: Create a release - ${{ github.event.inputs.version }}
uses: cycjimmy/semantic-release-action@v3 uses: cycjimmy/semantic-release-action@v6
with: with:
semantic_version: 24
dry_run: ${{ github.event.inputs.dryRun == 'true' }} dry_run: ${{ github.event.inputs.dryRun == 'true' }}
extra_plugins: | extra_plugins: |
@semantic-release/changelog @semantic-release/changelog

View File

@@ -12,13 +12,13 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ ubuntu-latest ] os: [ ubuntu-latest ]
node-version: [ 16.x ] node-version: [ 24.x ]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v6
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v6
with: with:
node-version: ${{ matrix['node-version'] }} node-version: ${{ matrix['node-version'] }}
- name: Install dependencies - name: Install dependencies
@@ -28,8 +28,10 @@ jobs:
- name: Run Tests - name: Run Tests
run: npm test --if-present run: npm test --if-present
- name: Release - name: Release
uses: cycjimmy/semantic-release-action@v3 id: semantic
uses: cycjimmy/semantic-release-action@v6
with: with:
semantic_version: 24
dry_run: false dry_run: false
extra_plugins: | extra_plugins: |
@semantic-release/changelog @semantic-release/changelog
@@ -42,3 +44,11 @@ jobs:
GIT_COMMITTER_NAME: github-actions GIT_COMMITTER_NAME: github-actions
GIT_COMMITTER_EMAIL: github-actions@github.com GIT_COMMITTER_EMAIL: github-actions@github.com
CI: true CI: true
- name: Update major version tag
if: steps.semantic.outputs.new_release_published == 'true'
run: |
MAJOR="v${{ steps.semantic.outputs.new_release_major_version }}"
TAG="v${{ steps.semantic.outputs.new_release_version }}"
echo "Updating $MAJOR tag to point to $TAG"
git tag -f "$MAJOR" "$TAG"
git push -f origin "$MAJOR"

View File

@@ -17,10 +17,10 @@ jobs:
issues: write issues: write
steps: steps:
- uses: actions/stale@v7 - uses: actions/stale@v9
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.' stale-issue-message: 'This issue is stale because it has been open 150 days with no activity. Remove stale label or comment or this will be closed in 30 days.'
days-before-stale: 30 days-before-stale: 150
days-before-close: 5 days-before-close: 30
stale-issue-label: 'stale' stale-issue-label: 'stale'

3
.gitignore vendored
View File

@@ -20,3 +20,6 @@ node_modules/
# IDE # IDE
.idea .idea
.vscode .vscode
# AI
.claude/settings.local.json

View File

@@ -17,6 +17,7 @@
{ {
"assets": ["docs/CHANGELOG.md", "package.json"] "assets": ["docs/CHANGELOG.md", "package.json"]
} }
] ],
"@semantic-release/github"
] ]
} }

40
CLAUDE.md Normal file
View File

@@ -0,0 +1,40 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
GitHub Action for deploying files via rsync over SSH, with optional remote script execution before/after deployment. Published as `easingthemes/ssh-deploy` on the GitHub Marketplace.
## Commands
- **Build (lint + bundle):** `npm run build`
- **Lint only:** `npm run lint`
- **Lint with autofix:** `npm run lint:fix`
- **No unit test suite** — testing is done via e2e workflows in CI (Docker-based SSH server, see `.github/workflows/e2e.yml`)
The build step runs ESLint then bundles `src/index.js` into `dist/index.js` using `@vercel/ncc`. The `dist/index.js` is the actual entrypoint executed by GitHub Actions (defined in `action.yml`).
## Architecture
The action runs as a single Node.js 24 process with this execution flow:
1. **`src/inputs.js`** — Reads all config from environment variables (both `INPUT_*` and bare names). Converts `SNAKE_CASE` input names to `camelCase`. Splits multi-value inputs: `SOURCE` and `ARGS` on spaces, `EXCLUDE` and `SSH_CMD_ARGS` on commas. Prepends `GITHUB_WORKSPACE` to source paths. Exports a single `inputs` object used by all other modules.
2. **`src/index.js`** — Orchestration entry point. Pipeline: validate inputs → write SSH key → optionally update known_hosts → run SCRIPT_BEFORE → rsync → run SCRIPT_AFTER.
3. **`src/sshKey.js`** — Writes the SSH private key to `~/.ssh/<deploy_key_name>` with mode `0400`. Creates `known_hosts` file. Uses `ssh-keyscan` to add the remote host when before/after scripts are configured.
4. **`src/rsyncCli.js`** — Validates rsync is installed (auto-installs via apt-get if missing). Uses the local `src/rsync.js` module (child_process.spawn) to execute the rsync transfer.
5. **`src/remoteCmd.js`** — Writes script content to a temporary `.sh` file in the workspace, executes it on the remote host via `ssh ... 'bash -s' < script.sh`, then deletes the local script file. Passes `RSYNC_STDOUT` env var to after-scripts.
6. **`src/helpers.js`** — File I/O utilities (`writeToFile`, `deleteFile`), input validation, and `snakeToCamel` converter.
## Key Conventions
- **CommonJS modules** — the project uses `require`/`module.exports`, not ES modules.
- **ESLint 10 flat config** (`eslint.config.js`) — uses `@eslint/js` recommended + `@stylistic/eslint-plugin` for formatting. Notable rules: no trailing commas, `console` is allowed.
- **Semantic release** on `main` branch via `.releaserc` — use conventional commit messages (`fix:`, `feat:`, etc.). npm publish is disabled; releases are git tags + changelog only.
- **`dist/index.js` must be committed** — it's the bundled action entrypoint. Run `npm run build` and commit the updated dist after any source changes.
- **Inputs are environment variables**, not `@actions/core` — the action reads directly from `process.env` rather than using the GitHub Actions toolkit.

View File

@@ -28,6 +28,8 @@ The keys should be generated using the PEM format. You can use this command
``` ```
ssh-keygen -m PEM -t rsa -b 4096 ssh-keygen -m PEM -t rsa -b 4096
``` ```
**Please Note:** You should not set a Passphrase (keep it empty) for the private key you generated.
Because rsync ssh (used for deploy) does not support private key password to be entered as a command line parameter.
##### 2. `REMOTE_HOST` [required] ##### 2. `REMOTE_HOST` [required]
@@ -41,7 +43,7 @@ eg: myusername
eg: '59184' eg: '59184'
##### 5. `ARGS` (optional, default '-rltgoDzvO') ##### 5. `ARGS` (optional, default '-rlgoDzvc -i')
For any initial/required rsync flags, eg: `-avzr --delete` For any initial/required rsync flags, eg: `-avzr --delete`
@@ -62,28 +64,38 @@ path to exclude separated by `,`, ie: `/dist/, /node_modules/`
Script to run on host machine before rsync. Single line or multiline commands. Script to run on host machine before rsync. Single line or multiline commands.
Execution is preformed by storing commands in `.sh` file and executing it via `.bash` over `ssh` Execution is preformed by storing commands in `.sh` file and executing it via `.bash` over `ssh`
If you have issues with `ssh` connection, use this var, eg `SCRIPT_BEFORE: ls`.
This will force `known_hosts` update, adding your host via `ssh-keyscan`.
##### 10. `SCRIPT_AFTER` (optional, default '') ##### 10. `SCRIPT_BEFORE_REQUIRED` (optional, default false)
If set to `true`, Job will fail if SCRIPT_BEFORE fails.
##### 11. `SCRIPT_AFTER` (optional, default '')
Script to run on host machine after rsync. Script to run on host machine after rsync.
Rsync output is stored in `$RSYNC_STDOUT` env variable. Rsync output is stored in `$RSYNC_STDOUT` env variable.
##### 11. `SSH_CMD_ARGS` (optional, default '-o StrictHostKeyChecking=no') ##### 12. `SCRIPT_AFTER_REQUIRED` (optional, default false)
If set to `true`, Job will fail if SCRIPT_AFTER fails.
##### 13. `SSH_CMD_ARGS` (optional, default '-o StrictHostKeyChecking=no')
A list of ssh arguments, they must be prefixed with -o and separated by a comma, for example: -o SomeArgument=no, -o SomeOtherArgument=5 A list of ssh arguments, they must be prefixed with -o and separated by a comma, for example: -o SomeArgument=no, -o SomeOtherArgument=5
# Usage # Usage
Use the latest version from Marketplace,eg: ssh-deploy@v2 Use the latest version from Marketplace,eg: ssh-deploy@v5.1.0
or use the latest version from a branch, eg: ssh-deploy@main or use the latest version from a branch, eg: ssh-deploy@main
``` ```
- name: Deploy to Staging server - name: Deploy to Staging server
uses: easingthemes/ssh-deploy@main uses: easingthemes/ssh-deploy@main
env: with:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO" ARGS: "-rlgoDzvc -i"
SOURCE: "dist/" SOURCE: "dist/"
REMOTE_HOST: ${{ secrets.REMOTE_HOST }} REMOTE_HOST: ${{ secrets.REMOTE_HOST }}
REMOTE_USER: ${{ secrets.REMOTE_USER }} REMOTE_USER: ${{ secrets.REMOTE_USER }}
@@ -111,20 +123,20 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v3
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v1 uses: actions/setup-node@v3
with: with:
node-version: '10.x' node-version: '16.x'
- name: Install npm dependencies - name: Install npm dependencies
run: npm install run: npm install
- name: Run build task - name: Run build task
run: npm run build --if-present run: npm run build --if-present
- name: Deploy to Server - name: Deploy to Server
uses: easingthemes/ssh-deploy@main uses: easingthemes/ssh-deploy@main
env: with:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO --delete" ARGS: "-rlgoDzvc -i --delete"
SOURCE: "dist/" SOURCE: "dist/"
REMOTE_HOST: ${{ secrets.REMOTE_HOST }} REMOTE_HOST: ${{ secrets.REMOTE_HOST }}
REMOTE_USER: ${{ secrets.REMOTE_USER }} REMOTE_USER: ${{ secrets.REMOTE_USER }}
@@ -140,13 +152,18 @@ Almost 95% of the issues are related to wrong SSH connection or `rsync` params a
These issues are not related to the action itself. These issues are not related to the action itself.
- Check manually your ssh connection from your client before opening a bug report. - Check manually your ssh connection from your client before opening a bug report.
- Check `rsync` params for your use-case. Default params are not going to be enough wor everyone, it highly depends on your setup. - Check `rsync` params for your use-case. Default params are not necessarily going to be enough for everyone, it highly depends on your setup.
- Check manually your rsync command from your client before opening a bug report. - Check manually your rsync command from your client before opening a bug report.
- `Deployment Failed, Permission denied (publickey,password)`: This issue occures in some cases, it is related to OS and ssh. This action can only provide a workaround:
- Use `SCRIPT_BEFORE` param, eg `SCRIPT_BEFORE: ls`. This will force `known_hosts` update, adding your host via `ssh-keyscan`.
- Or manually add public key to authorized_keys and add a new line to a private key.
I've added e2e test for this action. I've added e2e test for this action.
Real example is executed on every PR merge to `main`. Real example is executed on every PR merge to `main`.
Check actions tab for example. Check actions tab for example.
When opening an issue, please add example of your step with env vars. You can add dummy values.
More info for SSH keys: https://www.ssh.com/ssh/public-key-authentication More info for SSH keys: https://www.ssh.com/ssh/public-key-authentication
## Tips ## Tips
@@ -156,6 +173,7 @@ For complex use cases, use `ARGS` and `SSH_CMD_ARGS` to fully configure `rsync`
- If you need to use multiple steps, eg multi targets deployment, save shared ENV variables in `>> $GITHUB_ENV`. - If you need to use multiple steps, eg multi targets deployment, save shared ENV variables in `>> $GITHUB_ENV`.
Check .github/workflows/e2e.yml for an example Check .github/workflows/e2e.yml for an example
- For multi sources, use -R ARG to manipulate folders structure. - For multi sources, use -R ARG to manipulate folders structure.
- Great post about `rsync` options specific to usage of this action: https://logansnotes.com/2020/gh-action-site-deploy/
## Disclaimer ## Disclaimer

View File

@@ -22,11 +22,11 @@ inputs:
TARGET: TARGET:
description: "Target directory" description: "Target directory"
required: false required: false
default: "/home/REMOTE_USER/" default: ""
ARGS: ARGS:
description: "Arguments to pass to rsync" description: "Arguments to pass to rsync"
required: false required: false
default: "-rltgoDzvO" default: "-rlgoDzvc -i"
SSH_CMD_ARGS: SSH_CMD_ARGS:
description: "An array of ssh arguments, they must be prefixed with -o and separated by a comma, for example: -o SomeArgument=no, -o SomeOtherArgument=5 " description: "An array of ssh arguments, they must be prefixed with -o and separated by a comma, for example: -o SomeArgument=no, -o SomeOtherArgument=5 "
required: false required: false
@@ -39,15 +39,23 @@ inputs:
description: "Script to run on host machine before rsync" description: "Script to run on host machine before rsync"
required: false required: false
default: "" default: ""
SCRIPT_BEFORE_REQUIRED:
description: "If not an empty string, the action will fail if the before script fails. Note: The string 'false' will be treated as true"
required: false
default: ""
SCRIPT_AFTER: SCRIPT_AFTER:
description: "Script to run on host machine after rsync" description: "Script to run on host machine after rsync"
required: false required: false
default: "" default: ""
SCRIPT_AFTER_REQUIRED:
description: "If not an empty string, the action will fail if the after script fails. Note: The string 'false' will be treated as true"
required: false
default: ""
outputs: outputs:
status: status:
description: "Status" description: "Status"
runs: runs:
using: "node16" using: "node24"
main: "dist/index.js" main: "dist/index.js"
branding: branding:
color: "green" color: "green"

2
dist/index.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,248 @@
## [6.0.3](https://github.com/easingthemes/ssh-deploy/compare/v6.0.2...v6.0.3) (2026-04-02)
### Bug Fixes
* keep @semantic-release/github plugin for GitHub Releases ([0cffff4](https://github.com/easingthemes/ssh-deploy/commit/0cffff4878a082b939d7fa0db84034a64b498430))
* update major version tag as post-release step ([6306dda](https://github.com/easingthemes/ssh-deploy/commit/6306ddad7ccb78a18c3a18668fbb0b9b0adb911f))
## [6.0.2](https://github.com/easingthemes/ssh-deploy/compare/v6.0.1...v6.0.2) (2026-04-02)
### Bug Fixes
* add @semantic-release/github plugin to create GitHub Releases ([9e4918b](https://github.com/easingthemes/ssh-deploy/commit/9e4918b4e1c18dfdf7b93e70301baaefeb15bab3))
## [6.0.1](https://github.com/easingthemes/ssh-deploy/compare/v6.0.0...v6.0.1) (2026-04-02)
### Bug Fixes
* upgrade devDependencies and migrate to eslint 10 flat config ([c88faf5](https://github.com/easingthemes/ssh-deploy/commit/c88faf565603544c354d0d27ab6948a6d2048c40))
# [6.0.0](https://github.com/easingthemes/ssh-deploy/compare/v5.1.2...v6.0.0) (2026-04-02)
* feat!: replace rsyncwrapper with direct child_process.spawn ([b11fb7f](https://github.com/easingthemes/ssh-deploy/commit/b11fb7f9113ccfec263a5645d472d0351e4874da))
* feat!: replace rsyncwrapper with local rsync module ([71b8eb3](https://github.com/easingthemes/ssh-deploy/commit/71b8eb300f807e47a87dc96ace9e083d606c05e7))
### Bug Fixes
* add proc.on('error') handler to prevent hanging on spawn failure ([c81b43c](https://github.com/easingthemes/ssh-deploy/commit/c81b43c5bf3a389da4168d71e71ddf2f118c2939))
### BREAKING CHANGES
* rsyncwrapper dependency removed, rsync command is now
constructed and executed via a local module using child_process.spawn.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* rsyncwrapper dependency removed, rsync command is now
constructed and executed directly via child_process.spawn.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## [5.1.2](https://github.com/easingthemes/ssh-deploy/compare/v5.1.1...v5.1.2) (2026-04-02)
### Bug Fixes
* update Node.js runtime from 20 to 24 ([681efb5](https://github.com/easingthemes/ssh-deploy/commit/681efb59f1b7a4f41e72cf98a4e30f8860ab66f9)), closes [#207](https://github.com/easingthemes/ssh-deploy/issues/207)
## [5.1.1](https://github.com/easingthemes/ssh-deploy/compare/v5.1.0...v5.1.1) (2024-07-24)
### Bug Fixes
* Update README.md ([f007431](https://github.com/easingthemes/ssh-deploy/commit/f007431332cb2dae49153363ad22fb9f90f4aa75))
# [5.1.0](https://github.com/easingthemes/ssh-deploy/compare/v5.0.3...v5.1.0) (2024-07-24)
### Features
* Add deleteFile function to helpers module ([1befdb1](https://github.com/easingthemes/ssh-deploy/commit/1befdb1c6bf3282aa34e6caa431cb2da23d2b17d))
* apply deleteFile function to remoteCmd ([b82eced](https://github.com/easingthemes/ssh-deploy/commit/b82eced4571cb3f63369d51760a81820ffb1bc7f))
## [5.0.3](https://github.com/easingthemes/ssh-deploy/compare/v5.0.2...v5.0.3) (2024-02-27)
### Bug Fixes
* trigger automated release ([4d8bbf0](https://github.com/easingthemes/ssh-deploy/commit/4d8bbf0debaade9fb03b8dc3be3c020955557b12))
## [5.0.2](https://github.com/easingthemes/ssh-deploy/compare/v5.0.1...v5.0.2) (2024-02-18)
### Bug Fixes
* added the missing declarations [#177](https://github.com/easingthemes/ssh-deploy/issues/177) ([bb271fe](https://github.com/easingthemes/ssh-deploy/commit/bb271fe4c69eeeacb986a38cdb3347104143c61f))
* Fix default values used incorrectly. ([a1b383f](https://github.com/easingthemes/ssh-deploy/commit/a1b383f560a7f52a65da3670e61efe6e02f8639a))
## [5.0.1](https://github.com/easingthemes/ssh-deploy/compare/v5.0.0...v5.0.1) (2024-01-31)
### Bug Fixes
* Add info for Permission denied issue. ([845b578](https://github.com/easingthemes/ssh-deploy/commit/845b578606c0c5a956c70caf61e00a7d2b13ee37))
# [5.0.0](https://github.com/easingthemes/ssh-deploy/compare/v4.1.10...v5.0.0) (2023-12-12)
* Merge pull request #173 from jeromelachaud/main ([ac1908e](https://github.com/easingthemes/ssh-deploy/commit/ac1908e5d2dc749496fdbe8a918aa073e3357d85)), closes [#173](https://github.com/easingthemes/ssh-deploy/issues/173)
### BREAKING CHANGES
* update to use nodeJS v20
* update to use nodeJS v20
## [4.1.10](https://github.com/easingthemes/ssh-deploy/compare/v4.1.9...v4.1.10) (2023-09-30)
### Bug Fixes
* normalize line endings in SSH key for the underlying OS ([3f5d9aa](https://github.com/easingthemes/ssh-deploy/commit/3f5d9aab1a743bd426a4d132d07f1f5e9ed0310c))
## [4.1.9](https://github.com/easingthemes/ssh-deploy/compare/v4.1.8...v4.1.9) (2023-09-24)
### Bug Fixes
* add compiled file ([627ac29](https://github.com/easingthemes/ssh-deploy/commit/627ac29ece9dc2f1185a50d1002bc2c968fc973c))
* add uuid for ssh scripts ([66f6e4b](https://github.com/easingthemes/ssh-deploy/commit/66f6e4b367ea39479c285234797a4e86c90d9abd))
## [4.1.8](https://github.com/easingthemes/ssh-deploy/compare/v4.1.7...v4.1.8) (2023-02-21)
### Bug Fixes
* rebuild and update readme ([98025d6](https://github.com/easingthemes/ssh-deploy/commit/98025d680e96a5c6c805e377a1b81de2f626aa1e))
## [4.1.7](https://github.com/easingthemes/ssh-deploy/compare/v4.1.6...v4.1.7) (2023-02-21)
### Bug Fixes
* [#120](https://github.com/easingthemes/ssh-deploy/issues/120) check undefined data ([2fbb060](https://github.com/easingthemes/ssh-deploy/commit/2fbb06015d1a6ffd32e0100aaf1a1a46949e990e))
## [4.1.6](https://github.com/easingthemes/ssh-deploy/compare/v4.1.5...v4.1.6) (2023-02-21)
### Bug Fixes
* [#118](https://github.com/easingthemes/ssh-deploy/issues/118) check undefined default values rebuild ([54f8b6c](https://github.com/easingthemes/ssh-deploy/commit/54f8b6c60b8f2f926d5ed9538557e5521a905d87))
## [4.1.5](https://github.com/easingthemes/ssh-deploy/compare/v4.1.4...v4.1.5) (2023-02-21)
### Bug Fixes
* [#118](https://github.com/easingthemes/ssh-deploy/issues/118) check undefined default values ([f0c02fb](https://github.com/easingthemes/ssh-deploy/commit/f0c02fb2a5b3b69bb91004dd49d409eb6adfe7cd))
## [4.1.4](https://github.com/easingthemes/ssh-deploy/compare/v4.1.3...v4.1.4) (2023-02-21)
### Bug Fixes
* [#113](https://github.com/easingthemes/ssh-deploy/issues/113) limit ssh script input ([5894f5e](https://github.com/easingthemes/ssh-deploy/commit/5894f5e29008feccaf42787330ec8f49f3ad50b0))
## [4.1.3](https://github.com/easingthemes/ssh-deploy/compare/v4.1.2...v4.1.3) (2023-02-21)
### Bug Fixes
* [#113](https://github.com/easingthemes/ssh-deploy/issues/113) limit ssh script output - rebuild ([756a522](https://github.com/easingthemes/ssh-deploy/commit/756a522533d2206203b5d13b5aa11c88b3313784))
## [4.1.2](https://github.com/easingthemes/ssh-deploy/compare/v4.1.1...v4.1.2) (2023-02-21)
### Bug Fixes
* [#113](https://github.com/easingthemes/ssh-deploy/issues/113) limit ssh script output ([59827af](https://github.com/easingthemes/ssh-deploy/commit/59827af83c934996efda72f9fbd1fcd0bb9ccaac))
## [4.1.1](https://github.com/easingthemes/ssh-deploy/compare/v4.1.0...v4.1.1) (2023-02-21)
### Bug Fixes
* fix default TARGET ([4d08634](https://github.com/easingthemes/ssh-deploy/commit/4d086346af62ac5d57fa37ee6bb46f8de8ad48c3))
# [4.1.0](https://github.com/easingthemes/ssh-deploy/compare/v4.0.5...v4.1.0) (2023-02-19)
### Features
* add ssh port from VARs, fix package-lock ([808b002](https://github.com/easingthemes/ssh-deploy/commit/808b0020d44b7c25ef1c13b3979ffdab4f503236))
## [4.0.5](https://github.com/easingthemes/ssh-deploy/compare/v4.0.4...v4.0.5) (2023-01-06)
### Bug Fixes
* fix manual release action ([245b7a9](https://github.com/easingthemes/ssh-deploy/commit/245b7a9d2fe5272ee34608f86a612d643694c23b))
## [4.0.4](https://github.com/easingthemes/ssh-deploy/compare/v4.0.3...v4.0.4) (2023-01-03)
### Bug Fixes
* update sub dependencies ([2a32c8d](https://github.com/easingthemes/ssh-deploy/commit/2a32c8dcde2d64394a3577decdd9c902f37a30f8))
## [4.0.3](https://github.com/easingthemes/ssh-deploy/compare/v4.0.2...v4.0.3) (2023-01-03)
### Bug Fixes
* update v3 e2e test ([450bf42](https://github.com/easingthemes/ssh-deploy/commit/450bf423f388777bde052ad7b5bc24eca392434d))
## [4.0.2](https://github.com/easingthemes/ssh-deploy/compare/v4.0.1...v4.0.2) (2023-01-03)
### Bug Fixes
* add githubWorkspace as default source root ([3ef66d0](https://github.com/easingthemes/ssh-deploy/commit/3ef66d0be999ee45434505e8bedea4f8b5b5a909))
## [4.0.1](https://github.com/easingthemes/ssh-deploy/compare/v4.0.0...v4.0.1) (2023-01-03)
### Bug Fixes
* fix default source if empty ([9f191f4](https://github.com/easingthemes/ssh-deploy/commit/9f191f42633c4a0f66054f0fc229c9e30a08f00c))
# [4.0.0](https://github.com/easingthemes/ssh-deploy/compare/v3.4.3...v4.0.0) (2023-01-03)
### Bug Fixes
* rebuild ([2169399](https://github.com/easingthemes/ssh-deploy/commit/2169399fef9a60a2fea1ab03cce4ec8c2371e5c2))
### Performance Improvements
* update default rsync options ([2be7efb](https://github.com/easingthemes/ssh-deploy/commit/2be7efb376866327c1d1209f51eb43f34f07b354))
### BREAKING CHANGES
* Default rsync options updated to speed up default deployments.
from `rltgoDzvO` to `-rlgoDzvc -i`
## [3.4.3](https://github.com/easingthemes/ssh-deploy/compare/v3.4.2...v3.4.3) (2023-01-03)
### Bug Fixes
* move e2e tests typo branch name ([6d3554b](https://github.com/easingthemes/ssh-deploy/commit/6d3554b01e9a05de9a9d2b30274bee411a4986ed))
## [3.4.2](https://github.com/easingthemes/ssh-deploy/compare/v3.4.1...v3.4.2) (2023-01-03)
### Bug Fixes
* Update changelog ([765f5ff](https://github.com/easingthemes/ssh-deploy/commit/765f5ffd3153c76442521c61c04656cafc182731))
## [3.4.1](https://github.com/easingthemes/ssh-deploy/compare/v3.4.0...v3.4.1) (2023-01-03) ## [3.4.1](https://github.com/easingthemes/ssh-deploy/compare/v3.4.0...v3.4.1) (2023-01-03)
@@ -8,14 +253,20 @@
# [3.4.0](https://github.com/easingthemes/ssh-deploy/compare/v3.3.4...v3.4.0) (2023-01-03) # [3.4.0](https://github.com/easingthemes/ssh-deploy/compare/v3.3.4...v3.4.0) (2023-01-03)
### Bug Fixes **Full Changelog**: https://github.com/easingthemes/ssh-deploy/compare/v3.1.0...v3.4.1
* yaml step name ([5c13615](https://github.com/easingthemes/ssh-deploy/commit/5c13615d4b7b0bda47f622ac5f4444484d8bcdb4))
### Features ### Features
* Add SSH remote script support - before and after rsync ([2cd8a82](https://github.com/easingthemes/ssh-deploy/commit/2cd8a820e22135b7002fbe6a47cf33f99e2d337b))
* Add multi source and multi target support ([73a65ec](https://github.com/easingthemes/ssh-deploy/commit/73a65ec97c5046a53f6b4c40823be5fd3826ede0)) * Add multi source and multi target support ([73a65ec](https://github.com/easingthemes/ssh-deploy/commit/73a65ec97c5046a53f6b4c40823be5fd3826ede0))
* Add SSH_CMD_ARGS support ([51a0063](https://github.com/easingthemes/ssh-deploy/commit/51a00631e2b91983fb610ca2157a673b9ae03c95))
* Add manual inputs for e2e test ([8f71595](https://github.com/easingthemes/ssh-deploy/commit/8f715957ab9283ab2934dd1e5be9d78f2eaf3fae))
### Bug Fixes
* Add visible Rsync CMD for debugging ([91b6d28](https://github.com/easingthemes/ssh-deploy/commit/91b6d280aee6a7ae666a11426fb356406f4a25a5))
* log buffer from rsync stdout ([8e19e0d](https://github.com/easingthemes/ssh-deploy/commit/8e19e0d6bc9b1c332925ce0268ad64b50728fae5))
* fix e2e yaml step name ([5c13615](https://github.com/easingthemes/ssh-deploy/commit/5c13615d4b7b0bda47f622ac5f4444484d8bcdb4))
## [3.3.4](https://github.com/easingthemes/ssh-deploy/compare/v3.3.3...v3.3.4) (2023-01-02) ## [3.3.4](https://github.com/easingthemes/ssh-deploy/compare/v3.3.3...v3.3.4) (2023-01-02)

52
eslint.config.js Normal file
View File

@@ -0,0 +1,52 @@
const js = require('@eslint/js');
const stylistic = require('@stylistic/eslint-plugin');
const globals = require('globals');
module.exports = [
js.configs.recommended,
{
plugins: {
'@stylistic': stylistic
},
languageOptions: {
ecmaVersion: 2020,
sourceType: 'commonjs',
globals: {
...globals.node,
...globals.commonjs,
...globals.es2020,
Atomics: 'readonly',
SharedArrayBuffer: 'readonly'
}
},
rules: {
// Stylistic rules (migrated from airbnb-base)
'@stylistic/comma-dangle': ['error', 'never'],
'@stylistic/indent': ['error', 2, { SwitchCase: 1 }],
'@stylistic/semi': ['error', 'always'],
'@stylistic/quotes': ['error', 'single', { avoidEscape: true }],
'@stylistic/arrow-parens': ['error', 'always'],
'@stylistic/brace-style': ['error', '1tbs', { allowSingleLine: true }],
'@stylistic/comma-spacing': ['error', { before: false, after: true }],
'@stylistic/key-spacing': ['error', { beforeColon: false, afterColon: true }],
'@stylistic/keyword-spacing': ['error', { before: true, after: true }],
'@stylistic/eol-last': ['error', 'always'],
'@stylistic/no-trailing-spaces': 'error',
'@stylistic/space-before-blocks': 'error',
'@stylistic/space-infix-ops': 'error',
'@stylistic/arrow-spacing': ['error', { before: true, after: true }],
// JS rules (migrated from airbnb-base)
'no-console': 'off',
'no-var': 'error',
'prefer-const': 'error',
'prefer-arrow-callback': 'error',
'prefer-template': 'error',
'object-shorthand': ['error', 'always'],
'no-shadow': 'error',
'no-use-before-define': ['error', { functions: true, classes: true, variables: true }],
'camelcase': ['error', { properties: 'never' }],
'no-unused-vars': ['error', { vars: 'all', args: 'after-used', ignoreRestSiblings: true }]
}
}
];

3188
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "@draganfilipovic/ssh-deploy", "name": "@draganfilipovic/ssh-deploy",
"version": "3.4.1", "version": "6.0.3",
"description": "Fast NodeJS action to deploy specific directory from `GITHUB_WORKSPACE` to a server via rsync over ssh.", "description": "Fast NodeJS action to deploy specific directory from `GITHUB_WORKSPACE` to a server via rsync over ssh.",
"main": "dist/index.js", "main": "dist/index.js",
"files": [ "files": [
@@ -29,13 +29,11 @@
"url": "https://github.com/easingthemes/ssh-deploy/issues" "url": "https://github.com/easingthemes/ssh-deploy/issues"
}, },
"homepage": "https://github.com/easingthemes/ssh-deploy#readme", "homepage": "https://github.com/easingthemes/ssh-deploy#readme",
"dependencies": {
"rsyncwrapper": "^3.0.1"
},
"devDependencies": { "devDependencies": {
"@vercel/ncc": "^0.36.0", "@eslint/js": "^10.0.1",
"eslint": "^8.30.0", "@stylistic/eslint-plugin": "^5.10.0",
"eslint-config-airbnb-base": "^15.0.0", "@vercel/ncc": "^0.38.4",
"eslint-plugin-import": "^2.26.0" "eslint": "^10.1.0",
"globals": "^17.4.0"
} }
} }

View File

@@ -1,4 +1,4 @@
const { existsSync, mkdirSync, writeFileSync } = require('fs'); const { existsSync, mkdirSync, writeFileSync, unlink } = require('fs');
const { join } = require('path'); const { join } = require('path');
const validateDir = (dir) => { const validateDir = (dir) => {
@@ -45,6 +45,29 @@ const writeToFile = ({ dir, filename, content, isRequired, mode = '0644' }) => {
} }
}; };
const deleteFile = ({ dir, filename, isRequired }) => {
validateDir(dir);
const filePath = join(dir, filename);
if (existsSync(filePath)) {
const message = `⚠️ [FILE] ${filePath} Required file exist.`;
handleError(message, isRequired);
return;
}
try {
console.log(`[FILE] Deleting ${filePath} file ...`);
unlink(filePath, (error) => {
if (error) {
throw new Error(error);
}
});
} catch (error) {
const message = `⚠️[FILE] Deleting file error. filePath: ${filePath}, message: ${error.message}`;
handleError(message, isRequired);
}
};
const validateRequiredInputs = (inputs) => { const validateRequiredInputs = (inputs) => {
const inputKeys = Object.keys(inputs); const inputKeys = Object.keys(inputs);
const validInputs = inputKeys.filter((inputKey) => { const validInputs = inputKeys.filter((inputKey) => {
@@ -66,6 +89,7 @@ const snakeToCamel = (str) => str.replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.t
module.exports = { module.exports = {
writeToFile, writeToFile,
deleteFile,
validateRequiredInputs, validateRequiredInputs,
snakeToCamel snakeToCamel
}; };

View File

@@ -10,7 +10,8 @@ const run = async () => {
source, remoteUser, remoteHost, remotePort, source, remoteUser, remoteHost, remotePort,
deployKeyName, sshPrivateKey, deployKeyName, sshPrivateKey,
args, exclude, sshCmdArgs, args, exclude, sshCmdArgs,
scriptBefore, scriptAfter, scriptBefore, scriptBeforeRequired,
scriptAfter, scriptAfterRequired,
rsyncServer rsyncServer
} = inputs; } = inputs;
// Validate required inputs // Validate required inputs
@@ -20,20 +21,19 @@ const run = async () => {
const { path: privateKeyPath } = getPrivateKeyPath(deployKeyName); const { path: privateKeyPath } = getPrivateKeyPath(deployKeyName);
// Update known hosts if ssh command is present to avoid prompt // Update known hosts if ssh command is present to avoid prompt
if (scriptBefore || scriptAfter) { if (scriptBefore || scriptAfter) {
updateKnownHosts(remoteHost); updateKnownHosts(remoteHost, remotePort);
} }
// Check Script before // Check Script before
if (scriptBefore) { if (scriptBefore) {
await remoteCmdBefore(scriptBefore, privateKeyPath); await remoteCmdBefore(scriptBefore, privateKeyPath, scriptBeforeRequired);
} }
/* eslint-disable object-property-newline */
await sshDeploy({ await sshDeploy({
source, rsyncServer, exclude, remotePort, source, rsyncServer, exclude, remotePort,
privateKeyPath, args, sshCmdArgs privateKeyPath, args, sshCmdArgs
}); });
// Check script after // Check script after
if (scriptAfter) { if (scriptAfter) {
await remoteCmdAfter(scriptAfter, privateKeyPath); await remoteCmdAfter(scriptAfter, privateKeyPath, scriptAfterRequired);
} }
}; };

View File

@@ -4,16 +4,16 @@ const inputNames = [
'REMOTE_HOST', 'REMOTE_USER', 'REMOTE_PORT', 'REMOTE_HOST', 'REMOTE_USER', 'REMOTE_PORT',
'SSH_PRIVATE_KEY', 'DEPLOY_KEY_NAME', 'SSH_PRIVATE_KEY', 'DEPLOY_KEY_NAME',
'SOURCE', 'TARGET', 'ARGS', 'SSH_CMD_ARGS', 'EXCLUDE', 'SOURCE', 'TARGET', 'ARGS', 'SSH_CMD_ARGS', 'EXCLUDE',
'SCRIPT_BEFORE', 'SCRIPT_AFTER']; 'SCRIPT_BEFORE', 'SCRIPT_AFTER', 'SCRIPT_BEFORE_REQUIRED', 'SCRIPT_AFTER_REQUIRED'];
const githubWorkspace = process.env.GITHUB_WORKSPACE; const githubWorkspace = process.env.GITHUB_WORKSPACE;
const remoteUser = process.env.REMOTE_USER; const remoteUser = process.env.REMOTE_USER || process.env.INPUT_REMOTE_USER;
const defaultInputs = { const defaultInputs = {
source: './', source: '',
target: `/home/${remoteUser}/`, target: `/home/${remoteUser}/`,
exclude: '', exclude: '',
args: '-rltgoDzvO', args: '-rlgoDzvc -i',
sshCmdArgs: '-o StrictHostKeyChecking=no', sshCmdArgs: '-o StrictHostKeyChecking=no',
deployKeyName: `deploy_key_${remoteUser}_${Date.now()}` deployKeyName: `deploy_key_${remoteUser}_${Date.now()}`
}; };
@@ -24,13 +24,12 @@ const inputs = {
inputNames.forEach((input) => { inputNames.forEach((input) => {
const inputName = snakeToCamel(input.toLowerCase()); const inputName = snakeToCamel(input.toLowerCase());
const inputVal = process.env[input] || process.env[`INPUT_${input}`]; const inputVal = process.env[input] || process.env[`INPUT_${input}`] || defaultInputs[inputName];
const validVal = inputVal === undefined ? defaultInputs[inputName] : inputVal; const validVal = inputVal === undefined ? defaultInputs[inputName] : inputVal;
let extendedVal = validVal; let extendedVal = validVal;
// eslint-disable-next-line default-case
switch (inputName) { switch (inputName) {
case 'source': case 'source':
extendedVal = validVal.indexOf(' ') > -1 ? validVal.split(' ') : validVal; extendedVal = validVal.split(' ').map((src) => `${githubWorkspace}/${src}`);
break; break;
case 'args': case 'args':
extendedVal = validVal.split(' '); extendedVal = validVal.split(' ');

View File

@@ -1,6 +1,7 @@
const { exec } = require('child_process'); const { exec } = require('child_process');
const { sshServer, githubWorkspace } = require('./inputs'); const crypto = require('crypto');
const { writeToFile } = require('./helpers'); const { sshServer, githubWorkspace, remotePort } = require('./inputs');
const { writeToFile, deleteFile } = require('./helpers');
const handleError = (message, isRequired, callback) => { const handleError = (message, isRequired, callback) => {
if (isRequired) { if (isRequired) {
@@ -10,22 +11,27 @@ const handleError = (message, isRequired, callback) => {
} }
}; };
// eslint-disable-next-line max-len
const remoteCmd = async (content, privateKeyPath, isRequired, label) => new Promise((resolve, reject) => { const remoteCmd = async (content, privateKeyPath, isRequired, label) => new Promise((resolve, reject) => {
const filename = `local_ssh_script-${label}.sh`; const uuid = crypto.randomUUID();
const filename = `local_ssh_script-${label}-${uuid}.sh`;
try { try {
writeToFile({ dir: githubWorkspace, filename, content }); writeToFile({ dir: githubWorkspace, filename, content });
const dataLimit = 10000;
const rsyncStdout = (process.env.RSYNC_STDOUT || '').substring(0, dataLimit);
console.log(`Executing remote script: ssh -i ${privateKeyPath} ${sshServer}`); console.log(`Executing remote script: ssh -i ${privateKeyPath} ${sshServer}`);
exec( exec(
`DEBIAN_FRONTEND=noninteractive ssh -i ${privateKeyPath} -o StrictHostKeyChecking=no ${sshServer} 'RSYNC_STDOUT="${process.env.RSYNC_STDOUT}" bash -s' < ${filename}`, `DEBIAN_FRONTEND=noninteractive ssh -p ${(remotePort || 22)} -i ${privateKeyPath} -o StrictHostKeyChecking=no ${sshServer} 'RSYNC_STDOUT="${rsyncStdout}" bash -s' < ${filename}`,
(err, data, stderr) => { (err, data = '', stderr = '') => {
if (err) { if (err) {
const message = `⚠️ [CMD] Remote script failed: ${err.message}`; const message = `⚠️ [CMD] Remote script failed: ${err.message}`;
console.warn(`${message} \n`, data, stderr); console.warn(`${message} \n`, data, stderr);
handleError(message, isRequired, reject); handleError(message, isRequired, reject);
} else { } else {
console.log('✅ [CMD] Remote script executed. \n', data, stderr); const limited = data.substring(0, dataLimit);
resolve(data); console.log('✅ [CMD] Remote script executed. \n', limited, stderr);
deleteFile({ dir: githubWorkspace, filename });
console.log('✅ [FILE] Script file deleted.');
resolve(limited);
} }
} }
); );

56
src/rsync.js Normal file
View File

@@ -0,0 +1,56 @@
const { spawn } = require('child_process');
const escapeSpaces = (str) => (typeof str === 'string' ? str.replace(/\b\s/g, '\\ ') : str);
const buildRsyncCommand = ({ src, dest, excludeFirst, port, privateKey, args, sshCmdArgs }) => {
const cmdParts = [];
const sources = Array.isArray(src) ? src : [src];
cmdParts.push(...sources.map(escapeSpaces));
cmdParts.push(escapeSpaces(dest));
let sshCmd = `ssh -p ${port || 22} -i ${privateKey}`;
if (sshCmdArgs && sshCmdArgs.length > 0) {
sshCmd += ` ${sshCmdArgs.join(' ')}`;
}
cmdParts.push('--rsh', `"${sshCmd}"`);
cmdParts.push('--recursive');
if (Array.isArray(excludeFirst)) {
excludeFirst.forEach((pattern) => {
if (pattern) cmdParts.push(`--exclude=${escapeSpaces(pattern)}`);
});
}
if (Array.isArray(args)) {
cmdParts.push(...args);
}
return `rsync ${[...new Set(cmdParts)].join(' ')}`;
};
module.exports = (options, callback) => {
const cmd = buildRsyncCommand(options);
const noop = () => {};
const onStdout = options.onStdout || noop;
const onStderr = options.onStderr || noop;
let stdout = '';
let stderr = '';
const proc = spawn('/bin/sh', ['-c', cmd]);
proc.stdout.on('data', (data) => { onStdout(data); stdout += data; });
proc.stderr.on('data', (data) => { onStderr(data); stderr += data; });
proc.on('exit', (code) => {
let error = null;
if (code !== 0) {
error = new Error(`rsync exited with code ${code}`);
error.code = code;
}
callback(error, stdout, stderr, cmd);
});
proc.on('error', (err) => callback(err, stdout, stderr, cmd));
};

View File

@@ -1,5 +1,5 @@
const { execSync } = require('child_process'); const { execSync } = require('child_process');
const nodeRsync = require('rsyncwrapper'); const nodeRsync = require('./rsync');
const nodeRsyncPromise = async (config) => new Promise((resolve, reject) => { const nodeRsyncPromise = async (config) => new Promise((resolve, reject) => {
const logCMD = (cmd) => { const logCMD = (cmd) => {
@@ -46,7 +46,7 @@ const validateRsync = async () => {
execSync('sudo DEBIAN_FRONTEND=noninteractive apt-get -y update && sudo DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -y install rsync', { stdio: 'inherit' }); execSync('sudo DEBIAN_FRONTEND=noninteractive apt-get -y update && sudo DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -y install rsync', { stdio: 'inherit' });
console.log('✅ [CLI] Rsync installed. \n'); console.log('✅ [CLI] Rsync installed. \n');
} catch (error) { } catch (error) {
throw new Error(`⚠️ [CLI] Rsync installation failed. Aborting ... error: ${error.message}`); throw new Error(`⚠️ [CLI] Rsync installation failed. Aborting ... error: ${error.message}`, { cause: error });
} }
}; };
@@ -65,7 +65,6 @@ const rsyncCli = async ({
}; };
// RSYNC COMMAND // RSYNC COMMAND
/* eslint-disable object-property-newline */
return nodeRsyncPromise({ return nodeRsyncPromise({
...defaultOptions, ...defaultOptions,
src: source, dest: rsyncServer, excludeFirst: exclude, port: remotePort, src: source, dest: rsyncServer, excludeFirst: exclude, port: remotePort,

View File

@@ -1,5 +1,6 @@
const { join } = require('path'); const { join } = require('path');
const { execSync } = require('child_process'); const { execSync } = require('child_process');
const { EOL } = require('os');
const { writeToFile } = require('./helpers'); const { writeToFile } = require('./helpers');
const KNOWN_HOSTS = 'known_hosts'; const KNOWN_HOSTS = 'known_hosts';
@@ -19,15 +20,15 @@ const addSshKey = (content, deployKeyName) => {
const { dir, filename } = getPrivateKeyPath(deployKeyName); const { dir, filename } = getPrivateKeyPath(deployKeyName);
writeToFile({ dir, filename: KNOWN_HOSTS, content: '' }); writeToFile({ dir, filename: KNOWN_HOSTS, content: '' });
console.log('✅ [SSH] known_hosts file ensured', dir); console.log('✅ [SSH] known_hosts file ensured', dir);
writeToFile({ dir, filename, content, isRequired: true, mode: '0400' }); writeToFile({ dir, filename, content: `${content}${EOL}`, isRequired: true, mode: '0400' });
console.log('✅ [SSH] key added to `.ssh` dir ', dir, filename); console.log('✅ [SSH] key added to `.ssh` dir ', dir, filename);
}; };
const updateKnownHosts = (host) => { const updateKnownHosts = (host, remotePort) => {
const { knownHostsPath } = getPrivateKeyPath(); const { knownHostsPath } = getPrivateKeyPath();
console.log('[SSH] Adding host to `known_hosts` ....', host, knownHostsPath); console.log('[SSH] Adding host to `known_hosts` ....', host, knownHostsPath);
try { try {
execSync(`ssh-keyscan -H ${host} >> ${knownHostsPath}`, { execSync(`ssh-keyscan -p ${(remotePort || 22)} -H ${host} >> ${knownHostsPath}`, {
stdio: 'inherit' stdio: 'inherit'
}); });
} catch (error) { } catch (error) {