Compare commits

...

47 Commits
v2.2.0 ... v2

Author SHA1 Message Date
shimataro d4fffb5087
version 2.7.0 (#270) 2024-02-11 11:30:38 +09:00
shimataro 9383557752
update dependencies (#269) 2024-02-11 11:18:12 +09:00
shimataro 8f0e25e199
Feature/node20 (#268)
* Update to Node 20 (#267)

* Update action.yml

* Update build.yml

* update CHANGELOG

* Drop old containers

* update CHANGELOG

---------

Co-authored-by: Po Chen <chenpaul914@gmail.com>
2024-02-11 11:04:28 +09:00
shimataro 38b53cb2f4
version 2.6.1 (#264) 2023-10-13 10:02:31 +09:00
shimataro 9e1a5e7913
use cache for npm (#263) 2023-10-13 09:39:50 +09:00
shimataro c858f8173b
update dependencies (#262) 2023-10-13 09:06:52 +09:00
shimataro f848d33143
fix; release script error (#261) 2023-10-12 10:27:38 +09:00
shimataro b49a036be4
fix; JSON parse error on exit, if `if_key_exists`=`fail` and key exists (#260)
* fix; JSON parse error on exit, if `if_key_exists`=`fail` and key exists

* update CHANGELOG

* fix cleanup error

* add built files

* output only if created/removed/restored file exist.
2023-10-12 09:58:46 +09:00
shimataro 18e8292da0
update release script (#259) 2023-10-12 05:00:12 +09:00
shimataro d05e1bdf7d
Merge pull request #258 from shimataro/develop
version 2.6.0
2023-10-12 04:11:09 +09:00
shimataro a9c5970ee8
version 2.6.0 (#257) 2023-10-11 22:58:33 +09:00
shimataro ccfb951a8e
fix; files that didn't backed up is not removed in "post" phase (#256)
* fix; files that didn't backed up is not removed in "post" phase

* output logs

* output log in main phase

* update log text

* update log text

* create directory only if not exist

* amend step name
2023-10-11 16:20:54 +09:00
shimataro ab731d2fcd
update dependencies (#255) 2023-10-11 07:44:42 +09:00
shimataro 51874aa964
exit if differ (#254) 2023-10-11 05:25:38 +09:00
shimataro 00676f1f60
use `os.homedir()` in order to get home directory (#253) 2023-10-11 05:04:21 +09:00
shimataro 6948892be9
use module files (#252)
* use module

* detect files to be restore automatically

* use esbuild

* drop ncc

* add comments

* refactor
2023-10-11 04:35:20 +09:00
shimataro 31d4b8b483
backup & restore (#251)
* backup & restore

* refactor

* refactor

* back up key file

* fix messages

* update CHANGELOG

* update CHANGELOG
2023-10-10 13:51:45 +09:00
shimataro 2983fc456f
Feature/remove old runner (#249)
* Drop runnner: macOS 10.15, Ubuntu 18.04

* update README

* update CHANGELOG

* update key of bitbucket.com
2023-10-09 18:25:53 +09:00
shimataro f5671c022c
update dependencies (#241) 2023-03-25 05:53:47 +09:00
shimataro 685d0f20da
Merge pull request #240 from shimataro/develop
version 2.5.1
2023-03-25 05:13:30 +09:00
shimataro 699cc3af2a
version 2.5.1 (#239) 2023-03-25 04:53:10 +09:00
shimataro 18601dcd44
Feature/update gh key (#238)
* github: Update SSH key

Signed-off-by: Ryan Northey <ryan@synca.io>

* update GitHub key: https://github.blog/2023-03-23-we-updated-our-rsa-ssh-host-key/

* add name

---------

Signed-off-by: Ryan Northey <ryan@synca.io>
Co-authored-by: Ryan Northey <ryan@synca.io>
2023-03-25 04:27:28 +09:00
shimataro 02d189fc92
Merge pull request #230 from shimataro/develop
version 2.5.0
2022-12-24 21:59:35 +09:00
shimataro 70366947e2
version 2.5.0 (#229) 2022-12-24 21:37:26 +09:00
shimataro 00376433fd
update dependencies (#228) 2022-12-24 20:55:12 +09:00
shimataro d3bad3234b
update dependencies (#227) 2022-12-21 17:36:57 +09:00
shimataro c8a575584e
set workflow name (#226)
* set workflow name

* update actions/checkout version: v2 -> v3

* update actions/setup-node version: v1 -> v3
2022-12-21 11:14:30 +09:00
shimataro da84e6bf98
Feature/ci (#225)
* reuse workflows
https://docs.github.com/en/actions/using-workflows/reusing-workflows

* reuse container workflows

* integrate reusable-verify-container with reusable-verify

* container -> docker_iamge

* update description
2022-12-20 22:11:39 +09:00
shimataro 7cccbd3065
add cleanup process (#224)
* add cleanup process

* save state

* update README/CHANGELOG

* fix message

* `getSshDirectory()` should not be exported
2022-12-20 08:06:55 +09:00
shimataro 86a65fd09b
Merge pull request #222 from shimataro/develop
version 2.4.0
2022-11-03 05:05:47 +09:00
shimataro 193316a178
version 2.4.0 (#221) 2022-11-03 04:41:33 +09:00
shimataro a3a8a38571
update dependencies (#220) 2022-11-03 04:12:51 +09:00
shimataro 1512adeca4
Feature/GitHub key (#122)
* always prepend key of github.com

* update README and CHANGELOG

* update tests

* test to connect bitbucket.org

* update test

* update rest tests
2022-11-03 03:41:25 +09:00
shimataro bcb314ec07
fix usage of rsync (#218) 2022-10-31 00:31:19 +09:00
shimataro 53a7c26e5e
Feature/runners (#217)
* Updated runners list and tar updated to 6.1.11

* Updated runners list

* Added nodejs 16

* Updated .gitignore

* some adjusts

* update CHANGELOG

Co-authored-by: Viacheslav Kudinov <viacheslav.kudinov@gmail.com>
2022-10-30 23:46:03 +09:00
shimataro fc21805258
Update nodejs version to 16 (#208) (#216)
* Update nodejs version to 16 (#208)

* Update nodejs version to 16

* Update runtime used to node16

* update CHANGELOG

Co-authored-by: Davide Doronzo <duddu@users.noreply.github.com>
2022-10-30 22:47:45 +09:00
shimataro 1926ba6435
update dependencies (#211) 2022-10-30 21:57:29 +09:00
shimataro adea214356
Feature/refactor (#209)
* Change code style to 1TBS

* refactor creating ".ssh" directoy

* Add Windows-2022 / macOS-11 / macOS-12 / Ubuntu-22.04
Drop Ubuntu-16.04

* Drop centos:8 (Docker container)

* add CentOS 8 Stream (Docker container)

* use YAML alias

* Revert "use YAML alias"

This reverts commit 1ddbc7fde8.

* update .eslintrc

* move calling main to front
2022-10-30 19:57:06 +09:00
shimataro 3c9b0fc6f2
Merge pull request #190 from shimataro/develop
version 2.3.1
2021-08-01 23:19:32 +09:00
shimataro b38d88da8a
version 2.3.1 (#189) 2021-08-01 23:04:08 +09:00
shimataro 92fef6465a
Feature/virtual environments (#187)
* remove ubuntu-16.04 virtual environment; https://github.blog/changelog/2021-04-29-github-actions-ubuntu-16-04-lts-virtual-environment-will-be-removed-on-september-20-2021/

* add `windows-2016` virtual environment

* update README/CHANGELOG

* remove ubuntu-16.04
fix tests on Windows/macOS
2021-08-01 22:31:32 +09:00
shimataro a46749e290
Feature/update dependencies 20210801 (#186)
* update dependencies

* update CHANGELOG
2021-08-01 21:52:23 +09:00
shimataro ce5317ebbf
Merge pull request #183 from shimataro/develop
version 2.3.0
2021-03-21 16:25:36 +09:00
shimataro 4dfaf8f393
version 2.3.0 (#182) 2021-03-21 16:05:33 +09:00
shimataro 954c620b17
Feature/no known hosts (#181)
* add "if_key_exists"

* add test

* fix flag

* fix SSH connection commands

* add test for if_key_exists=ignore

* add test for if_key_exists=fail

* add tests to Windows / macOS

* update CHANGELOG

* update badges

* update README

* fix README

* update README

* test no_known_hosts parameter

* implement

* ignore known_hosts if no_known_hosts is true

* refactor

* no_known_hosts is false

* Revert "no_known_hosts is false"

This reverts commit 206d310c5c.

* test on Windows / macOS

* test on Docker containers

* add tests for Docker containers

* test no_known_hosts parameter

* implement

* ignore known_hosts if no_known_hosts is true

* refactor

* no_known_hosts is false

* Revert "no_known_hosts is false"

This reverts commit 206d310c5c.

* test on Windows / macOS

* test on Docker containers

* use `known_hosts: no` instead of `no_known_hosts: true`

* update README

* update README

* "known_hosts: no" -> "known_hosts: unnecessary"

* update README

* update README

* update CHANGELOG
2021-03-21 15:43:28 +09:00
shimataro f8aa6610de
Feature/verify on container alpine (#180)
* support Alpine Docker container

* add Git package

* update README

* update README; add install commands

* update CHANGELOG

* fix typo

* fix typo
2021-03-21 14:56:48 +09:00
shimataro 88fb14d113
add "if_key_exists" (#179)
* add "if_key_exists"

* add test

* fix flag

* fix SSH connection commands

* add test for if_key_exists=ignore

* add test for if_key_exists=fail

* add tests to Windows / macOS

* update CHANGELOG

* update badges

* update README

* fix README

* update README

* add tests for Docker containers
2021-03-18 20:57:28 +09:00
36 changed files with 11270 additions and 3746 deletions

View File

@ -25,6 +25,13 @@ spaces_around_brackets = none
indent_brace_style = allman
# JavaScript/TypeScript
[*.{js,ts}]
indent_style = space
curly_bracket_next_line = false
indent_brace_style = K&R
# JSON/YAML
[*.{json,babelrc,code-workspace,yml,yaml}]
indent_style = space

View File

@ -14,7 +14,9 @@ parserOptions:
project: ./tsconfig.json
rules: # https://eslint.org/docs/rules/
accessor-pairs: error
array-bracket-newline: error
array-bracket-newline:
- error
- consistent
array-bracket-spacing:
- error
- never
@ -29,9 +31,7 @@ rules: # https://eslint.org/docs/rules/
before: true
block-scoped-var: error
block-spacing: error
brace-style:
- error
- allman
brace-style: 'off' # see "@typescript-eslint/brace-style"
callback-return: error
capitalized-comments: 'off'
class-methods-use-this: error
@ -87,26 +87,14 @@ rules: # https://eslint.org/docs/rules/
- below
indent:
- error
- tab
- 4
- SwitchCase: 1
indent-legacy: 'off'
init-declarations: error
jsx-quotes: error
key-spacing: error
keyword-spacing:
- error
- overrides:
catch:
after: false
for:
after: false
if:
after: false
switch:
after: false
while:
after: false
with:
after: false
line-comment-position: 'off'
linebreak-style:
- error
@ -173,7 +161,7 @@ rules: # https://eslint.org/docs/rules/
- error
- max: 1
no-native-reassign: error
no-negated-condition: error
no-negated-condition: 'off'
no-negated-in-lhs: error
no-nested-ternary: error
no-new: error
@ -256,7 +244,7 @@ rules: # https://eslint.org/docs/rules/
rest-spread-spacing:
- error
- never
semi: error
semi: 'off' # see "@typescript-eslint/semi"
semi-spacing: error
semi-style:
- error
@ -308,8 +296,25 @@ rules: # https://eslint.org/docs/rules/
# @typescript-eslint plugin
"@typescript-eslint/ban-ts-ignore": 'off'
"@typescript-eslint/brace-style":
- error
- 1tbs
"@typescript-eslint/member-delimiter-style":
- error
- multiline:
delimiter: semi
requireLast: true
singleline:
delimiter: semi
requireLast: true
"@typescript-eslint/no-empty-interface": 'off'
"@typescript-eslint/no-floating-promises": error
"@typescript-eslint/no-use-before-define":
- error
- functions: false
"@typescript-eslint/strict-boolean-expressions": error
"@typescript-eslint/semi": error
"@typescript-eslint/strict-boolean-expressions":
- error
- allowString: false
allowNumber: false
allowNullableObject: false

25
.github/actions/cache-npm/action.yml vendored Normal file
View File

@ -0,0 +1,25 @@
# https://docs.github.com/en/actions/creating-actions/creating-a-composite-action
name: Cache NPM
description: Composite action (cache NPM)
runs:
using: composite
steps:
# https://github.com/actions/cache/blob/master/examples.md#node---npm
# https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-output-parameter
- name: Get NPM cache directory
run: echo "NPM_CACHE_DIRECTORY=$(npm config get cache)" >> ${{ github.env }} # use "github.env" instead of "github.output"; if use "github.output", "Warning: Input required and not supplied: path" is displayed on post-process
shell: pwsh # use PowerShell; Bash doesn't work on Windows because the value of "github.env" is like "D:\a\_temp\_runner_file_commands\set_env_XXX".
- name: Get Node.js version
run: echo "NODEJS_VERSION=$(node -v)" >> ${{ github.env }}
shell: pwsh
- name: Cache NPM modules
uses: actions/cache@v3
with:
path: ${{ env.NPM_CACHE_DIRECTORY }}
key: npm-${{ runner.os }}-${{ runner.arch }}-${{ env.NODEJS_VERSION }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
npm-${{ runner.os }}-${{ runner.arch }}-${{ env.NODEJS_VERSION }}-
npm-${{ runner.os }}-${{ runner.arch }}

View File

@ -12,26 +12,31 @@ jobs:
strategy:
matrix:
os:
- Windows-2019
- macOS-10.15
- Ubuntu-16.04
- Ubuntu-18.04
- Ubuntu-20.04
- windows-2019
- windows-2022
- macos-11
- macos-12
- ubuntu-20.04
- ubuntu-22.04
nodejs:
- 12
- 20
fail-fast: false
steps:
- name: Turn off auto-crlf
run: git config --global core.autocrlf false
- name: Checkout source codes
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.nodejs }}
- name: Cache NPM
uses: ./.github/actions/cache-npm
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Exit if differ (forgot to commit dist dir?)
run: git diff --exit-code --quiet
- name: Verify
run: npm run verify

278
.github/workflows/reusable-verify.yml vendored Normal file
View File

@ -0,0 +1,278 @@
# https://docs.github.com/en/actions/using-workflows/reusing-workflows
name: Reusable workflow (verify)
on:
workflow_call:
inputs:
os:
required: true
type: string
description: host OS that CI 'runs-on'
docker_image:
required: false
type: string
default: ""
description: Docker image name
package_installation_command:
required: false
type: string
default: ""
description: package installation command
secrets:
SSH_KEY_PEM:
required: true
description: SSH private key (PEM format)
SSH_KEY_PKCS8:
required: true
description: SSH private key (PKCS8 format)
SSH_KEY_RFC4716:
required: true
description: SSH private key (RFC4716 format)
jobs:
ssh-pem:
name: Connect to github.com (PEM format)
runs-on: ${{ inputs.os }}
container: ${{ inputs.docker_image }}
steps:
- name: Install packages
run: ${{ inputs.package_installation_command }}
if: ${{ inputs.package_installation_command != '' }}
- name: Checkout source codes
uses: actions/checkout@v3
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: unnecessary
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-pem-bitbucket:
name: Connect to bitbucket.org (PEM format)
runs-on: ${{ inputs.os }}
container: ${{ inputs.docker_image }}
steps:
- name: Install packages
run: ${{ inputs.package_installation_command }}
if: ${{ inputs.package_installation_command != '' }}
- name: Checkout source codes
uses: actions/checkout@v3
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: |
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M=
bitbucket.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIQmuzMBuKdWeF4+a2sjSSpBK0iqitSQ+5BM9KhpexuGt20JpTVM7u5BDZngncgrqDMbWdxMWWOGtZ9UgbqgZE=
bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO
- name: git clone through SSH
run: git clone git@bitbucket.org:shimataro999/ssh-test.git tmp
ssh-pkcs8:
name: Connect to github.com (PKCS8 format)
runs-on: ${{ inputs.os }}
container: ${{ inputs.docker_image }}
steps:
- name: Install packages
run: ${{ inputs.package_installation_command }}
if: ${{ inputs.package_installation_command != '' }}
- name: Checkout source codes
uses: actions/checkout@v3
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PKCS8 }}
known_hosts: unnecessary
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-pkcs8-bitbucket:
name: Connect to bitbucket.org (PKCS8 format)
runs-on: ${{ inputs.os }}
container: ${{ inputs.docker_image }}
steps:
- name: Install packages
run: ${{ inputs.package_installation_command }}
if: ${{ inputs.package_installation_command != '' }}
- name: Checkout source codes
uses: actions/checkout@v3
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PKCS8 }}
known_hosts: |
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M=
bitbucket.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIQmuzMBuKdWeF4+a2sjSSpBK0iqitSQ+5BM9KhpexuGt20JpTVM7u5BDZngncgrqDMbWdxMWWOGtZ9UgbqgZE=
bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO
- name: git clone through SSH
run: git clone git@bitbucket.org:shimataro999/ssh-test.git tmp
ssh-rfc4716:
name: Connect to github.com (RFC4716 format)
runs-on: ${{ inputs.os }}
container: ${{ inputs.docker_image }}
steps:
- name: Install packages
run: ${{ inputs.package_installation_command }}
if: ${{ inputs.package_installation_command != '' }}
- name: Checkout source codes
uses: actions/checkout@v3
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_RFC4716 }}
known_hosts: unnecessary
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-rfc4716-bitbucket:
name: Connect to bitbucket.org (RFC4716 format)
runs-on: ${{ inputs.os }}
container: ${{ inputs.docker_image }}
steps:
- name: Install packages
run: ${{ inputs.package_installation_command }}
if: ${{ inputs.package_installation_command != '' }}
- name: Checkout source codes
uses: actions/checkout@v3
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_RFC4716 }}
known_hosts: |
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M=
bitbucket.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIQmuzMBuKdWeF4+a2sjSSpBK0iqitSQ+5BM9KhpexuGt20JpTVM7u5BDZngncgrqDMbWdxMWWOGtZ9UgbqgZE=
bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO
- name: git clone through SSH
run: git clone git@bitbucket.org:shimataro999/ssh-test.git tmp
key_if_exists_replace-key_exists:
name: if_key_exists=replace / key exists
runs-on: ${{ inputs.os }}
container: ${{ inputs.docker_image }}
steps:
- name: Install packages
run: ${{ inputs.package_installation_command }}
if: ${{ inputs.package_installation_command != '' }}
- name: Checkout source codes
uses: actions/checkout@v3
- name: Install SSH key (dummy)
uses: ./.
with:
key: "dummy" # replaced
known_hosts: unnecessary
- name: Install SSH key (replaces existing key)
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: unnecessary
if_key_exists: replace
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
key_if_exists_replace-key_doesnt_exist:
name: if_key_exists=replace / key doesn't exist
runs-on: ${{ inputs.os }}
container: ${{ inputs.docker_image }}
steps:
- name: Install packages
run: ${{ inputs.package_installation_command }}
if: ${{ inputs.package_installation_command != '' }}
- name: Checkout source codes
uses: actions/checkout@v3
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: unnecessary
if_key_exists: replace
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
key_if_exists_ignore-key_exists:
name: if_key_exists=ignore / key exists
runs-on: ${{ inputs.os }}
container: ${{ inputs.docker_image }}
steps:
- name: Install packages
run: ${{ inputs.package_installation_command }}
if: ${{ inputs.package_installation_command != '' }}
- name: Checkout source codes
uses: actions/checkout@v3
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: unnecessary
- name: Install SSH key (does nothing)
uses: ./.
with:
key: "dummy" # ignored
known_hosts: unnecessary
if_key_exists: ignore
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
key_if_exists_ignore-key_doesnt_exist:
name: if_key_exists=ignore / key doesn't exist
runs-on: ${{ inputs.os }}
container: ${{ inputs.docker_image }}
steps:
- name: Install packages
run: ${{ inputs.package_installation_command }}
if: ${{ inputs.package_installation_command != '' }}
- name: Checkout source codes
uses: actions/checkout@v3
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: unnecessary
if_key_exists: ignore
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
key_if_exists_fail-key_exists:
name: if_key_exists=fail / key exists
runs-on: ${{ inputs.os }}
container: ${{ inputs.docker_image }}
steps:
- name: Install packages
run: ${{ inputs.package_installation_command }}
if: ${{ inputs.package_installation_command != '' }}
- name: Checkout source codes
uses: actions/checkout@v3
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: unnecessary
- name: Install SSH key (fails)
uses: ./.
with:
key: "dummy" # fails
known_hosts: unnecessary
if_key_exists: fail
continue-on-error: true
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
key_if_exists_fail-key_doesnt_exist:
name: if_key_exists=fail / key doesn't exist
runs-on: ${{ inputs.os }}
container: ${{ inputs.docker_image }}
steps:
- name: Install packages
run: ${{ inputs.package_installation_command }}
if: ${{ inputs.package_installation_command != '' }}
- name: Checkout source codes
uses: actions/checkout@v3
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: unnecessary
if_key_exists: fail
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp

View File

@ -0,0 +1,26 @@
# https://help.github.com/en/articles/workflow-syntax-for-github-actions
name: Docker container (Alpine Linux)
on:
- push
jobs:
verify:
name: Verify
strategy:
fail-fast: false
matrix:
os:
- ubuntu-20.04
- ubuntu-22.04
docker_image:
- alpine:3.10
- alpine:3.11
- alpine:3.12
- alpine:3.13
uses: "./.github/workflows/reusable-verify.yml"
with:
os: ${{ matrix.os }}
docker_image: ${{ matrix.docker_image }}
package_installation_command: apk add openssh-client git
secrets: inherit

View File

@ -1,95 +1,23 @@
# https://help.github.com/en/articles/workflow-syntax-for-github-actions
name: Docker container (CentOS)
on:
- push
jobs:
ssh-pem:
name: Connect to github.com (PEM format)
runs-on: ${{ matrix.os }}
container: ${{ matrix.container }}
verify:
name: Verify
strategy:
fail-fast: false
matrix:
os:
- ubuntu-16.04
- ubuntu-18.04
- ubuntu-20.04
container:
- centos:7
- centos:8
fail-fast: false
steps:
- name: Install packages
run: |
yum install -y git openssh-clients
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls -l /root/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-pkcs8:
name: Connect to github.com (PKCS8 format)
runs-on: ${{ matrix.os }}
container: ${{ matrix.container }}
strategy:
matrix:
os:
- ubuntu-16.04
- ubuntu-18.04
- ubuntu-20.04
container:
- centos:7
- centos:8
fail-fast: false
steps:
- name: Install packages
run: |
yum install -y git openssh-clients
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PKCS8 }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls -l /root/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-rfc4716:
name: Connect to github.com (RFC4716 format)
runs-on: ${{ matrix.os }}
container: ${{ matrix.container }}
strategy:
matrix:
os:
- ubuntu-16.04
- ubuntu-18.04
- ubuntu-20.04
container:
- centos:7
- centos:8
fail-fast: false
steps:
- name: Install packages
run: |
yum install -y git openssh-clients
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_RFC4716 }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls -l /root/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
- ubuntu-22.04
docker_image:
- quay.io/centos/centos:stream8
uses: "./.github/workflows/reusable-verify.yml"
with:
os: ${{ matrix.os }}
docker_image: ${{ matrix.docker_image }}
package_installation_command: yum install -y git openssh-clients
secrets: inherit

View File

@ -1,101 +1,26 @@
# https://help.github.com/en/articles/workflow-syntax-for-github-actions
name: Docker container (Ubuntu)
on:
- push
jobs:
ssh-pem:
name: Connect to github.com (PEM format)
runs-on: ${{ matrix.os }}
container: ${{ matrix.container }}
verify:
name: Verify
strategy:
fail-fast: false
matrix:
os:
- ubuntu-16.04
- ubuntu-18.04
- ubuntu-20.04
container:
- ubuntu:16.04
- ubuntu:18.04
- ubuntu-22.04
docker_image:
- ubuntu:20.04
fail-fast: false
steps:
- name: Install packages
run: |
- ubuntu:22.04
uses: "./.github/workflows/reusable-verify.yml"
with:
os: ${{ matrix.os }}
docker_image: ${{ matrix.docker_image }}
package_installation_command: |
apt update
apt -y install openssh-client git
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls -l /root/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-pkcs8:
name: Connect to github.com (PKCS8 format)
runs-on: ${{ matrix.os }}
container: ${{ matrix.container }}
strategy:
matrix:
os:
- ubuntu-16.04
- ubuntu-18.04
- ubuntu-20.04
container:
- ubuntu:16.04
- ubuntu:18.04
- ubuntu:20.04
fail-fast: false
steps:
- name: Install packages
run: |
apt update
apt -y install openssh-client git
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PKCS8 }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls -l /root/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-rfc4716:
name: Connect to github.com (RFC4716 format)
runs-on: ${{ matrix.os }}
container: ${{ matrix.container }}
strategy:
matrix:
os:
- ubuntu-16.04
- ubuntu-18.04
- ubuntu-20.04
container:
- ubuntu:16.04
- ubuntu:18.04
- ubuntu:20.04
fail-fast: false
steps:
- name: Install packages
run: |
apt update
apt -y install openssh-client git
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_RFC4716 }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls -l /root/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
apt install -y openssh-client git
secrets: inherit

View File

@ -1,74 +0,0 @@
# https://help.github.com/en/articles/workflow-syntax-for-github-actions
name: macOS Catalina
on:
- push
jobs:
ssh-pem:
name: Connect to github.com (PEM format)
runs-on: macos-10.15
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls -l ~/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-pkcs8:
name: Connect to github.com (PKCS8 format)
runs-on: macos-10.15
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PKCS8 }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls -l ~/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-rfc4716:
name: Connect to github.com (RFC4716 format)
runs-on: macos-10.15
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_RFC4716 }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls -l ~/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-with-name:
name: Connect to github.com with name and config
runs-on: macos-10.15
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
name: ssh_key_name # optional
config: | # optional
Host github
Hostname github.com
User git
IdentityFile ~/.ssh/ssh_key_name
- name: print created files
run: ls -l ~/.ssh
- name: git clone through SSH
run: git clone github:shimataro/ssh-key-action.git tmp

19
.github/workflows/verify-on-macos.yml vendored Normal file
View File

@ -0,0 +1,19 @@
# https://help.github.com/en/articles/workflow-syntax-for-github-actions
name: macOS
on:
- push
jobs:
verify:
name: Verify
strategy:
fail-fast: false
matrix:
os:
- macos-11
- macos-12
uses: "./.github/workflows/reusable-verify.yml"
with:
os: ${{ matrix.os }}
secrets: inherit

View File

@ -1,74 +0,0 @@
# https://help.github.com/en/articles/workflow-syntax-for-github-actions
name: Ubuntu 16.04
on:
- push
jobs:
ssh-pem:
name: Connect to github.com (PEM format)
runs-on: ubuntu-16.04
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls -l ~/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-pkcs8:
name: Connect to github.com (PKCS8 format)
runs-on: ubuntu-16.04
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PKCS8 }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls -l ~/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-rfc4716:
name: Connect to github.com (RFC4716 format)
runs-on: ubuntu-16.04
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_RFC4716 }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls -l ~/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-with-name:
name: Connect to github.com with name and config
runs-on: ubuntu-16.04
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
name: ssh_key_name # optional
config: | # optional
Host github
Hostname github.com
User git
IdentityFile ~/.ssh/ssh_key_name
- name: print created files
run: ls -l ~/.ssh
- name: git clone through SSH
run: git clone github:shimataro/ssh-key-action.git tmp

View File

@ -1,74 +0,0 @@
# https://help.github.com/en/articles/workflow-syntax-for-github-actions
name: Ubuntu 18.04
on:
- push
jobs:
ssh-pem:
name: Connect to github.com (PEM format)
runs-on: ubuntu-18.04
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls -l ~/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-pkcs8:
name: Connect to github.com (PKCS8 format)
runs-on: ubuntu-18.04
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PKCS8 }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls -l ~/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-rfc4716:
name: Connect to github.com (RFC4716 format)
runs-on: ubuntu-18.04
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_RFC4716 }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls -l ~/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-with-name:
name: Connect to github.com with name and config
runs-on: ubuntu-18.04
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
name: ssh_key_name # optional
config: | # optional
Host github
Hostname github.com
User git
IdentityFile ~/.ssh/ssh_key_name
- name: print created files
run: ls -l ~/.ssh
- name: git clone through SSH
run: git clone github:shimataro/ssh-key-action.git tmp

View File

@ -1,74 +0,0 @@
# https://help.github.com/en/articles/workflow-syntax-for-github-actions
name: Ubuntu 20.04
on:
- push
jobs:
ssh-pem:
name: Connect to github.com (PEM format)
runs-on: ubuntu-20.04
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls -l ~/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-pkcs8:
name: Connect to github.com (PKCS8 format)
runs-on: ubuntu-20.04
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PKCS8 }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls -l ~/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-rfc4716:
name: Connect to github.com (RFC4716 format)
runs-on: ubuntu-20.04
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_RFC4716 }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls -l ~/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-with-name:
name: Connect to github.com with name and config
runs-on: ubuntu-20.04
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
name: ssh_key_name # optional
config: | # optional
Host github
Hostname github.com
User git
IdentityFile ~/.ssh/ssh_key_name
- name: print created files
run: ls -l ~/.ssh
- name: git clone through SSH
run: git clone github:shimataro/ssh-key-action.git tmp

19
.github/workflows/verify-on-ubuntu.yml vendored Normal file
View File

@ -0,0 +1,19 @@
# https://help.github.com/en/articles/workflow-syntax-for-github-actions
name: Ubuntu
on:
- push
jobs:
verify:
name: Verify
strategy:
fail-fast: false
matrix:
os:
- ubuntu-20.04
- ubuntu-22.04
uses: "./.github/workflows/reusable-verify.yml"
with:
os: ${{ matrix.os }}
secrets: inherit

View File

@ -1,74 +0,0 @@
# https://help.github.com/en/articles/workflow-syntax-for-github-actions
name: Windows Server 2019
on:
- push
jobs:
ssh-pem:
name: Connect to github.com (PEM format)
runs-on: windows-2019
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls ~/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-pkcs8:
name: Connect to github.com (PKCS8 format)
runs-on: windows-2019
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PKCS8 }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls ~/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-rfc4716:
name: Connect to github.com (RFC4716 format)
runs-on: windows-2019
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_RFC4716 }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: print created files
run: ls ~/.ssh
- name: git clone through SSH
run: git clone git@github.com:shimataro/ssh-key-action.git tmp
ssh-with-name:
name: Connect to github.com with name and config
runs-on: windows-2019
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
key: ${{ secrets.SSH_KEY_PEM }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
name: ssh_key_name # optional
config: | # optional
Host github
Hostname github.com
User git
IdentityFile ~/.ssh/ssh_key_name
- name: print created files
run: ls -l ~/.ssh
- name: git clone through SSH
run: git clone github:shimataro/ssh-key-action.git tmp

19
.github/workflows/verify-on-windows.yml vendored Normal file
View File

@ -0,0 +1,19 @@
# https://help.github.com/en/articles/workflow-syntax-for-github-actions
name: Windows
on:
- push
jobs:
verify:
name: Verify
strategy:
fail-fast: false
matrix:
os:
- windows-2019
- windows-2022
uses: "./.github/workflows/reusable-verify.yml"
with:
os: ${{ matrix.os }}
secrets: inherit

3
.gitignore vendored
View File

@ -13,5 +13,8 @@ Thumbs.db
*.orig
*.rej
# IDE
/.idea/
# Node.js modules
/node_modules/

View File

@ -1,7 +1,7 @@
MD007: # ul-indent
indent: 4
MD013: # line-length
line_length: 255
line_length: 1024
MD024: # no-duplicate-heading
siblings_only: true
MD026: false # no-trailing-punctuation

View File

@ -7,6 +7,74 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased]
## [2.7.0] - 2024-02-11
### Others
* Update to Node.js v20 (thanks [@princemaple](https://github.com/princemaple))
* drop old containers; Ubuntu 16.04, and CentOS 7
## [2.6.1] - 2023-10-13
### Fixed
* JSON parse error on exit, if `if_key_exists`=`fail` and key exists
## [2.6.0] - 2023-10-11
### Others
* back up and restore files when exist (thanks [@bambeusz](https://github.com/bambeusz))
* remove `macos-10.15` and `ubuntu-18.04` virtual environment
## [2.5.1] - 2023-03-25
### Hotfix
* update github.com key: <https://github.blog/2023-03-23-we-updated-our-rsa-ssh-host-key/> (thanks [@phlax](https://github.com/phlax))
## [2.5.0] - 2022-12-24
### Added
* remove SSH directory at the end of workflow
## [2.4.0] - 2022-11-03
### Added
* always set server key of `github.com` to `known_hosts`
### Fixed
* usage of `rsync` in README
### Others
* add `windows-2022`, and `macos-11` (thanks [@ViacheslavKudinov](https://github.com/ViacheslavKudinov))
* add `macos-12`, `ubuntu-22.04`, and `CentOS 8 Stream (Docker container)`
* drop `ubuntu-16.04`, and `CentOS 8 (Docker container)`
* [update Node.js version to 16](https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/) (thanks [@duddu](https://github.com/duddu))
## [2.3.1] - 2021-08-01
### Security
* Fix [CVE-2021-33502](https://github.com/advisories/GHSA-px4h-xg32-q955)
### Others
* add `windows-2016` virtual environment
* [remove `ubuntu-16.04` virtual environment](https://github.blog/changelog/2021-04-29-github-actions-ubuntu-16-04-lts-virtual-environment-will-be-removed-on-september-20-2021/)
## [2.3.0] - 2021-03-21
### Added
* `if_key_exists` parameter
* `known_hosts: unnecessary`
* Support Alpine Linux Docker container
## [2.2.0] - 2021-02-27
### Added
@ -138,7 +206,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
* First release.
[Unreleased]: https://github.com/shimataro/ssh-key-action/compare/v2.2.0...HEAD
[Unreleased]: https://github.com/shimataro/ssh-key-action/compare/v2.7.0...HEAD
[2.7.0]: https://github.com/shimataro/ssh-key-action/compare/v2.6.1...v2.7.0
[2.6.1]: https://github.com/shimataro/ssh-key-action/compare/v2.6.0...v2.6.1
[2.6.0]: https://github.com/shimataro/ssh-key-action/compare/v2.5.1...v2.6.0
[2.5.1]: https://github.com/shimataro/ssh-key-action/compare/v2.5.0...v2.5.1
[2.5.0]: https://github.com/shimataro/ssh-key-action/compare/v2.4.0...v2.5.0
[2.4.0]: https://github.com/shimataro/ssh-key-action/compare/v2.3.1...v2.4.0
[2.3.1]: https://github.com/shimataro/ssh-key-action/compare/v2.3.0...v2.3.1
[2.3.0]: https://github.com/shimataro/ssh-key-action/compare/v2.2.0...v2.3.0
[2.2.0]: https://github.com/shimataro/ssh-key-action/compare/v2.1.0...v2.2.0
[2.1.0]: https://github.com/shimataro/ssh-key-action/compare/v2.0.3...v2.1.0
[2.0.3]: https://github.com/shimataro/ssh-key-action/compare/v2.0.2...v2.0.3

View File

@ -1,13 +1,12 @@
# Install SSH Key
[![Build][image-build]][link-build]
[![Windows Server 2019][image-verify-windows-2019]][link-verify-windows-2019]
[![macOS Catalina][image-verify-macos-1015]][link-verify-macos-1015]
[![Ubuntu 20.04][image-verify-ubuntu-2004]][link-verify-ubuntu-2004]
[![Ubuntu 18.04][image-verify-ubuntu-1804]][link-verify-ubuntu-1804]
[![Ubuntu 16.04][image-verify-ubuntu-1604]][link-verify-ubuntu-1604]
[![Windows][image-verify-windows]][link-verify-windows]
[![macOS][image-verify-macos]][link-verify-macos]
[![Ubuntu][image-verify-ubuntu]][link-verify-ubuntu]
[![Docker container (Ubuntu)][image-verify-docker-container-ubuntu]][link-verify-docker-container-ubuntu]
[![Docker container (CentOS)][image-verify-docker-container-centos]][link-verify-docker-container-centos]
[![Docker container (Alpine Linux)][image-verify-docker-container-alpine]][link-verify-docker-container-alpine]
[![Release][image-release]][link-release]
[![License][image-license]][link-license]
[![Stars][image-stars]][link-stars]
@ -18,9 +17,10 @@ Useful for SCP, SFTP, and `rsync` over SSH in deployment script.
tested on:
* [all available virtual machines](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners#supported-runners-and-hardware-resources) (Windows Server 2019, macOS Catalina, and Ubuntu 20.04/18.04/16.04)
* [Docker container (Ubuntu)](https://hub.docker.com/_/ubuntu) / requires `openssh-client` package
* [Docker container (CentOS)](https://hub.docker.com/_/centos) / requires `openssh-clients` package
* [all available virtual machines](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners#supported-runners-and-hardware-resources) (Windows Server 2022/2019, macOS Monterey/Big Sur, and Ubuntu 22.04/20.04)
* [Docker container (Ubuntu)](https://hub.docker.com/_/ubuntu) / requires `openssh-client` package; `apt install -y openssh-client`
* [Docker container (CentOS)](https://quay.io/repository/centos/centos) / requires `openssh-clients` package; `yum install -y openssh-clients`
* [Docker container (Alpine Linux)](https://hub.docker.com/_/alpine) / requires `openssh-client` package; `apk add openssh-client`
## Usage
@ -38,18 +38,24 @@ steps:
name: id_rsa # optional
known_hosts: ${{ secrets.KNOWN_HOSTS }}
config: ${{ secrets.CONFIG }} # ssh_config; optional
- name: rsync over ssh
run: rsync ./foo/ user@remote:bar/
if_key_exists: fail # replace / ignore / fail; optional (defaults to fail)
- name: rsync over SSH
run: rsync -r ./foo/ user@remote:bar/
```
See [Workflow syntax for GitHub Actions](https://help.github.com/en/articles/workflow-syntax-for-github-actions) for details.
**NOTE:**
* Server key of `github.com` will be always set to `known_hosts`.
* SSH keys will be removed at the end of workflow.
### Install multiple keys
If you want to install multiple keys, call this action multiple times.
It is useful for port forwarding.
**NOTE:** When this action is called multiple times, **the contents of `known_hosts` and `config` will be appended**. `key` must be saved as different name, by using `name` option.
**NOTE:** When this action is called multiple times, **the contents of `known_hosts` and `config` will be appended**. `key` must be saved as different name, by using `name` option.
```yaml
runs-on: ubuntu-latest
@ -90,6 +96,14 @@ Check below:
* `Host key verification failed.`:
* Set `known_hosts` parameter correctly (use `ssh-keyscan` command).
### I want to replace/ignore key if exists.
Use `if_key_exists` parameter.
* `replace`: replaces key
* `ignore`: does nothing
* `fail`: fails (default)
### How do I use encrypted SSH key?
This action doesn't support encrypted key directly.
@ -105,7 +119,7 @@ Here are some solutions:
I recommend **rsync via bastion**.
```bash
rsync -e "ssh bastion ssh" ./foo/ target:bar/
rsync -r -e "ssh bastion ssh" ./foo/ target:bar/
```
It has some advantages over other methods:
@ -124,6 +138,18 @@ It has some advantages over other methods:
* And will be updated continuously.
* if security incident ―e.g., private key leaked― occurs, it's OK just to remove `authorized_keys` on bastion.
### I want to omit `known_hosts`.
First of all, you have to understand that it is NOT secure to SSH with no `known_hosts` and using `StrictHostKeyChecking=no` option.
Why do you want to omit it?
If the reason is **"I'm not understanding about the function of `known_hosts`"** or **"It's bother to fetch server key"**, you should not omit.
If **"It is hard to prefetch server key because the server will be created dynamically"**, you can use bastion server.
**"`known_hosts` is unnecessary because I'm using secure method for SSH, such as SSHFP and signed server key."** — OK, here is a special value to omit `known_hosts`.
You should use it ONLY IF you are using secure methods...
It is `known_hosts: unnecessary`.
## License
The scripts and documentation in this project are released under the [MIT License](LICENSE)
@ -134,20 +160,18 @@ See [CHANGELOG.md](CHANGELOG.md).
[image-build]: https://github.com/shimataro/ssh-key-action/workflows/Build/badge.svg?event=push&branch=v2
[link-build]: https://github.com/shimataro/ssh-key-action/actions/workflows/build.yml
[image-verify-windows-2019]: https://github.com/shimataro/ssh-key-action/workflows/Windows%20Server%202019/badge.svg?event=push&branch=v2
[link-verify-windows-2019]: https://github.com/shimataro/ssh-key-action/actions/workflows/verify-on-windows-server-2019.yml
[image-verify-macos-1015]: https://github.com/shimataro/ssh-key-action/workflows/macOS%20Catalina/badge.svg?event=push&branch=v2
[link-verify-macos-1015]: https://github.com/shimataro/ssh-key-action/actions/workflows/verify-on-macos-1015.yml
[image-verify-ubuntu-2004]: https://github.com/shimataro/ssh-key-action/workflows/Ubuntu%2020.04/badge.svg?event=push&branch=v2
[link-verify-ubuntu-2004]: https://github.com/shimataro/ssh-key-action/actions/workflows/verify-on-ubuntu-2004.yml
[image-verify-ubuntu-1804]: https://github.com/shimataro/ssh-key-action/workflows/Ubuntu%2018.04/badge.svg?event=push&branch=v2
[link-verify-ubuntu-1804]: https://github.com/shimataro/ssh-key-action/actions/workflows/verify-on-ubuntu-1804.yml
[image-verify-ubuntu-1604]: https://github.com/shimataro/ssh-key-action/workflows/Ubuntu%2016.04/badge.svg?event=push&branch=v2
[link-verify-ubuntu-1604]: https://github.com/shimataro/ssh-key-action/actions/workflows/verify-on-ubuntu-1604.yml
[image-verify-windows]: https://github.com/shimataro/ssh-key-action/workflows/Windows/badge.svg?event=push&branch=v2
[link-verify-windows]: https://github.com/shimataro/ssh-key-action/actions/workflows/verify-on-windows.yml
[image-verify-macos]: https://github.com/shimataro/ssh-key-action/workflows/macOS/badge.svg?event=push&branch=v2
[link-verify-macos]: https://github.com/shimataro/ssh-key-action/actions/workflows/verify-on-macos.yml
[image-verify-ubuntu]: https://github.com/shimataro/ssh-key-action/workflows/Ubuntu/badge.svg?event=push&branch=v2
[link-verify-ubuntu]: https://github.com/shimataro/ssh-key-action/actions/workflows/verify-on-ubuntu.yml
[image-verify-docker-container-ubuntu]: https://github.com/shimataro/ssh-key-action/actions/workflows/verify-on-container-ubuntu.yml/badge.svg?event=push&branch=v2
[link-verify-docker-container-ubuntu]: https://github.com/shimataro/ssh-key-action/actions/workflows/verify-on-container-ubuntu.yml
[image-verify-docker-container-centos]: https://github.com/shimataro/ssh-key-action/actions/workflows/verify-on-container-centos.yml/badge.svg?event=push&branch=v2
[link-verify-docker-container-centos]: https://github.com/shimataro/ssh-key-action/actions/workflows/verify-on-container-centos.yml
[image-verify-docker-container-alpine]: https://github.com/shimataro/ssh-key-action/actions/workflows/verify-on-container-alpine.yml/badge.svg?event=push&branch=v2
[link-verify-docker-container-alpine]: https://github.com/shimataro/ssh-key-action/actions/workflows/verify-on-container-alpine.yml
[image-release]: https://img.shields.io/github/release/shimataro/ssh-key-action.svg
[link-release]: https://github.com/shimataro/ssh-key-action/releases
[image-license]: https://img.shields.io/github/license/shimataro/ssh-key-action.svg

View File

@ -21,6 +21,11 @@ inputs:
description: "SSH config"
required: false
default: ""
if_key_exists:
description: "replace / ignore / fail"
required: false
default: "fail"
runs:
using: "node12"
main: "lib/index.js"
using: "node20"
main: "./dist/main.js"
post: "./dist/post.js"

74
dist/main.js vendored Normal file

File diff suppressed because one or more lines are too long

7
dist/main.js.map vendored Normal file

File diff suppressed because one or more lines are too long

69
dist/post.js vendored Normal file

File diff suppressed because one or more lines are too long

7
dist/post.js.map vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,593 +0,0 @@
module.exports =
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ 351:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const os = __importStar(__nccwpck_require__(87));
const utils_1 = __nccwpck_require__(278);
/**
* Commands
*
* Command Format:
* ::name key=value,key=value::message
*
* Examples:
* ::warning::This is the message
* ::set-env name=MY_VAR::some value
*/
function issueCommand(command, properties, message) {
const cmd = new Command(command, properties, message);
process.stdout.write(cmd.toString() + os.EOL);
}
exports.issueCommand = issueCommand;
function issue(name, message = '') {
issueCommand(name, {}, message);
}
exports.issue = issue;
const CMD_STRING = '::';
class Command {
constructor(command, properties, message) {
if (!command) {
command = 'missing.command';
}
this.command = command;
this.properties = properties;
this.message = message;
}
toString() {
let cmdStr = CMD_STRING + this.command;
if (this.properties && Object.keys(this.properties).length > 0) {
cmdStr += ' ';
let first = true;
for (const key in this.properties) {
if (this.properties.hasOwnProperty(key)) {
const val = this.properties[key];
if (val) {
if (first) {
first = false;
}
else {
cmdStr += ',';
}
cmdStr += `${key}=${escapeProperty(val)}`;
}
}
}
}
cmdStr += `${CMD_STRING}${escapeData(this.message)}`;
return cmdStr;
}
}
function escapeData(s) {
return utils_1.toCommandValue(s)
.replace(/%/g, '%25')
.replace(/\r/g, '%0D')
.replace(/\n/g, '%0A');
}
function escapeProperty(s) {
return utils_1.toCommandValue(s)
.replace(/%/g, '%25')
.replace(/\r/g, '%0D')
.replace(/\n/g, '%0A')
.replace(/:/g, '%3A')
.replace(/,/g, '%2C');
}
//# sourceMappingURL=command.js.map
/***/ }),
/***/ 186:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const command_1 = __nccwpck_require__(351);
const file_command_1 = __nccwpck_require__(717);
const utils_1 = __nccwpck_require__(278);
const os = __importStar(__nccwpck_require__(87));
const path = __importStar(__nccwpck_require__(622));
/**
* The code to exit an action
*/
var ExitCode;
(function (ExitCode) {
/**
* A code indicating that the action was successful
*/
ExitCode[ExitCode["Success"] = 0] = "Success";
/**
* A code indicating that the action was a failure
*/
ExitCode[ExitCode["Failure"] = 1] = "Failure";
})(ExitCode = exports.ExitCode || (exports.ExitCode = {}));
//-----------------------------------------------------------------------
// Variables
//-----------------------------------------------------------------------
/**
* Sets env variable for this action and future actions in the job
* @param name the name of the variable to set
* @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function exportVariable(name, val) {
const convertedVal = utils_1.toCommandValue(val);
process.env[name] = convertedVal;
const filePath = process.env['GITHUB_ENV'] || '';
if (filePath) {
const delimiter = '_GitHubActionsFileCommandDelimeter_';
const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`;
file_command_1.issueCommand('ENV', commandValue);
}
else {
command_1.issueCommand('set-env', { name }, convertedVal);
}
}
exports.exportVariable = exportVariable;
/**
* Registers a secret which will get masked from logs
* @param secret value of the secret
*/
function setSecret(secret) {
command_1.issueCommand('add-mask', {}, secret);
}
exports.setSecret = setSecret;
/**
* Prepends inputPath to the PATH (for this action and future actions)
* @param inputPath
*/
function addPath(inputPath) {
const filePath = process.env['GITHUB_PATH'] || '';
if (filePath) {
file_command_1.issueCommand('PATH', inputPath);
}
else {
command_1.issueCommand('add-path', {}, inputPath);
}
process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`;
}
exports.addPath = addPath;
/**
* Gets the value of an input. The value is also trimmed.
*
* @param name name of the input to get
* @param options optional. See InputOptions.
* @returns string
*/
function getInput(name, options) {
const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || '';
if (options && options.required && !val) {
throw new Error(`Input required and not supplied: ${name}`);
}
return val.trim();
}
exports.getInput = getInput;
/**
* Sets the value of an output.
*
* @param name name of the output to set
* @param value value to store. Non-string values will be converted to a string via JSON.stringify
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function setOutput(name, value) {
command_1.issueCommand('set-output', { name }, value);
}
exports.setOutput = setOutput;
/**
* Enables or disables the echoing of commands into stdout for the rest of the step.
* Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set.
*
*/
function setCommandEcho(enabled) {
command_1.issue('echo', enabled ? 'on' : 'off');
}
exports.setCommandEcho = setCommandEcho;
//-----------------------------------------------------------------------
// Results
//-----------------------------------------------------------------------
/**
* Sets the action status to failed.
* When the action exits it will be with an exit code of 1
* @param message add error issue message
*/
function setFailed(message) {
process.exitCode = ExitCode.Failure;
error(message);
}
exports.setFailed = setFailed;
//-----------------------------------------------------------------------
// Logging Commands
//-----------------------------------------------------------------------
/**
* Gets whether Actions Step Debug is on or not
*/
function isDebug() {
return process.env['RUNNER_DEBUG'] === '1';
}
exports.isDebug = isDebug;
/**
* Writes debug message to user log
* @param message debug message
*/
function debug(message) {
command_1.issueCommand('debug', {}, message);
}
exports.debug = debug;
/**
* Adds an error issue
* @param message error issue message. Errors will be converted to string via toString()
*/
function error(message) {
command_1.issue('error', message instanceof Error ? message.toString() : message);
}
exports.error = error;
/**
* Adds an warning issue
* @param message warning issue message. Errors will be converted to string via toString()
*/
function warning(message) {
command_1.issue('warning', message instanceof Error ? message.toString() : message);
}
exports.warning = warning;
/**
* Writes info to log with console.log.
* @param message info message
*/
function info(message) {
process.stdout.write(message + os.EOL);
}
exports.info = info;
/**
* Begin an output group.
*
* Output until the next `groupEnd` will be foldable in this group
*
* @param name The name of the output group
*/
function startGroup(name) {
command_1.issue('group', name);
}
exports.startGroup = startGroup;
/**
* End an output group.
*/
function endGroup() {
command_1.issue('endgroup');
}
exports.endGroup = endGroup;
/**
* Wrap an asynchronous function call in a group.
*
* Returns the same type as the function itself.
*
* @param name The name of the group
* @param fn The function to wrap in the group
*/
function group(name, fn) {
return __awaiter(this, void 0, void 0, function* () {
startGroup(name);
let result;
try {
result = yield fn();
}
finally {
endGroup();
}
return result;
});
}
exports.group = group;
//-----------------------------------------------------------------------
// Wrapper action state
//-----------------------------------------------------------------------
/**
* Saves state for current action, the state can only be retrieved by this action's post job execution.
*
* @param name name of the state to store
* @param value value to store. Non-string values will be converted to a string via JSON.stringify
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function saveState(name, value) {
command_1.issueCommand('save-state', { name }, value);
}
exports.saveState = saveState;
/**
* Gets the value of an state set by this action's main execution.
*
* @param name name of the state to get
* @returns string
*/
function getState(name) {
return process.env[`STATE_${name}`] || '';
}
exports.getState = getState;
//# sourceMappingURL=core.js.map
/***/ }),
/***/ 717:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
// For internal use, subject to change.
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
// We use any as a valid input type
/* eslint-disable @typescript-eslint/no-explicit-any */
const fs = __importStar(__nccwpck_require__(747));
const os = __importStar(__nccwpck_require__(87));
const utils_1 = __nccwpck_require__(278);
function issueCommand(command, message) {
const filePath = process.env[`GITHUB_${command}`];
if (!filePath) {
throw new Error(`Unable to find environment variable for file command ${command}`);
}
if (!fs.existsSync(filePath)) {
throw new Error(`Missing file at path: ${filePath}`);
}
fs.appendFileSync(filePath, `${utils_1.toCommandValue(message)}${os.EOL}`, {
encoding: 'utf8'
});
}
exports.issueCommand = issueCommand;
//# sourceMappingURL=file-command.js.map
/***/ }),
/***/ 278:
/***/ ((__unused_webpack_module, exports) => {
// We use any as a valid input type
/* eslint-disable @typescript-eslint/no-explicit-any */
Object.defineProperty(exports, "__esModule", ({ value: true }));
/**
* Sanitizes an input into a string so it can be passed into issueCommand safely
* @param input input to sanitize into a string
*/
function toCommandValue(input) {
if (input === null || input === undefined) {
return '';
}
else if (typeof input === 'string' || input instanceof String) {
return input;
}
return JSON.stringify(input);
}
exports.toCommandValue = toCommandValue;
//# sourceMappingURL=utils.js.map
/***/ }),
/***/ 399:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const fs_1 = __importDefault(__nccwpck_require__(747));
const path_1 = __importDefault(__nccwpck_require__(622));
const core = __importStar(__nccwpck_require__(186));
/**
* main function
*/
function main() {
try {
const files = [
{
name: core.getInput("name"),
contents: insertLf(core.getInput("key", {
required: true,
}), false, true),
options: {
mode: 0o400,
flag: "ax",
},
},
{
name: "known_hosts",
contents: insertLf(core.getInput("known_hosts", {
required: true,
}), true, true),
options: {
mode: 0o644,
flag: "a",
},
},
{
name: "config",
contents: insertLf(core.getInput("config"), true, true),
options: {
mode: 0o644,
flag: "a",
},
},
];
// create ".ssh" directory
const home = getHomeDirectory();
const dirName = path_1.default.resolve(home, ".ssh");
fs_1.default.mkdirSync(dirName, {
recursive: true,
mode: 0o700,
});
// create files
for (const file of files) {
const fileName = path_1.default.join(dirName, file.name);
fs_1.default.writeFileSync(fileName, file.contents, file.options);
}
console.log(`SSH key has been stored to ${dirName} successfully.`);
}
catch (err) {
core.setFailed(err.message);
}
}
/**
* get home directory
* @returns home directory
*/
function getHomeDirectory() {
const homeEnv = getHomeEnv();
const home = process.env[homeEnv];
if (home === undefined) {
throw Error(`${homeEnv} is not defined`);
}
if (home === "/github/home") {
// Docker container
return "/root";
}
return home;
}
/**
* get HOME environment name
* @returns HOME environment name
*/
function getHomeEnv() {
if (process.platform === "win32") {
// Windows
return "USERPROFILE";
}
// macOS / Linux
return "HOME";
}
/**
* prepend/append LF to value if not empty
* @param value the value to insert LF
* @param prepend true to prepend
* @param append true to append
* @returns new value
*/
function insertLf(value, prepend, append) {
let affectedValue = value;
if (value.length === 0) {
// do nothing if empty
return "";
}
if (prepend && !affectedValue.startsWith("\n")) {
affectedValue = `\n${affectedValue}`;
}
if (append && !affectedValue.endsWith("\n")) {
affectedValue = `${affectedValue}\n`;
}
return affectedValue;
}
main();
/***/ }),
/***/ 747:
/***/ ((module) => {
module.exports = require("fs");;
/***/ }),
/***/ 87:
/***/ ((module) => {
module.exports = require("os");;
/***/ }),
/***/ 622:
/***/ ((module) => {
module.exports = require("path");;
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __nccwpck_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(__webpack_module_cache__[moduleId]) {
/******/ return __webpack_module_cache__[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ var threw = true;
/******/ try {
/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __nccwpck_require__);
/******/ threw = false;
/******/ } finally {
/******/ if(threw) delete __webpack_module_cache__[moduleId];
/******/ }
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat */
/******/
/******/ __nccwpck_require__.ab = __dirname + "/";/************************************************************************/
/******/ // module exports must be returned from runtime so entry inlining is disabled
/******/ // startup
/******/ // Load entry module and return exports
/******/ return __nccwpck_require__(399);
/******/ })()
;

12221
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,19 @@
{
"name": "install-ssh-key",
"version": "2.2.0",
"version": "2.7.0",
"private": true,
"description": "Install SSH key in .ssh",
"main": "lib/index.js",
"main": "./dist/main.js",
"engines": {
"node": ">=8.0.0",
"npm": ">=5.7.0"
},
"scripts": {
"build": "ncc build src/main.ts -o lib",
"build": "esbuild ./src/main.ts ./src/post.ts --bundle --platform=node --minify --sourcemap --outdir=./dist",
"check-updates": "ncu",
"lint": "run-p lint:*",
"lint:ts": "eslint ./src --ext .ts",
"lint:es": "eslint ./src --ext .ts",
"lint:ts": "tsc --noEmit ./src/main.ts ./src/post.ts",
"lint:md": "markdownlint . --ignore node_modules --ignore examples",
"lint:yaml": "yamllint **/{,.}*.{yml,yaml} --ignore=node_modules/**",
"verify": "run-p lint"
@ -31,16 +32,16 @@
"author": "shimataro",
"license": "MIT",
"devDependencies": {
"@actions/core": "1.2.6",
"@types/node": "14.14.31",
"@typescript-eslint/eslint-plugin": "4.15.2",
"@typescript-eslint/parser": "4.15.2",
"@vercel/ncc": "0.27.0",
"eslint": "7.20.0",
"markdownlint-cli": "0.26.0",
"npm-check-updates": "11.1.9",
"@actions/core": "1.10.1",
"@types/node": "20.11.17",
"@typescript-eslint/eslint-plugin": "6.21.0",
"@typescript-eslint/parser": "6.21.0",
"esbuild": "0.20.0",
"eslint": "8.56.0",
"markdownlint-cli": "0.39.0",
"npm-check-updates": "16.14.15",
"npm-run-all": "4.1.5",
"typescript": "4.2.2",
"yaml-lint": "1.2.4"
"typescript": "5.3.3",
"yaml-lint": "1.7.0"
}
}

View File

@ -1,135 +0,0 @@
#!/bin/bash
# requires following packages:
# - git; I believe you have already installed.
# - sed; GNU sed is preferred. POSIX sed may not work.
# - perl; Already installed on most of unix system.
set -eu
BASE_BRANCH="develop"
PACKAGE_NAME="ssh-key-action"
URL_PRODUCT="https://github.com/shimataro/${PACKAGE_NAME}"
URL_REPOSITORY="${URL_PRODUCT}.git"
URL_COMPARE="${URL_PRODUCT}/compare"
URL_RELEASE="${URL_PRODUCT}/releases/new"
COLOR_ERROR="\e[1;41m"
COLOR_SECTION="\e[1;34m"
COLOR_COMMAND_NAME="\e[1;34m"
COLOR_OPTION="\e[4;36m"
COLOR_COMMAND="\e[4m"
COLOR_FILE="\e[1;34m"
COLOR_BRANCH="\e[1;31m"
COLOR_INPUT="\e[1;31m"
COLOR_SELECT="\e[1;32m"
COLOR_RESET="\e[m"
function main() {
cd $(dirname ${0})/..
if [ $# -lt 1 ]; then
usage
fi
local VERSION=$1
local BRANCH="release/v${VERSION}"
local TAG="v${VERSION}"
check_version_format ${VERSION}
check_current_branch
create_branch ${BRANCH}
./scripts/prepare-release.sh ${VERSION}
finish ${VERSION} ${BRANCH} ${TAG}
}
function usage() {
local COMMAND=`basename ${0}`
echo -e "${COLOR_SECTION}NAME${COLOR_RESET}
${COMMAND} - Create a branch and prepare for new release
${COLOR_SECTION}SYNOPSIS${COLOR_RESET}
${COLOR_COMMAND_NAME}${COMMAND}${COLOR_RESET} <${COLOR_OPTION}new-version${COLOR_RESET}>
${COLOR_SECTION}DESCRIPTION${COLOR_RESET}
This command:
- creates a new branch for release
- updates ${COLOR_FILE}CHANGELOG.md${COLOR_RESET}
- updates package version in ${COLOR_FILE}package.json${COLOR_RESET}
- updates dependencies version in ${COLOR_FILE}package.json${COLOR_RESET}
- verifies
- ...and commits!
${COLOR_OPTION}new-version${COLOR_RESET} must follow \"Semantic Versioning\" <https://semver.org/>.
"
exit 1
}
function check_version_format() {
if [[ $1 =~ ^[0-9]+\.[0-9]+\.[0-9]+ ]]; then
return
fi
echo -e "${COLOR_ERROR}ERROR:${COLOR_RESET} Follow \"Semantic Versioning\" <https://semver.org/> for new version.
" >&2
exit 2
}
function check_current_branch() {
local CURRENT_BRANCH=`git rev-parse --abbrev-ref HEAD`
if [ ${CURRENT_BRANCH} = ${BASE_BRANCH} ]; then
return
fi
echo -e "${COLOR_ERROR}ERROR:${COLOR_RESET} Work on ${COLOR_BRANCH}${BASE_BRANCH}${COLOR_RESET} branch
${COLOR_COMMAND}git checkout ${BASE_BRANCH}${COLOR_RESET}
" >&2
exit 2
}
function create_branch() {
local BRANCH=$1
git checkout -b ${BRANCH} ${BASE_BRANCH}
}
function finish() {
local VERSION=$1
local BRANCH=$2
local TAG=$3
local TARGET_BRANCH="v${VERSION%%[!0-9]*}"
local UPSTREAM="origin"
local CHANGELOG=$(git diff ${UPSTREAM}/${TARGET_BRANCH} ${BRANCH} CHANGELOG.md | sed -e "/^[^+]/d" -e "s/^\+\(.*\)$/\1/" -e "/^## /d" -e "/^\+/d" -e "/^\[/d" -e "s/\s/%20/g" -e "s/#/%23/g" -e 's/\n//g' | perl -pe "s/\n/%0A/g" | perl -pe "s/^(%0A)+//" | perl -pe "s/(%0A)+$//")
echo -e "
Branch ${COLOR_BRANCH}${BRANCH}${COLOR_RESET} has been created.
Remaining processes are...
1. Make sure all changes are correct
${COLOR_COMMAND}git diff ${BASE_BRANCH} ${BRANCH}${COLOR_RESET}
2. Push to remote ${UPSTREAM}
${COLOR_COMMAND}git push --set-upstream ${UPSTREAM} ${BRANCH}${COLOR_RESET}
3. Create a pull-request: ${COLOR_BRANCH}${BRANCH}${COLOR_RESET} to ${COLOR_BRANCH}${BASE_BRANCH}${COLOR_RESET}
${URL_COMPARE}/${BASE_BRANCH}...${BRANCH}?expand=1
select ${COLOR_SELECT}Squash and merge${COLOR_RESET}
4. Create a pull-request: ${COLOR_BRANCH}${BASE_BRANCH}${COLOR_RESET} to ${COLOR_BRANCH}${TARGET_BRANCH}${COLOR_RESET}
${URL_COMPARE}/${TARGET_BRANCH}...${BASE_BRANCH}?expand=1&title=version%20${VERSION}&body=${CHANGELOG}
select ${COLOR_SELECT}Create a merge commit${COLOR_RESET}
5. Create a new release
${URL_RELEASE}?tag=${TAG}&target=${TARGET_BRANCH}&title=${PACKAGE_NAME}%20${VERSION}%20released&body=${CHANGELOG}
Tag version: ${COLOR_INPUT}${TAG}${COLOR_RESET}
Target: ${COLOR_INPUT}${TARGET_BRANCH}${COLOR_RESET}
Release title: ${COLOR_INPUT}${PACKAGE_NAME} ${VERSION} released${COLOR_RESET}
Description this release: (copy and paste CHANGELOG.md)
6. Post processing
${COLOR_COMMAND}git checkout ${BASE_BRANCH}${COLOR_RESET}
${COLOR_COMMAND}git pull${COLOR_RESET}
${COLOR_COMMAND}git fetch -p${COLOR_RESET}
${COLOR_COMMAND}git branch -D ${BRANCH}${COLOR_RESET}
That's all!
"
}
main "$@"

View File

@ -1,40 +1,59 @@
#!/bin/bash
# requires following packages:
# - git; I believe it's already installed.
# - sed; GNU sed is preferred. POSIX sed may not work.
# requires following programs:
# - git; I believe you have already installed.
# - sed; Both GNU sed and POSIX sed will work.
set -eu
COLOR_ERROR="\e[1;41m"
COLOR_SECTION="\e[1;34m"
COLOR_COMMAND_NAME="\e[1;34m"
COLOR_OPTION="\e[4;36m"
COLOR_COMMAND="\e[4m"
COLOR_FILE="\e[1;34m"
COLOR_BRANCH="\e[1;31m"
COLOR_INPUT="\e[1;31m"
COLOR_SELECT="\e[1;32m"
COLOR_RESET="\e[m"
GITHUB_BASE="https://github.com"
GITHUB_USER="shimataro"
GITHUB_REPO="ssh-key-action"
UPSTREAM="origin"
COLOR_ERROR="\033[1;41m"
COLOR_SECTION="\033[1;34m"
COLOR_COMMAND_NAME="\033[1;34m"
COLOR_OPTION="\033[4;36m"
COLOR_COMMAND="\033[4m"
COLOR_FILE="\033[1;34m"
COLOR_BRANCH="\033[1;31m"
COLOR_INPUT="\033[1;31m"
COLOR_SELECT="\033[1;32m"
COLOR_RESET="\033[m"
URL_PRODUCT="${GITHUB_BASE}/${GITHUB_USER}/${GITHUB_REPO}"
URL_REPOSITORY="${URL_PRODUCT}.git"
URL_COMPARE="${URL_PRODUCT}/compare"
URL_RELEASE="${URL_PRODUCT}/releases/new"
function main() {
if [ $# -lt 1 ]; then
cd $(dirname ${0})/..
if [[ $# -lt 1 ]]; then
usage
fi
cd $(dirname ${0})/..
local NEW_VERSION=$1
local CURRENT_VERSION=$(
node -e 'console.log(JSON.parse(require("fs").readFileSync("package.json")).version)'
)
local TAG="v${NEW_VERSION}"
local BRANCH="release/v${NEW_VERSION}"
local BASE_BRANCH="${TAG%%.*}"
local VERSION=$1
check_version_format ${VERSION}
check_version_format ${NEW_VERSION}
check_current_branch ${BASE_BRANCH}
update_changelog ${VERSION}
update_package_version ${VERSION}
update_dependencies_version
regenerate_package_lock
build_package
commit_changes ${VERSION}
create_branch ${BRANCH} ${BASE_BRANCH}
update_package_version ${NEW_VERSION}
update_changelog ${NEW_VERSION}
verify_package
commit_changes ${NEW_VERSION}
finish ${NEW_VERSION} ${CURRENT_VERSION} ${BRANCH} ${BASE_BRANCH} ${TAG}
}
function usage() {
local COMMAND=`basename ${0}`
local COMMAND=$(basename ${0})
echo -e "${COLOR_SECTION}NAME${COLOR_RESET}
${COMMAND} - Prepare for new release
@ -43,12 +62,13 @@ ${COLOR_SECTION}SYNOPSIS${COLOR_RESET}
${COLOR_COMMAND_NAME}${COMMAND}${COLOR_RESET} <${COLOR_OPTION}new-version${COLOR_RESET}>
${COLOR_SECTION}DESCRIPTION${COLOR_RESET}
This command:
- updates ${COLOR_FILE}CHANGELOG.md${COLOR_RESET}
- updates package version in ${COLOR_FILE}package.json${COLOR_RESET}
- updates dependencies version in ${COLOR_FILE}package.json${COLOR_RESET}
- verifies
- ...and commits!
This command will...
- create a new branch for release
- update ${COLOR_FILE}CHANGELOG.md${COLOR_RESET}
- update package version in ${COLOR_FILE}package.json${COLOR_RESET}
- update dependencies version in ${COLOR_FILE}package.json${COLOR_RESET}
- verify
- ...and commit!
${COLOR_OPTION}new-version${COLOR_RESET} must follow \"Semantic Versioning\" <https://semver.org/>.
"
@ -56,7 +76,7 @@ ${COLOR_SECTION}DESCRIPTION${COLOR_RESET}
}
function check_version_format() {
if [[ $1 =~ ^[0-9]+\.[0-9]+\.[0-9]+ ]]; then
if [[ ${1} =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*) ]]; then
return
fi
@ -65,47 +85,118 @@ function check_version_format() {
exit 2
}
function check_current_branch() {
local BASE_BRANCH=$1
local CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [ ${CURRENT_BRANCH} = ${BASE_BRANCH} ]; then
return
fi
echo -e "${COLOR_ERROR}ERROR:${COLOR_RESET} Work on ${COLOR_BRANCH}${BASE_BRANCH}${COLOR_RESET} branch
${COLOR_COMMAND}git checkout ${BASE_BRANCH}${COLOR_RESET}
" >&2
exit 2
}
function create_branch() {
local BRANCH=$1
local BASE_BRANCH=$2
git checkout -b ${BRANCH} ${BASE_BRANCH}
}
function update_package_version() {
local VERSION=$1
npm version --no-git-tag-version ${VERSION}
}
function update_changelog() {
local VERSION=$1
local DATE=`date "+%Y-%m-%d"`
local KEYWORD="Unreleased"
sed -i".bak" -r \
-e "s/^((##\s+)\[${KEYWORD}\])$/\1\n\n\2[${VERSION}] - ${DATE}/" \
-e "s/^((##[[:space:]]+)\[${KEYWORD}\])$/\1\n\n\2[${VERSION}] - ${DATE}/" \
-e "s/^(\[${KEYWORD}\](.*))(v.*)\.\.\.HEAD$/\1v${VERSION}...HEAD\n[${VERSION}]\2\3...v${VERSION}/" \
CHANGELOG.md
}
function update_package_version() {
local VERSION=$1
sed -i".bak" -r \
-e "s/(\"version\"\s*:\s*)\".*?\"/\1\"${VERSION}\"/" \
package.json
}
function update_dependencies_version() {
npm ci
npm run check-updates -- -u
}
function regenerate_package_lock() {
rm -rf package-lock.json node_modules
npm install
}
function build_package() {
npm run build
function verify_package() {
npm run verify
}
function commit_changes() {
local VERSION=$1
rm -rf node_modules
npm ci --only=production
git add CHANGELOG.md package.json package-lock.json lib
git add CHANGELOG.md package.json package-lock.json
git commit -m "version ${VERSION}"
}
function finish() {
local NEW_VERSION="${1}"
local CURRENT_VERSION="${2}"
local BRANCH="${3}"
local BASE_BRANCH="${4}"
local TAG="${5}"
local TITLE="${GITHUB_REPO} ${NEW_VERSION} released"
local CHANGELOG=$(
git diff v${CURRENT_VERSION} -- CHANGELOG.md |
sed -r -e '/^[^+]/d' -e 's/^\+(.*)$/\1/' -e '/^## /d' -e '/^\+/d' -e '/^\[/d' |
urlencode |
replace_lf
)
local PRERELEASE=0
if [[ ${NEW_VERSION} == "0."* ]]; then
# < 1.0.0
PRERELEASE=1
fi
if [[ ${NEW_VERSION} =~ -[0-9a-zA-Z] ]]; then
# -alpha, -pre, -rc, etc...
PRERELEASE=1
fi
echo -e "
Branch ${COLOR_BRANCH}${BRANCH}${COLOR_RESET} has been created.
Remaining processes are...
1. Make sure all changes are correct
${COLOR_COMMAND}git diff ${BASE_BRANCH} ${BRANCH}${COLOR_RESET}
2. Push to remote ${UPSTREAM}
${COLOR_COMMAND}git push --set-upstream ${UPSTREAM} ${BRANCH}${COLOR_RESET}
3. Create a pull-request: ${COLOR_BRANCH}${BRANCH}${COLOR_RESET} to ${COLOR_BRANCH}${BASE_BRANCH}${COLOR_RESET}
${URL_COMPARE}/${BASE_BRANCH}...${BRANCH}?expand=1
select ${COLOR_SELECT}Squash and merge${COLOR_RESET}
4. Create a new release
${URL_RELEASE}?tag=${TAG}&target=${BASE_BRANCH}&title=$(urlencode <<<"${TITLE}")&body=${CHANGELOG}&prerelease=${PRERELEASE}
Tag version: ${COLOR_INPUT}${TAG}${COLOR_RESET}
Target: ${COLOR_INPUT}${BASE_BRANCH}${COLOR_RESET}
Release title: ${COLOR_INPUT}${TITLE}${COLOR_RESET}
Description this release: (copy and paste CHANGELOG.md)
5. Post processing
${COLOR_COMMAND}git checkout ${BASE_BRANCH}${COLOR_RESET}
${COLOR_COMMAND}git pull${COLOR_RESET}
${COLOR_COMMAND}git fetch -p${COLOR_RESET}
${COLOR_COMMAND}git branch -D ${BRANCH}${COLOR_RESET}
That's all!
"
}
function urlencode() {
# https://developer.mozilla.org/en-US/docs/Glossary/percent-encoding
sed -r \
-e 's/%/%25/g' \
-e 's/\$/%24/g' -e 's/\(/%28/g' -e 's/\)/%29/g' -e 's/\*/%2A/g' -e 's/\+/%2B/g' -e 's/\//%2F/g' -e 's/\?/%3F/g' -e 's/\[/%5B/g' -e 's/\]/%5D/g' \
-e 's/!/%21/g' -e 's/#/%23/g' -e 's/&/%26/g' -e "s/'/%27/g" -e 's/,/%2C/g' -e 's/:/%3A/g' -e 's/;/%3B/g' -e 's/=/%3D/g' -e 's/@/%40/g' \
-e 's/ /+/g'
}
function replace_lf() {
sed -r \
-e ':a' -e 'N' -e '$!ba' \
-e 's/^\n+//' -e 's/\n+$//' -e 's/\n/%0A/g'
}
main "$@"

View File

@ -7,4 +7,4 @@ npm run verify
rm -rf node_modules
npm ci --only=production
git add lib
git add dist

View File

@ -3,13 +3,21 @@
set -eu
DATE=$(date +"%Y%m%d")
BRANCH=feature/update-dependencies-${DATE}
COLOR_SUCCESS="\e[1;32m"
COLOR_RESET="\e[m"
BASE_BRANCH=$(git rev-parse --abbrev-ref HEAD)
TARGET_BRANCH=feature/update-dependencies-${DATE}
# create branch
git checkout develop
git checkout -b ${BRANCH}
COLOR_SUCCESS="\033[1;32m"
COLOR_ERROR="\033[1;41m"
COLOR_RESET="\033[m"
cd $(dirname ${0})/..
# create target branch
if [[ ! ${BASE_BRANCH} =~ ^v[0-9]+$ ]]; then
echo -e "${COLOR_ERROR}Error:${COLOR_RESET} Base branch must match 'v*'; got '${BASE_BRANCH}'."
exit 1
fi
git checkout -b ${TARGET_BRANCH}
# check updates
npm ci
@ -18,20 +26,21 @@ npm run check-updates -- -u
# re-install packages
rm -rf package-lock.json node_modules
npm i
npm dedupe
# check
# test
npm run build
npm run verify
# commit
git add package.json package-lock.json lib
git add package.json package-lock.json dist
git commit -m "update dependencies"
# finished!
echo -e "
${COLOR_SUCCESS}🎉All dependencies are updated successfully.🎉${COLOR_RESET}
Push changes and merge into 'develop' branch.
Push changes and merge into '${BASE_BRANCH}' branch.
git push --set-upstream origin ${BRANCH}
git push --set-upstream origin ${TARGET_BRANCH}
"

76
src/common.ts Normal file
View File

@ -0,0 +1,76 @@
import * as fs from "fs";
import * as os from "os";
import * as path from "path";
import * as core from "@actions/core";
/** state name of backup suffix */
const STATE_BACKUP_SUFFIX = "backup-suffix";
const STATE_CREATED_FILES = "created-files";
/**
* create backup suffix name
* @param dirName directory to back up
* @returns backup suffix; empty string if directory does not exist
*/
export function createBackupSuffix(dirName: string): string {
if (!fs.existsSync(dirName)) {
return "";
}
const backupSuffix = `.bak-${Date.now()}`;
core.saveState(STATE_BACKUP_SUFFIX, backupSuffix);
return backupSuffix;
}
/**
* get backup suffix name
* @returns backup suffix (if not, empty string)
*/
export function getBackupSuffix(): string {
return core.getState(STATE_BACKUP_SUFFIX);
}
/**
* save created file names
* @param fileNames array of file names
*/
export function saveCreatedFileNames(fileNames: string[]): void {
const json = JSON.stringify(fileNames);
core.saveState(STATE_CREATED_FILES, json);
}
/**
* save created file names
* @returns saved array of file names
*/
export function loadCreatedFileNames(): string[] {
const json = core.getState(STATE_CREATED_FILES);
if (json === "") {
return [];
}
return JSON.parse(json) as string[];
}
/**
* get SSH directory
* @returns SSH directory name
*/
export function getSshDirectory(): string {
return path.resolve(getHomeDirectory(), ".ssh");
}
/**
* get home directory
* @returns home directory name
*/
function getHomeDirectory(): string {
const homedir = os.homedir();
if (homedir === "/github/home") {
// Docker container
return "/root";
}
return homedir;
}

View File

@ -1,112 +1,162 @@
import fs from "fs";
import path from "path";
import * as fs from "fs";
import * as path from "path";
import * as core from "@actions/core";
interface FileInfo
{
name: string;
contents: string;
options: fs.WriteFileOptions;
import * as common from "./common";
/** file creation info */
interface FileInfo {
/** file name */
name: string;
/** file contents */
contents: string;
/** creation options */
options: fs.WriteFileOptions;
/** file must not exist when creating */
mustNotExist: boolean;
}
/** default known_hosts */
const KNOWN_HOSTS = [
"github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=",
];
try {
main();
} catch (err) {
if (err instanceof Error) {
core.setFailed(err);
}
}
/**
* main function
*/
function main(): void
{
try
{
const files: FileInfo[] = [
{
name: core.getInput("name"),
contents: insertLf(core.getInput("key", {
required: true,
}), false, true),
options: {
mode: 0o400,
flag: "ax",
},
},
{
name: "known_hosts",
contents: insertLf(core.getInput("known_hosts", {
required: true,
}), true, true),
options: {
mode: 0o644,
flag: "a",
},
},
{
name: "config",
contents: insertLf(core.getInput("config"), true, true),
options: {
mode: 0o644,
flag: "a",
},
},
];
export function main(): void {
const sshDirName = common.getSshDirectory();
// create ".ssh" directory
const home = getHomeDirectory();
const dirName = path.resolve(home, ".ssh");
fs.mkdirSync(dirName, {
recursive: true,
mode: 0o700,
});
// create ".ssh" directory
const backupSuffix = common.createBackupSuffix(sshDirName);
if (backupSuffix === "") {
createDirectory(sshDirName);
console.log(`✅SSH directory "${sshDirName}" has been created successfully.`);
}
// create files
for(const file of files)
{
const fileName = path.join(dirName, file.name);
fs.writeFileSync(fileName, file.contents, file.options);
}
// files to be created
const files = buildFilesToCreate(sshDirName);
console.log(`SSH key has been stored to ${dirName} successfully.`);
}
catch(err)
{
core.setFailed(err.message);
}
// back up & create files
const createdFileNames: string[] = [];
const backedUpFileNames: string[] = [];
for (const file of files) {
const pathName = path.join(sshDirName, file.name);
if (backup(pathName, backupSuffix, file.mustNotExist)) {
backedUpFileNames.push(file.name);
}
fs.writeFileSync(pathName, file.contents, file.options);
createdFileNames.push(file.name);
}
common.saveCreatedFileNames(createdFileNames);
if (createdFileNames.length > 0) {
console.log(`✅Following files have been created in "${sshDirName}" successfully; ${createdFileNames.join(", ")}`);
}
if (backedUpFileNames.length > 0) {
console.log(`✅Following files have been backed up in suffix "${backupSuffix}" successfully; ${backedUpFileNames.join(", ")}`);
}
}
/**
* get home directory
* @returns home directory
* build files to create
* @param dirName directory name in where files will be created
* @returns files
*/
function getHomeDirectory(): string
{
const homeEnv = getHomeEnv();
const home = process.env[homeEnv];
if(home === undefined)
{
throw Error(`${homeEnv} is not defined`);
}
function buildFilesToCreate(dirName: string): FileInfo[] {
// parameters
const key = core.getInput("key", {
required: true,
});
const name = core.getInput("name");
const knownHosts = core.getInput("known_hosts", {
required: true,
});
const config = core.getInput("config");
const ifKeyExists = core.getInput("if_key_exists");
if(home === "/github/home")
{
// Docker container
return "/root";
}
// files to be created
const files: FileInfo[] = [
{
name: "known_hosts",
contents: insertLf(buildKnownHostsArray(knownHosts).join("\n"), true, true),
options: {
mode: 0o644,
flag: "a",
},
mustNotExist: false,
},
];
if (shouldCreateKeyFile(path.join(dirName, name), ifKeyExists)) {
files.push({
name: name,
contents: insertLf(key, false, true),
options: {
mode: 0o400,
flag: "wx",
},
mustNotExist: true,
});
}
if (config !== "") {
files.push({
name: "config",
contents: insertLf(config, true, true),
options: {
mode: 0o644,
flag: "a",
},
mustNotExist: false,
});
}
return home;
return files;
}
/**
* get HOME environment name
* @returns HOME environment name
* create directory
* @param dirName directory name to remove
*/
function getHomeEnv(): string
{
if(process.platform === "win32")
{
// Windows
return "USERPROFILE";
}
function createDirectory(dirName: string): void {
fs.mkdirSync(dirName, {
recursive: true,
mode: 0o700,
});
}
// macOS / Linux
return "HOME";
/**
* back up file
* @param fileName file to back up
* @param backupSuffix suffix
* @param removeOrig remove original file
* @returns is file backed up?
*/
function backup(fileName: string, backupSuffix: string, removeOrig: boolean): boolean {
if (backupSuffix === "") {
return false;
}
if (!fs.existsSync(fileName)) {
return false;
}
// move -> copy (in order to keep permissions when restore)
const fileNameBak = `${fileName}${backupSuffix}`;
fs.renameSync(fileName, fileNameBak);
if (!removeOrig) {
fs.copyFileSync(fileNameBak, fileName);
}
return true;
}
/**
@ -116,25 +166,58 @@ function getHomeEnv(): string
* @param append true to append
* @returns new value
*/
function insertLf(value: string, prepend: boolean, append: boolean): string
{
let affectedValue = value;
function insertLf(value: string, prepend: boolean, append: boolean): string {
let affectedValue = value;
if(value.length === 0)
{
// do nothing if empty
return "";
}
if(prepend && !affectedValue.startsWith("\n"))
{
affectedValue = `\n${affectedValue}`;
}
if(append && !affectedValue.endsWith("\n"))
{
affectedValue = `${affectedValue}\n`;
}
if (value.length === 0) {
// do nothing if empty
return "";
}
if (prepend && !affectedValue.startsWith("\n")) {
affectedValue = `\n${affectedValue}`;
}
if (append && !affectedValue.endsWith("\n")) {
affectedValue = `${affectedValue}\n`;
}
return affectedValue;
return affectedValue;
}
main();
/**
* should create SSH key file?
* @param keyFilePath path of key file
* @param ifKeyExists action if SSH key exists
* @returns Yes/No
*/
function shouldCreateKeyFile(keyFilePath: string, ifKeyExists: string): boolean {
if (!fs.existsSync(keyFilePath)) {
// should create if file does not exist
return true;
}
switch (ifKeyExists) {
case "replace":
// should create if replace (existing file will be backed up when creating)
return true;
case "ignore":
// should NOT create if ignore
return false;
default:
// error otherwise
throw new Error(`SSH key is already installed. Set "if_key_exists" to "replace" or "ignore" in order to avoid this error.`);
}
}
/**
* build array of known_hosts
* @param knownHosts known_hosts
* @returns array of known_hosts
*/
function buildKnownHostsArray(knownHosts: string): string[] {
if (knownHosts === "unnecessary") {
return KNOWN_HOSTS;
}
return KNOWN_HOSTS.concat(knownHosts);
}

89
src/post.ts Normal file
View File

@ -0,0 +1,89 @@
import * as fs from "fs";
import * as path from "path";
import * as core from "@actions/core";
import * as common from "./common";
try {
post();
} catch (err) {
if (err instanceof Error) {
core.setFailed(err);
}
}
/**
* cleanup function
*/
export function post(): void {
const sshDirName = common.getSshDirectory();
const backupSuffix = common.getBackupSuffix();
if (backupSuffix === "") {
// remove ".ssh" directory if suffix is not set
removeDirectory(sshDirName);
console.log(`✅SSH directory "${sshDirName}" has been removed successfully.`);
} else {
// remove created files and restore from backup
const removedFileNames = removeCreatedFiles(sshDirName);
if (removedFileNames.length > 0) {
console.log(`✅Following files have been removed successfully; ${removedFileNames.join(", ")}`);
}
const restoredFileNames = restoreFiles(sshDirName, backupSuffix);
if (restoredFileNames.length > 0) {
console.log(`✅Following files in suffix "${backupSuffix}" have been restored successfully; ${restoredFileNames.join(", ")}`);
}
}
}
/**
* remove directory
* @param dirName directory name to remove
*/
function removeDirectory(dirName: string): void {
fs.rmSync(dirName, {
recursive: true,
force: true,
});
}
/**
* remove created files in main phase
* @param dirName directory name
* @returns removed file names
*/
function removeCreatedFiles(dirName: string): string[] {
const createdFileNames = common.loadCreatedFileNames();
for (const fileName of createdFileNames) {
const pathName = path.join(dirName, fileName);
fs.rmSync(pathName);
}
return createdFileNames;
}
/**
* restore files from backups
* @param dirName directory name
* @param backupSuffix suffix of backup directory
* @returns restored file names
*/
function restoreFiles(dirName: string, backupSuffix: string): string[] {
const restoredFileNames: string[] = [];
const entries = fs.readdirSync(dirName)
.filter((entry) => {
// skip if not a backed-up file
return entry.endsWith(backupSuffix);
});
for (const entry of entries) {
const entryOrg = entry.substring(0, entry.length - backupSuffix.length);
const pathNameOrg = path.join(dirName, entryOrg);
const pathNameBak = path.join(dirName, entry);
fs.renameSync(pathNameBak, pathNameOrg);
restoredFileNames.push(entryOrg);
}
return restoredFileNames;
}

View File

@ -2,11 +2,12 @@
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"moduleResolution": "node",
"lib": [
"es6"
],
"sourceMap": true,
"outDir": "./lib",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,