Comment gérez-vous les fichiers de configuration dans le contrôle de code source ?

StackOverflow https://stackoverflow.com/questions/6009

  •  08-06-2019
  •  | 
  •  

Question

Disons que vous disposez d'une application Web typique et d'une configuration de fichier, quelle qu'elle soit.Chaque développeur travaillant sur le projet aura une version pour ses boîtes de développement, il y aura des versions dev, prod et stage.Comment gérez-vous cela dans le contrôle de code source ?Ne pas archiver ce fichier du tout, le vérifier sous des noms différents ou faire quelque chose de fantaisiste ?

Était-ce utile?

La solution

Ce que j'ai fait dans le passé, c'est d'avoir un fichier de configuration par défaut qui est archivé dans le contrôle de code source.Ensuite, chaque développeur dispose de son propre fichier de configuration de remplacement qui est exclu du contrôle de code source.L'application charge d'abord le fichier par défaut, puis si le fichier de remplacement est présent, le charge et utilise tous les paramètres du remplacement de préférence au fichier par défaut.

En général, plus le fichier de remplacement est petit, mieux c'est, mais il peut toujours contenir plus de paramètres pour un développeur disposant d'un environnement très non standard.

Autres conseils

Ne versionnez pas ce fichier.Version d'un modèle ou quelque chose du genre.

Configuration est code, et vous devez le versionner.Nous basons nos fichiers de configuration sur les noms d'utilisateur ;sous UNIX/Mac et Windows, vous pouvez accéder au nom de connexion de l'utilisateur, et tant qu'il est unique au projet, tout va bien.Vous pouvez même remplacer cela dans l'environnement, mais vous devrait la version contrôle tout.

Cela vous permet également d'examiner les configurations des autres, ce qui peut aider à diagnostiquer les problèmes de build et de plate-forme.

Mon équipe conserve des versions distinctes des fichiers de configuration pour chaque environnement (web.config.dev, web.config.test, web.config.prod).Nos scripts de déploiement copient la version correcte et la renomment web.config.De cette façon, nous avons un contrôle de version complet sur les fichiers de configuration pour chaque environnement, pouvons facilement effectuer une comparaison, etc.

Actuellement, j'ai le fichier de configuration "modèle" avec une extension ajoutée par exemple :

web.config.rename

Cependant, je peux voir un problème avec cette méthode si des changements critiques ont changé.

La solution que nous utilisons est de n'avoir qu'un seul fichier de configuration (web.config/app.config), mais nous ajoutons une section spéciale au fichier qui contient les paramètres de tous les environnements.

Il y a un LOCAL, DÉV, QA, PRODUCTION sections contenant chacune les clés de configuration pertinentes pour cet environnement dans notre (nos) fichier (s) de configuration.

Ce qui fait que tout cela fonctionne, c'est une assemblée nommée xxx.Environnement qui est référencé dans toutes nos applications (winforms et webforms) et qui indique à l'application sur quel environnement elle fonctionne.

L'assembly xxx.Environment lit une seule ligne d'informations à partir du machine.config de la machine donnée qui lui indique qu'elle est en DEV, QA, etc.Cette entrée est présente sur tous nos postes de travail et serveurs.

J'espère que cela t'aides.

+1 sur l'approche modèle.

Mais comme cette question a étiqueté, l'alternative distribuée vient à l'esprit, dans laquelle les personnalisations sont conservées sur une branche de tests privés:

A---B---C---D---           <- mainline (public)
     \       \
      B'------D'---        <- testing (private)

Dans ce schéma, la ligne principale contient un fichier de configuration générique "modèle" nécessitant la quantité minimale d'ajustements pour devenir fonctionnel.

