Skip to content

Commit

Permalink
Added Cake Frosting switch
Browse files Browse the repository at this point in the history
  • Loading branch information
louisfischer authored and ecampidoglio committed Sep 30, 2024
1 parent ce69ea7 commit 8c83e3a
Show file tree
Hide file tree
Showing 9 changed files with 182 additions and 15 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,9 @@ typings/

# Secret files
.secrets

# bin folder
bin/

# obj folder
obj/
30 changes: 25 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![GitHub Marketplace](https://img.shields.io/github/v/release/cake-build/cake-action?label=Marketplace&sort=semver)](https://github.com/marketplace/actions/cake-action) [![GitHub Actions Build](https://github.com/cake-build/cake-action/workflows/Build/badge.svg)](https://github.com/cake-build/cake-action/actions?workflow=Build) [![GitHub Actions Tests](https://github.com/cake-build/cake-action/workflows/Tests/badge.svg)](https://github.com/cake-build/cake-action/actions?workflow=Tests) [![Coveralls](https://coveralls.io/repos/github/cake-build/cake-action/badge.svg?branch=master)](https://coveralls.io/github/cake-build/cake-action?branch=master)

This action allows you to run a Cake script from your GitHub Actions workflow without having to use a [bootstrapper](https://github.com/cake-build/resources).
This action allows you to run a Cake script or Cake Frosting project from your GitHub Actions workflow without having to use a [bootstrapper](https://github.com/cake-build/resources).

## Usage

Expand All @@ -14,7 +14,9 @@ steps:
uses: cake-build/cake-action@v2
```
The Cake action will look for a script named `build.cake` in your repository's root directory and run it for you using the [Cake Tool](https://www.nuget.org/packages/Cake.Tool/). All output from the Cake script will be automatically redirected to the build log for inspection.
The Cake action will look for a script named `build.cake` in your repository's root directory and run it for you using the [Cake Tool](https://www.nuget.org/packages/Cake.Tool/). If you are using a [Cake Frosting](https://cakebuild.net/docs/running-builds/runners/cake-frosting) project, the `csproj-path` parameter must be specified and the `script-path` is ignored.

All output from the Cake script or Cake Frosting project will be automatically redirected to the build log for inspection.

## Inputs

Expand All @@ -30,9 +32,21 @@ steps:
script-path: path/to/script.cake
```

### `csproj-path`

If you are using [Cake Frosting](https://cakebuild.net/docs/running-builds/runners/cake-frosting), you can specify the path with the `csproj-path` [input parameter](https://help.github.com/en/github/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#jobsjob_idstepswith):

```yml
steps:
- name: Run Cake Frosting
uses: cake-build/cake-action@v2
with:
csproj-path: ./path/to/build.csproj
```

### `target`

You'll likely want to specify which task to run out of the ones defined in the Cake script. For that, you can use the `target` parameter:
You'll likely want to specify which task to run out of the ones defined in the Cake script or Cake Frosting project. For that, you can use the `target` parameter:

```yml
steps:
Expand Down Expand Up @@ -88,7 +102,11 @@ The arguments are defined in a [multi-line string literal](https://yaml.org/spec

### `cake-version`

By default, the Cake action will run your script using the latest _stable_ version of the [Cake .NET Core Global tool](https://www.nuget.org/packages/Cake.Tool/). However, if for some reason you want to [use a specific version of Cake](https://cakebuild.net/docs/tutorials/pinning-cake-version) (for compatibility with older third-party addins, for example), you can do so by specifying the version number in the `cake-version` parameter:
By default, the Cake action will run your script using the latest _stable_ version of the [Cake .NET Core Global tool](https://www.nuget.org/packages/Cake.Tool/).

_Ignored_ for Cake Frosting Project.

If for some reason you want to [use a specific version of Cake](https://cakebuild.net/docs/tutorials/pinning-cake-version) (for compatibility with older third-party addins, for example), you can do so by specifying the version number in the `cake-version` parameter.:

```yml
steps:
Expand All @@ -112,6 +130,8 @@ steps:

As of [Cake 1.0.0](https://github.com/cake-build/cake/releases/tag/v1.0.0), any [custom modules](https://cakebuild.net/docs/fundamentals/modules) that you reference in your script are [bootstrapped automatically](https://github.com/cake-build/cake/issues/2833) upon running it.

_Ignored_ for Cake Frosting Project.

If you're using an older version of Cake, however, you need to explicitly [bootstrap](https://cakebuild.net/docs/fundamentals/preprocessor-directives#module-directive) them before running the script. The Cake action can take care of this extra step for you by setting the `cake-bootstrap` parameter to `explicit`:

```yml
Expand All @@ -137,7 +157,7 @@ The default value is `auto`, which means that the modules will be automatically

## Cross-platform

Since the [Cake Tool](https://www.nuget.org/packages/Cake.Tool/) is built on .NET Core, the Cake action will run on any of the [virtual environments](https://help.github.com/en/github/automating-your-workflow-with-github-actions/software-in-virtual-environments-for-github-actions) supported by GitHub Actions, namely Linux, Windows and macOS.
Since the [Cake Tool](https://www.nuget.org/packages/Cake.Tool/) and [Cake Frosting](https://www.nuget.org/packages/Cake.Frosting) are built on .NET Core, the Cake action will run on any of the [virtual environments](https://help.github.com/en/github/automating-your-workflow-with-github-actions/software-in-virtual-environments-for-github-actions) supported by GitHub Actions, namely Linux, Windows and macOS.

This allows you to define your build step exactly _once_ and run it on multiple operating systems _in parallel_ by defining a [build matrix](https://help.github.com/en/github/automating-your-workflow-with-github-actions/configuring-a-workflow#configuring-a-build-matrix):

Expand Down
59 changes: 59 additions & 0 deletions __tests__/cake.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import { CakeArgument, CakeSwitch } from '../src/cakeParameter';

const pathToLocalToolsDirectory = path.join('path', 'to', 'tool');
const pathToLocalTool = path.join(pathToLocalToolsDirectory, 'dotnet-cake');
const pathToCsprojFile = path.join('build', 'Build.csproj');
const dotnetManifestCake = 'dotnet tool run dotnet-cake';
const dotnetRun = 'dotnet run';

jest.mock('@actions/exec');
jest.mock('@actions/io');
Expand Down Expand Up @@ -190,3 +192,60 @@ describe('When running a script successfully using the tool manifest', () => {
['script.cake', '--switch']);
});
});

describe('When running a Cake Frosting project successfully', () => {
const fakeExec = exec as jest.MockedFunction<typeof exec>;
const fakeToolsDirectory = new ToolsDirectory();

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

test('it should run with the default non-required parameters', async () => {
await cake.runProject(pathToCsprojFile, fakeToolsDirectory);

expect(fakeExec).toHaveBeenCalledWith(
dotnetRun,
[
'--project', pathToCsprojFile,
'--no-launch-profile',
'--verbosity', 'minimal',
'--configuration', 'Release',
'--',
`--paths_tools="${fakeToolsDirectory.path}"`
]);
});

test('it should run with the specified parameters', async () => {
await cake.runProject(
pathToCsprojFile,
fakeToolsDirectory,
new CakeArgument('param', 'arg'),
new CakeSwitch('switch'));

expect(fakeExec).toHaveBeenCalledWith(
dotnetRun,
[
'--project', pathToCsprojFile,
'--no-launch-profile',
'--verbosity', 'minimal',
'--configuration', 'Release',
'--',
`--paths_tools="${fakeToolsDirectory.path}"`,
'--param=arg',
'--switch'
]);
});
});

describe('When failing to run a Cake Frosting Project', () => {
const fakeExec = exec as jest.MockedFunction<typeof exec>;

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

test('it should throw an error containing the exit code', async () => {
await expect(cake.runProject('', new ToolsDirectory())).rejects.toThrow('-21');
});
});
22 changes: 22 additions & 0 deletions __tests__/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,28 @@ describe('When running the action with the script path input argument', () => {
});
});

describe('When running the action with the csproj path input argument', () => {
const fakeGetInputs = action.getInputs as jest.MockedFunction<typeof action.getInputs>;
const fakeRunProject = cake.runProject as jest.MockedFunction<typeof cake.runProject>;

beforeAll(() => {
fakeGetInputs.mockReturnValue({
csprojPath: './path/to/build.csproj',
scriptArguments: []
});
});

test('it should run the Cake Frosting Project', async () => {
await run();
expect(cake.runProject).toHaveBeenCalled();
});

test('it should run the specified Cake Frosting project', async () => {
await run();
expect(fakeRunProject.mock.calls[0][0]).toBe('./path/to/build.csproj');
});
});

describe('When running the action with tool-manifest as the Cake version input argument', () => {
const fakeGetInputs = action.getInputs as jest.MockedFunction<typeof action.getInputs>;
const fakeInstallCakeTool = cakeTool.install as jest.MockedFunction<typeof cakeTool.install>;
Expand Down
5 changes: 4 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: 'Cake Action'
description: 'Run a Cake script as part of your build.'
description: 'Run a Cake script or Cake Frosting project as part of your build.'
author: 'Enrico Campidoglio'
branding:
icon: 'box'
Expand All @@ -9,6 +9,9 @@ inputs:
description: 'The path of the Cake script to run.'
required: false
default: 'build.cake'
csproj-path:
description: 'The path of the Cake Frosting Project to run. Takes precedence over script-path'
required: false
target:
description: 'The name of the task to execute. Note that this argument must be supported by the script.'
required: false
Expand Down
36 changes: 31 additions & 5 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3991,6 +3991,7 @@ const input = __importStar(__nccwpck_require__(6747));
function getInputs() {
return {
scriptPath: core.getInput('script-path'),
csprojPath: core.getInput('csproj-path'),
cakeVersion: getCakeVersionInput(),
cakeBootstrap: getCakeBootstrapInput(),
scriptArguments: getScriptInputs()
Expand Down Expand Up @@ -4070,11 +4071,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
});
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.bootstrapScript = exports.runScript = void 0;
exports.bootstrapScript = exports.runProject = exports.runScript = void 0;
const exec_1 = __nccwpck_require__(1514);
const io_1 = __nccwpck_require__(7436);
const dotnetCake = 'dotnet-cake';
const dotnetLocalToolCake = 'dotnet tool run dotnet-cake';
const dotnetRun = 'dotnet run';
function runScript(scriptPath = 'build.cake', cakeToolSettings, ...params) {
return __awaiter(this, void 0, void 0, function* () {
const cakeToolPath = yield resolveCakeToolPath(cakeToolSettings);
Expand All @@ -4086,6 +4088,24 @@ function runScript(scriptPath = 'build.cake', cakeToolSettings, ...params) {
});
}
exports.runScript = runScript;
function runProject(csprojPath, toolsDir, ...params) {
return __awaiter(this, void 0, void 0, function* () {
const cakeParams = formatParameters(params);
const exitCode = yield (0, exec_1.exec)(dotnetRun, [
'--project', csprojPath,
'--no-launch-profile',
'--verbosity', 'minimal',
'--configuration', 'Release',
'--',
`--paths_tools="${toolsDir}"`,
...cakeParams
]);
if (exitCode != 0) {
throw new Error(`Failed to run the csproj. Exit code: ${exitCode}`);
}
});
}
exports.runProject = runProject;
function bootstrapScript(scriptPath = 'build.cake', cakeToolSettings) {
return __awaiter(this, void 0, void 0, function* () {
const cakeToolPath = yield resolveCakeToolPath(cakeToolSettings);
Expand Down Expand Up @@ -4515,18 +4535,24 @@ function run() {
try {
const inputs = action.getInputs();
const scriptPath = inputs.scriptPath;
const csprojPath = inputs.csprojPath;
const version = inputs.cakeVersion;
const bootstrap = inputs.cakeBootstrap;
const toolsDir = new toolsDirectory_1.ToolsDirectory();
toolsDir.create();
const cakeToolSettings = new cakeToolSettings_1.CakeToolSettings(toolsDir, (version === null || version === void 0 ? void 0 : version.version) === 'tool-manifest');
dotnet.disableTelemetry();
dotnet.disableWelcomeMessage();
yield cakeTool.install(toolsDir, version);
if (bootstrap === 'explicit') {
yield cake.bootstrapScript(scriptPath, cakeToolSettings);
if (csprojPath) {
yield cake.runProject(csprojPath, toolsDir, ...inputs.scriptArguments);
}
else {
yield cakeTool.install(toolsDir, version);
if (bootstrap === 'explicit') {
yield cake.bootstrapScript(scriptPath, cakeToolSettings);
}
yield cake.runScript(scriptPath, cakeToolSettings, ...inputs.scriptArguments);
}
yield cake.runScript(scriptPath, cakeToolSettings, ...inputs.scriptArguments);
}
catch (error) {
if ((0, guards_1.isError)(error)) {
Expand Down
2 changes: 2 additions & 0 deletions src/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as input from './input';

interface CakeInputs {
readonly scriptPath?: string,
readonly csprojPath?: string,
readonly cakeVersion?: CakeVersion,
readonly cakeBootstrap?: CakeBootstrap;
}
Expand Down Expand Up @@ -35,6 +36,7 @@ export type CakeBootstrap =
export function getInputs(): CakeInputs & ScriptInputs {
return {
scriptPath: core.getInput('script-path'),
csprojPath: core.getInput('csproj-path'),
cakeVersion: getCakeVersionInput(),
cakeBootstrap: getCakeBootstrapInput(),
scriptArguments: getScriptInputs()
Expand Down
23 changes: 23 additions & 0 deletions src/cake.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { exec } from '@actions/exec';
import { which } from '@actions/io';
import { CakeToolSettings } from './cakeToolSettings';
import { CakeParameter } from './cakeParameter';
import { ToolsDirectory } from './toolsDirectory';

const dotnetCake = 'dotnet-cake';
const dotnetLocalToolCake = 'dotnet tool run dotnet-cake';
const dotnetRun = 'dotnet run';

export async function runScript(
scriptPath = 'build.cake',
Expand All @@ -20,6 +22,27 @@ export async function runScript(
}
}

export async function runProject(
csprojPath: string,
toolsDir: ToolsDirectory,
...params: CakeParameter[]
) {
const cakeParams = formatParameters(params);
const exitCode = await exec(dotnetRun, [
'--project', csprojPath,
'--no-launch-profile',
'--verbosity', 'minimal',
'--configuration', 'Release',
'--',
`--paths_tools="${toolsDir}"`,
...cakeParams
]);

if (exitCode != 0) {
throw new Error(`Failed to run the csproj. Exit code: ${exitCode}`);
}
}

export async function bootstrapScript(
scriptPath = 'build.cake',
cakeToolSettings?: CakeToolSettings
Expand Down
14 changes: 10 additions & 4 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export async function run() {
try {
const inputs = action.getInputs();
const scriptPath = inputs.scriptPath;
const csprojPath = inputs.csprojPath;
const version = inputs.cakeVersion;
const bootstrap = inputs.cakeBootstrap;

Expand All @@ -22,13 +23,18 @@ export async function run() {
dotnet.disableTelemetry();
dotnet.disableWelcomeMessage();

await cakeTool.install(toolsDir, version);
if (csprojPath) {
await cake.runProject(csprojPath, toolsDir, ...inputs.scriptArguments);
} else {
await cakeTool.install(toolsDir, version);

if (bootstrap === 'explicit') {
await cake.bootstrapScript(scriptPath, cakeToolSettings);
if (bootstrap === 'explicit') {
await cake.bootstrapScript(scriptPath, cakeToolSettings);
}

await cake.runScript(scriptPath, cakeToolSettings, ...inputs.scriptArguments);
}

await cake.runScript(scriptPath, cakeToolSettings, ...inputs.scriptArguments);
} catch (error) {
if (isError(error)) {
core.setFailed(error.message);
Expand Down

0 comments on commit 8c83e3a

Please sign in to comment.