-
-
Notifications
You must be signed in to change notification settings - Fork 39
Expand file tree
/
Copy pathlando-setup-build-engine-win32.js
More file actions
199 lines (178 loc) · 6.72 KB
/
lando-setup-build-engine-win32.js
File metadata and controls
199 lines (178 loc) · 6.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
'use strict';
const axios = require('../utils/get-axios')();
const fs = require('fs');
const getDockerDesktopBin = require('../utils/get-docker-desktop-x');
const os = require('os');
const path = require('path');
const semver = require('semver');
const {color} = require('listr2');
const {nanoid} = require('nanoid');
const buildIds = {
'4.37.1': '178610',
'4.37.0': '178034',
'4.36.0': '175267',
'4.35.1': '173168',
'4.35.0': '172550',
'4.34.3': '170107',
'4.34.2': '167172',
'4.34.1': '166053',
'4.34.0': '165256',
'4.33.1': '161083',
'4.33.0': '160616',
'4.32.0': '157355',
'4.31.1': '153621',
'4.31.0': '153195',
'4.30.0': '149282',
'4.29.0': '145265',
'4.28.0': '139021',
'4.27.2': '137060',
'4.27.1': '136059',
'4.27.0': '135262',
'4.26.1': '131620',
'4.26.0': '130397',
'4.25.2': '129061',
'4.25.1': '128006',
'4.25.0': '126437',
};
/*
* Helper to get build engine id
*/
const getId = version => {
// if version is an integer then assume its already the id
if (semver.valid(version) === null && Number.isInteger(parseInt(version))) return version;
// otherwise return that corresponding build-id
return buildIds[version];
};
const getVersion = version => {
// if version is not an integer then assume its already the version
if (semver.valid(version) !== null) return version;
// otherwise return the version that corresponds to the build id
return Object.keys(buildIds).find(key => buildIds[key] === version);
};
/*
* Helper to get docker compose v2 download url
*/
const getEngineDownloadUrl = (id = '175267') => {
const arch = process.arch === 'arm64' ? 'arm64' : 'amd64';
return `https://desktop.docker.com/win/main/${arch}/${id}/Docker%20Desktop%20Installer.exe`;
};
/*
* wrapper for docker-desktop install
*/
const downloadDockerDesktop = (url, {debug, task, ctx}) => new Promise((resolve, reject) => {
const download = require('../utils/download-x')(url, {
debug,
dest: path.join(os.tmpdir(), `${nanoid()}.exe`),
});
// success
download.on('done', result => {
task.title = `Downloaded build engine`;
resolve(result);
});
// handle errors
download.on('error', error => {
ctx.errors.push(error);
reject(error);
});
// update title to reflect download progress
download.on('progress', progress => {
task.title = `Downloading build engine ${color.dim(`[${progress.percentage}%]`)}`;
});
});
module.exports = async (lando, options) => {
const debug = require('../utils/debug-shim')(lando.log);
debug.enabled = lando.debuggy;
// if build engine is set to false allow it to be skipped
// @NOTE: this is mostly for internal stuff
if (options.buildEngine === false) return;
// get stuff from config/opts
const build = getId(options.buildEngine);
const version = getVersion(options.buildEngine);
// cosmetics
const install = version ? `v${version}` : `build ${build}`;
// download url
const url = getEngineDownloadUrl(build);
// win32 install docker desktop task
options.tasks.push({
title: 'Downloading build engine',
id: 'setup-build-engine',
description: '@lando/build-engine (docker-desktop)',
version: `Docker Desktop ${install}`,
hasRun: async () => {
// if we are missing any files we can check then terminate here
if (lando.engine.dockerInstalled === false || !fs.existsSync(getDockerDesktopBin())) return false;
// if we get here let's make sure the engine is on
try {
await lando.engine.daemon.up({max: 5, backoff: 1000});
return true;
} catch (error) {
lando.log.debug('docker install task has not run %j', error);
return false;
}
},
canRun: async () => {
// throw if we cannot resolve a semantic version to a buildid
if (!build) throw new Error(`Could not resolve ${install} to an installable version!`);
// throw error if we cannot ping the download link
await axios.head(url);
// @TODO: check for wsl2?
return true;
},
requiresRestart: async () => {
// if wsl is not installed then this requires a restart
const {installed, features} = await require('../utils/get-wsl-status')({debug});
const restart = !installed || !features;
debug('wsl installed=%o, features=%o, restart %o', installed, features, restart ? 'required' : 'not required');
return restart;
},
task: async (ctx, task) => {
try {
// download the installer
ctx.download = await downloadDockerDesktop(url, {ctx, debug, task});
// script
const script = path.join(lando.config.userConfRoot, 'scripts', 'install-docker-desktop.ps1');
// args
const args = ['-Installer', ctx.download.dest];
if (options.buildEngineAcceptLicense) args.push('-AcceptLicense');
if ((options.debug || options.verbose > 0 || lando.debuggy) && lando.config.isInteractive) args.push('-Debug');
// run install command
task.title = `Installing build engine ${color.dim('(this may take a minute)')}`;
const result = await require('../utils/run-powershell-script')(script, args, {debug});
result.download = ctx.download;
// finish up
const location = process.env.ProgramW6432 ?? process.env.ProgramFiles;
task.title = `Installed build engine (Docker Desktop) to ${location}/Docker/Docker!`;
return result;
} catch (error) {
throw error;
}
},
});
// add docker group add task
options.tasks.push({
title: `Adding ${lando.config.username} to docker-users group`,
id: 'setup-build-engine-group',
dependsOn: ['setup-build-engine'],
description: `@lando/build-engine-group (${lando.config.username}@docker-users)`,
comments: {
'NOT INSTALLED': `Will add ${lando.config.username} to docker-users group`,
},
hasRun: async () => require('../utils/is-group-member')('docker-users'),
task: async (ctx, task) => {
// check one last time incase this was added by a dependee or otherwise
if (require('../utils/is-group-member')('docker-users')) return {code: 0};
const command = ['net', 'localgroup', 'docker-users', lando.config.username, '/ADD'];
const {code, stdout, stderr} = await require('../utils/run-elevated')(command, {ignoreReturnCode: true, debug});
// fail on anything except 1378 which is user already exists
if (code !== 0 && (!stderr.includes('1378') || !stderr.includes('already a member'))) {
const error = new Error(`Error adding ${lando.config.username} to the docker-users group!`);
error.code = code;
error.stdout = stdout;
error.stderr = stderr;
throw error;
}
task.title = `Added ${lando.config.username} to docker-users`;
return {code, stdout, stderr};
},
});
};