¿Cómo puedo implementar / enviar solo un subdirectorio de mi repositorio git a Heroku?

121

Tengo un proyecto que usa Serve y está controlado por versiones usando Git. Serve crea una outputcarpeta con archivos estáticos que quiero implementar en Heroku.

No quiero implementar el proyecto Serve en sí, ya que a la pila de Heroku Cedar no parece gustarle demasiado, pero lo más importante es que quiero aprovechar el excelente soporte de Heroku para sitios web estáticos.

¿Hay alguna forma de implementar una subcarpeta en un control remoto de git? ¿Debo crear un repositorio de Git en la outputcarpeta (eso suena mal) y enviarlo a Heroku?

Olivier Lacan
fuente
1
Es posible que esté buscando submódulos: book.git-scm.com/5_submodules.html
greg0ire

Respuestas:

220

Hay una forma aún más fácil a través de git-subtree . Suponiendo que desea enviar la 'salida' de su carpeta como raíz a Heroku, puede hacer:

git subtree push --prefix output heroku master

Actualmente, parece que git-subtree se está incluyendo en git-core, pero no sé si esa versión de git-core ya se ha lanzado.

anshumanos
fuente
1
Sí, pero el subárbol todavía (a partir de 1.8.0.2) no está incluido a través del instalador de git . Afortunadamente, la instalación desde la fuente es rápida y sencilla, esta página me funcionó en Mac.
dribnet
14
Si lo necesita --force, use git push heroku `git subtree split --prefix output master`:master --force. Consulte stackoverflow.com/a/15623469/2066546 .
fiedl
2
Pero, ¿cuál es la forma correcta de impulsar una etiqueta específica? Pensé que debería ser git subtree push --prefix output heroku +refs/tags/v1.0.0:refs/heads/master. Pero esto no funciona y vuelve +refs/tags/v1.0.0:refs/heads/master does not look like a ref. Necesito este tipo de funcionalidad para poder realizar un roleback a etiquetas específicas más adelante. ¿Cuál es la forma correcta de hacerlo?
denis
1
Recibo el error 'Las actualizaciones fueron rechazadas porque la punta de una rama empujada está detrás de su control remoto'
Ally
2
@ and-dev @Eric Burel Empujé con éxito la outputcarpeta que solo estaba presente en mi developrama a la heroku masterrama sin la necesidad de especificar develop:master, por lo que aparentemente empuja a la rama de destino que especifica desde su rama actualmente desprotegida.
cprcrack
10

Comencé con lo que dijo John Berryman, pero en realidad puede ser más simple si no te importa en absoluto la historia de heroku git.

cd bin
git init
git add .
git commit -m"deploy"
git push [email protected]:your-project-name.git -f
rm -fr .git

Supongo que oficial git subtreees la mejor respuesta, pero tuve problemas para que el subárbol funcionara en mi mac.

LessQuesar
fuente
9

Tuve un problema similar. En mi caso, nunca fue un problema eliminar todo en el repositorio de heroku y reemplazarlo con lo que esté en mi subdirectorio. Si este es tu caso, puedes usar el siguiente script bash. Simplemente colóquelo en el directorio de su aplicación Rails.

#!/bin/bash

#change to whichever directory this lives in
cd "$( dirname "$0" )"

#create new git repository and add everything
git init
git add .
git commit -m"init"
git remote add heroku [email protected]:young-rain-5086.git

#pull heroku but then checkback out our current local master and mark everything as merged
git pull heroku master
git checkout --ours .
git add -u
git commit -m"merged"

#push back to heroku, open web browser, and remove git repository
git push heroku master
heroku open
rm -fr .git

#go back to wherever we started.
cd -

Estoy seguro de que hay muchas formas de mejorar esto, ¡así que no dudes en decirme cómo!

JnBrymn
fuente
+1Gracias. Esta solución funciona muy bien si no le importan los registros de git en Heroku. Se puede modificar el script anterior en caso de que haya algunas carpetas que desee ignorar, dentro de la ruta secundaria de la aplicación que se implementará. Por ejemplo, no quería speccarpeta en heroku. Ejemplo Gist
ch4nd4n
+1pero puede simplificar no tirando y fusionándose con heroku master y en su lugar simplementegit push --force heroku master
MK Safi
4

Después de un largo y duro mes de probar cosas diferentes y ser mordido cada vez que me di cuenta,

solo porque Heroku usa un repositorio git como mecanismo de implementación, no debe tratarlo como un repositorio git

podría haber sido rsync igual de bien, fueron por git, no te distraigas por esto

