mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-04-25 00:16:29 +02:00
docs: Add comprehensive end-to-end testing guide for GitHub Copilot
- Add step-by-step testing procedures for all components - Include manual Device Flow authentication testing - Add LLM provider testing examples - Include token storage and refresh verification - Add model discovery and disconnection tests - Provide troubleshooting guide - Add security notes and best practices
This commit is contained in:
parent
c240e13646
commit
e1e6fa92e8
1 changed files with 280 additions and 0 deletions
280
GITHUB_COPILOT_E2E_TESTING.md
Normal file
280
GITHUB_COPILOT_E2E_TESTING.md
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
# GitHub Copilot Integration - End-to-End Testing Guide
|
||||
|
||||
Este documento describe cómo realizar pruebas end-to-end completas de la integración de GitHub Copilot en Rowboat.
|
||||
|
||||
## Requisitos Previos
|
||||
|
||||
- Rowboat compilado y funcionando (`npm run deps` sin errores)
|
||||
- Cuenta de GitHub activa
|
||||
- Acceso a GitHub Copilot (Student, Pro, o Enterprise)
|
||||
|
||||
## Test 1: Verificar Compilación
|
||||
|
||||
```bash
|
||||
cd /home/wilber/rowboat/apps/x
|
||||
|
||||
# Compilar todas las dependencias
|
||||
npm run deps
|
||||
|
||||
# Verificar que no hay errores de TypeScript
|
||||
npm run lint
|
||||
|
||||
# Expected output:
|
||||
# ✓ shared compiled successfully
|
||||
# ✓ core compiled successfully
|
||||
# ✓ preload compiled successfully
|
||||
```
|
||||
|
||||
## Test 2: Verificar Tests Unitarios
|
||||
|
||||
```bash
|
||||
# Ejecutar tests de GitHub Copilot
|
||||
npm test -- github-copilot.test.ts
|
||||
|
||||
# Expected output:
|
||||
# ✓ GitHub Copilot Device Flow
|
||||
# ✓ requestDeviceCode
|
||||
# ✓ pollForToken
|
||||
# ✓ startGitHubCopilotAuth
|
||||
# ✓ OAuthTokens validation
|
||||
# ✓ GitHub Copilot Models
|
||||
# ✓ Model availability
|
||||
# ✓ Model constants
|
||||
#
|
||||
# Tests: 25+ passed
|
||||
```
|
||||
|
||||
## Test 3: Device Flow Authentication (Manual)
|
||||
|
||||
### Paso 1: Crear un script de prueba
|
||||
|
||||
Crea `/tmp/test-github-copilot-auth.ts`:
|
||||
|
||||
```typescript
|
||||
import container from '@x/core/di/container';
|
||||
import { startGitHubCopilotAuthentication, isGitHubCopilotAuthenticated, getGitHubCopilotAuthStatus } from '@x/core/auth/github-copilot-auth';
|
||||
|
||||
async function testAuth() {
|
||||
console.log('Starting GitHub Copilot authentication test...\n');
|
||||
|
||||
// Paso 1: Iniciar autenticación
|
||||
console.log('1️⃣ Iniciando Device Flow...');
|
||||
const { userCode, verificationUri, tokenPromise } = await startGitHubCopilotAuthentication();
|
||||
|
||||
console.log(`\n📱 Código de dispositivo: ${userCode}`);
|
||||
console.log(`🔗 Visita: ${verificationUri}`);
|
||||
console.log('\n⏳ Esperando autorización... (timeout en 15 minutos)\n');
|
||||
|
||||
try {
|
||||
// Paso 2: Esperar autenticación
|
||||
await tokenPromise;
|
||||
console.log('✅ ¡Autenticado exitosamente!\n');
|
||||
|
||||
// Paso 3: Verificar estado
|
||||
const authenticated = await isGitHubCopilotAuthenticated();
|
||||
console.log(`2️⃣ ¿Autenticado? ${authenticated ? '✅ Sí' : '❌ No'}`);
|
||||
|
||||
const status = await getGitHubCopilotAuthStatus();
|
||||
console.log(`3️⃣ Estado:`, JSON.stringify(status, null, 2));
|
||||
|
||||
console.log('\n✨ Test completo exitosamente');
|
||||
} catch (error) {
|
||||
console.error('\n❌ Error:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
testAuth();
|
||||
```
|
||||
|
||||
### Paso 2: Ejecutar el test
|
||||
|
||||
```bash
|
||||
cd /home/wilber/rowboat/apps/x
|
||||
npx ts-node /tmp/test-github-copilot-auth.ts
|
||||
|
||||
# Expected output:
|
||||
# 1️⃣ Iniciando Device Flow...
|
||||
#
|
||||
# 📱 Código de dispositivo: ABCD-1234
|
||||
# 🔗 Visita: https://github.com/login/device
|
||||
#
|
||||
# ⏳ Esperando autorización... (timeout en 15 minutos)
|
||||
#
|
||||
# (Usuario visita GitHub, ingresa código ABCD-1234)
|
||||
#
|
||||
# ✅ ¡Autenticado exitosamente!
|
||||
#
|
||||
# 2️⃣ ¿Autenticado? ✅ Sí
|
||||
# 3️⃣ Estado: {
|
||||
# "authenticated": true,
|
||||
# "expiresAt": 1234567890
|
||||
# }
|
||||
#
|
||||
# ✨ Test completo exitosamente
|
||||
```
|
||||
|
||||
## Test 4: Crear proveedor LLM
|
||||
|
||||
```typescript
|
||||
import { createProvider } from '@x/core/models/models';
|
||||
import { generateText } from 'ai';
|
||||
|
||||
async function testLLM() {
|
||||
console.log('Testing GitHub Copilot LLM...\n');
|
||||
|
||||
// Crear proveedor
|
||||
console.log('1️⃣ Creando proveedor GitHub Copilot...');
|
||||
const config = {
|
||||
flavor: 'github-copilot' as const,
|
||||
};
|
||||
const provider = await createProvider(config);
|
||||
console.log('✅ Proveedor creado\n');
|
||||
|
||||
// Crear modelo
|
||||
console.log('2️⃣ Creando modelo gpt-4o...');
|
||||
const model = provider.languageModel('gpt-4o');
|
||||
console.log('✅ Modelo creado\n');
|
||||
|
||||
// Generar texto
|
||||
console.log('3️⃣ Enviando prompt a GitHub Copilot...');
|
||||
const response = await generateText({
|
||||
model,
|
||||
prompt: 'Say hello in Spanish',
|
||||
});
|
||||
console.log('✅ Respuesta recibida:\n');
|
||||
console.log(response.text);
|
||||
}
|
||||
|
||||
testLLM();
|
||||
```
|
||||
|
||||
## Test 5: Verificar Almacenamiento de Tokens
|
||||
|
||||
```bash
|
||||
# Ver tokens guardados
|
||||
cat ~/.rowboat/config/oauth.json | jq '.providers."github-copilot"'
|
||||
|
||||
# Expected output:
|
||||
# {
|
||||
# "tokens": {
|
||||
# "access_token": "ghu_...",
|
||||
# "refresh_token": null,
|
||||
# "expires_at": 1234567890,
|
||||
# "token_type": "Bearer",
|
||||
# "scopes": ["read:user", "user:email", "gist"]
|
||||
# },
|
||||
# "clientId": "Iv1.b507a08c87ecfe98"
|
||||
# }
|
||||
```
|
||||
|
||||
## Test 6: Probar Refresh de Tokens
|
||||
|
||||
```typescript
|
||||
import { getGitHubCopilotAccessToken } from '@x/core/auth/github-copilot-auth';
|
||||
import * as oauthClient from '@x/core/auth/oauth-client';
|
||||
|
||||
async function testTokenRefresh() {
|
||||
console.log('Testing token refresh...\n');
|
||||
|
||||
// Obtener token actual
|
||||
console.log('1️⃣ Obteniendo token de acceso...');
|
||||
const token = await getGitHubCopilotAccessToken();
|
||||
console.log(`✅ Token: ${token.substring(0, 20)}...\n`);
|
||||
|
||||
// Verificar expiración
|
||||
console.log('2️⃣ Verificando expiración...');
|
||||
const connection = await container.resolve('oauthRepo').read('github-copilot');
|
||||
if (connection.tokens) {
|
||||
const expiresIn = connection.tokens.expires_at - Math.floor(Date.now() / 1000);
|
||||
console.log(`✅ Token expira en: ${expiresIn} segundos`);
|
||||
if (expiresIn > 3600) {
|
||||
console.log(' (Aún es válido por más de 1 hora)\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testTokenRefresh();
|
||||
```
|
||||
|
||||
## Test 7: Listar Modelos Disponibles
|
||||
|
||||
```typescript
|
||||
import { getAvailableGitHubCopilotModels } from '@x/core/auth/github-copilot-models';
|
||||
|
||||
async function testModels() {
|
||||
console.log('Modelos disponibles en GitHub Copilot:\n');
|
||||
|
||||
const models = await getAvailableGitHubCopilotModels();
|
||||
models.forEach((model, i) => {
|
||||
console.log(`${i + 1}. ${model}`);
|
||||
});
|
||||
}
|
||||
|
||||
testModels();
|
||||
```
|
||||
|
||||
## Test 8: Desconectar GitHub Copilot
|
||||
|
||||
```typescript
|
||||
import { disconnectGitHubCopilot, isGitHubCopilotAuthenticated } from '@x/core/auth/github-copilot-auth';
|
||||
|
||||
async function testDisconnect() {
|
||||
console.log('Desconectando GitHub Copilot...\n');
|
||||
|
||||
console.log('1️⃣ Estado antes: ', await isGitHubCopilotAuthenticated());
|
||||
|
||||
await disconnectGitHubCopilot();
|
||||
|
||||
console.log('2️⃣ Estado después: ', await isGitHubCopilotAuthenticated());
|
||||
|
||||
console.log('\n✅ Desconectado correctamente');
|
||||
}
|
||||
|
||||
testDisconnect();
|
||||
```
|
||||
|
||||
## Verificación de Checklist
|
||||
|
||||
- [ ] Compilación exitosa sin errores TypeScript
|
||||
- [ ] Tests unitarios pasan (25+ casos)
|
||||
- [ ] Device Flow funciona y abre el navegador
|
||||
- [ ] Usuario puede completar autenticación en GitHub
|
||||
- [ ] Tokens se guardan en `~/.rowboat/config/oauth.json`
|
||||
- [ ] Proveedor LLM se crea correctamente
|
||||
- [ ] Modelo responde a prompts
|
||||
- [ ] Token se actualiza automáticamente si expira
|
||||
- [ ] Tokens se eliminan al desconectar
|
||||
- [ ] Modelos disponibles se listan correctamente
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Error: "GitHub Copilot not authenticated"
|
||||
- Ejecutar Device Flow nuevamente: `startGitHubCopilotAuthentication()`
|
||||
- Verificar que tokens existen: `cat ~/.rowboat/config/oauth.json`
|
||||
|
||||
### Error: "Token expired"
|
||||
- El sistema debería intentar refresh automático
|
||||
- Si falla, ejecutar Device Flow nuevamente
|
||||
|
||||
### Error: "Cannot reach API"
|
||||
- Verificar conexión a internet
|
||||
- Verificar que `https://models.github.com/api/openai/` es accesible
|
||||
- Verificar que token es válido: `npm run test -- github-copilot`
|
||||
|
||||
### Error: "Model not found"
|
||||
- Verificar que el modelo está disponible en tu plan
|
||||
- Usar `gpt-4o` como fallback
|
||||
|
||||
## Recursos Adicionales
|
||||
|
||||
- [GITHUB_COPILOT_INTEGRATION.md](./GITHUB_COPILOT_INTEGRATION.md) - Documentación técnica completa
|
||||
- [RFC 8628](https://tools.ietf.org/html/rfc8628) - Device Flow OAuth spec
|
||||
- [GitHub Copilot Docs](https://docs.github.com/en/copilot) - Documentación oficial
|
||||
|
||||
## Notas de Seguridad
|
||||
|
||||
- **Nunca** compartas tu código de dispositivo
|
||||
- Los tokens se almacenan en `~/.rowboat/config/oauth.json` - asegúrate de que los permisos son correctos
|
||||
- Desconecta cuando no uses GitHub Copilot
|
||||
- Los tokens expiran automáticamente (generalmente en 8 horas)
|
||||
Loading…
Add table
Add a link
Reference in a new issue