Je fais un pipeline simple:
Construire -> Mise en scène -> Production
J'ai besoin de différentes variables d'environnement pour la mise en scène et la production, donc j'essaie de source variables.
sh 'source $JENKINS_HOME/.envvars/stacktest-staging.sh'
Mais ça retourne Introuvable
[Stack Test] Running Shell script
+ source /var/jenkins_home/.envvars/stacktest-staging.sh
/var/jenkins_home/workspace/Stack Test@tmp/durable-bcbe1515/script.sh: 2: /var/jenkins_home/workspace/Stack Test@tmp/durable-bcbe1515/script.sh: source: not found
Le chemin est correct, parce que je lance la même commande lorsque je me connecte via ssh, et cela fonctionne bien.
Voici l’idée du pipeline:
node {
stage name: 'Build'
// git and gradle build OK
echo 'My build stage'
stage name: 'Staging'
sh 'source $JENKINS_HOME/.envvars/stacktest-staging.sh' // PROBLEM HERE
echo '$DB_URL' // Expects http://production_url/my_db
sh 'gradle flywayMigrate' // To staging
input message: "Does Staging server look good?"
stage name: 'Production'
sh 'source $JENKINS_HOME/.envvars/stacktest-production.sh'
echo '$DB_URL' // Expects http://production_url/my_db
sh 'gradle flywayMigrate' // To production
sh './deploy.sh'
}
Que devrais-je faire?
Pour charger des variables d'environnement à partir d'un fichier, vous pouvez notamment charger un fichier Groovy.
Par exemple:
Dans ce fichier, vous définissez 2 variables d’environnement que vous souhaitez charger.
env.DB_URL="hello"
env.DB_URL2="hello2"
Vous pouvez ensuite charger cela en utilisant
load "$JENKINS_HOME/.envvars/stacktest-staging.groovy"
Ensuite, vous pouvez les utiliser dans les étapes suivantes echo/Shell.
Par exemple, voici un court script de pipeline:
node {
load "$JENKINS_HOME/.envvars/stacktest-staging.groovy"
echo "${env.DB_URL}"
echo "${env.DB_URL2}"
}
Des commentaires aux réponse acceptée
N'utilisez pas la méthode globale 'env' mais la construction 'withEnv', par exemple, consultez: Numéro 9: ne définissez pas les variables env avec la valeur globale env dans les 10 meilleures pratiques du plugin jenkins pipeline
Dans l'exemple suivant: VAR1 est une chaîne Java simple (pas d'expansion de variable groovy), VAR2 est une chaîne groovy (la variable 'someGroovyVar' est développée).
Le script transmis est une chaîne Java simple. Ainsi, $ VAR1 et $ VAR2 sont transmis littéralement au shell, et l'écho accède aux variables d'environnement VAR1 et VAR2.
stage('build') {
def someGroovyVar = 'Hello world'
withEnv(['VAR1=VALUE ONE',
"VAR2=${someGroovyVar}"
]) {
def result = sh(script: 'echo $VAR1; echo $VAR2', returnStdout: true)
echo result
}
}
Pour les secrets/mots de passe, vous pouvez utiliser plugin de liaison des informations d'identification
Exemple:
REMARQUE: CREDENTIALS_ID1 est un secret de nom d'utilisateur/mot de passe enregistré dans les paramètres Jenkins.
stage('Push') {
withCredentials([usernamePassword(
credentialsId: 'CREDENTIALS_ID1',
passwordVariable: 'PASSWORD',
usernameVariable: 'USER')]) {
echo "User name: $USER"
echo "Password: $PASSWORD"
}
}
La sortie du journal de la console jenkisn cache les valeurs réelles:
[Pipeline] echo
User name: ****
[Pipeline] echo
Password: ****
Jenkins et les informations d'identification est un gros problème, voir probablement: plugin accréditations
Pour être complet: la plupart du temps, nous avons besoin des secrets dans les variables d'environnement, car nous les utilisons à partir de scripts Shell. Nous combinons donc les éléments withCredentials et withEnv comme suit:
stage('Push') {
withCredentials([usernamePassword(
credentialsId: 'CREDENTIALS_ID1',
passwordVariable: 'PASSWORD',
usernameVariable: 'USER')]) {
withEnv(["ENV_USERNAME=${USER}",
"ENV_PASSWORD=${PASSWORD}"
]) {
def result = sh(script: 'echo $ENV_USERNAME', returnStdout: true)
echo result
}
}
}
Un autre moyen de résoudre cette installation du plug-in 'Pipeline Utility Steps' qui nous fournit la méthode readProperties (pour référence, veuillez consulter le lien https://jenkins.io/doc/pipeline/steps/pipeline-utility-steps/#pipeline- utility-steps ) Ici, dans l'exemple, nous pouvons voir qu'ils stockent les clés dans un tableau et utilisent les clés pour récupérer la valeur. Mais dans ce cas, le problème en production sera comme si nous ajoutions une variable ultérieurement dans le fichier de propriétés, cette variable devait également être ajoutée dans le tableau du fichier Jenkins . Pour supprimer ce couplage étroit, nous pouvons écrire du code de manière à ce que l'environnement de génération Jenkins puisse obtenir automatiquement des informations sur toutes les clés existantes présentes dans le fichier Property. Voici un exemple pour la référence
def loadEnvironmentVariables(path){
def props = readProperties file: path
keys= props.keySet()
for(key in keys) {
value = props["${key}"]
env."${key}" = "${value}"
}
}
Et le code client ressemble à
path = '\\ABS_Output\\EnvVars\\pic_env_vars.properties'
loadEnvironmentVariables(path)
Si vous utilisez Jenkins 2.0, vous pouvez charger le fichier de propriétés (qui contient toutes les variables d’environnement requises ainsi que leurs valeurs correspondantes), lire automatiquement toutes les variables d’environnement répertoriées et les insérer dans l’entité env fournie par Jenkins.
Voici une méthode qui effectue l'action indiquée ci-dessus.
def loadProperties(path) {
properties = new Properties()
File propertiesFile = new File(path)
properties.load(propertiesFile.newDataInputStream())
Set<Object> keys = properties.keySet();
for(Object k:keys){
String key = (String)k;
String value =(String) properties.getProperty(key)
env."${key}" = "${value}"
}
}
Pour appeler cette méthode, nous devons passer le chemin du fichier de propriétés sous forme de variable chaîne. Par exemple, dans notre fichier Jenkins utilisant un script groovy, vous pouvez appeler comme
path = "${workspace}/pic_env_vars.properties"
loadProperties(path)
S'il vous plaît demandez-moi si vous avez un doute