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

96

Disons que vous avez une application Web typique et un fichier de configuration. Chaque développeur travaillant sur le projet aura une version pour ses boîtes de développement, il y aura des versions de développement, de production et de scène. Comment gérez-vous cela dans le contrôle de code source? Ne pas archiver du tout ce fichier, le vérifier avec des noms différents ou faire quelque chose de compliqué?

programmeur mort
la source

Réponses:

69

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 a son propre fichier de configuration de remplacement qui est exclu du contrôle de code source. L'application charge d'abord la valeur 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 avec un environnement très non standard.

Yukondude
la source
24

La configuration est du code et vous devez le version. 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 que ceux-ci sont uniques au projet, tout va bien. Vous pouvez même passer outre cela dans l'environnement, mais vous devriez tout contrôle de version.

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

davetron5000
la source
10
+1 absolument pour souligner que la configuration doit toujours être versionnée
Alexander Bird
Et si le nom d'utilisateur n'est pas fiable pour une raison quelconque, vous pouvez avoir un seul fichier avec une seule ligne donnant le nom du fichier de configuration de remplacement. De cette façon, il y en a très peu (environ 10 caractères environ) qui ne sont pas contrôlés par version. Et le fichier README pourrait expliquer que vous devez créer ce fichier.
Alexander Bird
Je pense toujours que les configurations doivent être séparées du code. J'ai travaillé dans des endroits qui nécessitent tellement de configurations pour un dépôt que Git est tout simplement submergé par les fichiers de configuration. Ne disant pas que les configurations ne devraient pas être versionnées, elles appartiennent ailleurs comme un gestionnaire d'artefacts. La configuration n'est pas du code, ce sont des paramètres pour le code.
Thomas
Les fichiers de configuration peuvent contenir des informations sensibles telles que des mots de passe qui ne doivent pas être versionnés. Ou souhaitez-vous accorder à chaque développeur l'accès à votre environnement de production? Je pense qu'il vaut mieux juste une version d'une "configuration principale" et la remplacer dans des environnements spécifiques.
Christophe Weis
19

Ne versez pas ce fichier. Version un modèle ou quelque chose.

Subvention
la source
2
J'utilise cette approche, j'ai juste un main.php.tmpl et quand je vérifie une nouvelle copie, copiez-la simplement dans main, php. J'ajoute le fichier main.php à la liste des ignorés pour éviter de le valider par accident.
levhita le
10

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 un diff, etc.

Bois Brandon
la source
6

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 des changements critiques ont changé.

GateKiller
la source
6

+1 sur l'approche modèle.

Mais comme cette question a tagué Git, l'alternative distribuée vient à l'esprit, dans laquelle les personnalisations sont conservées sur une branche 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 «modèle» générique nécessitant un minimum d'ajustements pour devenir fonctionnel.

