Utilisation de capistrano pour déployer à partir de différentes branches git

125

J'utilise capistrano pour déployer une application RoR. La base de code est dans un référentiel git et le branchement est largement utilisé dans le développement. Capistrano utilise un deploy.rbfichier pour ses paramètres, l'un d'entre eux étant la branche à partir de laquelle effectuer le déploiement.

Mon problème est le suivant: disons que je crée une nouvelle branche A à partir de master . Le fichier Deploy référence maître branche. Je modifie cela, afin que A puisse être déployé pour tester l'environnement. J'ai fini de travailler sur la fonctionnalité et fusionne la branche A dans master . Étant donné que le deploy.rbfichier de A est plus frais, il se fusionné et maintenant deploy.rben maître des références de la branche A . Il est temps de modifier à nouveau.

C'est beaucoup de modifications manuelles apparemment inutiles - le paramètre doit toujours correspondre au nom de la branche actuelle. En plus de cela, il est facile d'oublier de modifier les paramètres à chaque fois.

Quelle serait la meilleure façon d'automatiser ce processus?

Edit: Il s'avère que quelqu'un avait déjà fait exactement ce dont j'avais besoin :

Ce matin, j'ai eu l'occasion de déployer une branche d'un référentiel git sur un serveur intermédiaire, mais je n'avais pas la moindre idée de comment. Une recherche rapide dans le code source de capistrano a révélé que je pouvais utiliser set :branch "branch_name"dans mon script de déploiement. Je l'ai essayé et cela a fonctionné. J'ai alors pensé que je devrais effectuer un changement similaire dans toutes mes succursales. Bien sûr, je suis paresseux et je me demande s'il n'y a pas de meilleur moyen.

Si vous n'êtes pas familier avec git, la sortie de la commande git branch est une liste de branches avec un astérisque marquant celle actuellement extraite sur votre machine locale. Par exemple:

> git branch
* drupal_authentication
fragment_caching
master

Donc, j'ai pensé, que se passerait-il si je viens d'analyser la sortie et de rechercher la branche marquée comme actuelle:

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

Je suis maintenant en mesure de déployer n'importe quelle branche actuelle sur ma machine locale à partir d'un seul script de déploiement partagé.

Toms Mikoss
la source
Ceci est le lien mis à jour: Déploiement de branches avec Capistrano
wacko

Réponses:

157

Cela fonctionne avec Capistrano> = 3.1:

ajoutez cette ligne à config/deploy.rb:

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

puis appelez capistrano avec:

cap production deploy BRANCH=master

Cette solution fonctionne avec Capistrano <3.1:

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

set :branch, fetch(:branch, "master")
set :env, fetch(:env, "production")
solutions hivernales
la source
4
Si vous utilisez l'extension mustistage, pas besoin de définir env, mais cela a fonctionné pour moi simplement en utilisant une branche
Tom Harrison
comme indiqué par @lulalala, je dois utiliser -s minuscules pour qu'il récupère la branche spécifiée.
Jahan
@Jani: Merci, il semble qu'ils aient changé cela dans les nouvelles versions de capistrano, j'ai modifié ma réponse en conséquence.
wintersolutions
J'ai eu le problème exactement opposé à @Jani: je devais majuscule -S, sinon l'argument ne passerait pas à cap, lors de l'utilisation de fetch (: var_name, 'default') pour l'obtenir.
Frederik Struck-Schøning
1
l'option '-s' (--set) signifie 'Définir une variable après le chargement des recettes.' et l'option «S» (--set-before) signifie «Définir une variable avant le chargement des recettes».
Ramon Caldeira
33

En utilisant Capistrano 3.1.0+, aucun de ceux-ci ne fonctionnait plus pour moi. Au lieu de cela, selon leurs instructions commentées:

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

Mais, vous ne voulez pas utiliser askou cela vous le demandera. Au lieu de cela, vous devriez utiliser set. HEADest la branche la plus élevée; «bord» comme on l'appelle. Si vous voulez une autre branche, remplacez HEADvotre nom de la branche, par exemple: master, staging, etc.

Pour conclure avec des exemples, dans /config/deploy/production.rb, vous pouvez inclure cette ligne:

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

...ou

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

btw, HEADest le paramètre par défaut, donc pas besoin de vraiment l'indiquer dans le fichier. Peut être mieux utilisé dans un fichier /config/deploy/edge.rb.

Dans /config/deploy/staging.rb, vous pouvez inclure cette ligne:

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

...ou

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

Vous avez eu l'idée!

J'espère que ces exemples aideront les futurs utilisateurs de capistrano (^_^)

Eric Wanchic
la source
4
git rev-parse --abbrev-ref HEADest utilisé pour savoir sur quelle branche HEAD se trouve. l'exécution git rev-parse --abbrev-ref stagingsera (presque) toujours sortie staging. Vous pouvez simplement utiliser set :branch, 'staging'.
MiniGod
27

