mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 18:39:33 +01:00
merge feat/no-admin-install into the graphical installer branch
The graphical install runs install.sh --no-admin, so this branch needs both PR #763 (the app) and PR #768 (the route that needs no password). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
ed74ae41bc
16 files changed
+1466
-78
No files matched your search
+4
-1
@@ -31,8 +31,11 @@ export type SupervisorKind = 'systemd' | 'launchd' | 'launchd-daemon' | 'docker-
|
||||
* How Codeman was installed. `git` and `docker-compose` can self-update in
|
||||
* place; `docker-compose` is a git checkout bind-mounted into the container, so
|
||||
* the pull/build happen on the host filesystem and survive container recreation.
|
||||
* `archive` is what `install.sh` leaves on a machine with no working git (its
|
||||
* no-admin route): the source unpacked from an archive, with nothing for the
|
||||
* in-app updater to pull into, so it updates by re-running the installer.
|
||||
*/
|
||||
export type InstallKind = 'git' | 'docker-compose' | 'npm' | 'unknown';
|
||||
export type InstallKind = 'git' | 'docker-compose' | 'npm' | 'archive' | 'unknown';
|
||||
|
||||
/**
|
||||
* Why an in-place container update is refused. Each is derived mechanically from
|
||||
|
||||
@@ -1940,10 +1940,14 @@ Object.assign(CodemanApp.prototype, {
|
||||
// `docker-compose` self-updates in place like `git` does — the container
|
||||
// restarts itself. Anything else cannot.
|
||||
if (data.installKind && data.installKind !== 'git' && data.installKind !== 'docker-compose') {
|
||||
// `archive` = installed by install.sh on a machine with no working git: the
|
||||
// installer replaces it with a fresh build, so point there, not at npm.
|
||||
const hint =
|
||||
data.supervisor === 'docker-compose'
|
||||
? 'Update from the Docker host with <code>docker/Start-Codeman.sh</code>.'
|
||||
: 'Update with <code>npm i -g aicodeman@latest</code>.';
|
||||
: data.installKind === 'archive'
|
||||
? 'It was installed without git. Re-run the installer to update: <code>curl -fsSL https://getcodeman.com/install | bash</code>'
|
||||
: 'Update with <code>npm i -g aicodeman@latest</code>.';
|
||||
this._setUpdateResult(`This install can't update itself (${escapeHtml(data.installKind)}). ${hint}`);
|
||||
return;
|
||||
}
|
||||
|
||||
+21
-3
@@ -462,12 +462,26 @@ export function isRunningInContainer(): boolean {
|
||||
return process.env.CODEMAN_IN_CONTAINER === '1' || existsSync('/.dockerenv');
|
||||
}
|
||||
|
||||
function detectInstallKind(dir: string): InstallKind {
|
||||
/**
|
||||
* Marker `install.sh` writes into an install directory whose source came from an
|
||||
* archive instead of a git clone (`SOURCE_MARKER` there; the two names are pinned
|
||||
* to each other by `test/install-sh-invariants.test.ts`).
|
||||
*/
|
||||
export const ARCHIVE_INSTALL_MARKER = '.install-source';
|
||||
|
||||
/** How an `archive` install updates: the installer replaces it with a fresh build. */
|
||||
export const ARCHIVE_UPDATE_HINT =
|
||||
'This install has no git checkout, so it cannot update in place. Re-run the installer to update: ' +
|
||||
'curl -fsSL https://getcodeman.com/install | bash';
|
||||
|
||||
export function detectInstallKind(dir: string): InstallKind {
|
||||
// A container whose code is a bind-mounted checkout updates in place (the pull
|
||||
// and build land on the host filesystem and survive container recreation). A
|
||||
// container WITHOUT that mount runs a baked image copy — a pull there would go
|
||||
// to the writable layer and vanish on the next `up`, so it is not updatable.
|
||||
if (existsSync(join(dir, '.git'))) return isRunningInContainer() ? 'docker-compose' : 'git';
|
||||
// install.sh on a machine with no working git: the source from an archive.
|
||||
if (existsSync(join(dir, ARCHIVE_INSTALL_MARKER))) return 'archive';
|
||||
// Global npm install ships only dist/ (no src/, no .git).
|
||||
if (!existsSync(join(dir, 'src'))) return 'npm';
|
||||
return 'unknown';
|
||||
@@ -705,7 +719,9 @@ export async function checkForUpdate(): Promise<UpdateCheckResult> {
|
||||
error:
|
||||
info.installKind === 'unknown' && isRunningInContainer()
|
||||
? 'This container runs a baked image copy with no repository mounted — self-update is unavailable. See docs/docker-self-update.md.'
|
||||
: 'Not a git install — self-update is unavailable.',
|
||||
: info.installKind === 'archive'
|
||||
? ARCHIVE_UPDATE_HINT
|
||||
: 'Not a git install — self-update is unavailable.',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -829,7 +845,9 @@ export async function startUpdate(): Promise<StartUpdateResult> {
|
||||
code: 'not-git',
|
||||
message: isRunningInContainer()
|
||||
? 'This container has no repository mounted. Update from the host with docker/Start-Codeman.sh.'
|
||||
: 'This is not a git install. Update with: npm i -g aicodeman@latest',
|
||||
: info.installKind === 'archive'
|
||||
? ARCHIVE_UPDATE_HINT
|
||||
: 'This is not a git install. Update with: npm i -g aicodeman@latest',
|
||||
};
|
||||
}
|
||||
const existing = readCurrentUpdateStatus();
|
||||
|
||||
Reference in new issue
Block a user