2019-09-14 22:28:16 +00:00
const core = require ( '@actions/core' ) ;
const child _process = require ( 'child_process' ) ;
const fs = require ( 'fs' ) ;
2021-02-19 13:37:34 +00:00
const crypto = require ( 'crypto' ) ;
2023-01-27 17:09:18 +00:00
const { homePath , sshAgentCmdDefault , sshAddCmdDefault , gitCmdDefault } = require ( './paths.js' ) ;
2019-09-14 22:28:16 +00:00
try {
2024-09-30 15:14:06 +00:00
const instanceURL = core . getInput ( 'instance-url' ) || process . env . GITHUB _SERVER _URL || 'https://github.com' ;
const instanceDomain = instanceURL . replace ( /^https?:\/\// , '' ) ;
2024-09-30 14:38:04 +00:00
const escapedDomain = instanceDomain . replace ( /[-.]/g , '\\$&' ) ;
const regexDomain = new RegExp ( ` \\ b ${ escapedDomain } [:/]([_.a-z0-9-]+ \/ [_.a-z0-9-]+) ` , 'i' ) ;
2020-02-06 18:09:44 +00:00
const privateKey = core . getInput ( 'ssh-private-key' ) ;
2022-10-19 10:41:11 +00:00
const logPublicKey = core . getBooleanInput ( 'log-public-key' , { default : true } ) ;
2020-01-14 09:29:16 +00:00
2023-01-27 17:09:18 +00:00
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 ;
2020-01-14 09:29:16 +00:00
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." ) ;
return ;
}
2022-10-19 11:27:50 +00:00
const homeSsh = homePath + '/.ssh' ;
2020-03-03 00:41:12 +00:00
fs . mkdirSync ( homeSsh , { recursive : true } ) ;
2019-09-14 22:28:16 +00:00
console . log ( "Starting ssh-agent" ) ;
2021-03-10 07:19:17 +00:00
2019-09-14 22:28:16 +00:00
const authSock = core . getInput ( 'ssh-auth-sock' ) ;
2021-03-10 07:19:17 +00:00
const sshAgentArgs = ( authSock && authSock . length > 0 ) ? [ '-a' , authSock ] : [ ] ;
2020-05-18 07:08:29 +00:00
// Extract auth socket path and agent pid and set them as job variables
2022-10-19 11:27:50 +00:00
child _process . execFileSync ( sshAgentCmd , sshAgentArgs ) . toString ( ) . split ( "\n" ) . forEach ( function ( line ) {
2021-03-10 07:19:17 +00:00
const matches = /^(SSH_AUTH_SOCK|SSH_AGENT_PID)=(.*); export \1/ . exec ( line ) ;
2020-05-18 07:08:29 +00:00
if ( matches && matches . length > 0 ) {
2021-03-10 07:19:17 +00:00
// This will also set process.env accordingly, so changes take effect for this script
2020-05-18 07:08:29 +00:00
core . exportVariable ( matches [ 1 ] , matches [ 2 ] )
2021-03-10 07:19:17 +00:00
console . log ( ` ${ matches [ 1 ] } = ${ matches [ 2 ] } ` ) ;
2020-05-18 07:08:29 +00:00
}
2021-03-10 07:19:17 +00:00
} ) ;
console . log ( "Adding private key(s) to agent" ) ;
2019-09-14 22:28:16 +00:00
2020-01-14 09:29:16 +00:00
privateKey . split ( /(?=-----BEGIN)/ ) . forEach ( function ( key ) {
2022-10-19 11:27:50 +00:00
child _process . execFileSync ( sshAddCmd , [ '-' ] , { input : key . trim ( ) + "\n" } ) ;
2020-01-14 09:21:11 +00:00
} ) ;
2020-01-14 09:29:16 +00:00
2021-03-10 07:19:17 +00:00
console . log ( "Key(s) added:" ) ;
2022-10-19 11:27:50 +00:00
child _process . execFileSync ( sshAddCmd , [ '-l' ] , { stdio : 'inherit' } ) ;
2021-03-10 07:19:17 +00:00
console . log ( 'Configuring deployment key(s)' ) ;
2020-01-14 09:29:16 +00:00
2022-10-19 12:54:52 +00:00
child _process . execFileSync ( sshAddCmd , [ '-L' ] ) . toString ( ) . trim ( ) . split ( /\r?\n/ ) . forEach ( function ( key ) {
2024-09-30 15:14:06 +00:00
console . log ( 'Instance domain is:' , instanceDomain ) ;
2024-09-30 14:38:04 +00:00
const parts = key . match ( regexDomain ) ;
2021-02-19 13:37:34 +00:00
2021-03-10 07:19:17 +00:00
if ( ! parts ) {
2022-10-19 10:41:11 +00:00
if ( logPublicKey ) {
console . log ( ` Comment for (public) key ' ${ key } ' does not match GitHub URL pattern. Not treating it as a GitHub deploy key. ` ) ;
}
2021-02-19 13:37:34 +00:00
return ;
}
2021-03-10 07:19:17 +00:00
const sha256 = crypto . createHash ( 'sha256' ) . update ( key ) . digest ( 'hex' ) ;
const ownerAndRepo = parts [ 1 ] . replace ( /\.git$/ , '' ) ;
2021-02-19 13:37:34 +00:00
2021-03-10 07:19:17 +00:00
fs . writeFileSync ( ` ${ homeSsh } /key- ${ sha256 } ` , key + "\n" , { mode : '600' } ) ;
2021-02-19 13:37:34 +00:00
2024-09-30 14:38:04 +00:00
child _process . execSync ( ` ${ gitCmd } config --global --replace-all url."git@key- ${ sha256 } . ${ instanceDomain } : ${ ownerAndRepo } ".insteadOf "https:// ${ instanceDomain } / ${ ownerAndRepo } " ` ) ;
child _process . execSync ( ` ${ gitCmd } config --global --add url."git@key- ${ sha256 } . ${ instanceDomain } : ${ ownerAndRepo } ".insteadOf "git@ ${ instanceDomain } : ${ ownerAndRepo } " ` ) ;
child _process . execSync ( ` ${ gitCmd } config --global --add url."git@key- ${ sha256 } . ${ instanceDomain } : ${ ownerAndRepo } ".insteadOf "ssh://git@ ${ instanceDomain } / ${ ownerAndRepo } " ` ) ;
2021-02-19 13:37:34 +00:00
2024-09-30 14:38:04 +00:00
const sshConfig = ` \n Host key- ${ sha256 } . ${ instanceDomain } \n `
+ ` HostName ${ instanceDomain } \n `
2021-03-10 07:19:17 +00:00
+ ` IdentityFile ${ homeSsh } /key- ${ sha256 } \n `
2021-02-19 13:37:34 +00:00
+ ` IdentitiesOnly yes \n ` ;
fs . appendFileSync ( ` ${ homeSsh } /config ` , sshConfig ) ;
2021-03-10 07:19:17 +00:00
console . log ( ` Added deploy-key mapping: Use identity ' ${ homeSsh } /key- ${ sha256 } ' for GitHub repository ${ ownerAndRepo } ` ) ;
2021-02-19 13:37:34 +00:00
} ) ;
2019-09-14 22:28:16 +00:00
} catch ( error ) {
2021-03-05 20:17:14 +00:00
if ( error . code == 'ENOENT' ) {
console . log ( ` The ' ${ error . path } ' executable could not be found. Please make sure it is on your PATH and/or the necessary packages are installed. ` ) ;
console . log ( ` PATH is set to: ${ process . env . PATH } ` ) ;
}
2019-09-14 22:28:16 +00:00
core . setFailed ( error . message ) ;
}