@localctl/cli 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/package.json +1 -1
- package/src/commands/uninstall.js +6 -1
- package/src/index.js +3 -0
- package/src/lib/clusterProvision.js +3 -3
- package/src/lib/toolInstall.js +72 -2
package/README.md
CHANGED
|
@@ -318,6 +318,7 @@ The full documentation lives at **[psilvmoreira.github.io/localctl](https://psil
|
|
|
318
318
|
|---|---|
|
|
319
319
|
| [Getting started](https://psilvmoreira.github.io/localctl/getting-started/) | Install and first deploy, step by step |
|
|
320
320
|
| [Architecture](https://psilvmoreira.github.io/localctl/architecture/) | Every component, why it was chosen, multi-project support |
|
|
321
|
+
| [CLI commands](https://psilvmoreira.github.io/localctl/cli-reference/) | Every command and option |
|
|
321
322
|
| [Config schema](https://psilvmoreira.github.io/localctl/config-schema/) | Every `.local/config.json` field |
|
|
322
323
|
| [Debugging](https://psilvmoreira.github.io/localctl/debugging/) | Attach a debugger in Node, Python, Go, Java and .NET |
|
|
323
324
|
| [Adding tools](https://psilvmoreira.github.io/localctl/adding-tools/) | Write your own per-app or cluster-wide addon |
|
|
@@ -339,7 +340,8 @@ The full documentation lives at **[psilvmoreira.github.io/localctl](https://psil
|
|
|
339
340
|
|
|
340
341
|
## Contributing
|
|
341
342
|
|
|
342
|
-
Issues and pull requests are welcome.
|
|
343
|
+
Issues and pull requests are welcome. The full guide (constraints, dependency policy, working on
|
|
344
|
+
the docs site) is in [**Contributing**](https://psilvmoreira.github.io/localctl/contributing/).
|
|
343
345
|
|
|
344
346
|
1. Fork the repository and create a branch.
|
|
345
347
|
2. Make your change and run the tests:
|
package/package.json
CHANGED
|
@@ -91,7 +91,12 @@ async function uninstall(opts) {
|
|
|
91
91
|
logger.success('Uninstall complete.');
|
|
92
92
|
console.log('');
|
|
93
93
|
console.log('Left in place (remove yourself if you want them gone too):');
|
|
94
|
-
|
|
94
|
+
if (process.platform === 'win32') {
|
|
95
|
+
console.log(' winget uninstall k3d.k3d Kubernetes.kubectl FiloSottile.mkcert Helm.Helm # only if nothing else needs them');
|
|
96
|
+
console.log(' Remove-Item -Recurse -Force ~\\.localctl\\tools # tilt, if localctl installed it');
|
|
97
|
+
} else {
|
|
98
|
+
console.log(' brew uninstall k3d kubectl tilt mkcert helm # only if nothing else needs them');
|
|
99
|
+
}
|
|
95
100
|
console.log(" mkcert -uninstall # removes the root CA from trust stores - affects EVERY");
|
|
96
101
|
console.log(' # mkcert-issued cert on this machine, not just *.local.test');
|
|
97
102
|
}
|
package/src/index.js
CHANGED
|
@@ -2,6 +2,9 @@ const { Command } = require('commander');
|
|
|
2
2
|
const { version } = require('../package.json');
|
|
3
3
|
|
|
4
4
|
require('./lib/updateCheck').start(version);
|
|
5
|
+
// Tools localctl downloaded itself (e.g. tilt on Windows) work even in a terminal opened before
|
|
6
|
+
// they were added to the user's PATH.
|
|
7
|
+
require('./lib/toolInstall').addToolsDirToPath();
|
|
5
8
|
|
|
6
9
|
const program = new Command();
|
|
7
10
|
program
|
|
@@ -4,7 +4,7 @@ const path = require('path');
|
|
|
4
4
|
const yaml = require('js-yaml');
|
|
5
5
|
const { run, capture, sleepSync, commandExists } = require('./exec');
|
|
6
6
|
const { detectEngine, warnIfExperimental } = require('./engine');
|
|
7
|
-
const { installIfMissing } = require('./toolInstall');
|
|
7
|
+
const { installIfMissing, installTiltWindows } = require('./toolInstall');
|
|
8
8
|
const { ensureInsecureRegistry } = require('./podman');
|
|
9
9
|
const { DOMAIN } = require('./constants');
|
|
10
10
|
const logger = require('./logger');
|
|
@@ -49,9 +49,9 @@ function provisionCluster({ clusterName, httpPort, httpsPort, registryPort }) {
|
|
|
49
49
|
ensureInsecureRegistry(registryPort);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
installIfMissing('k3d', 'k3d', 'k3d
|
|
52
|
+
installIfMissing('k3d', 'k3d', 'k3d.k3d');
|
|
53
53
|
installIfMissing('kubectl', 'kubernetes-cli', 'Kubernetes.kubectl');
|
|
54
|
-
installIfMissing('tilt', 'tilt',
|
|
54
|
+
installIfMissing('tilt', 'tilt', installTiltWindows);
|
|
55
55
|
installIfMissing('mkcert', 'mkcert', 'FiloSottile.mkcert');
|
|
56
56
|
installIfMissing('helm', 'helm', 'Helm.Helm');
|
|
57
57
|
|
package/src/lib/toolInstall.js
CHANGED
|
@@ -1,7 +1,72 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
1
3
|
const { commandExists, run } = require('./exec');
|
|
2
4
|
const logger = require('./logger');
|
|
5
|
+
const { HOME_STATE_DIR } = require('./paths');
|
|
3
6
|
|
|
4
|
-
//
|
|
7
|
+
// Tools that have no package-manager package on a platform get downloaded here instead. The
|
|
8
|
+
// directory is added to the user's PATH for new terminals, and to this process's PATH by
|
|
9
|
+
// addToolsDirToPath() on every run, so the current terminal needs no restart.
|
|
10
|
+
const TOOLS_DIR = path.join(HOME_STATE_DIR, 'tools');
|
|
11
|
+
|
|
12
|
+
function prependToPath(dir) {
|
|
13
|
+
if (!fs.existsSync(dir)) return;
|
|
14
|
+
const entries = (process.env.PATH || '').split(path.delimiter);
|
|
15
|
+
if (!entries.includes(dir)) process.env.PATH = [dir, ...entries].join(path.delimiter);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function addToolsDirToPath() {
|
|
19
|
+
prependToPath(TOOLS_DIR);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// winget puts portable packages (k3d, kubectl, helm, mkcert) behind links in this directory and
|
|
23
|
+
// adds it to PATH for new terminals only. Adding it here lets the rest of `localctl setup` use a
|
|
24
|
+
// tool winget just installed.
|
|
25
|
+
function addWingetLinksToPath() {
|
|
26
|
+
if (process.env.LOCALAPPDATA) prependToPath(path.join(process.env.LOCALAPPDATA, 'Microsoft', 'WinGet', 'Links'));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function powershell(script) {
|
|
30
|
+
run('powershell', ['-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-Command', script]);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Tilt isn't published to winget. Same steps as Tilt's own install.ps1 (latest release zip from
|
|
34
|
+
// GitHub), but into TOOLS_DIR and with the directory added to the user's PATH, which install.ps1
|
|
35
|
+
// leaves to you.
|
|
36
|
+
function installTiltWindows() {
|
|
37
|
+
logger.step('Installing tilt from its GitHub release (not available on winget)...');
|
|
38
|
+
powershell(`
|
|
39
|
+
$ErrorActionPreference = 'Stop'
|
|
40
|
+
$ProgressPreference = 'SilentlyContinue'
|
|
41
|
+
$dir = '${TOOLS_DIR.replace(/'/g, "''")}'
|
|
42
|
+
$version = (Invoke-RestMethod 'https://api.github.com/repos/tilt-dev/tilt/releases/latest').tag_name.TrimStart('v')
|
|
43
|
+
$url = "https://github.com/tilt-dev/tilt/releases/download/v$version/tilt.$version.windows.x86_64.zip"
|
|
44
|
+
$tmp = Join-Path $env:TEMP "localctl-tilt-$version"
|
|
45
|
+
if (Test-Path $tmp) { Remove-Item -Recurse -Force $tmp }
|
|
46
|
+
New-Item -ItemType Directory -Force -Path $tmp, $dir | Out-Null
|
|
47
|
+
Write-Host "Downloading $url"
|
|
48
|
+
Invoke-WebRequest $url -OutFile "$tmp\\tilt.zip"
|
|
49
|
+
Expand-Archive "$tmp\\tilt.zip" -DestinationPath $tmp
|
|
50
|
+
Move-Item -Force "$tmp\\tilt.exe" "$dir\\tilt.exe"
|
|
51
|
+
Remove-Item -Recurse -Force $tmp
|
|
52
|
+
# Raw registry value, so entries like %USERPROFILE%\\bin stay unexpanded (REG_EXPAND_SZ).
|
|
53
|
+
$key = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Environment', $true)
|
|
54
|
+
$userPath = [string]$key.GetValue('Path', '', 'DoNotExpandEnvironmentNames')
|
|
55
|
+
if ((($userPath -split ';') | Where-Object { $_ -eq $dir }).Count -eq 0) {
|
|
56
|
+
$key.SetValue('Path', (($userPath.TrimEnd(';'), $dir) -join ';').TrimStart(';'), 'ExpandString')
|
|
57
|
+
# Setting any user variable through .NET broadcasts WM_SETTINGCHANGE, so terminals opened
|
|
58
|
+
# from now on pick up the new PATH without signing out.
|
|
59
|
+
[Environment]::SetEnvironmentVariable('LOCALCTL_PATH_REFRESH', '1', 'User')
|
|
60
|
+
[Environment]::SetEnvironmentVariable('LOCALCTL_PATH_REFRESH', $null, 'User')
|
|
61
|
+
}
|
|
62
|
+
$key.Close()
|
|
63
|
+
`);
|
|
64
|
+
addToolsDirToPath();
|
|
65
|
+
logger.success(`tilt installed in ${TOOLS_DIR} (added to your PATH for new terminals)`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// macId: Homebrew formula name. winId: winget package id, or a function that installs the tool
|
|
69
|
+
// when winget doesn't have it.
|
|
5
70
|
function installIfMissing(bin, macId, winId) {
|
|
6
71
|
if (commandExists(bin)) {
|
|
7
72
|
logger.success(`${bin} already installed`);
|
|
@@ -14,6 +79,10 @@ function installIfMissing(bin, macId, winId) {
|
|
|
14
79
|
logger.step(`Installing ${macId} via brew...`);
|
|
15
80
|
run('brew', ['install', macId]);
|
|
16
81
|
} else if (process.platform === 'win32') {
|
|
82
|
+
if (typeof winId === 'function') {
|
|
83
|
+
winId();
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
17
86
|
if (!commandExists('winget')) {
|
|
18
87
|
throw new Error('winget is required to install missing tools (ships with modern Windows / App Installer).');
|
|
19
88
|
}
|
|
@@ -22,9 +91,10 @@ function installIfMissing(bin, macId, winId) {
|
|
|
22
91
|
'install', '--id', winId, '-e', '--source', 'winget',
|
|
23
92
|
'--accept-package-agreements', '--accept-source-agreements',
|
|
24
93
|
]);
|
|
94
|
+
addWingetLinksToPath();
|
|
25
95
|
} else {
|
|
26
96
|
throw new Error(`"${bin}" is missing and automatic install isn't supported on this platform. Install it manually.`);
|
|
27
97
|
}
|
|
28
98
|
}
|
|
29
99
|
|
|
30
|
-
module.exports = { installIfMissing };
|
|
100
|
+
module.exports = { installIfMissing, installTiltWindows, addToolsDirToPath, TOOLS_DIR };
|