Skip to content

Commit

Permalink
Parse boolean inputs in main.ts
Browse files Browse the repository at this point in the history
  • Loading branch information
brandonchinn178 committed Jul 13, 2023
1 parent 7bee105 commit 0bcb5a2
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 143 deletions.
14 changes: 6 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,19 +189,17 @@ jobs:
| `ghc-version` | GHC version to use, e.g. `9.2` or `9.2.5`. | `string` | `latest` |
| `cabal-version` | Cabal version to use, e.g. `3.6`. | `string` | `latest` |
| `stack-version` | Stack version to use, e.g. `latest`. Stack will only be installed if `enable-stack` is set. | `string` | `latest` |
| `enable-stack` | If set, will setup Stack. | "boolean" | false/unset |
| `stack-no-global` | If set, `enable-stack` must be set. Prevents installing GHC and Cabal globally. | "boolean" | false/unset |
| `stack-setup-ghc` | If set, `enable-stack` must be set. Runs stack setup to install the specified GHC. (Note: setting this does _not_ imply `stack-no-global`.) | "boolean" | false/unset |
| `disable-matcher` | If set, disables match messages from GHC as GitHub CI annotations. | "boolean" | false/unset |
| `enable-stack` | If set, will setup Stack. | `Toggle` | false/unset |
| `stack-no-global` | If set, `enable-stack` must be set. Prevents installing GHC and Cabal globally. | `Toggle` | false/unset |
| `stack-setup-ghc` | If set, `enable-stack` must be set. Runs stack setup to install the specified GHC. (Note: setting this does _not_ imply `stack-no-global`.) | `Toggle` | false/unset |
| `disable-matcher` | If set, disables match messages from GHC as GitHub CI annotations. | `Toggle` | false/unset |
| `cabal-update` | If set to `false`, skip `cabal update` step. | `boolean` | `true` |
| `ghcup-release-channels` | If set, add [release channels](https://www.haskell.org/ghcup/guide/#pre-release-channels) to ghcup. | `URL[]` | none |

Notes:

- "boolean" types are set/unset, not true/false. That is, setting any "boolean" to a value other than the empty string (`""`) will be considered true/set.
However, to avoid confusion and for forward compatibility, it is still recommended to **only use value `true` to set a "boolean" flag.**

In contrast, a proper `boolean` input like `cabal-update` only accepts values `true` and `false`.
- `Toggle` inputs are booleans that are false when set as the empty string and true when set to _anything_.
However, to avoid confusion and for forward compatibility, it is still recommended to **only use value `true` to set a `Toggle` input.**

- Inputs that can take multiple values (like `ghcup-release-channels`) should be specified as a comma separated list, e.g.

Expand Down
18 changes: 9 additions & 9 deletions __tests__/find-haskell.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe('haskell/actions/setup', () => {
it('Setting disable-matcher to true disables matcher', () => {
forAllOS(os => {
const options = getOpts(def(os), os, {
disableMatcher: 'true'
disableMatcher: true
});
expect(options.general.matcher.enable).toBe(false);
});
Expand All @@ -70,7 +70,7 @@ describe('haskell/actions/setup', () => {
const v = {ghc: '8.6.5', cabal: '3.4.1.0', stack: '1.9.3'};
forAllOS(os => {
const options = getOpts(def(os), os, {
enableStack: 'true',
enableStack: true,
stackVersion: '1',
ghcVersion: '8.6',
cabalVersion: '3.4'
Expand All @@ -82,7 +82,7 @@ describe('haskell/actions/setup', () => {
it('"latest" Versions resolve correctly', () => {
forAllOS(os => {
const options = getOpts(def(os), os, {
enableStack: 'true',
enableStack: true,
stackVersion: 'latest',
ghcVersion: 'latest',
cabalVersion: 'latest'
Expand All @@ -100,7 +100,7 @@ describe('haskell/actions/setup', () => {
const v = {ghc: '8.10.7', cabal: '2.4.1.0', stack: '2.1.3'};
forAllOS(os => {
const options = getOpts(def(os), os, {
enableStack: 'true',
enableStack: true,
stackVersion: '2.1',
ghcVersion: '8.10',
cabalVersion: '2'
Expand All @@ -112,7 +112,7 @@ describe('haskell/actions/setup', () => {
it('Enabling stack does not disable GHC or Cabal', () => {
forAllOS(os => {
const {ghc, cabal, stack} = getOpts(def(os), os, {
enableStack: 'true'
enableStack: true
});
expect({
ghc: ghc.enable,
Expand All @@ -137,8 +137,8 @@ describe('haskell/actions/setup', () => {
it('Enabling stack-no-global disables GHC and Cabal', () => {
forAllOS(os => {
const {ghc, cabal, stack} = getOpts(def(os), os, {
enableStack: 'true',
stackNoGlobal: 'true'
enableStack: true,
stackNoGlobal: true
});
expect({
ghc: ghc.enable,
Expand All @@ -150,13 +150,13 @@ describe('haskell/actions/setup', () => {

it('Enabling stack-no-global without setting enable-stack errors', () => {
forAllOS(os =>
expect(() => getOpts(def(os), os, {stackNoGlobal: 'true'})).toThrow()
expect(() => getOpts(def(os), os, {stackNoGlobal: true})).toThrow()
);
});

it('Enabling stack-setup-ghc without setting enable-stack errors', () => {
forAllOS(os =>
expect(() => getOpts(def(os), os, {stackNoGlobal: 'true'})).toThrow()
expect(() => getOpts(def(os), os, {stackNoGlobal: true})).toThrow()
);
});
});
48 changes: 12 additions & 36 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13630,17 +13630,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
Object.defineProperty(exports, "__esModule", ({ value: true }));
const core = __importStar(__nccwpck_require__(2186));
const setup_haskell_1 = __importDefault(__nccwpck_require__(9351));
const getToggleInput = (name) => core.getInput(name) !== '';
(0, setup_haskell_1.default)({
ghcVersion: core.getInput('ghc-version'),
cabalVersion: core.getInput('cabal-version'),
stackVersion: core.getInput('stack-version'),
enableStack: core.getInput('enable-stack'),
stackNoGlobal: core.getInput('stack-no-global'),
stackSetupGhc: core.getInput('stack-setup-ghc'),
cabalUpdate: core.getInput('cabal-update'),
enableStack: getToggleInput('enable-stack'),
stackNoGlobal: getToggleInput('stack-no-global'),
stackSetupGhc: getToggleInput('stack-setup-ghc'),
cabalUpdate: core.getBooleanInput('cabal-update'),
ghcupReleaseChannels: core.getInput('ghcup-release-channels'),
ghcupReleaseChannel: core.getInput('ghcup-release-channel'),
disableMatcher: core.getInput('disable-matcher')
disableMatcher: getToggleInput('disable-matcher')
});


Expand Down Expand Up @@ -13675,7 +13676,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result;
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getOpts = exports.parseYAMLBoolean = exports.releaseRevision = exports.getDefaults = exports.yamlInputs = exports.ghcup_version = exports.supported_versions = exports.release_revisions = void 0;
exports.getOpts = exports.releaseRevision = exports.getDefaults = exports.yamlInputs = exports.ghcup_version = exports.supported_versions = exports.release_revisions = void 0;
const core = __importStar(__nccwpck_require__(2186));
const fs_1 = __nccwpck_require__(7147);
const js_yaml_1 = __nccwpck_require__(1917);
Expand Down Expand Up @@ -13754,27 +13755,6 @@ function releaseRevision(version, tool, os) {
return result;
}
exports.releaseRevision = releaseRevision;
/**
* Convert a string input to a boolean according to the YAML 1.2 "core schema" specification.
* Supported boolean renderings: `true | True | TRUE | false | False | FALSE` .
* ref: https://yaml.org/spec/1.2/spec.html#id2804923
* Adapted from: https://github.com/actions/toolkit/commit/fbdf27470cdcb52f16755d32082f1fee0bfb7d6d#diff-f63fb32fca85d8e177d6400ce078818a4815b80ac7a3319b60d3507354890992R94-R115
*
* @param name name of the input
* @param val supposed string representation of a boolean
* @returns boolean
*/
function parseYAMLBoolean(name, val) {
const trueValue = ['true', 'True', 'TRUE'];
const falseValue = ['false', 'False', 'FALSE'];
if (trueValue.includes(val))
return true;
if (falseValue.includes(val))
return false;
throw new TypeError(`Action input "${name}" does not meet YAML 1.2 "Core Schema" specification: \n` +
`Supported boolean values: \`true | True | TRUE | false | False | FALSE\``);
}
exports.parseYAMLBoolean = parseYAMLBoolean;
/**
* Parse a string as a comma-separated list.
*/
Expand All @@ -13786,10 +13766,11 @@ function parseCSV(val) {
}
function getOpts({ ghc, cabal, stack }, os, inputs) {
core.debug(`Inputs are: ${JSON.stringify(inputs)}`);
const stackNoGlobal = (inputs.stackNoGlobal ?? '') !== '';
const stackSetupGhc = (inputs.stackSetupGhc ?? '') !== '';
const stackEnable = (inputs.enableStack ?? '') !== '';
const matcherDisable = (inputs.disableMatcher ?? '') !== '';
const stackNoGlobal = inputs.stackNoGlobal ?? false;
const stackSetupGhc = inputs.stackSetupGhc ?? false;
const stackEnable = inputs.enableStack ?? false;
const cabalUpdate = inputs.cabalUpdate ?? true;
const matcherDisable = inputs.disableMatcher ?? false;
if (inputs.ghcupReleaseChannel) {
core.warning('ghcup-release-channel is deprecated in favor of ghcup-release-channels');
inputs.ghcupReleaseChannels = inputs.ghcupReleaseChannel;
Expand All @@ -13802,11 +13783,6 @@ function getOpts({ ghc, cabal, stack }, os, inputs) {
throw new TypeError(`Not a valid URL: ${v}`);
}
});
// Andreas, 2023-01-05, issue #29:
// 'cabal-update' has a default value, so we should get a proper boolean always.
// Andreas, 2023-01-06: This is not true if we use the action as a library.
// Thus, need to patch with default value here.
const cabalUpdate = parseYAMLBoolean('cabal-update', inputs.cabalUpdate ?? 'true');
core.debug(`${stackNoGlobal}/${stackSetupGhc}/${stackEnable}`);
const verInpt = {
ghc: inputs.ghcVersion || ghc.version,
Expand Down
21 changes: 5 additions & 16 deletions lib/opts.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,28 +74,17 @@ export declare const yamlInputs: Record<string, {
}>;
export declare function getDefaults(os: OS): Defaults;
export declare function releaseRevision(version: string, tool: Tool, os: OS): string;
/**
* Convert a string input to a boolean according to the YAML 1.2 "core schema" specification.
* Supported boolean renderings: `true | True | TRUE | false | False | FALSE` .
* ref: https://yaml.org/spec/1.2/spec.html#id2804923
* Adapted from: https://github.com/actions/toolkit/commit/fbdf27470cdcb52f16755d32082f1fee0bfb7d6d#diff-f63fb32fca85d8e177d6400ce078818a4815b80ac7a3319b60d3507354890992R94-R115
*
* @param name name of the input
* @param val supposed string representation of a boolean
* @returns boolean
*/
export declare function parseYAMLBoolean(name: string, val: string): boolean;
export type RawInputs = {
ghcVersion?: string;
cabalVersion?: string;
stackVersion?: string;
enableStack?: string;
stackNoGlobal?: string;
stackSetupGhc?: string;
cabalUpdate?: string;
enableStack?: boolean;
stackNoGlobal?: boolean;
stackSetupGhc?: boolean;
cabalUpdate?: boolean;
ghcupReleaseChannels?: string;
ghcupReleaseChannel?: string;
disableMatcher?: string;
disableMatcher?: boolean;
};
export declare function getOpts({ ghc, cabal, stack }: Defaults, os: OS, inputs: RawInputs): Options;
export {};
37 changes: 6 additions & 31 deletions lib/opts.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getOpts = exports.parseYAMLBoolean = exports.releaseRevision = exports.getDefaults = exports.yamlInputs = exports.ghcup_version = exports.supported_versions = exports.release_revisions = void 0;
exports.getOpts = exports.releaseRevision = exports.getDefaults = exports.yamlInputs = exports.ghcup_version = exports.supported_versions = exports.release_revisions = void 0;
const core = __importStar(require("@actions/core"));
const fs_1 = require("fs");
const js_yaml_1 = require("js-yaml");
Expand Down Expand Up @@ -102,27 +102,6 @@ function releaseRevision(version, tool, os) {
return result;
}
exports.releaseRevision = releaseRevision;
/**
* Convert a string input to a boolean according to the YAML 1.2 "core schema" specification.
* Supported boolean renderings: `true | True | TRUE | false | False | FALSE` .
* ref: https://yaml.org/spec/1.2/spec.html#id2804923
* Adapted from: https://github.com/actions/toolkit/commit/fbdf27470cdcb52f16755d32082f1fee0bfb7d6d#diff-f63fb32fca85d8e177d6400ce078818a4815b80ac7a3319b60d3507354890992R94-R115
*
* @param name name of the input
* @param val supposed string representation of a boolean
* @returns boolean
*/
function parseYAMLBoolean(name, val) {
const trueValue = ['true', 'True', 'TRUE'];
const falseValue = ['false', 'False', 'FALSE'];
if (trueValue.includes(val))
return true;
if (falseValue.includes(val))
return false;
throw new TypeError(`Action input "${name}" does not meet YAML 1.2 "Core Schema" specification: \n` +
`Supported boolean values: \`true | True | TRUE | false | False | FALSE\``);
}
exports.parseYAMLBoolean = parseYAMLBoolean;
/**
* Parse a string as a comma-separated list.
*/
Expand All @@ -134,10 +113,11 @@ function parseCSV(val) {
}
function getOpts({ ghc, cabal, stack }, os, inputs) {
core.debug(`Inputs are: ${JSON.stringify(inputs)}`);
const stackNoGlobal = (inputs.stackNoGlobal ?? '') !== '';
const stackSetupGhc = (inputs.stackSetupGhc ?? '') !== '';
const stackEnable = (inputs.enableStack ?? '') !== '';
const matcherDisable = (inputs.disableMatcher ?? '') !== '';
const stackNoGlobal = inputs.stackNoGlobal ?? false;
const stackSetupGhc = inputs.stackSetupGhc ?? false;
const stackEnable = inputs.enableStack ?? false;
const cabalUpdate = inputs.cabalUpdate ?? true;
const matcherDisable = inputs.disableMatcher ?? false;
if (inputs.ghcupReleaseChannel) {
core.warning('ghcup-release-channel is deprecated in favor of ghcup-release-channels');
inputs.ghcupReleaseChannels = inputs.ghcupReleaseChannel;
Expand All @@ -150,11 +130,6 @@ function getOpts({ ghc, cabal, stack }, os, inputs) {
throw new TypeError(`Not a valid URL: ${v}`);
}
});
// Andreas, 2023-01-05, issue #29:
// 'cabal-update' has a default value, so we should get a proper boolean always.
// Andreas, 2023-01-06: This is not true if we use the action as a library.
// Thus, need to patch with default value here.
const cabalUpdate = parseYAMLBoolean('cabal-update', inputs.cabalUpdate ?? 'true');
core.debug(`${stackNoGlobal}/${stackSetupGhc}/${stackEnable}`);
const verInpt = {
ghc: inputs.ghcVersion || ghc.version,
Expand Down
12 changes: 7 additions & 5 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import * as core from '@actions/core';
import run from './setup-haskell';

const getToggleInput = (name: string) => core.getInput(name) !== '';

run({
ghcVersion: core.getInput('ghc-version'),
cabalVersion: core.getInput('cabal-version'),
stackVersion: core.getInput('stack-version'),
enableStack: core.getInput('enable-stack'),
stackNoGlobal: core.getInput('stack-no-global'),
stackSetupGhc: core.getInput('stack-setup-ghc'),
cabalUpdate: core.getInput('cabal-update'),
enableStack: getToggleInput('enable-stack'),
stackNoGlobal: getToggleInput('stack-no-global'),
stackSetupGhc: getToggleInput('stack-setup-ghc'),
cabalUpdate: core.getBooleanInput('cabal-update'),
ghcupReleaseChannels: core.getInput('ghcup-release-channels'),
ghcupReleaseChannel: core.getInput('ghcup-release-channel'),
disableMatcher: core.getInput('disable-matcher')
disableMatcher: getToggleInput('disable-matcher')
});
49 changes: 11 additions & 38 deletions src/opts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,27 +117,6 @@ export function releaseRevision(version: string, tool: Tool, os: OS): string {
return result;
}

/**
* Convert a string input to a boolean according to the YAML 1.2 "core schema" specification.
* Supported boolean renderings: `true | True | TRUE | false | False | FALSE` .
* ref: https://yaml.org/spec/1.2/spec.html#id2804923
* Adapted from: https://github.com/actions/toolkit/commit/fbdf27470cdcb52f16755d32082f1fee0bfb7d6d#diff-f63fb32fca85d8e177d6400ce078818a4815b80ac7a3319b60d3507354890992R94-R115
*
* @param name name of the input
* @param val supposed string representation of a boolean
* @returns boolean
*/
export function parseYAMLBoolean(name: string, val: string): boolean {
const trueValue = ['true', 'True', 'TRUE'];
const falseValue = ['false', 'False', 'FALSE'];
if (trueValue.includes(val)) return true;
if (falseValue.includes(val)) return false;
throw new TypeError(
`Action input "${name}" does not meet YAML 1.2 "Core Schema" specification: \n` +
`Supported boolean values: \`true | True | TRUE | false | False | FALSE\``
);
}

/**
* Parse a string as a comma-separated list.
*/
Expand All @@ -152,13 +131,13 @@ export type RawInputs = {
ghcVersion?: string;
cabalVersion?: string;
stackVersion?: string;
enableStack?: string;
stackNoGlobal?: string;
stackSetupGhc?: string;
cabalUpdate?: string;
enableStack?: boolean;
stackNoGlobal?: boolean;
stackSetupGhc?: boolean;
cabalUpdate?: boolean;
ghcupReleaseChannels?: string;
ghcupReleaseChannel?: string;
disableMatcher?: string;
disableMatcher?: boolean;
};

export function getOpts(
Expand All @@ -167,10 +146,12 @@ export function getOpts(
inputs: RawInputs
): Options {
core.debug(`Inputs are: ${JSON.stringify(inputs)}`);
const stackNoGlobal = (inputs.stackNoGlobal ?? '') !== '';
const stackSetupGhc = (inputs.stackSetupGhc ?? '') !== '';
const stackEnable = (inputs.enableStack ?? '') !== '';
const matcherDisable = (inputs.disableMatcher ?? '') !== '';

const stackNoGlobal = inputs.stackNoGlobal ?? false;
const stackSetupGhc = inputs.stackSetupGhc ?? false;
const stackEnable = inputs.enableStack ?? false;
const cabalUpdate = inputs.cabalUpdate ?? true;
const matcherDisable = inputs.disableMatcher ?? false;

if (inputs.ghcupReleaseChannel) {
core.warning(
Expand All @@ -189,14 +170,6 @@ export function getOpts(
}
);

// Andreas, 2023-01-05, issue #29:
// 'cabal-update' has a default value, so we should get a proper boolean always.
// Andreas, 2023-01-06: This is not true if we use the action as a library.
// Thus, need to patch with default value here.
const cabalUpdate = parseYAMLBoolean(
'cabal-update',
inputs.cabalUpdate ?? 'true'
);
core.debug(`${stackNoGlobal}/${stackSetupGhc}/${stackEnable}`);
const verInpt = {
ghc: inputs.ghcVersion || ghc.version,
Expand Down

0 comments on commit 0bcb5a2

Please sign in to comment.