diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cace0c9..e7e594e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,13 +14,13 @@ jobs: strategy: matrix: os: [ubuntu-latest] - node-version: [20.x] + node-version: [16.x] steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v3 - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - name: Install dependencies diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 6c93953..781156d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -31,11 +31,11 @@ jobs: language: [ 'javascript' ] steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v3 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} @@ -44,4 +44,4 @@ jobs: npm run build --if-present - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/e2e-manual.yml b/.github/workflows/e2e-manual.yml deleted file mode 100644 index 11fb9f6..0000000 --- a/.github/workflows/e2e-manual.yml +++ /dev/null @@ -1,104 +0,0 @@ -name: e2e Manual Test - -on: - workflow_dispatch: - inputs: - ARGS: - description: 'ARGS' - required: true - default: '-rlgoDzvc -i --delete --chmod=ugo+rwX --progress' - EXCLUDE: - description: 'EXCLUDE' - required: true - default: 'skip_dir/, /node_modules/' - SSH_CMD_ARGS: - description: 'SSH_CMD_ARGS' - required: true - default: '-o StrictHostKeyChecking=no, -o UserKnownHostsFile=/dev/null' - - -env: - TEST_HOST_DOCKER: ./test - TEST_USER: test - -jobs: - e2e-manual: - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v4 - -# ---------------------------------------------------------------- -# 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<> $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<> $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 - uses: easingthemes/ssh-deploy@main - env: - # ENV Vars created in previous steps: - # SSH_PRIVATE_KEY: $EXAMPLE_SSH_PRIVATE_KEY - # REMOTE_HOST: $EXAMPLE_REMOTE_HOST - REMOTE_USER: ${{ env.TEST_USER }} - ARGS: ${{ github.event.inputs.ARGS }} - SSH_CMD_ARGS: ${{ github.event.inputs.SSH_CMD_ARGS }} - SOURCE: test_project/ test_project2/ - TARGET: /var/www/html/ - EXCLUDE: ${{ github.event.inputs.EXCLUDE }} - SCRIPT_BEFORE: | - whoami - ls -lR /var/www/html/ - SCRIPT_AFTER: | - ls -lR /var/www/html/ - echo $RSYNC_STDOUT diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 09bf162..5d440d5 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -3,11 +3,25 @@ name: e2e Test on: push: branches: [ 'main' ] + workflow_dispatch: + inputs: + ARGS: + description: 'ARGS' + required: true + default: '-rltgoDzvO --delete --chmod=ugo=rwX --progress' + EXCLUDE: + description: 'EXCLUDE' + required: true + default: 'skip_dir/, /node_modules/' + SSH_CMD_ARGS: + description: 'SSH_CMD_ARGS' + required: true + default: '-o StrictHostKeyChecking=no, -o UserKnownHostsFile=/dev/null' + env: TEST_HOST_DOCKER: ./test TEST_USER: test - TEST_USER2: test2 jobs: e2e: @@ -15,17 +29,13 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v3 -# : --------------------------------------------------------------- -# : START E2E Test Specific - steps -# : ---------------------------------------------------------------- - - - name: E2E Test Specific - Clean up old test files + - name: 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 + - name: Create ssh keys run: | echo $HOME ls -la $HOME @@ -37,12 +47,13 @@ jobs: cat $HOME/.ssh/id_rsa >> $GITHUB_ENV echo "EOF" >> $GITHUB_ENV - - name: E2E Test Specific - Build Host Server Image + - name: 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)" + --build-arg SSH_PUB_KEY="$(cat $HOME/.ssh/id_rsa.pub)" \ + --build-arg ssh_user="${{ env.TEST_USER }}" 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<> $GITHUB_ENV @@ -50,11 +61,8 @@ jobs: echo "EOF" >> $GITHUB_ENV shell: bash - - name: E2E Test Specific - Create project file + - name: 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 @@ -65,115 +73,24 @@ jobs: truncate -s 5MB text_in_skip_dir.txt cd ../ cat index.html - echo "test_project:" && ls -lR - echo "skip_dir:" && ls -lR skip_dir + echo "test_project: \n" && ls -l + echo "skip_dir: \n" && ls -l skip_dir -# ---------------------------------------------------------------- -# END E2E Test Specific - steps -# ---------------------------------------------------------------- - - - name: set shared ENV variables for multi target deployment - run: | - 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 "SOURCE=test_project/ test_project2/" >> $GITHUB_ENV - echo "EXCLUDE=skip_dir/, /node_modules/" >> $GITHUB_ENV - echo "SCRIPT_BEFORE<> $GITHUB_ENV - echo "whoami" >> $GITHUB_ENV - echo "ls -lR /var/www/html/" >> $GITHUB_ENV - echo "EOF" >> $GITHUB_ENV - echo "SCRIPT_AFTER<> $GITHUB_ENV - echo $RSYNC_STDOUT >> $GITHUB_ENV - echo "ls -lR /var/www/html/" >> $GITHUB_ENV - echo "EOF" >> $GITHUB_ENV - - - name: e2e Test ssh-deploy action - Target 1 + - name: e2e Test published ssh-deploy action uses: easingthemes/ssh-deploy@main env: - # Shared ENV Vars created in previous steps + # ENV Vars created in previous steps: + # SSH_PRIVATE_KEY: $EXAMPLE_SSH_PRIVATE_KEY + # REMOTE_HOST: $EXAMPLE_REMOTE_HOST REMOTE_USER: ${{ env.TEST_USER }} - TARGET: /var/www/html/${{ env.TEST_USER }} - - - name: e2e Test ssh-deploy action - Target 2 - uses: easingthemes/ssh-deploy@main - env: - # Shared ENV Vars created in previous steps - REMOTE_USER: ${{ 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@v4 - - # : --------------------------------------------------------------- - # : 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<> $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<> $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 + ARGS: ${{ github.event.inputs.ARGS || '-rltgoDzvO --delete --chmod=ugo=rwX --progress' }} + SSH_CMD_ARGS: ${{ github.event.inputs.SSH_CMD_ARGS || '-o StrictHostKeyChecking=no, -o UserKnownHostsFile=/dev/null' }} + SOURCE: "test_project/" + TARGET: "/var/www/html/" + EXCLUDE: ${{ github.event.inputs.EXCLUDE || 'skip_dir/, /node_modules/' }} + SCRIPT_BEFORE: | + whoami + ls -al /var/www/html/ + SCRIPT_AFTER: | + ls -al /var/www/html/ + echo $RSYNC_STDOUT diff --git a/.github/workflows/manual-release.yml b/.github/workflows/manual-release.yml index 6545a29..e4040ad 100644 --- a/.github/workflows/manual-release.yml +++ b/.github/workflows/manual-release.yml @@ -2,71 +2,43 @@ name: Manual Release on: workflow_dispatch: inputs: - version: - description: 'Version' - type: choice + dryrun: + description: 'DryRUn' required: true - default: fix - options: - - fix - - feat - dryRun: - description: 'DryRun' - type: boolean - default: true -# ENV and Config -env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - GIT_AUTHOR_NAME: github-actions - GIT_AUTHOR_EMAIL: github-actions@github.com - GIT_COMMITTER_NAME: github-actions - GIT_COMMITTER_EMAIL: github-actions@github.com - CI: true - CONFIG_NODE_VERSION: '["lts/*"]' - CONFIG_OS: '["ubuntu-latest"]' -# Main Job + default: 'false' jobs: - config: - runs-on: ubuntu-latest - outputs: - NODE_VERSION: ${{ steps.set-config.outputs.CONFIG_NODE_VERSION }} - OS: ${{ steps.set-config.outputs.CONFIG_OS }} - steps: - - id: set-config - run: | - echo "CONFIG_NODE_VERSION=${{ toJSON(env.CONFIG_NODE_VERSION) }}" >> $GITHUB_OUTPUT - echo "CONFIG_OS=${{ toJSON(env.CONFIG_OS) }}" >> $GITHUB_OUTPUT - release-manual: - name: Test, Build and force Release - needs: config - - runs-on: ${{ matrix.OS }} + release: + name: Test, Build and Release + runs-on: ${{ matrix.os }} strategy: matrix: - OS: ${{ fromJSON(needs.config.outputs.OS) }} - NODE_VERSION: ${{ fromJSON(needs.config.outputs.NODE_VERSION) }} - + os: [ ubuntu-latest ] + node-version: [ 16.x ] steps: - - name: Checkout repo - uses: actions/checkout@v4 - - name: Setup Node.js ${{ matrix.NODE_VERSION }} - uses: actions/setup-node@v4 + - name: Checkout + uses: actions/checkout@v3 + - name: Setup Node.js + uses: actions/setup-node@v3 with: - node-version: ${{ matrix.NODE_VERSION }} - - name: Commit trigger - run: | - git commit --allow-empty -m "${{ github.event.inputs.version }}: Trigger Manual Release" + node-version: ${{ matrix['node-version'] }} - name: Install dependencies run: npm ci - name: Build Library run: npm run build --if-present - name: Run Tests run: npm test --if-present - - name: Create a release - ${{ github.event.inputs.version }} - uses: cycjimmy/semantic-release-action@v4 + - name: Release + uses: cycjimmy/semantic-release-action@v3 with: - dry_run: ${{ github.event.inputs.dryRun == 'true' }} + dry_run: ${{ github.event.inputs.dryrun == 'true' }} extra_plugins: | @semantic-release/changelog @semantic-release/git + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + GIT_AUTHOR_NAME: github-actions + GIT_AUTHOR_EMAIL: github-actions@github.com + GIT_COMMITTER_NAME: github-actions + GIT_COMMITTER_EMAIL: github-actions@github.com + CI: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0999d40..b658860 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,13 +12,13 @@ jobs: strategy: matrix: os: [ ubuntu-latest ] - node-version: [ 20.x ] + node-version: [ 16.x ] steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v3 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v3 with: node-version: ${{ matrix['node-version'] }} - name: Install dependencies @@ -28,7 +28,7 @@ jobs: - name: Run Tests run: npm test --if-present - name: Release - uses: cycjimmy/semantic-release-action@v4 + uses: cycjimmy/semantic-release-action@v3 with: dry_run: false extra_plugins: | diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 43ecafd..0a768d3 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -17,10 +17,10 @@ jobs: issues: write steps: - - uses: actions/stale@v9 + - uses: actions/stale@v7 with: 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.' - days-before-stale: 90 - days-before-close: 15 + days-before-stale: 30 + days-before-close: 5 stale-issue-label: 'stale' diff --git a/README.md b/README.md index a52946a..f4cc8fe 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,6 @@ The keys should be generated using the PEM format. You can use this command ``` 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] @@ -43,14 +41,13 @@ eg: myusername eg: '59184' -##### 5. `ARGS` (optional, default '-rlgoDzvc -i') +##### 5. `ARGS` (optional, default '-rltgoDzvO') For any initial/required rsync flags, eg: `-avzr --delete` ##### 6. `SOURCE` (optional, default '') -The source directory, path relative to `$GITHUB_WORKSPACE` root, eg: `dist/`. -Multiple sources should be separated by space. +The source directory, path relative to `$GITHUB_WORKSPACE` root, eg: `dist/` ##### 7. `TARGET` (optional, default '/home/REMOTE_USER/') @@ -64,38 +61,28 @@ path to exclude separated by `,`, ie: `/dist/, /node_modules/` 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` -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_BEFORE_REQUIRED` (optional, default false) - -If set to `true`, Job will fail if SCRIPT_BEFORE fails. - -##### 11. `SCRIPT_AFTER` (optional, default '') +##### 10. `SCRIPT_AFTER` (optional, default '') Script to run on host machine after rsync. Rsync output is stored in `$RSYNC_STDOUT` env variable. -##### 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') +##### 11. `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 # Usage -Use the latest version from Marketplace,eg: ssh-deploy@v5.1.0 +Use the latest version from Marketplace,eg: ssh-deploy@v2 or use the latest version from a branch, eg: ssh-deploy@main ``` - name: Deploy to Staging server uses: easingthemes/ssh-deploy@main - with: + env: SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} - ARGS: "-rlgoDzvc -i" + ARGS: "-rltgoDzvO" SOURCE: "dist/" REMOTE_HOST: ${{ secrets.REMOTE_HOST }} REMOTE_USER: ${{ secrets.REMOTE_USER }} @@ -123,20 +110,20 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v1 - name: Install Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v1 with: - node-version: '16.x' + node-version: '10.x' - name: Install npm dependencies run: npm install - name: Run build task run: npm run build --if-present - name: Deploy to Server uses: easingthemes/ssh-deploy@main - with: + env: SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} - ARGS: "-rlgoDzvc -i --delete" + ARGS: "-rltgoDzvO --delete" SOURCE: "dist/" REMOTE_HOST: ${{ secrets.REMOTE_HOST }} REMOTE_USER: ${{ secrets.REMOTE_USER }} @@ -152,29 +139,15 @@ Almost 95% of the issues are related to wrong SSH connection or `rsync` params a These issues are not related to the action itself. - Check manually your ssh connection from your client before opening a bug report. -- 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 `rsync` params for your use-case. Default params are not going to be enough wor everyone, it highly depends on your setup. - 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. Real example is executed on every PR merge to `main`. 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 -## Tips - -- Optional ENV variables are created for simple requirements. -For complex use cases, use `ARGS` and `SSH_CMD_ARGS` to fully configure `rsync` with all possible options. -- 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 -- 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 diff --git a/action.yml b/action.yml index 1c30b61..f26e459 100644 --- a/action.yml +++ b/action.yml @@ -22,11 +22,11 @@ inputs: TARGET: description: "Target directory" required: false - default: "" + default: "/home/REMOTE_USER/" ARGS: description: "Arguments to pass to rsync" required: false - default: "-rlgoDzvc -i" + default: "-rltgoDzvO" 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 " required: false @@ -39,23 +39,15 @@ inputs: description: "Script to run on host machine before rsync" required: false 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: description: "Script to run on host machine after rsync" required: false 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: status: description: "Status" runs: - using: "node20" + using: "node16" main: "dist/index.js" branding: color: "green" diff --git a/dist/index.js b/dist/index.js index b0a43df..e499357 100755 --- a/dist/index.js +++ b/dist/index.js @@ -1,2 +1,2 @@ #!/usr/bin/env node -(()=>{var e={898:(e,s,r)=>{"use strict";var o=r(81).spawn;var t=r(837);var escapeSpaces=function(e){if(typeof e==="string"){return e.replace(/\b\s/g,"\\ ")}else{return e}};var escapeSpacesInOptions=function(e){["src","dest","include","exclude","excludeFirst"].forEach((function(s){var r=e[s];if(typeof r==="string"){e[s]=escapeSpaces(r)}else if(Array.isArray(r)===true){e[s]=r.map(escapeSpaces)}}));return e};e.exports=function(e,s){e=e||{};e=t._extend({},e);e=escapeSpacesInOptions(e);var r=e.platform||process.platform;var n=r==="win32";if(typeof e.src==="undefined"){throw new Error("'src' directory is missing from options")}if(typeof e.dest==="undefined"){throw new Error("'dest' directory is missing from options")}var c=e.dest;if(typeof e.host!=="undefined"){c=e.host+":"+e.dest}if(!Array.isArray(e.src)){e.src=[e.src]}var i=[].concat(e.src);i.push(c);var a=(e.args||[]).find((function(e){return e.match(/--chmod=/)}));if(n&&!a){i.push("--chmod=ugo=rwX")}if(typeof e.host!=="undefined"||e.ssh){i.push("--rsh");var d="ssh";if(typeof e.port!=="undefined"){d+=" -p "+e.port}if(typeof e.privateKey!=="undefined"){d+=" -i "+e.privateKey}if(typeof e.sshCmdArgs!=="undefined"){d+=" "+e.sshCmdArgs.join(" ")}i.push(d)}if(e.recursive===true){i.push("--recursive")}if(e.times===true){i.push("--times")}if(e.syncDest===true||e.deleteAll===true){i.push("--delete");i.push("--delete-excluded")}if(e.syncDestIgnoreExcl===true||e.delete===true){i.push("--delete")}if(e.dryRun===true){i.push("--dry-run");i.push("--verbose")}if(typeof e.excludeFirst!=="undefined"&&t.isArray(e.excludeFirst)){e.excludeFirst.forEach((function(e,s){i.push("--exclude="+e)}))}if(typeof e.include!=="undefined"&&t.isArray(e.include)){e.include.forEach((function(e,s){i.push("--include="+e)}))}if(typeof e.exclude!=="undefined"&&t.isArray(e.exclude)){e.exclude.forEach((function(e,s){i.push("--exclude="+e)}))}switch(e.compareMode){case"sizeOnly":i.push("--size-only");break;case"checksum":i.push("--checksum");break}if(typeof e.args!=="undefined"&&t.isArray(e.args)){i=[...new Set([...i,...e.args])]}i=[...new Set(i)];var noop=function(){};var l=e.onStdout||noop;var u=e.onStderr||noop;var p="rsync ";i.forEach((function(e){if(e.substr(0,4)==="ssh "){e='"'+e+'"'}p+=e+" "}));p=p.trim();if(e.noExec){s(null,null,null,p);return}try{var f="";var h="";var y;if(n){y=o("cmd.exe",["/s","/c",'"'+p+'"'],{windowsVerbatimArguments:true,stdio:[process.stdin,"pipe","pipe"]})}else{y=o("/bin/sh",["-c",p])}y.stdout.on("data",(function(e){l(e);f+=e}));y.stderr.on("data",(function(e){u(e);h+=e}));y.on("exit",(function(e){var r=null;if(e!==0){r=new Error("rsync exited with code "+e);r.code=e}s(r,f,h,p)}))}catch(e){s(e,null,null,p)}}},505:(e,s,r)=>{const{existsSync:o,mkdirSync:t,writeFileSync:n}=r(147);const{join:c}=r(17);const validateDir=e=>{if(!e){console.warn("⚠️ [DIR] dir is not defined");return}if(o(e)){console.log(`✅ [DIR] ${e} dir exist`);return}console.log(`[DIR] Creating ${e} dir in workspace root`);t(e);console.log("✅ [DIR] dir created.")};const handleError=(e,s)=>{if(s){throw new Error(e)}console.warn(e)};const writeToFile=({dir:e,filename:s,content:r,isRequired:t,mode:i="0644"})=>{validateDir(e);const a=c(e,s);if(o(a)){const e=`⚠️ [FILE] ${a} Required file exist.`;handleError(e,t);return}try{console.log(`[FILE] writing ${a} file ...`,r.length);n(a,r,{encoding:"utf8",mode:i})}catch(e){const s=`⚠️[FILE] Writing to file error. filePath: ${a}, message: ${e.message}`;handleError(s,t)}};const validateRequiredInputs=e=>{const s=Object.keys(e);const r=s.filter((s=>{const r=e[s];if(!r){console.error(`❌ [INPUTS] ${s} is mandatory`)}return r}));if(r.length!==s.length){throw new Error("⚠️ [INPUTS] Inputs not valid, aborting ...")}};const snakeToCamel=e=>e.replace(/[^a-zA-Z0-9]+(.)/g,((e,s)=>s.toUpperCase()));e.exports={writeToFile:writeToFile,validateRequiredInputs:validateRequiredInputs,snakeToCamel:snakeToCamel}},229:(e,s,r)=>{const{snakeToCamel:o}=r(505);const t=["REMOTE_HOST","REMOTE_USER","REMOTE_PORT","SSH_PRIVATE_KEY","DEPLOY_KEY_NAME","SOURCE","TARGET","ARGS","SSH_CMD_ARGS","EXCLUDE","SCRIPT_BEFORE","SCRIPT_AFTER","SCRIPT_BEFORE_REQUIRED","SCRIPT_AFTER_REQUIRED"];const n=process.env.GITHUB_WORKSPACE;const c=process.env.REMOTE_USER||process.env.INPUT_REMOTE_USER;const i={source:"",target:`/home/${c}/`,exclude:"",args:"-rlgoDzvc -i",sshCmdArgs:"-o StrictHostKeyChecking=no",deployKeyName:`deploy_key_${c}_${Date.now()}`};const a={githubWorkspace:n};t.forEach((e=>{const s=o(e.toLowerCase());const r=process.env[e]||process.env[`INPUT_${e}`]||i[s];const t=r===undefined?i[s]:r;let c=t;switch(s){case"source":c=t.split(" ").map((e=>`${n}/${e}`));break;case"args":c=t.split(" ");break;case"exclude":case"sshCmdArgs":c=t.split(",").map((e=>e.trim()));break}a[s]=c}));a.sshServer=`${a.remoteUser}@${a.remoteHost}`;a.rsyncServer=`${a.remoteUser}@${a.remoteHost}:${a.target}`;e.exports=a},976:(e,s,r)=>{const{exec:o}=r(81);const t=r(113);const{sshServer:n,githubWorkspace:c,remotePort:i}=r(229);const{writeToFile:a}=r(505);const handleError=(e,s,r)=>{if(s){r(new Error(e))}else{console.warn(e)}};const remoteCmd=async(e,s,r,d)=>new Promise(((l,u)=>{const p=t.randomUUID();const f=`local_ssh_script-${d}-${p}.sh`;try{a({dir:c,filename:f,content:e});const t=1e4;const d=(process.env.RSYNC_STDOUT||"").substring(0,t);console.log(`Executing remote script: ssh -i ${s} ${n}`);o(`DEBIAN_FRONTEND=noninteractive ssh -p ${i||22} -i ${s} -o StrictHostKeyChecking=no ${n} 'RSYNC_STDOUT="${d}" bash -s' < ${f}`,((e,s="",o="")=>{if(e){const t=`⚠️ [CMD] Remote script failed: ${e.message}`;console.warn(`${t} \n`,s,o);handleError(t,r,u)}else{const e=s.substring(0,t);console.log("✅ [CMD] Remote script executed. \n",e,o);l(e)}}))}catch(e){handleError(e.message,r,u)}}));e.exports={remoteCmdBefore:async(e,s,r)=>remoteCmd(e,s,r,"before"),remoteCmdAfter:async(e,s,r)=>remoteCmd(e,s,r,"after")}},447:(e,s,r)=>{const{execSync:o}=r(81);const t=r(898);const nodeRsyncPromise=async e=>new Promise(((s,r)=>{const logCMD=e=>{console.warn("================================================================");console.log(e);console.warn("================================================================")};try{t(e,((e,o,t,n)=>{if(e){console.error("❌ [Rsync] error: ");console.error(e);console.error("❌ [Rsync] stderr: ");console.error(t);console.error("❌️ [Rsync] stdout: ");console.error(o);console.error("❌ [Rsync] command: ");logCMD(n);r(new Error(`${e.message}\n\n${t}`))}else{console.log("⭐ [Rsync] command finished: ");logCMD(n);s(o)}}))}catch(e){console.error("❌ [Rsync] command error: ",e.message,e.stack);r(e)}}));const validateRsync=async()=>{try{o("rsync --version",{stdio:"inherit"});console.log("✅️ [CLI] Rsync exists");return}catch(e){console.warn("⚠️ [CLI] Rsync doesn't exists",e.message)}console.log('[CLI] Start rsync installation with "apt-get" \n');try{o("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")}catch(e){throw new Error(`⚠️ [CLI] Rsync installation failed. Aborting ... error: ${e.message}`)}};const rsyncCli=async({source:e,rsyncServer:s,exclude:r,remotePort:o,privateKeyPath:t,args:n,sshCmdArgs:c})=>{console.log(`[Rsync] Starting Rsync Action: ${e} to ${s}`);if(r&&r.length>0)console.log(`[Rsync] excluding folders ${r}`);const i={ssh:true,recursive:true,onStdout:e=>console.log(e.toString()),onStderr:e=>console.error(e.toString())};return nodeRsyncPromise({...i,src:e,dest:s,excludeFirst:r,port:o,privateKey:t,args:n,sshCmdArgs:c})};const sshDeploy=async e=>{await validateRsync();const s=await rsyncCli(e);console.log("✅ [Rsync] finished.",s);process.env.RSYNC_STDOUT=`${s}`;return s};e.exports={sshDeploy:sshDeploy}},822:(e,s,r)=>{const{join:o}=r(17);const{execSync:t}=r(81);const{EOL:n}=r(37);const{writeToFile:c}=r(505);const i="known_hosts";const getPrivateKeyPath=(e="")=>{const{HOME:s}=process.env;const r=o(s||"~",".ssh");const t=o(r,i);return{dir:r,filename:e,path:o(r,e),knownHostsPath:t}};const addSshKey=(e,s)=>{const{dir:r,filename:o}=getPrivateKeyPath(s);c({dir:r,filename:i,content:""});console.log("✅ [SSH] known_hosts file ensured",r);c({dir:r,filename:o,content:`${e}${n}`,isRequired:true,mode:"0400"});console.log("✅ [SSH] key added to `.ssh` dir ",r,o)};const updateKnownHosts=(e,s)=>{const{knownHostsPath:r}=getPrivateKeyPath();console.log("[SSH] Adding host to `known_hosts` ....",e,r);try{t(`ssh-keyscan -p ${s||22} -H ${e} >> ${r}`,{stdio:"inherit"})}catch(s){console.error("❌ [SSH] Adding host to `known_hosts` ERROR",e,s.message)}console.log("✅ [SSH] Adding host to `known_hosts` DONE",e,r)};e.exports={getPrivateKeyPath:getPrivateKeyPath,updateKnownHosts:updateKnownHosts,addSshKey:addSshKey}},81:e=>{"use strict";e.exports=require("child_process")},113:e=>{"use strict";e.exports=require("crypto")},147:e=>{"use strict";e.exports=require("fs")},37:e=>{"use strict";e.exports=require("os")},17:e=>{"use strict";e.exports=require("path")},837:e=>{"use strict";e.exports=require("util")}};var s={};function __nccwpck_require__(r){var o=s[r];if(o!==undefined){return o.exports}var t=s[r]={exports:{}};var n=true;try{e[r](t,t.exports,__nccwpck_require__);n=false}finally{if(n)delete s[r]}return t.exports}if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=__dirname+"/";var r={};(()=>{const{sshDeploy:e}=__nccwpck_require__(447);const{remoteCmdBefore:s,remoteCmdAfter:r}=__nccwpck_require__(976);const{addSshKey:o,getPrivateKeyPath:t,updateKnownHosts:n}=__nccwpck_require__(822);const{validateRequiredInputs:c}=__nccwpck_require__(505);const i=__nccwpck_require__(229);const run=async()=>{const{source:a,remoteUser:d,remoteHost:l,remotePort:u,deployKeyName:p,sshPrivateKey:f,args:h,exclude:y,sshCmdArgs:m,scriptBefore:g,scriptBeforeRequired:_,scriptAfter:R,scriptAfterRequired:E,rsyncServer:w}=i;c({sshPrivateKey:f,remoteHost:l,remoteUser:d});o(f,p);const{path:v}=t(p);if(g||R){n(l,u)}if(g){await s(g,v,_)}await e({source:a,rsyncServer:w,exclude:y,remotePort:u,privateKeyPath:v,args:h,sshCmdArgs:m});if(R){await r(R,v,E)}};run().then(((e="")=>{console.log("✅ [DONE]",e)})).catch((e=>{console.error("❌ [ERROR]",e.message);process.exit(1)}))})();module.exports=r})(); \ No newline at end of file +(()=>{var e={898:(e,s,r)=>{"use strict";var o=r(81).spawn;var t=r(837);var escapeSpaces=function(e){if(typeof e==="string"){return e.replace(/\b\s/g,"\\ ")}else{return e}};var escapeSpacesInOptions=function(e){["src","dest","include","exclude","excludeFirst"].forEach((function(s){var r=e[s];if(typeof r==="string"){e[s]=escapeSpaces(r)}else if(Array.isArray(r)===true){e[s]=r.map(escapeSpaces)}}));return e};e.exports=function(e,s){e=e||{};e=t._extend({},e);e=escapeSpacesInOptions(e);var r=e.platform||process.platform;var n=r==="win32";if(typeof e.src==="undefined"){throw new Error("'src' directory is missing from options")}if(typeof e.dest==="undefined"){throw new Error("'dest' directory is missing from options")}var c=e.dest;if(typeof e.host!=="undefined"){c=e.host+":"+e.dest}if(!Array.isArray(e.src)){e.src=[e.src]}var i=[].concat(e.src);i.push(c);var a=(e.args||[]).find((function(e){return e.match(/--chmod=/)}));if(n&&!a){i.push("--chmod=ugo=rwX")}if(typeof e.host!=="undefined"||e.ssh){i.push("--rsh");var d="ssh";if(typeof e.port!=="undefined"){d+=" -p "+e.port}if(typeof e.privateKey!=="undefined"){d+=" -i "+e.privateKey}if(typeof e.sshCmdArgs!=="undefined"){d+=" "+e.sshCmdArgs.join(" ")}i.push(d)}if(e.recursive===true){i.push("--recursive")}if(e.times===true){i.push("--times")}if(e.syncDest===true||e.deleteAll===true){i.push("--delete");i.push("--delete-excluded")}if(e.syncDestIgnoreExcl===true||e.delete===true){i.push("--delete")}if(e.dryRun===true){i.push("--dry-run");i.push("--verbose")}if(typeof e.excludeFirst!=="undefined"&&t.isArray(e.excludeFirst)){e.excludeFirst.forEach((function(e,s){i.push("--exclude="+e)}))}if(typeof e.include!=="undefined"&&t.isArray(e.include)){e.include.forEach((function(e,s){i.push("--include="+e)}))}if(typeof e.exclude!=="undefined"&&t.isArray(e.exclude)){e.exclude.forEach((function(e,s){i.push("--exclude="+e)}))}switch(e.compareMode){case"sizeOnly":i.push("--size-only");break;case"checksum":i.push("--checksum");break}if(typeof e.args!=="undefined"&&t.isArray(e.args)){i=[...new Set([...i,...e.args])]}i=[...new Set(i)];var noop=function(){};var l=e.onStdout||noop;var u=e.onStderr||noop;var f="rsync ";i.forEach((function(e){if(e.substr(0,4)==="ssh "){e='"'+e+'"'}f+=e+" "}));f=f.trim();if(e.noExec){s(null,null,null,f);return}try{var p="";var h="";var y;if(n){y=o("cmd.exe",["/s","/c",'"'+f+'"'],{windowsVerbatimArguments:true,stdio:[process.stdin,"pipe","pipe"]})}else{y=o("/bin/sh",["-c",f])}y.stdout.on("data",(function(e){l(e);p+=e}));y.stderr.on("data",(function(e){u(e);h+=e}));y.on("exit",(function(e){var r=null;if(e!==0){r=new Error("rsync exited with code "+e);r.code=e}s(r,p,h,f)}))}catch(e){s(e,null,null,f)}}},505:(e,s,r)=>{const{existsSync:o,mkdirSync:t,writeFileSync:n}=r(147);const{join:c}=r(17);const validateDir=e=>{if(!e){console.warn("⚠️ [DIR] dir is not defined");return}if(o(e)){console.log(`✅ [DIR] ${e} dir exist`);return}console.log(`[DIR] Creating ${e} dir in workspace root`);t(e);console.log("✅ [DIR] dir created.")};const handleError=(e,s)=>{if(s){throw new Error(e)}console.warn(e)};const writeToFile=({dir:e,filename:s,content:r,isRequired:t,mode:i="0644"})=>{validateDir(e);const a=c(e,s);if(o(a)){const e=`⚠️ [FILE] ${a} Required file exist.`;handleError(e,t);return}try{console.log(`[FILE] writing ${a} file ...`,r.length);n(a,r,{encoding:"utf8",mode:i})}catch(e){const s=`⚠️[FILE] Writing to file error. filePath: ${a}, message: ${e.message}`;handleError(s,t)}};const validateRequiredInputs=e=>{const s=Object.keys(e);const r=s.filter((s=>{const r=e[s];if(!r){console.error(`❌ [INPUTS] ${s} is mandatory`)}return r}));if(r.length!==s.length){throw new Error("⚠️ [INPUTS] Inputs not valid, aborting ...")}};const snakeToCamel=e=>e.replace(/[^a-zA-Z0-9]+(.)/g,((e,s)=>s.toUpperCase()));e.exports={writeToFile:writeToFile,validateRequiredInputs:validateRequiredInputs,snakeToCamel:snakeToCamel}},229:(e,s,r)=>{const{snakeToCamel:o}=r(505);const t=["REMOTE_HOST","REMOTE_USER","REMOTE_PORT","SSH_PRIVATE_KEY","DEPLOY_KEY_NAME","SOURCE","TARGET","ARGS","SSH_CMD_ARGS","EXCLUDE","SCRIPT_BEFORE","SCRIPT_AFTER"];const n=process.env.GITHUB_WORKSPACE;const c=process.env.REMOTE_USER;const i={source:"",target:`/home/${c}/`,exclude:"",args:"-rltgoDzvO",sshCmdArgs:"-o StrictHostKeyChecking=no",deployKeyName:"deploy_key"};const a={githubWorkspace:n};t.forEach((e=>{const s=o(e.toLowerCase());const r=process.env[e]||process.env[`INPUT_${e}`];const t=r===undefined?i[s]:r;let c=t;switch(s){case"source":c=`${n}/${t}`;break;case"exclude":case"args":case"sshCmdArgs":c=t.split(",").map((e=>e.trim()));break}a[s]=c}));a.sshServer=`${a.remoteUser}@${a.remoteHost}`;a.rsyncServer=`${a.remoteUser}@${a.remoteHost}:${a.target}`;e.exports=a},976:(e,s,r)=>{const{exec:o}=r(81);const{sshServer:t,githubWorkspace:n}=r(229);const{writeToFile:c}=r(505);const handleError=(e,s,r)=>{if(s){r(new Error(e))}else{console.warn(e)}};const remoteCmd=async(e,s,r,i)=>new Promise(((a,d)=>{const l=`local_ssh_script-${i}.sh`;try{c({dir:n,filename:l,content:e});console.log(`Executing remote script: ssh -i ${s} ${t}`);o(`DEBIAN_FRONTEND=noninteractive ssh -i ${s} ${t} 'RSYNC_STDOUT="${process.env.RSYNC_STDOUT}" bash -s' < ${l}`,((e,s,o)=>{if(e){const t=`⚠️ [CMD] Remote script failed: ${e.message}`;console.warn(`${t} \n`,s,o);handleError(t,r,d)}else{console.log("✅ [CMD] Remote script executed. \n",s,o);a(s)}}))}catch(e){handleError(e.message,r,d)}}));e.exports={remoteCmdBefore:async(e,s,r)=>remoteCmd(e,s,r,"before"),remoteCmdAfter:async(e,s,r)=>remoteCmd(e,s,r,"after")}},447:(e,s,r)=>{const{execSync:o}=r(81);const t=r(898);const nodeRsyncPromise=async e=>new Promise(((s,r)=>{const logCMD=e=>{console.warn("================================================================");console.log(e);console.warn("================================================================")};try{t(e,((e,o,t,n)=>{if(e){console.error("❌ [Rsync] error: ");console.error(e);console.error("❌ [Rsync] stderr: ");console.error(t);console.error("❌️ [Rsync] stdout: ");console.error(o);console.error("❌ [Rsync] command: ");logCMD(n);r(new Error(`${e.message}\n\n${t}`))}else{console.log("⭐ [Rsync] command finished: ");logCMD(n);s(o)}}))}catch(e){console.error("❌ [Rsync] command error: ",e.message,e.stack);r(e)}}));const validateRsync=async()=>{try{o("rsync --version",{stdio:"inherit"});console.log("✅️ [CLI] Rsync exists");return}catch(e){console.warn("⚠️ [CLI] Rsync doesn't exists",e.message)}console.log('[CLI] Start rsync installation with "apt-get" \n');try{o("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")}catch(e){throw new Error(`⚠️ [CLI] Rsync installation failed. Aborting ... error: ${e.message}`)}};const rsyncCli=async({source:e,rsyncServer:s,exclude:r,remotePort:o,privateKeyPath:t,args:n,sshCmdArgs:c})=>{console.log(`[Rsync] Starting Rsync Action: ${e} to ${s}`);if(r)console.log(`[Rsync] excluding folders ${r}`);const i={ssh:true,recursive:true,onStdout:e=>console.log(e.toString()),onStderr:e=>console.error(e.toString())};return nodeRsyncPromise({...i,src:e,dest:s,excludeFirst:r,port:o,privateKey:t,args:n,sshCmdArgs:c})};const sshDeploy=async e=>{await validateRsync();const s=await rsyncCli(e);console.log("✅ [Rsync] finished.",s);process.env.RSYNC_STDOUT=`${s}`;return s};e.exports={sshDeploy:sshDeploy}},822:(e,s,r)=>{const{join:o}=r(17);const{execSync:t}=r(81);const{writeToFile:n}=r(505);const c="known_hosts";const getPrivateKeyPath=(e="")=>{const{HOME:s}=process.env;const r=o(s||"~",".ssh");const t=o(r,c);return{dir:r,filename:e,path:o(r,e),knownHostsPath:t}};const addSshKey=(e,s)=>{const{dir:r,filename:o}=getPrivateKeyPath(s);n({dir:r,filename:c,content:""});console.log("✅ [SSH] known_hosts file ensured",r);n({dir:r,filename:o,content:e,isRequired:true,mode:"0400"});console.log("✅ [SSH] key added to `.ssh` dir ",r,o)};const updateKnownHosts=e=>{const{knownHostsPath:s}=getPrivateKeyPath();console.log("[SSH] Adding host to `known_hosts` ....",e,s);try{t(`ssh-keyscan -H ${e} >> ${s}`,{stdio:"inherit"})}catch(s){console.error("❌ [SSH] Adding host to `known_hosts` ERROR",e,s.message)}console.log("✅ [SSH] Adding host to `known_hosts` DONE",e,s)};e.exports={getPrivateKeyPath:getPrivateKeyPath,updateKnownHosts:updateKnownHosts,addSshKey:addSshKey}},81:e=>{"use strict";e.exports=require("child_process")},147:e=>{"use strict";e.exports=require("fs")},17:e=>{"use strict";e.exports=require("path")},837:e=>{"use strict";e.exports=require("util")}};var s={};function __nccwpck_require__(r){var o=s[r];if(o!==undefined){return o.exports}var t=s[r]={exports:{}};var n=true;try{e[r](t,t.exports,__nccwpck_require__);n=false}finally{if(n)delete s[r]}return t.exports}if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=__dirname+"/";var r={};(()=>{const{sshDeploy:e}=__nccwpck_require__(447);const{remoteCmdBefore:s,remoteCmdAfter:r}=__nccwpck_require__(976);const{addSshKey:o,getPrivateKeyPath:t,updateKnownHosts:n}=__nccwpck_require__(822);const{validateRequiredInputs:c}=__nccwpck_require__(505);const i=__nccwpck_require__(229);const run=async()=>{const{source:a,remoteUser:d,remoteHost:l,remotePort:u,deployKeyName:f,sshPrivateKey:p,args:h,exclude:y,sshCmdArgs:m,scriptBefore:g,scriptAfter:_,rsyncServer:w}=i;c({sshPrivateKey:p,remoteHost:l,remoteUser:d});o(p,f);const{path:v}=t(f);if(g||_){n(l)}if(g){await s(g,v)}await e({source:a,rsyncServer:w,exclude:y,remotePort:u,privateKeyPath:v,args:h,sshCmdArgs:m});if(_){await r(_,v)}};run().then(((e="")=>{console.log("✅ [DONE]",e)})).catch((e=>{console.error("❌ [ERROR]",e.message);process.exit(1)}))})();module.exports=r})(); \ No newline at end of file diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 873cbcf..abac0ca 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,221 +1,3 @@ -## [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) - - -### Bug Fixes - -* move e2e tests to main branch ([0069fae](https://github.com/easingthemes/ssh-deploy/commit/0069faea9ff3ea3cdd095b0f2663c9e2bcd97480)) - -# [3.4.0](https://github.com/easingthemes/ssh-deploy/compare/v3.3.4...v3.4.0) (2023-01-03) - - -**Full Changelog**: https://github.com/easingthemes/ssh-deploy/compare/v3.1.0...v3.4.1 - -### 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 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) diff --git a/package-lock.json b/package-lock.json index 7cc9222..0c51f95 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@draganfilipovic/ssh-deploy", - "version": "4.1.10", + "version": "3.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@draganfilipovic/ssh-deploy", - "version": "4.1.10", + "version": "3.1.0", "license": "MIT", "dependencies": { "rsyncwrapper": "^3.0.1" @@ -19,9 +19,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", - "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.0.tgz", + "integrity": "sha512-7yfvXy6MWLgWSFsLhz5yH3iQ52St8cdUY6FoGieKkRDVxuxmrNuUetIuu6cmjNWwniUHiWXjxCr5tTXDrbYS5A==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -326,6 +326,21 @@ "node": ">= 8" } }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -455,12 +470,12 @@ } }, "node_modules/eslint": { - "version": "8.31.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.31.0.tgz", - "integrity": "sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.30.0.tgz", + "integrity": "sha512-MGADB39QqYuzEGov+F/qb18r4i7DohCDOfatHaxI2iGlPuC65bwG2gxgO+7DkyL38dRFaRH7RaRAgU6JKL9rMQ==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.4.1", + "@eslint/eslintrc": "^1.4.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -755,9 +770,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", + "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -1312,9 +1327,9 @@ "dev": true }, "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "dependencies": { "minimist": "^1.2.0" @@ -1357,18 +1372,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -1495,16 +1498,6 @@ "node": ">= 0.8.0" } }, - "node_modules/optionator/node_modules/word-wrap": { - "name": "@aashutoshrathi/word-wrap", - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-plhoNEfSVdHMKXQyAxvH0Zyv3/4NL8r6pwgMQdmHR2vBUXn2t74PN2pBRppqKUa6RMT0yldyvOHG5Dbjwy2mBQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -1744,18 +1737,12 @@ } }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/shebang-command": { @@ -1944,21 +1931,6 @@ "punycode": "^2.1.0" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/which-boxed-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", @@ -1975,18 +1947,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -2002,9 +1977,9 @@ }, "dependencies": { "@eslint/eslintrc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", - "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.0.tgz", + "integrity": "sha512-7yfvXy6MWLgWSFsLhz5yH3iQ52St8cdUY6FoGieKkRDVxuxmrNuUetIuu6cmjNWwniUHiWXjxCr5tTXDrbYS5A==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -2228,6 +2203,17 @@ "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, "debug": { @@ -2324,12 +2310,12 @@ "dev": true }, "eslint": { - "version": "8.31.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.31.0.tgz", - "integrity": "sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.30.0.tgz", + "integrity": "sha512-MGADB39QqYuzEGov+F/qb18r4i7DohCDOfatHaxI2iGlPuC65bwG2gxgO+7DkyL38dRFaRH7RaRAgU6JKL9rMQ==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.4.1", + "@eslint/eslintrc": "^1.4.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -2379,7 +2365,7 @@ "confusing-browser-globals": "^1.0.10", "object.assign": "^4.1.2", "object.entries": "^1.1.5", - "semver": "^7.5.2" + "semver": "^6.3.0" } }, "eslint-import-resolver-node": { @@ -2563,9 +2549,9 @@ "dev": true }, "fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", + "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -2957,9 +2943,9 @@ "dev": true }, "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { "minimist": "^1.2.0" @@ -2990,15 +2976,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3092,15 +3069,7 @@ "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", - "word-wrap": "npm:@aashutoshrathi/word-wrap@1.2.5" - }, - "dependencies": { - "word-wrap": { - "version": "npm:@aashutoshrathi/word-wrap@1.2.5", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-plhoNEfSVdHMKXQyAxvH0Zyv3/4NL8r6pwgMQdmHR2vBUXn2t74PN2pBRppqKUa6RMT0yldyvOHG5Dbjwy2mBQ==", - "dev": true - } + "word-wrap": "^1.2.3" } }, "p-limit": { @@ -3247,13 +3216,10 @@ } }, "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true }, "shebang-command": { "version": "2.0.0", @@ -3393,15 +3359,6 @@ "punycode": "^2.1.0" } }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, "which-boxed-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", @@ -3415,18 +3372,18 @@ "is-symbol": "^1.0.3" } }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 22b5373..d2484ab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@draganfilipovic/ssh-deploy", - "version": "5.1.1", + "version": "3.3.4", "description": "Fast NodeJS action to deploy specific directory from `GITHUB_WORKSPACE` to a server via rsync over ssh.", "main": "dist/index.js", "files": [ @@ -37,9 +37,5 @@ "eslint": "^8.30.0", "eslint-config-airbnb-base": "^15.0.0", "eslint-plugin-import": "^2.26.0" - }, - "overrides": { - "word-wrap": "npm:@aashutoshrathi/word-wrap@1.2.5", - "semver": "^7.5.2" } } diff --git a/src/helpers.js b/src/helpers.js index 78379e1..1c705df 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -1,4 +1,4 @@ -const { existsSync, mkdirSync, writeFileSync, unlink } = require('fs'); +const { existsSync, mkdirSync, writeFileSync } = require('fs'); const { join } = require('path'); const validateDir = (dir) => { @@ -45,29 +45,6 @@ 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 inputKeys = Object.keys(inputs); const validInputs = inputKeys.filter((inputKey) => { @@ -89,7 +66,6 @@ const snakeToCamel = (str) => str.replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.t module.exports = { writeToFile, - deleteFile, validateRequiredInputs, snakeToCamel }; diff --git a/src/index.js b/src/index.js index 7266355..0586e40 100644 --- a/src/index.js +++ b/src/index.js @@ -10,8 +10,7 @@ const run = async () => { source, remoteUser, remoteHost, remotePort, deployKeyName, sshPrivateKey, args, exclude, sshCmdArgs, - scriptBefore, scriptBeforeRequired, - scriptAfter, scriptAfterRequired, + scriptBefore, scriptAfter, rsyncServer } = inputs; // Validate required inputs @@ -21,11 +20,11 @@ const run = async () => { const { path: privateKeyPath } = getPrivateKeyPath(deployKeyName); // Update known hosts if ssh command is present to avoid prompt if (scriptBefore || scriptAfter) { - updateKnownHosts(remoteHost, remotePort); + updateKnownHosts(remoteHost); } // Check Script before if (scriptBefore) { - await remoteCmdBefore(scriptBefore, privateKeyPath, scriptBeforeRequired); + await remoteCmdBefore(scriptBefore, privateKeyPath); } /* eslint-disable object-property-newline */ await sshDeploy({ @@ -34,7 +33,7 @@ const run = async () => { }); // Check script after if (scriptAfter) { - await remoteCmdAfter(scriptAfter, privateKeyPath, scriptAfterRequired); + await remoteCmdAfter(scriptAfter, privateKeyPath); } }; diff --git a/src/inputs.js b/src/inputs.js index 2c5dd19..f636080 100644 --- a/src/inputs.js +++ b/src/inputs.js @@ -4,18 +4,18 @@ const inputNames = [ 'REMOTE_HOST', 'REMOTE_USER', 'REMOTE_PORT', 'SSH_PRIVATE_KEY', 'DEPLOY_KEY_NAME', 'SOURCE', 'TARGET', 'ARGS', 'SSH_CMD_ARGS', 'EXCLUDE', - 'SCRIPT_BEFORE', 'SCRIPT_AFTER', 'SCRIPT_BEFORE_REQUIRED', 'SCRIPT_AFTER_REQUIRED']; + 'SCRIPT_BEFORE', 'SCRIPT_AFTER']; const githubWorkspace = process.env.GITHUB_WORKSPACE; -const remoteUser = process.env.REMOTE_USER || process.env.INPUT_REMOTE_USER; +const remoteUser = process.env.REMOTE_USER; const defaultInputs = { source: '', target: `/home/${remoteUser}/`, exclude: '', - args: '-rlgoDzvc -i', + args: '-rltgoDzvO', sshCmdArgs: '-o StrictHostKeyChecking=no', - deployKeyName: `deploy_key_${remoteUser}_${Date.now()}` + deployKeyName: 'deploy_key' }; const inputs = { @@ -24,18 +24,16 @@ const inputs = { inputNames.forEach((input) => { const inputName = snakeToCamel(input.toLowerCase()); - const inputVal = process.env[input] || process.env[`INPUT_${input}`] || defaultInputs[inputName]; + const inputVal = process.env[input] || process.env[`INPUT_${input}`]; const validVal = inputVal === undefined ? defaultInputs[inputName] : inputVal; let extendedVal = validVal; // eslint-disable-next-line default-case switch (inputName) { case 'source': - extendedVal = validVal.split(' ').map((src) => `${githubWorkspace}/${src}`); - break; - case 'args': - extendedVal = validVal.split(' '); + extendedVal = `${githubWorkspace}/${validVal}`; break; case 'exclude': + case 'args': case 'sshCmdArgs': extendedVal = validVal.split(',').map((item) => item.trim()); break; diff --git a/src/remoteCmd.js b/src/remoteCmd.js index 70f7656..640234b 100644 --- a/src/remoteCmd.js +++ b/src/remoteCmd.js @@ -1,7 +1,6 @@ const { exec } = require('child_process'); -const crypto = require('crypto'); -const { sshServer, githubWorkspace, remotePort } = require('./inputs'); -const { writeToFile, deleteFile } = require('./helpers'); +const { sshServer, githubWorkspace } = require('./inputs'); +const { writeToFile } = require('./helpers'); const handleError = (message, isRequired, callback) => { if (isRequired) { @@ -13,26 +12,20 @@ const handleError = (message, isRequired, callback) => { // eslint-disable-next-line max-len const remoteCmd = async (content, privateKeyPath, isRequired, label) => new Promise((resolve, reject) => { - const uuid = crypto.randomUUID(); - const filename = `local_ssh_script-${label}-${uuid}.sh`; + const filename = `local_ssh_script-${label}.sh`; try { 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}`); exec( - `DEBIAN_FRONTEND=noninteractive ssh -p ${(remotePort || 22)} -i ${privateKeyPath} -o StrictHostKeyChecking=no ${sshServer} 'RSYNC_STDOUT="${rsyncStdout}" bash -s' < ${filename}`, - (err, data = '', stderr = '') => { + `DEBIAN_FRONTEND=noninteractive ssh -i ${privateKeyPath} ${sshServer} 'RSYNC_STDOUT="${process.env.RSYNC_STDOUT}" bash -s' < ${filename}`, + (err, data, stderr) => { if (err) { const message = `⚠️ [CMD] Remote script failed: ${err.message}`; console.warn(`${message} \n`, data, stderr); handleError(message, isRequired, reject); } else { - const limited = data.substring(0, dataLimit); - console.log('✅ [CMD] Remote script executed. \n', limited, stderr); - deleteFile({ dir: githubWorkspace, filename }); - console.log('✅ [FILE] Script file deleted.'); - resolve(limited); + console.log('✅ [CMD] Remote script executed. \n', data, stderr); + resolve(data); } } ); diff --git a/src/rsyncCli.js b/src/rsyncCli.js index 562a22e..cebb941 100644 --- a/src/rsyncCli.js +++ b/src/rsyncCli.js @@ -55,7 +55,7 @@ const rsyncCli = async ({ privateKeyPath, args, sshCmdArgs }) => { console.log(`[Rsync] Starting Rsync Action: ${source} to ${rsyncServer}`); - if (exclude && exclude.length > 0) console.log(`[Rsync] excluding folders ${exclude}`); + if (exclude) console.log(`[Rsync] excluding folders ${exclude}`); const defaultOptions = { ssh: true, diff --git a/src/sshKey.js b/src/sshKey.js index 066ed02..ce40d50 100644 --- a/src/sshKey.js +++ b/src/sshKey.js @@ -1,6 +1,5 @@ const { join } = require('path'); const { execSync } = require('child_process'); -const { EOL } = require('os'); const { writeToFile } = require('./helpers'); const KNOWN_HOSTS = 'known_hosts'; @@ -20,15 +19,15 @@ const addSshKey = (content, deployKeyName) => { const { dir, filename } = getPrivateKeyPath(deployKeyName); writeToFile({ dir, filename: KNOWN_HOSTS, content: '' }); console.log('✅ [SSH] known_hosts file ensured', dir); - writeToFile({ dir, filename, content: `${content}${EOL}`, isRequired: true, mode: '0400' }); + writeToFile({ dir, filename, content, isRequired: true, mode: '0400' }); console.log('✅ [SSH] key added to `.ssh` dir ', dir, filename); }; -const updateKnownHosts = (host, remotePort) => { +const updateKnownHosts = (host) => { const { knownHostsPath } = getPrivateKeyPath(); console.log('[SSH] Adding host to `known_hosts` ....', host, knownHostsPath); try { - execSync(`ssh-keyscan -p ${(remotePort || 22)} -H ${host} >> ${knownHostsPath}`, { + execSync(`ssh-keyscan -H ${host} >> ${knownHostsPath}`, { stdio: 'inherit' }); } catch (error) { diff --git a/test/Dockerfile b/test/Dockerfile index fc9efdf..a79ba12 100644 --- a/test/Dockerfile +++ b/test/Dockerfile @@ -6,32 +6,23 @@ RUN apt update RUN apt install openssh-server rsync sudo -y +RUN useradd -rm -d /home/test -s /bin/bash -g root -G sudo -u 1000 test + +RUN usermod -aG sudo test + RUN echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config.d/pub.conf RUN echo "AuthorizedKeysFile .ssh/authorized_keys" >> /etc/ssh/sshd_config.d/pub.conf RUN mkdir -p /var/www/html -RUN mkdir -p /var/www/html/test -RUN mkdir -p /var/www/html/test2 -RUN chmod -R 775 /var/www/html - -RUN useradd -rm -d /home/test -s /bin/bash -g root -G sudo -u 1000 test -RUN usermod -aG sudo test +RUN chown -R test /var/www/html RUN mkdir -p /home/test/.ssh RUN echo "$SSH_PUB_KEY" > /home/test/.ssh/authorized_keys RUN chmod 700 /home/test/.ssh RUN chown -R test /home/test/.ssh -RUN useradd -rm -d /home/test2 -s /bin/bash -g root -G sudo -u 1002 test2 -RUN usermod -aG sudo test2 -RUN mkdir -p /home/test2/.ssh -RUN echo "$SSH_PUB_KEY" > /home/test2/.ssh/authorized_keys -RUN chmod 700 /home/test2/.ssh -RUN chown -R test2 /home/test2/.ssh - RUN service ssh start RUN echo 'test:test' | chpasswd -RUN echo 'test2:test2' | chpasswd EXPOSE 22