Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
"loc.input.help.feedPublish": "Select a feed hosted in this organization. You must have Azure Artifacts installed and licensed to select a feed here.",
"loc.input.label.publishPackageMetadata": "Publish pipeline metadata",
"loc.input.help.publishPackageMetadata": "Associate this build/release pipeline’s metadata (run #, source code information) with the package",
"loc.input.label.allowPackageConflicts": "Allow duplicates to be skipped",
"loc.input.help.allowPackageConflicts": "If you continually publish a set of packages and only change the version number of the subset of packages that have changed, use this option. It allows the task to report success even if some of your packages are rejected with a 409 Conflict error. This option appends the --skip-duplicate argument to the dotnet nuget push command.",
"loc.input.label.externalEndpoint": "NuGet server",
"loc.input.help.externalEndpoint": "The NuGet service connection that contains the external NuGet server’s credentials.",
"loc.input.label.searchPatternPack": "Path to csproj or nuspec file(s) to pack",
Expand Down
12 changes: 12 additions & 0 deletions Tasks/DotNetCoreCLIV2/Tests/L0.ts
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,18 @@ describe('DotNetCoreExe Suite', function () {
assert.equal(tr.errorIssues.length, 1, "should have thrown an error");
});

it('pushes successfully to internal hosted feed with --skip-duplicate', async () => {
let tp = path.join(__dirname, './PushTests/internalFeedWithSkipDuplicate.js')
let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);

await tr.runAsync()
assert(tr.invokedToolCount == 1, 'should have run dotnet once');
assert(tr.ran('c:\\path\\dotnet.exe nuget push c:\\agent\\home\\directory\\foo.nupkg --source https://vsts/packagesource --api-key VSTS --skip-duplicate'), 'it should have run dotnet with --skip-duplicate');
assert(tr.stdOutContained('dotnet output'), "should have dotnet output");
assert(tr.succeeded, 'should have succeeded');
assert.equal(tr.errorIssues.length, 0, "should have no errors");
});

