fix(cli): skip rebuild when git install is already on latest version (#1585)
* fix(cli): skip rebuild when git install is already on latest version After `git fetch`, compare local HEAD to remote HEAD. If they match, print "Already on latest version." and exit without running pnpm install, clean, build, or npm link. Without this check, `ao update` re-ran the full rebuild on every invocation even when nothing had changed, because the git path in `handleGitUpdate` (unlike the npm path) never called `checkForUpdate()` to short-circuit before delegating to the shell script. Fixes #1584 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(cli): keep running smoke tests when already on latest version The previous fix exited 0 immediately on the "already on latest" path, which silently skipped smoke tests that would otherwise verify the install. Restructure with an else-branch so the rebuild block is skipped but execution continues to the smoke-test gate, preserving the prior smoke-test behavior for the no-update case. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
818f11f987
commit
64f67f3425
|
|
@ -36,6 +36,8 @@ describe("ao-update.sh", () => {
|
|||
"status --porcelain") ;;
|
||||
"branch --show-current") printf 'main\\n' ;;
|
||||
"fetch origin main") ;;
|
||||
"rev-parse HEAD") printf 'oldsha000\\n' ;;
|
||||
"rev-parse origin/main") printf 'newsha111\\n' ;;
|
||||
"pull --ff-only origin main") ;;
|
||||
*) ;;
|
||||
esac\nexit 0`,
|
||||
|
|
@ -96,6 +98,8 @@ esac\nexit 0`,
|
|||
"status --porcelain") ;;
|
||||
"branch --show-current") printf 'main\\n' ;;
|
||||
"fetch upstream main") ;;
|
||||
"rev-parse HEAD") printf 'oldsha000\\n' ;;
|
||||
"rev-parse upstream/main") printf 'newsha111\\n' ;;
|
||||
"pull --ff-only upstream main") ;;
|
||||
*) ;;
|
||||
esac\nexit 0`,
|
||||
|
|
@ -232,6 +236,75 @@ exit 0`,
|
|||
expect(result.stderr).toContain("commit or stash");
|
||||
});
|
||||
|
||||
it("skips rebuild but still runs smoke tests when local HEAD matches remote HEAD", () => {
|
||||
const tempRoot = mkdtempSync(join(tmpdir(), "ao-update-already-latest-"));
|
||||
const fakeRepo = join(tempRoot, "repo");
|
||||
mkdirSync(join(fakeRepo, "packages", "cli"), { recursive: true });
|
||||
mkdirSync(join(fakeRepo, "packages", "ao", "bin"), { recursive: true });
|
||||
writeFileSync(join(fakeRepo, "packages", "ao", "bin", "ao.js"), "#!/usr/bin/env node\n");
|
||||
|
||||
const binDir = join(tempRoot, "bin");
|
||||
mkdirSync(binDir, { recursive: true });
|
||||
const commandLog = join(tempRoot, "commands.log");
|
||||
|
||||
const sha = "abc123def456abc123def456abc123def456abc123";
|
||||
|
||||
createFakeBinary(
|
||||
binDir,
|
||||
"git",
|
||||
`printf 'git %s\\n' "$*" >> ${JSON.stringify(commandLog)}
|
||||
case "$*" in
|
||||
"remote get-url upstream") exit 1 ;;
|
||||
"rev-parse --is-inside-work-tree") printf 'true\\n' ;;
|
||||
"status --porcelain") ;;
|
||||
"branch --show-current") printf 'main\\n' ;;
|
||||
"fetch origin main") ;;
|
||||
"rev-parse HEAD") printf '${sha}\\n' ;;
|
||||
"rev-parse origin/main") printf '${sha}\\n' ;;
|
||||
*) ;;
|
||||
esac
|
||||
exit 0`,
|
||||
);
|
||||
createFakeBinary(
|
||||
binDir,
|
||||
"pnpm",
|
||||
`printf 'pnpm %s\\n' "$*" >> ${JSON.stringify(commandLog)}\nif [ "$1" = "--version" ]; then\n printf '9.15.4\\n'\nfi\nexit 0`,
|
||||
);
|
||||
createFakeBinary(binDir, "npm", `printf 'npm %s\\n' "$*" >> ${JSON.stringify(commandLog)}\nexit 0`);
|
||||
createFakeBinary(
|
||||
binDir,
|
||||
"node",
|
||||
`printf 'node %s\\n' "$*" >> ${JSON.stringify(commandLog)}\nif [ "$1" = "--version" ]; then\n printf 'v20.11.1\\n'\nfi\nexit 0`,
|
||||
);
|
||||
|
||||
const result = spawnSync("bash", [scriptPath], {
|
||||
env: {
|
||||
...process.env,
|
||||
PATH: `${binDir}:${process.env.PATH || ""}`,
|
||||
AO_REPO_ROOT: fakeRepo,
|
||||
},
|
||||
encoding: "utf8",
|
||||
});
|
||||
|
||||
const commands = readFileSync(commandLog, "utf8");
|
||||
rmSync(tempRoot, { recursive: true, force: true });
|
||||
|
||||
expect(result.status).toBe(0);
|
||||
expect(result.stdout).toContain("Already on latest version");
|
||||
// Rebuild commands should NOT have run
|
||||
expect(commands).not.toContain("pnpm install");
|
||||
expect(commands).not.toContain("pnpm --filter @aoagents/ao-core build");
|
||||
expect(commands).not.toContain("npm link");
|
||||
expect(commands).not.toContain("git pull --ff-only origin main");
|
||||
// Smoke tests SHOULD still have run
|
||||
expect(commands).toContain(
|
||||
`node ${join(fakeRepo, "packages", "ao", "bin", "ao.js")} --version`,
|
||||
);
|
||||
expect(commands).toContain(
|
||||
`node ${join(fakeRepo, "packages", "ao", "bin", "ao.js")} doctor --help`,
|
||||
);
|
||||
});
|
||||
|
||||
it("rejects conflicting smoke flags in the script", () => {
|
||||
const result = spawnSync("bash", [scriptPath, "--skip-smoke", "--smoke-only"], {
|
||||
encoding: "utf8",
|
||||
|
|
@ -262,6 +335,8 @@ exit 0`,
|
|||
fi
|
||||
;;
|
||||
"branch --show-current") printf "main\\n" ;;
|
||||
"rev-parse HEAD") printf "oldsha000\\n" ;;
|
||||
"rev-parse origin/main") printf "newsha111\\n" ;;
|
||||
"pull --ff-only origin main") touch ${JSON.stringify(join(tempRoot, "post-dirty"))} ;;
|
||||
esac
|
||||
exit 0`,
|
||||
|
|
|
|||
|
|
@ -177,32 +177,39 @@ if [ "$SMOKE_ONLY" = false ]; then
|
|||
maybe_sync_origin_with_upstream
|
||||
|
||||
run_cmd git fetch "$UPDATE_REMOTE" "$TARGET_BRANCH"
|
||||
run_cmd git pull --ff-only "$UPDATE_REMOTE" "$TARGET_BRANCH"
|
||||
run_cmd pnpm install
|
||||
|
||||
run_cmd pnpm --filter @aoagents/ao-core clean
|
||||
run_cmd pnpm --filter @aoagents/ao-cli clean
|
||||
run_cmd pnpm --filter @aoagents/ao-web clean
|
||||
local_sha="$(git rev-parse HEAD)"
|
||||
remote_sha="$(git rev-parse "$UPDATE_REMOTE/$TARGET_BRANCH")"
|
||||
if [ "$local_sha" = "$remote_sha" ]; then
|
||||
printf '\nAlready on latest version.\n'
|
||||
else
|
||||
run_cmd git pull --ff-only "$UPDATE_REMOTE" "$TARGET_BRANCH"
|
||||
run_cmd pnpm install
|
||||
|
||||
run_cmd pnpm --filter @aoagents/ao-core build
|
||||
run_cmd pnpm --filter @aoagents/ao-cli build
|
||||
run_cmd pnpm --filter @aoagents/ao-web build
|
||||
run_cmd pnpm --filter @aoagents/ao-core clean
|
||||
run_cmd pnpm --filter @aoagents/ao-cli clean
|
||||
run_cmd pnpm --filter @aoagents/ao-web clean
|
||||
|
||||
printf '\nRefreshing ao launcher...\n'
|
||||
(
|
||||
cd "$REPO_ROOT/packages/ao"
|
||||
if npm link 2>/dev/null; then
|
||||
:
|
||||
elif [ -t 0 ]; then
|
||||
printf ' Permission denied. Retrying with sudo...\n'
|
||||
sudo npm link
|
||||
else
|
||||
printf 'ERROR: Permission denied. Run manually: cd %s/packages/ao && sudo npm link\n' "$REPO_ROOT"
|
||||
exit 1
|
||||
fi
|
||||
)
|
||||
run_cmd pnpm --filter @aoagents/ao-core build
|
||||
run_cmd pnpm --filter @aoagents/ao-cli build
|
||||
run_cmd pnpm --filter @aoagents/ao-web build
|
||||
|
||||
ensure_repo_clean "Update modified tracked files. Inspect git status, review the changes, and rerun after restoring a clean checkout if needed."
|
||||
printf '\nRefreshing ao launcher...\n'
|
||||
(
|
||||
cd "$REPO_ROOT/packages/ao"
|
||||
if npm link 2>/dev/null; then
|
||||
:
|
||||
elif [ -t 0 ]; then
|
||||
printf ' Permission denied. Retrying with sudo...\n'
|
||||
sudo npm link
|
||||
else
|
||||
printf 'ERROR: Permission denied. Run manually: cd %s/packages/ao && sudo npm link\n' "$REPO_ROOT"
|
||||
exit 1
|
||||
fi
|
||||
)
|
||||
|
||||
ensure_repo_clean "Update modified tracked files. Inspect git status, review the changes, and rerun after restoring a clean checkout if needed."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$SKIP_SMOKE" = false ]; then
|
||||
|
|
|
|||
Loading…
Reference in New Issue