Skip to content

Commit 4b6f4eb

Browse files
authored
Windows virtual environment: Use SSH binaries from the Git suite (#63)
* Use SSH binaries from the Git suite * Try to kill the ssh-agent upon action termination on Windows as well
1 parent 7954857 commit 4b6f4eb

File tree

6 files changed

+174
-138
lines changed

6 files changed

+174
-138
lines changed

.github/workflows/demo.yml

+34-48
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,46 @@
1-
on: [push, pull_request]
1+
on: [ push, pull_request ]
22

33
jobs:
4-
single_key_demo:
5-
strategy:
6-
matrix:
7-
os: [ubuntu-latest, macOS-latest, windows-latest]
8-
runs-on: ${{ matrix.os }}
9-
steps:
10-
- uses: actions/checkout@v2
11-
- name: Setup key
12-
uses: ./
13-
with:
14-
ssh-private-key: |
15-
${{ secrets.DEMO_KEY }}
16-
${{ secrets.DEMO_KEY_2 }}
17-
18-
multiple_keys_demo:
4+
deployment_keys_demo:
195
strategy:
6+
fail-fast: false
207
matrix:
21-
os: [ubuntu-latest, macOS-latest]
8+
os: [ ubuntu-latest, macOS-latest, windows-latest ]
229
runs-on: ${{ matrix.os }}
2310
steps:
24-
- uses: actions/checkout@v2
25-
- name: Setup key
26-
uses: ./
27-
with:
28-
ssh-private-key: ${{ secrets.DEMO_KEY }}
11+
- uses: actions/checkout@v2
12+
- name: Setup key
13+
uses: ./
14+
with:
15+
ssh-private-key: |
16+
${{ secrets.MPDUDE_TEST_1_DEPLOY_KEY }}
17+
${{ secrets.MPDUDE_TEST_2_DEPLOY_KEY }}
18+
- run: |
19+
git clone https://github.com/mpdude/test-1.git test-1-http
20+
git clone [email protected]:mpdude/test-1.git test-1-git
21+
git clone ssh://[email protected]/mpdude/test-1.git test-1-git-ssh
22+
git clone https://github.com/mpdude/test-2.git test-2-http
23+
git clone [email protected]:mpdude/test-2.git test-2-git
24+
git clone ssh://[email protected]/mpdude/test-2.git test-2-git-ssh
2925
3026
docker_demo:
31-
runs-on: ubuntu-latest
27+
runs-on: ubuntu-latest
3228
container:
3329
image: ubuntu:latest
3430
steps:
35-
- uses: actions/checkout@v2
36-
- run: apt update && apt install -y openssh-client
37-
- name: Setup key
38-
uses: ./
39-
with:
40-
ssh-private-key: |
41-
${{ secrets.DEMO_KEY }}
42-
${{ secrets.DEMO_KEY_2 }}
31+
- uses: actions/checkout@v2
32+
- run: apt update && apt install -y openssh-client git
33+
- name: Setup key
34+
uses: ./
35+
with:
36+
ssh-private-key: |
37+
${{ secrets.MPDUDE_TEST_1_DEPLOY_KEY }}
38+
${{ secrets.MPDUDE_TEST_2_DEPLOY_KEY }}
39+
- run: |
40+
git clone https://github.com/mpdude/test-1.git test-1-http
41+
git clone [email protected]:mpdude/test-1.git test-1-git
42+
git clone ssh://[email protected]/mpdude/test-1.git test-1-git-ssh
43+
git clone https://github.com/mpdude/test-2.git test-2-http
44+
git clone [email protected]:mpdude/test-2.git test-2-git
45+
git clone ssh://[email protected]/mpdude/test-2.git test-2-git-ssh
4346
44-
deployment_keys_demo:
45-
runs-on: ubuntu-latest
46-
steps:
47-
- uses: actions/checkout@v2
48-
- name: Setup key
49-
uses: ./
50-
with:
51-
ssh-private-key: |
52-
${{ secrets.MPDUDE_TEST_1_DEPLOY_KEY }}
53-
${{ secrets.MPDUDE_TEST_2_DEPLOY_KEY }}
54-
- run: |
55-
git clone https://github.com/mpdude/test-1.git test-1-http
56-
git clone [email protected]:mpdude/test-1.git test-1-git
57-
git clone ssh://[email protected]/mpdude/test-1.git test-1-git-ssh
58-
git clone https://github.com/mpdude/test-2.git test-2-http
59-
git clone [email protected]:mpdude/test-2.git test-2-git
60-
git clone ssh://[email protected]/mpdude/test-2.git test-2-git-ssh

cleanup.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
const core = require('@actions/core')
2-
const { execSync } = require('child_process')
1+
const core = require('@actions/core');
2+
const { execSync } = require('child_process');
3+
const { sshAgent } = require('./paths.js');
34

45
try {
56
// Kill the started SSH agent
6-
console.log('Stopping SSH agent')
7-
execSync('kill ${SSH_AGENT_PID}', { stdio: 'inherit' })
7+
console.log('Stopping SSH agent');
8+
execSync(sshAgent, ['-k'], { stdio: 'inherit' });
9+
810
} catch (error) {
911
console.log(error.message);
1012
console.log('Error stopping the SSH agent, proceeding anyway');

dist/cleanup.js

+31-4
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,15 @@ module.exports = require("child_process");
122122
/***/ 175:
123123
/***/ (function(__unusedmodule, __unusedexports, __webpack_require__) {
124124

125-
const core = __webpack_require__(470)
126-
const { execSync } = __webpack_require__(129)
125+
const core = __webpack_require__(470);
126+
const { execSync } = __webpack_require__(129);
127+
const { sshAgent } = __webpack_require__(972);
127128

128129
try {
129130
// Kill the started SSH agent
130-
console.log('Stopping SSH agent')
131-
execSync('kill ${SSH_AGENT_PID}', { stdio: 'inherit' })
131+
console.log('Stopping SSH agent');
132+
execSync(sshAgent, ['-k'], { stdio: 'inherit' });
133+
132134
} catch (error) {
133135
console.log(error.message);
134136
console.log('Error stopping the SSH agent, proceeding anyway');
@@ -480,6 +482,31 @@ module.exports = require("path");
480482

481483
module.exports = require("fs");
482484

485+
/***/ }),
486+
487+
/***/ 972:
488+
/***/ (function(module, __unusedexports, __webpack_require__) {
489+
490+
const os = __webpack_require__(87);
491+
492+
module.exports = (process.env['OS'] != 'Windows_NT') ? {
493+
494+
// Use getent() system call, since this is what ssh does; makes a difference in Docker-based
495+
// Action runs, where $HOME is different from the pwent
496+
home: os.userInfo().homedir,
497+
sshAgent: 'ssh-agent',
498+
sshAdd: 'ssh-add'
499+
500+
} : {
501+
502+
home: os.homedir(),
503+
sshAgent: 'c://progra~1//git//usr//bin//ssh-agent.exe',
504+
sshAdd: 'c://progra~1//git//usr//bin//ssh-add.exe'
505+
506+
};
507+
508+
509+
483510
/***/ })
484511

485512
/******/ });

dist/index.js

+55-41
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,8 @@ exports.issueCommand = issueCommand;
118118
const core = __webpack_require__(470);
119119
const child_process = __webpack_require__(129);
120120
const fs = __webpack_require__(747);
121-
const os = __webpack_require__(87);
122121
const crypto = __webpack_require__(417);
122+
const { home, sshAgent, sshAdd } = __webpack_require__(972);
123123

124124
try {
125125
const privateKey = core.getInput('ssh-private-key');
@@ -130,77 +130,66 @@ try {
130130
return;
131131
}
132132

133-
var home;
134-
135-
if (process.env['OS'] == 'Windows_NT') {
136-
console.log('Preparing ssh-agent service on Windows');
137-
child_process.execSync('sc config ssh-agent start=demand', { stdio: 'inherit' });
138-
139-
home = os.homedir();
140-
} else {
141-
// Use getent() system call, since this is what ssh does; makes a difference in Docker-based
142-
// Action runs, where $HOME is different from the pwent
143-
var { homedir: home } = os.userInfo();
144-
}
145-
146133
const homeSsh = home + '/.ssh';
147134

148135
console.log(`Adding GitHub.com keys to ${homeSsh}/known_hosts`);
136+
149137
fs.mkdirSync(homeSsh, { recursive: true });
150138
fs.appendFileSync(`${homeSsh}/known_hosts`, '\ngithub.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==\n');
151139
fs.appendFileSync(`${homeSsh}/known_hosts`, '\ngithub.com ssh-dss AAAAB3NzaC1kc3MAAACBANGFW2P9xlGU3zWrymJgI/lKo//ZW2WfVtmbsUZJ5uyKArtlQOT2+WRhcg4979aFxgKdcsqAYW3/LS1T2km3jYW/vr4Uzn+dXWODVk5VlUiZ1HFOHf6s6ITcZvjvdbp6ZbpM+DuJT7Bw+h5Fx8Qt8I16oCZYmAPJRtu46o9C2zk1AAAAFQC4gdFGcSbp5Gr0Wd5Ay/jtcldMewAAAIATTgn4sY4Nem/FQE+XJlyUQptPWMem5fwOcWtSXiTKaaN0lkk2p2snz+EJvAGXGq9dTSWHyLJSM2W6ZdQDqWJ1k+cL8CARAqL+UMwF84CR0m3hj+wtVGD/J4G5kW2DBAf4/bqzP4469lT+dF2FRQ2L9JKXrCWcnhMtJUvua8dvnwAAAIB6C4nQfAA7x8oLta6tT+oCk2WQcydNsyugE8vLrHlogoWEicla6cWPk7oXSspbzUcfkjN3Qa6e74PhRkc7JdSdAlFzU3m7LMkXo1MHgkqNX8glxWNVqBSc0YRdbFdTkL0C6gtpklilhvuHQCdbgB3LBAikcRkDp+FCVkUgPC/7Rw==\n');
152140

153141
console.log("Starting ssh-agent");
142+
154143
const authSock = core.getInput('ssh-auth-sock');
155-
let sshAgentOutput = ''
156-
if (authSock && authSock.length > 0) {
157-
sshAgentOutput = child_process.execFileSync('ssh-agent', ['-a', authSock]);
158-
} else {
159-
sshAgentOutput = child_process.execFileSync('ssh-agent')
160-
}
144+
const sshAgentArgs = (authSock && authSock.length > 0) ? ['-a', authSock] : [];
161145

162146
// Extract auth socket path and agent pid and set them as job variables
163-
const lines = sshAgentOutput.toString().split("\n")
164-
for (const lineNumber in lines) {
165-
const matches = /^(SSH_AUTH_SOCK|SSH_AGENT_PID)=(.*); export \1/.exec(lines[lineNumber])
147+
child_process.execFileSync(sshAgent, sshAgentArgs).toString().split("\n").forEach(function(line) {
148+
const matches = /^(SSH_AUTH_SOCK|SSH_AGENT_PID)=(.*); export \1/.exec(line);
149+
166150
if (matches && matches.length > 0) {
151+
// This will also set process.env accordingly, so changes take effect for this script
167152
core.exportVariable(matches[1], matches[2])
153+
console.log(`${matches[1]}=${matches[2]}`);
168154
}
169-
}
155+
});
156+
157+
console.log("Adding private key(s) to agent");
170158

171-
console.log("Adding private key to agent");
172159
privateKey.split(/(?=-----BEGIN)/).forEach(function(key) {
173-
child_process.execSync('ssh-add -', { input: key.trim() + "\n" });
160+
child_process.execFileSync(sshAdd, ['-'], { input: key.trim() + "\n" });
174161
});
175162

176-
console.log("Keys added:");
177-
child_process.execSync('ssh-add -l', { stdio: 'inherit' });
163+
console.log("Key(s) added:");
164+
165+
child_process.execFileSync(sshAdd, ['-l'], { stdio: 'inherit' });
166+
167+
console.log('Configuring deployment key(s)');
178168

179-
child_process.execFileSync('ssh-add', ['-L']).toString().split(/\r?\n/).forEach(function(key) {
180-
let parts = key.match(/\bgithub.com[:/](.*)(?:\.git)?\b/);
169+
child_process.execFileSync(sshAdd, ['-L']).toString().split(/\r?\n/).forEach(function(key) {
170+
const parts = key.match(/\bgithub\.com[:/]([_.a-z0-9-]+\/[_.a-z0-9-]+)/);
181171

182-
if (parts == null) {
172+
if (!parts) {
183173
return;
184174
}
185175

186-
let ownerAndRepo = parts[1];
187-
let sha256 = crypto.createHash('sha256').update(key).digest('hex');
176+
const sha256 = crypto.createHash('sha256').update(key).digest('hex');
177+
const ownerAndRepo = parts[1].replace(/\.git$/, '');
188178

189-
fs.writeFileSync(`${homeSsh}/${sha256}`, key + "\n", { mode: '600' });
179+
fs.writeFileSync(`${homeSsh}/key-${sha256}`, key + "\n", { mode: '600' });
190180

191-
child_process.execSync(`git config --global --replace-all url."git@${sha256}:${ownerAndRepo}".insteadOf "https://github.com/${ownerAndRepo}"`);
192-
child_process.execSync(`git config --global --add url."git@${sha256}:${ownerAndRepo}".insteadOf "[email protected]:${ownerAndRepo}"`);
193-
child_process.execSync(`git config --global --add url."git@${sha256}:${ownerAndRepo}".insteadOf "ssh://[email protected]/${ownerAndRepo}"`);
181+
child_process.execSync(`git config --global --replace-all url."git@key-${sha256}.github.com:${ownerAndRepo}".insteadOf "https://github.com/${ownerAndRepo}"`);
182+
child_process.execSync(`git config --global --add url."git@key-${sha256}.github.com:${ownerAndRepo}".insteadOf "[email protected]:${ownerAndRepo}"`);
183+
child_process.execSync(`git config --global --add url."git@key-${sha256}.github.com:${ownerAndRepo}".insteadOf "ssh://[email protected]/${ownerAndRepo}"`);
194184

195-
let sshConfig = `\nHost ${sha256}\n`
185+
const sshConfig = `\nHost key-${sha256}.github.com\n`
196186
+ ` HostName github.com\n`
197-
+ ` User git\n`
198-
+ ` IdentityFile ${homeSsh}/${sha256}\n`
187+
+ ` IdentityFile ${homeSsh}/key-${sha256}\n`
199188
+ ` IdentitiesOnly yes\n`;
200189

201190
fs.appendFileSync(`${homeSsh}/config`, sshConfig);
202191

203-
console.log(`Added deploy-key mapping: Use key "${key}" for GitHub repository ${ownerAndRepo}`);
192+
console.log(`Added deploy-key mapping: Use identity '${homeSsh}/key-${sha256}' for GitHub repository ${ownerAndRepo}`);
204193
});
205194

206195
} catch (error) {
@@ -573,6 +562,31 @@ module.exports = require("path");
573562

574563
module.exports = require("fs");
575564

565+
/***/ }),
566+
567+
/***/ 972:
568+
/***/ (function(module, __unusedexports, __webpack_require__) {
569+
570+
const os = __webpack_require__(87);
571+
572+
module.exports = (process.env['OS'] != 'Windows_NT') ? {
573+
574+
// Use getent() system call, since this is what ssh does; makes a difference in Docker-based
575+
// Action runs, where $HOME is different from the pwent
576+
home: os.userInfo().homedir,
577+
sshAgent: 'ssh-agent',
578+
sshAdd: 'ssh-add'
579+
580+
} : {
581+
582+
home: os.homedir(),
583+
sshAgent: 'c://progra~1//git//usr//bin//ssh-agent.exe',
584+
sshAdd: 'c://progra~1//git//usr//bin//ssh-add.exe'
585+
586+
};
587+
588+
589+
576590
/***/ })
577591

578592
/******/ });

0 commit comments

Comments
 (0)