Skip to content

Commit

Permalink
Merge pull request #2 from devlead/feature/gh-1
Browse files Browse the repository at this point in the history
Allows to specify the version of Cake to use (#1)
  • Loading branch information
ecampidoglio committed Oct 31, 2019
2 parents 92d9326 + d4cab86 commit beb9882
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 33 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,17 @@ jobs:
uses: ./
with:
target: Successful-Task
- name: Run a specific version ( 0.34.1 )
env:
TEST_CAKE_VERSION: 0.34.1
uses: ./
with:
cake-version: 0.34.1
target: Version-Check-Task
- name: Run a specific version ( 0.33.0 )
env:
TEST_CAKE_VERSION: 0.33.0
uses: ./
with:
cake-version: 0.33.0
target: Version-Check-Task
65 changes: 54 additions & 11 deletions __tests__/dotnet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ import { Platform } from '../src/platform';
import { ToolsDirectory } from '../src/toolsDirectory';

const targetDirectory = path.join('target', 'directory');
const cakeVersion = '0.35.0';
const installedCakeVersion = '0.34.0';
const containsFileWithOldToolInstalled = (fileName: string) => {
switch (fileName) {
case 'dotnet-cake':
case 'dotnet-cake.exe':
case path.join('.store', 'cake.tool', installedCakeVersion, 'project.assets.json'):
return true;
default:
return false;
}
};

jest.mock('@actions/core');
jest.mock('@actions/exec');
Expand Down Expand Up @@ -38,6 +50,16 @@ describe('When successfully installing the Cake Tool locally', () => {
await DotNet.installLocalCakeTool(new ToolsDirectory(targetDirectory));
expect(fakeExec).toBeCalledWith('dotnet tool install', ['--tool-path', targetDirectory, 'Cake.Tool']);
});

test('it should install specific version of the Cake.Tool in the tools directory', async () => {
await DotNet.installLocalCakeTool(undefined, cakeVersion);
expect(fakeExec).toBeCalledWith('dotnet tool install', ['--version', cakeVersion, '--tool-path', 'tools', 'Cake.Tool']);
});

test('it should install specific version of the Cake.Tool in the specified target directory', async () => {
await DotNet.installLocalCakeTool(new ToolsDirectory(targetDirectory), cakeVersion);
expect(fakeExec).toBeCalledWith('dotnet tool install', ['--version', cakeVersion, '--tool-path', targetDirectory, 'Cake.Tool']);
});
});

describe('When failing to install the Cake Tool locally', () => {
Expand All @@ -54,6 +76,12 @@ describe('When failing to install the Cake Tool locally', () => {
test('it should throw an error containing the exit code', async () => {
await expect(DotNet.installLocalCakeTool()).rejects.toThrowError('-99');
});

test('it should throw an error containing the exit code', async () => {
const directoryWithCakeTool = new ToolsDirectory(targetDirectory);
directoryWithCakeTool.containsFile = jest.fn().mockImplementation(containsFileWithOldToolInstalled);
await expect(DotNet.installLocalCakeTool(directoryWithCakeTool, cakeVersion)).rejects.toThrowError('-99');
});
});

describe('When successfully installing a tool locally', () => {
Expand All @@ -64,12 +92,12 @@ describe('When successfully installing a tool locally', () => {
});

test('it should install the specified tool in the tools directory', async () => {
await DotNet.installLocalTool('The.Tool');
await DotNet.installLocalTool('The.Tool', 'dotnet-tool');
expect(fakeExec).toBeCalledWith('dotnet tool install', ['--tool-path', 'tools', 'The.Tool']);
});

test('it should install the specified tool in the specified target directory', async () => {
await DotNet.installLocalTool('The.Tool', new ToolsDirectory(targetDirectory));
await DotNet.installLocalTool('The.Tool', 'dotnet-tool', new ToolsDirectory(targetDirectory));
expect(fakeExec).toBeCalledWith('dotnet tool install', ['--tool-path', targetDirectory, 'The.Tool']);
});
});
Expand All @@ -81,12 +109,12 @@ describe('When failing to install the a tool locally', () => {
fakeExec.mockReturnValue(Promise.resolve(-99));
});

test('it should throw an error containing the tool name', async () => {
await expect(DotNet.installLocalTool('The.Tool')).rejects.toThrowError('The.Tool');
test('it should throw an error containing the package id', async () => {
await expect(DotNet.installLocalTool('The.Tool', 'dotnet-tool')).rejects.toThrowError('The.Tool');
});

test('it should throw an error containing the exit code', async () => {
await expect(DotNet.installLocalTool('The.Tool')).rejects.toThrowError('-99');
await expect(DotNet.installLocalTool('The.Tool', 'dotnet-tool')).rejects.toThrowError('-99');
});
});

Expand All @@ -95,9 +123,8 @@ describe('When installing the Cake Tool locally to a directory where it already
const fakeExec = exec as jest.MockedFunction<typeof exec>;

beforeAll(() => {
directoryWithCakeTool.containsFile = jest.fn().mockImplementation(() => {
return true;
});
directoryWithCakeTool.containsFile = jest.fn().mockImplementation(containsFileWithOldToolInstalled);
fakeExec.mockReturnValue(Promise.resolve(0));
});

test('it should not attempt to install the Cake.Tool in the same directory', () => {
Expand All @@ -108,10 +135,26 @@ describe('When installing the Cake Tool locally to a directory where it already
});

test('it should look for the Cake.Tool executable with extension on Windows', () => {
Platform.isWindows = jest.fn().mockImplementation(() => {
return true;
});
Platform.isWindows = jest.fn().mockImplementation(() => true);
DotNet.installLocalCakeTool(directoryWithCakeTool);
expect(directoryWithCakeTool.containsFile).toBeCalledWith(expect.stringMatching('dotnet-cake.exe$'));
});

test('it should look for the Cake.Tool executable without extension on Posix', () => {
Platform.isWindows = jest.fn().mockImplementation(() => false);
DotNet.installLocalCakeTool(directoryWithCakeTool);
expect(directoryWithCakeTool.containsFile).toBeCalledWith(expect.stringMatching('dotnet-cake$'));
});

test('it should uninstall and install specific version of the Cake.Tool in the specified target directory', async () => {
await DotNet.installLocalCakeTool(directoryWithCakeTool, cakeVersion);
expect(fakeExec).toBeCalledWith('dotnet tool uninstall', ['--tool-path', targetDirectory, 'Cake.Tool']);
expect(fakeExec).toBeCalledWith('dotnet tool install', ['--version', cakeVersion, '--tool-path', targetDirectory, 'Cake.Tool']);
});

test('it should not uninstall and install already installed specific version of the Cake.Tool', async () => {
await DotNet.installLocalCakeTool(directoryWithCakeTool, installedCakeVersion);
expect(fakeExec).not.toBeCalledWith('dotnet tool uninstall', ['--tool-path', installedCakeVersion, 'Cake.Tool']);
expect(fakeExec).not.toBeCalledWith('dotnet tool install', ['--version', installedCakeVersion, '--tool-path', targetDirectory, 'Cake.Tool']);
});
});
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ inputs:
target:
description: 'The name of the task to execute. Note that this argument must be supported by the script.'
required: false
cake-version:
description: 'The version of Cake to install.'
required: false
runs:
using: 'node12'
main: 'lib/main.js'
15 changes: 15 additions & 0 deletions build.cake
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,19 @@ Task("Failing-Task")
throw new Exception("Failed");
});

