2009-08-10 7 views
12

Soy un desarrollador web que trabaja por mi cuenta usando django, y estoy tratando de entender cómo implementar sitios usando mercurial. Lo que me gustaría tener es poder mantener un repositorio que pueda usar para el trabajo de producción y desarrollo. Siempre habrá algunas diferencias entre producción/desarrollo (por ejemplo, pueden usar bases de datos diferentes, el desarrollo siempre tendrá activada la depuración) pero, en general, estarán sincronizados. También me gustaría poder realizar cambios directamente en el servidor de producción (ordenando html o css, correcciones de errores simples, etc.).Mercurial: mantener 2 ramas sincronizadas pero con ciertas diferencias persistentes?

El flujo de trabajo que tengo la intención de utilizar para hacer esto es el siguiente:

  • crear 2 ramas, prod y dev (todos los ajustes inicialmente en su configuración de producción)
  • Cambio settings.py y unos pocos otras cosas en la rama de desarrollo. Así que ahora tengo 2 cabezas, y de ahora en adelante el repositorio siempre tendrá 2 cabezas.
  • (en la máquina dev) Realice cambios en dev, luego use 'hg transplant' para copiar los conjuntos de cambios relevantes a producción.
  • empuje para repositorio principal
  • (El servidor de producción) Tire de repo principal, actualizar a la cabeza prod

Nota: también se puede hacer cambios directamente a pinchan siempre y cuando se trasplanta los cambios en prog.

Este flujo de trabajo tiene el inconveniente de que cada vez que realiza un cambio, no solo debe comprometerlo con la rama en la que realice el cambio, sino que también debe trasplantarlo a la otra rama. ¿Hay una manera más sensata de hacer lo que quiero aquí, tal vez usando parches? O en su defecto, ¿hay alguna manera de automatizar el proceso de confirmación para trasplantar automáticamente el conjunto de cambios a la otra rama, y ​​sería una buena idea?

+1

Voy a pesar en una respuesta más adelante, aunque excelente sugerencia de Steve L. ya se ha seleccionado, pero quiero señalar que, independientemente de la forma en que finalmente lo hace , la extensión 'trasplante 'es una forma particularmente mala de hacerlo. Transplant hace una exportación y luego una importación, que le dan a su conjunto de cambios una identificación hash/node completamente nueva. Si cada conjunto de cambios cambia los nombres entre el desarrollo y la producción, está pidiendo problemas para rastrear qué se solucionó en dónde y dónde se introdujo el problema. Hacer 'hg entrante' y' hg saliente' inutilizable entre dev y prod es pedir problemas. –

Respuesta

5

Probablemente usaría Mercurial Queues para algo como esto. Mantenga el repositorio principal como versión de desarrollo y tenga un parche for-production que realice los cambios necesarios para la producción.

+0

Extensión de Mercurial Queues http://mercurial.selenic.com/wiki/MqExtension Tutorial de Extensión de Colas Mercurial http://mercurial.selenic.com/wiki/MqTutorial –

1

Tal vez intentar algo como esto: (Estaba pensando acerca de este problema, en mi caso se trata de una base de datos SQLite)

  • Añadir a settings.py .hgignore, para mantenerlo fuera del repositorio.
  • tomar su settings.py archivos de las dos ramas separadas y se mueven en dos archivos separados, y settings-prod.pysettings-dev.py
  • crear un script de despliegue que copia el archivo de configuración de X-apropiado settings.py, por lo que se puede implementar de cualquier manera.

Si tiene un par de archivos adicionales, haga lo mismo por ellos. Si tiene muchos archivos pero están todos ellos en el mismo directorio, puede crear un par de directorios: production y development, y luego copiarlos o enlazarlos en el directorio deploy.

Si hizo algo como esto, podría prescindir de la necesidad de ramificar su repositorio.

+0

Me gusta este enfoque debido a la falta de sucursales, de hecho, ya utilizo uno similar. En lugar de crear 2 archivos de configuración, hago un directorio de configuración y pongo un archivo '__init __. Py' en él, agrego mis archivos de configuración allí, prod.py y dev.py (idea extraída de este blog: http: // blog. haydon.id.au/2009/07/django-development-workflow.html). Luego solo inserte el script wsgi correcto. Pero desafortunadamente también necesito cambiar algunas plantillas, la producción usa versiones minificadas de javascript y dev usa sin minificar, y no creo que pueda hacer esto sin un enlace simbólico desagradable. – markmuetz

2

Aquí hay dos posibles soluciones usando uno de mercurio y uno no usar mercurial:

  1. Utilice el nombre de host para cambiar entre prod and Devel. Tenemos una sola marca en la parte superior de nuestro archivo de configuración que mira la variable de entorno SERVER_NAME. Si se trata de www.production.com es el DB de prod y, de lo contrario, elige un DB de demostración/prueba/etapa específico o predeterminado.
  2. Al usar Mercurial, solo tiene un clon que es dev y un clon que es prod, realiza todos los cambios en dev y despliega el tiempo de tir de dev a prod. Después de tirar tendrá 2 cabezas en Prod divergentes de un único ancestro común (el último despliegue). Una cabeza tendrá un solo conjunto de cambios que contenga solo las diferencias entre implementaciones dev y prod, y la otra tendrá todo el nuevo trabajo. Combínalos en el clon prod, seleccionando los cambios prod en el conflicto, por supuesto, y tienes una configuración desplegable, y estás listo para trabajar más en 'dev'. No es necesario ramificar, trasplantar o usar colas. Siempre que nunca hagas ese cambio con la configuración de prod en 'dev', siempre necesitará una fusión después de tirar de dev, y si son solo unas pocas líneas no hay mucho que hacer.
1

De hecho hago esto usando ramas con nombre y fusión directa en lugar de trasplantar (que es más confiable, IMO). Esto generalmente funciona, aunque a veces (cuando edite los diferentes archivos en la otra rama), tendrá que prestar atención para no eliminar las diferencias nuevamente cuando se está fusionando.

Por lo tanto, funciona muy bien si no está cambiando los archivos diferentes mucho.

2

He resuelto esto con la configuración local.

  1. Anexar al settings.py:

     
    try: 
    from local_settings import * 
    except ImportError: 
    pass 
    

  2. touch local_settings.py

  3. Añadir ^local_settings.py$ a su .hgignore

Cada despliegue que hago tiene sus propios ajustes locales (normalmente cosas diferentes DB y diferentes direcciones de correo electrónico de origen).

PD: solo lea las "versiones minificadas de la parte javascript" más adelante. Para esto, sugeriría un gancho post-actualización y una configuración (como JS_EXTENSION).

Ejemplo (de la parte superior de mi cabeza no probado, adaptar como sea necesario!):

  1. Ponga JS_EXTENSION ='.raw.js en su archivo settings.py;
  2. Ponga JS_EXTENSION = '.mini.js 'en su archivo local_settings.py en el servidor de producción;
  3. Cambio JS inclusión de:
    <script type="text/javascript" src="blabla.js"></script>
    Para:
    <script type="text/javascript" src="blabla{{JS_EXTENSION}}"></script>
  4. Hacer un gancho posterior a la actualización que busca y genera *.raw.js.mini.js (versiones minified de prima);
  5. Añadir .mini.js$ a su .hgignore
+0

Este método es bastante ordenado. Me gusta la parte JS_EXTENSION, hace exactamente lo que quería y tiene sentido de inmediato. – markmuetz

Cuestiones relacionadas