Maintenant, les développeurs / testeurs peuvent modifier le fichier de configuration au contenu de leur cœur et ne commettre ces modifications localement sur une branche de tests privés (par exempleB' = B + personnalisations).Chaque fois que la ligne principale progresse, ils le fusionnent sans effort en tests, ce qui se traduit par des commits de fusion tels que D '(= d + version fusionnée des personnalisations de B).

Ce schéma brille vraiment lorsque le fichier de configuration « modèle » est mis à jour :Les changements des deux côtés sont fusionnés et sont extrêmement susceptibles de se traduire par des conflits (ou des échecs de test) s'ils sont incompatibles!

J'ai déjà utilisé le modèle, c'est-à-direweb.dev.config, web.prod.config, etc, mais préfèrent désormais la technique du « fichier de remplacement ».Le fichier web.config contient la majorité des paramètres, mais un fichier externe contient des valeurs spécifiques à l'environnement telles que les connexions à la base de données.Bonne explication sur Le blog de Paul Wilson.

Je pense que cela réduit le nombre de duplications entre les fichiers de configuration, ce qui peut causer des problèmes lors de l'ajout de nouvelles valeurs/attributs.

J'ai toujours conservé toutes les versions des fichiers de configuration dans le contrôle de source, dans le même dossier que le fichier web.config.

Par exemple

web.config
web.qa.config
web.staging.config
web.production.config

Je préfère cette convention de dénomination (par opposition à web.config.production ou production.web.config) car

  • Il conserve les fichiers ensemble lorsque vous les triez par nom de fichier
  • Il conserve les fichiers ensemble lorsque vous les triez par extension de fichier
  • Si le fichier est accidentellement poussé en production, vous ne pourrez pas voir le contenu via http car IIS empêchera la diffusion des fichiers *.config.

Le fichier de configuration par défaut doit être configuré de manière à ce que vous puissiez exécuter l'application localement sur votre propre ordinateur.

Plus important encore, ces fichiers doivent être presque 100 % identiques dans tous leurs aspects, même au niveau du formatage.Vous ne devez pas utiliser de tabulations dans une version et d'espaces dans une autre pour l'indentation.Vous devriez pouvoir exécuter un outil de comparaison sur les fichiers pour voir exactement ce qui est différent entre eux.Je préfère utiliser WinMerge pour comparer les fichiers.

Lorsque votre processus de construction crée les binaires, une tâche doit écraser le fichier web.config par le fichier de configuration approprié à cet environnement.Si les fichiers sont compressés, les fichiers non pertinents doivent être supprimés de cette version.

@Grant a raison.

Je fais partie d'une équipe avec près de 100 autres développeurs et nos fichiers de configuration ne sont pas archivés dans le contrôle de source.Nous avons des versions des fichiers dans le référentiel qui sont extraites à chaque extraction, mais elles ne changent pas.

Cela a plutôt bien fonctionné pour nous.

Je le contrôle de version, mais je ne le transmets jamais aux autres serveurs.Si le serveur de production nécessite une modification, j'apporte cette modification directement au fichier de configuration.

Ce n'est peut-être pas joli, mais ça fonctionne très bien.

La version simple et enregistrée de app/web.config doit être suffisamment générique pour fonctionner sur toutes les machines de développement et être tenue à jour avec toute nouvelle modification de paramètres, etc.Si vous avez besoin d'un ensemble spécifique de paramètres pour les paramètres de développement/test/production, archivez des fichiers séparés avec ces paramètres, comme GateKiller l'a indiqué, avec une sorte de convention de dénomination, bien que j'utilise généralement "web.prod.config", car ce n'est pas le cas. pour changer l'extension du fichier.

Nous utilisons un fichier de configuration de modèle qui est archivé dans le contrôle de version, puis une étape de notre construction automatisée pour remplacer les entrées spécifiques du fichier modèle par des paramètres spécifiques à l'environnement.Les paramètres spécifiques à l'environnement sont stockés dans un fichier XML distinct qui est également sous contrôle de version.

Nous utilisons MSBuild dans notre build automatisé, nous utilisons donc la tâche XmlUpdate de Tâches de la communauté MSBuild pour mettre à jour les valeurs.

Pendant longtemps, j’ai fait exactement ce que bcwood a fait.Je conserve des copies de web.dev.config, web.test.config, web.prod.config, etc.sous contrôle de source, puis mon système de construction/déploiement les renomme automatiquement au fur et à mesure qu'il se déploie dans divers environnements.Vous obtenez une certaine redondance entre les fichiers (en particulier avec tous les éléments asp.net qu'il contient), mais en général, cela fonctionne très bien.Vous devez également vous assurer que tous les membres de l'équipe se souviennent de mettre à jour tous les fichiers lorsqu'ils effectuent une modification.

À propos, j'aime garder ".config" à la fin comme extension afin que les associations de fichiers ne soient pas rompues.

En ce qui concerne les versions de développement local du fichier de configuration, je fais toujours de mon mieux pour encourager les gens à utiliser autant que possible les mêmes paramètres locaux afin qu'il ne soit pas nécessaire d'avoir votre propre version.Cela ne fonctionne pas toujours pour tout le monde, auquel cas les gens se contentent généralement de le remplacer localement selon les besoins et de partir de là.Ce n'est pas trop douloureux ou quoi que ce soit.