Désormais, les développeurs / testeurs peuvent modifier le fichier de configuration à leur guise, et ne valider ces modifications que localement sur une branche de test privée (par exemple, B '= B + personnalisations). Chaque fois que la ligne principale avance, ils la fusionnent sans effort dans les tests, ce qui entraîne 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 changements des deux côtés sont fusionnés, et sont extrêmement susceptibles d'entraîner des conflits (ou des échecs de test) s'ils sont incompatibles!

Damien Diederen
la source
Mais lorsque les développeurs testeurs poussent dans la ligne principale, leurs modifications dans le fichier de modèle seront également intégrées. Non?
Nick Zalutskiy
À moins qu'il n'y ait une solution au commentaire de Nick, cela ne fonctionnera pas d'après ce que je vois. Ou peut-être expliquez-vous quel modèle de flux vous utilisez pour résoudre le problème.
Alexander Bird
Je suis d'accord avec l'approche du modèle avec tous les ajustements nécessaires intégrés au moment de la construction. Cependant sur le sujet des branches ... Et s'il y avait plusieurs modèles (dev, test, etc.) et que les développeurs omettent simplement les changements de leurs commits. Pas infaillible mais pourrait fonctionner avec la coopération.
NickSuperb
5

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 pour tous les environnements.

Il y a une section LOCAL, DEV, QA, PRODUCTION 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 un assemblage nommé xxx.Environment qui est référencé dans toutes nos applications (winforms et webforms) qui indique à l'application sur quel environnement elle fonctionne.

L'assembly xxx.Environment lit une seule ligne d'informations à partir du fichier machine.config de la machine donnée qui lui indique qu'elle est 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.

Jason Stevenson
la source
1
Cela fonctionne extrêmement bien s'il n'y a que quelques différences entre l'environnement (c.-à-d. Les chaînes de connexion)
Eric Labashosky
et en supposant qu'il n'y a pas des centaines de développeurs qui y mettent tous leurs paramètres personnalisés (cela fonctionnerait toujours, mais serait très encombrant)
Alexander Bird
5

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 dénomination (par opposition à web.config.production ou production.web.config) car

  • Il garde les fichiers ensemble lorsque vous triez par nom de fichier
  • Il garde les fichiers ensemble lorsque vous 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 les fichiers * .config d'être servis

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

Plus important encore, ces fichiers doivent être presque identiques à 100% dans tous les aspects, même le formatage. Vous ne devez pas utiliser d'onglets 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 différencier les fichiers.

Lorsque votre processus de construction crée les binaires, une tâche doit remplacer le fichier web.config par 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.

JackAce
la source
4

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 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 la quantité de duplication entre les fichiers de configuration, ce qui peut causer des problèmes lors de l'ajout de nouvelles valeurs / attributs.

Andy Whitfield
la source
3

@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 code 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.

À M
la source
2

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

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

En voie de disparitionMassa
la source
2

La version archivée et simple 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 des paramètres, etc. Si vous avez besoin d'un ensemble spécifique de paramètres pour le développement / test / production settings, archivez des fichiers séparés avec ces paramètres, comme l'a déclaré GateKiller, avec une sorte de convention de dénomination, bien que j'utilise généralement "web.prod.config", pour ne pas changer l'extension du fichier.

Greg Hurlman
la source
2

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 des entrées spécifiques dans le fichier de 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 également sous contrôle de version.

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

Sean Carpenter
la source
2

Pendant longtemps, j'ai fait exactement ce que bcwood a fait. Je garde des copies de web.dev.config, web.test.config, web.prod.config, etc. sous le contrôle du code source, puis mon système de construction / déploiement les renomme automatiquement lors de son déploiement dans divers environnements. Vous obtenez une certaine redondance entre les fichiers (en particulier avec tous les éléments asp.net), mais généralement 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 apportent une modification.

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 de développement local du fichier de configuration, je fais toujours de mon mieux pour encourager les gens à utiliser les mêmes paramètres locaux autant que possible afin qu'il n'y ait pas besoin d'avoir votre propre version. Cela ne fonctionne pas toujours pour tout le monde, auquel cas les gens le remplacent généralement localement au besoin et partent de là. Ce n'est pas trop douloureux ou quoi que ce soit.

Jeremcc
la source
1

Sur notre projet, nous avons la 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 dans une équipe relativement petite, ce qui nous permet d'appliquer des modifications de configuration aux fichiers d'autres personnes si / lorsque nous ajoutons un nouvel élément de configuration. De toute évidence, cela ne s'adapte pas aux projets open source avec un nombre illimité de développeurs.

Rob Oxspring
la source
1

Nous avons deux problèmes ici.

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

    Il est facile pour un développeur d'archiver un changement indésirable dans le fichier de configuration principal, s'il utilise le même fichier dans l'environnement de dévolution.

    D'un autre côté, si vous avez un fichier de configuration séparé qui est inclus par l'installateur, 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 de la dévolution fichier de configuration.

  • Ensuite, nous avons le problème que les développeurs doivent conserver une copie du fichier de configuration à jour alors que 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 la question / les réponses ne couvrent pas. Comment fusionner 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'ai vu des solutions partielles (qui peuvent être combinées dans différentes combinaisons selon les besoins) qui réduisent 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 d'injection de dépendances.

  • Divisez le fichier de configuration lorsque cela est possible, par exemple, 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 exemple, si vous avez 4 applications Web qui sont toutes installées sur la même machine, ayez un fichier de configuration global vers lequel pointe le fichier web.config dans chaque application.

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

  • Traitez le fichier de configuration de 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éfinis dans le fichier de configuration lorsqu'une génération est terminée. Ou avoir des sections qui sont 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, utilisez-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é, puis recherchez "database"

    Avoir un deuxième niveau "par exemple -oracle ou -sqlserver" permet aux développeurs d'accéder plus rapidement aux deux systèmes de bases de données.

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

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

Cependant à la fin ce que vous êtes est un «propriétaire du fichier de configuration» qui prend la responsabilité de gérer le (s) fichier (s) de configuration comme ci-dessus ou autrement. Il / Elle doit également faire une différence sur le fichier de configuration des faces client avant chaque expédition.

Vous ne pouvez pas supprimer le besoin d'une personne attentionnée, à court de problème.

Ian Ringrose
la source
1

Je ne pense pas qu'il existe une solution unique qui fonctionne pour tous les cas, car cela peut dépendre de la sensibilité des données dans les fichiers de configuration, ou du langage de programmation que vous utilisez, et de tant d'autres facteurs. Mais je pense qu'il est important de garder les fichiers de configuration pour tous les environnements sous contrôle de code source, afin que vous puissiez toujours savoir quand ils ont été modifiés et par qui, et plus important encore, être en mesure de les récupérer si les choses tournent mal. Et ils le feront.

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

Ce que je fais, c'est créer un configsrépertoire à la racine du projet et, sous ce répertoire, conserver plusieurs fichiers pour tous les environnements (et parfois des fichiers séparés pour l'environnement de chaque développeur) 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 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 souhaite utiliser dans le configfichier non suivi 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 si nécessaire.

Et sur les serveurs, le fichier non suivi peut simplement être une copie (ou 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 de la suppression ou de la modification d'un fichier de configuration sur le serveur sans avoir une sauvegarde 2. De même si un développeur a une configuration personnalisée sur son la machine et sa machine cessent de fonctionner pour une raison quelconque 3. Avant tout déploiement, vous pouvez comparer les fichiers de configuration pour developmentet stagingpar exemple et voir si quelque chose manque ou est cassé.

gafi
la source
0

Nous conservons simplement le fichier de configuration de production archivé. Il est de la responsabilité du développeur de modifier le fichier lorsqu'il le extrait de la source en toute sécurité pour la préparation ou le développement. Cela nous a brûlés dans le passé, donc je ne le suggérerais pas.

Ryan
la source
0

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

Donc, si un développeur récupère les fichiers du référentiel, la configuration du développeur est également là. Lors de la modification apportée à 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 rester localement.

Je 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 qui contiennent 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 pré-build, je ferais un appel au fichier bat, par exemple:

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

J'ai trouvé sur SO un fichier chauve-souris qui copie le fichier de configuration correct dans le web.config / app.config. J'appelle également ce fichier chauve-souris 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 mon pré-build, je ferais un appel au fichier bat, par exemple:

call "$(ProjectDir)\..\..\copyifnewer.bat" "$(ProjectDir)web.config.$(ConfigurationName)" "$(ProjectDir)web.config
Benny Emmers
la source