2019-09-10 00:27:23 +07:00
import * as fs from 'fs' ;
import * as path from 'path' ;
import * as core from '@actions/core' ;
import * as github from '@actions/github' ;
import * as xmlbuilder from 'xmlbuilder' ;
import * as xmlParser from 'fast-xml-parser' ;
2020-09-03 01:11:56 +07:00
import { ProcessEnvOptions } from 'child_process' ;
2019-09-10 00:27:23 +07:00
export function configAuthentication (
feedUrl : string ,
2020-09-03 01:11:56 +07:00
existingFileLocation : string = '' ,
processRoot : string = process . cwd ( )
2019-09-10 00:27:23 +07:00
) {
const existingNuGetConfig : string = path . resolve (
2020-09-03 01:11:56 +07:00
processRoot ,
2021-04-19 20:11:14 +07:00
existingFileLocation === ''
2021-04-19 18:26:05 +07:00
? getExistingNugetConfig ( processRoot )
: existingFileLocation
2019-09-10 00:27:23 +07:00
) ;
const tempNuGetConfig : string = path . resolve (
2020-09-03 01:11:56 +07:00
processRoot ,
2019-09-10 00:27:23 +07:00
'../' ,
'nuget.config'
) ;
writeFeedToFile ( feedUrl , existingNuGetConfig , tempNuGetConfig ) ;
}
2021-04-15 17:30:04 +07:00
function isValidKey ( key : string ) : boolean {
2021-04-15 17:44:48 +07:00
return /^[\w\-\.]+$/i . test ( key ) ;
2021-04-15 17:28:24 +07:00
}
2021-04-19 18:25:42 +07:00
function getExistingNugetConfig ( processRoot : string ) {
2021-04-19 20:16:44 +07:00
const defaultConfigName = 'nuget.config' ;
2021-04-19 18:26:05 +07:00
const configFileNames = fs
. readdirSync ( processRoot )
2021-04-19 20:16:44 +07:00
. filter ( filename = > filename . toLowerCase ( ) === defaultConfigName ) ;
2021-04-19 18:25:42 +07:00
if ( configFileNames . length ) {
return configFileNames [ 0 ] ;
}
2021-04-19 20:16:44 +07:00
return defaultConfigName ;
2021-04-19 18:25:42 +07:00
}
2019-09-10 00:27:23 +07:00
function writeFeedToFile (
feedUrl : string ,
existingFileLocation : string ,
tempFileLocation : string
) {
console . log (
` dotnet-auth: Finding any source references in ${ existingFileLocation } , writing a new temporary configuration file with credentials to ${ tempFileLocation } `
) ;
let xml : xmlbuilder.XMLElement ;
2019-10-04 07:29:20 +07:00
let sourceKeys : string [ ] = [ ] ;
2019-09-10 00:27:23 +07:00
let owner : string = core . getInput ( 'owner' ) ;
2019-10-04 07:29:20 +07:00
let sourceUrl : string = feedUrl ;
if ( ! owner ) {
2019-09-10 00:27:23 +07:00
owner = github . context . repo . owner ;
}
if ( ! process . env . NUGET_AUTH_TOKEN || process . env . NUGET_AUTH_TOKEN == '' ) {
throw new Error (
'The NUGET_AUTH_TOKEN environment variable was not provided. In this step, add the following: \r\nenv:\r\n NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}'
) ;
}
if ( fs . existsSync ( existingFileLocation ) ) {
// get key from existing NuGet.config so NuGet/dotnet can match credentials
const curContents : string = fs . readFileSync ( existingFileLocation , 'utf8' ) ;
var json = xmlParser . parse ( curContents , { ignoreAttributes : false } ) ;
if ( typeof json . configuration == 'undefined' ) {
throw new Error ( ` The provided NuGet.config seems invalid. ` ) ;
}
if ( typeof json . configuration . packageSources != 'undefined' ) {
if ( typeof json . configuration . packageSources . add != 'undefined' ) {
// file has at least one <add>
if ( typeof json . configuration . packageSources . add [ 0 ] == 'undefined' ) {
// file has only one <add>
if (
json . configuration . packageSources . add [ '@_value' ]
. toLowerCase ( )
2019-10-04 07:29:20 +07:00
. includes ( feedUrl . toLowerCase ( ) )
2019-09-10 00:27:23 +07:00
) {
let key = json . configuration . packageSources . add [ '@_key' ] ;
2019-10-04 07:29:20 +07:00
sourceKeys . push ( key ) ;
core . debug ( ` Found a URL with key ${ key } ` ) ;
2019-09-10 00:27:23 +07:00
}
} else {
// file has 2+ <add>
for (
let i = 0 ;
i < json . configuration . packageSources . add . length ;
i ++
) {
2020-01-26 13:37:54 +07:00
const source = json . configuration . packageSources . add [ i ] ;
const value = source [ '@_value' ] ;
core . debug ( ` source ' ${ value } ' ` ) ;
if ( value . toLowerCase ( ) . includes ( feedUrl . toLowerCase ( ) ) ) {
let key = source [ '@_key' ] ;
2019-10-04 07:29:20 +07:00
sourceKeys . push ( key ) ;
core . debug ( ` Found a URL with key ${ key } ` ) ;
2019-09-10 00:27:23 +07:00
}
}
}
}
}
}
xml = xmlbuilder
. create ( 'configuration' )
. ele ( 'config' )
. ele ( 'add' , { key : 'defaultPushSource' , value : sourceUrl } )
. up ( )
. up ( ) ;
2019-10-04 07:29:20 +07:00
if ( sourceKeys . length == 0 ) {
let keystring = 'Source' ;
2019-09-10 00:27:23 +07:00
xml = xml
. ele ( 'packageSources' )
. ele ( 'add' , { key : keystring , value : sourceUrl } )
. up ( )
. up ( ) ;
2019-10-04 07:29:20 +07:00
sourceKeys . push ( keystring ) ;
2019-09-10 00:27:23 +07:00
}
2019-10-04 07:29:20 +07:00
xml = xml . ele ( 'packageSourceCredentials' ) ;
sourceKeys . forEach ( key = > {
2021-04-15 17:28:24 +07:00
if ( ! isValidKey ( key ) ) {
2019-09-10 00:27:23 +07:00
throw new Error (
2021-04-15 17:43:20 +07:00
"Source name can contain letters, numbers, and '-', '_', '.' symbols only. Please, fix source name in NuGet.config and try again."
2019-09-10 00:27:23 +07:00
) ;
}
xml = xml
. ele ( key )
. ele ( 'add' , { key : 'Username' , value : owner } )
. up ( )
. ele ( 'add' , {
key : 'ClearTextPassword' ,
value : process.env.NUGET_AUTH_TOKEN
} )
. up ( )
. up ( ) ;
} ) ;
// If NuGet fixes itself such that on Linux it can look for environment variables in the config file (it doesn't seem to work today),
// use this for the value above
// process.platform == 'win32'
// ? '%NUGET_AUTH_TOKEN%'
// : '$NUGET_AUTH_TOKEN'
var output = xml . end ( { pretty : true } ) ;
fs . writeFileSync ( tempFileLocation , output ) ;
}