Avec plusieurs étages, c'est en fait maintenant:

cap production deploy -s branch=my-branch

La syntaxe de l'article précédent ne fonctionne pas dans mon environnement

David Hersey
la source
1
-s branch=foodéfinit la branche variable capistrano sur fooaprès le chargement des recettes
alvin
26

Je peux confirmer que ce qui suit fonctionne toujours dans Cap 3.11.0 13/10/18 ainsi que Cap 2:

Dans deploy.rb / stage.rb:

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

Sur la ligne de commande:

cap deploy BRANCH=featurex

Cela vous donne une branche par défaut (qui peut être différente pour différents environnements) et la possibilité de changer de branche quand vous le souhaitez.

Paul Odéon
la source
15

Vous pouvez également le structurer à partir de la ligne de commande où vous avez une branche et un environnement par défaut et vous pouvez également passer des paramètres à l'appel de cap qui pourraient inclure l'environnement et la branche à utiliser. Cela pourrait être une branche qui est explicitement passée ou vous pourriez avoir un paramètre qui indiquerait la branche actuelle comme décrit dans le lien que vous avez répertorié.

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

Exemple de code largement emprunté à ici

naven87
la source
3
Je dois utiliser des minuscules -spour qu'il récupère la branche spécifiée
lulalala
J'ai eu le problème exactement opposé à @lulula: je devais majuscule -S, sinon l'argument ne passerait pas à cap, lors de l'utilisation de fetch (: var_name, 'default') pour l'obtenir.
Frederik Struck-Schøning
10

Si vous utilisez capistrano-multi-étapes , il vous suffit d'exécuter

cap -s branch=$MY_BRANCH deploy

ou

cap -s branch=$MY_BRANCH production deploy

sans autre modification de votre deploy.rb.

asymétrique
la source
2
Cela devrait être branch=, non branch-.
Jimothy
3
OptionParser :: AmbiguousOption: option ambiguë: -s
giorgio
8

Cette commande ne fonctionnera plus:

cap deploy -s branch=your_branch

La prise en charge des -sSindicateurs a été supprimée dans capistrano v3 +.
Ici, vous pouvez en savoir plus à ce sujet: lien
Il a été mentionné dans quelques réponses, mais n'est actuellement pas correct.

Ce qui fonctionne pour moi:
dans un deploy.rbfichier ajouter

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

puis exécutez:

BRANCH=your_branch cap deploy

Veuillez également noter que pour exécuter cette commande avec succès, vous devez être sur la branche principale.

SakyHank
la source
3

Cette solution devrait fonctionner avec toutes les versions 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')

Usage:

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

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

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

J'utilise la version 3.3.5 et cela fonctionne:

set :branch, 'develop'
David Rosa
la source
1

Réponse générale:

Si vous avez un fichier de paramètres avec un contenu modifié d'un environnement à l'autre, vous devez créer cette ligne comme un "modèle" (avec une chaîne représentant le nom de la variable comme @BRANCH_NAME@ou @ENV_NAME@).

Ensuite, vous auriez un script (versionné) capable de lire votre fichier de configuration et de remplacer la @BRANCH_NAME@variable " " par la valeur appropriée requise par votre processus de déploiement.

VonC
la source
1

Pour les utilisateurs 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
la source
1

Méthode 1: définir une branche spécifique à l'étape (par exemple, test, production) pour le déploiement

Placez la branchconfiguration dans des fichiers d'étape au lieu de «deploy.rb» et définissez la branche cible pour cette étape à partir de laquelle effectuer le déploiement.

Pour une application en deux étapes avec un nom de branche associé testet production, la configuration ressemblera à ceci,

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

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

Cette méthode permet de déployer à partir de branches spécifiques à l'étape. Ainsi, la seule étape supplémentaire qui sera requise est de fusionner ou de rebaser le dernier code de la branche de base.

Méthode 2: déployer directement à partir de n'importe quelle branche (en utilisant une balise)

Une autre approche consiste à déployer à l'aide de tag. Afin de déployer à l'aide de la balise, définissez le branchfichier config. dans 'deploy.rb' comme suit,

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

Et, configurez le CI pour un déploiement conditionnel à différentes étapes si le modèle de balise associé correspond (par exemple /.*-test$/).

Désormais, un déploiement peut être effectué depuis n'importe quelle branche,

  • Tout d'abord, créez une balise à partir de n'importe quelle branche,

    balise git -a v0.1.0-test -m "Version 0.1.0-test"

  • Et, poussez

    git push origin v0.1.0-test

Remarque: les méthodes ci-dessus sont basées sur Capistrano 3.

Shakil
la source
0
git rev-parse --abbrev-ref HEAD

renverra la branche actuelle dans laquelle vous vous trouvez exactement.

J'ai toujours mis le gpshau lieu degit push -u origin branch_name

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