Usando capistrano para desplegar desde diferentes ramas de git

125

Estoy usando capistrano para implementar una aplicación RoR. La base de código está en un repositorio git, y la ramificación se usa ampliamente en el desarrollo. Capistrano usa el deploy.rbarchivo para su configuración, una de ellas es la rama desde la que se implementa.

Mi problema es este: digamos que creo una nueva rama A desde el maestro . El archivo de implementación hará referencia a la rama maestra . Editar I que, por lo que una puede ser desplegado a entorno de prueba. Termino de trabajar en la función y fusiono la rama A en la maestra . Dado que el deploy.rbarchivo de A es más fresca, que se fusionó en y ahora el deploy.rbde maestro de referencias rama Una . Hora de editar de nuevo.

Esa es una gran cantidad de edición manual aparentemente innecesaria: el parámetro siempre debe coincidir con el nombre de la rama actual. Además de eso, es fácil olvidarse de editar la configuración cada vez.

¿Cuál sería la mejor manera de automatizar este proceso?

Editar: Resulta que alguien ya había hecho exactamente lo que necesitaba :

Esta mañana tuve la oportunidad de desplegar una rama de un repositorio git en un servidor provisional, pero no tenía la menor idea de cómo. Una búsqueda rápida a través del código fuente de capistrano reveló que podía usar set :branch "branch_name"en mi script de implementación. Lo intenté y funcionó. Entonces pensé que tendría que hacer un cambio similar en todas mis ramas. Por supuesto, soy un holgazán y me preguntaba si no había una mejor manera.

Si no está familiarizado con git, la salida del comando git branch es una lista de ramas con un asterisco que marca el que está actualmente desprotegido en su máquina local. Por ejemplo:

> git branch
* drupal_authentication
fragment_caching
master

Entonces, pensé, ¿qué pasaría si solo analizara la salida y buscara la rama marcada como actual:

set :branch, $1 if `git branch` =~ /\* (\S+)\s/m

Ahora puedo implementar cualquier rama que esté actualizada en mi máquina local desde un solo script de implementación compartido.

Toms Mikoss
fuente
Este es el enlace actualizado: Implementación de sucursales con Capistrano
wacko

Respuestas:

157

Esto funciona con Capistrano> = 3.1:

agregue esta línea a config/deploy.rb:

set :branch, ENV['BRANCH'] if ENV['BRANCH']

y luego llame a capistrano con:

cap production deploy BRANCH=master

Esta solución funciona con Capistrano <3.1:

# call with cap -s env="<env>" branch="<branchname>" deploy

set :branch, fetch(:branch, "master")
set :env, fetch(:env, "production")
soluciones de invierno
fuente
44
Si usa la extensión mustistage, no es necesario establecerla env, pero esto funcionó para mí solo usando una rama
Tom Harrison el
según lo indicado por @lulalala , necesito usar minúsculas para obtener la rama especificada.
Jahan
@ Jani: Gracias, parece que cambiaron eso en las nuevas versiones de capistrano, edité mi respuesta en consecuencia.
wintersolutions
Tuve exactamente el problema opuesto al de @Jani: tuve que poner en mayúscula -S, o bien el argumento no pasaría a cap, al usar fetch (: var_name, 'default') para obtenerlo.
Frederik Struck-Schøning el
1
la opción '-s' (--set) significa 'Establecer una variable después de cargar las recetas'. y la opción 'S' (--set-before) significa 'Establecer una variable antes de cargar las recetas'.
Ramon Caldeira
33

Usando Capistrano 3.1.0+, ninguno de estos funcionó para mí. En cambio, de acuerdo con sus instrucciones comentadas:

   ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }

Pero no desea usarlo asko se lo indicará. En su lugar deberías usar set. HEADes la rama más alta; 'borde' como se llama. Si quieres una rama diferente, reemplace HEADcon su nombre de la sucursal, por ejemplo: master, staging, etc.

Para concluir con ejemplos, en /config/deploy/production.rb, puede incluir esta línea:

   set :branch, proc { `git rev-parse --abbrev-ref master`.chomp }

...o

   set :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }

por cierto, HEADes la configuración predeterminada, por lo que no es necesario indicarlo realmente en el archivo. Podría usarse mejor en a /config/deploy/edge.rb.

En /config/deploy/staging.rb, puede incluir esta línea:

   set :branch, proc { `git rev-parse --abbrev-ref staging`.chomp }

...o

   set :branch, proc { `git rev-parse --abbrev-ref test`.chomp }

¡Tienes la idea!

Espero que estos ejemplos ayuden a los futuros usuarios de capistrano (^_^)

Eric Wanchic
fuente
44
git rev-parse --abbrev-ref HEADse usa para averiguar en qué rama está HEAD. ejecutar git rev-parse --abbrev-ref staging(casi) siempre saldrá staging. Solo puedes usar set :branch, 'staging'.
MiniGod
27

Con etapas múltiples, en realidad es ahora:

cap production deploy -s branch=my-branch

La sintaxis de la publicación anterior no funciona en mi entorno

David Hersey
fuente
1
-s branch=fooestablece la rama variable capistrano foodespués de cargar las recetas
alvin
26

Puedo confirmar que lo siguiente todavía funciona en Cap 3.11.0 13/10/18 y Cap 2:

En deploy.rb / stage.rb:

set :branch, ENV['BRANCH'] || 'develop'

En la línea de comando:

cap deploy BRANCH=featurex

Esto le brinda una rama predeterminada (que podría ser diferente para diferentes entornos) y la capacidad de cambiar las ramas cuando lo desee.

Paul Odeon
fuente
15

