Usando o capistrano para implantar a partir de diferentes ramificações git

125

Estou usando o capistrano para implantar um aplicativo RoR. A base de código está em um repositório git, e a ramificação é amplamente usada no desenvolvimento. Capistrano usa o deploy.rbarquivo para suas configurações, sendo um deles o ramo para implantar.

Meu problema é o seguinte: digamos que eu crie um novo ramo A do mestre . O arquivo de implantação fará referência à ramificação principal . Eu edito isso, para que A possa ser implantado no ambiente de teste. Termino de trabalhar no recurso e fundo o ramo A no mestre . Uma vez que o deploy.rbarquivo a partir de A é mais fresco, torna-se fundiram em e agora o deploy.rbde mestre referências filiais A . Hora de editar novamente.

São muitas edições manuais aparentemente desnecessárias - o parâmetro sempre deve corresponder ao nome atual da filial. Além disso, é fácil esquecer de editar as configurações sempre.

Qual seria a melhor maneira de automatizar esse processo?

Edit: Acontece que alguém já tinha feito exatamente o que eu precisava :

Esta manhã, tive a oportunidade de implantar uma filial de um repositório git em um servidor intermediário, mas não tinha a menor idéia de como. Uma rápida pesquisa no código-fonte capistrano revelou que eu poderia usar o conjunto :branch "branch_name"no meu script de implantação. Eu tentei e funcionou. Imaginei que precisaria fazer uma alteração semelhante em todos os meus ramos. Claro, eu sou um preguiçoso e me perguntei se não havia uma maneira melhor.

Se você não estiver familiarizado com o git, a saída do comando git branch é uma lista de branches com um asterisco marcando o que está atualmente em check-out na sua máquina local. Por exemplo:

> git branch
* drupal_authentication
fragment_caching
master

Então, pensei, e se eu apenas analisasse a saída e procurasse o ramo marcado como atual:

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

Agora sou capaz de implantar qualquer ramificação que esteja atual na minha máquina local a partir de um único script de implantação compartilhado.

Toms Mikoss
fonte
Este é o link atualizado: Implantando ramificações com o Capistrano
wacko

Respostas:

157

Isso funciona com Capistrano> = 3.1:

adicione esta linha a config/deploy.rb:

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

e ligue para o capistrano com:

cap production deploy BRANCH=master

Esta solução funciona com Capistrano <3.1:

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

set :branch, fetch(:branch, "master")
set :env, fetch(:env, "production")
wintersolutions
fonte
4
Se estiver usando extensão mustistage, sem necessidade de set env, mas isso funcionou para mim usando apenas um ramo
Tom Harrison
como declarado por @lulalala , preciso usar minúsculas -s para buscar o ramo especificado.
Jahan
@Jani: Obrigado, parece que eles mudaram isso nos lançamentos mais recentes do capistrano, editei minha resposta de acordo.
Wintersolutions
Eu tive o problema exatamente oposto ao @Jani: eu tinha que maiúsculas -S, ou então o argumento não passaria para o cap, ao usar fetch (: var_name, 'default') para obtê-lo.
Frederik Struck-Schøning
1
a opção '-s' (--set) significa 'Definir uma variável após o carregamento das receitas.' e a opção 'S' (--set-before) significa 'Definir uma variável antes que as receitas sejam carregadas'.
Ramon Caldeira
33

Usando o Capistrano 3.1.0+, nenhum deles estava mais funcionando para mim. Em vez disso, de acordo com as instruções comentadas:

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

Mas você não deseja usar askou ele solicitará. Em vez disso, você deve usar set. HEADé o ramo mais alto; 'edge' como é chamado. Se você quer um ramo diferente, substitua HEADcom seu nome ramo, por exemplo: master, staging, etc.

Para concluir com exemplos, em /config/deploy/production.rb, você pode incluir esta linha:

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

...ou

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

btw, HEADé a configuração padrão, portanto, não há necessidade de realmente declarar isso no arquivo. Pode ser usado melhor em a /config/deploy/edge.rb.

Em /config/deploy/staging.rb, você pode incluir esta linha:

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

...ou

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

Você entendeu a ideia!

Espero que esses exemplos ajudem futuros usuários de capistrano (^_^)

Eric Wanchic
fonte
4
git rev-parse --abbrev-ref HEADé usado para descobrir em qual ramo o HEAD está. a execução git rev-parse --abbrev-ref staging(quase) sempre será gerada staging. Você pode apenas usar set :branch, 'staging'.
MiniGod
27

