Skip to content

Commit d0e8f3f

Browse files
fix: add more logging for file checking and manipulation and explicitly check for the existence of files we need
1 parent ab4c551 commit d0e8f3f

File tree

1 file changed

+44
-14
lines changed

1 file changed

+44
-14
lines changed

lib/ssh.ts

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,49 +10,68 @@ import os from 'os';
1010
*/
1111
export async function setupSshCredentials(): Promise<void> {
1212
const homeDir = os.homedir();
13-
const sshDir = `${homeDir}/.ssh/`;
14-
const sshConfigDir = `/opt/atlassian/pipelines/agent/ssh`;
13+
const sshDir = `${homeDir}/.ssh`;
14+
15+
// Bitbucket injects the SSH config into the container at these paths...
16+
const sshConfigDir = '/opt/atlassian/pipelines/agent/ssh';
1517
const identityFile = `${sshConfigDir}/id_rsa_tmp`;
1618
const knownHostsFile = `${sshConfigDir}/known_hosts`;
1719

18-
// Ensure the SSH directory exists, when `stat` throws an error, we know the directory doesn't exist
19-
const sshDirExists = await fs.promises
20-
.stat(sshDir)
21-
.then((stat) => stat.isDirectory())
22-
.catch((err) => false);
23-
if (!sshDirExists) {
20+
// ...and we copy them to the user's .ssh directory
21+
const hostsFile = `${sshDir}/known_hosts`;
22+
const pipelinesIdFile = `${sshDir}/pipelines_id`;
23+
const configFile = `${sshDir}/config`;
24+
25+
// Ensure the SSH directory exists, we're OK to create it if it doesn't exist
26+
if (!(await pathExists(sshDir))) {
2427
await fs.promises.mkdir(sshDir, { recursive: true });
2528
}
2629

27-
// Copy over the SSH identity file that Bitbucket has generated, if this fails then we should fail the whole pipeline
30+
// Ensure all the required directories and files exist
31+
// If these don't exist, we can't continue
32+
const pathsToCheck = [
33+
sshConfigDir,
34+
identityFile,
35+
knownHostsFile,
36+
configFile,
37+
];
38+
for (const path of pathsToCheck) {
39+
if (!(await pathExists(path))) {
40+
console.error(
41+
`${path} not found. Check that the SSH configuration is valid.`
42+
);
43+
return;
44+
}
45+
}
46+
47+
// Copy the Bitbucket injected identity file to the local .ssh directory
2848
try {
2949
console.log('Attempting to copy SSH identity file...');
3050

31-
const pipelinesIdFile = `${sshDir}/pipelines_id`;
3251
await fs.promises.copyFile(identityFile, pipelinesIdFile);
3352

3453
console.log(`Copied to ${pipelinesIdFile}`);
3554
console.log(`Adding identity file config to config file`);
3655

37-
const configFile = `${sshDir}/config`;
3856
await fs.promises.appendFile(
3957
configFile,
4058
`\nIdentityFile ${pipelinesIdFile}\n`
4159
);
4260
} catch (e) {
4361
console.error(
44-
'Failed to update SSH configuration, check that SSH key configuration in Pipelines is valid. \n Check Pipelines -> SSH Keys.'
62+
`Failed to update SSH configuration, check that SSH key configuration in Pipelines is valid. \n Check Pipelines -> SSH Keys.\n\n ${
63+
(e as Error).message
64+
}`
4565
);
4666
return;
4767
}
4868

49-
// Copy over the known_hosts file that Bitbucket generated
69+
// Copy the Bitbucket injected known hosts file to the local .ssh directory
5070
try {
5171
console.log('Piping known hosts into runtime ssh config');
5272
const knownHosts = await fs.promises
5373
.readFile(knownHostsFile)
5474
.then((buf) => `\n${buf.toString()}\n`);
55-
const hostsFile = `${sshDir}/known_hosts`;
5675
await fs.promises.appendFile(hostsFile, knownHosts);
5776
} catch (e) {
5877
console.error(
@@ -89,3 +108,14 @@ async function chmodRecursive(path: fs.PathLike, mode: fs.Mode): Promise<void> {
89108
}
90109
}
91110
}
111+
112+
async function pathExists(path: fs.PathLike): Promise<boolean> {
113+
console.log(`Checking if ${path} exists`);
114+
// An error _typically_ means the object at `path` doesn't exist
115+
// Though we may want to check whether the error is a permission error
116+
// or a file not found error (the latter is OK)
117+
return fs.promises
118+
.stat(path)
119+
.then((_) => true)
120+
.catch((_) => false);
121+
}

0 commit comments

Comments
 (0)