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

Disons que vous avez une application Web typique et une configuration de fichier. 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 des sources? Ne pas archiver ce fichier, le vérifier avec des noms différents ou faire quelque chose de compliqué?

Ce que j’ai fait dans le passé est d’avoir un fichier de configuration par défaut qui est archivé pour le contrôle de la source. Ensuite, chaque développeur dispose de son propre fichier de configuration de substitution qui est exclu du contrôle de source. L’application charge d’abord le fichier par défaut, puis, si le fichier de remplacement est présent, le charge et utilise les parameters 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 parameters pour un développeur avec un environnement très non standard.

Ne version pas ce fichier. Version d’un modèle ou quelque chose.

La configuration est du code, et vous devez le mettre à jour. Nous basons nos fichiers de configuration sur les noms d’utilisateur; sous UNIX / Mac et Windows, vous pouvez accéder à l’identifiant de connexion de l’utilisateur, et tant que ces informations sont spécifiques au projet, vous êtes en règle. Vous pouvez même remplacer cela dans l’environnement, mais vous devriez tout contrôler par la version.

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

Mon équipe conserve des versions séparées 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, en la renommant web.config. De cette façon, nous avons un contrôle de version complet sur les fichiers de configuration pour chaque environnement, nous pouvons facilement effectuer un diff, etc.

Actuellement, j’ai le fichier de configuration “template” avec une extension supplémentaire, par exemple:

web.config.rename 

Cependant, je peux voir un problème avec cette méthode si les 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 contenant les parameters pour tous les environnements.

Il y a des sections LOCAL, DEV, QA, PRODUCTION contenant chacune les clés de configuration pertinentes pour cet environnement dans nos fichiers de configuration.

Ce qui fait que tout cela fonctionne est un assembly nommé xxx.Environment qui est référencé dans toutes nos applications (winforms et webforms) qui indique à l’application dans quel environnement elle fonctionne.

L’assembly xxx.Environment lit une seule ligne d’informations à partir de la machine.config de la machine donnée qui lui indique qu’il se trouve sur 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 du modèle.

Mais puisque cette question a le tag Git, les alternatives dissortingbuées sont à l’esprit, dans lesquelles les personnalisations sont conservées sur une twig de test privée:

 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 le minimum de réglages pour devenir fonctionnel.

