Configuración del entorno de desarrollo
Esta página lo guiará para configurar un omegaUp local completo (frontend, PHP API, MySQL y Go Grader/runner/gitserver) en su propia máquina con Docker. Toda la pila reside en un puñado de contenedores descritos por docker-compose.yml, por lo que no instala PHP 8.1, MySQL 8.0, Redis o RabbitMQ a mano; extraes imágenes prediseñadas y las abres. Ahora preferimos Docker para todos: la antigua máquina virtual Vagrant/VirtualBox suministrada desde omegaup/deploy está obsoleta y ya no es la ruta admitida, por lo que si encuentra una página wiki que le indique que debe ir a vagrant up, omítala.
Videotutorial
Si prefiere mirar que leer, tenemos un videotutorial que explica la misma configuración de principio a fin.
Requisitos previos
Antes que nada, instale las dos piezas de herramientas Docker y Git:
- Docker Engine — instalarlo. Esto es lo que realmente hace funcionar los contenedores.
- Docker Compose v2 — instalar el complemento. Redactar es lo que dice
docker-compose.ymly reúne toda la pila. Si todavía estás en Compose v1, puedes migrar a v2; Tanto la ortografíadocker compose(espacio) comodocker-compose(guión) funcionan y esta guía las usa indistintamente. - Git: para clonar el repositorio y porque todo el flujo de trabajo de contribución se basa en él.
¿Nuevo en Git?
Si aún no está seguro de Git, lea este tutorial de Git antes de comenzar. Todo lo que ocurre después del clon (ramificaciones, solicitudes de extracción, mantener sincronizado a main) supone que puedes moverte en Git cómodamente.
Linux: añádete al grupo docker
En Linux, ejecute esto una vez para poder invocar docker sin sudo:
sudo usermod -a -G docker $USER
sudo docker compose up, el árbol del proyecto montado en enlace termina siendo propiedad de root, y el usuario no root del contenedor ya no puede escribir en él, lo que aparece más adelante como un desconcertante bucle de reinicio (consulte Mi entorno de desarrollo no aparece). Hágalo de la manera correcta una vez y evitará toda la clase de problema.
Windows: desarrollar dentro de WSL2
En Windows, ejecute todo a través de WSL2 con la integración WSL de Docker Desktop habilitada y, esta es la parte que soporta la carga, clone el repositorio en el sistema de archivos de Linux (en algún lugar debajo de su inicio WSL, por ejemplo, ~/omegaup), no bajo /mnt/c/.... Los montajes de enlace de Docker que cruzan el límite de Windows↔Linux son lentos y, lo que es peor, el webpack --watch dentro del contenedor pierde silenciosamente eventos de cambio de archivos en /mnt/c, por lo que sus ediciones nunca desencadenan una reconstrucción y usted se queda mirando la salida obsoleta. Mantener el pago en el lado de Linux es el reemplazo moderno del antiguo baile de sincronización de archivos WinSCP/Xming de la era Vagrant.
Paso 1: Bifurcar y clonar
Primero bifurca omegaup/omegaup en GitHub (empujas a tu bifurcación, no al repositorio principal) y luego clonas tu bifurcación en un directorio vacío. La bandera --recurse-submodules es importante: varias dependencias de interfaz de terceros (pagedown para el editor Markdown, iso-3166-2.js para códigos de país, mathjax para renderizado matemático y más) viven en submódulos de Git, y la compilación se interrumpe sin ellos.
git clone --recurse-submodules https://github.com/YOURUSERNAME/omegaup
cd omegaup
--recurse-submodules, o un submódulo parece vacío, insértelo explícitamente desde la raíz del repositorio:
git submodule update --init --recursive
Paso 2: Abrir los contenedores
Desde la raíz del repositorio (omegaup/), extraiga las imágenes e inicie la pila:
docker-compose pull # only needed the first time, or when the next command complains
docker-compose up --no-build
pull toma las imágenes prediseñadas que Compose necesita: la interfaz PHP/nginx, MySQL 8.0, Redis, RabbitMQ y los servicios Go separados (omegaup/backend, omegaup/runner, omegaup/gitserver) que proporcionan el clasificador, el corredor y el almacenamiento de problemas. Sólo necesita volver a tirar cuando configura por primera vez o cuando docker-compose up se queja de que falta una imagen o está obsoleta. El indicador --no-build le indica a Compose que ejecute esas imágenes prediseñadas tal como están en lugar de reconstruirlas desde cero, que es lo que mantiene el inicio en minutos en lugar de una pausa para tomar café muy larga.
El primer arranque tarda entre 2 y 10 minutos. Después de esa espera, el contenedor de la interfaz ejecuta Webpack para compilar toda la interfaz de Vue 2.7 + TypeScript, MySQL se está inicializando y el calificador está esperando en la base de datos (wait-for-it mysql:13306). Lo que indica que realmente está listo es un volcado del módulo Webpack similar a este:
frontend_1 | Child frontend:
frontend_1 | 1550 modules
frontend_1 | Child HtmlWebpackCompiler:
frontend_1 | 1 module
frontend_1 | Child style:
frontend_1 | 1 module
frontend_1 | Child extract-text-webpack-plugin node_modules/extract-text-webpack-plugin/dist node_modules/css-loader/dist/cjs.js!node_modules/sass-loader/dist/cjs.js!frontend/www/sass/main.scss:
frontend_1 | 2 modules
frontend_1 | Child grader:
frontend_1 | 1131 modules
frontend_1 | Child vs/editor/editor:
frontend_1 | 36 modules
frontend_1 | Child vs/language/typescript/tsWorker:
frontend_1 | 41 modules
En ejecuciones posteriores, puede omitir el pull y simplemente iniciar la pila:
docker compose up --no-build
Paso 3: Abra su instancia local
Con los contenedores en funcionamiento, tu omegaUp local está en:
Ese es el puerto 8001, publicado desde el contenedor frontend en docker-compose.yml. Tenga en cuenta que es http simple; consulte la solución de redireccionamiento HTTPS del navegador si su navegador insiste en reescribirlo.
Paso 4: Obtenga un caparazón dentro del contenedor
Casi todos los comandos de desarrollo (ejecutar pruebas, invocar scripts stuff/, hurgar en la base de datos) se ejecutan dentro del contenedor frontend, porque ahí es donde realmente residen PHP 8.1, Node, Yarn y las herramientas. Abra un shell con cualquiera de estos (son equivalentes):
docker compose exec frontend /bin/bash
# or, by container name:
docker exec -it omegaup-frontend-1 /bin/bash
omegaup-frontend-1 (guiones), el docker-compose anterior usaba omegaup_frontend_1 (guiones bajos). Si no está seguro de cuál tiene, docker compose ps enumera los nombres reales. Dentro del contenedor, el código base está montado en /opt/omegaup: los mismos archivos que editas en tu host, por lo que un guardado en tu máquina es visible instantáneamente en el contenedor.
Cuentas de Desarrollo
Su nueva instalación viene con dos cuentas ya configuradas, por lo que puede iniciar sesión inmediatamente sin registrar nada:
omegaup/ contraseñaomegaup: un usuario con privilegios de administrador de sistemas. Úselo cuando necesite tocar la interfaz de usuario solo para administradores.user/ contraseñauser: un usuario normal y corriente, para probar la experiencia de usuario normal.
Además de eso, el conjunto de pruebas genera una lista estable de cuentas en las que puede iniciar sesión. La contraseña es siempre idéntica al nombre de usuario, lo que los hace fáciles de recordar:
| Nombre de usuario | Contraseña |
|---|---|
test_user_0 |
test_user_0 |
test_user_1 |
test_user_1 |
test_user_2 |
test_user_2 |
test_user_3 |
test_user_3 |
test_user_4 |
test_user_4 |
test_user_5 |
test_user_5 |
test_user_6 |
test_user_6 |
test_user_7 |
test_user_7 |
test_user_8 |
test_user_8 |
test_user_9 |
test_user_9 |
course_test_user_0 |
course_test_user_0 |
course_test_user_1 |
course_test_user_1 |
course_test_user_2 |
course_test_user_2 |
Siéntete libre de crear tantos usuarios como necesites para probar tus cambios. En el modo de desarrollo, la verificación de correo electrónico está desactivada, por lo que cualquier dirección ficticia funciona; nunca tendrás que revisar una bandeja de entrada para activar una cuenta.
Estructura de la base de código
El código omegaUp vive en /opt/omegaup dentro del contenedor (y en su clon en el host; es el mismo árbol montado en enlace). Estos son los directorios en los que trabajamos activamente en el día a día:
frontend/server/src/Controllers/: los controladores, con espacio de nombres\OmegaUp\Controllers, que contienen la lógica empresarial y exponen la API del servidor. Cada método estáticoapiXxxes un punto final API; por ejemplo,\OmegaUp\Controllers\Run::apiCreate(enRun.php) es lo que maneja un envío. Tenga en cuenta que la clase esRun, noRunController; los controladores omegaUp eliminan el sufijoController.frontend/server/src/DAO/: la capa de acceso a datos. Está dividido a propósito: las clases base abstractas generadas automáticamente enDAO/Base/llevan el SQL sin formato, los objetos de valor simples enDAO/VO/reflejan las filas de la base de datos y los contenedores escritos a mano directamente enDAO/agregan las consultas que los controladores realmente llaman. Editas los contenedores y los VO, no las bases generadas.frontend/server/src/: el resto de las bibliotecas y utilidades del servidor, incluidoApiCaller.php(el despachador de solicitudes) yGrader.php(el cliente HTTP ligero que se comunica con el evaluador Go).frontend/templates/: el shell HTML renderizado por el servidor más los archivos de internacionalización para inglés, español y portugués. Aquí hay una única plantilla,template.tpl, y a pesar de la extensión.tples Twig 3, no Smarty; Smarty ya no está. Sus etiquetas personalizadas ({% entrypoint %},{% jsInclude %}) se implementan mediante nuestras propias extensiones Twig enfrontend/server/src/Template/, y todo lo que hacen es iniciar una aplicación Vue y entregarle una carga útil JSON.frontend/www/: toda la aplicación orientada al navegador. La interfaz de usuario de cada página es un componente de archivo único de Vue 2.7; los componentes se encuentran bajofrontend/www/js/omegaup/components/, y el cliente API escrito (api.ts,api_types.ts) se genera a partir de los controladores PHP mediantefrontend/server/cmd/APITool.php; no edite manualmente esos dos, regénelos.
Una cosa que hace tropezar a la gente: el nivelador, corredor, emisora y minijail sandbox no están en este repositorio. Son servicios Go separados en github.com/omegaup/quark (y el almacenamiento de problemas se encuentra en github.com/omegaup/gitserver). Docker los ejecuta como archivos binarios prediseñados, y el backend de PHP solo habla con el evaluador a través de HTTP a través de \OmegaUp\Grader, en OMEGAUP_GRADER_URL (https://localhost:21680 predeterminado). Si está buscando un error de calificación, ese es el repositorio al que debe indicarle su editor, no este.
Para obtener un recorrido más profundo, consulte la Descripción general de la arquitectura y la Arquitectura frontend. El flujo de trabajo de solicitud de rama y extracción se encuentra en Contribuir.
Edición con Visual Studio Code
Puede editar en su host con Visual Studio Code mientras la pila sigue ejecutándose en Docker. Debido a que su clon está montado en /opt/omegaup, guardar en el host es guardar en el contenedor: la recarga en caliente y el paquete web dentro del contenedor lo recogen sin ningún paso de copia, que es exactamente la fricción que existía para solucionar la antigua configuración Vagrant-plus-WinSCP y ya no es necesaria.
Dos formas de trabajar, dependiendo de cuánto desee que las herramientas propias de VS Code (PHP IntelliSense, el terminal integrado, extensiones) se ejecuten en el sistema de archivos del contenedor:
- Edite en el host, ejecútelo en Docker. Simplemente abra su clon como una carpeta y edítelo normalmente. Camino más sencillo; tus partidas guardadas fluyen hacia el contenedor a través del soporte de enlace.
- Adjunte VS Code al contenedor en ejecución. Instale la extensión Dev Containers (o la extensión Docker). Con la pila arriba (
docker compose up --no-build), abra la paleta de comandos y seleccione Adjuntar al contenedor en ejecución, elija el contenedor de interfaz (llamadoomegaup-frontend-1; confirme condocker compose ps), luego Archivo → Abrir carpeta en/opt/omegaup. Ahora la terminal y los servidores de idiomas de VS Code se ejecutan dentro del contenedor, con el mismo PHP 8.1 y Nodo que usa la aplicación.
Agregue las extensiones PHP, Vue y ESLint según lo requieran los archivos que toque.
GitHub OAuth (local "Iniciar sesión con GitHub")
Para que el botón Iniciar sesión con GitHub funcione en http://localhost:8001/, registre una aplicación OAuth con GitHub y entregue sus credenciales a su configuración local.
1. Cree la aplicación OAuth en GitHub
Abra Configuración de desarrollador de GitHub, vaya a Aplicaciones OAuth → Nueva aplicación OAuth y configure:
- Nombre de la aplicación: cualquier cosa, p.e.
omegaUp local - URL de la página de inicio:
http://localhost:8001/ - URL de devolución de llamada de autorización:
http://localhost:8001/login?third_party_login=github
Regístrelo, copie el ID de cliente, luego genere y copie el Secreto de cliente: GitHub solo muestra el secreto una vez, así que consígalo ahora.
2. Configurar omegaUp localmente
Coloque las credenciales en frontend/server/config.php, el archivo de anulaciones locales (créelo si no existe). Este archivo es solo para su máquina: nunca lo confirme y nunca coloque secretos en el config.default.php controlado por versión.
<?php
define('OMEGAUP_GITHUB_CLIENT_ID', 'your_real_client_id_here');
define('OMEGAUP_GITHUB_CLIENT_SECRET', 'your_real_client_secret_here');
define surta efecto, pero si el botón permanece atenuado, reinicie el contenedor de interfaz una vez.
Nunca confirmes secretos de OAuth
Revierta o excluya config.php antes de enviarlo, y mantenga su ID de cliente/secreto en un administrador de contraseñas; si el contenedor se vuelve a crear y lleva config.php consigo, los querrá tener a mano. Si el botón de inicio de sesión permanece inactivo, la ID del cliente falta o es incorrecta en config.php; Si cambia de host o puerto, actualice la URL de devolución de llamada en la aplicación GitHub OAuth para que coincida, o la redirección fallará.
Consulte Seguridad → OAuth para saber cómo encaja el inicio de sesión de terceros en la plataforma.
Solución de problemas
Estos son los problemas que la gente realmente enfrenta, aproximadamente en el orden en que los enfrentan: primero el error sin procesar, luego lo que significa y luego la solución.
¡La aplicación web no muestra mis cambios!
Editó un archivo .vue o .ts, lo guardó, lo volvió a cargar y el navegador muestra el archivo anterior. La interfaz se sirve desde una compilación de paquete web, por lo que una edición no creada es invisible sin importar cuántas veces se actualice. Reconstrúyalo desde el interior del contenedor:
docker compose exec frontend /bin/bash
cd /opt/omegaup && yarn run dev
yarn run dev ejecuta Webpack una vez en el frontend; Si está iterando y no desea volver a ejecutarlo manualmente después de cada guardado, use yarn dev:watch en su lugar, que observa el árbol y lo reconstruye cuando cambia. (En Windows, esta es exactamente la razón por la que su pago debe residir en el sistema de archivos WSL2 de Linux y no en /mnt/c; el observador omite eventos de cambio a través de ese límite). Si aún no se actualiza después de una compilación exitosa, asegúrese de que los contenedores realmente se estén ejecutando (docker compose up --no-build) y, en su defecto, pregunte en nuestros canales de comunicación.
Mi entorno de desarrollo no aparece :(
Síntomas: los registros muestran Permission denied mientras se crea phpminiadmin o se escribe en stuff/venv/, el contenedor developer-environment sale y se reinicia en un bucle, y el sitio nunca funciona en http://localhost:8001.
Causa: el repositorio se clonó como raíz, o docker compose se ejecutó con sudo, por lo que el directorio del proyecto es propiedad de root. El montaje de enlace asigna su directorio de host a /opt/omegaup, y un árbol de propiedad raíz impide que el usuario no raíz del contenedor escriba en él, por lo que falla, muere y Compose lo reinicia para siempre.
Solución: no intentes "reparar" el árbol de propiedad raíz en su lugar; no vale la pena luchar. Como usuario normal, clone nuevamente en su directorio de inicio, asegúrese de haberse agregado al grupo docker (sudo usermod -a -G docker $USER, luego cierre sesión y vuelva a iniciarla) y ejecute docker compose sin sudo. Nunca sudo git clone.
Mi navegador sigue forzando HTTPS
Si su navegador reescribe http://localhost:8001 a https:// y luego no puede conectarse, ese es el comportamiento HSTS/HTTPS forzado del navegador, no omegaUp: la instancia local solo habla HTTP simple. Deshabilite la política HTTPS forzada para localhost siguiendo esta guía.
git push falla con un rastreo de MySQL
Cuando presiona, los enlaces de políticas de omegaUp ejecutan stuff/policy-tool.py, que necesita consultar la base de datos. En muchas máquinas, el primer impulso explota con un largo rastreo de Python que termina en:
Traceback (most recent call last):
File "/home/ubuntu/dev/omegaup/stuff/policy-tool.py", line 124, in <module>
main()
...
File "/home/ubuntu/dev/omegaup/stuff/database_utils.py", line 75, in mysql
return subprocess.check_output(args, universal_newlines=True)
...
FileNotFoundError: [Errno 2] No such file or directory: '/usr/bin/mysql'
error: failed to push some refs to 'https://github.com/user/omegaup'
FileNotFoundError: ... '/usr/bin/mysql' significa que no hay ningún binario de cliente mysql en la máquina que ejecuta el enlace. El problema: git push se ejecuta en su host, fuera del contenedor, por lo que aunque MySQL 8.0 se ejecuta felizmente en Docker, el host no tiene un cliente con quien hablar. Instale el cliente fuera del contenedor:
sudo apt-get install mysql-client
git push falla con "No se puede conectar al servidor MySQL local"
A veces, el cliente se instala pero la inserción aún falla, esta vez con un error de socket antes del mismo rastreo:
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
Traceback (most recent call last):
File "/home/ubuntu/dev/omegaup/stuff/policy-tool.py", line 124, in <module>
main()
...
subprocess.CalledProcessError: Command '['/usr/bin/mysql', '--user=root', '--password=omegaup', 'omegaup', '-NBe', 'SELECT COUNT(*) FROM `PrivacyStatements` WHERE ...']' returned non-zero exit status 1.
error: failed to push some refs to 'https://github.com/user/omegaup'
Can't connect ... through socket '/var/run/mysqld/mysqld.sock' es el regalo: el cliente está predeterminado en un socket Unix local, pero su MySQL no es local: está en un contenedor, al que solo se puede acceder a través de TCP en el puerto 13306 (publicado desde el contenedor en docker-compose.yml). La solución es entregarle al cliente host una configuración TCP que apunte a ese puerto, luego vincularlo simbólicamente como el .my.cnf predeterminado, el gancho dice:
cat > ~/.mysql.docker.cnf <<EOF
[client]
port=13306
host=127.0.0.1
protocol=tcp
user=root
password=omegaup
EOF
ln -sf ~/.mysql.docker.cnf .my.cnf
Un script stuff/ produce errores
Si ejecuta uno de los scripts stuff/ directamente en su host y obtiene el mismo rastreo de /usr/bin/mysql que se muestra arriba, la causa habitual es que lo ejecutó fuera del contenedor. La mayoría de esos scripts asumen el acceso a las herramientas y a la base de datos que solo existen dentro del contenedor frontend. Abra un shell en el contenedor (docker compose exec frontend /bin/bash) y ejecútelo allí. (Los enlaces git push anteriores son la excepción deliberada: estos se ejecutan en el host, por lo que necesitan el cliente MySQL del lado del host y la configuración TCP).
Faltan módulos de terceros
Si la compilación o las pruebas fallan debido a que faltan módulos en frontend/www/third_party/js/, sus submódulos no están desprotegidos. Tirarlos hacia adentro:
git submodule update --init --recursive
Errores de nodo/hilo después de realizar grandes cambios
Si Node o Yarn comienzan a arrojar errores justo después de generar un gran aumento de dependencia, la imagen de interfaz prediseñada puede no estar sincronizada con el nuevo package.json. Reconstrúyelo:
docker compose build frontend
docker compose up
docker compose build frontend
docker compose up
Si encuentra algo que no se cubre aquí, presente un problema en omegaup/deploy/issues con sus pasos de reproducción y el mensaje de error exacto; el texto de error es lo que nos permite relacionar su síntoma con uno conocido.
Próximos pasos
- Más información sobre cómo contribuir: sucursales, controles remotos y envío de una solicitud de extracción.
- Revise las pautas de codificación: las convenciones que respetamos el código.
- Explora la arquitectura: cómo encajan las piezas que acabas de iniciar.
Obteniendo ayuda
Si estás atrapado en algo que esta página no cubre:
- Consulte la Guía para obtener ayuda.
- Busque los [problemas de GitHub] existentes (https://github.com/omegaup/deploy/issues).
- Pregunta en nuestro servidor de Discord.
¿Listo para comenzar a codificar? Dirígete a la Guía de contribución para enviar tu primera solicitud de extracción.