release: git-arboretum 3.3.0 (« Démarrer le projet » : lancement multi-terminaux), vscode 0.4.0, desktop 0.1.3
All checks were successful
CI / Build & test (Node 22) (push) Successful in 10m17s
CI / Build & test (Node 24) (push) Successful in 10m13s
CI / No em/en dashes (push) Successful in 4s
Deploy site (production) / build-and-deploy (push) Successful in 24s
Release / Publish to Gitea npm registry (push) Successful in 10m17s
VSCode Release / Package VSIX (push) Successful in 9m39s
Desktop Release / Build Linux (AppImage + deb) (push) Successful in 15m41s
CI / Pack & boot smoke (Node 22) (push) Successful in 10m3s
All checks were successful
CI / Build & test (Node 22) (push) Successful in 10m17s
CI / Build & test (Node 24) (push) Successful in 10m13s
CI / No em/en dashes (push) Successful in 4s
Deploy site (production) / build-and-deploy (push) Successful in 24s
Release / Publish to Gitea npm registry (push) Successful in 10m17s
VSCode Release / Package VSIX (push) Successful in 9m39s
Desktop Release / Build Linux (AppImage + deb) (push) Successful in 15m41s
CI / Pack & boot smoke (Node 22) (push) Successful in 10m3s
« Démarrer le projet » : un repo définit une fois ses commandes de démarrage (serveur de dev, API, base de données), un clic ouvre un terminal PTY par commande dans le dock IDE. Serveur (additif, PROTOCOL_VERSION inchangé) : - LaunchCommand[] persistées sur repos.launch_commands (migration 13) ; champ additif SessionSummary.launchRunId. - POST /repos/:id/launch : résolution du worktree côté serveur, cwd de commande borné (anti-traversal), commandIds outrepasse enabled. - GET /repos/:id/launch/detect : détection package.json / Procfile / docker-compose. - Shell de login interactif ($SHELL -l -i, charge le PATH nvm/asdf) + auto-type de la commande ; le shell survit à la commande (échec visible). Web : LaunchProjectModal + actions (ProjectTreeNode, SessionsPanel, CommandPalette), stores sessions/worktrees, i18n EN/FR. Alignement du reste du projet : - Extension VS Code 0.4.0 : commande Start Project (repo/worktree), Stop Launch, badge « launch » dans l'arbre, méthode REST startLaunch. - Site vitrine : 16e feature card (Rocket) + section showcase « Start the project » (mockup fidèle au modal), i18n EN/FR. - Documentation : README (EN + FR), help-content (EN + FR), CHANGELOGs server + vscode. Vérifié : 430 tests, typecheck, build (web + site + vscode), acceptance-p13 ALL GREEN, VSIX packagé, garde anti-tirets, vérif visuelle du site (thèmes clair et sombre).
This commit is contained in:
55
packages/server/test/launch-detect.test.ts
Normal file
55
packages/server/test/launch-detect.test.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { afterAll, describe, expect, it } from 'vitest';
|
||||
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import { detectLaunchCommands } from '../src/core/launch-detect.js';
|
||||
|
||||
const tmp = mkdtempSync(join(tmpdir(), 'launch-detect-'));
|
||||
afterAll(() => rmSync(tmp, { recursive: true, force: true }));
|
||||
|
||||
function fixture(name: string, files: Record<string, string>): string {
|
||||
const dir = join(tmp, name);
|
||||
mkdirSync(dir, { recursive: true });
|
||||
for (const [f, content] of Object.entries(files)) writeFileSync(join(dir, f), content);
|
||||
return dir;
|
||||
}
|
||||
|
||||
describe('detectLaunchCommands', () => {
|
||||
it('extrait les scripts npm (par défaut : npm run), active les scripts de dev', () => {
|
||||
const dir = fixture('npm', {
|
||||
'package.json': JSON.stringify({ scripts: { dev: 'vite', build: 'vite build', 'test:unit': 'vitest' } }),
|
||||
});
|
||||
const cmds = detectLaunchCommands(dir);
|
||||
const dev = cmds.find((c) => c.run === 'npm run dev');
|
||||
const build = cmds.find((c) => c.run === 'npm run build');
|
||||
expect(dev?.enabled).toBe(true); // heuristique : dev/start/serve/watch activés
|
||||
expect(build?.enabled).toBe(false);
|
||||
expect(cmds.some((c) => c.run === 'npm run test:unit')).toBe(true);
|
||||
});
|
||||
|
||||
it('utilise pnpm/yarn selon le lockfile présent', () => {
|
||||
const pnpm = fixture('pnpm', { 'package.json': JSON.stringify({ scripts: { dev: 'x' } }), 'pnpm-lock.yaml': '' });
|
||||
expect(detectLaunchCommands(pnpm).find((c) => c.label === 'dev')?.run).toBe('pnpm run dev');
|
||||
const yarn = fixture('yarn', { 'package.json': JSON.stringify({ scripts: { dev: 'x' } }), 'yarn.lock': '' });
|
||||
expect(detectLaunchCommands(yarn).find((c) => c.label === 'dev')?.run).toBe('yarn dev');
|
||||
});
|
||||
|
||||
it('lit le Procfile (name: command), toutes activées', () => {
|
||||
const dir = fixture('proc', { Procfile: 'web: bundle exec puma\nworker: rake jobs:work\n# comment\n' });
|
||||
const cmds = detectLaunchCommands(dir);
|
||||
expect(cmds.find((c) => c.label === 'web')?.run).toBe('bundle exec puma');
|
||||
expect(cmds.find((c) => c.label === 'worker')?.enabled).toBe(true);
|
||||
expect(cmds).toHaveLength(2); // la ligne de commentaire est ignorée
|
||||
});
|
||||
|
||||
it('suggère docker compose up si un fichier compose est présent', () => {
|
||||
const dir = fixture('compose', { 'compose.yaml': 'services: {}' });
|
||||
expect(detectLaunchCommands(dir).some((c) => c.run === 'docker compose up')).toBe(true);
|
||||
});
|
||||
|
||||
it('tolère un répertoire vide ou un package.json invalide', () => {
|
||||
expect(detectLaunchCommands(join(tmp, 'inexistant'))).toEqual([]);
|
||||
const bad = fixture('bad', { 'package.json': '{ not json' });
|
||||
expect(detectLaunchCommands(bad)).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user