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
17 changes: 15 additions & 2 deletions Tasks/DotNetCoreCLIV2/Tests/L0.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,9 @@ describe('DotNetCoreExe Suite', function () {
it('publish does not use logger when feature flag is disabled', async () => {
let tp = path.join(__dirname, 'publishWithFeatureFlagDisabled.js');
let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);

await tr.runAsync();

assert(tr.invokedToolCount == 1, 'should have invoked tool once');
assert(tr.succeeded, 'task should have succeeded');
assert(tr.ran('dotnet publish web/project.csproj'), 'should have run dotnet publish');
Expand Down Expand Up @@ -497,6 +497,19 @@ describe('DotNetCoreExe Suite', function () {
assert.equal(tr.errorIssues.length, 0, 'should have no errors');
});

it('test command finds non-root global.json file based on working directory', async () => {
const tp = path.join(__dirname, './TestCommandTests/runTestsWithNonRootGlobalJson.js');
const 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 test --project c:\\agent\\home\\directory\\sources\\src\\temp.csproj'), 'it should have run dotnet test in MTP mode');
assert(tr.stdOutContained('dotnet output'), 'should have dotnet output');
assert(tr.stdOutContained('global.json found at c:\\agent\\home\\directory\\sources\\src\\global.json. Test runner is: \'Microsoft.Testing.Platform\''), 'it should have used MTP runner from global.json');
assert(tr.succeeded, 'should have succeeded');
assert.equal(tr.errorIssues.length, 0, 'should have no errors');
});

it('custom command fails when no project match found', async () => {
process.env["__command__"] = "custom";
process.env["__custom__"] = "test";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
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');

const taskPath = path.join(__dirname, '../..', 'dotnetcore.js');
const tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath);
const nmh: util.DotnetMockHelper = new util.DotnetMockHelper(tmr);

nmh.setNugetVersionInputDefault();
tmr.setInput('command', 'test');
tmr.setInput('projects', 'src\\temp.csproj');
tmr.setInput('publishTestResults', 'false');
tmr.setInput('workingDirectory', 'src');

const a: ma.TaskLibAnswers = <ma.TaskLibAnswers>{
'osType': {},
'checkPath': {
'c:\\agent\\home\\directory\\sources\\src\\temp.csproj': true,
'c:\\path\\dotnet.exe': true
},
'which': {
'dotnet': 'c:\\path\\dotnet.exe'
},
'exec': {
'c:\\path\\dotnet.exe test --project c:\\agent\\home\\directory\\sources\\src\\temp.csproj': {
'code': 0,
'stdout': 'dotnet output',
'stderr': ''
}
},
'exist': {
'D:\\src\\github\\vsts-tasks\\Tests\\Nuget': true,
'c:\\agent\\home\\directory\\sources\\src\\global.json': true
},
'stats': {
'c:\\agent\\home\\directory\\sources\\src\\temp.csproj': {
'isFile': true
}
},
'findMatch': {
'src\\temp.csproj': ['c:\\agent\\home\\directory\\sources\\src\\temp.csproj']
}
};
nmh.setAnswers(a);
nmh.registerNugetUtilityMock(['c:\\agent\\home\\directory\\sources\\src\\temp.csproj']);
nmh.registerDefaultNugetVersionMock();
nmh.registerToolRunnerMock();
nmh.registerNugetConfigMock();

// Create mock for fs module
let fs = require('fs');
let fsClone = Object.assign({}, fs);
fsClone.readFileSync = function(filePath, options) {
switch (filePath) {
case 'c:\\agent\\home\\directory\\sources\\src\\global.json':
return '{"test":{"runner":"Microsoft.Testing.Platform"}}';

default:
return fs.readFileSync(filePath, options);
}
};
tmr.registerMock('fs', fsClone);

// Create mock for path module
let pathClone = Object.assign({}, path);
pathClone.resolve = function(...paths: string[]): string {
if (paths.length === 1) {
let p = paths[0];
if (p.startsWith('c:') || p.startsWith('/')) {
return p;
}

return 'c:\\agent\\home\\directory\\sources\\' + p;
}

return path.resolve(...paths);
};
tmr.registerMock('path', pathClone);

tmr.run();
46 changes: 39 additions & 7 deletions Tasks/DotNetCoreCLIV2/dotnetcore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,23 +146,55 @@ export class dotNetExe {
}
}

private findGlobalJsonFile(): string | null {
// Start searching from workingDirectory, fall back to repo root if not set
const repoRoot = path.resolve(tl.getVariable('build.sourcesDirectory') || tl.getVariable('system.defaultWorkingDirectory') || '');
let searchDir = this.workingDirectory || repoRoot;
searchDir = path.resolve(searchDir);

tl.debug(`Searching for global.json starting in '${searchDir}' and ending at '${repoRoot}'.`);

while (searchDir.startsWith(repoRoot)) {
const globalJsonPath = path.join(searchDir, "global.json");
tl.debug(`Checking for global.json at: ${globalJsonPath}`);

if (tl.exist(globalJsonPath)) {
tl.debug(`Found global.json at: ${globalJsonPath}`);
return globalJsonPath;
}

// Move to parent directory, stop if at filesystem root
const parentDir = path.dirname(searchDir);
if (parentDir === searchDir) {
break;
}

searchDir = parentDir;
}

return null;
}

private getIsMicrosoftTestingPlatform(): boolean {
if (!tl.exist("global.json")) {
const globalJsonPath = this.findGlobalJsonFile();

if (!globalJsonPath) {
tl.debug("global.json not found. Test run is VSTest");
return false;
}

let globalJsonContents = fs.readFileSync("global.json", 'utf8');
let globalJsonContents = fs.readFileSync(globalJsonPath, 'utf8');
if (!globalJsonContents.length) {
tl.debug("global.json is empty. Test run is VSTest");
return false;
}

try {
const testRunner = JSON5.parse(globalJsonContents)?.test?.runner;
tl.debug(`global.json is found. Test run is read as '${testRunner}'`);
tl.debug(`global.json found at ${globalJsonPath}. Test runner is: '${testRunner}'`);
return testRunner === 'Microsoft.Testing.Platform';
} catch (error) {
tl.warning(`Error occurred reading global.json: ${error}`);
tl.warning(`Error occurred reading global.json at ${globalJsonPath}: ${error}`);
return false;
}
}
Expand Down Expand Up @@ -468,12 +500,12 @@ export class dotNetExe {
// Default: enabled (opt-out pattern) - users can disable if needed
// Set DISTRIBUTEDTASK_TASKS_DISABLEDOTNETPUBLISHLOGGER=true to disable
const disablePublishLogger = tl.getPipelineFeature('DisableDotNetPublishLogger');

if (disablePublishLogger) {
tl.debug('MSBuild logger disabled for dotnet publish via feature flag DisableDotNetPublishLogger');
return false;
}

return true;
}

Expand All @@ -494,7 +526,7 @@ export class dotNetExe {
};
}
}

let externalendpoints = tl.getDelimitedInput("externalendpoints", ",");
if (externalendpoints) {
externalendpoints = externalendpoints.reduce((ary, id) => {
Expand Down
2 changes: 1 addition & 1 deletion Tasks/DotNetCoreCLIV2/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"version": {
"Major": 2,
"Minor": 266,
"Patch": 0
"Patch": 1
},
"minimumAgentVersion": "2.144.0",
"instanceNameFormat": "dotnet $(command)",
Expand Down