Com vários estágios, agora é realmente:

cap production deploy -s branch=my-branch

A sintaxe da postagem anterior não funciona no meu ambiente

David Hersey
fonte
1
-s branch=foodefine o ramo variável Capistrano para foodepois as receitas são carregados
Alvin
26

Posso confirmar que o abaixo ainda funciona no Cap 3.11.0 13/10/18, bem como no Cap 2:

Em deploy.rb / stage.rb:

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

Na linha de comando:

cap deploy BRANCH=featurex

Isso fornece uma ramificação padrão (que pode ser diferente para ambientes diferentes) e a capacidade de alterar ramificações quando você desejar.

Paul Odeon
fonte
15

Como alternativa, você pode estruturá-lo a partir da linha de comando em que possui uma ramificação e um ambiente padrão e também é capaz de passar parâmetros para a chamada de limite, que pode incluir o ambiente e a ramificação a serem usados. Pode ser um ramo que é explicitamente passado ou você pode ter um parâmetro que indique o ramo atual conforme descrito no link que você listou.

#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
...

Exemplo de código emprestado pesadamente daqui

naven87
fonte
3
Eu preciso usar minúsculas -spara que ele para buscar o ramo especificado
lulalala
Eu tive o problema exatamente oposto ao @lulula: eu tinha que maiúsculas -S, ou então o argumento não passaria para o cap, ao usar fetch (: var_name, 'default') para obtê-lo.
Frederik Struck-Schøning
10

Se você estiver usando capistrano-multistage , precisará executar apenas

cap -s branch=$MY_BRANCH deploy

ou

cap -s branch=$MY_BRANCH production deploy

sem mais edições no seu deploy.rb.

assimétrico
fonte
2
Isso deveria ser branch=, não branch-.
Jimothy
3
OptionParser :: AmbiguousOption: opção ambígua: -s
giorgio
8

Este comando não funcionará mais:

cap deploy -s branch=your_branch

O suporte para -sSsinalizadores foi removido no capistrano v3 +.
Aqui você pode ler mais sobre o assunto: link
Foi mencionado em algumas respostas, mas atualmente não está correto.

O que funciona para mim:
no deploy.rbarquivo add

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

então corra:

BRANCH=your_branch cap deploy

Observe também que, para executar com êxito este comando, você precisa estar na ramificação principal.

SakyHank
fonte
3

Esta solução deve funcionar com todas as versões do 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
fonte
2

Estou usando a versão 3.3.5 e tenho este trabalho:

set :branch, 'develop'
David Rosa
fonte
1

Resposta geral:

Se você tiver um arquivo de configuração com um conteúdo modificado de ambiente para ambiente, faça essa linha como um "modelo" (com uma sequência que represente o nome da variável como @BRANCH_NAME@ou @ENV_NAME@).

Então você teria um script (com versão) capaz de ler seu arquivo de configuração e substituir a " @BRANCH_NAME@" variável pelo valor apropriado necessário ao seu processo de implantação.

VonC
fonte
1

Para usuários do 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
fonte
1

Método 1: Definir ramo específico do estágio (por exemplo, teste, produção) para implantação

Coloque a branchconfiguração nos arquivos de estágio em vez de 'deploy.rb' e defina a ramificação de destino para o estágio a ser implantado.

Para um aplicativo de dois estágios com nome de filial associado teste production, a configuração terá esta aparência,

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

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

Este método permite implantar a partir de ramificações específicas do estágio. Portanto, apenas uma etapa adicional necessária será mesclar ou refazer o código mais recente da ramificação base.

Método 2: implantar diretamente de qualquer ramificação (usando a marca)

Outra abordagem é implantar usando tag. Para implantar usando tag, defina a branchconfiguração. em 'deploy.rb' da seguinte maneira,

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

E, configure o IC para implantar condicionalmente em diferentes estágios, se o padrão de tag associado corresponder (por exemplo /.*-test$/).

Agora, uma implantação pode ser feita a partir de qualquer filial,

  • Primeiro, crie uma tag a partir de qualquer ramo,

    tag git -a v0.1.0-test -m "Versão 0.1.0-test"

  • E, empurre

    origem do push do git v0.1.0-test

Nota: Os métodos acima são baseados no Capistrano 3.

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

retornará a ramificação atual em que você está exatamente.

Eu sempre defino o em gpshvez degit push -u origin branch_name

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