From: Wilson, B. <Bri...@dh...> - 2011-08-29 20:11:06
|
You are welcome, we are working on getting TFS2010 up and running, so I shouldn't have to worry about this as much. Hopefully. Brian Wilson Programmer Analyst, Associate Department of Human Resources Email: bri...@dh...<mailto:bri...@dh...> From: Scott Pennington [mailto:spe...@pr...] Sent: Monday, August 29, 2011 3:08 PM To: nan...@li... Subject: Re: [NAnt-users] xmlpoke vs token replace for Config Files Brian, This solution wont really work for us since we plan to have multiple dev environments and then multiple promotion streams and each a at least 5 machines for the install with multiple configs for each machine. it gets to be a lot of changes in a lot of files. I can see this working for a smaller install. Thanks Scott From: Wilson, Brian [mailto:Bri...@dh...] Sent: Monday, August 29, 2011 12:47 PM To: nan...@li... Subject: Re: [NAnt-users] xmlpoke vs token replace for Config Files Good Afternoon, I use a less elegant design, but here it goes. We usually don't have very many changes so I have created a config file for each environment. * config.dev.cfg * config.qa.cfg * config.prod.cfg Prior to the compilation of the project, I delete the config.cfg file and rename the config.prod.cfg to config.cfg. The only real problem is the problem you stated where a new AppSetting is not added, but it eliminates several of the drawbacks stated. Tell me what you think. Brian Wilson Programmer Analyst, Associate Department of Human Resources Email: bri...@dh...<mailto:bri...@dh...> From: Scott Pennington [mailto:spe...@pr...] Sent: Monday, August 29, 2011 1:50 PM To: nan...@li... Subject: [NAnt-users] xmlpoke vs token replace for Config Files This is a long post. The simple question is what methods have you chosen to maintain config files when deployed to multiple environments? I am in the process of reworking a set of build, package, install NAnt scripts that mainly use Token Replace and I am trying to decide if it is better to switch to a method I have used before of XMLPoke. The current method is to take the existing config file and replace the AppSettings with a version of the AppSettings that have all of the values replaced as tokens with the token name being the same name as the key. When the script comes to the part where it needs to set the values for the environment it will pass the each config file to a single target. In the target it has all of the replacestokens for each file seperated by an if in the <replacetokens if="${output.config.name == 'MailerService.exe.config'}"> and then it sets the tokens for that specific config file. Once it has gone through all the ones it know s about it has a section that it tries to catch the ones that might be there. I see some good things and bad things with this method. Bad 1) I don't really like the Target being the all in one place for each config file (this could be fixed with refactoring) 2) Lots of repeated values (this could be fixed with refactoring) 3) If new appsettings are added the token will need to be added. Good 1) Each config could have unique values 2) When a appsetting is missed the build will fail allowing new appsettings to not be forgotten 3) it is already built 4) The name of the token is always the name of the appsetting A method I came up with to handle config files would work here but I am not sure it is worth the effort in the long run. I will share the basic method below. There are 4 files. 1) Run.build is where you will be determining what values need to be set in the config file and what config file to work with 2) config.helper.build is where the actual replacement happens. 3) config.xpath.build is where the actual xpaths of where the specific item is located in the config file 4) env.properties.build is where the specific values are set for each value. This is the file you would be changing for each environment. change all you need in one file. The over view of the process is that you create a file that holds all the xpath to each of the settings. if the values need to be different in different config files for the same key and xpath you will need to create a unique property/target combo name that is unique. Each item that you want to set in a config file has a property and a target of the same name. This way you can easily find the property and xpath match. For each time you want to set the property in your config file you simply need to set the config file you want to change and call the target of the item you want to replace. This is really clean and easy to read. Bad 1) need to track down all the valid XPaths 2) need seperate property / target when the same xpath and different values are needed 3) could miss values set for keys that are not specifically called out leaving dev or other values in the deployed version. Good 1) easy to see what all the values are 2) know specifically what is being replaced for each config file 3) one file for each environment 4) no need to create and replace tokens 5) can replace any attribute in the config file as long as you can create an XPath to it. 6) more likely to reuse properties for configs Run.build <project name="SupportConfig" default="config.update"> <property name="property.values.file" value="env.properties.build" /> <include buildfile="${property.values.file}" /> <include buildfile="config.xpath.build" /> <include buildfile="config.helper.build" /> <target name="support.config.update"> <property name="this.config.file" value="${Depot_Path}\projects\Support\web.config" /> <call target="PUBLIC_SITE_URL" /> <call target="PUBLIC_SITE_SECURE_URL" /> </target> </project> config.helper.build <project name="config.helper"> <property name="this.config.file" value="" /> <property name="this.xpath" value="" /> <property name="this.value" value="" /> <target name="config.poke"> <if test="${file::exists(this.config.file)}"> <xmlpoke file="${this.config.file}" value="${this.value}" xpath="${this.xpath}" /> <echo message="Poked ${this.config.file}. Changed value @ ${this.xpath} to ${this.value}" /> </if> <if test="${not file::exists(this.config.file)}"> <echo message="The version file ${this.config.file} doesn't exist!" /> </if> </target> </project> config.xpath.build <project name="config.xpath"> <target name="PUBLIC_SITE_URL"> <property name="this.xpath" value="/configuration/appSettings/add[@key='PUBLIC_SITE_URL']/@value" /> <property name="this.value" value=" ${target::get-current-target()}" /> <call target="config.poke" /> </target> <target name="PUBLIC_SITE_SECURE_URL"> <property name="this.xpath" value="/configuration/appSettings/add[@key='PUBLIC_SITE_SECURE_URL']/@value" /> <property name="this.value" value="${target::get-current-target()}" /> <call target="config.poke" /> </target> </project> env.properties.build <project name="env.properties"> <property name="Platform_Domain" value="wwww.mydomain.com" /> <property name="Depot_Path" value="c:\perforce-depot\Branch" /> <property name="PUBLIC_SITE_URL" value="http://${Platform_Domain}<http://$%7bPlatform_Domain%7d>"/> <property name="PUBLIC_SITE_SECURE_URL" value="https://${Platform_Domain}<https://$%7bPlatform_Domain%7d>"/> </project> Scott Pennington Senior Software Engineer Prosper Marketplace, Inc. 111 Sutter Street, 22nd Floor San Francisco CA 94104 www.prosper.com<http://www.prosper.com/> CONFIDENTIALITY STATEMENT: This email message, together with all attachments, is intended only for the individual or entity to which it is addressed and may contain legally privileged or confidential information. Any dissemination, distribution or copying of this communication by persons or entities other than the intended recipient, is strictly prohibited, and may be unlawful. If you have received this communication in error please contact the sender immediately and delete the transmitted material and all copies from your system, or if received in hard copy format, return the material to us via the United States Postal Service. Thank you. |