Task("Version-Check-Task")
.Does(context =>
{
Version expect = Version.TryParse($"{EnvironmentVariable("TEST_CAKE_VERSION")}.0", out Version parsedVersion)
? parsedVersion
: null;
if (expect != context.Environment.Runtime.CakeVersion)
{
throw new Exception($"Expected version {expect} got {context.Environment.Runtime.CakeVersion}");
}
Information("Successful");
});

RunTarget(target);
37 changes: 27 additions & 10 deletions lib/dotnet.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,48 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const path = __importStar(require("path"));
const core = __importStar(require("@actions/core"));
const exec_1 = require("@actions/exec");
const toolsDirectory_1 = require("./toolsDirectory");
const platform_1 = require("./platform");
const dotnetToolInstall = 'dotnet tool install';
const dotnetToolUnInstall = 'dotnet tool uninstall';
const dotnetCake = 'dotnet-cake';
class DotNet {
static disableTelemetry() {
core.exportVariable('DOTNET_CLI_TELEMETRY_OPTOUT', '1');
}
static installLocalCakeTool(targetDirectory = new toolsDirectory_1.ToolsDirectory()) {
static installLocalCakeTool(targetDirectory = new toolsDirectory_1.ToolsDirectory(), version) {
return __awaiter(this, void 0, void 0, function* () {
const cakeTool = platform_1.Platform.isWindows() ? `${dotnetCake}.exe` : dotnetCake;
if (targetDirectory.containsFile(cakeTool)) {
core.info(`The Cake.Tool already exists in ${targetDirectory}, skipping installation`);
return;
}
return DotNet.installLocalTool('Cake.Tool', targetDirectory);
return DotNet.installLocalTool('Cake.Tool', dotnetCake, targetDirectory, version);
});
}
static installLocalTool(toolName, targetDirectory = new toolsDirectory_1.ToolsDirectory()) {
static installLocalTool(packageId, toolName, targetDirectory = new toolsDirectory_1.ToolsDirectory(), version) {
return __awaiter(this, void 0, void 0, function* () {
const exitCode = yield exec_1.exec(dotnetToolInstall, ['--tool-path', targetDirectory.path, toolName]);
const toolExecutable = `${toolName}${platform_1.Platform.isWindows() ? '.exe' : ''}`;
if (targetDirectory.containsFile(toolExecutable)) {
if (version) {
const toolInstallPath = path.join('.store', packageId.toLowerCase(), version.toLowerCase(), 'project.assets.json');
if (targetDirectory.containsFile(toolInstallPath)) {
core.info(`The ${packageId} version ${version} already exists in ${targetDirectory}, skipping installation`);
return;
}
const uninstallExitCode = yield exec_1.exec(dotnetToolUnInstall, ['--tool-path', targetDirectory.path, packageId]);
if (uninstallExitCode != 0) {
throw new Error(`Failed to uninstall previous version of ${packageId}. Exit code: ${uninstallExitCode}`);
}
}
else {
core.info(`The ${packageId} already exists in ${targetDirectory}, skipping installation`);
return;
}
}
const versionArg = (version) ? ['--version', version] : [];
const installArgs = [...versionArg, '--tool-path', targetDirectory.path, packageId];
const exitCode = yield exec_1.exec(dotnetToolInstall, installArgs);
if (exitCode != 0) {
throw new Error(`Failed to install ${toolName}. Exit code: ${exitCode}`);
throw new Error(`Failed to install ${packageId}. Exit code: ${exitCode}`);
}
});
}
Expand Down
3 changes: 2 additions & 1 deletion lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ function run() {
try {
const scriptPath = core.getInput('script-path');
const target = new cakeParameter_1.CakeArgument('target', core.getInput('target'));
const version = core.getInput('cake-version');
const toolsDir = new toolsDirectory_1.ToolsDirectory();
toolsDir.create();
dotnet_1.DotNet.disableTelemetry();
yield dotnet_1.DotNet.installLocalCakeTool(toolsDir);
yield dotnet_1.DotNet.installLocalCakeTool(toolsDir, version);
yield cake_1.CakeTool.runScript(scriptPath, toolsDir, target);
}
catch (error) {
Expand Down
53 changes: 43 additions & 10 deletions src/dotnet.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,65 @@
import * as path from 'path';
import * as core from '@actions/core';
import { exec } from '@actions/exec';
import { ToolsDirectory } from './toolsDirectory';
import { Platform } from './platform';

const dotnetToolInstall = 'dotnet tool install';
const dotnetToolUnInstall = 'dotnet tool uninstall';
const dotnetCake = 'dotnet-cake';

export class DotNet {
static disableTelemetry() {
core.exportVariable('DOTNET_CLI_TELEMETRY_OPTOUT', '1');
}

static async installLocalCakeTool(targetDirectory: ToolsDirectory = new ToolsDirectory()) {
const cakeTool = Platform.isWindows() ? `${dotnetCake}.exe` : dotnetCake;
static async installLocalCakeTool(
targetDirectory: ToolsDirectory = new ToolsDirectory(),
version?: string
) {
return DotNet.installLocalTool('Cake.Tool', dotnetCake, targetDirectory, version);
}

static async installLocalTool(
packageId: string,
toolName: string,
targetDirectory: ToolsDirectory = new ToolsDirectory(),
version?: string
) {
const toolExecutable = `${toolName}${Platform.isWindows() ? '.exe' : ''}`;

if (targetDirectory.containsFile(toolExecutable)) {
if (version) {
const toolInstallPath = path.join(
'.store',
packageId.toLowerCase(),
version.toLowerCase(),
'project.assets.json'
);

if (targetDirectory.containsFile(cakeTool)) {
core.info(`The Cake.Tool already exists in ${targetDirectory}, skipping installation`);
return;
if (targetDirectory.containsFile(toolInstallPath)) {
core.info(`The ${packageId} version ${version} already exists in ${targetDirectory}, skipping installation`);
return;
}

const uninstallExitCode = await exec(dotnetToolUnInstall, ['--tool-path', targetDirectory.path, packageId]);

if (uninstallExitCode != 0) {
throw new Error(`Failed to uninstall previous version of ${packageId}. Exit code: ${uninstallExitCode}`);
}
} else {
core.info(`The ${packageId} already exists in ${targetDirectory}, skipping installation`);
return;
}
}

return DotNet.installLocalTool('Cake.Tool', targetDirectory);
}
const versionArg = (version) ? ['--version', version] : [];
const installArgs = [...versionArg, '--tool-path', targetDirectory.path, packageId];

static async installLocalTool(toolName: string, targetDirectory: ToolsDirectory = new ToolsDirectory()) {
const exitCode = await exec(dotnetToolInstall, ['--tool-path', targetDirectory.path, toolName]);
const exitCode = await exec(dotnetToolInstall, installArgs);

if (exitCode != 0) {
throw new Error(`Failed to install ${toolName}. Exit code: ${exitCode}`);
throw new Error(`Failed to install ${packageId}. Exit code: ${exitCode}`);
}
}
}
3 changes: 2 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ export async function run() {
try {
const scriptPath = core.getInput('script-path');
const target = new CakeArgument('target', core.getInput('target'));
const version = core.getInput('cake-version');

const toolsDir = new ToolsDirectory();
toolsDir.create();

DotNet.disableTelemetry();

await DotNet.installLocalCakeTool(toolsDir);
await DotNet.installLocalCakeTool(toolsDir, version);
await CakeTool.runScript(scriptPath, toolsDir, target);
} catch (error) {
core.setFailed(error.message);
Expand Down

0 comments on commit beb9882

Please sign in to comment.