Maintenant, les développeurs / testeurs peuvent modifier le fichier de configuration en fonction de leur contenu, et ne valider que localement ces modifications sur une twig de test privée (par exemple, personnalisations B '= B +). Chaque fois que la ligne principale avance, elle la fusionne sans effort avec des tests, ce qui se traduit par des validations de fusion telles que D '(= D + version fusionnée des personnalisations de B).

Ce schéma brille vraiment lorsque le fichier de configuration "template" est mis à jour: les modifications des deux côtés sont fusionnées et risquent fort de provoquer des conflits (ou des échecs de test) si elles sont incompatibles!

J’ai déjà utilisé le modèle, c’est-à-dire web.dev.config, web.prod.config, etc., mais je préfère maintenant la technique du “fichier de substitution”. Le fichier web.config contient la majorité des parameters, mais un fichier externe contient des valeurs spécifiques à l’environnement, telles que les connexions à la firebase database. Bonne explication sur le blog de Paul Wilson .

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

@Grant a raison.

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

Cela s’est très bien passé pour nous.

J’ai toujours conservé toutes les versions des fichiers de configuration dans le contrôle de code 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 nommage (par opposition à web.config.production ou production.web.config) car

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

Le fichier de configuration par défaut doit être configuré de sorte que vous puissiez exécuter l’application localement sur votre propre ordinateur.

Plus important encore, ces fichiers doivent être presque 100% identiques dans tous les aspects, même le formatage. Vous ne devez pas utiliser les tabs dans une version et les espaces dans une autre pour l’indentation. Vous devriez pouvoir exécuter un outil de comparaison sur les fichiers pour voir exactement ce qui les différencie. Je préfère utiliser WinMerge pour différencier les fichiers.

Lorsque votre processus de génération crée les fichiers binarys, une tâche doit remplacer le fichier web.config avec le fichier de configuration approprié pour cet environnement. Si les fichiers sont compressés, les fichiers non pertinents doivent être supprimés de cette version.

Je contrôle la version, mais ne le pousse jamais vers les autres serveurs. Si le serveur de production nécessite une modification, je le modifie directement dans le fichier de configuration.

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

La version archivée de plain / vanilla de app / web.config devrait être suffisamment générique pour fonctionner sur toutes les machines de développement, et être mise à jour avec toute nouvelle modification de paramètre, etc. Si vous avez besoin d’un ensemble spécifique de parameters pour dev / test / production settings, archivez des fichiers séparés avec ces parameters, comme indiqué par GateKiller, avec une sorte de convention de nommage, bien que je passe généralement par “web.prod.config”, pour ne pas modifier 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 génération automatisée pour remplacer des entrées spécifiques du fichier de modèle par des parameters spécifiques à l’environnement. Les parameters spécifiques à l’environnement sont stockés dans un fichier XML distinct, également sous contrôle de version.

Nous utilisons MSBuild dans notre génération automatisée, nous utilisons donc la tâche XmlUpdate de MSBuild Community Tasks 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 code source, puis mon système de génération / déploiement les renomme automatiquement lorsqu’il se déploie dans différents environnements. Vous obtenez une certaine redondance entre les fichiers (en particulier avec tous les éléments asp.net), mais cela fonctionne généralement 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 apportent des modifications.

Au fait, j’aime garder “.config” à la fin comme extension pour que les associations de fichiers ne soient pas brisées.

En ce qui concerne les versions locales des développeurs du fichier de configuration, je fais toujours de mon mieux pour encourager les utilisateurs à utiliser autant que possible les mêmes parameters locaux afin de ne pas avoir besoin de votre propre version. Cela ne marche pas toujours pour tout le monde, auquel cas les gens le remplacent généralement au besoin et partent de là. Ce n’est pas trop douloureux ou quoi que ce soit.

Sur notre projet, nous avons une configuration stockée dans des fichiers avec un préfixe, puis notre système de construction extrait la configuration appropriée en fonction du nom d’hôte du système actuel. Cela fonctionne bien pour nous sur 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 permet pas de déployer des projets open source avec un nombre illimité de développeurs.

Nous ne conservons que le fichier de configuration de production archivé. Il appartient au développeur de modifier le fichier lorsqu’il le sort de la source en toute sécurité pour le staging ou le développement. Cela nous a brûlé dans le passé, donc je ne le suggérerais pas.

Nous avons deux problèmes ici.

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

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

    D’un autre côté, si vous avez un fichier de configuration séparé inclus par l’installateur, il est très facile d’oublier d’append un nouveau paramètre, ou de laisser les commentaires se désynchroniser avec les commentaires de la délégation. configuration du fichier.

  • Ensuite, nous avons le problème que les développeurs doivent conserver à jour la copie du fichier de configuration lorsque d’autres développeurs ajoutent de nouveaux parameters de configuration. Cependant, certains parameters tels que les chaînes de connexion à la firebase database sont différents pour chaque développeur.

  • Il y a un troisième problème que les questions / réponses ne couvrent pas. Comment fusionner les modifications apscopes par un client à 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, cependant j’ai vu des solutions partielles (qui peuvent être combinées en différentes combinaisons selon les besoins) qui réduisent beaucoup le problème.

  • Réduisez tout 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épence.

  • Divisez le fichier de configuration lorsque cela est possible, par exemple, utilisez un fichier séparé pour configurer ce que Log4Net enregistre.

  • Ne répétez pas les éléments entre de nombreux fichiers de configuration. Par exemple, si vous disposez de 4 applications Web installées sur le même ordinateur, indiquez un fichier de configuration global sur lequel le fichier web.config de chaque application pointe.

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

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

    Cela peut ê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 génération est effectuée. Ou avoir des sections qui sont supprimées dans le cadre du processus de création du programme d’installation.

  • Au lieu d’avoir juste une firebase database, les chaînes de connexion en ont une par développeur.

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

    Avoir un deuxième niveau “eg -oracle ou -sqlserver” permet aux développeurs d’accéder plus rapidement aux deux systèmes de firebase database.

    Cela peut bien sûr être fait pour toute autre valeur de configuration.

    Ensuite, toutes les valeurs se terminant par «_userName» peuvent être agrégées avant d’envoyer le fichier de configuration.

Cependant, en fin de compte, vous êtes un «propriétaire de fichier de configuration» qui gère de manière responsable le ou les fichiers de configuration comme ci-dessus ou autrement. Il / Elle doit également faire une différence sur le fichier de configuration des façades avant chaque envoi.

Vous ne pouvez pas éliminer le besoin d’une personne bienveillante en partie à court de problème.

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

Alors, voici comment je le fais. C’est généralement pour les projets nodejs mais je pense que cela fonctionne aussi pour les autres frameworks et langages.

Ce que je fais, c’est créer un répertoire de configs à la racine du projet et, sous ce répertoire, conserver plusieurs fichiers pour tous les environnements (et parfois des fichiers distincts pour chaque environnement de développeur), tous suivis dans le contrôle de code source. Et il y a le fichier réel que le code utilise nommé config à la racine 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 

Quand quelqu’un extrait le projet, il copie le fichier de configuration qu’il veut utiliser dans le fichier de config suivi et il est libre de le modifier comme il le souhaite, mais il doit également copier ces modifications avant de les valider.

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 une ligne pour demander ce fichier.

Ce stream peut être un peu compliqué au début, mais il présente de grands avantages: 1. Vous n’avez jamais à vous soucier de la suppression ou de la modification d’un fichier de configuration sur le serveur sans une sauvegarde. La machine et sa machine cessent de fonctionner pour une raison quelconque. 3. Avant tout déploiement, vous pouvez modifier les fichiers de configuration pour le development et le staging par exemple, et voir si quelque chose est manquant ou cassé.

J’ai rencontré le 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 du développeur).

Donc, si un développeur récupère les fichiers à partir du référentiel, la configuration du développeur est également présente. Lors de la modification de ce fichier, Git ne devrait pas être au courant de ces modifications. De cette façon, les modifications ne peuvent pas être transférées au référentiel mais restr 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 le 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 mon prebuild, je faisais un appel au 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 le fichier web.config / app.config. J’appelle aussi ce fichier de chauve-souris dans la pré-construction. Le code de ce fichier de chauve-souris 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 mon prebuild, je faisais un appel au fichier bat, par exemple:

 call "$(ProjectDir)\..\..\copyifnewer.bat" "$(ProjectDir)web.config.$(ConfigurationName)" "$(ProjectDir)web.config