mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-27 10:46:51 +00:00
feat(onboarding): add first-run environment checker (#1290)
* feat(onboarding): add first-run environment checker Add a preflight that checks whether the host can run Docker deploys before a deploy fails for an avoidable reason. It verifies the Docker engine is reachable and permitted, the Compose plugin is present, the compose directory is writable and mounted at a matching host path, the dashboard is behind TLS, and the compose volume has disk headroom. Each result that needs attention carries a specific fix rather than a generic error, and the checks never block: an operator who knows their setup can continue. The checks run as the final step of first-boot setup and can be re-run any time from the Recovery settings tab. A new admin-only endpoint, GET /api/diagnostics/environment, backs both surfaces. * fix(onboarding): distinguish unverified path mapping and support parent binds Treat a container whose self-inspect fails as an unverified path-mapping warning instead of a false "not containerized" pass, so an unverifiable mapping never reads as healthy. Resolve the compose directory through the longest-prefix bind mount and compare the host path it resolves to, so a parent bind such as -v /opt:/opt correctly covers COMPOSE_DIR=/opt/compose instead of warning that the directory is not bind-mounted. * test(e2e): advance the setup wizard past the environment step in loginAs The first-run setup helper clicked "Initialize console" and immediately waited for the dashboard, but setup now shows an environment-preflight step before landing the console. Click "Enter Sencho" to complete onboarding before asserting the dashboard, so the first test on a fresh instance passes.
This commit is contained in:
@@ -6,6 +6,7 @@ import { ArrowRight, Loader2 } from 'lucide-react';
|
||||
import { AuthCanvas } from '@/components/auth/AuthCanvas';
|
||||
import { AuthStepHeader } from '@/components/auth/AuthStepHeader';
|
||||
import { ErrorRail } from '@/components/auth/ErrorRail';
|
||||
import { EnvironmentChecks } from '@/components/settings/EnvironmentChecks';
|
||||
|
||||
interface SetupProps {
|
||||
onComplete: () => void;
|
||||
@@ -34,6 +35,10 @@ export function Setup({ onComplete, className, ...props }: SetupProps & React.Co
|
||||
const [confirmPassword, setConfirmPassword] = useState('');
|
||||
const [error, setError] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
// The admin account is created in step 1; /api/auth/setup signs the operator
|
||||
// in (session cookie), so step 2 can run the admin-gated environment checks
|
||||
// before handing off to the console.
|
||||
const [step, setStep] = useState<'account' | 'env'>('account');
|
||||
|
||||
const strength = gaugePassword(password);
|
||||
const strengthClass =
|
||||
@@ -72,7 +77,7 @@ export function Setup({ onComplete, className, ...props }: SetupProps & React.Co
|
||||
});
|
||||
const data = await response.json();
|
||||
if (response.ok && data.success) {
|
||||
onComplete();
|
||||
setStep('env');
|
||||
} else {
|
||||
setError(data.error || 'Setup failed');
|
||||
}
|
||||
@@ -83,6 +88,37 @@ export function Setup({ onComplete, className, ...props }: SetupProps & React.Co
|
||||
}
|
||||
};
|
||||
|
||||
if (step === 'env') {
|
||||
return (
|
||||
<div className={cn('relative', className)} {...props}>
|
||||
<AuthCanvas
|
||||
footer={
|
||||
<div className="flex items-center justify-between">
|
||||
<span>Console · First boot</span>
|
||||
<span className="text-stat-subtitle/70">Account ready</span>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className="flex flex-col gap-7">
|
||||
<AuthStepHeader
|
||||
kicker="SENCHO · ENVIRONMENT"
|
||||
hero="Preflight"
|
||||
caption="A quick check that this host can run Docker deploys. Warnings won't stop you; each one carries a fix."
|
||||
/>
|
||||
<EnvironmentChecks />
|
||||
<Button
|
||||
type="button"
|
||||
onClick={onComplete}
|
||||
className="h-11 w-full bg-brand text-brand-foreground shadow-btn-glow hover:bg-brand/90"
|
||||
>
|
||||
Enter Sencho<ArrowRight strokeWidth={1.5} />
|
||||
</Button>
|
||||
</div>
|
||||
</AuthCanvas>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cn('relative', className)} {...props}>
|
||||
<AuthCanvas
|
||||
|
||||
Reference in New Issue
Block a user