@ijfw/install 1.1.2 → 1.1.3
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/CHANGELOG.md +24 -0
- package/dist/install.js +46 -5
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog -- @ijfw/install
|
|
2
2
|
|
|
3
|
+
## [1.1.3] -- 2026-04-21
|
|
4
|
+
|
|
5
|
+
Windows "it just works" fix + Windows CI gate.
|
|
6
|
+
|
|
7
|
+
### Windows npx path finally works
|
|
8
|
+
|
|
9
|
+
- **`install.js` now resolves `bash.exe` via `git.exe`'s install root** instead of requiring `bash` on PATH. Git for Windows installs `bash.exe` at `C:\Program Files\Git\bin\bash.exe` but by default does **not** add that dir to PATH, so the previous `hasBin('bash')` preflight always failed -- even on a perfectly-functional Git for Windows install. New `findBash()` helper mirrors `install.ps1`'s `Resolve-GitBash`: walks `where git` output to find the sibling bash.exe, falls back to `Program Files\Git\{bin,usr/bin}\bash.exe`, and only errors if nothing lands.
|
|
10
|
+
- `runInstallScript` now calls the resolved `bash.exe` path directly instead of bare `"bash"`, so the child process spawns cleanly on Windows without PATH manipulation.
|
|
11
|
+
- Error message when git is missing on Windows now leads with a single `winget install --id Git.Git` command, drops the PS1 `irm | iex` fallback (Windows Defender heuristically blocks that pattern), and tells the user to reopen PowerShell before rerunning so the PATH refresh picks up.
|
|
12
|
+
- Error message when git is present but bash.exe cannot be located points at the expected path and gives a one-line remediation.
|
|
13
|
+
|
|
14
|
+
### Windows CI gate (new)
|
|
15
|
+
|
|
16
|
+
- `.github/workflows/windows-smoke.yml`. Runs on every push and PR on `windows-latest`. Checks: install.js loads, `findBash()` returns a live path, installer clones + runs `scripts/install.sh` against a scratch IJFW_HOME with `IJFW_CUSTOM_DIR=1`, writes the expected files. Catches the 1.1.2 regression at source -- a Windows publish that would have shipped a broken `npx` entry point now fails CI before it reaches main.
|
|
17
|
+
|
|
18
|
+
### Internal
|
|
19
|
+
|
|
20
|
+
- `mcp-server/package.json` bumped 1.1.2 -> 1.1.3 to stay in lockstep with the installer.
|
|
21
|
+
|
|
22
|
+
### Notes for upgraders
|
|
23
|
+
|
|
24
|
+
- No behavioral change for macOS or Linux users. `findBash()` returns `"bash"` on non-Windows hosts where PATH is reliable.
|
|
25
|
+
- No config-schema changes. `~/.codex/hooks.json` stays on the 1.1.2 nested map schema.
|
|
26
|
+
|
|
3
27
|
## [1.1.2] -- 2026-04-21
|
|
4
28
|
|
|
5
29
|
Reach + bug fixes. Two new platforms (Hermes + Wayland), deep installer repairs uncovered by live-platform testing, cross-platform sync of new behavioral rules. Ships with a full end-to-end smoke harness at `scripts/e2e-smoke.sh` that now has to pass before any future release.
|
package/dist/install.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// src/install.js
|
|
4
4
|
import { spawnSync } from "node:child_process";
|
|
5
5
|
import { existsSync as existsSync2, rmSync, mkdirSync as mkdirSync2, realpathSync, renameSync as renameSync2 } from "node:fs";
|
|
6
|
-
import { resolve, join as join2 } from "node:path";
|
|
6
|
+
import { resolve, join as join2, dirname as dirname2 } from "node:path";
|
|
7
7
|
import { homedir as homedir2, platform } from "node:os";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
9
|
|
|
@@ -151,10 +151,20 @@ function preflight() {
|
|
|
151
151
|
const issues = [];
|
|
152
152
|
const [major] = process.versions.node.split(".").map(Number);
|
|
153
153
|
if (major < 18) issues.push(`IJFW needs Node >=18 -- current: ${process.versions.node}. Upgrade Node, then retry.`);
|
|
154
|
-
if (!hasBin("git"))
|
|
155
|
-
if (!hasBin("bash")) {
|
|
154
|
+
if (!hasBin("git")) {
|
|
156
155
|
if (platform() === "win32") {
|
|
157
|
-
issues.push(
|
|
156
|
+
issues.push(
|
|
157
|
+
"IJFW needs Git for Windows (it bundles git + bash). One command:\n winget install --id Git.Git -e --source winget --accept-source-agreements --accept-package-agreements\n Then close this PowerShell window, open a fresh one, and rerun:\n npx -p @ijfw/install ijfw-install"
|
|
158
|
+
);
|
|
159
|
+
} else {
|
|
160
|
+
issues.push("IJFW needs git on PATH -- install git (https://git-scm.com), then retry.");
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (!findBash()) {
|
|
164
|
+
if (platform() === "win32") {
|
|
165
|
+
issues.push(
|
|
166
|
+
"IJFW could not locate bash.exe. Git for Windows installs it at\n C:\\Program Files\\Git\\bin\\bash.exe\n If you installed Git elsewhere, add its bin\\ to PATH and rerun.\n Missing Git entirely? winget install --id Git.Git -e --source winget"
|
|
167
|
+
);
|
|
158
168
|
} else {
|
|
159
169
|
issues.push("IJFW needs bash on PATH -- install bash, then retry.");
|
|
160
170
|
}
|
|
@@ -165,6 +175,32 @@ function hasBin(bin) {
|
|
|
165
175
|
const res = spawnSync(bin, ["--version"], { stdio: "ignore" });
|
|
166
176
|
return res.status === 0 || res.status === null ? res.error ? false : true : false;
|
|
167
177
|
}
|
|
178
|
+
function findBash() {
|
|
179
|
+
if (hasBin("bash") && platform() !== "win32") return "bash";
|
|
180
|
+
if (platform() !== "win32") return hasBin("bash") ? "bash" : null;
|
|
181
|
+
const whereGit = spawnSync("where", ["git"], { encoding: "utf8" });
|
|
182
|
+
if (whereGit.status === 0) {
|
|
183
|
+
const gitPath = (whereGit.stdout || "").split(/\r?\n/)[0].trim();
|
|
184
|
+
if (gitPath && existsSync2(gitPath)) {
|
|
185
|
+
const gitDir = dirname2(gitPath);
|
|
186
|
+
const gitRoot = dirname2(gitDir);
|
|
187
|
+
const candidates = [
|
|
188
|
+
join2(gitDir, "bash.exe"),
|
|
189
|
+
join2(gitRoot, "bin", "bash.exe"),
|
|
190
|
+
join2(gitRoot, "usr", "bin", "bash.exe")
|
|
191
|
+
];
|
|
192
|
+
for (const c of candidates) if (existsSync2(c)) return c;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
for (const c of [
|
|
196
|
+
"C:\\Program Files\\Git\\bin\\bash.exe",
|
|
197
|
+
"C:\\Program Files\\Git\\usr\\bin\\bash.exe",
|
|
198
|
+
"C:\\Program Files (x86)\\Git\\bin\\bash.exe",
|
|
199
|
+
"C:\\Program Files (x86)\\Git\\usr\\bin\\bash.exe"
|
|
200
|
+
]) if (existsSync2(c)) return c;
|
|
201
|
+
if (hasBin("bash")) return "bash";
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
168
204
|
function resolveTarget(opt) {
|
|
169
205
|
if (opt.dir) return resolve(opt.dir);
|
|
170
206
|
if (process.env.IJFW_HOME) return resolve(process.env.IJFW_HOME);
|
|
@@ -224,7 +260,11 @@ function runInstallScript(dir) {
|
|
|
224
260
|
IJFW_HOME: dir,
|
|
225
261
|
IJFW_CUSTOM_DIR: isCustomDir
|
|
226
262
|
};
|
|
227
|
-
const
|
|
263
|
+
const bashExe = findBash();
|
|
264
|
+
if (!bashExe) {
|
|
265
|
+
throw new Error("IJFW could not locate bash (preflight should have caught this -- file an issue).");
|
|
266
|
+
}
|
|
267
|
+
const r = spawnSync(bashExe, ["scripts/install.sh"], { cwd: dir, stdio: "inherit", env });
|
|
228
268
|
if (r.status !== 0) throw new Error(`IJFW platform config step did not complete (exit ${r.status}) -- run ijfw doctor to see what to fix.`);
|
|
229
269
|
}
|
|
230
270
|
async function main() {
|
|
@@ -282,5 +322,6 @@ if (isDirectRun()) {
|
|
|
282
322
|
});
|
|
283
323
|
}
|
|
284
324
|
export {
|
|
325
|
+
findBash,
|
|
285
326
|
resolveBranchOrTag
|
|
286
327
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ijfw/install",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "One-command installer for IJFW -- the AI efficiency layer. One install, every AI coding agent, zero config.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"LICENSE"
|
|
19
19
|
],
|
|
20
20
|
"scripts": {
|
|
21
|
-
"build": "
|
|
21
|
+
"build": "node scripts/build.js",
|
|
22
22
|
"test": "node --test test.js",
|
|
23
23
|
"preflight": "node dist/ijfw.js preflight",
|
|
24
24
|
"pack:check": "npm pack --dry-run",
|