Skip to content

Commit

Permalink
Merge pull request #27 from devlead/feature/gh-26
Browse files Browse the repository at this point in the history
GH26: Add support for installing Cake using tool manifest
  • Loading branch information
ecampidoglio authored Sep 28, 2021
2 parents 4584b77 + 9e10b13 commit 1bc8c8b
Show file tree
Hide file tree
Showing 16 changed files with 3,084 additions and 331 deletions.
12 changes: 12 additions & 0 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"cake.tool": {
"version": "1.2.0",
"commands": [
"dotnet-cake"
]
}
}
}
4 changes: 4 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ jobs:
steps:
- name: Get the sources
uses: actions/checkout@v1
- name: Install Node 16
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Restore the dependencies
run: npm install
- name: Build
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ jobs:
with:
cake-version: 0.33.0
target: Test-Cake-Version
- name: Run with tool manifest
env:
EXPECTED_CAKE_VERSION: 1.2.0
uses: ./
with:
cake-version: tool-manifest
target: Test-Cake-Version
- name: Run bootstrapping of Cake module
uses: ./
with:
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,17 @@ steps:
cake-version: 0.30.0
```

If you're pinning your Cake version using a [tool manifest file](https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools#install-a-local-tool), then you can have the action restore any local tools, including Cake, by specifying `tool-manifest` as the argument for `cake-version`:


```yml
steps:
- name: Run the Cake script
uses: cake-build/cake-action@v1
with:
cake-version: tool-manifest
```

### `cake-bootstrap`

If you're referencing any [custom modules](https://cakebuild.net/docs/fundamentals/modules) from within your script, you'll have to [bootstrap](https://cakebuild.net/docs/fundamentals/preprocessor-directives#module-directive) them _before_ the script runs. The Cake action can do this extra step for you; all you have to do is set the `cake-bootstrap` parameter to `true`:
Expand Down
28 changes: 26 additions & 2 deletions __tests__/action.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ describe('When getting no input arguments from the action', () => {
expect(action.getInputs().scriptPath).toBe('');
});

test('it should return an empty string for the cake-version parameter', () => {
expect(action.getInputs().cakeVersion).toBe('');
test('it should return an false for the cake-version parameter', () => {
expect(action.getInputs().cakeVersion).toBe(false);
});

test('it should return false for the cake-bootstrap parameter', () => {
Expand All @@ -178,3 +178,27 @@ describe('When getting no input arguments from the action', () => {
expect(action.getInputs().scriptArguments).not.toContainEqual(new CakeSwitch('dryrun'));
});
});

describe('When getting the cake-version script input argument set to tool-manifest from the action', () => {
const fakeGetInput = core.getInput as jest.MockedFunction<typeof core.getInput>;

beforeAll(() => {
when(fakeGetInput).calledWith('cake-version').mockReturnValue('tool-manifest');
});

test('it should return cakeVersion as true and no version for cake-version parameter', () => {
expect(action.getInputs().cakeVersion).toBe(true);
});
});

describe('When getting the cake-version script input argument set to latest from the action', () => {
const fakeGetInput = core.getInput as jest.MockedFunction<typeof core.getInput>;

beforeAll(() => {
when(fakeGetInput).calledWith('cake-version').mockReturnValue('latest');
});

test('it should return cakeVersion as false and no version for cake-version parameter', () => {
expect(action.getInputs().cakeVersion).toBe(false);
});
});
58 changes: 50 additions & 8 deletions __tests__/cake.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { exec } from '@actions/exec';
import { which } from '@actions/io';
import * as cake from '../src/cake';
import { ToolsDirectory } from '../src/toolsDirectory';
import { CakeToolSettings } from '../src/cakeToolSettings';
import { CakeArgument, CakeSwitch } from '../src/cakeParameter';

const pathToLocalToolsDirectory = path.join('path', 'to', 'tool');
const pathToLocalTool = path.join(pathToLocalToolsDirectory, 'dotnet-cake');
const dotnetManifestCake = 'dotnet tool run dotnet-cake';

jest.mock('@actions/exec');
jest.mock('@actions/io');
Expand Down Expand Up @@ -61,19 +63,19 @@ describe('When running a script successfully using the local Cake tool', () => {
});

test('it should run the local dotnet-cake tool on the default script', async () => {
await cake.runScript(undefined, new ToolsDirectory(pathToLocalToolsDirectory));
await cake.runScript(undefined, new CakeToolSettings(new ToolsDirectory(pathToLocalToolsDirectory)));
expect(fakeExec).toHaveBeenCalledWith(pathToLocalTool, ['build.cake']);
});

test('it should run the local dotnet-cake tool on the specified script', async () => {
await cake.runScript('script.cake', new ToolsDirectory(pathToLocalToolsDirectory));
await cake.runScript('script.cake', new CakeToolSettings(new ToolsDirectory(pathToLocalToolsDirectory)));
expect(fakeExec).toHaveBeenCalledWith(pathToLocalTool, ['script.cake']);
});

test('it should run the local dotnet-cake tool with the specified parameters', async () => {
await cake.runScript(
'script.cake',
new ToolsDirectory(pathToLocalToolsDirectory),
new CakeToolSettings(new ToolsDirectory(pathToLocalToolsDirectory)),
new CakeArgument('param', 'arg'),
new CakeSwitch('switch'));
expect(fakeExec).toHaveBeenCalledWith(
Expand All @@ -84,7 +86,7 @@ describe('When running a script successfully using the local Cake tool', () => {
test('it should run the local dotnet-cake tool without any invalid parameters', async () => {
await cake.runScript(
'script.cake',
new ToolsDirectory(pathToLocalToolsDirectory),
new CakeToolSettings(new ToolsDirectory(pathToLocalToolsDirectory)),
new CakeArgument('', ''),
new CakeSwitch('switch'));
expect(fakeExec).toHaveBeenCalledWith(
Expand Down Expand Up @@ -115,7 +117,7 @@ describe('When failing to run a script using the local Cake tool', () => {
});

test('it should throw an error containing the exit code', async () => {
await expect(cake.runScript('script.cake', new ToolsDirectory())).rejects.toThrow('-21');
await expect(cake.runScript('script.cake', new CakeToolSettings(new ToolsDirectory()))).rejects.toThrow('-21');
});
});

Expand All @@ -127,12 +129,12 @@ describe('When bootstrapping a script successfully using the local Cake tool', (
});

test('it should run the local dotnet-cake tool on the default script', async () => {
await cake.bootstrapScript(undefined, new ToolsDirectory(pathToLocalToolsDirectory));
await cake.bootstrapScript(undefined, new CakeToolSettings(new ToolsDirectory(pathToLocalToolsDirectory)));
expect(fakeExec).toHaveBeenCalledWith(pathToLocalTool, ['build.cake', '--bootstrap']);
});

test('it should run the local dotnet-cake tool on the specified script', async () => {
await cake.bootstrapScript('script.cake', new ToolsDirectory(pathToLocalToolsDirectory));
await cake.bootstrapScript('script.cake', new CakeToolSettings(new ToolsDirectory(pathToLocalToolsDirectory)));
expect(fakeExec).toHaveBeenCalledWith(pathToLocalTool, ['script.cake', '--bootstrap']);
});
});
Expand All @@ -145,6 +147,46 @@ describe('When failing to bootstrap a script using the local Cake tool', () => {
});

test('it should throw an error containing the exit code', async () => {
await expect(cake.bootstrapScript('script.cake', new ToolsDirectory())).rejects.toThrow('-21');
await expect(cake.bootstrapScript('script.cake', new CakeToolSettings(new ToolsDirectory()))).rejects.toThrow('-21');
});
});

describe('When running a script successfully using the tool manifest', () => {
const fakeExec = exec as jest.MockedFunction<typeof exec>;

beforeAll(async () => {
fakeExec.mockReturnValue(Promise.resolve(0));
});

test('it should run the local dotnet-cake tool on the default script', async () => {
await cake.runScript(undefined, new CakeToolSettings(undefined, true));
expect(fakeExec).toHaveBeenCalledWith(dotnetManifestCake, ['build.cake']);
});

test('it should run the local dotnet-cake tool on the specified script', async () => {
await cake.runScript('script.cake', new CakeToolSettings(undefined, true));
expect(fakeExec).toHaveBeenCalledWith(dotnetManifestCake, ['script.cake']);
});

test('it should run the local dotnet-cake tool with the specified parameters', async () => {
await cake.runScript(
'script.cake',
new CakeToolSettings(undefined, true),
new CakeArgument('param', 'arg'),
new CakeSwitch('switch'));
expect(fakeExec).toHaveBeenCalledWith(
dotnetManifestCake,
['script.cake', '--param=arg', '--switch']);
});

test('it should run the local dotnet-cake tool without any invalid parameters', async () => {
await cake.runScript(
'script.cake',
new CakeToolSettings(undefined, true),
new CakeArgument('', ''),
new CakeSwitch('switch'));
expect(fakeExec).toHaveBeenCalledWith(
dotnetManifestCake,
['script.cake', '--switch']);
});
});
25 changes: 25 additions & 0 deletions __tests__/dotnet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,28 @@ describe('When failing to uninstall a tool locally', () => {
await expect(dotnet.uninstallLocalTool('The.Tool', new ToolsDirectory(targetDirectory))).rejects.toThrow('-99');
});
});

describe('When successfully restoring tools', () => {
const fakeExec = exec as jest.MockedFunction<typeof exec>;

beforeAll(() => {
fakeExec.mockReturnValue(Promise.resolve(0));
});

test('it should restore tools', async () => {
await dotnet.restoreTool();
expect(fakeExec).toHaveBeenCalledWith('dotnet tool restore');
});
});

describe('When failing to restore tools', () => {
const fakeExec = exec as jest.MockedFunction<typeof exec>;

beforeAll(() => {
fakeExec.mockReturnValue(Promise.resolve(-99));
});

test('it should throw an error containing the exit code', async () => {
await expect(dotnet.restoreTool()).rejects.toThrow('-99');
});
});
17 changes: 17 additions & 0 deletions __tests__/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,20 @@ describe('When running the action with the cake-bootstrap input argument', () =>
expect.anything());
});
});

describe('When running the action with the Cake tool manifest input argument', () => {
const fakeGetInputs = action.getInputs as jest.MockedFunction<typeof action.getInputs>;
const fakeRestoreTool = dotnet.restoreTool as jest.MockedFunction<typeof dotnet.restoreTool>;

beforeAll(() => {
fakeGetInputs.mockReturnValue({
scriptArguments: [],
cakeVersion: true
});
});

test('it should restore dotnet tools', async () => {
await run();
expect(fakeRestoreTool).toHaveBeenCalled();
});
});
3 changes: 2 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ inputs:
description: 'Any custom parameters to pass to the script. Multiple parameters are defined on separate lines.'
required: false
cake-version:
description: 'The version of Cake to install.'
description: 'The version of Cake to install. Either a specific version, "latest" (default) or "tool-manifest".'
default: 'latest'
required: false
cake-bootstrap:
description: 'Flag for if Cake modules should be installed/bootstrapped.'
Expand Down
Loading

0 comments on commit 1bc8c8b

Please sign in to comment.