si lo hace, se abre a todo tipo de heridas. Todas las soluciones mencionadas fallan miserablemente en alguna parte:

  1. requiere que se haga algo cada vez, o periódicamente, o suceden cosas inesperadas (empujar submódulos, sincronizar subárboles, ...)
  2. si usa un motor, por ejemplo, para modularizar su código, Bundler lo comerá vivo, es imposible describir la cantidad de frustración que he tenido con ese proyecto durante la búsqueda para encontrar una buena solución para esto
    • intenta agregar el motor como enlace de repositorio de git + bundle deploy- falla, necesita actualizar el paquete cada vez
    • Intentas agregar el motor como :path+ bundle deploy- falla, el equipo de desarrollo considera la :pathopción como "no estás usando Bundler con esta opción de gema", por lo que no se empaquetará para producción.
    • Además, cada actualización del motor quiere actualizar su pila de rieles -_-
  3. La única solución que he encontrado es usar el motor como /vendorenlace simbólico en desarrollo y copiar los archivos para producción.

La solución

La aplicación en cuestión tiene 4 proyectos en git root:

  1. api: dependiendo del perfil, se ejecutará en 2 hosts heroku diferentes: carga y api
  2. web - el sitio web
  3. web-old: el sitio web antiguo, aún en proceso de migración
  4. común: los componentes comunes extraídos en un motor

Todos los proyectos tienen un vendor/commonenlace simbólico que busca en la raíz del commonmotor. Al compilar el código fuente para la implementación en heroku, necesitamos eliminar el enlace simbólico y rsync, su código para que esté físicamente en la carpeta del proveedor de cada host por separado.

  1. acepta una lista de nombres de host como argumentos
  2. ejecuta un git push en su repositorio de desarrollo y luego ejecuta un git pull limpio en una carpeta separada, asegurándose de que no se envíen cambios sucios (no confirmados) a los hosts automáticamente
  3. despliega los hosts en paralelo: se extrae cada repositorio de heroku git, se sincroniza el nuevo código en los lugares correctos, se confirma con información push básica en el comentario de confirmación de git,
  4. al final, enviamos un ping con curl para decirle a los anfitriones del hobby que se despierten y sigan los registros para ver si todo se volvió vino
  5. también juega bien con jenkins: D (código automático para probar servidores después de pruebas exitosas)

Funciona muy, muy bien en la naturaleza con problemas mínimos (¿no?) 6 meses ahora

Aquí está el script https://gist.github.com/bbozo/fafa2bbbf8c7b12d923f

Actualización 1

@AdamBuczynski, nunca es tan sencillo.

Primero, siempre tendrá un entorno de producción y prueba al menos, y un montón de clústeres específicos de funciones en el peor de los casos, de repente, 1 carpeta debe mapearse en n proyectos de heroku como un requisito bastante básico y todo debe organizarse de alguna manera para que la secuencia de comandos "sabe" qué fuente desea implementar y dónde,

En segundo lugar, querrá compartir código entre proyectos; ahora viene la sync_commonparte, los shennanigans con enlaces simbólicos en desarrollo se reemplazan por código real sincronizado en Heroku porque Heroku requiere una cierta estructura de carpetas y un paquete y rubygems realmente realmente hacen que las cosas sean feas, muy mal si usted quiero extraer los hilos comunes en una gema

En tercer lugar, querrá conectar CI y cambiará un poco la forma en que las subcarpetas y el repositorio de git deben organizarse, al final, en el caso de uso más simple posible, terminará con la esencia mencionada anteriormente.

En otros proyectos, necesito conectar compilaciones de Java, cuando venda software a varios clientes, necesitará filtrar los módulos que se instalan según los requisitos de instalación y otras cosas,

Realmente debería considerar explorar la posibilidad de agrupar cosas en un Rakefile o algo así y hacer todo de esa manera ...

bbozo
fuente
Hola @bbozo, ¿te importaría condensar un poco tu solución y hacerla específica para el caso de uso de implementar una subcarpeta específica en un proyecto heroku específico y eliminar todo lo que no es necesario / específico para Heroku?
Adam Reis
Gracias por actualizar tu respuesta. Creo que voy a morder la bala y dividir el código del lado del cliente y del servidor en repositorios separados. No es ideal para nuestra situación, pero superará los empujes de subárbol forzados que tenemos que hacer ahora, y por lo que deduzco, también será mucho más simple que intentar usar enlaces simbólicos.
Adam Reis
No tenga miedo de un "script de implementación", vale la pena
bbozo