From 4512be8010f262a32b74d4b4a59300d76bdd43c6 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Tue, 25 Oct 2022 17:23:31 +0200 Subject: [PATCH 01/17] Update to `actions/checkout@v3` (#143) --- .github/workflows/demo.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/demo.yml b/.github/workflows/demo.yml index 9d8fad0..1cfd2a1 100644 --- a/.github/workflows/demo.yml +++ b/.github/workflows/demo.yml @@ -8,7 +8,7 @@ jobs: os: [ ubuntu-latest, macOS-latest, windows-latest ] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup key uses: ./ with: @@ -28,7 +28,7 @@ jobs: container: image: ubuntu:latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - run: apt update && apt install -y openssh-client git - name: Setup key uses: ./ From 2996779c087b05cb911c8fefc8403a8af8d8f2d4 Mon Sep 17 00:00:00 2001 From: Patrick Higgins Date: Fri, 25 Nov 2022 10:40:39 -0800 Subject: [PATCH 02/17] Replace 0.6.0 references with 0.7.0 in README.md (#153) --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 63d86fd..22c6a25 100644 --- a/README.md +++ b/README.md @@ -36,9 +36,9 @@ jobs: ... steps: - actions/checkout@v2 - # Make sure the @v0.6.0 matches the current version of the + # Make sure the @v0.7.0 matches the current version of the # action - - uses: webfactory/ssh-agent@v0.6.0 + - uses: webfactory/ssh-agent@v0.7.0 with: ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} - ... other steps @@ -53,7 +53,7 @@ You can set up different keys as different secrets and pass them all to the acti ```yaml # ... contens as before - - uses: webfactory/ssh-agent@v0.6.0 + - uses: webfactory/ssh-agent@v0.7.0 with: ssh-private-key: | ${{ secrets.FIRST_KEY }} From 18ff7066d37af765c4268af534ab1500bc3ea7f9 Mon Sep 17 00:00:00 2001 From: kjarkur <108679036+kjarkur@users.noreply.github.com> Date: Fri, 25 Nov 2022 10:44:41 -0800 Subject: [PATCH 03/17] Update README.md (#147) Update `actions/checkout` to `@v3` and make it syntactically correct in order to allow copy and paste. Co-authored-by: Matthias Pigulla --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 22c6a25..c2bdecb 100644 --- a/README.md +++ b/README.md @@ -35,13 +35,12 @@ jobs: my_job: ... steps: - - actions/checkout@v2 - # Make sure the @v0.7.0 matches the current version of the - # action + - uses: actions/checkout@v3 + # Make sure the @v0.7.0 matches the current version of the action - uses: webfactory/ssh-agent@v0.7.0 with: ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} - - ... other steps + # ... other steps ``` 5. If, for some reason, you need to change the location of the SSH agent socket, you can use the `ssh-auth-sock` input to provide a path. From 209e2d72ff4a448964d26610aceaaf1b3f8764c6 Mon Sep 17 00:00:00 2001 From: kjarkur <108679036+kjarkur@users.noreply.github.com> Date: Fri, 25 Nov 2022 10:45:57 -0800 Subject: [PATCH 04/17] Fix a typo in the README.md (#146) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c2bdecb..c7f826a 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ There are cases where you might need to use multiple keys. For example, "[deploy You can set up different keys as different secrets and pass them all to the action like so: ```yaml -# ... contens as before +# ... contents as before - uses: webfactory/ssh-agent@v0.7.0 with: ssh-private-key: | From 6f828ccb51b0d042f4783ff45710decae9836d37 Mon Sep 17 00:00:00 2001 From: Dilum Aluthge Date: Fri, 27 Jan 2023 12:09:18 -0500 Subject: [PATCH 05/17] Allow the user to override the commands for `git`, `ssh-agent`, and `ssh-add` (#154) On my self-hosted Windows runners, the `git`, `ssh-agent`, and `ssh-add` commands are not located in the locations that are currently hard-coded in `paths.js`. With this PR, I am able to get this action to work on my runners as follows: ```yaml - uses: webfactory/ssh-agent@... with: ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} git-cmd: git ssh-agent-cmd: ssh-agent ssh-add-cmd: ssh-add ``` --- README.md | 3 +++ action.yml | 9 +++++++++ dist/cleanup.js | 12 ++++++------ dist/index.js | 22 +++++++++++++++------- index.js | 10 +++++++++- paths.js | 12 ++++++------ 6 files changed, 48 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index c7f826a..8e2416b 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,9 @@ The following inputs can be used to control the action's behavior: * `ssh-private-key`: Required. Use this to provide the key(s) to load as GitHub Actions secrets. * `ssh-auth-sock`: Can be used to control where the SSH agent socket will be placed. Ultimately affects the `$SSH_AUTH_SOCK` environment variable. * `log-public-key`: Set this to `false` if you want to suppress logging of _public_ key information. To simplify debugging and since it contains public key information only, this is turned on by default. +* `ssh-agent-cmd`: Optional. Use this to specify a custom location for the `ssh-agent` binary. +* `ssh-add-cmd`: Optional. Use this to specify a custom location for the `ssh-add` binary. +* `git-cmd`: Optional. Use this to specify a custom location for the `git` binary. ## Exported variables diff --git a/action.yml b/action.yml index ec3dfd9..4c54ef5 100644 --- a/action.yml +++ b/action.yml @@ -10,6 +10,15 @@ inputs: description: 'Whether or not to log public key fingerprints' required: false default: true + ssh-agent-cmd: + description: 'ssh-agent command' + required: false + ssh-add-cmd: + description: 'ssh-add command' + required: false + git-cmd: + description: 'git command' + required: false runs: using: 'node16' main: 'dist/index.js' diff --git a/dist/cleanup.js b/dist/cleanup.js index 8af40c8..bc904c0 100644 --- a/dist/cleanup.js +++ b/dist/cleanup.js @@ -2827,15 +2827,15 @@ module.exports = (process.env['OS'] != 'Windows_NT') ? { // Use getent() system call, since this is what ssh does; makes a difference in Docker-based // Action runs, where $HOME is different from the pwent homePath: os.userInfo().homedir, - sshAgentCmd: 'ssh-agent', - sshAddCmd: 'ssh-add', - gitCmd: 'git' + sshAgentCmdDefault: 'ssh-agent', + sshAddCmdDefault: 'ssh-add', + gitCmdDefault: 'git' } : { // Assuming GitHub hosted `windows-*` runners for now homePath: os.homedir(), - sshAgentCmd: 'c://progra~1//git//usr//bin//ssh-agent.exe', - sshAddCmd: 'c://progra~1//git//usr//bin//ssh-add.exe', - gitCmd: 'c://progra~1//git//bin//git.exe' + sshAgentCmdDefault: 'c://progra~1//git//usr//bin//ssh-agent.exe', + sshAddCmdDefault: 'c://progra~1//git//usr//bin//ssh-add.exe', + gitCmdDefault: 'c://progra~1//git//bin//git.exe' }; diff --git a/dist/index.js b/dist/index.js index 3039a0b..ce61449 100644 --- a/dist/index.js +++ b/dist/index.js @@ -322,12 +322,20 @@ const core = __webpack_require__(470); const child_process = __webpack_require__(129); const fs = __webpack_require__(747); const crypto = __webpack_require__(417); -const { homePath, sshAgentCmd, sshAddCmd, gitCmd } = __webpack_require__(972); +const { homePath, sshAgentCmdDefault, sshAddCmdDefault, gitCmdDefault } = __webpack_require__(972); try { const privateKey = core.getInput('ssh-private-key'); const logPublicKey = core.getBooleanInput('log-public-key', {default: true}); + const sshAgentCmdInput = core.getInput('ssh-agent-cmd'); + const sshAddCmdInput = core.getInput('ssh-add-cmd'); + const gitCmdInput = core.getInput('git-cmd'); + + const sshAgentCmd = sshAgentCmdInput ? sshAgentCmdInput : sshAgentCmdDefault + const sshAddCmd = sshAddCmdInput ? sshAddCmdInput : sshAddCmdDefault + const gitCmd = gitCmdInput ? gitCmdInput : gitCmdDefault + if (!privateKey) { core.setFailed("The ssh-private-key argument is empty. Maybe the secret has not been configured, or you are using a wrong secret name in your workflow file."); @@ -2906,15 +2914,15 @@ module.exports = (process.env['OS'] != 'Windows_NT') ? { // Use getent() system call, since this is what ssh does; makes a difference in Docker-based // Action runs, where $HOME is different from the pwent homePath: os.userInfo().homedir, - sshAgentCmd: 'ssh-agent', - sshAddCmd: 'ssh-add', - gitCmd: 'git' + sshAgentCmdDefault: 'ssh-agent', + sshAddCmdDefault: 'ssh-add', + gitCmdDefault: 'git' } : { // Assuming GitHub hosted `windows-*` runners for now homePath: os.homedir(), - sshAgentCmd: 'c://progra~1//git//usr//bin//ssh-agent.exe', - sshAddCmd: 'c://progra~1//git//usr//bin//ssh-add.exe', - gitCmd: 'c://progra~1//git//bin//git.exe' + sshAgentCmdDefault: 'c://progra~1//git//usr//bin//ssh-agent.exe', + sshAddCmdDefault: 'c://progra~1//git//usr//bin//ssh-add.exe', + gitCmdDefault: 'c://progra~1//git//bin//git.exe' }; diff --git a/index.js b/index.js index add5f7c..549bc00 100644 --- a/index.js +++ b/index.js @@ -2,12 +2,20 @@ const core = require('@actions/core'); const child_process = require('child_process'); const fs = require('fs'); const crypto = require('crypto'); -const { homePath, sshAgentCmd, sshAddCmd, gitCmd } = require('./paths.js'); +const { homePath, sshAgentCmdDefault, sshAddCmdDefault, gitCmdDefault } = require('./paths.js'); try { const privateKey = core.getInput('ssh-private-key'); const logPublicKey = core.getBooleanInput('log-public-key', {default: true}); + const sshAgentCmdInput = core.getInput('ssh-agent-cmd'); + const sshAddCmdInput = core.getInput('ssh-add-cmd'); + const gitCmdInput = core.getInput('git-cmd'); + + const sshAgentCmd = sshAgentCmdInput ? sshAgentCmdInput : sshAgentCmdDefault; + const sshAddCmd = sshAddCmdInput ? sshAddCmdInput : sshAddCmdDefault; + const gitCmd = gitCmdInput ? gitCmdInput : gitCmdDefault; + if (!privateKey) { core.setFailed("The ssh-private-key argument is empty. Maybe the secret has not been configured, or you are using a wrong secret name in your workflow file."); diff --git a/paths.js b/paths.js index fa2c366..1c6fbf0 100644 --- a/paths.js +++ b/paths.js @@ -4,13 +4,13 @@ module.exports = (process.env['OS'] != 'Windows_NT') ? { // Use getent() system call, since this is what ssh does; makes a difference in Docker-based // Action runs, where $HOME is different from the pwent homePath: os.userInfo().homedir, - sshAgentCmd: 'ssh-agent', - sshAddCmd: 'ssh-add', - gitCmd: 'git' + sshAgentCmdDefault: 'ssh-agent', + sshAddCmdDefault: 'ssh-add', + gitCmdDefault: 'git' } : { // Assuming GitHub hosted `windows-*` runners for now homePath: os.homedir(), - sshAgentCmd: 'c://progra~1//git//usr//bin//ssh-agent.exe', - sshAddCmd: 'c://progra~1//git//usr//bin//ssh-add.exe', - gitCmd: 'c://progra~1//git//bin//git.exe' + sshAgentCmdDefault: 'c://progra~1//git//usr//bin//ssh-agent.exe', + sshAddCmdDefault: 'c://progra~1//git//usr//bin//ssh-add.exe', + gitCmdDefault: 'c://progra~1//git//bin//git.exe' }; From 9fbc246995ce195568ea31d1110c161283c89684 Mon Sep 17 00:00:00 2001 From: j-riebe <52535122+j-riebe@users.noreply.github.com> Date: Fri, 27 Jan 2023 18:32:35 +0100 Subject: [PATCH 06/17] Clarify usage for Docker build processes, especially with deployment keys (#145) The current docs mention only `docker/build-push-action` in conjunction with deploy keys. This might mislead users to believe, that this only applies to said Action. But the concept applies to all workflows that somehow use `docker build` with deploy keys. This PR clarifies the relevant section. Co-authored-by: Matthias Pigulla --- README.md | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 8e2416b..fdf936f 100644 --- a/README.md +++ b/README.md @@ -112,9 +112,11 @@ If you know that your favorite tool or platform of choice requires extra tweaks If you are using this action on container-based workflows, make sure the container has the necessary SSH binaries or package(s) installed. -### Using the `docker/build-push-action` Action +### Building Docker Images and/or Using the `docker/build-push-action` Action -If you are using the `docker/build-push-action`, and would like to pass the SSH key, you can do so by adding the following config to pass the socket file through: +When you are building Docker images with `docker build` or `docker compose build` and need to provide the SSH keys to the build, don't forget to pass `--ssh default=${{ env.SSH_AUTH_SOCK }}` on the command line to pass the SSH agent socket through. See the [Docker documentation](https://docs.docker.com/engine/reference/commandline/buildx_build/#ssh) for more information on this option. + +If you are using the `docker/build-push-action`, you can do so by adding the following config. ```yml - name: Build and push @@ -125,35 +127,45 @@ If you are using the `docker/build-push-action`, and would like to pass the SSH default=${{ env.SSH_AUTH_SOCK }} ``` -### Using the `docker/build-push-action` Action together with multiple Deploy Keys +Make sure not to miss the next section, though. -If you use the `docker/build-push-action` and want to use multiple GitHub deploy keys, you need to copy the git and ssh configuration to the container during the build. Otherwise, the Docker build process would still not know how to handle multiple deploy keys. Even if the ssh agent was set up correctly on the runner. +### Using Multiple Deploy Keys Inside Docker Builds -This requires an additional step in the actions workflow and two additional lines in the Dockerfile. +When you pass the SSH agent socket to the Docker build environment _and_ want to use multiple GitHub deploy keys, you need to copy the Git and SSH configuration files to the build environment as well. This is necessary _in addition to_ forwarding the SSH agent socket into the build process. The config files are required so that Git can pick the right one from your deployment keys. + +This requires an additional step in the workflow file **after** the `ssh-agent` step and **before** the Docker build step. You also need two additional lines in the `Dockerfile` to actually copy the configs. + +The following example will: +* collect the necessary Git and SSH configuration files in a directory that must be part of the Docker build context so that... +* ... the files can be copied into the Docker image (or an intermediate build stage). Workflow: + ```yml - - name: Prepare git and ssh config for build context + - name: ssh-agent setup + ... + + - name: Collect Git and SSH config files in a directory that is part of the Docker build context run: | mkdir root-config cp -r ~/.gitconfig ~/.ssh root-config/ - - name: Build and push - id: docker_build - uses: docker/build-push-action@v2 - with: - ssh: | - default=${{ env.SSH_AUTH_SOCK }} + - name: Docker build + # build-push-action | docker [compose] build | etc. + ... ``` Dockerfile: + ```Dockerfile +# Copy the two files in place and fix different path/locations inside the Docker image COPY root-config /root/ RUN sed 's|/home/runner|/root|g' -i.bak /root/.ssh/config ``` -Have in mind that the Dockerfile now contains customized git and ssh configurations. If you don't want that in your final image, use multi-stage builds. +Keep in mind that the resulting Docker image now might contain these customized Git and SSH configuration files! Your private SSH keys are never written to files anywhere, just loaded into the SSH agent and forwarded into the container. The config files might, however, give away details about your build or development process and contain the names and URLs of your (private) repositories. You might want to use a multi-staged build to make sure these files do not end up in the final image. +If you still get the error message: `fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.`, you most likely forgot one of the steps above. ### Cargo's (Rust) Private Dependencies on Windows From ea17a056b908d85ca1f46c275ab91389eb65c9fa Mon Sep 17 00:00:00 2001 From: Dilum Aluthge Date: Sat, 28 Jan 2023 02:20:24 -0500 Subject: [PATCH 07/17] Add missing semicolons (#159) Follow-up to #154 --- dist/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/index.js b/dist/index.js index ce61449..bdebdb8 100644 --- a/dist/index.js +++ b/dist/index.js @@ -332,9 +332,9 @@ try { const sshAddCmdInput = core.getInput('ssh-add-cmd'); const gitCmdInput = core.getInput('git-cmd'); - const sshAgentCmd = sshAgentCmdInput ? sshAgentCmdInput : sshAgentCmdDefault - const sshAddCmd = sshAddCmdInput ? sshAddCmdInput : sshAddCmdDefault - const gitCmd = gitCmdInput ? gitCmdInput : gitCmdDefault + const sshAgentCmd = sshAgentCmdInput ? sshAgentCmdInput : sshAgentCmdDefault; + const sshAddCmd = sshAddCmdInput ? sshAddCmdInput : sshAddCmdDefault; + const gitCmd = gitCmdInput ? gitCmdInput : gitCmdDefault; if (!privateKey) { core.setFailed("The ssh-private-key argument is empty. Maybe the secret has not been configured, or you are using a wrong secret name in your workflow file."); From d4b9b8ff72958532804b70bbe600ad43b36d5f2e Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Fri, 24 Mar 2023 12:15:25 +0100 Subject: [PATCH 08/17] Stop adding GitHub SSH keys (#171) We need to fix the SSH keys shipped with this action: https://github.blog/2023-03-23-we-updated-our-rsa-ssh-host-key/ But, we have another issue (https://github.com/webfactory/ssh-agent/pull/108) with regards to host keys: On self-hosted runners which are not ephemeral the known_host file fills up with repeated entries, because every action run adds a new line with the same host keys. Also, on those machines, the old key will still be in the `known_hosts` file. IMHO this action should not be repsonsible for shipping SSH host keys, that's too much responsibility. This section in the code is a leftover from early days when GitHub provided runners did not include SSH keys at all. For a long time already, GH takes care of placing their SSH keys in their runner images. For self-hosted runners, those people setting up the runner should fetch and verify SSH keys themselves and put it into the `known_hosts` file. I know this is a breaking change and is going to annoy users. But on the other hand, there is no better opportunity to drop this feature than with an emergency-style key revocation as today. Closes #106, closes #129, closes #169, closes #170, closes #172. --- README.md | 2 +- dist/cleanup.js | 57 +++++++++++++++++++++++++++----------------- dist/index.js | 63 ++++++++++++++++++++++++++++--------------------- index.js | 6 ----- 4 files changed, 73 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index fdf936f..46c74a5 100644 --- a/README.md +++ b/README.md @@ -272,4 +272,4 @@ developer looking for new challenges, we'd like to hear from you! - - -Copyright 2019 – 2022 webfactory GmbH, Bonn. Code released under [the MIT license](LICENSE). +Copyright 2019 – 2023 webfactory GmbH, Bonn. Code released under [the MIT license](LICENSE). diff --git a/dist/cleanup.js b/dist/cleanup.js index bc904c0..61fc276 100644 --- a/dist/cleanup.js +++ b/dist/cleanup.js @@ -292,13 +292,14 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.issueCommand = void 0; +exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; // We use any as a valid input type /* eslint-disable @typescript-eslint/no-explicit-any */ const fs = __importStar(__webpack_require__(747)); const os = __importStar(__webpack_require__(87)); +const uuid_1 = __webpack_require__(62); const utils_1 = __webpack_require__(82); -function issueCommand(command, message) { +function issueFileCommand(command, message) { const filePath = process.env[`GITHUB_${command}`]; if (!filePath) { throw new Error(`Unable to find environment variable for file command ${command}`); @@ -310,7 +311,22 @@ function issueCommand(command, message) { encoding: 'utf8' }); } -exports.issueCommand = issueCommand; +exports.issueFileCommand = issueFileCommand; +function prepareKeyValueMessage(key, value) { + const delimiter = `ghadelimiter_${uuid_1.v4()}`; + const convertedValue = utils_1.toCommandValue(value); + // These should realistically never happen, but just in case someone finds a + // way to exploit uuid generation let's not allow keys or values that contain + // the delimiter. + if (key.includes(delimiter)) { + throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); + } + if (convertedValue.includes(delimiter)) { + throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); + } + return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; +} +exports.prepareKeyValueMessage = prepareKeyValueMessage; //# sourceMappingURL=file-command.js.map /***/ }), @@ -1668,7 +1684,6 @@ const file_command_1 = __webpack_require__(102); const utils_1 = __webpack_require__(82); const os = __importStar(__webpack_require__(87)); const path = __importStar(__webpack_require__(622)); -const uuid_1 = __webpack_require__(62); const oidc_utils_1 = __webpack_require__(742); /** * The code to exit an action @@ -1698,20 +1713,9 @@ function exportVariable(name, val) { process.env[name] = convertedVal; const filePath = process.env['GITHUB_ENV'] || ''; if (filePath) { - const delimiter = `ghadelimiter_${uuid_1.v4()}`; - // These should realistically never happen, but just in case someone finds a way to exploit uuid generation let's not allow keys or values that contain the delimiter. - if (name.includes(delimiter)) { - throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); - } - if (convertedVal.includes(delimiter)) { - throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); - } - const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`; - file_command_1.issueCommand('ENV', commandValue); - } - else { - command_1.issueCommand('set-env', { name }, convertedVal); + return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val)); } + command_1.issueCommand('set-env', { name }, convertedVal); } exports.exportVariable = exportVariable; /** @@ -1729,7 +1733,7 @@ exports.setSecret = setSecret; function addPath(inputPath) { const filePath = process.env['GITHUB_PATH'] || ''; if (filePath) { - file_command_1.issueCommand('PATH', inputPath); + file_command_1.issueFileCommand('PATH', inputPath); } else { command_1.issueCommand('add-path', {}, inputPath); @@ -1769,7 +1773,10 @@ function getMultilineInput(name, options) { const inputs = getInput(name, options) .split('\n') .filter(x => x !== ''); - return inputs; + if (options && options.trimWhitespace === false) { + return inputs; + } + return inputs.map(input => input.trim()); } exports.getMultilineInput = getMultilineInput; /** @@ -1802,8 +1809,12 @@ exports.getBooleanInput = getBooleanInput; */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function setOutput(name, value) { + const filePath = process.env['GITHUB_OUTPUT'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('OUTPUT', file_command_1.prepareKeyValueMessage(name, value)); + } process.stdout.write(os.EOL); - command_1.issueCommand('set-output', { name }, value); + command_1.issueCommand('set-output', { name }, utils_1.toCommandValue(value)); } exports.setOutput = setOutput; /** @@ -1932,7 +1943,11 @@ exports.group = group; */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function saveState(name, value) { - command_1.issueCommand('save-state', { name }, value); + const filePath = process.env['GITHUB_STATE'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('STATE', file_command_1.prepareKeyValueMessage(name, value)); + } + command_1.issueCommand('save-state', { name }, utils_1.toCommandValue(value)); } exports.saveState = saveState; /** diff --git a/dist/index.js b/dist/index.js index bdebdb8..2c23f23 100644 --- a/dist/index.js +++ b/dist/index.js @@ -292,13 +292,14 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.issueCommand = void 0; +exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; // We use any as a valid input type /* eslint-disable @typescript-eslint/no-explicit-any */ const fs = __importStar(__webpack_require__(747)); const os = __importStar(__webpack_require__(87)); +const uuid_1 = __webpack_require__(62); const utils_1 = __webpack_require__(82); -function issueCommand(command, message) { +function issueFileCommand(command, message) { const filePath = process.env[`GITHUB_${command}`]; if (!filePath) { throw new Error(`Unable to find environment variable for file command ${command}`); @@ -310,7 +311,22 @@ function issueCommand(command, message) { encoding: 'utf8' }); } -exports.issueCommand = issueCommand; +exports.issueFileCommand = issueFileCommand; +function prepareKeyValueMessage(key, value) { + const delimiter = `ghadelimiter_${uuid_1.v4()}`; + const convertedValue = utils_1.toCommandValue(value); + // These should realistically never happen, but just in case someone finds a + // way to exploit uuid generation let's not allow keys or values that contain + // the delimiter. + if (key.includes(delimiter)) { + throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); + } + if (convertedValue.includes(delimiter)) { + throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); + } + return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; +} +exports.prepareKeyValueMessage = prepareKeyValueMessage; //# sourceMappingURL=file-command.js.map /***/ }), @@ -343,13 +359,7 @@ try { } const homeSsh = homePath + '/.ssh'; - - console.log(`Adding GitHub.com keys to ${homeSsh}/known_hosts`); - fs.mkdirSync(homeSsh, { recursive: true }); - fs.appendFileSync(`${homeSsh}/known_hosts`, '\ngithub.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=\n'); - fs.appendFileSync(`${homeSsh}/known_hosts`, '\ngithub.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl\n'); - fs.appendFileSync(`${homeSsh}/known_hosts`, '\ngithub.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==\n'); console.log("Starting ssh-agent"); @@ -1755,7 +1765,6 @@ const file_command_1 = __webpack_require__(102); const utils_1 = __webpack_require__(82); const os = __importStar(__webpack_require__(87)); const path = __importStar(__webpack_require__(622)); -const uuid_1 = __webpack_require__(62); const oidc_utils_1 = __webpack_require__(742); /** * The code to exit an action @@ -1785,20 +1794,9 @@ function exportVariable(name, val) { process.env[name] = convertedVal; const filePath = process.env['GITHUB_ENV'] || ''; if (filePath) { - const delimiter = `ghadelimiter_${uuid_1.v4()}`; - // These should realistically never happen, but just in case someone finds a way to exploit uuid generation let's not allow keys or values that contain the delimiter. - if (name.includes(delimiter)) { - throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); - } - if (convertedVal.includes(delimiter)) { - throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); - } - const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`; - file_command_1.issueCommand('ENV', commandValue); - } - else { - command_1.issueCommand('set-env', { name }, convertedVal); + return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val)); } + command_1.issueCommand('set-env', { name }, convertedVal); } exports.exportVariable = exportVariable; /** @@ -1816,7 +1814,7 @@ exports.setSecret = setSecret; function addPath(inputPath) { const filePath = process.env['GITHUB_PATH'] || ''; if (filePath) { - file_command_1.issueCommand('PATH', inputPath); + file_command_1.issueFileCommand('PATH', inputPath); } else { command_1.issueCommand('add-path', {}, inputPath); @@ -1856,7 +1854,10 @@ function getMultilineInput(name, options) { const inputs = getInput(name, options) .split('\n') .filter(x => x !== ''); - return inputs; + if (options && options.trimWhitespace === false) { + return inputs; + } + return inputs.map(input => input.trim()); } exports.getMultilineInput = getMultilineInput; /** @@ -1889,8 +1890,12 @@ exports.getBooleanInput = getBooleanInput; */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function setOutput(name, value) { + const filePath = process.env['GITHUB_OUTPUT'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('OUTPUT', file_command_1.prepareKeyValueMessage(name, value)); + } process.stdout.write(os.EOL); - command_1.issueCommand('set-output', { name }, value); + command_1.issueCommand('set-output', { name }, utils_1.toCommandValue(value)); } exports.setOutput = setOutput; /** @@ -2019,7 +2024,11 @@ exports.group = group; */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function saveState(name, value) { - command_1.issueCommand('save-state', { name }, value); + const filePath = process.env['GITHUB_STATE'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('STATE', file_command_1.prepareKeyValueMessage(name, value)); + } + command_1.issueCommand('save-state', { name }, utils_1.toCommandValue(value)); } exports.saveState = saveState; /** diff --git a/index.js b/index.js index 549bc00..0c2e08b 100644 --- a/index.js +++ b/index.js @@ -23,13 +23,7 @@ try { } const homeSsh = homePath + '/.ssh'; - - console.log(`Adding GitHub.com keys to ${homeSsh}/known_hosts`); - fs.mkdirSync(homeSsh, { recursive: true }); - fs.appendFileSync(`${homeSsh}/known_hosts`, '\ngithub.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=\n'); - fs.appendFileSync(`${homeSsh}/known_hosts`, '\ngithub.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl\n'); - fs.appendFileSync(`${homeSsh}/known_hosts`, '\ngithub.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==\n'); console.log("Starting ssh-agent"); From fd34b8dee206fe74b288a5e61bc95fba2f1911eb Mon Sep 17 00:00:00 2001 From: wolf++ Date: Thu, 2 Nov 2023 09:03:13 -0700 Subject: [PATCH 09/17] Update README.md to reflect latest version (#196) --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 46c74a5..96f0dae 100644 --- a/README.md +++ b/README.md @@ -36,8 +36,8 @@ jobs: ... steps: - uses: actions/checkout@v3 - # Make sure the @v0.7.0 matches the current version of the action - - uses: webfactory/ssh-agent@v0.7.0 + # Make sure the @v0.8.0 matches the current version of the action + - uses: webfactory/ssh-agent@v0.8.0 with: ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} # ... other steps @@ -52,7 +52,7 @@ You can set up different keys as different secrets and pass them all to the acti ```yaml # ... contents as before - - uses: webfactory/ssh-agent@v0.7.0 + - uses: webfactory/ssh-agent@v0.8.0 with: ssh-private-key: | ${{ secrets.FIRST_KEY }} From 2e59dd7d06f6a994bb6366e0639c13fb756e8bb6 Mon Sep 17 00:00:00 2001 From: Benjamin Ragheb Date: Mon, 5 Feb 2024 01:37:14 -0500 Subject: [PATCH 10/17] Remove outdated claim from README (#206) Since #171 was merged, this action no longer touches `known_hosts`; this line should have been removed from the README at that time. --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 96f0dae..253a405 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ # `ssh-agent` GitHub Action -This action -* starts the `ssh-agent`, -* exports the `SSH_AUTH_SOCK` environment variable, -* loads one or several private SSH key into the agent and -* configures `known_hosts` for GitHub.com. +This action +* starts the `ssh-agent`, +* exports the `SSH_AUTH_SOCK` environment variable, and +* loads one or several private SSH key into the agent. It should work in all GitHub Actions virtual environments, including container-based workflows. From 9f6f312a31523794f99d8264ed8b069d8a395733 Mon Sep 17 00:00:00 2001 From: Felix Seifert Date: Tue, 6 Feb 2024 09:38:02 +0100 Subject: [PATCH 11/17] chore: update all versions of `actions/checkout` to v4 (#199) In this PR, I update the `actions/checkout` versions. When I recently started using this action, I was confused about whether it works with the newest checkout action. I tested it and everything is fine. For future users, we should display examples with the newest versions. --- .github/workflows/demo.yml | 4 ++-- README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/demo.yml b/.github/workflows/demo.yml index 1cfd2a1..42a1e26 100644 --- a/.github/workflows/demo.yml +++ b/.github/workflows/demo.yml @@ -8,7 +8,7 @@ jobs: os: [ ubuntu-latest, macOS-latest, windows-latest ] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup key uses: ./ with: @@ -28,7 +28,7 @@ jobs: container: image: ubuntu:latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: apt update && apt install -y openssh-client git - name: Setup key uses: ./ diff --git a/README.md b/README.md index 253a405..cc19dbc 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ GitHub Actions only have access to the repository they run for. So, in order to * In your repository, go to the *Settings > Secrets* menu and create a new secret. In this example, we'll call it `SSH_PRIVATE_KEY`. * Put the contents of the *private* SSH key file into the contents field.
* This key should start with `-----BEGIN ... PRIVATE KEY-----`, consist of many lines and ends with `-----END ... PRIVATE KEY-----`. -5. In your workflow definition file, add the following step. Preferably this would be rather on top, near the `actions/checkout@v2` line. +5. In your workflow definition file, add the following step. Preferably this would be rather on top, near the `actions/checkout@v4` line. ```yaml # .github/workflows/my-workflow.yml @@ -34,7 +34,7 @@ jobs: my_job: ... steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 # Make sure the @v0.8.0 matches the current version of the action - uses: webfactory/ssh-agent@v0.8.0 with: From 204eb35a4ecff7628304146c9d326f72b532fc1f Mon Sep 17 00:00:00 2001 From: Kevin Glavin Date: Tue, 6 Feb 2024 04:26:21 -0500 Subject: [PATCH 12/17] Bump to `node20` (#201) Fix for deprecated node16 Node.js 16 actions are deprecated. Please update the following actions to use Node.js 20: webfactory/ssh-agent@v0.8.0. For more information see: https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/ --- action.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 4c54ef5..8f32cc8 100644 --- a/action.yml +++ b/action.yml @@ -20,10 +20,11 @@ inputs: description: 'git command' required: false runs: - using: 'node16' + using: 'node20' main: 'dist/index.js' post: 'dist/cleanup.js' post-if: 'always()' + branding: icon: loader color: 'yellow' From dc588b651fe13675774614f8e6a936a468676387 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Tue, 6 Feb 2024 10:28:20 +0100 Subject: [PATCH 13/17] Update version numbers in the README examples --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cc19dbc..3028201 100644 --- a/README.md +++ b/README.md @@ -35,8 +35,8 @@ jobs: ... steps: - uses: actions/checkout@v4 - # Make sure the @v0.8.0 matches the current version of the action - - uses: webfactory/ssh-agent@v0.8.0 + # Make sure the @v0.9.0 matches the current version of the action + - uses: webfactory/ssh-agent@v0.9.0 with: ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} # ... other steps @@ -51,7 +51,7 @@ You can set up different keys as different secrets and pass them all to the acti ```yaml # ... contents as before - - uses: webfactory/ssh-agent@v0.8.0 + - uses: webfactory/ssh-agent@v0.9.0 with: ssh-private-key: | ${{ secrets.FIRST_KEY }} From b504c19775343714e11b8c754e4fe1f02dc7b8e7 Mon Sep 17 00:00:00 2001 From: Jano Paetzold Date: Wed, 8 Jan 2025 17:52:14 +0100 Subject: [PATCH 14/17] Update CHANGELOG.md --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 811af67..572a902 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## v0.9.0 [2024-02-06] + +### Changed + +* Update all versions of `actions/checkout` to v4 (#199) +* Update to Node 20 (#201) + +## v0.8.0 [2023-03-24] + +### Changed + +* No longer writing GitHub's SSH host keys to `known_hosts` (#171) +* Update to actions/checkout@v3 (#143) +* Allow the user to override the commands for git, ssh-agent, and ssh-add (#154) + ## v0.7.0 [2022-10-19] ### Added From e3f1a8e046525bfed3725ef54a31ca91aed399f4 Mon Sep 17 00:00:00 2001 From: Jano Paetzold Date: Wed, 8 Jan 2025 17:59:51 +0100 Subject: [PATCH 15/17] Acknowledge custom command inputs in cleanup.js (#235) Refactored version of https://github.com/webfactory/ssh-agent/pull/183. Fixes: https://github.com/webfactory/ssh-agent/issues/208 --- CHANGELOG.md | 4 +++ cleanup.js | 1 - dist/cleanup.js | 72 +++++++++++++++++++++---------------------- dist/index.js | 81 +++++++++++++++++++++---------------------------- index.js | 10 +----- paths.js | 14 ++++++++- 6 files changed, 87 insertions(+), 95 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 572a902..2c733d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +* Fix path used to execute ssh-agent in cleanup.js to respect custom paths set by input (#235) + ## v0.9.0 [2024-02-06] ### Changed diff --git a/cleanup.js b/cleanup.js index 6b7ab7d..71c657b 100644 --- a/cleanup.js +++ b/cleanup.js @@ -1,4 +1,3 @@ -const core = require('@actions/core'); const { execFileSync } = require('child_process'); const { sshAgentCmd } = require('./paths.js'); diff --git a/dist/cleanup.js b/dist/cleanup.js index 61fc276..7e478b7 100644 --- a/dist/cleanup.js +++ b/dist/cleanup.js @@ -292,14 +292,13 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; +exports.issueCommand = void 0; // We use any as a valid input type /* eslint-disable @typescript-eslint/no-explicit-any */ const fs = __importStar(__webpack_require__(747)); const os = __importStar(__webpack_require__(87)); -const uuid_1 = __webpack_require__(62); const utils_1 = __webpack_require__(82); -function issueFileCommand(command, message) { +function issueCommand(command, message) { const filePath = process.env[`GITHUB_${command}`]; if (!filePath) { throw new Error(`Unable to find environment variable for file command ${command}`); @@ -311,22 +310,7 @@ function issueFileCommand(command, message) { encoding: 'utf8' }); } -exports.issueFileCommand = issueFileCommand; -function prepareKeyValueMessage(key, value) { - const delimiter = `ghadelimiter_${uuid_1.v4()}`; - const convertedValue = utils_1.toCommandValue(value); - // These should realistically never happen, but just in case someone finds a - // way to exploit uuid generation let's not allow keys or values that contain - // the delimiter. - if (key.includes(delimiter)) { - throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); - } - if (convertedValue.includes(delimiter)) { - throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); - } - return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; -} -exports.prepareKeyValueMessage = prepareKeyValueMessage; +exports.issueCommand = issueCommand; //# sourceMappingURL=file-command.js.map /***/ }), @@ -613,7 +597,6 @@ exports.debug = debug; // for test /***/ 175: /***/ (function(__unusedmodule, __unusedexports, __webpack_require__) { -const core = __webpack_require__(470); const { execFileSync } = __webpack_require__(129); const { sshAgentCmd } = __webpack_require__(972); @@ -1684,6 +1667,7 @@ const file_command_1 = __webpack_require__(102); const utils_1 = __webpack_require__(82); const os = __importStar(__webpack_require__(87)); const path = __importStar(__webpack_require__(622)); +const uuid_1 = __webpack_require__(62); const oidc_utils_1 = __webpack_require__(742); /** * The code to exit an action @@ -1713,9 +1697,20 @@ function exportVariable(name, val) { process.env[name] = convertedVal; const filePath = process.env['GITHUB_ENV'] || ''; if (filePath) { - return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val)); + const delimiter = `ghadelimiter_${uuid_1.v4()}`; + // These should realistically never happen, but just in case someone finds a way to exploit uuid generation let's not allow keys or values that contain the delimiter. + if (name.includes(delimiter)) { + throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); + } + if (convertedVal.includes(delimiter)) { + throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); + } + const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`; + file_command_1.issueCommand('ENV', commandValue); + } + else { + command_1.issueCommand('set-env', { name }, convertedVal); } - command_1.issueCommand('set-env', { name }, convertedVal); } exports.exportVariable = exportVariable; /** @@ -1733,7 +1728,7 @@ exports.setSecret = setSecret; function addPath(inputPath) { const filePath = process.env['GITHUB_PATH'] || ''; if (filePath) { - file_command_1.issueFileCommand('PATH', inputPath); + file_command_1.issueCommand('PATH', inputPath); } else { command_1.issueCommand('add-path', {}, inputPath); @@ -1773,10 +1768,7 @@ function getMultilineInput(name, options) { const inputs = getInput(name, options) .split('\n') .filter(x => x !== ''); - if (options && options.trimWhitespace === false) { - return inputs; - } - return inputs.map(input => input.trim()); + return inputs; } exports.getMultilineInput = getMultilineInput; /** @@ -1809,12 +1801,8 @@ exports.getBooleanInput = getBooleanInput; */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function setOutput(name, value) { - const filePath = process.env['GITHUB_OUTPUT'] || ''; - if (filePath) { - return file_command_1.issueFileCommand('OUTPUT', file_command_1.prepareKeyValueMessage(name, value)); - } process.stdout.write(os.EOL); - command_1.issueCommand('set-output', { name }, utils_1.toCommandValue(value)); + command_1.issueCommand('set-output', { name }, value); } exports.setOutput = setOutput; /** @@ -1943,11 +1931,7 @@ exports.group = group; */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function saveState(name, value) { - const filePath = process.env['GITHUB_STATE'] || ''; - if (filePath) { - return file_command_1.issueFileCommand('STATE', file_command_1.prepareKeyValueMessage(name, value)); - } - command_1.issueCommand('save-state', { name }, utils_1.toCommandValue(value)); + command_1.issueCommand('save-state', { name }, value); } exports.saveState = saveState; /** @@ -2837,8 +2821,9 @@ exports.default = _default; /***/ (function(module, __unusedexports, __webpack_require__) { const os = __webpack_require__(87); +const core = __webpack_require__(470); -module.exports = (process.env['OS'] != 'Windows_NT') ? { +const defaults = (process.env['OS'] != 'Windows_NT') ? { // Use getent() system call, since this is what ssh does; makes a difference in Docker-based // Action runs, where $HOME is different from the pwent homePath: os.userInfo().homedir, @@ -2853,6 +2838,17 @@ module.exports = (process.env['OS'] != 'Windows_NT') ? { gitCmdDefault: 'c://progra~1//git//bin//git.exe' }; +const sshAgentCmdInput = core.getInput('ssh-agent-cmd'); +const sshAddCmdInput = core.getInput('ssh-add-cmd'); +const gitCmdInput = core.getInput('git-cmd'); + +module.exports = { + homePath: defaults.homePath, + sshAgentCmd: sshAgentCmdInput !== '' ? sshAgentCmdInput : defaults.sshAgentCmdDefault, + sshAddCmd: sshAddCmdInput !== '' ? sshAddCmdInput : defaults.sshAddCmdDefault, + gitCmd: gitCmdInput !== '' ? gitCmdInput : defaults.gitCmdDefault, +}; + /***/ }) diff --git a/dist/index.js b/dist/index.js index 2c23f23..3f288c7 100644 --- a/dist/index.js +++ b/dist/index.js @@ -292,14 +292,13 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; +exports.issueCommand = void 0; // We use any as a valid input type /* eslint-disable @typescript-eslint/no-explicit-any */ const fs = __importStar(__webpack_require__(747)); const os = __importStar(__webpack_require__(87)); -const uuid_1 = __webpack_require__(62); const utils_1 = __webpack_require__(82); -function issueFileCommand(command, message) { +function issueCommand(command, message) { const filePath = process.env[`GITHUB_${command}`]; if (!filePath) { throw new Error(`Unable to find environment variable for file command ${command}`); @@ -311,22 +310,7 @@ function issueFileCommand(command, message) { encoding: 'utf8' }); } -exports.issueFileCommand = issueFileCommand; -function prepareKeyValueMessage(key, value) { - const delimiter = `ghadelimiter_${uuid_1.v4()}`; - const convertedValue = utils_1.toCommandValue(value); - // These should realistically never happen, but just in case someone finds a - // way to exploit uuid generation let's not allow keys or values that contain - // the delimiter. - if (key.includes(delimiter)) { - throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); - } - if (convertedValue.includes(delimiter)) { - throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); - } - return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; -} -exports.prepareKeyValueMessage = prepareKeyValueMessage; +exports.issueCommand = issueCommand; //# sourceMappingURL=file-command.js.map /***/ }), @@ -338,20 +322,12 @@ const core = __webpack_require__(470); const child_process = __webpack_require__(129); const fs = __webpack_require__(747); const crypto = __webpack_require__(417); -const { homePath, sshAgentCmdDefault, sshAddCmdDefault, gitCmdDefault } = __webpack_require__(972); +const { homePath, sshAgentCmd, sshAddCmd, gitCmd } = __webpack_require__(972); try { const privateKey = core.getInput('ssh-private-key'); const logPublicKey = core.getBooleanInput('log-public-key', {default: true}); - const sshAgentCmdInput = core.getInput('ssh-agent-cmd'); - const sshAddCmdInput = core.getInput('ssh-add-cmd'); - const gitCmdInput = core.getInput('git-cmd'); - - const sshAgentCmd = sshAgentCmdInput ? sshAgentCmdInput : sshAgentCmdDefault; - const sshAddCmd = sshAddCmdInput ? sshAddCmdInput : sshAddCmdDefault; - const gitCmd = gitCmdInput ? gitCmdInput : gitCmdDefault; - if (!privateKey) { core.setFailed("The ssh-private-key argument is empty. Maybe the secret has not been configured, or you are using a wrong secret name in your workflow file."); @@ -1765,6 +1741,7 @@ const file_command_1 = __webpack_require__(102); const utils_1 = __webpack_require__(82); const os = __importStar(__webpack_require__(87)); const path = __importStar(__webpack_require__(622)); +const uuid_1 = __webpack_require__(62); const oidc_utils_1 = __webpack_require__(742); /** * The code to exit an action @@ -1794,9 +1771,20 @@ function exportVariable(name, val) { process.env[name] = convertedVal; const filePath = process.env['GITHUB_ENV'] || ''; if (filePath) { - return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val)); + const delimiter = `ghadelimiter_${uuid_1.v4()}`; + // These should realistically never happen, but just in case someone finds a way to exploit uuid generation let's not allow keys or values that contain the delimiter. + if (name.includes(delimiter)) { + throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); + } + if (convertedVal.includes(delimiter)) { + throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); + } + const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`; + file_command_1.issueCommand('ENV', commandValue); + } + else { + command_1.issueCommand('set-env', { name }, convertedVal); } - command_1.issueCommand('set-env', { name }, convertedVal); } exports.exportVariable = exportVariable; /** @@ -1814,7 +1802,7 @@ exports.setSecret = setSecret; function addPath(inputPath) { const filePath = process.env['GITHUB_PATH'] || ''; if (filePath) { - file_command_1.issueFileCommand('PATH', inputPath); + file_command_1.issueCommand('PATH', inputPath); } else { command_1.issueCommand('add-path', {}, inputPath); @@ -1854,10 +1842,7 @@ function getMultilineInput(name, options) { const inputs = getInput(name, options) .split('\n') .filter(x => x !== ''); - if (options && options.trimWhitespace === false) { - return inputs; - } - return inputs.map(input => input.trim()); + return inputs; } exports.getMultilineInput = getMultilineInput; /** @@ -1890,12 +1875,8 @@ exports.getBooleanInput = getBooleanInput; */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function setOutput(name, value) { - const filePath = process.env['GITHUB_OUTPUT'] || ''; - if (filePath) { - return file_command_1.issueFileCommand('OUTPUT', file_command_1.prepareKeyValueMessage(name, value)); - } process.stdout.write(os.EOL); - command_1.issueCommand('set-output', { name }, utils_1.toCommandValue(value)); + command_1.issueCommand('set-output', { name }, value); } exports.setOutput = setOutput; /** @@ -2024,11 +2005,7 @@ exports.group = group; */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function saveState(name, value) { - const filePath = process.env['GITHUB_STATE'] || ''; - if (filePath) { - return file_command_1.issueFileCommand('STATE', file_command_1.prepareKeyValueMessage(name, value)); - } - command_1.issueCommand('save-state', { name }, utils_1.toCommandValue(value)); + command_1.issueCommand('save-state', { name }, value); } exports.saveState = saveState; /** @@ -2918,8 +2895,9 @@ exports.default = _default; /***/ (function(module, __unusedexports, __webpack_require__) { const os = __webpack_require__(87); +const core = __webpack_require__(470); -module.exports = (process.env['OS'] != 'Windows_NT') ? { +const defaults = (process.env['OS'] != 'Windows_NT') ? { // Use getent() system call, since this is what ssh does; makes a difference in Docker-based // Action runs, where $HOME is different from the pwent homePath: os.userInfo().homedir, @@ -2934,6 +2912,17 @@ module.exports = (process.env['OS'] != 'Windows_NT') ? { gitCmdDefault: 'c://progra~1//git//bin//git.exe' }; +const sshAgentCmdInput = core.getInput('ssh-agent-cmd'); +const sshAddCmdInput = core.getInput('ssh-add-cmd'); +const gitCmdInput = core.getInput('git-cmd'); + +module.exports = { + homePath: defaults.homePath, + sshAgentCmd: sshAgentCmdInput !== '' ? sshAgentCmdInput : defaults.sshAgentCmdDefault, + sshAddCmd: sshAddCmdInput !== '' ? sshAddCmdInput : defaults.sshAddCmdDefault, + gitCmd: gitCmdInput !== '' ? gitCmdInput : defaults.gitCmdDefault, +}; + /***/ }) diff --git a/index.js b/index.js index 0c2e08b..d28a764 100644 --- a/index.js +++ b/index.js @@ -2,20 +2,12 @@ const core = require('@actions/core'); const child_process = require('child_process'); const fs = require('fs'); const crypto = require('crypto'); -const { homePath, sshAgentCmdDefault, sshAddCmdDefault, gitCmdDefault } = require('./paths.js'); +const { homePath, sshAgentCmd, sshAddCmd, gitCmd } = require('./paths.js'); try { const privateKey = core.getInput('ssh-private-key'); const logPublicKey = core.getBooleanInput('log-public-key', {default: true}); - const sshAgentCmdInput = core.getInput('ssh-agent-cmd'); - const sshAddCmdInput = core.getInput('ssh-add-cmd'); - const gitCmdInput = core.getInput('git-cmd'); - - const sshAgentCmd = sshAgentCmdInput ? sshAgentCmdInput : sshAgentCmdDefault; - const sshAddCmd = sshAddCmdInput ? sshAddCmdInput : sshAddCmdDefault; - const gitCmd = gitCmdInput ? gitCmdInput : gitCmdDefault; - if (!privateKey) { core.setFailed("The ssh-private-key argument is empty. Maybe the secret has not been configured, or you are using a wrong secret name in your workflow file."); diff --git a/paths.js b/paths.js index 1c6fbf0..bd4cd30 100644 --- a/paths.js +++ b/paths.js @@ -1,6 +1,7 @@ const os = require('os'); +const core = require('@actions/core'); -module.exports = (process.env['OS'] != 'Windows_NT') ? { +const defaults = (process.env['OS'] != 'Windows_NT') ? { // Use getent() system call, since this is what ssh does; makes a difference in Docker-based // Action runs, where $HOME is different from the pwent homePath: os.userInfo().homedir, @@ -14,3 +15,14 @@ module.exports = (process.env['OS'] != 'Windows_NT') ? { sshAddCmdDefault: 'c://progra~1//git//usr//bin//ssh-add.exe', gitCmdDefault: 'c://progra~1//git//bin//git.exe' }; + +const sshAgentCmdInput = core.getInput('ssh-agent-cmd'); +const sshAddCmdInput = core.getInput('ssh-add-cmd'); +const gitCmdInput = core.getInput('git-cmd'); + +module.exports = { + homePath: defaults.homePath, + sshAgentCmd: sshAgentCmdInput !== '' ? sshAgentCmdInput : defaults.sshAgentCmdDefault, + sshAddCmd: sshAddCmdInput !== '' ? sshAddCmdInput : defaults.sshAddCmdDefault, + gitCmd: gitCmdInput !== '' ? gitCmdInput : defaults.gitCmdDefault, +}; From 72c0bfd31ab22a2e11716951e3f107a9647dc97e Mon Sep 17 00:00:00 2001 From: Jano Paetzold Date: Wed, 8 Jan 2025 18:58:23 +0100 Subject: [PATCH 16/17] Improve documentation on why we use os.userInfo() (use correct syscall name) Co-authored-by: Matthias Pigulla --- paths.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/paths.js b/paths.js index bd4cd30..f440579 100644 --- a/paths.js +++ b/paths.js @@ -2,8 +2,9 @@ const os = require('os'); const core = require('@actions/core'); const defaults = (process.env['OS'] != 'Windows_NT') ? { - // Use getent() system call, since this is what ssh does; makes a difference in Docker-based - // Action runs, where $HOME is different from the pwent + // We use os.userInfo() rather than os.homedir(), since it uses the getpwuid() system call to get the user's home directory (see https://nodejs.org/api/os.html#osuserinfooptions). + // This mimics the way openssh derives the home directory for locating config files (see https://github.com/openssh/openssh-portable/blob/826483d51a9fee60703298bbf839d9ce37943474/ssh.c#L710); + // Makes a difference in Docker-based Action runs, when $HOME is different from what getpwuid() returns (which is based on the entry in /etc/passwd) homePath: os.userInfo().homedir, sshAgentCmdDefault: 'ssh-agent', sshAddCmdDefault: 'ssh-add', From a6f90b1f127823b31d4d4a8d96047790581349bd Mon Sep 17 00:00:00 2001 From: Jano Paetzold Date: Mon, 17 Mar 2025 15:05:58 +0100 Subject: [PATCH 17/17] Release v0.9.1 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c733d3..dc99093 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## v0.9.1 [2024-03-17] + ### Fixed * Fix path used to execute ssh-agent in cleanup.js to respect custom paths set by input (#235)