it('test command with publish test results should call trx logger and publish test results', async () => {
let tp = path.join(__dirname, './TestCommandTests/publishtests.js');
let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import ma = require('azure-pipelines-task-lib/mock-answer');
import tmrm = require('azure-pipelines-task-lib/mock-run');
import path = require('path');
import util = require('../DotnetMockHelper');

let taskPath = path.join(__dirname, '../..', 'dotnetcore.js');
let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath);
let nmh: util.DotnetMockHelper = new util.DotnetMockHelper(tmr);
nmh.setNugetVersionInputDefault();
tmr.setInput('command', 'push');
tmr.setInput('searchPatternPush', 'foo.nupkg');
tmr.setInput('nuGetFeedType', 'internal');
tmr.setInput('feedPublish', 'ProjectId/FeedFooId');
tmr.setInput('allowPackageConflicts', 'true');

let a: ma.TaskLibAnswers = <ma.TaskLibAnswers>{
"osType": {},
"checkPath": {
"c:\\agent\\home\\directory\\foo.nupkg": true,
"c:\\path\\dotnet.exe": true
},
"which": {
"dotnet": "c:\\path\\dotnet.exe"
},
"exec": {
"c:\\path\\dotnet.exe nuget push c:\\agent\\home\\directory\\foo.nupkg --source https://vsts/packagesource --api-key VSTS --skip-duplicate": {
"code": 0,
"stdout": "dotnet output",
"stderr": ""
}
},
"exist": {},
"stats": {
"c:\\agent\\home\\directory\\foo.nupkg": {
"isFile": true
}
},
"rmRF": {
"c:\\agent\\home\\directory\\NuGet_1": {
"success": true
},
"c:\\agent\\home\\directory/NuGet_1": {
"success": true
}
},
"findMatch": {
"fromMockedUtility-foo.nupkg" : ["c:\\agent\\home\\directory\\foo.nupkg"]
}
};
nmh.setAnswers(a);
nmh.registerNugetUtilityMock(["c:\\agent\\home\\directory\\foo.nupkg"]);
nmh.registerDefaultNugetVersionMock();
nmh.registerToolRunnerMock();
nmh.registerNugetConfigMock();
nmh.RegisterLocationServiceMocks();

tmr.run();
11 changes: 9 additions & 2 deletions Tasks/DotNetCoreCLIV2/pushcommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,13 @@ export async function run(): Promise<void> {
}
// Setting creds in the temp NuGet.config if needed
nuGetConfigHelper.setAuthForSourcesInTempNuGetConfig();

// Retrieving if 429 conflicts should not return an error
const allowPackageConflicts = tl.getBoolInput('allowPackageConflicts', false);
const dotnetPath = tl.which('dotnet', true);
try {
for (const packageFile of filesList) {
await dotNetNuGetPushAsync(dotnetPath, packageFile, feedUri, apiKey, configFile, tempNuGetConfigDirectory);
await dotNetNuGetPushAsync(dotnetPath, packageFile, feedUri, apiKey, configFile, tempNuGetConfigDirectory, allowPackageConflicts);
}
} finally {
credCleanup();
Expand All @@ -183,7 +186,7 @@ export async function run(): Promise<void> {
}
}

function dotNetNuGetPushAsync(dotnetPath: string, packageFile: string, feedUri: string, apiKey: string, configFile: string, workingDirectory: string): Q.Promise<number> {
function dotNetNuGetPushAsync(dotnetPath: string, packageFile: string, feedUri: string, apiKey: string, configFile: string, workingDirectory: string, skipDuplicate: boolean): Q.Promise<number> {
const dotnet = tl.tool(dotnetPath);

dotnet.arg('nuget');
Expand All @@ -197,6 +200,10 @@ function dotNetNuGetPushAsync(dotnetPath: string, packageFile: string, feedUri:
dotnet.arg('--api-key');
dotnet.arg(apiKey);

if (skipDuplicate) {
dotnet.arg('--skip-duplicate');
}

// dotnet.exe v1 and v2 do not accept the --verbosity parameter for the "nuget push"" command, although it does for other commands
const envWithProxy = ngRunner.setNuGetProxyEnvironment(process.env, /*configFile*/ null, feedUri);
return dotnet.exec({ cwd: workingDirectory, env: envWithProxy } as IExecOptions);
Expand Down
13 changes: 11 additions & 2 deletions Tasks/DotNetCoreCLIV2/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"demands": [],
"version": {
"Major": 2,
"Minor": 269,
"Minor": 270,
"Patch": 0
},
"minimumAgentVersion": "2.144.0",
Expand Down Expand Up @@ -333,6 +333,15 @@
"helpMarkDown": "Associate this build/release pipeline’s metadata (run #, source code information) with the package",
"visibleRule": "command = push && nuGetFeedType = internal"
},
{
"name": "allowPackageConflicts",
"groupName": "pushAdvanced",
"type": "boolean",
"label": "Allow duplicates to be skipped",
"defaultValue": false,
"helpMarkDown": "If you continually publish a set of packages and only change the version number of the subset of packages that have changed, use this option. It allows the task to report success even if some of your packages are rejected with a 409 Conflict error. This option appends the --skip-duplicate argument to the dotnet nuget push command.",
"visibleRule": "command = push"
},
{
"name": "externalEndpoint",
"aliases": [
Expand Down Expand Up @@ -610,4 +619,4 @@
"Warning_UnsupportedServiceConnectionAuth": "The service connection does not use a supported authentication method. Please use a service connection with personal access token based auth.",
"Error_InvalidSemVer": "Build number is not a valid SemVer 2.0 string."
}
}
}
11 changes: 10 additions & 1 deletion Tasks/DotNetCoreCLIV2/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"demands": [],
"version": {
"Major": 2,
"Minor": 269,
"Minor": 270,
"Patch": 0
},
"minimumAgentVersion": "2.144.0",
Expand Down Expand Up @@ -333,6 +333,15 @@
"helpMarkDown": "ms-resource:loc.input.help.publishPackageMetadata",
"visibleRule": "command = push && nuGetFeedType = internal"
},
{
"name": "allowPackageConflicts",
"groupName": "pushAdvanced",
"type": "boolean",
"label": "ms-resource:loc.input.label.allowPackageConflicts",
"defaultValue": false,
"helpMarkDown": "ms-resource:loc.input.help.allowPackageConflicts",
"visibleRule": "command = push"
},
{
"name": "externalEndpoint",
"aliases": [
Expand Down