Sur notre projet, nous avons la configuration stockée dans des fichiers avec un préfixe, puis notre système de construction récupère la configuration appropriée en fonction du nom d'hôte du système actuel.Cela fonctionne bien pour nous dans une équipe relativement petite, nous permettant d'appliquer des modifications de configuration aux fichiers d'autres personnes si/quand nous ajoutons un nouvel élément de configuration.Évidemment, cela ne s'applique certainement pas aux projets open source avec un nombre illimité de développeurs.

Nous avons ici deux problèmes.

  • Tout d'abord, nous devons contrôler le fichier de configuration fourni avec le logiciel.

    Il est facile pour un développeur d'enregistrer une modification indésirable dans le fichier de configuration principal, s'il utilise le même fichier dans l'environnement de développement.

    D'un autre côté, si vous disposez d'un fichier de configuration distinct inclus par le programme d'installation, il est très facile d'oublier d'y ajouter un nouveau paramètre ou de laisser les commentaires qu'il contient se désynchroniser avec les commentaires du développement. fichier de configuration.

  • Nous avons ensuite le problème que les développeurs doivent conserver une copie du fichier de configuration à jour lorsque d'autres développeurs ajoutent de nouveaux paramètres de configuration.Cependant, certains paramètres tels que les chaînes de connexion à la base de données sont différents pour chaque développeur.

  • Il y a un troisième problème que les questions/réponses ne couvrent pas. Comment intégrer les modifications qu'un client a apportées à votre fichier de configuration lorsque vous installez une nouvelle version de votre logiciel ?

Je n'ai pas encore vu de bonnes solutions qui fonctionnent bien dans tous les cas, mais j'en ai vu solutions partielles(qui peut être combiné dans différentes combinaisons selon les besoins) qui réduit beaucoup le problème.

  • Réduisez d’abord le nombre d’éléments de configuration que vous avez dans votre fichier de configuration principal.

    Si vous n'avez pas besoin de laisser vos clients modifier vos mappages, utilisez Fluent NHibernate (ou autre) pour déplacer la configuration dans le code.

    De même pour la configuration de l’injection de dépendance.

  • Divisez le fichier de configuration lorsque cela est possible, par ex.utilisez un fichier séparé pour configurer les journaux Log4Net.

  • Ne répétez pas les éléments entre de nombreux fichiers de configuration, par ex.si vous avez 4 applications Web toutes installées sur la même machine, disposez d'un fichier de configuration global vers lequel pointe le fichier web.config de chaque application.

    (Utilisez un chemin relatif par défaut, il est donc rare de devoir modifier le fichier web.config)

  • Traitez le fichier de configuration de développement pour obtenir le fichier de configuration d'expédition.

    Cela pourrait être fait en ayant des valeurs par défaut dans les commentaires XML qui sont ensuite définies dans le fichier de configuration lorsqu'une construction est terminée.Ou avoir des sections supprimées dans le cadre du processus de création du programme d'installation.

  • Au lieu de n'avoir qu'une seule chaîne de connexion à la base de données, ayez-en une par développeur.

    Par exemple, recherchez d'abord "database_ianr" (où ianr est mon nom d'utilisateur ou le nom de ma machine) dans le fichier de configuration au moment de l'exécution, s'il n'est pas trouvé, recherchez "database"

    Avoir un 2ème niveau "ex.-oracle ou -sqlserver" permettent aux développeurs d'accéder plus rapidement aux deux systèmes de bases de données.

    Bien entendu, cela peut également être fait pour toute autre valeur de configuration.

    Ensuite, toutes les valeurs qui se terminent par « _userName » peuvent être supprimées avant d'envoyer le fichier de configuration.

Cependant, en fin de compte, ce que vous est un «propriétaire du fichier de configuration» qui prend la gestion de responsabilité de la gestion du (s) fichier (s) de configuration comme ci-dessus ou autrement.Il / elle devrait également faire un DIFF sur le fichier de configuration des faces des clients avant chaque expédition.

Vous ne pouvez pas supprimer le besoin d’une personne attentionnée sans problème.

Je ne pense pas qu'il existe une solution unique qui fonctionne dans tous les cas, car cela peut dépendre de la sensibilité des données contenues dans les fichiers de configuration, du langage de programmation que vous utilisez et de nombreux autres facteurs.Mais je pense qu'il est important de conserver les fichiers de configuration de tous les environnements sous contrôle de source, afin que vous puissiez toujours savoir quand ils ont été modifiés et par qui, et plus important encore, pouvoir les récupérer en cas de problème.Et ils le feront.

