From 70528ac0079547ee846f23c57e45048c446d7a06 Mon Sep 17 00:00:00 2001 From: Alex Mullans <483400+infin8x@users.noreply.github.com> Date: Thu, 3 Oct 2019 17:29:20 -0700 Subject: [PATCH] Support for non-GPR sources --- __tests__/__snapshots__/authutil.test.ts.snap | 82 ++++++++++--- __tests__/authutil.test.ts | 113 +++++++++++++++--- lib/authutil.js | 35 +++--- lib/setup-dotnet.js | 3 +- src/authutil.ts | 32 ++--- src/setup-dotnet.ts | 3 +- 6 files changed, 203 insertions(+), 65 deletions(-) diff --git a/__tests__/__snapshots__/authutil.test.ts.snap b/__tests__/__snapshots__/authutil.test.ts.snap index 8f4334f..245ced7 100644 --- a/__tests__/__snapshots__/authutil.test.ts.snap +++ b/__tests__/__snapshots__/authutil.test.ts.snap @@ -15,6 +15,21 @@ exports[`authutil tests Existing config not in repo root, sets up a partial NuGe " `; +exports[`authutil tests Existing config w/ Azure Artifacts source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR 1`] = ` +" + + + + + + + + + + +" +`; + exports[`authutil tests Existing config w/ GPR source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR 1`] = ` " @@ -37,13 +52,13 @@ exports[`authutil tests Existing config w/ no GPR sources, sets up a full NuGet. - + - + - + " `; @@ -55,13 +70,28 @@ exports[`authutil tests Existing config w/ no sources, sets up a full NuGet.conf - + - + - + + +" +`; + +exports[`authutil tests Existing config w/ only Azure Artifacts source, sets up a partial NuGet.config user/PAT for GPR 1`] = ` +" + + + + + + + + + " `; @@ -92,12 +122,10 @@ exports[`authutil tests Existing config w/ two GPR sources, sets up a partial Nu - - - - - - + + + + " `; @@ -109,13 +137,31 @@ exports[`authutil tests No existing config, sets up a full NuGet.config with URL - + - + - + + +" +`; + +exports[`authutil tests No existing config, sets up a full NuGet.config with URL and token for other source 1`] = ` +" + + + + + + + + + + + + " `; @@ -127,13 +173,13 @@ exports[`authutil tests No existing config, sets up a full NuGet.config with URL - + - + - + " `; diff --git a/__tests__/authutil.test.ts b/__tests__/authutil.test.ts index 19d31c0..610ea12 100644 --- a/__tests__/authutil.test.ts +++ b/__tests__/authutil.test.ts @@ -2,7 +2,7 @@ import io = require('@actions/io'); import fs = require('fs'); import path = require('path'); -const tempDir = path.join( +const fakeSourcesDirForTesting = path.join( __dirname, 'runner', path.join( @@ -10,7 +10,7 @@ const tempDir = path.join( .toString(36) .substring(7) ), - 'temp' + 's' ); const invalidNuGetConfig: string = ``; @@ -56,16 +56,32 @@ const spaceNuGetConfig: string = ` `; -const nugetConfigFile = path.join(tempDir, '../nuget.config'); +const azureartifactsNuGetConfig: string = ` + + + + +`; + +const azureartifactsnugetorgNuGetConfig: string = ` + + + + + +`; + +// We want a NuGet.config one level above the sources directory, so it doesn't trample a user's NuGet.config but is still picked up by NuGet/dotnet. +const nugetConfigFile = path.join(fakeSourcesDirForTesting, '../nuget.config'); process.env['GITHUB_REPOSITORY'] = 'OwnerName/repo'; -process.env['RUNNER_TEMP'] = tempDir; +process.env['RUNNER_TEMP'] = fakeSourcesDirForTesting; import * as auth from '../src/authutil'; describe('authutil tests', () => { - beforeAll(async () => { - await io.rmRF(tempDir); - await io.mkdirP(tempDir); + beforeEach(async () => { + await io.rmRF(fakeSourcesDirForTesting); + await io.mkdirP(fakeSourcesDirForTesting); }, 100000); beforeEach(() => { @@ -107,7 +123,10 @@ describe('authutil tests', () => { it('Existing config (invalid), tries to parse an invalid NuGet.config and throws', async () => { process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; - const inputNuGetConfigPath: string = path.join(tempDir, 'nuget.config'); + const inputNuGetConfigPath: string = path.join( + fakeSourcesDirForTesting, + 'nuget.config' + ); fs.writeFileSync(inputNuGetConfigPath, invalidNuGetConfig); let thrown = false; try { @@ -120,7 +139,10 @@ describe('authutil tests', () => { it('Existing config w/ no sources, sets up a full NuGet.config with URL and user/PAT for GPR', async () => { process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; - const inputNuGetConfigPath: string = path.join(tempDir, 'nuget.config'); + const inputNuGetConfigPath: string = path.join( + fakeSourcesDirForTesting, + 'nuget.config' + ); fs.writeFileSync(inputNuGetConfigPath, emptyNuGetConfig); await auth.configAuthentication('https://nuget.pkg.github.com'); expect(fs.existsSync(nugetConfigFile)).toBe(true); @@ -131,7 +153,10 @@ describe('authutil tests', () => { it('Existing config w/ no GPR sources, sets up a full NuGet.config with URL and user/PAT for GPR', async () => { process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; - const inputNuGetConfigPath: string = path.join(tempDir, 'nuget.config'); + const inputNuGetConfigPath: string = path.join( + fakeSourcesDirForTesting, + 'nuget.config' + ); fs.writeFileSync(inputNuGetConfigPath, nugetorgNuGetConfig); await auth.configAuthentication('https://nuget.pkg.github.com'); expect(fs.existsSync(nugetConfigFile)).toBe(true); @@ -142,7 +167,10 @@ describe('authutil tests', () => { it('Existing config w/ only GPR source, sets up a partial NuGet.config user/PAT for GPR', async () => { process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; - const inputNuGetConfigPath: string = path.join(tempDir, 'nuget.config'); + const inputNuGetConfigPath: string = path.join( + fakeSourcesDirForTesting, + 'nuget.config' + ); fs.writeFileSync(inputNuGetConfigPath, gprNuGetConfig); await auth.configAuthentication('https://nuget.pkg.github.com'); expect(fs.existsSync(nugetConfigFile)).toBe(true); @@ -153,7 +181,10 @@ describe('authutil tests', () => { it('Existing config w/ GPR source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR', async () => { process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; - const inputNuGetConfigPath: string = path.join(tempDir, 'nuget.config'); + const inputNuGetConfigPath: string = path.join( + fakeSourcesDirForTesting, + 'nuget.config' + ); fs.writeFileSync(inputNuGetConfigPath, gprnugetorgNuGetConfig); await auth.configAuthentication('https://nuget.pkg.github.com'); expect(fs.existsSync(nugetConfigFile)).toBe(true); @@ -164,7 +195,10 @@ describe('authutil tests', () => { it('Existing config w/ two GPR sources, sets up a partial NuGet.config user/PAT for GPR', async () => { process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; - const inputNuGetConfigPath: string = path.join(tempDir, 'nuget.config'); + const inputNuGetConfigPath: string = path.join( + fakeSourcesDirForTesting, + 'nuget.config' + ); fs.writeFileSync(inputNuGetConfigPath, twogprNuGetConfig); await auth.configAuthentication('https://nuget.pkg.github.com'); expect(fs.existsSync(nugetConfigFile)).toBe(true); @@ -175,7 +209,10 @@ describe('authutil tests', () => { it('Existing config w/ spaces in key, throws for now', async () => { process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; - const inputNuGetConfigPath: string = path.join(tempDir, 'nuget.config'); + const inputNuGetConfigPath: string = path.join( + fakeSourcesDirForTesting, + 'nuget.config' + ); fs.writeFileSync(inputNuGetConfigPath, spaceNuGetConfig); let thrown = false; try { @@ -188,7 +225,10 @@ describe('authutil tests', () => { it('Existing config not in repo root, sets up a partial NuGet.config user/PAT for GPR', async () => { process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; - const inputNuGetConfigDirectory: string = path.join(tempDir, 'subfolder'); + const inputNuGetConfigDirectory: string = path.join( + fakeSourcesDirForTesting, + 'subfolder' + ); const inputNuGetConfigPath: string = path.join( inputNuGetConfigDirectory, 'nuget.config' @@ -204,4 +244,47 @@ describe('authutil tests', () => { fs.readFileSync(nugetConfigFile, {encoding: 'utf8'}) ).toMatchSnapshot(); }); + + it('Existing config w/ only Azure Artifacts source, sets up a partial NuGet.config user/PAT for GPR', async () => { + process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; + const inputNuGetConfigPath: string = path.join( + fakeSourcesDirForTesting, + 'nuget.config' + ); + fs.writeFileSync(inputNuGetConfigPath, azureartifactsNuGetConfig); + await auth.configAuthentication( + 'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json' + ); + expect(fs.existsSync(nugetConfigFile)).toBe(true); + expect( + fs.readFileSync(nugetConfigFile, {encoding: 'utf8'}) + ).toMatchSnapshot(); + }); + + it('Existing config w/ Azure Artifacts source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR', async () => { + process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; + const inputNuGetConfigPath: string = path.join( + fakeSourcesDirForTesting, + 'nuget.config' + ); + fs.writeFileSync(inputNuGetConfigPath, azureartifactsnugetorgNuGetConfig); + await auth.configAuthentication( + 'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json' + ); + expect(fs.existsSync(nugetConfigFile)).toBe(true); + expect( + fs.readFileSync(nugetConfigFile, {encoding: 'utf8'}) + ).toMatchSnapshot(); + }); + + it('No existing config, sets up a full NuGet.config with URL and token for other source', async () => { + process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; + await auth.configAuthentication( + 'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json' + ); + expect(fs.existsSync(nugetConfigFile)).toBe(true); + expect( + fs.readFileSync(nugetConfigFile, {encoding: 'utf8'}) + ).toMatchSnapshot(); + }); }); diff --git a/lib/authutil.js b/lib/authutil.js index d7ffa4b..7c98a9f 100644 --- a/lib/authutil.js +++ b/lib/authutil.js @@ -22,12 +22,15 @@ exports.configAuthentication = configAuthentication; function writeFeedToFile(feedUrl, existingFileLocation, tempFileLocation) { console.log(`dotnet-auth: Finding any source references in ${existingFileLocation}, writing a new temporary configuration file with credentials to ${tempFileLocation}`); let xml; - let gprKeys = []; + let sourceKeys = []; let owner = core.getInput('owner'); - if (!owner && feedUrl.indexOf('nuget.pkg.github.com') > -1) { + let sourceUrl = feedUrl; + if (!owner) { owner = github.context.repo.owner; } - let sourceUrl = 'https://nuget.pkg.github.com/' + owner; + if (feedUrl.indexOf('nuget.pkg.github.com') > -1) { + sourceUrl = 'https://nuget.pkg.github.com/' + 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}}'); } @@ -45,10 +48,10 @@ function writeFeedToFile(feedUrl, existingFileLocation, tempFileLocation) { // file has only one if (json.configuration.packageSources.add['@_value'] .toLowerCase() - .includes('nuget.pkg.github.com')) { + .includes(feedUrl.toLowerCase())) { let key = json.configuration.packageSources.add['@_key']; - gprKeys.push(key); - core.debug(`Found a GPR URL with key ${key}`); + sourceKeys.push(key); + core.debug(`Found a URL with key ${key}`); } } else { @@ -57,10 +60,10 @@ function writeFeedToFile(feedUrl, existingFileLocation, tempFileLocation) { core.debug(json.configuration.packageSources.add[i]); if (json.configuration.packageSources.add[i]['@_value'] .toLowerCase() - .includes('nuget.pkg.github.com')) { + .includes(feedUrl.toLowerCase())) { let key = json.configuration.packageSources.add[i]['@_key']; - gprKeys.push(key); - core.debug(`Found a GPR URL with key ${key}`); + sourceKeys.push(key); + core.debug(`Found a URL with key ${key}`); } } } @@ -73,22 +76,22 @@ function writeFeedToFile(feedUrl, existingFileLocation, tempFileLocation) { .ele('add', { key: 'defaultPushSource', value: sourceUrl }) .up() .up(); - if (gprKeys.length == 0) { - let keystring = 'GPR'; + if (sourceKeys.length == 0) { + let keystring = 'Source'; xml = xml .ele('packageSources') .ele('add', { key: keystring, value: sourceUrl }) .up() .up(); - gprKeys.push(keystring); + sourceKeys.push(keystring); } - gprKeys.forEach(key => { + xml = xml + .ele('packageSourceCredentials'); + sourceKeys.forEach(key => { if (key.indexOf(' ') > -1) { throw new Error("This action currently can't handle source names with spaces. Remove the space from your repo's NuGet.config and try again."); } - xml = xml - .ele('packageSourceCredentials') - .ele(key) + xml = xml.ele(key) .ele('add', { key: 'Username', value: owner }) .up() .ele('add', { diff --git a/lib/setup-dotnet.js b/lib/setup-dotnet.js index 283e0a5..7c42583 100644 --- a/lib/setup-dotnet.js +++ b/lib/setup-dotnet.js @@ -35,8 +35,9 @@ function run() { yield dotnetInstaller.installDotnet(); } const sourceUrl = core.getInput('source-url'); + const configFile = core.getInput('config-file'); if (sourceUrl) { - auth.configAuthentication(sourceUrl); + auth.configAuthentication(sourceUrl, configFile); } // TODO: setup proxy from runner proxy config const matchersPath = path.join(__dirname, '..', '.github'); diff --git a/src/authutil.ts b/src/authutil.ts index ed17ba4..2979bb6 100644 --- a/src/authutil.ts +++ b/src/authutil.ts @@ -34,12 +34,15 @@ function writeFeedToFile( `dotnet-auth: Finding any source references in ${existingFileLocation}, writing a new temporary configuration file with credentials to ${tempFileLocation}` ); let xml: xmlbuilder.XMLElement; - let gprKeys: string[] = []; + let sourceKeys: string[] = []; let owner: string = core.getInput('owner'); - if (!owner && feedUrl.indexOf('nuget.pkg.github.com') > -1) { + let sourceUrl: string = feedUrl; + if (!owner) { owner = github.context.repo.owner; } - let sourceUrl: string = 'https://nuget.pkg.github.com/' + owner; + if (feedUrl.indexOf('nuget.pkg.github.com') > -1) { + sourceUrl = 'https://nuget.pkg.github.com/' + owner; + } if (!process.env.NUGET_AUTH_TOKEN || process.env.NUGET_AUTH_TOKEN == '') { throw new Error( @@ -63,11 +66,11 @@ function writeFeedToFile( if ( json.configuration.packageSources.add['@_value'] .toLowerCase() - .includes('nuget.pkg.github.com') + .includes(feedUrl.toLowerCase()) ) { let key = json.configuration.packageSources.add['@_key']; - gprKeys.push(key); - core.debug(`Found a GPR URL with key ${key}`); + sourceKeys.push(key); + core.debug(`Found a URL with key ${key}`); } } else { // file has 2+ @@ -80,11 +83,11 @@ function writeFeedToFile( if ( json.configuration.packageSources.add[i]['@_value'] .toLowerCase() - .includes('nuget.pkg.github.com') + .includes(feedUrl.toLowerCase()) ) { let key = json.configuration.packageSources.add[i]['@_key']; - gprKeys.push(key); - core.debug(`Found a GPR URL with key ${key}`); + sourceKeys.push(key); + core.debug(`Found a URL with key ${key}`); } } } @@ -99,16 +102,18 @@ function writeFeedToFile( .up() .up(); - if (gprKeys.length == 0) { - let keystring = 'GPR'; + if (sourceKeys.length == 0) { + let keystring = 'Source'; xml = xml .ele('packageSources') .ele('add', {key: keystring, value: sourceUrl}) .up() .up(); - gprKeys.push(keystring); + sourceKeys.push(keystring); } - gprKeys.forEach(key => { + xml = xml.ele('packageSourceCredentials'); + + sourceKeys.forEach(key => { if (key.indexOf(' ') > -1) { throw new Error( "This action currently can't handle source names with spaces. Remove the space from your repo's NuGet.config and try again." @@ -116,7 +121,6 @@ function writeFeedToFile( } xml = xml - .ele('packageSourceCredentials') .ele(key) .ele('add', {key: 'Username', value: owner}) .up() diff --git a/src/setup-dotnet.ts b/src/setup-dotnet.ts index 038b294..d1cac40 100644 --- a/src/setup-dotnet.ts +++ b/src/setup-dotnet.ts @@ -19,8 +19,9 @@ async function run() { } const sourceUrl: string = core.getInput('source-url'); + const configFile: string = core.getInput('config-file'); if (sourceUrl) { - auth.configAuthentication(sourceUrl); + auth.configAuthentication(sourceUrl, configFile); } // TODO: setup proxy from runner proxy config