Alternativamente, puede estructurarlo desde la línea de comandos donde tiene una rama y un entorno predeterminados y también puede pasar parámetros a la llamada de límite que podrían incluir el entorno y la rama que se utilizarán. Esto podría ser una rama que se pasa explícitamente o podría tener un parámetro que indicaría la rama actual como se describe en el enlace que enumeró.

#call with cap -S env="<env>" branch="<branchname>" deploy
...

# Prevents error if not parameter passed, assumes that default 'cap deploy' command
# and should deploy the master branch to the production server
set(:env, ‘production’) unless exists?(:env)
set(:branch, ‘master’) unless exists?(:branch)

if !env.nil? && env == "production"
   role :web, "production_ip_address"
else   # add more as needed 
   role :web, "development_ip_address"
end

if !branch.nil? && branch == "current"
   set :branch, $1 if `git branch` =~ /\* (\S+)\s/m
elsif !branch.nil?
   set :branch, branch
else   # add more as needed 
   set :branch, "master"
end
...

Ejemplo de código prestado mucho de aquí

naven87
fuente
3
Necesito usar minúsculas -spara obtener la rama especificada
lulalala
Tuve exactamente el problema opuesto al de @lulula: tuve que poner en mayúscula -S, o bien, el argumento no pasaría a cap, al usar fetch (: var_name, 'default') para obtenerlo.
Frederik Struck-Schøning el
10

Si está utilizando capistrano-multietapa , solo necesita ejecutar

cap -s branch=$MY_BRANCH deploy

o

cap -s branch=$MY_BRANCH production deploy

sin ninguna otra edición a su deploy.rb.

asimétrico
fuente
2
Eso debería ser branch=, no branch-.
Jimothy
3
OptionParser :: AmbiguousOption: opción ambigua: -s
giorgio
8

Este comando ya no funcionará:

cap deploy -s branch=your_branch

Se -sSeliminó el soporte para banderas en capistrano v3 +.
Aquí puedes leer más al respecto: enlace
Se mencionó en un par de respuestas, pero actualmente no es correcto.

Lo que funciona para mí:
en el deploy.rbarchivo agregar

set :branch, ENV['BRANCH'] || :master

entonces corre:

BRANCH=your_branch cap deploy

También tenga en cuenta que, para ejecutar con éxito este comando, debe estar en la rama maestra.

SakyHank
fuente
3

Esta solución debería funcionar con todas las versiones de Capistrano.

def branch_name(default_branch)
  branch = ENV.fetch('BRANCH', default_branch)

  if branch == '.'
    # current branch
    `git rev-parse --abbrev-ref HEAD`.chomp
  else
    branch
  end
end

set :branch, branch_name('master')

Uso:

BRANCH=. cap [staging] deploy
# => deploy current branch

BRANCH=master cap [staging] deploy
# => deploy master branch

cap [staging] deploy
# => deploy default branch
Pablo Cantero
fuente
2

Estoy usando la versión 3.3.5 y tengo esto funcionando:

set :branch, 'develop'
David Rosa
fuente
1

Respuesta general:

Si tiene un archivo de configuración con un contenido modificado de un entorno a otro, debe hacer esa línea como una "plantilla" (con una cadena que representa el nombre de la variable como @BRANCH_NAME@o @ENV_NAME@).

Luego, tendría un script (versionado) capaz de leer su archivo de configuración y reemplazar la @BRANCH_NAME@variable " " por el valor apropiado que necesita su proceso de implementación.

VonC
fuente
1

Para usuarios de capistrano 3:

desc "prompt for branch or tag"
task :git_branch_or_tag do
  on roles(:all) do |host|
    run_locally do
      execute :git, 'tag'
      tag_prompt = "Enter a branch or tag name to deploy"
      ask(:branch_or_tag, tag_prompt)
      tag_branch_target = fetch(:branch_or_tag, 'master')
      set(:branch, tag_branch_target)
    end
  end
end

before 'deploy:updated',  :git_branch_or_tag
lfender6445
fuente
1

Método 1: establecer una rama específica de la etapa (por ejemplo, prueba, producción) para la implementación

Poner branch configuración en los archivos de la etapa en lugar de 'deploy.rb' y establezca la rama de destino desde la que se implementará esa etapa.

Para una aplicación de dos etapas con nombre de sucursal asociado testy production, la configuración se verá así,

# app_root/config/deploy/test.rb
...
set :branch, "test"
...

# app_root/config/deploy/production.rb
...
set :branch, "production"
...

Este método permite la implementación desde ramas específicas de la etapa. Por lo tanto, el único paso adicional que se requerirá es fusionar o modificar el código más reciente de la rama base.

Método 2: Implemente directamente desde cualquier rama (usando la etiqueta)

Otro enfoque es implementar usando la etiqueta. Para implementar usando la etiqueta, configure la branchconfiguración. en 'deploy.rb' de la siguiente manera,

set :branch, `git describe --tags $(git rev-list --tags --max-count=1)`.chomp

Y configure el CI para que se implemente condicionalmente en diferentes etapas si el patrón de etiqueta asociado coincide (por ejemplo, /.*-test$/ ).

Ahora, se puede implementar desde cualquier sucursal,

  • Primero, crea una etiqueta desde cualquier rama,

    git tag -a v0.1.0-test -m "Versión 0.1.0-test"

  • Y empujar

    git push origin v0.1.0-test

Nota: Los métodos anteriores se basan en Capistrano 3.

Shakil
fuente
0
git rev-parse --abbrev-ref HEAD

devolverá la rama actual en la que se encuentra exactamente.

Siempre configuro el en gpshlugar degit push -u origin branch_name

$ which gpsh
gpsh: aliased to git push -u origin `git rev-parse --abbrev-ref HEAD`
TorvaldsDB
fuente