Compare commits

...

90 Commits
v1 ... 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
shimataro 0bbd533afd
Merge pull request #178 from shimataro/develop
version 2.2.0
2021-02-27 14:16:22 +09:00
shimataro 8053198ce5
version 2.2.0 (#177) 2021-02-27 14:09:25 +09:00
shimataro 68b956be12
Feature/centos (#176)
* check on CentOS container

* update README

* update links

* update CHANGELOG

* refactor insertLf()
2021-02-24 21:24:03 +09:00
shimataro cdcc4725b3
test on Docker for Windows (#175)
* test on Docker for Windows

* Revert "test on Docker for Windows"

This reverts commit 5ad4baf9d8.

* update README
2021-02-23 11:27:02 +09:00
shimataro 80ed341cfe
update dependencies (#174) 2021-02-23 10:42:34 +09:00
shimataro 4b6bc79244
Feature/matrix docker container (#173)
* use matrix for Docker container

* update badge
2021-02-23 10:38:18 +09:00
shimataro 5b144c9cec
remove "pull_request" trigger from CI (#172) 2021-02-23 10:25:44 +09:00
shimataro e83b5ac86d
support OpenSSH key format (#171)
* Make up for LF in last line of SSH key file

* refactor insertLf()

* add test for OpenSSH format

* add PKCS8 format

* apply to other virtual machines

* update README

* update CHANGELOG

Co-authored-by: Tatsunori Uchino <tats.u@live.jp>
2021-02-23 10:22:30 +09:00
shimataro 026e5f82bf
Feature/container (#170)
* support Docker container

* move .ssh to /root

* remove print step

* change home directory for Docker container

* print HOME

* print home

* print home

* update dist file

* update dirname

* update CHANGELOG

* add badge
2021-02-08 23:31:19 +09:00
shimataro 0b924ac88f
update dependencies (#169) 2021-02-08 22:40:11 +09:00
shimataro a988908393
Feature/ignore node modules (#166)
* Ignore Node files that should not be tracked

The list can be fetched by `gibo dump node`.

* Untrack node_modules/@actions

* Cache node_modules

* Don't add node_modules ins Bash scripts

* Use ncc to pack dependencies

* Change final product path

Remove & ignore previous one (lib/main.js{,.map})

* Disable PR check using author's key

Author's key is not passed to PR builds (#164)

* update settings

* update CHANGELOG

* update build.yml

Co-authored-by: Tatsunori Uchino <tats.u@live.jp>
2021-02-08 22:19:05 +09:00
shimataro 47a775a015
Feature/fix readme (#167)
* fix README.md

* update README

Co-authored-by: KimSoungRyoul <KimSoungRyoul@gmail.com>
2021-02-08 21:40:22 +09:00
dependabot[bot] 66374eaff9
Bump @actions/core from 1.2.4 to 1.2.6 (#158)
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.2.4 to 1.2.6.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-10-10 22:53:14 +09:00
shimataro c1b9a14080
Feature/funding (#155)
* Create FUNDING.yml

* add PayPal.ME URL
2020-09-03 00:40:40 +09:00
shimataro 6f350ca848
Merge pull request #154 from shimataro/develop
version 2.1.0
2020-08-15 11:19:53 +09:00
shimataro 93a402e560
version 2.1.0 (#153) 2020-08-15 10:56:46 +09:00
shimataro 54623227a4
update dependencies (#152) 2020-08-15 10:38:03 +09:00
shimataro 34604805aa
append LF (#151)
* append LF to known_hosts and config

* build

* update CHANGELOG
2020-08-15 10:31:03 +09:00
shimataro c6c7de11ed
update dependencies (#149) 2020-08-09 16:05:50 +09:00
dependabot[bot] 363e8e6fa1
Bump lodash from 4.17.15 to 4.17.19 (#146)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-08-09 15:48:52 +09:00
shimataro ba121ac3a2
update dependencies (#144) 2020-07-05 07:35:03 +09:00
shimataro d78e9995b0
Fix typo (#141)
* option -> parameter

* update CHANGELOG
2020-06-17 23:12:44 +09:00
shimataro d93f5c693a
Build on all supported platforms (#139)
* Build on all supported platforms

* rename job
2020-06-06 15:37:44 +09:00
shimataro 8ddce4efa1
Merge pull request #138 from shimataro/develop
version 2.0.3
2020-06-06 15:27:33 +09:00
shimataro be59087152
version 2.0.3 (#137) 2020-06-06 15:22:19 +09:00
shimataro ae1cf3fcc9
insert CHANGELOG into release page (#136) 2020-06-06 12:10:25 +09:00
shimataro 01556dafe4
add Ubuntu 20.04 (#135)
* add Ubuntu 20.04

* macOS -> macOS Catalina

* rename CI files

* Windows -> Windows Server 2019

* update README

* update CHANGELOG
2020-06-06 11:05:25 +09:00
shimataro db8ead54b2
Add short note on how to convert OPENSSH to PEM format (#134)
* Fix #130 - improve readme.md (#131)

Co-authored-by: shimataro <shimataro@zelkova.cc>

* update CHANGELOG

* fixed lint error

* add link to contributor

Co-authored-by: Helmut Wolf <shadow1runner@users.noreply.github.com>
2020-06-06 09:33:26 +09:00
shimataro e45e94049a
build on pull_request (#133) 2020-05-11 21:36:22 +09:00
shimataro 536ce5b853
verify on pull_request (#132) 2020-05-11 18:11:13 +09:00
shimataro 147b45cece
Merge pull request #129 from shimataro/develop
version 2.0.2
2020-04-12 10:18:25 +09:00
shimataro f1a1580bbd
version 2.0.2 (#128) 2020-04-12 10:13:37 +09:00
shimataro 37c93f4d12
Feature/update dependencies 20200412 (#127)
* update dependencies

* * update CHANGELOG
2020-04-12 10:03:20 +09:00
shimataro 262770b68b
Merge pull request #126 from shimataro/develop
version 2.0.1
2020-03-14 14:27:49 +09:00
shimataro ef5287d6c2
version 2.0.1 (#125) 2020-03-14 14:25:16 +09:00
shimataro 6f49ca664f
Feature/update dependencies 20200314 (#124)
* update dependencies

* * update CHANGELOG
2020-03-14 14:14:40 +09:00
shimataro f75e1f50c3
Feature/scripts (#123)
* * just "npm ci" on rebuild

* * do not add "package-lock.json"
2020-03-01 08:32:20 +09:00
shimataro 9a0947af3f
* update keyword-spacing (#121) 2020-02-26 09:08:08 +09:00
shimataro b7ac21090a
Feature/eslint (#120)
* * remove eslint-plugin-import

* * update TypeScript rules

* * update valid-jsdoc

* * update sort-imports

* * update semicolon style

* * update lines-between-class-members

* * update id-length

* * update function-paren-newline

* * update dot-notation
2020-02-26 08:28:23 +09:00
shimataro 0033eb1846
* add ol-prefix rule (#119) 2020-02-25 18:35:42 +09:00
shimataro 8cfbd50da1 * add example of "rsync via bastion" (#118) 2020-02-10 20:05:55 +09:00
shimataro 5bd2f032f1
Merge pull request #117 from shimataro/develop
version 2.0.0
2020-02-08 19:00:45 +09:00
shimataro 5f6cc712bb
version 2.0.0 (#116)
* Feature/private key (#71)

* * rename private-key to key

* * update CI

* * update README / CHANGELOG

* Feature/rename known hosts (#72)

* * rename known-hosts to known_hosts

* * update CI

* * update README

* * update CHANGELOG

* * update README

* Feature/known hosts required (#73)

* * make known-hosts required

* * update CI

* * update README

* * update CHANGELOG

* * update README

* Feature/docs v2 (#80)

* * update version in README

* * update badge URL

* * remove duplicated reference

* * update versions

* * fix CHANGELOG

* * fix version
2020-02-08 18:58:07 +09:00
42 changed files with 11934 additions and 3847 deletions

View File

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

View File

@ -7,7 +7,6 @@ extends:
- plugin:@typescript-eslint/eslint-recommended - plugin:@typescript-eslint/eslint-recommended
- plugin:@typescript-eslint/recommended - plugin:@typescript-eslint/recommended
plugins: plugins:
- import
- "@typescript-eslint" - "@typescript-eslint"
parser: "@typescript-eslint/parser" parser: "@typescript-eslint/parser"
parserOptions: parserOptions:
@ -15,7 +14,9 @@ parserOptions:
project: ./tsconfig.json project: ./tsconfig.json
rules: # https://eslint.org/docs/rules/ rules: # https://eslint.org/docs/rules/
accessor-pairs: error accessor-pairs: error
array-bracket-newline: error array-bracket-newline:
- error
- consistent
array-bracket-spacing: array-bracket-spacing:
- error - error
- never - never
@ -30,9 +31,7 @@ rules: # https://eslint.org/docs/rules/
before: true before: true
block-scoped-var: error block-scoped-var: error
block-spacing: error block-spacing: error
brace-style: brace-style: 'off' # see "@typescript-eslint/brace-style"
- error
- allman
callback-return: error callback-return: error
capitalized-comments: 'off' capitalized-comments: 'off'
class-methods-use-this: error class-methods-use-this: error
@ -60,7 +59,7 @@ rules: # https://eslint.org/docs/rules/
- property - property
dot-notation: dot-notation:
- error - error
- allowKeywords: true - allowPattern: "^_"
eol-last: error eol-last: error
eqeqeq: error eqeqeq: error
for-direction: error for-direction: error
@ -72,38 +71,30 @@ rules: # https://eslint.org/docs/rules/
func-style: func-style:
- error - error
- declaration - declaration
function-paren-newline: error function-paren-newline:
- error
- multiline-arguments
generator-star-spacing: error generator-star-spacing: error
getter-return: error getter-return: error
global-require: error global-require: error
guard-for-in: error guard-for-in: error
handle-callback-err: error handle-callback-err: error
id-blacklist: error id-blacklist: error
id-length: 'off' id-length: error
id-match: error id-match: error
implicit-arrow-linebreak: implicit-arrow-linebreak:
- error - error
- below - below
indent: indent:
- error - error
- tab - 4
- SwitchCase: 1
indent-legacy: 'off' indent-legacy: 'off'
init-declarations: error init-declarations: error
jsx-quotes: error jsx-quotes: error
key-spacing: error key-spacing: error
keyword-spacing: keyword-spacing:
- error - error
- overrides:
if:
after: false
for:
after: false
while:
after: false
catch:
after: false
with:
after: false
line-comment-position: 'off' line-comment-position: 'off'
linebreak-style: linebreak-style:
- error - error
@ -113,6 +104,7 @@ rules: # https://eslint.org/docs/rules/
lines-between-class-members: lines-between-class-members:
- error - error
- always - always
- exceptAfterSingleLine: true
max-depth: error max-depth: error
max-len: 'off' max-len: 'off'
max-lines: 'off' max-lines: 'off'
@ -147,6 +139,7 @@ rules: # https://eslint.org/docs/rules/
no-extra-bind: error no-extra-bind: error
no-extra-label: error no-extra-label: error
no-extra-parens: error no-extra-parens: error
no-extra-semi: error
no-floating-decimal: error no-floating-decimal: error
no-implicit-coercion: error no-implicit-coercion: error
no-implicit-globals: error no-implicit-globals: error
@ -168,7 +161,7 @@ rules: # https://eslint.org/docs/rules/
- error - error
- max: 1 - max: 1
no-native-reassign: error no-native-reassign: error
no-negated-condition: error no-negated-condition: 'off'
no-negated-in-lhs: error no-negated-in-lhs: error
no-nested-ternary: error no-nested-ternary: error
no-new: error no-new: error
@ -251,12 +244,15 @@ rules: # https://eslint.org/docs/rules/
rest-spread-spacing: rest-spread-spacing:
- error - error
- never - never
semi: error semi: 'off' # see "@typescript-eslint/semi"
semi-spacing: error semi-spacing: error
semi-style: semi-style:
- error - error
- last - last
sort-imports: 'off' sort-imports:
- error
- ignoreCase: false
ignoreDeclarationSort: true
sort-keys: 'off' sort-keys: 'off'
sort-vars: error sort-vars: error
space-before-blocks: error space-before-blocks: error
@ -281,8 +277,14 @@ rules: # https://eslint.org/docs/rules/
- never - never
valid-jsdoc: valid-jsdoc:
- error - error
- requireParamType: false - prefer:
arg: param
argument: param
return: returns
yield: yields
exception: throws
requireReturn: false requireReturn: false
requireParamType: false
requireReturnType: false requireReturnType: false
vars-on-top: error vars-on-top: error
wrap-iife: error wrap-iife: error
@ -292,14 +294,27 @@ rules: # https://eslint.org/docs/rules/
- error - error
- never - never
# import plugin
import/extensions: 'off'
import/no-unresolved:
- error
# @typescript-eslint plugin # @typescript-eslint plugin
"@typescript-eslint/explicit-function-return-type": 'off' "@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": "@typescript-eslint/no-use-before-define":
- error - error
- functions: false - functions: false
"@typescript-eslint/strict-boolean-expressions": error "@typescript-eslint/semi": error
"@typescript-eslint/strict-boolean-expressions":
- error
- allowString: false
allowNumber: false
allowNullableObject: false

4
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,4 @@
github:
- shimataro
custom:
- "https://www.paypal.me/shimataro"

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

@ -1,32 +1,42 @@
# https://help.github.com/en/articles/workflow-syntax-for-github-actions # https://help.github.com/en/articles/workflow-syntax-for-github-actions
on: push
name: Build name: Build
on:
- push
jobs: jobs:
build: build:
name: Build on ${{ matrix.os }} / Node.js v${{ matrix.nodejs }} name: Build
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: os:
- Windows-latest - windows-2019
- macOS-latest - windows-2022
- Ubuntu-latest - macos-11
- macos-12
- ubuntu-20.04
- ubuntu-22.04
nodejs: nodejs:
- 12 - 20
fail-fast: false fail-fast: false
steps: steps:
- name: Turn off auto-crlf - name: Turn off auto-crlf
run: git config --global core.autocrlf false run: git config --global core.autocrlf false
- name: Checkout source codes - name: Checkout source codes
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v1 uses: actions/setup-node@v4
with: with:
node-version: ${{ matrix.nodejs }} node-version: ${{ matrix.nodejs }}
- name: Cache NPM
uses: ./.github/actions/cache-npm
- name: Install dependencies - name: Install dependencies
run: npm ci run: npm ci
- name: Build - name: Build
run: npm run build run: npm run build
- name: Exit if differ (forgot to commit dist dir?)
run: git diff --exit-code --quiet
- name: Verify - name: Verify
run: npm run 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

@ -0,0 +1,23 @@
# https://help.github.com/en/articles/workflow-syntax-for-github-actions
name: Docker container (CentOS)
on:
- push
jobs:
verify:
name: Verify
strategy:
fail-fast: false
matrix:
os:
- ubuntu-20.04
- 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

@ -0,0 +1,26 @@
# https://help.github.com/en/articles/workflow-syntax-for-github-actions
name: Docker container (Ubuntu)
on:
- push
jobs:
verify:
name: Verify
strategy:
fail-fast: false
matrix:
os:
- ubuntu-20.04
- ubuntu-22.04
docker_image:
- ubuntu:20.04
- ubuntu:22.04
uses: "./.github/workflows/reusable-verify.yml"
with:
os: ${{ matrix.os }}
docker_image: ${{ matrix.docker_image }}
package_installation_command: |
apt update
apt install -y openssh-client git
secrets: inherit

View File

@ -1,41 +1,19 @@
# https://help.github.com/en/articles/workflow-syntax-for-github-actions # https://help.github.com/en/articles/workflow-syntax-for-github-actions
on: push
name: macOS name: macOS
on:
- push
jobs: jobs:
ssh: verify:
name: Connect to github.com name: Verify
runs-on: macos-latest strategy:
steps: fail-fast: false
- name: Checkout source codes matrix:
uses: actions/checkout@v2 os:
- name: Install SSH key - macos-11
uses: ./. - macos-12
with: uses: "./.github/workflows/reusable-verify.yml"
private-key: ${{ secrets.SSH_KEY }} with:
known-hosts: ${{ secrets.KNOWN_HOSTS }} # optional os: ${{ matrix.os }}
- name: print created files secrets: inherit
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-latest
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
private-key: ${{ secrets.SSH_KEY }}
known-hosts: ${{ secrets.KNOWN_HOSTS }} # optional
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,41 +1,19 @@
# https://help.github.com/en/articles/workflow-syntax-for-github-actions # https://help.github.com/en/articles/workflow-syntax-for-github-actions
on: push
name: Ubuntu name: Ubuntu
on:
- push
jobs: jobs:
ssh: verify:
name: Connect to github.com name: Verify
runs-on: ubuntu-latest strategy:
steps: fail-fast: false
- name: Checkout source codes matrix:
uses: actions/checkout@v2 os:
- name: Install SSH key - ubuntu-20.04
uses: ./. - ubuntu-22.04
with: uses: "./.github/workflows/reusable-verify.yml"
private-key: ${{ secrets.SSH_KEY }} with:
known-hosts: ${{ secrets.KNOWN_HOSTS }} # optional os: ${{ matrix.os }}
- name: print created files secrets: inherit
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-latest
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
private-key: ${{ secrets.SSH_KEY }}
known-hosts: ${{ secrets.KNOWN_HOSTS }} # optional
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,41 +0,0 @@
# https://help.github.com/en/articles/workflow-syntax-for-github-actions
on: push
name: Ubuntu 16.04
jobs:
ssh:
name: Connect to github.com
runs-on: ubuntu-16.04
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
private-key: ${{ secrets.SSH_KEY }}
known-hosts: ${{ secrets.KNOWN_HOSTS }} # optional
- 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:
private-key: ${{ secrets.SSH_KEY }}
known-hosts: ${{ secrets.KNOWN_HOSTS }} # optional
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,41 +1,19 @@
# https://help.github.com/en/articles/workflow-syntax-for-github-actions # https://help.github.com/en/articles/workflow-syntax-for-github-actions
on: push
name: Windows name: Windows
on:
- push
jobs: jobs:
ssh: verify:
name: Connect to github.com name: Verify
runs-on: windows-latest strategy:
steps: fail-fast: false
- name: Checkout source codes matrix:
uses: actions/checkout@v2 os:
- name: Install SSH key - windows-2019
uses: ./. - windows-2022
with: uses: "./.github/workflows/reusable-verify.yml"
private-key: ${{ secrets.SSH_KEY }} with:
known-hosts: ${{ secrets.KNOWN_HOSTS }} # optional os: ${{ matrix.os }}
- name: print created files secrets: inherit
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-latest
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Install SSH key
uses: ./.
with:
private-key: ${{ secrets.SSH_KEY }}
known-hosts: ${{ secrets.KNOWN_HOSTS }} # optional
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 ~/.ssh
- name: git clone through SSH
run: git clone github:shimataro/ssh-key-action.git tmp

6
.gitignore vendored
View File

@ -12,3 +12,9 @@ Thumbs.db
# patch/merge # patch/merge
*.orig *.orig
*.rej *.rej
# IDE
/.idea/
# Node.js modules
/node_modules/

View File

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

View File

@ -7,6 +7,129 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased] ## [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
* Support Ubuntu/CentOS Docker container (thanks [@kujaomega](https://github.com/kujaomega))
* Support PKCS8/RFC4716 formats (thanks [@tats-u](https://github.com/tats-u))
### Changed
* Bundle dependencies (thanks [@tats-u](https://github.com/tats-u))
### Fixed
* comments in README (thanks [@KimSoungRyoul](https://github.com/KimSoungRyoul))
## [2.1.0] - 2020-08-15
### Changed
* Append LF to `known_hosts` / `config` (thanks [@jacktuck](https://github.com/jacktuck))
### Fixed
* Typo (thanks [@psbss](https://github.com/psbss))
## [2.0.3] - 2020-06-06
### Added
* Ubuntu 20.04
### Changed
* Add short note on how to convert OPENSSH to PEM format by [@shadow1runner](https://github.com/shadow1runner)
## [2.0.2] - 2020-04-12
### Security
* update [minimist](https://www.npmjs.com/package/minimist) to 1.2.5 ([CVE-2020-7598](https://github.com/advisories/GHSA-vh95-rmgr-6w4m))
## [2.0.1] - 2020-03-14
### Security
* update [acorn](https://www.npmjs.com/package/acorn) to 7.1.1 ([GHSA-7fhm-mqm4-2wp7](https://github.com/advisories/GHSA-7fhm-mqm4-2wp7))
## [2.0.0] - 2020-02-08
### Changed
* rename `private-key` to `key`
* rename `known-hosts` to `known_hosts`
* make `known_hosts` required
## [1.6.5] - 2020-02-08 ## [1.6.5] - 2020-02-08
### Others ### Others
@ -83,7 +206,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
* First release. * First release.
[Unreleased]: https://github.com/shimataro/ssh-key-action/compare/v1.6.5...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
[2.0.2]: https://github.com/shimataro/ssh-key-action/compare/v2.0.1...v2.0.2
[2.0.1]: https://github.com/shimataro/ssh-key-action/compare/v2.0.0...v2.0.1
[2.0.0]: https://github.com/shimataro/ssh-key-action/compare/v1.6.5...v2.0.0
[1.6.5]: https://github.com/shimataro/ssh-key-action/compare/v1.6.4...v1.6.5 [1.6.5]: https://github.com/shimataro/ssh-key-action/compare/v1.6.4...v1.6.5
[1.6.4]: https://github.com/shimataro/ssh-key-action/compare/v1.6.3...v1.6.4 [1.6.4]: https://github.com/shimataro/ssh-key-action/compare/v1.6.3...v1.6.4
[1.6.3]: https://github.com/shimataro/ssh-key-action/compare/v1.6.2...v1.6.3 [1.6.3]: https://github.com/shimataro/ssh-key-action/compare/v1.6.2...v1.6.3

105
README.md
View File

@ -4,7 +4,9 @@
[![Windows][image-verify-windows]][link-verify-windows] [![Windows][image-verify-windows]][link-verify-windows]
[![macOS][image-verify-macos]][link-verify-macos] [![macOS][image-verify-macos]][link-verify-macos]
[![Ubuntu][image-verify-ubuntu]][link-verify-ubuntu] [![Ubuntu][image-verify-ubuntu]][link-verify-ubuntu]
[![Ubuntu 16.04][image-verify-ubuntu1604]][link-verify-ubuntu1604] [![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] [![Release][image-release]][link-release]
[![License][image-license]][link-license] [![License][image-license]][link-license]
[![Stars][image-stars]][link-stars] [![Stars][image-stars]][link-stars]
@ -13,58 +15,69 @@ This action installs SSH key in `~/.ssh`.
Useful for SCP, SFTP, and `rsync` over SSH in deployment script. Useful for SCP, SFTP, and `rsync` over SSH in deployment script.
**Works on all [virtual environment](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners#supported-runners-and-hardware-resources) -- Windows, macOS, Ubuntu and Ubuntu 16.04.** 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 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 ## Usage
Add your SSH key to your product secrets by clicking `Settings` - `Secrets` - `Add a new secret` beforehand. Add your SSH key to your product secrets by clicking `Settings` - `Secrets` - `Add a new secret` beforehand.
**NOTE:** OPENSSH format (key begins with `-----BEGIN OPENSSH PRIVATE KEY-----`) may not work due to OpenSSH version on VM. Please use PEM format (begins with `-----BEGIN RSA PRIVATE KEY-----`) instead. PEM(RSA), PKCS8, and RFC4716(OpenSSH) formats are OK.
```yaml ```yaml
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Install SSH key - name: Install SSH key
uses: shimataro/ssh-key-action@v1 uses: shimataro/ssh-key-action@v2
with: with:
private-key: ${{ secrets.SSH_KEY }} key: ${{ secrets.SSH_KEY }}
name: id_rsa # optional name: id_rsa # optional
known-hosts: ${{ secrets.KNOWN_HOSTS }} # known_hosts; optional known_hosts: ${{ secrets.KNOWN_HOSTS }}
config: ${{ secrets.CONFIG }} # ssh_config; optional config: ${{ secrets.CONFIG }} # ssh_config; optional
- name: rsync over ssh if_key_exists: fail # replace / ignore / fail; optional (defaults to fail)
run: rsync ./foo/ user@remote:bar/ - 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. 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 ### Install multiple keys
If you want to install multiple keys, call this action multiple times. If you want to install multiple keys, call this action multiple times.
It is useful for port forwarding. It is useful for port forwarding.
**NOTE:** When this action is called multiple times, **the contents of `known-hosts` and `config` will be appended**. `private-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 ```yaml
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Install SSH key of bastion - name: Install SSH key of bastion
uses: shimataro/ssh-key-action@v1 uses: shimataro/ssh-key-action@v2
with: with:
private-key: ${{ secrets.SSH_KEY_OF_BASTION }} key: ${{ secrets.SSH_KEY_OF_BASTION }}
name: id_rsa-bastion name: id_rsa-bastion
known-hosts: ${{ secrets.KNOWN_HOSTS_OF_BASTION }} known_hosts: ${{ secrets.KNOWN_HOSTS_OF_BASTION }}
config: | config: |
Host bastion Host bastion
HostName xxx.xxx.xxx.xxx HostName xxx.xxx.xxx.xxx
User user-of-bastion User user-of-bastion
IdentityFile ~/.ssh/id_rsa-bastion IdentityFile ~/.ssh/id_rsa-bastion
- name: Install SSH key of target - name: Install SSH key of target
uses: shimataro/ssh-key-action@v1 uses: shimataro/ssh-key-action@v2
with: with:
private-key: ${{ secrets.SSH_KEY_OF_TARGET }} key: ${{ secrets.SSH_KEY_OF_TARGET }}
name: id_rsa-target name: id_rsa-target
known-hosts: ${{ secrets.KNOWN_HOSTS_OF_TARGET }} # will be appended! known_hosts: ${{ secrets.KNOWN_HOSTS_OF_TARGET }} # will be appended to existing .ssh/known_hosts
config: | # will be appended! config: | # will be appended to existing .ssh/config
Host target Host target
HostName yyy.yyy.yyy.yyy HostName yyy.yyy.yyy.yyy
User user-of-target User user-of-target
@ -78,15 +91,18 @@ steps:
### SSH failed even though key has been installed. ### SSH failed even though key has been installed.
Check belows: Check below:
* `Load key "/HOME/.ssh/id_rsa": invalid format`:
* OPENSSH format (key begins with `-----BEGIN OPENSSH PRIVATE KEY-----`) may not work.
* Use PEM format (begins with `-----BEGIN RSA PRIVATE KEY-----`).
* `Host key verification failed.`: * `Host key verification failed.`:
* Set `known-hosts` option or use `ssh -o StrictHostKeyChecking=no`. * Set `known_hosts` parameter correctly (use `ssh-keyscan` command).
* The former is **HIGHLY** recommended for security reason.
* I'm planning to make `known-hosts` required in v2. ### 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? ### How do I use encrypted SSH key?
@ -101,10 +117,15 @@ Here are some solutions:
### Which one is the best way for transferring files, "direct SCP/SFTP/rsync" or "SCP/SFTP/rsync via bastion"? ### Which one is the best way for transferring files, "direct SCP/SFTP/rsync" or "SCP/SFTP/rsync via bastion"?
I recommend **rsync via bastion**. I recommend **rsync via bastion**.
```bash
rsync -r -e "ssh bastion ssh" ./foo/ target:bar/
```
It has some advantages over other methods: It has some advantages over other methods:
* "Rsync via bastion" doesn't require to update workflow files and `secrets` even if it is necessary to transfer files to multiple servers. * "Rsync via bastion" doesn't require to update workflow files and `secrets` even if it is necessary to transfer files to multiple servers.
* Other methods require to update `known-hosts` if servers have changed. * Other methods require to update `known_hosts` if servers have changed.
* Rsync: * Rsync:
* is fastest of all. * is fastest of all.
* does **NOT** break files even if disconnected during transferring. * does **NOT** break files even if disconnected during transferring.
@ -117,6 +138,18 @@ It has some advantages over other methods:
* And will be updated continuously. * And will be updated continuously.
* if security incident ―e.g., private key leaked― occurs, it's OK just to remove `authorized_keys` on bastion. * 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 ## License
The scripts and documentation in this project are released under the [MIT License](LICENSE) The scripts and documentation in this project are released under the [MIT License](LICENSE)
@ -125,16 +158,20 @@ The scripts and documentation in this project are released under the [MIT Licens
See [CHANGELOG.md](CHANGELOG.md). See [CHANGELOG.md](CHANGELOG.md).
[image-build]: https://github.com/shimataro/ssh-key-action/workflows/Build/badge.svg?event=push&branch=v1 [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?query=workflow%3ABuild [link-build]: https://github.com/shimataro/ssh-key-action/actions/workflows/build.yml
[image-verify-windows]: https://github.com/shimataro/ssh-key-action/workflows/Windows/badge.svg?event=push&branch=v1 [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?query=workflow%3AWindows [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=v1 [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?query=workflow%3AmacOS [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=v1 [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?query=workflow%3AUbuntu [link-verify-ubuntu]: https://github.com/shimataro/ssh-key-action/actions/workflows/verify-on-ubuntu.yml
[image-verify-ubuntu1604]: https://github.com/shimataro/ssh-key-action/workflows/Ubuntu%2016.04/badge.svg?event=push&branch=v1 [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-ubuntu1604]: https://github.com/shimataro/ssh-key-action/actions?query=workflow%3A%22Ubuntu+16.04%22 [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 [image-release]: https://img.shields.io/github/release/shimataro/ssh-key-action.svg
[link-release]: https://github.com/shimataro/ssh-key-action/releases [link-release]: https://github.com/shimataro/ssh-key-action/releases
[image-license]: https://img.shields.io/github/license/shimataro/ssh-key-action.svg [image-license]: https://img.shields.io/github/license/shimataro/ssh-key-action.svg

View File

@ -6,21 +6,26 @@ branding:
icon: "terminal" icon: "terminal"
color: "gray-dark" color: "gray-dark"
inputs: inputs:
private-key: key:
description: "private SSH key" description: "SSH private key"
required: true required: true
name: name:
description: "SSH key file name (default: id_rsa)" description: "SSH key file name (default: id_rsa)"
required: false required: false
default: "id_rsa" default: "id_rsa"
known-hosts: known_hosts:
description: "public keys of SSH servers" description: "public keys of SSH servers"
required: false required: true
default: "" default: ""
config: config:
description: "SSH config" description: "SSH config"
required: false required: false
default: "" default: ""
if_key_exists:
description: "replace / ignore / fail"
required: false
default: "fail"
runs: runs:
using: "node12" using: "node20"
main: "lib/main.js" 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,104 +0,0 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
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 fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const core = __importStar(require("@actions/core"));
/**
* main function
*/
function main() {
try {
const files = [
{
name: core.getInput("name"),
contents: core.getInput("private-key", {
required: true,
}),
options: {
mode: 0o400,
flag: "ax",
},
},
{
name: "known_hosts",
contents: prependLf(core.getInput("known-hosts")),
options: {
mode: 0o644,
flag: "a",
},
},
{
name: "config",
contents: prependLf(core.getInput("config")),
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`);
}
return home;
}
/**
* get HOME environment name
* @returns HOME environment name
*/
function getHomeEnv() {
if (process.platform === "win32") {
// Windows
return "USERPROFILE";
}
// macOS / Linux
return "HOME";
}
/**
* prepend LF to value if not empty
* @param value the value to prepend LF
* @returns prepended value
*/
function prependLf(value) {
if (value.length === 0) {
// do nothing if empty
return "";
}
return `\n${value}`;
}
main();
//# sourceMappingURL=main.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AAExB,oDAAsC;AAStC;;GAEG;AACH,SAAS,IAAI;IAEZ,IACA;QACC,MAAM,KAAK,GAAe;YACzB;gBACC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE;oBACtC,QAAQ,EAAE,IAAI;iBACd,CAAC;gBACF,OAAO,EAAE;oBACR,IAAI,EAAE,KAAK;oBACX,IAAI,EAAE,IAAI;iBACV;aACD;YACD;gBACC,IAAI,EAAE,aAAa;gBACnB,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;gBACjD,OAAO,EAAE;oBACR,IAAI,EAAE,KAAK;oBACX,IAAI,EAAE,GAAG;iBACT;aACD;YACD;gBACC,IAAI,EAAE,QAAQ;gBACd,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBAC5C,OAAO,EAAE;oBACR,IAAI,EAAE,KAAK;oBACX,IAAI,EAAE,GAAG;iBACT;aACD;SACD,CAAC;QAEF,0BAA0B;QAC1B,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,cAAI,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC3C,YAAE,CAAC,SAAS,CAAC,OAAO,EAAE;YACrB,SAAS,EAAE,IAAI;YACf,IAAI,EAAE,KAAK;SACX,CAAC,CAAC;QAEH,eAAe;QACf,KAAI,MAAM,IAAI,IAAI,KAAK,EACvB;YACC,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/C,YAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;SACxD;QAED,OAAO,CAAC,GAAG,CAAC,8BAA8B,OAAO,gBAAgB,CAAC,CAAC;KACnE;IACD,OAAM,GAAG,EACT;QACC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;KAC5B;AACF,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB;IAExB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAClC,IAAG,IAAI,KAAK,SAAS,EACrB;QACC,MAAM,KAAK,CAAC,GAAG,OAAO,iBAAiB,CAAC,CAAC;KACzC;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,SAAS,UAAU;IAElB,IAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,EAC/B;QACC,UAAU;QACV,OAAO,aAAa,CAAC;KACrB;IAED,gBAAgB;IAChB,OAAO,MAAM,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,SAAS,SAAS,CAAC,KAAa;IAE/B,IAAG,KAAK,CAAC,MAAM,KAAK,CAAC,EACrB;QACC,sBAAsB;QACtB,OAAO,EAAE,CAAC;KACV;IAED,OAAO,KAAK,KAAK,EAAE,CAAC;AACrB,CAAC;AAED,IAAI,EAAE,CAAC"}

140
node_modules/@actions/core/README.md generated vendored
View File

@ -1,140 +0,0 @@
# `@actions/core`
> Core functions for setting results, logging, registering secrets and exporting variables across actions
## Usage
### Import the package
```js
// javascript
const core = require('@actions/core');
// typescript
import * as core from '@actions/core';
```
#### Inputs/Outputs
Action inputs can be read with `getInput`. Outputs can be set with `setOutput` which makes them available to be mapped into inputs of other actions to ensure they are decoupled.
```js
const myInput = core.getInput('inputName', { required: true });
core.setOutput('outputKey', 'outputVal');
```
#### Exporting variables
Since each step runs in a separate process, you can use `exportVariable` to add it to this step and future steps environment blocks.
```js
core.exportVariable('envVar', 'Val');
```
#### Setting a secret
Setting a secret registers the secret with the runner to ensure it is masked in logs.
```js
core.setSecret('myPassword');
```
#### PATH Manipulation
To make a tool's path available in the path for the remainder of the job (without altering the machine or containers state), use `addPath`. The runner will prepend the path given to the jobs PATH.
```js
core.addPath('/path/to/mytool');
```
#### Exit codes
You should use this library to set the failing exit code for your action. If status is not set and the script runs to completion, that will lead to a success.
```js
const core = require('@actions/core');
try {
// Do stuff
}
catch (err) {
// setFailed logs the message and sets a failing exit code
core.setFailed(`Action failed with error ${err}`);
}
Note that `setNeutral` is not yet implemented in actions V2 but equivalent functionality is being planned.
```
#### Logging
Finally, this library provides some utilities for logging. Note that debug logging is hidden from the logs by default. This behavior can be toggled by enabling the [Step Debug Logs](../../docs/action-debugging.md#step-debug-logs).
```js
const core = require('@actions/core');
const myInput = core.getInput('input');
try {
core.debug('Inside try block');
if (!myInput) {
core.warning('myInput was not set');
}
// Do stuff
}
catch (err) {
core.error(`Error ${err}, action may still succeed though`);
}
```
This library can also wrap chunks of output in foldable groups.
```js
const core = require('@actions/core')
// Manually wrap output
core.startGroup('Do some function')
doSomeFunction()
core.endGroup()
// Wrap an asynchronous function call
const result = await core.group('Do something async', async () => {
const response = await doSomeHTTPRequest()
return response
})
```
#### Action state
You can use this library to save state and get state for sharing information between a given wrapper action:
**action.yml**
```yaml
name: 'Wrapper action sample'
inputs:
name:
default: 'GitHub'
runs:
using: 'node12'
main: 'main.js'
post: 'cleanup.js'
```
In action's `main.js`:
```js
const core = require('@actions/core');
core.saveState("pidToKill", 12345);
```
In action's `cleanup.js`:
```js
const core = require('@actions/core');
var pid = core.getState("pidToKill");
process.kill(pid);
```

View File

@ -1,16 +0,0 @@
interface CommandProperties {
[key: string]: string;
}
/**
* Commands
*
* Command Format:
* ::name key=value,key=value::message
*
* Examples:
* ::warning::This is the message
* ::set-env name=MY_VAR::some value
*/
export declare function issueCommand(command: string, properties: CommandProperties, message: string): void;
export declare function issue(name: string, message?: string): void;
export {};

View File

@ -1,78 +0,0 @@
"use strict";
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(require("os"));
/**
* 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 (s || '')
.replace(/%/g, '%25')
.replace(/\r/g, '%0D')
.replace(/\n/g, '%0A');
}
function escapeProperty(s) {
return (s || '')
.replace(/%/g, '%25')
.replace(/\r/g, '%0D')
.replace(/\n/g, '%0A')
.replace(/:/g, '%3A')
.replace(/,/g, '%2C');
}
//# sourceMappingURL=command.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":";;;;;;;;;AAAA,uCAAwB;AAQxB;;;;;;;;;GASG;AACH,SAAgB,YAAY,CAC1B,OAAe,EACf,UAA6B,EAC7B,OAAe;IAEf,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;IACrD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAA;AAC/C,CAAC;AAPD,oCAOC;AAED,SAAgB,KAAK,CAAC,IAAY,EAAE,UAAkB,EAAE;IACtD,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;AACjC,CAAC;AAFD,sBAEC;AAED,MAAM,UAAU,GAAG,IAAI,CAAA;AAEvB,MAAM,OAAO;IAKX,YAAY,OAAe,EAAE,UAA6B,EAAE,OAAe;QACzE,IAAI,CAAC,OAAO,EAAE;YACZ,OAAO,GAAG,iBAAiB,CAAA;SAC5B;QAED,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAED,QAAQ;QACN,IAAI,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC,OAAO,CAAA;QAEtC,IAAI,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;YAC9D,MAAM,IAAI,GAAG,CAAA;YACb,IAAI,KAAK,GAAG,IAAI,CAAA;YAChB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,UAAU,EAAE;gBACjC,IAAI,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE;oBACvC,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;oBAChC,IAAI,GAAG,EAAE;wBACP,IAAI,KAAK,EAAE;4BACT,KAAK,GAAG,KAAK,CAAA;yBACd;6BAAM;4BACL,MAAM,IAAI,GAAG,CAAA;yBACd;wBAED,MAAM,IAAI,GAAG,GAAG,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAA;qBAC1C;iBACF;aACF;SACF;QAED,MAAM,IAAI,GAAG,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAA;QACpD,OAAO,MAAM,CAAA;IACf,CAAC;CACF;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;SACb,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;AAC1B,CAAC;AAED,SAAS,cAAc,CAAC,CAAS;IAC/B,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;SACb,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;AACzB,CAAC"}

View File

@ -1,112 +0,0 @@
/**
* Interface for getInput options
*/
export interface InputOptions {
/** Optional. Whether the input is required. If required and not present, will throw. Defaults to false */
required?: boolean;
}
/**
* The code to exit an action
*/
export declare enum ExitCode {
/**
* A code indicating that the action was successful
*/
Success = 0,
/**
* A code indicating that the action was a failure
*/
Failure = 1
}
/**
* 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
*/
export declare function exportVariable(name: string, val: string): void;
/**
* Registers a secret which will get masked from logs
* @param secret value of the secret
*/
export declare function setSecret(secret: string): void;
/**
* Prepends inputPath to the PATH (for this action and future actions)
* @param inputPath
*/
export declare function addPath(inputPath: string): void;
/**
* 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
*/
export declare function getInput(name: string, options?: InputOptions): string;
/**
* Sets the value of an output.
*
* @param name name of the output to set
* @param value value to store
*/
export declare function setOutput(name: string, value: string): void;
/**
* 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
*/
export declare function setFailed(message: string): void;
/**
* Writes debug message to user log
* @param message debug message
*/
export declare function debug(message: string): void;
/**
* Adds an error issue
* @param message error issue message
*/
export declare function error(message: string): void;
/**
* Adds an warning issue
* @param message warning issue message
*/
export declare function warning(message: string): void;
/**
* Writes info to log with console.log.
* @param message info message
*/
export declare function info(message: string): void;
/**
* Begin an output group.
*
* Output until the next `groupEnd` will be foldable in this group
*
* @param name The name of the output group
*/
export declare function startGroup(name: string): void;
/**
* End an output group.
*/
export declare function endGroup(): void;
/**
* 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
*/
export declare function group<T>(name: string, fn: () => Promise<T>): Promise<T>;
/**
* 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
*/
export declare function saveState(name: string, value: string): void;
/**
* Gets the value of an state set by this action's main execution.
*
* @param name name of the state to get
* @returns string
*/
export declare function getState(name: string): string;

View File

@ -1,202 +0,0 @@
"use strict";
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 = require("./command");
const os = __importStar(require("os"));
const path = __importStar(require("path"));
/**
* 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
*/
function exportVariable(name, val) {
process.env[name] = val;
command_1.issueCommand('set-env', { name }, val);
}
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) {
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
*/
function setOutput(name, value) {
command_1.issueCommand('set-output', { name }, value);
}
exports.setOutput = setOutput;
//-----------------------------------------------------------------------
// 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
//-----------------------------------------------------------------------
/**
* 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
*/
function error(message) {
command_1.issue('error', message);
}
exports.error = error;
/**
* Adds an warning issue
* @param message warning issue message
*/
function warning(message) {
command_1.issue('warning', 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
*/
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

View File

@ -1 +0,0 @@
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,uCAA6C;AAE7C,uCAAwB;AACxB,2CAA4B;AAU5B;;GAEG;AACH,IAAY,QAUX;AAVD,WAAY,QAAQ;IAClB;;OAEG;IACH,6CAAW,CAAA;IAEX;;OAEG;IACH,6CAAW,CAAA;AACb,CAAC,EAVW,QAAQ,GAAR,gBAAQ,KAAR,gBAAQ,QAUnB;AAED,yEAAyE;AACzE,YAAY;AACZ,yEAAyE;AAEzE;;;;GAIG;AACH,SAAgB,cAAc,CAAC,IAAY,EAAE,GAAW;IACtD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,CAAA;IACvB,sBAAY,CAAC,SAAS,EAAE,EAAC,IAAI,EAAC,EAAE,GAAG,CAAC,CAAA;AACtC,CAAC;AAHD,wCAGC;AAED;;;GAGG;AACH,SAAgB,SAAS,CAAC,MAAc;IACtC,sBAAY,CAAC,UAAU,EAAE,EAAE,EAAE,MAAM,CAAC,CAAA;AACtC,CAAC;AAFD,8BAEC;AAED;;;GAGG;AACH,SAAgB,OAAO,CAAC,SAAiB;IACvC,sBAAY,CAAC,UAAU,EAAE,EAAE,EAAE,SAAS,CAAC,CAAA;IACvC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,GAAG,SAAS,GAAG,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAA;AAC7E,CAAC;AAHD,0BAGC;AAED;;;;;;GAMG;AACH,SAAgB,QAAQ,CAAC,IAAY,EAAE,OAAsB;IAC3D,MAAM,GAAG,GACP,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,IAAI,EAAE,CAAA;IACrE,IAAI,OAAO,IAAI,OAAO,CAAC,QAAQ,IAAI,CAAC,GAAG,EAAE;QACvC,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,EAAE,CAAC,CAAA;KAC5D;IAED,OAAO,GAAG,CAAC,IAAI,EAAE,CAAA;AACnB,CAAC;AARD,4BAQC;AAED;;;;;GAKG;AACH,SAAgB,SAAS,CAAC,IAAY,EAAE,KAAa;IACnD,sBAAY,CAAC,YAAY,EAAE,EAAC,IAAI,EAAC,EAAE,KAAK,CAAC,CAAA;AAC3C,CAAC;AAFD,8BAEC;AAED,yEAAyE;AACzE,UAAU;AACV,yEAAyE;AAEzE;;;;GAIG;AACH,SAAgB,SAAS,CAAC,OAAe;IACvC,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAA;IACnC,KAAK,CAAC,OAAO,CAAC,CAAA;AAChB,CAAC;AAHD,8BAGC;AAED,yEAAyE;AACzE,mBAAmB;AACnB,yEAAyE;AAEzE;;;GAGG;AACH,SAAgB,KAAK,CAAC,OAAe;IACnC,sBAAY,CAAC,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;AACpC,CAAC;AAFD,sBAEC;AAED;;;GAGG;AACH,SAAgB,KAAK,CAAC,OAAe;IACnC,eAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AACzB,CAAC;AAFD,sBAEC;AAED;;;GAGG;AACH,SAAgB,OAAO,CAAC,OAAe;IACrC,eAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;AAC3B,CAAC;AAFD,0BAEC;AAED;;;GAGG;AACH,SAAgB,IAAI,CAAC,OAAe;IAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,CAAA;AACxC,CAAC;AAFD,oBAEC;AAED;;;;;;GAMG;AACH,SAAgB,UAAU,CAAC,IAAY;IACrC,eAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;AACtB,CAAC;AAFD,gCAEC;AAED;;GAEG;AACH,SAAgB,QAAQ;IACtB,eAAK,CAAC,UAAU,CAAC,CAAA;AACnB,CAAC;AAFD,4BAEC;AAED;;;;;;;GAOG;AACH,SAAsB,KAAK,CAAI,IAAY,EAAE,EAAoB;;QAC/D,UAAU,CAAC,IAAI,CAAC,CAAA;QAEhB,IAAI,MAAS,CAAA;QAEb,IAAI;YACF,MAAM,GAAG,MAAM,EAAE,EAAE,CAAA;SACpB;gBAAS;YACR,QAAQ,EAAE,CAAA;SACX;QAED,OAAO,MAAM,CAAA;IACf,CAAC;CAAA;AAZD,sBAYC;AAED,yEAAyE;AACzE,uBAAuB;AACvB,yEAAyE;AAEzE;;;;;GAKG;AACH,SAAgB,SAAS,CAAC,IAAY,EAAE,KAAa;IACnD,sBAAY,CAAC,YAAY,EAAE,EAAC,IAAI,EAAC,EAAE,KAAK,CAAC,CAAA;AAC3C,CAAC;AAFD,8BAEC;AAED;;;;;GAKG;AACH,SAAgB,QAAQ,CAAC,IAAY;IACnC,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,IAAI,EAAE,CAAA;AAC3C,CAAC;AAFD,4BAEC"}

View File

@ -1,44 +0,0 @@
{
"name": "@actions/core",
"version": "1.2.2",
"description": "Actions core lib",
"keywords": [
"github",
"actions",
"core"
],
"homepage": "https://github.com/actions/toolkit/tree/master/packages/core",
"license": "MIT",
"main": "lib/core.js",
"types": "lib/core.d.ts",
"directories": {
"lib": "lib",
"test": "__tests__"
},
"files": [
"lib"
],
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/actions/toolkit.git",
"directory": "packages/core"
},
"scripts": {
"audit-moderate": "npm install && npm audit --audit-level=moderate",
"test": "echo \"Error: run tests from root\" && exit 1",
"tsc": "tsc"
},
"bugs": {
"url": "https://github.com/actions/toolkit/issues"
},
"devDependencies": {
"@types/node": "^12.0.2"
}
,"_resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.2.tgz"
,"_integrity": "sha512-IbCx7oefq+Gi6FWbSs2Fnw8VkEI6Y4gvjrYprY3RV//ksq/KPMlClOerJ4jRosyal6zkUIc8R9fS/cpRMlGClg=="
,"_from": "@actions/core@1.2.2"
}

13086
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,19 @@
{ {
"name": "install-ssh-key", "name": "install-ssh-key",
"version": "1.6.5", "version": "2.7.0",
"private": true, "private": true,
"description": "Install SSH key in .ssh", "description": "Install SSH key in .ssh",
"main": "lib/main.js", "main": "./dist/main.js",
"engines": { "engines": {
"node": ">=8.0.0", "node": ">=8.0.0",
"npm": ">=5.7.0" "npm": ">=5.7.0"
}, },
"scripts": { "scripts": {
"build": "tsc", "build": "esbuild ./src/main.ts ./src/post.ts --bundle --platform=node --minify --sourcemap --outdir=./dist",
"check-updates": "ncu", "check-updates": "ncu",
"lint": "run-p lint:*", "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:md": "markdownlint . --ignore node_modules --ignore examples",
"lint:yaml": "yamllint **/{,.}*.{yml,yaml} --ignore=node_modules/**", "lint:yaml": "yamllint **/{,.}*.{yml,yaml} --ignore=node_modules/**",
"verify": "run-p lint" "verify": "run-p lint"
@ -30,19 +31,17 @@
], ],
"author": "shimataro", "author": "shimataro",
"license": "MIT", "license": "MIT",
"dependencies": {
"@actions/core": "1.2.2"
},
"devDependencies": { "devDependencies": {
"@types/node": "13.7.0", "@actions/core": "1.10.1",
"@typescript-eslint/eslint-plugin": "2.19.0", "@types/node": "20.11.17",
"@typescript-eslint/parser": "2.19.0", "@typescript-eslint/eslint-plugin": "6.21.0",
"eslint": "6.8.0", "@typescript-eslint/parser": "6.21.0",
"eslint-plugin-import": "2.20.1", "esbuild": "0.20.0",
"markdownlint-cli": "0.21.0", "eslint": "8.56.0",
"npm-check-updates": "4.0.1", "markdownlint-cli": "0.39.0",
"npm-check-updates": "16.14.15",
"npm-run-all": "4.1.5", "npm-run-all": "4.1.5",
"typescript": "3.7.5", "typescript": "5.3.3",
"yaml-lint": "1.2.4" "yaml-lint": "1.7.0"
} }
} }

View File

@ -1,133 +0,0 @@
#!/bin/bash
# requires following packages:
# - git; I believe it's already installed.
# - sed; GNU sed is preferred. POSIX sed may not work.
set -e
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]*}"
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 origin
${COLOR_COMMAND}git push --set-upstream origin ${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}
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
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,41 +1,59 @@
#!/bin/bash #!/bin/bash
# requires following packages: # requires following programs:
# - git; I believe it's already installed. # - git; I believe you have already installed.
# - sed; GNU sed is preferred. POSIX sed may not work. # - sed; Both GNU sed and POSIX sed will work.
set -eu
set -e GITHUB_BASE="https://github.com"
GITHUB_USER="shimataro"
GITHUB_REPO="ssh-key-action"
COLOR_ERROR="\e[1;41m" UPSTREAM="origin"
COLOR_SECTION="\e[1;34m"
COLOR_COMMAND_NAME="\e[1;34m" COLOR_ERROR="\033[1;41m"
COLOR_OPTION="\e[4;36m" COLOR_SECTION="\033[1;34m"
COLOR_COMMAND="\e[4m" COLOR_COMMAND_NAME="\033[1;34m"
COLOR_FILE="\e[1;34m" COLOR_OPTION="\033[4;36m"
COLOR_BRANCH="\e[1;31m" COLOR_COMMAND="\033[4m"
COLOR_INPUT="\e[1;31m" COLOR_FILE="\033[1;34m"
COLOR_SELECT="\e[1;32m" COLOR_BRANCH="\033[1;31m"
COLOR_RESET="\e[m" 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() { function main() {
if [ $# -lt 1 ]; then cd $(dirname ${0})/..
if [[ $# -lt 1 ]]; then
usage usage
fi 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 ${NEW_VERSION}
check_version_format ${VERSION} check_current_branch ${BASE_BRANCH}
update_changelog ${VERSION} create_branch ${BRANCH} ${BASE_BRANCH}
update_package_version ${VERSION} update_package_version ${NEW_VERSION}
update_dependencies_version update_changelog ${NEW_VERSION}
regenerate_package_lock verify_package
build_package commit_changes ${NEW_VERSION}
commit_changes ${VERSION} finish ${NEW_VERSION} ${CURRENT_VERSION} ${BRANCH} ${BASE_BRANCH} ${TAG}
} }
function usage() { function usage() {
local COMMAND=`basename ${0}` local COMMAND=$(basename ${0})
echo -e "${COLOR_SECTION}NAME${COLOR_RESET} echo -e "${COLOR_SECTION}NAME${COLOR_RESET}
${COMMAND} - Prepare for new release ${COMMAND} - Prepare for new release
@ -44,12 +62,13 @@ ${COLOR_SECTION}SYNOPSIS${COLOR_RESET}
${COLOR_COMMAND_NAME}${COMMAND}${COLOR_RESET} <${COLOR_OPTION}new-version${COLOR_RESET}> ${COLOR_COMMAND_NAME}${COMMAND}${COLOR_RESET} <${COLOR_OPTION}new-version${COLOR_RESET}>
${COLOR_SECTION}DESCRIPTION${COLOR_RESET} ${COLOR_SECTION}DESCRIPTION${COLOR_RESET}
This command: This command will...
- updates ${COLOR_FILE}CHANGELOG.md${COLOR_RESET} - create a new branch for release
- updates package version in ${COLOR_FILE}package.json${COLOR_RESET} - update ${COLOR_FILE}CHANGELOG.md${COLOR_RESET}
- updates dependencies version in ${COLOR_FILE}package.json${COLOR_RESET} - update package version in ${COLOR_FILE}package.json${COLOR_RESET}
- verifies - update dependencies version in ${COLOR_FILE}package.json${COLOR_RESET}
- ...and commits! - verify
- ...and commit!
${COLOR_OPTION}new-version${COLOR_RESET} must follow \"Semantic Versioning\" <https://semver.org/>. ${COLOR_OPTION}new-version${COLOR_RESET} must follow \"Semantic Versioning\" <https://semver.org/>.
" "
@ -57,7 +76,7 @@ ${COLOR_SECTION}DESCRIPTION${COLOR_RESET}
} }
function check_version_format() { 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 return
fi fi
@ -66,47 +85,118 @@ function check_version_format() {
exit 2 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() { function update_changelog() {
local VERSION=$1 local VERSION=$1
local DATE=`date "+%Y-%m-%d"` local DATE=`date "+%Y-%m-%d"`
local KEYWORD="Unreleased" local KEYWORD="Unreleased"
sed -i".bak" -r \ 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}/" \ -e "s/^(\[${KEYWORD}\](.*))(v.*)\.\.\.HEAD$/\1v${VERSION}...HEAD\n[${VERSION}]\2\3...v${VERSION}/" \
CHANGELOG.md CHANGELOG.md
} }
function update_package_version() { function verify_package() {
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
npm run verify npm run verify
} }
function commit_changes() { function commit_changes() {
local VERSION=$1 local VERSION=$1
rm -rf node_modules git add CHANGELOG.md package.json package-lock.json
npm ci --only=production
git add CHANGELOG.md package.json package-lock.json node_modules lib
git commit -m "version ${VERSION}" 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 "$@" main "$@"

View File

@ -1,12 +1,10 @@
#!/bin/bash #!/bin/bash
set -eu
set -e npm ci
rm -rf node_modules package-lock.json
npm i
npm run build npm run build
npm run verify npm run verify
rm -rf node_modules rm -rf node_modules
npm ci --only=production npm ci --only=production
git add node_modules package-lock.json lib git add dist

View File

@ -1,16 +1,23 @@
#!/bin/bash #!/bin/bash
# update dependencies # update dependencies
set -eu
set -e
DATE=$(date +"%Y%m%d") DATE=$(date +"%Y%m%d")
BRANCH=feature/update-dependencies-${DATE} BASE_BRANCH=$(git rev-parse --abbrev-ref HEAD)
COLOR_SUCCESS="\e[1;32m" TARGET_BRANCH=feature/update-dependencies-${DATE}
COLOR_RESET="\e[m"
# create branch COLOR_SUCCESS="\033[1;32m"
git checkout develop COLOR_ERROR="\033[1;41m"
git checkout -b ${BRANCH} 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 # check updates
npm ci npm ci
@ -19,22 +26,21 @@ npm run check-updates -- -u
# re-install packages # re-install packages
rm -rf package-lock.json node_modules rm -rf package-lock.json node_modules
npm i npm i
npm dedupe
# check # test
npm run build npm run build
npm run verify npm run verify
# commit # commit
rm -rf node_modules git add package.json package-lock.json dist
npm ci --only=production
git add package.json package-lock.json node_modules
git commit -m "update dependencies" git commit -m "update dependencies"
# finished! # finished!
echo -e " echo -e "
${COLOR_SUCCESS}🎉All dependencies are updated successfully.🎉${COLOR_RESET} ${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,120 +1,223 @@
import fs from "fs"; import * as fs from "fs";
import path from "path"; import * as path from "path";
import * as core from "@actions/core"; import * as core from "@actions/core";
interface FileInfo import * as common from "./common";
{
name: string; /** file creation info */
contents: string; interface FileInfo {
options: fs.WriteFileOptions; /** 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 * main function
*/ */
function main(): void export function main(): void {
{ const sshDirName = common.getSshDirectory();
try
{
const files: FileInfo[] = [
{
name: core.getInput("name"),
contents: core.getInput("private-key", {
required: true,
}),
options: {
mode: 0o400,
flag: "ax",
},
},
{
name: "known_hosts",
contents: prependLf(core.getInput("known-hosts")),
options: {
mode: 0o644,
flag: "a",
},
},
{
name: "config",
contents: prependLf(core.getInput("config")),
options: {
mode: 0o644,
flag: "a",
},
},
];
// create ".ssh" directory // create ".ssh" directory
const home = getHomeDirectory(); const backupSuffix = common.createBackupSuffix(sshDirName);
const dirName = path.resolve(home, ".ssh"); if (backupSuffix === "") {
fs.mkdirSync(dirName, { createDirectory(sshDirName);
recursive: true, console.log(`✅SSH directory "${sshDirName}" has been created successfully.`);
mode: 0o700, }
});
// create files // files to be created
for(const file of files) const files = buildFilesToCreate(sshDirName);
{
const fileName = path.join(dirName, file.name);
fs.writeFileSync(fileName, file.contents, file.options);
}
console.log(`SSH key has been stored to ${dirName} successfully.`); // back up & create files
} const createdFileNames: string[] = [];
catch(err) const backedUpFileNames: string[] = [];
{ for (const file of files) {
core.setFailed(err.message); 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 * build files to create
* @returns home directory * @param dirName directory name in where files will be created
* @returns files
*/ */
function getHomeDirectory(): string function buildFilesToCreate(dirName: string): FileInfo[] {
{ // parameters
const homeEnv = getHomeEnv(); const key = core.getInput("key", {
const home = process.env[homeEnv]; required: true,
if(home === undefined) });
{ const name = core.getInput("name");
throw Error(`${homeEnv} is not defined`); const knownHosts = core.getInput("known_hosts", {
} required: true,
});
const config = core.getInput("config");
const ifKeyExists = core.getInput("if_key_exists");
return home; // 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 files;
} }
/** /**
* get HOME environment name * create directory
* @returns HOME environment name * @param dirName directory name to remove
*/ */
function getHomeEnv(): string function createDirectory(dirName: string): void {
{ fs.mkdirSync(dirName, {
if(process.platform === "win32") recursive: true,
{ mode: 0o700,
// Windows });
return "USERPROFILE";
}
// macOS / Linux
return "HOME";
} }
/** /**
* prepend LF to value if not empty * back up file
* @param value the value to prepend LF * @param fileName file to back up
* @returns prepended value * @param backupSuffix suffix
* @param removeOrig remove original file
* @returns is file backed up?
*/ */
function prependLf(value: string): string function backup(fileName: string, backupSuffix: string, removeOrig: boolean): boolean {
{ if (backupSuffix === "") {
if(value.length === 0) return false;
{ }
// do nothing if empty if (!fs.existsSync(fileName)) {
return ""; return false;
} }
return `\n${value}`; // 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;
} }
main(); /**
* 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: 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`;
}
return affectedValue;
}
/**
* 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": { "compilerOptions": {
"target": "es6", "target": "es6",
"module": "commonjs", "module": "commonjs",
"moduleResolution": "node",
"lib": [ "lib": [
"es6" "es6"
], ],
"sourceMap": true, "sourceMap": true,
"outDir": "./lib", "outDir": "./dist",
"rootDir": "./src", "rootDir": "./src",
"strict": true, "strict": true,