@mriekki/project-forge 4.14.1 → 4.14.2
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.
|
@@ -6,13 +6,16 @@
|
|
|
6
6
|
"asset": "assets/bootstrap-migrations/wsl-setup/setup-wsl.py",
|
|
7
7
|
"source": {
|
|
8
8
|
"component": "bootstrap",
|
|
9
|
-
"revision": "
|
|
9
|
+
"revision": "9f0f7fd4e0e2220250f6fd5b035706a7d15834af",
|
|
10
10
|
"artifact": "runtime/dev_environment_wsl.py"
|
|
11
11
|
},
|
|
12
|
-
"targetGitBlob": "
|
|
13
|
-
"supportedPredecessorGitBlobs": [
|
|
12
|
+
"targetGitBlob": "883f7bbadd2de4bc0dcb601ee2285f88a0085b52",
|
|
13
|
+
"supportedPredecessorGitBlobs": [
|
|
14
|
+
"6731910246fb99887c58b9f3a8a14fec1bf02c01"
|
|
15
|
+
],
|
|
14
16
|
"supportedBootstrapRevisions": [
|
|
15
|
-
"0c45eb332a815ad79ea061443f337500b9dc5712"
|
|
17
|
+
"0c45eb332a815ad79ea061443f337500b9dc5712",
|
|
18
|
+
"173203baaf36935d04eb81c89f1d016131a40442"
|
|
16
19
|
],
|
|
17
20
|
"allowMissing": true
|
|
18
21
|
}
|
|
@@ -85,24 +85,79 @@ def ensure_apt_package(package: str) -> None:
|
|
|
85
85
|
raise SetupError(f"Unable to install required Ubuntu package: {package}")
|
|
86
86
|
|
|
87
87
|
|
|
88
|
+
def fnm_install_dir() -> Path:
|
|
89
|
+
xdg_data_home = os.environ.get("XDG_DATA_HOME")
|
|
90
|
+
base = Path(xdg_data_home).expanduser() if xdg_data_home else Path.home() / ".local" / "share"
|
|
91
|
+
return base / "fnm"
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def refresh_fnm_path() -> None:
|
|
95
|
+
install_dir = fnm_install_dir()
|
|
96
|
+
fnm_binary = install_dir / "fnm"
|
|
97
|
+
if not fnm_binary.is_file():
|
|
98
|
+
return
|
|
99
|
+
current = os.environ.get("PATH", "")
|
|
100
|
+
prefix = str(install_dir)
|
|
101
|
+
parts = current.split(os.pathsep) if current else []
|
|
102
|
+
if prefix not in parts:
|
|
103
|
+
os.environ["PATH"] = prefix + (os.pathsep + current if current else "")
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def ensure_fnm_available(check_only: bool) -> tuple[bool, str, str]:
|
|
107
|
+
refresh_fnm_path()
|
|
108
|
+
path = command_path("fnm")
|
|
109
|
+
if path:
|
|
110
|
+
result = run(["fnm", "--version"])
|
|
111
|
+
detail = "\n".join(filter(None, [(result.stdout or "").strip(), (result.stderr or "").strip()]))
|
|
112
|
+
return result.returncode == 0, detail or path, "PASS" if result.returncode == 0 else "FAILED"
|
|
113
|
+
|
|
114
|
+
if check_only:
|
|
115
|
+
return False, "fnm is missing in WSL", "MISSING"
|
|
116
|
+
|
|
117
|
+
ensure_apt_package("curl")
|
|
118
|
+
ensure_apt_package("unzip")
|
|
119
|
+
install = run(
|
|
120
|
+
["bash", "-lc", "curl -fsSL https://fnm.vercel.app/install | bash"],
|
|
121
|
+
capture=False,
|
|
122
|
+
)
|
|
123
|
+
if install.returncode != 0:
|
|
124
|
+
return False, "fnm installer failed", "FAILED"
|
|
125
|
+
|
|
126
|
+
refresh_fnm_path()
|
|
127
|
+
path = command_path("fnm")
|
|
128
|
+
if not path:
|
|
129
|
+
return False, f"fnm installer completed but {fnm_install_dir() / 'fnm'} is unavailable", "FAILED"
|
|
130
|
+
|
|
131
|
+
verify = run(["fnm", "--version"])
|
|
132
|
+
detail = "\n".join(filter(None, [(verify.stdout or "").strip(), (verify.stderr or "").strip()]))
|
|
133
|
+
return verify.returncode == 0, detail or path, "PASS" if verify.returncode == 0 else "FAILED"
|
|
134
|
+
|
|
135
|
+
|
|
88
136
|
def ensure_fnm_node(version: str | None, check_only: bool) -> tuple[bool, str, str]:
|
|
89
|
-
|
|
90
|
-
|
|
137
|
+
fnm_ok, fnm_detail, fnm_state = ensure_fnm_available(check_only)
|
|
138
|
+
if not fnm_ok:
|
|
139
|
+
return False, fnm_detail, fnm_state
|
|
91
140
|
if not version:
|
|
92
|
-
return True, "fnm available", "PASS"
|
|
141
|
+
return True, fnm_detail or "fnm available", "PASS"
|
|
142
|
+
|
|
93
143
|
result = run(["fnm", "exec", f"--using={version}", "--", "node", "--version"])
|
|
94
144
|
detail = "\n".join(filter(None, [(result.stdout or "").strip(), (result.stderr or "").strip()]))
|
|
95
145
|
if result.returncode == 0 and version in detail.lstrip("v"):
|
|
96
146
|
return True, detail, "PASS"
|
|
97
147
|
if check_only:
|
|
98
148
|
return False, detail or f"Node {version} is not installed through fnm", "VERSION_MISMATCH"
|
|
149
|
+
|
|
99
150
|
install = run(["fnm", "install", version], capture=False)
|
|
100
151
|
if install.returncode != 0:
|
|
101
152
|
return False, f"fnm failed to install Node {version}", "FAILED"
|
|
102
|
-
run(["fnm", "default", version], capture=False)
|
|
153
|
+
default = run(["fnm", "default", version], capture=False)
|
|
154
|
+
if default.returncode != 0:
|
|
155
|
+
return False, f"fnm installed Node {version} but failed to make it the default", "FAILED"
|
|
156
|
+
|
|
103
157
|
verify = run(["fnm", "exec", f"--using={version}", "--", "node", "--version"])
|
|
104
158
|
text = (verify.stdout or verify.stderr or "").strip()
|
|
105
|
-
|
|
159
|
+
ok = verify.returncode == 0 and version in text.lstrip("v")
|
|
160
|
+
return ok, text or f"Node {version} verification failed", "PASS" if ok else "FAILED"
|
|
106
161
|
|
|
107
162
|
|
|
108
163
|
def ensure_tool(entry: dict[str, Any], check_only: bool) -> tuple[bool, str, str]:
|
|
@@ -110,6 +165,8 @@ def ensure_tool(entry: dict[str, Any], check_only: bool) -> tuple[bool, str, str
|
|
|
110
165
|
spec = read_json(CATALOG / f"{tool_id}.json")
|
|
111
166
|
version = entry.get("version")
|
|
112
167
|
|
|
168
|
+
if tool_id == "fnm":
|
|
169
|
+
return ensure_fnm_available(check_only)
|
|
113
170
|
if tool_id == "node":
|
|
114
171
|
return ensure_fnm_node(version, check_only)
|
|
115
172
|
|
|
@@ -130,10 +187,15 @@ def ensure_tool(entry: dict[str, Any], check_only: bool) -> tuple[bool, str, str
|
|
|
130
187
|
if check_only:
|
|
131
188
|
return False, detail, "MISSING" if detail == "missing" else "VERSION_MISMATCH"
|
|
132
189
|
|
|
190
|
+
if tool_id == "python":
|
|
191
|
+
ensure_apt_package("python3")
|
|
192
|
+
ensure_apt_package("python-is-python3")
|
|
193
|
+
ok, detail = version_ok(spec, version)
|
|
194
|
+
return ok, detail, "PASS" if ok else "FAILED"
|
|
195
|
+
|
|
133
196
|
apt_packages = {
|
|
134
197
|
"git": "git",
|
|
135
198
|
"github-cli": "gh",
|
|
136
|
-
"python": "python3",
|
|
137
199
|
"sqlite": "sqlite3",
|
|
138
200
|
"ssh": "openssh-client",
|
|
139
201
|
"go": "golang-go",
|
|
@@ -143,6 +205,16 @@ def ensure_tool(entry: dict[str, Any], check_only: bool) -> tuple[bool, str, str
|
|
|
143
205
|
ok, detail = version_ok(spec, version)
|
|
144
206
|
return ok, detail, "PASS" if ok else "FAILED"
|
|
145
207
|
|
|
208
|
+
if tool_id == "dotnet":
|
|
209
|
+
if not version:
|
|
210
|
+
return False, ".NET SDK version is required for automatic WSL installation", "FAILED"
|
|
211
|
+
major = version.split(".", 1)[0]
|
|
212
|
+
if not re.fullmatch(r"\d+", major):
|
|
213
|
+
return False, f"Unsupported .NET SDK version: {version}", "FAILED"
|
|
214
|
+
ensure_apt_package(f"dotnet-sdk-{major}.0")
|
|
215
|
+
ok, detail = version_ok(spec, version)
|
|
216
|
+
return ok, detail, "PASS" if ok else "FAILED"
|
|
217
|
+
|
|
146
218
|
if tool_id == "vscode":
|
|
147
219
|
return False, (
|
|
148
220
|
"VS Code's WSL command bridge is unavailable. Install VS Code on Windows and the "
|
|
@@ -153,16 +225,6 @@ def ensure_tool(entry: dict[str, Any], check_only: bool) -> tuple[bool, str, str
|
|
|
153
225
|
"Docker is unavailable inside WSL. Install/start Docker Desktop on Windows and enable "
|
|
154
226
|
"WSL integration for this distro; do not install Docker Engine inside WSL."
|
|
155
227
|
), "MISSING"
|
|
156
|
-
if tool_id == "fnm":
|
|
157
|
-
return False, (
|
|
158
|
-
"fnm is required inside WSL for Project-declared Node versions. Install fnm in this "
|
|
159
|
-
"distro, then rerun /setup."
|
|
160
|
-
), "MISSING"
|
|
161
|
-
if tool_id == "dotnet":
|
|
162
|
-
return False, (
|
|
163
|
-
f".NET SDK {version or ''} is required inside WSL. Install the matching Microsoft .NET SDK "
|
|
164
|
-
"for Ubuntu in this distro, then rerun /setup."
|
|
165
|
-
).strip(), "MISSING" if detail == "missing" else "VERSION_MISMATCH"
|
|
166
228
|
if tool_id == "java":
|
|
167
229
|
return False, (
|
|
168
230
|
f"Java {version or ''} is required inside WSL. Install the matching JDK in this distro, "
|
package/assets/components.json
CHANGED