J'essaie de créer une nouvelle configuration de projet pour le serveur de génération Jenkins. Pour simplifier ce que j'essaie de faire, je n'utiliserai que deux composants pour décrire le problème.
ComposantA
Composant b
Quelle est la bonne façon de réaliser cela sur Jenkins? J'essayais de savoir comment ajouter ce comportement dynamique d'analyse du fichier de configuration et de faire en sorte que Git Plugin vérifie la branche en fonction de la version attendue de ComponentB, mais je n'en ai aucune idée.
Dans la prochaine étape, je souhaiterai peut-être même avoir des caractères génériques (tels que 5.3. *) Dans le fichier de configuration. Je devrai donc rechercher la balise la plus récente de ComponentB correspondant au caractère générique.
EDIT
Maintenant, je vois que j'ai trop simplifié mon problème et, en raison de la simplification, la principale limitation n’est plus présente.
La principale limitation est que les composants A et B doivent être construits ensemble. Il n'est pas possible de les construire séparément car ils forment un seul exécutable/bibliothèque et le script de construction nécessite des fichiers source des deux composants.
Si vous demandez pourquoi une configuration aussi étrange, donnons une description aux composants A et B:
Il peut y avoir plusieurs composants en tant que composant - un pour chaque plate-forme, mais un seul composant B. La fusion de A à B génère un code source complet pour une plate-forme unique, mais chaque plate-forme ne peut pas être mise à jour vers la dernière version de B, il est donc nécessaire de contrôler quelle version de B doit être utilisé pour construit.
Une option pour réaliser ce que vous voulez consiste à utiliser la configuration suivante:
Créez deux emplois Jenkins:
Définissez le branch
paramètre de construction pour "Composant B":
Utilisez ce paramètre comme spécificateur de branche "Git Plugin":
Vous devriez maintenant pouvoir déclencher manuellement la construction de "Composant B" en spécifiant un paramètre de branche (balise) approprié, par ex. tags/5.3.0
.
Ajoutez une nouvelle étape de génération "Execute Shell" à votre construction "Composant A", qui extraira la version "Composant B" du fichier de configuration dans l'espace de travail et préparera b.properties
fichier avec les paramètres de construction "Composant B".
Installez un déclencheur paramétré plug-in Jenkins et ajoutez une nouvelle étape de génération "Déclencheurs/appels sur d'autres projets" au travail "Composant A":
En utilisant votre b.properties
fichier en tant que source des paramètres de construction.
Maintenant, chaque fois que "Composant A" est reconstruit, un nouveau "Composant B" sera déclenché, avec la branche/balise cible en tant que paramètre de construction.
Si vous voulez supporter les versions génériques, vous pouvez utiliser git ls-remote
commande pour trouver la dernière balise, comme celle-ci:
#B=$(obtain B version from the config file in a usual way)
LATEST=$(\
git ls-remote --tags YOUR_REPOSITORY_URL "$B"\
|cut -d / -f3|sort -r --version-sort|head -1\
)
cat <<EOF > b.properties
branch=tags/$LATEST
EOF
Ceci listera toutes les balises, correspondant au modèle de version "B", dans le référentiel distant "Composant B", et sauvegardera le dernier numéro de version dans la variable LATEST
.
Ajoutez ceci à votre étape "Exécuter Shell" du travail "Composant A" et il devrait être capable de gérer des modèles de numéros de version tels que: 5.3.*
Le problème est que le script Shell s'exécutera en tant qu'utilisateur du démon Jenkins. Il doit donc disposer des informations d'identification appropriées pour accéder au référentiel Git distant (par exemple, via la clé de publication ssh).
Sinon, vous voudrez peut-être consulter = Credential Binding Plugin , pour réutiliser les informations d'identification Git stockées dans Jenkins même.
Vous pouvez également résoudre le problème en utilisant un Jenkins 2.0-style Pipeline , qui vous permettra d'extraire le code des composants A et B dans un seul espace de travail, puis d'appliquer une étape de construction commune. pour eux.
Votre pipeline pourrait ressembler à ceci:
node {
//Settings
def credentialsId = '8fd28e34-b04e-4bc5-874a-87f4c0e05a03'
def repositoryA = 'ssh://[email protected]/projects/a.git'
def repositoryB = 'ssh://[email protected]/projects/b.git'
stage('Checkout component A') {
git credentialsId: credentialsId ,
url: repositoryA , branch : "master"
}
stage("Resolve and checkout component B") {
def deps = readProperties file: 'meta.properties'
echo "Resolved B version = ${deps['b']}"
dir("module/b") {
//Clone/Fetch Component B
checkout scm:[
$class: 'GitSCM',
userRemoteConfigs: [[url: repositoryB, credentialsId: credentialsId]],
branches: [[name: 'refs/tags/*']]
],
changelog: false, poll: false
//Checkout the tag, matching deps['b'] pattern
sshagent([credentialsId]) {
sh "git checkout \$(git tag -l \"${deps['b']}\" |sort -r --version-sort|head -1)"
}
}
}
stage("Build A+B") {
//Apply a common build step
}
}
Nous utilisons ici la commande "readProperties", qui fait partie du plug-in Pipeline Utility Steps , pour extraire le modèle de version "Composant B" de meta.properties
. Des commandes readYaml, readJSON sont également disponibles.
Ensuite nous récupérons/clonons le "Composant B", avec le changelog: false, poll: false
_ drapeaux, pour l’empêcher d’être enregistrés pour l’enquête SCM, dans le dossier "module/b" de l’espace de travail actuel.
Ensuite, appelez une commande Shell pour sélectionner la balise, basée sur le modèle de version que nous avons obtenu ci-dessus, et extrayez-la (les caractères génériques de style 5.3. * Devraient également fonctionner).
L'invocation sh
est encapsulée dans sshagent , afin de lui permettre de réutiliser les informations d'identification appropriées à partir du magasin d'informations d'identification Jenkins.
Utiliser le Credential Binding Plugin a très bien fonctionné pour moi (également mentionné par @zeppelin)
Add Credentials
De type: "Nom d'utilisateur avec mot de passe". Il doit s'agir du nom d'utilisateur et du mot de passe du serveur git du référentiel du composant B utilisant le protocole [~ # ~] https [~ # ~] (l'option SSH n'est pas bon pour cela)Git
de tous les champs obligatoires ( Référentiels , Branches, etc.). Check out to a sub-directory
Et écrivez: component_a
Build when a change is pushed to GitHub
Dans la section Environnement de construction, cochez la case Use secret text(s) or file(s)
Variable
un nom: MY_CREDCredentials
choisissez les informations d'identification spécifiques que vous avez créées à l'étape 1.Maintenant, en utilisant le MY_CRED
Dans le code Execute Shell , vous aurez accès au référentiel du composant B:
DIR="component_b"
if [ "$(ls -A $DIR/.git)" ]; then
cd $DIR
git fetch
else
git clone https://[email protected]/proj/component_b.git $DIR
cd $DIR
fi
git show
git clone 'https://****@github.com/proj/component_b.git' component_b
Effectuez toutes vos analyses de la configuration du composant A pour obtenir la balise souhaitée: TAG=$(cat ./component_a/config.cfg | grep ... | sed ...)
cd component_b; git checkout -f $TAG
-f
.1 - l’ajout du projet B
en tant que sous-dépôt du projet A
serait-il une solution possible?
2- (si l’inclusion du code source complet pour B devrait vraiment être évitée): pousserait les constructions de B vers un repo B_builds
, Et ajouterait ce repo en tant que sous-repo de A
être un solution possible ?
Justification: une façon de rendre plus explicite la dépendance entre A
et B
consiste à la représenter dans les dépendances du référentiel.
Cela nécessiterait d'ajouter une étape supplémentaire lors de la gestion du projet A
:
update `B` sub repo in `A` project, and Push this to `A`
chaque fois que vous produisez une nouvelle version pour B
.
Cependant, vous auriez une vue claire, à partir de A
, sur le moment où les versions de B
ont été intégrées (par exemple: "nous n’utilisions que B 2.0.1
À partir de A 4.3.2
] "), et pousser à A
déclenchera votre flux habituel de Jenkins.