Skip to content
This repository was archived by the owner on Jan 5, 2024. It is now read-only.

Commit fc78d67

Browse files
author
Jared Weakly
committed
Handle chocolatey on windows better
1 parent 2e698e5 commit fc78d67

File tree

3 files changed

+90
-80
lines changed

3 files changed

+90
-80
lines changed

setup/.lintstagedrc.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
module.exports = {
2-
'!(*test).{js,ts}': [
2+
'setup/!(*test).{js,ts,json}': [
33
'eslint --cache --fix',
44
() => 'ncc build',
55
() => 'git add dist'
66
],
7-
'src/**/*.ts': () => 'tsc -p tsconfig.json',
8-
'*.{js,ts,json,md}': 'prettier --write'
7+
'setup/src/**/*.ts': () => 'tsc -p tsconfig.json',
8+
'setup/*.{js,ts,json,md}': 'prettier --write'
99
};

setup/dist/index.js

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4320,7 +4320,7 @@ function escapeProperty(s) {
43204320
/***/ 447:
43214321
/***/ (function(module) {
43224322

4323-
module.exports = {"ghc":["8.10.2","8.10.1","8.8.4","8.8.3","8.8.2","8.8.1","8.6.5","8.6.4","8.6.3","8.6.2","8.6.1","8.4.4","8.4.3","8.4.2","8.4.1","8.2.2","8.0.2","7.10.3"],"cabal":["3.2.0.0","3.0.0.0","2.4.1.0","2.4.0.0","2.2.0.0"],"stack":["2.3.1","2.1.3","2.1.1","1.9.3","1.9.1","1.7.1","1.6.5","1.6.3","1.6.1","1.5.1","1.5.0","1.4.0","1.3.2","1.3.0","1.2.0"]};
4323+
module.exports = {"ghc":["8.10.2","8.10.1","8.8.4","8.8.3","8.8.2","8.8.1","8.6.5","8.6.4","8.6.3","8.6.2","8.6.1","8.4.4","8.4.3","8.4.2","8.4.1","8.2.2","8.0.2","7.10.3"],"cabal":["3.2.0.0","3.0.0.0","2.4.1.0","2.4.0.0","2.2.0.0"],"stack":["2.5.1","2.3.3","2.3.1","2.1.3","2.1.1","1.9.3","1.9.1","1.7.1","1.6.5","1.6.3","1.6.1","1.5.1","1.5.0","1.4.0","1.3.2","1.3.0","1.2.0"]};
43244324

43254325
/***/ }),
43264326

@@ -11137,13 +11137,27 @@ const glob_1 = __webpack_require__(281);
1113711137
const tc = __importStar(__webpack_require__(533));
1113811138
const fs_1 = __webpack_require__(747);
1113911139
const path_1 = __webpack_require__(622);
11140+
// Don't throw on non-zero.
11141+
const exec = async (cmd, args) => exec_1.exec(cmd, args, { ignoreReturnCode: true });
1114011142
function failed(tool, version) {
1114111143
throw new Error(`All install methods for ${tool} ${version} failed`);
1114211144
}
11143-
async function success(tool, version, path) {
11144-
core.addPath(path);
11145+
async function configureOutputs(tool, path, os) {
1114511146
core.setOutput(`${tool}-path`, path);
1114611147
core.setOutput(`${tool}-exe`, await io_1.which(tool));
11148+
if (tool == 'stack') {
11149+
if (os === 'win32') {
11150+
core.exportVariable('STACK_ROOT', 'C:\\sr');
11151+
core.setOutput('stack-root', 'C:\\sr');
11152+
}
11153+
else {
11154+
core.setOutput('stack-root', `${process.env.HOME}/.stack`);
11155+
}
11156+
}
11157+
}
11158+
async function success(tool, version, path, os) {
11159+
core.addPath(path);
11160+
await configureOutputs(tool, path, os);
1114711161
core.info(`Found ${tool} ${version} in cache at path ${path}. Setup successful.`);
1114811162
return true;
1114911163
}
@@ -11163,7 +11177,7 @@ function warn(tool, version) {
1116311177
async function isInstalled(tool, version, os) {
1116411178
const toolPath = tc.find(tool, version);
1116511179
if (toolPath)
11166-
return success(tool, version, toolPath);
11180+
return success(tool, version, toolPath, os);
1116711181
const ghcupPath = `${process.env.HOME}/.ghcup${tool === 'ghc' ? `/ghc/${version}` : ''}/bin`;
1116811182
const v = tool === 'cabal' ? version.slice(0, 3) : version;
1116911183
const aptPath = `/opt/${tool}/${v}/bin`;
@@ -11190,17 +11204,19 @@ async function isInstalled(tool, version, os) {
1119011204
// Make sure that the correct ghc is used, even if ghcup has set a
1119111205
// default prior to this action being ran.
1119211206
if (tool === 'ghc' && installedPath === ghcupPath)
11193-
await exec_1.exec(await ghcupBin(os), ['set', version]);
11194-
return success(tool, version, installedPath);
11207+
await exec(await ghcupBin(os), ['set', tool, version]);
11208+
return success(tool, version, installedPath, os);
1119511209
}
1119611210
}
1119711211
if (tool === 'cabal' && os !== 'win32') {
1119811212
const installedPath = await fs_1.promises
1119911213
.access(`${ghcupPath}/cabal`)
1120011214
.then(() => ghcupPath)
1120111215
.catch(() => undefined);
11202-
if (installedPath)
11203-
return success(tool, version, installedPath);
11216+
if (installedPath) {
11217+
await exec(await ghcupBin(os), ['set', tool, version]);
11218+
return success(tool, version, installedPath, os);
11219+
}
1120411220
}
1120511221
return false;
1120611222
}
@@ -11246,23 +11262,19 @@ async function stack(version, os) {
1124611262
implicitDescendants: false
1124711263
}).then(async (g) => g.glob());
1124811264
await tc.cacheDir(stackPath, 'stack', version);
11249-
if (os === 'win32')
11250-
core.exportVariable('STACK_ROOT', 'C:\\sr');
1125111265
}
1125211266
async function apt(tool, version) {
1125311267
const toolName = tool === 'ghc' ? 'ghc' : 'cabal-install';
1125411268
const v = tool === 'cabal' ? version.slice(0, 3) : version;
1125511269
core.info(`Attempting to install ${toolName} ${v} using apt-get`);
1125611270
// Ignore the return code so we can fall back to ghcup
11257-
await exec_1.exec(`sudo -- sh -c "apt-get -y install ${toolName}-${v}"`, undefined, {
11258-
ignoreReturnCode: true
11259-
});
11271+
await exec(`sudo -- sh -c "apt-get -y install ${toolName}-${v}"`);
1126011272
}
1126111273
async function choco(tool, version) {
1126211274
core.info(`Attempting to install ${tool} ${version} using chocolatey`);
1126311275
// Choco tries to invoke `add-path` command on earlier versions of ghc, which has been deprecated and fails the step, so disable command execution during this.
1126411276
console.log('::stop-commands::SetupHaskellStopCommands');
11265-
await exec_1.exec('powershell', [
11277+
await exec('powershell', [
1126611278
'choco',
1126711279
'install',
1126811280
tool,
@@ -11271,14 +11283,11 @@ async function choco(tool, version) {
1127111283
'-m',
1127211284
'--no-progress',
1127311285
'-r'
11274-
], {
11275-
ignoreReturnCode: true
11276-
});
11286+
]);
1127711287
console.log('::SetupHaskellStopCommands::'); // Re-enable command execution
1127811288
// Add GHC to path automatically because it does not add until the end of the step and we check the path.
11279-
if (tool == 'ghc') {
11289+
if (tool == 'ghc')
1128011290
core.addPath(getChocoPath(tool, version));
11281-
}
1128211291
}
1128311292
async function ghcupBin(os) {
1128411293
const v = '0.1.12';
@@ -11292,19 +11301,16 @@ async function ghcupBin(os) {
1129211301
async function ghcup(tool, version, os) {
1129311302
core.info(`Attempting to install ${tool} ${version} using ghcup`);
1129411303
const bin = await ghcupBin(os);
11295-
const returnCode = await exec_1.exec(bin, [tool === 'ghc' ? 'install' : 'install-cabal', version], {
11296-
ignoreReturnCode: true
11297-
});
11298-
if (returnCode === 0 && tool === 'ghc')
11299-
await exec_1.exec(bin, ['set', version]);
11304+
const returnCode = await exec(bin, ['install', tool, version]);
11305+
if (returnCode === 0)
11306+
await exec(bin, ['set', tool, version]);
1130011307
}
1130111308
function getChocoPath(tool, version) {
11302-
// Manually add the path because it won't happen until the end of the step normally
11303-
const pathArray = version.split('.');
11304-
const pathVersion = pathArray.length > 3
11305-
? pathArray.slice(0, pathArray.length - 1).join('.')
11306-
: pathArray.join('.');
11307-
const chocoPath = path_1.join(`${process.env.ChocolateyInstall}`, 'lib', `${tool}.${version}`, 'tools', tool === 'ghc' ? `${tool}-${pathVersion}` : `${tool}-${version}`, // choco trims the ghc version here
11309+
// If chocolatey has a patch release for GHC, 'version' will be a.b.c.d
11310+
// but GHC's version is still a.b.c and the chocolatey path contains both
11311+
// (This is only valid for GHC. cabal-install has 4-segment versions)
11312+
const ghcVersion = version.split('.').slice(0, 3).join('.');
11313+
const chocoPath = path_1.join(`${process.env.ChocolateyInstall}`, 'lib', `${tool}.${version}`, 'tools', tool === 'ghc' ? `${tool}-${ghcVersion}` : `${tool}-${version}`, // choco trims the ghc version here
1130811314
tool === 'ghc' ? 'bin' : '');
1130911315
return chocoPath;
1131011316
}

setup/src/installer.ts

Lines changed: 51 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,45 @@
11
import * as core from '@actions/core';
2-
import {exec} from '@actions/exec';
2+
import {exec as e} from '@actions/exec';
33
import {which} from '@actions/io';
44
import {create as glob} from '@actions/glob';
55
import * as tc from '@actions/tool-cache';
66
import {promises as fs} from 'fs';
77
import {join} from 'path';
88
import type {OS, Tool} from './opts';
99

10+
// Don't throw on non-zero.
11+
const exec = async (cmd: string, args?: string[]): Promise<number> =>
12+
e(cmd, args, {ignoreReturnCode: true});
13+
1014
function failed(tool: Tool, version: string): void {
1115
throw new Error(`All install methods for ${tool} ${version} failed`);
1216
}
1317

18+
async function configureOutputs(
19+
tool: Tool,
20+
path: string,
21+
os: OS
22+
): Promise<void> {
23+
core.setOutput(`${tool}-path`, path);
24+
core.setOutput(`${tool}-exe`, await which(tool));
25+
if (tool == 'stack') {
26+
if (os === 'win32') {
27+
core.exportVariable('STACK_ROOT', 'C:\\sr');
28+
core.setOutput('stack-root', 'C:\\sr');
29+
} else {
30+
core.setOutput('stack-root', `${process.env.HOME}/.stack`);
31+
}
32+
}
33+
}
34+
1435
async function success(
1536
tool: Tool,
1637
version: string,
17-
path: string
38+
path: string,
39+
os: OS
1840
): Promise<true> {
1941
core.addPath(path);
20-
core.setOutput(`${tool}-path`, path);
21-
core.setOutput(`${tool}-exe`, await which(tool));
42+
await configureOutputs(tool, path, os);
2243
core.info(
2344
`Found ${tool} ${version} in cache at path ${path}. Setup successful.`
2445
);
@@ -48,7 +69,7 @@ async function isInstalled(
4869
os: OS
4970
): Promise<boolean> {
5071
const toolPath = tc.find(tool, version);
51-
if (toolPath) return success(tool, version, toolPath);
72+
if (toolPath) return success(tool, version, toolPath, os);
5273

5374
const ghcupPath = `${process.env.HOME}/.ghcup${
5475
tool === 'ghc' ? `/ghc/${version}` : ''
@@ -82,9 +103,9 @@ async function isInstalled(
82103
// Make sure that the correct ghc is used, even if ghcup has set a
83104
// default prior to this action being ran.
84105
if (tool === 'ghc' && installedPath === ghcupPath)
85-
await exec(await ghcupBin(os), ['set', version]);
106+
await exec(await ghcupBin(os), ['set', tool, version]);
86107

87-
return success(tool, version, installedPath);
108+
return success(tool, version, installedPath, os);
88109
}
89110
}
90111

@@ -94,7 +115,10 @@ async function isInstalled(
94115
.then(() => ghcupPath)
95116
.catch(() => undefined);
96117

97-
if (installedPath) return success(tool, version, installedPath);
118+
if (installedPath) {
119+
await exec(await ghcupBin(os), ['set', tool, version]);
120+
return success(tool, version, installedPath, os);
121+
}
98122
}
99123

100124
return false;
@@ -146,45 +170,33 @@ async function stack(version: string, os: OS): Promise<void> {
146170
implicitDescendants: false
147171
}).then(async g => g.glob());
148172
await tc.cacheDir(stackPath, 'stack', version);
149-
150-
if (os === 'win32') core.exportVariable('STACK_ROOT', 'C:\\sr');
151173
}
152174

153175
async function apt(tool: Tool, version: string): Promise<void> {
154176
const toolName = tool === 'ghc' ? 'ghc' : 'cabal-install';
155177
const v = tool === 'cabal' ? version.slice(0, 3) : version;
156178
core.info(`Attempting to install ${toolName} ${v} using apt-get`);
157179
// Ignore the return code so we can fall back to ghcup
158-
await exec(`sudo -- sh -c "apt-get -y install ${toolName}-${v}"`, undefined, {
159-
ignoreReturnCode: true
160-
});
180+
await exec(`sudo -- sh -c "apt-get -y install ${toolName}-${v}"`);
161181
}
162182

163183
async function choco(tool: Tool, version: string): Promise<void> {
164184
core.info(`Attempting to install ${tool} ${version} using chocolatey`);
165185
// Choco tries to invoke `add-path` command on earlier versions of ghc, which has been deprecated and fails the step, so disable command execution during this.
166186
console.log('::stop-commands::SetupHaskellStopCommands');
167-
await exec(
168-
'powershell',
169-
[
170-
'choco',
171-
'install',
172-
tool,
173-
'--version',
174-
version,
175-
'-m',
176-
'--no-progress',
177-
'-r'
178-
],
179-
{
180-
ignoreReturnCode: true
181-
}
182-
);
187+
await exec('powershell', [
188+
'choco',
189+
'install',
190+
tool,
191+
'--version',
192+
version,
193+
'-m',
194+
'--no-progress',
195+
'-r'
196+
]);
183197
console.log('::SetupHaskellStopCommands::'); // Re-enable command execution
184198
// Add GHC to path automatically because it does not add until the end of the step and we check the path.
185-
if (tool == 'ghc') {
186-
core.addPath(getChocoPath(tool, version));
187-
}
199+
if (tool == 'ghc') core.addPath(getChocoPath(tool, version));
188200
}
189201

190202
async function ghcupBin(os: OS): Promise<string> {
@@ -204,29 +216,21 @@ async function ghcupBin(os: OS): Promise<string> {
204216
async function ghcup(tool: Tool, version: string, os: OS): Promise<void> {
205217
core.info(`Attempting to install ${tool} ${version} using ghcup`);
206218
const bin = await ghcupBin(os);
207-
const returnCode = await exec(
208-
bin,
209-
[tool === 'ghc' ? 'install' : 'install-cabal', version],
210-
{
211-
ignoreReturnCode: true
212-
}
213-
);
214-
if (returnCode === 0 && tool === 'ghc') await exec(bin, ['set', version]);
219+
const returnCode = await exec(bin, ['install', tool, version]);
220+
if (returnCode === 0) await exec(bin, ['set', tool, version]);
215221
}
216222

217223
function getChocoPath(tool: Tool, version: string): string {
218-
// Manually add the path because it won't happen until the end of the step normally
219-
const pathArray = version.split('.');
220-
const pathVersion =
221-
pathArray.length > 3
222-
? pathArray.slice(0, pathArray.length - 1).join('.')
223-
: pathArray.join('.');
224+
// If chocolatey has a patch release for GHC, 'version' will be a.b.c.d
225+
// but GHC's version is still a.b.c and the chocolatey path contains both
226+
// (This is only valid for GHC. cabal-install has 4-segment versions)
227+
const ghcVersion = version.split('.').slice(0, 3).join('.');
224228
const chocoPath = join(
225229
`${process.env.ChocolateyInstall}`,
226230
'lib',
227231
`${tool}.${version}`,
228232
'tools',
229-
tool === 'ghc' ? `${tool}-${pathVersion}` : `${tool}-${version}`, // choco trims the ghc version here
233+
tool === 'ghc' ? `${tool}-${ghcVersion}` : `${tool}-${version}`, // choco trims the ghc version here
230234
tool === 'ghc' ? 'bin' : ''
231235
);
232236
return chocoPath;

0 commit comments

Comments
 (0)