2019-09-14 22:28:16 +00:00
const core = require ( '@actions/core' ) ;
const child _process = require ( 'child_process' ) ;
const fs = require ( 'fs' ) ;
2020-08-17 16:30:59 -07:00
const os = require ( 'os' ) ;
// Param names
const privateKeyName = 'ssh-private-key' ;
const repoMappingsName = 'repo-mappings' ;
const authSockName = 'ssh-auth-sock' ;
const dropExtraHeaderName = 'drop-extra-header' ;
2019-09-14 22:28:16 +00:00
try {
2020-01-14 09:29:16 +00:00
2020-08-17 16:30:59 -07:00
const home = os . homedir ( ) ;
2019-09-15 09:32:43 +02:00
const homeSsh = home + '/.ssh' ;
2020-08-17 16:30:59 -07:00
const sshConfig = homeSsh + '/config' ;
const sshKnownHosts = homeSsh + '/known_hosts' ;
2019-09-15 09:32:43 +02:00
2020-08-17 16:30:59 -07:00
const privateKey = core . getInput ( privateKeyName ) ;
2020-01-14 09:29:16 +00:00
if ( ! privateKey ) {
2020-08-17 16:30:59 -07:00
core . setFailed ( ` The ${ privateKeyName } argument is empty. Maybe the secret has not been configured, or you are using a wrong secret name in your workflow file. ` ) ;
2020-01-14 09:29:16 +00:00
return ;
}
2020-08-17 16:30:59 -07:00
console . log ( ` Adding GitHub.com keys to ${ sshKnownHosts } ` ) ;
2020-03-02 16:41:12 -08:00
fs . mkdirSync ( homeSsh , { recursive : true } ) ;
2020-08-17 16:30:59 -07:00
fs . appendFileSync ( sshKnownHosts , '\ngithub.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==\n' ) ;
fs . appendFileSync ( sshKnownHosts , '\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' ) ;
2019-09-14 22:28:16 +00:00
console . log ( "Starting ssh-agent" ) ;
2020-08-17 16:30:59 -07:00
const authSock = core . getInput ( authSockName ) ;
2020-05-18 09:08:29 +02:00
let sshAgentOutput = ''
if ( authSock && authSock . length > 0 ) {
sshAgentOutput = child _process . execFileSync ( 'ssh-agent' , [ '-a' , authSock ] ) ;
} else {
sshAgentOutput = child _process . execFileSync ( 'ssh-agent' )
}
// Extract auth socket path and agent pid and set them as job variables
const lines = sshAgentOutput . toString ( ) . split ( "\n" )
for ( const lineNumber in lines ) {
const matches = /^(SSH_AUTH_SOCK|SSH_AGENT_PID)=(.*); export \1/ . exec ( lines [ lineNumber ] )
if ( matches && matches . length > 0 ) {
core . exportVariable ( matches [ 1 ] , matches [ 2 ] )
}
}
2019-09-14 22:28:16 +00:00
2020-08-17 16:30:59 -07:00
// Do we need to drop the http.extraheader added by actions/checkout@v2?
const dropExtraHeader = ( core . getInput ( dropExtraHeaderName ) . toLowerCase ( ) === 'true' ) ;
if ( dropExtraHeader ) {
console . log ( "Dropping any existing http.extraheader git config" ) ;
child _process . execSync ( ` git config --global http.https://github.com/.extraheader '' ` ) ;
}
// Grab the repo mappings
console . log ( "Parsing repo mappings" ) ;
const repoMappingsInput = core . getInput ( repoMappingsName ) ;
let repoMappings = null ;
if ( repoMappingsInput ) {
repoMappings = new Array ( ) ;
repoMappingsInput . split ( /\r?\n/ ) . forEach ( function ( key ) {
// Get the hostname, org name, and repo name
// format expected: sub.host.com/OWNER/REPO
let parts = key . trim ( ) . match ( /(.*)\/(.*)\/(.*)/ ) ;
if ( parts . length != 4 ) {
throw ` Invalid ${ repoMappingsName } format at: ${ key } ` ;
}
// Add this to the array of mappings
let mapping = {
host : parts [ 1 ] ,
owner : parts [ 2 ] ,
repo : parts [ 3 ] ,
pseudoHost : ` ${ parts [ 3 ] } . ${ parts [ 1 ] } `
} ;
repoMappings . push ( mapping ) ;
// Create rewrites
console . log ( ` Adding insteadOf entries in git config for ${ key } ` ) ;
child _process . execSync ( ` git config --global url."git@http. ${ mapping . pseudoHost } : ${ mapping . owner } / ${ mapping . repo } ".insteadOf "https:// ${ mapping . host } / ${ mapping . owner } / ${ mapping . repo } " ` ) ;
child _process . execSync ( ` git config --global url."git@ssh. ${ mapping . pseudoHost } : ${ mapping . owner } / ${ mapping . repo } ".insteadOf "git@ ${ mapping . host } : ${ mapping . owner } / ${ mapping . repo } " ` ) ;
} ) ;
}
// Add private keys to ssh-agent
2019-09-14 22:28:16 +00:00
console . log ( "Adding private key to agent" ) ;
2020-08-17 16:30:59 -07:00
const privateKeys = privateKey . split ( /(?=-----BEGIN)/ ) ;
if ( repoMappings && privateKeys . length != repoMappings . length ) {
core . setFailed ( ` The number of ${ privateKeyName } arguments and ${ repoMappingsName } must match. ` ) ;
return ;
}
privateKeys . forEach ( function ( key , i ) {
if ( repoMappings ) {
let mapping = repoMappings [ i ] ;
let keyFile = ` ${ mapping . pseudoHost } .key ` ;
// Since we can't specify hostname/user/host options in a ssh-add call...
// Write the key to a file
fs . writeFileSync ( ` ${ homeSsh } / ${ keyFile } ` , key . replace ( "\r\n" , "\n" ) . trim ( ) + "\n" , { mode : '600' } ) ;
// Update ssh config
let hostEntry = ` \n Host http. ${ mapping . pseudoHost } \n `
+ ` HostName ${ mapping . host } \n `
+ ` User git \n `
+ ` IdentityFile ~/.ssh/ ${ keyFile } \n `
+ ` IdentitiesOnly yes \n `
+ ` \n Host ssh. ${ mapping . pseudoHost } \n `
+ ` HostName ${ mapping . host } \n `
+ ` User git \n `
+ ` IdentityFile ~/.ssh/ ${ keyFile } \n `
+ ` IdentitiesOnly yes \n ` ;
fs . appendFileSync ( sshConfig , hostEntry ) ;
} else {
// No mappings, just use ssh-add
child _process . execSync ( 'ssh-add -' , { input : key . trim ( ) + "\n" } ) ;
}
2020-01-14 10:21:11 +01:00
} ) ;
2020-01-14 09:29:16 +00:00
2020-01-14 10:21:11 +01:00
console . log ( "Keys added:" ) ;
2020-08-17 16:30:59 -07:00
if ( repoMappings ) {
repoMappings . forEach ( function ( key ) {
console . log ( ` ~/.ssh/ ${ key . pseudoHost } .key ` ) ;
} ) ;
} else {
child _process . execSync ( 'ssh-add -l' , { stdio : 'inherit' } ) ;
}
2020-01-14 09:29:16 +00:00
2019-09-14 22:28:16 +00:00
} catch ( error ) {
core . setFailed ( error . message ) ;
}