Alors voici comment je procède.Ceci est généralement destiné aux projets nodejs, mais je pense que cela fonctionne également pour d'autres frameworks et langages.

Ce que je fais, c'est créer un configs répertoire à la racine du projet, et sous ce répertoire, conservez plusieurs fichiers pour tous les environnements (et parfois des fichiers séparés pour l'environnement de chaque développeur également) qui sont tous suivis dans le contrôle de code source.Et il y a le fichier réel que le code utilise nommé config à la base du projet.C'est le seul fichier qui n'est pas suivi.Donc ça ressemble à ça

root
|
|- config (not tracked)
|
|- configs/ (all tracked)
    |- development
    |- staging
    |- live
    |- James

Lorsque quelqu'un extrait le projet, il copie le fichier de configuration qu'il souhaite utiliser dans le fichier non suivi. config et il est libre de le modifier comme il le souhaite, mais il est également responsable de copier ces modifications avant de s'engager dans les autres fichiers d'environnement selon ses besoins.

Et sur les serveurs, le fichier non suivi peut simplement être une copie (ou une référence) du fichier suivi correspondant à cet environnement.Dans JS, vous pouvez simplement avoir 1 ligne pour exiger ce fichier.

Ce flux peut être un peu compliqué au début mais il présente de grands avantages :1.Vous n'avez jamais à vous soucier qu'un fichier de configuration soit supprimé ou modifié sur le serveur sans avoir de sauvegarde 2.La même chose si un développeur a une configuration personnalisée sur sa machine et que sa machine cesse de fonctionner pour quelque raison que ce soit 3.Avant tout déploiement, vous pouvez comparer les fichiers de configuration pour development et staging par exemple et voyez s'il manque quelque chose ou s'il est cassé.

Nous gardons simplement le fichier de configuration de production archivé.Il est de la responsabilité du développeur de modifier le fichier lorsqu'il le retire du coffre-fort des sources pour la préparation ou le développement.Cela nous a brûlés dans le passé, donc je ne le suggérerais pas.

J'ai été confronté au même problème et j'ai trouvé une solution.J'ai d'abord ajouté tous les fichiers au référentiel central (également ceux des développeurs).

Ainsi, si un développeur récupère les fichiers du référentiel, la configuration du développeur est également présente.Lors des modifications apportées à ce fichier, Git ne doit pas être conscient de ces modifications.De cette façon, les modifications ne peuvent pas être poussées/validées dans le référentiel mais restent localement.

J'ai résolu ce problème en utilisant la commande git : update-index --assume-unchanged.J'ai créé un fichier bat qui est exécuté dans la pré-construction des projets contenant un fichier dont les modifications doivent être ignorées par Git.Voici le code que j'ai mis dans le fichier bat :

IF NOT EXIST %2%\.git GOTO NOGIT
set fileName=%1
set fileName=%fileName:\=/%
for /f "useback tokens=*" %%a in ('%fileName%') do set fileName=%%~a
set "gitUpdate=git update-index --assume-unchanged"
set parameter= "%gitUpdate% %fileName%"
echo %parameter% as parameter for git
"C:\Program Files (x86)\Git\bin\sh.exe" --login -i -c %parameter%
echo Make FIleBehaveLikeUnchangedForGit Done.
GOTO END
:NOGIT
echo no git here.
echo %2%
:END

Dans ma pré-construction, j'appellerais le fichier bat, par exemple :

call "$(ProjectDir)\..\..\MakeFileBehaveLikeUnchangedForGit.bat" "$(ProjectDir)Web.config.developer" "$(SolutionDir)"

J'ai trouvé sur SO un fichier bat qui copie le fichier de configuration correct dans web.config/app.config.J'appelle également ce fichier bat dans la pré-construction.Le code de ce fichier bat est :

@echo off
echo Comparing two files: %1 with %2
if not exist %1 goto File1NotFound
if not exist %2 goto File2NotFound
fc %1 %2 
if %ERRORLEVEL%==0 GOTO NoCopy
echo Files are not the same.  Copying %1 over %2
copy %1 %2 /y & goto END
:NoCopy
echo Files are the same.  Did nothing
goto END
:File1NotFound
echo %1 not found.
goto END
:File2NotFound
copy %1 %2 /y
goto END
:END
echo Done.

Dans ma pré-construction, j'appellerais le fichier bat, par exemple :

call "$(ProjectDir)\..\..\copyifnewer.bat" "$(ProjectDir)web.config.$(ConfigurationName)" "$(ProjectDir)web.config
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top