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