-
Notifications
You must be signed in to change notification settings - Fork 0
/
rake-transforms.html
429 lines (362 loc) · 27.6 KB
/
rake-transforms.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="manifest" href="/manifest.json" />
<link rel="icon" href="/images/icons/icon-152x152.png" />
<!-- theme-color defines the top bar color-->
<meta name="theme-color" content="#575757" />
<meta
http-equiv="X-Content-Security-Policy"
content="default-src 'self'; script-src 'report-sample' 'self' https://app.posthog.com/static/array.js https://www.googletagmanager.com/gtag/js; style-src 'report-sample' 'self' https://fonts.googleapis.com; object-src 'none'; base-uri 'self'; connect-src 'self' https://app.posthog.com; font-src 'self'; frame-src 'self'; img-src 'self'; manifest-src 'self'; media-src 'self'; report-uri https://pauldambra.report-uri.com/r/d/csp/enforce; worker-src 'self';"
/>
<!-- Add to home screen for Safari on iOS-->
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
<meta name="apple-mobile-web-app-title" content="MiRaNo" />
<link rel="apple-touch-icon" href="/images/icons/icon-152x152.png" />
<!-- Add to home screen for Windows-->
<meta
name="msapplication-TileImage"
content="/images/icons/icon-152x152.png"
/>
<meta name="msapplication-TileColor" content="#575757" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>Transforming web.config values with Rake</title>
<link rel="canonical" href="https://pauldambra.dev/rake-transforms.html" />
<meta property="og:url" content="https://pauldambra.dev/rake-transforms.html" />
<meta property="og:type" content="article" />
<meta property="og:title" content="Transforming web.config values with Rake" />
<meta
property="og:description"
content="transforming web.config with rake"
/>
<meta
property="og:image"
content="https://pauldambra.dev/images/cardboard.jpg"
/>
<meta name="twitter:creator" content="@pauldambra" />
<meta property="fb:app_id" content="1029758320473951" />
<meta name="viewport" content="width=device-width" />
<meta
name="description"
content="transforming web.config with rake"
/>
<meta property="fb:pages" content="1029758320473951" />
<link
rel="alternate"
type="application/rss+xml"
title="Mindless Rambling Nonsense"
href="https://pauldambra.dev/feed.xml"
/>
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="prefetch" href="/images/cardboard.jpg" />
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="stylesheet" href="/assets/css/syntax.css">
<meta name="msvalidate.01" content="54691C3C7B863CEE60F0305D6EDFF7A8" />
<meta
name="google-site-verification"
content="hLKEdujpXNQ9PSZWEcQkwxCgL2z1tWxVedeaUmttH7c"
/>
<script>
!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init capture register register_once register_for_session unregister unregister_for_session getFeatureFlag getFeatureFlagPayload isFeatureEnabled reloadFeatureFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSessionId getSurveys getActiveMatchingSurveys renderSurvey canRenderSurvey getNextSurveyStep identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset get_distinct_id getGroups get_session_id get_session_replay_url alias set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException loadToolbar get_property getSessionProperty createPersonProfile opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing clear_opt_in_out_capturing debug".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
posthog.init('phc_xcwOfYtGDcfv8619HtTWgHEfVMeTqS5YKkBsVEpy1ns', {
api_host:'https://ph.pauldambra.dev',
person_profiles: 'identified_only' // or 'always' to create profiles for anonymous users as well
})
</script>
</head>
<body class="flex flex-col h-screen">
<header class="flex flex-col px-8 pt-4 text-white text-xl" role="banner">
<div class="flex flex-col sm:flex-row">
<div class="no-underline hover:underline">
<a href="/">Mindless Rambling Nonsense</a>
</div>
<div class="flex-grow my-2 sm:m-0"></div>
<div class="flex justify-start items-end flex-col text-sm">
<div class="flex items-center">
<div class="mr-4">Paul D'Ambra</div>
<a href="https://github.com/pauldambra" rel="noopener">
<img
src="/images/GitHub-Mark-Light-32px.png"
alt="pauldambra on github"
width="32"
height="32"
/>
</a>
</div>
<div class="flex items-center">
<div class="mr-4">Fangler</div>
<a href="https://twitter.com/pauldambra" rel="noopener">
<img
src="/images/twitter-32.png"
alt="pauldambra on twitter"
width="32"
height="32"
/>
</a>
</div>
<div class="flex items-center">
<div class="mr-4"></div>
<a rel="me" href="https://mastodon.me.uk/@pauldambra">
</a>
</div>
</div>
</div>
<div class="flex-grow"></div>
<div
class="flex align-middle items-start px-2 py-4 text-white space-x-4 text-lg"
>
<nav role="navigation">
<a class="underline" href="/">Blog Posts</a>
<a class="underline ml-5" href="/weeknotes.html">Week Notes</a>
<a class="underline ml-5" href="/kids-games.html">Kids games</a>
</nav>
</div>
</header>
<main role="main" class="bg-white p-4 w-11/12 m-auto flex-auto flex-grow">
<script type="application/ld+json">
{
"@context":"http://schema.org",
"@type":"BlogPosting",
"headline":"Transforming web.config values with Rake",
"genre":"",
"keywords":"",
"wordCount":"962",
"url":"https://pauldambra.dev/rake-transforms.html",
"datePublished":"2014-11-06",
"author":{
"@type":"Person",
"name":"Paul D'Ambra",
"sameAs":[
"https://twitter.com/pauldambra",
"https://github.com/pauldambra",
"https://plus.google.com/u/0/+PaulDAmbraPlus"
]
},
"publisher":{
"@type": "Organization",
"name": "Paul D'Ambra",
"sameAs": [
"https://twitter.com/pauldambra",
"https://github.com/pauldambra",
"https://plus.google.com/u/0/+PaulDAmbraPlus"
],
"logo": {
"@type": "ImageObject",
"contentUrl": "https://pauldambra.dev/images/logo.png",
"url": "https://pauldambra.dev"
}
},
"image":{
"@type":"ImageObject",
"contentUrl":"https://pauldambra.dev/images/cardboard.jpg",
"url":"https://pauldambra.dev",
"height":"450",
"width":"1000"
},
"mainEntityOfPage":{
"@type":"WebPage",
"@id":"https://pauldambra.dev/rake-transforms.html"
},
"articleBody":"I've really been enjoying using Albacore Rake instead of MSBuild at work. It's enabled us to get everyone involved (because ugh, msbuild xml) and to improve our CI/CD pipeline.\n\nToday we were talking about reducing the number of build configurations we have… which we only have in order to support config transforms.\n\n\n\nNB: this is all with Albacore Rake version one.\n\nHere's a rakefile that will clean and build a .Net solution\n\nrequire 'albacore'\n\nSOLUTION_FILE = \"../SolutionName.sln\"\nBUILD_CONFIG = ENV['Configuration'] || \"Release\"\n\nMSBUILD_PROPERTIES = {\n :configuration => BUILD_CONFIG,\n :VisualStudioVersion => 12.0 # or you have to edit csproj for this to work\n}\n\ntask :default => [:build]\n\nmsbuild :clean do |msb|\n msb.properties = MSBUILD_PROPERTIES\n msb.targets :Clean\n msb.solution = SOLUTION_FILE\n msb.verbosity = :normal\nend\n\nmsbuild :build=>[:clean] do |msb|\n msb.properties = MSBUILD_PROPERTIES\n msb.targets :Build\n msb.solution = SOLUTION_FILE\n msb.verbosity = :normal\nend\n\n\nIn this scenario I want to replace the value of an app setting key. The section in the web.config in question:\n\n <appSettings>\n <add key=\"TheSetting\" value=\"value that needs to change\"/>\n </appSettings>\n\n\naside: don't always do this!\n\nThe web.config transform to replace one or two values is pretty straightforward so if you don't have many different configurations or many things to change then you can probably stick with that.\n\nBut if you want to be able to apply the transform outside of packaging/deploying or if things are getting gnarly then I definitely recommend exploring albacore\n\nA template web.config\nI keep rake files in a folder at the root of the solution named Build (but they don't have to be there). And so I added a folder named templates to that. Then added a copy of the web.config to that folder.\n\nThis annoys and worries me as it will need to be kept in sync as the web.config changes (say someone adds a Nuget package to the project that alters the web.config). And so this feels like a potential source of error. But…\n\nIn this file any value that needs changing can be replaced with a ruby string interpolation format placeholder thingy (hmmm, did I give away that I don't ruby programming language much?)\n\nSo…\n\n <appSettings>\n <add key=\"TheSetting\" value=\"%{the_setting}\"/>\n </appSettings>\n\n\nYAML\n\nYAML or YAML Ain't Markup Language is a \"human friendly data serialization\n standard for all programming languages.\". There's more to learn about yaml in ruby here\n\nFor each build config add a yaml file. In this example case I added a release.yaml file to the Build/templates folder:\n\n:the_setting: altered-value\n\n\nComplex, right? Wrong! If anything there's too little text in here for my tastes (although I'm unfamiliar with yaml so it may be because of the effort I have to expend to parse it)\n\nThe important thing here is that the yaml key begins with a colon to support the string replacement method used below.\n\nThe rake task\n\nThe rakefile should look like this:\n\nrequire 'albacore'\nrequire 'yaml'\n\nSOLUTION_FILE = \"../SolutionName.sln\"\nBUILD_CONFIG = ENV['Configuration'] || \"Release\"\nWEBCONFIG_PATH = \"../ProjectName/Web.config\"\n\nMSBUILD_PROPERTIES = {\n :configuration => BUILD_CONFIG,\n :VisualStudioVersion => 12.0\n}\n\ntask :default => [:build]\n\nmsbuild :clean do |msb|\n msb.properties = MSBUILD_PROPERTIES\n msb.targets :Clean\n msb.solution = SOLUTION_FILE\n msb.verbosity = :normal\nend\n\nmsbuild :build=>[:clean] do |msb|\n msb.properties = MSBUILD_PROPERTIES\n msb.targets :Build\n msb.solution = SOLUTION_FILE\n msb.verbosity = :normal\nend\n\ntask :transform_config do \n configHash = YAML.load_file(\"templates/#{BUILD_CONFIG}.yaml\")\n templateConfig = File.read(\"templates/web.config\") \n newConfig = templateConfig % configHash\n File.write(WEBCONFIG_PATH, newConfig)\nend\n\n\nThis file has a new task which loads the settings from the yaml file into a hash. And then loads the contents of the web.config template as a string.\n\nIt then uses the string % hash method of string interpolation that has been available since Ruby 1.9.2\n\nThis mechanism requires that the hash keys are symbols and not strings which is why the keys in the yaml file have to begin with a colon.\n\nDoes this solve my problems?\n\nMore config yaml files can be added. Whole sections can be excluded from configs by being replaced with empty strings. And more importantly the project and solution files don't need to know about these configurations to support different values in different deployments.\n\nThere might be pain points here I haven't discovered in this example but I like what I see so far!\n\n"
}
</script>
<article>
<header class="flex flex-col border-b-black border-b-2 bg-white text-black">
<div class="heading">
<div class="date">Thu Nov 06 2014</div>
<h1 class="title leading-10 pt-2 mb-0 mt-1">Transforming web.config values with Rake</h1>
</div>
<div class="meta flex-grow flex flex-row">
<div class="share-this flex self-end space-x-2">
<a
id="facebook-share-link"
class="social-share"
target="_blank"
rel="noopener"
href="https://www.facebook.com/dialog/share?app_id=305449093152216&href=https://pauldambra.dev/rake-transforms.html"
>
<img
class="w-8"
src="/images/facebook-black-32.png"
alt="share on facebook"
width="32"
height="32"
/>
</a>
<a
id="twitter-share-link"
class="social-share"
target="_blank"
rel="noopener"
href="https://twitter.com/intent/tweet?text=Transforming+web.config+values+with+Rake&via=pauldambra&url=https://pauldambra.dev/rake-transforms.html"
>
<img
class="w-8"
src="/images/twitter-black-32.png"
alt="share on twitter"
width="32"
height="32"
/>
</a>
</div>
<div class="more-like-this text-right content-end flex-grow">
<a
class="post-metadata"
href="/categories.html#continuous-integration"
>
in: continuous-integration
</a>
<div>
<span class="text-slate-500">
<img class="w-6 h-6 inline-block" src="/images/tag.svg" alt="tag-icon" />
<a class="no-underline hover:underline" href="/tags.html#rake">
rake
</a>
</span>
<span class="text-slate-500">
<img class="w-6 h-6 inline-block" src="/images/tag.svg" alt="tag-icon" />
<a class="no-underline hover:underline" href="/tags.html#ci">
CI
</a>
</span>
<span class="text-slate-500">
<img class="w-6 h-6 inline-block" src="/images/tag.svg" alt="tag-icon" />
<a class="no-underline hover:underline" href="/tags.html#ruby">
ruby
</a>
</span>
</div>
</div>
</div>
</header>
<div class="post">
<p>I've really been enjoying using Albacore Rake instead of MSBuild at work. It's enabled us to get everyone involved (because ugh, msbuild xml) and to improve our CI/CD pipeline.</p>
<p>Today we were talking about reducing the number of build configurations we have… which we only have in order to support config transforms.</p>
<!--more-->
<p>NB: this is all with Albacore Rake version one.</p>
<p>Here's a rakefile that will clean and build a .Net solution</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">require</span> <span class="s1">'albacore'</span>
<span class="no">SOLUTION_FILE</span> <span class="o">=</span> <span class="s2">"../SolutionName.sln"</span>
<span class="no">BUILD_CONFIG</span> <span class="o">=</span> <span class="no">ENV</span><span class="p">[</span><span class="s1">'Configuration'</span><span class="p">]</span> <span class="o">||</span> <span class="s2">"Release"</span>
<span class="no">MSBUILD_PROPERTIES</span> <span class="o">=</span> <span class="p">{</span>
<span class="ss">:configuration</span> <span class="o">=></span> <span class="no">BUILD_CONFIG</span><span class="p">,</span>
<span class="ss">:VisualStudioVersion</span> <span class="o">=></span> <span class="mf">12.0</span> <span class="c1"># or you have to edit csproj for this to work</span>
<span class="p">}</span>
<span class="n">task</span> <span class="ss">:default</span> <span class="o">=></span> <span class="p">[</span><span class="ss">:build</span><span class="p">]</span>
<span class="n">msbuild</span> <span class="ss">:clean</span> <span class="k">do</span> <span class="o">|</span><span class="n">msb</span><span class="o">|</span>
<span class="n">msb</span><span class="p">.</span><span class="nf">properties</span> <span class="o">=</span> <span class="no">MSBUILD_PROPERTIES</span>
<span class="n">msb</span><span class="p">.</span><span class="nf">targets</span> <span class="ss">:Clean</span>
<span class="n">msb</span><span class="p">.</span><span class="nf">solution</span> <span class="o">=</span> <span class="no">SOLUTION_FILE</span>
<span class="n">msb</span><span class="p">.</span><span class="nf">verbosity</span> <span class="o">=</span> <span class="ss">:normal</span>
<span class="k">end</span>
<span class="n">msbuild</span> <span class="ss">:build</span><span class="o">=></span><span class="p">[</span><span class="ss">:clean</span><span class="p">]</span> <span class="k">do</span> <span class="o">|</span><span class="n">msb</span><span class="o">|</span>
<span class="n">msb</span><span class="p">.</span><span class="nf">properties</span> <span class="o">=</span> <span class="no">MSBUILD_PROPERTIES</span>
<span class="n">msb</span><span class="p">.</span><span class="nf">targets</span> <span class="ss">:Build</span>
<span class="n">msb</span><span class="p">.</span><span class="nf">solution</span> <span class="o">=</span> <span class="no">SOLUTION_FILE</span>
<span class="n">msb</span><span class="p">.</span><span class="nf">verbosity</span> <span class="o">=</span> <span class="ss">:normal</span>
<span class="k">end</span>
</code></pre></div></div>
<p>In this scenario I want to replace the value of an app setting key. The section in the web.config in question:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><appSettings></span>
<span class="nt"><add</span> <span class="na">key=</span><span class="s">"TheSetting"</span> <span class="na">value=</span><span class="s">"value that needs to change"</span><span class="nt">/></span>
<span class="nt"></appSettings></span>
</code></pre></div></div>
<h3 id="aside-dont-always-do-this">aside: don't always do this!</h3>
<p>The web.config transform to replace one or two values is pretty straightforward so if you don't have many different configurations or many things to change then you can probably stick with that.</p>
<p>But if you want to be able to apply the transform outside of packaging/deploying or if things are getting gnarly then I definitely recommend exploring <a href="https://github.com/Albacore/albacore">albacore</a></p>
<h1 id="a-template-webconfig">A template web.config</h1>
<p>I keep rake files in a folder at the root of the solution named Build (but they don't have to be there). And so I added a folder named templates to that. Then added a copy of the web.config to that folder.</p>
<p>This annoys and worries me as it will need to be kept in sync as the web.config changes (say someone adds a Nuget package to the project that alters the web.config). And so this feels like a potential source of error. But…</p>
<p>In this file any value that needs changing can be replaced with a <a href="http://blog.revathskumar.com/2013/01/ruby-multiple-string-substitution-in-string-template.html">ruby string interpolation format placeholder thingy</a> (hmmm, did I give away that I don't ruby programming language much?)</p>
<p>So…</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><appSettings></span>
<span class="nt"><add</span> <span class="na">key=</span><span class="s">"TheSetting"</span> <span class="na">value=</span><span class="s">"%{the_setting}"</span><span class="nt">/></span>
<span class="nt"></appSettings></span>
</code></pre></div></div>
<h1 id="yaml">YAML</h1>
<p>YAML or YAML Ain't Markup Language is a <a href="http://www.yaml.org/">"human friendly data serialization
standard for all programming languages."</a>. There's more to learn about <a href="http://yaml4r.sourceforge.net/doc/">yaml in ruby here</a></p>
<p>For each build config add a yaml file. In this example case I added a release.yaml file to the Build/templates folder:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">:the_setting</span><span class="pi">:</span> <span class="s">altered-value</span>
</code></pre></div></div>
<p>Complex, right? Wrong! If anything there's too little text in here for my tastes (although I'm unfamiliar with yaml so it may be because of the effort I have to expend to parse it)</p>
<p>The important thing here is that the yaml key begins with a colon to support the string replacement method used below.</p>
<h1 id="the-rake-task">The rake task</h1>
<p>The rakefile should look like this:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">require</span> <span class="s1">'albacore'</span>
<span class="nb">require</span> <span class="s1">'yaml'</span>
<span class="no">SOLUTION_FILE</span> <span class="o">=</span> <span class="s2">"../SolutionName.sln"</span>
<span class="no">BUILD_CONFIG</span> <span class="o">=</span> <span class="no">ENV</span><span class="p">[</span><span class="s1">'Configuration'</span><span class="p">]</span> <span class="o">||</span> <span class="s2">"Release"</span>
<span class="no">WEBCONFIG_PATH</span> <span class="o">=</span> <span class="s2">"../ProjectName/Web.config"</span>
<span class="no">MSBUILD_PROPERTIES</span> <span class="o">=</span> <span class="p">{</span>
<span class="ss">:configuration</span> <span class="o">=></span> <span class="no">BUILD_CONFIG</span><span class="p">,</span>
<span class="ss">:VisualStudioVersion</span> <span class="o">=></span> <span class="mf">12.0</span>
<span class="p">}</span>
<span class="n">task</span> <span class="ss">:default</span> <span class="o">=></span> <span class="p">[</span><span class="ss">:build</span><span class="p">]</span>
<span class="n">msbuild</span> <span class="ss">:clean</span> <span class="k">do</span> <span class="o">|</span><span class="n">msb</span><span class="o">|</span>
<span class="n">msb</span><span class="p">.</span><span class="nf">properties</span> <span class="o">=</span> <span class="no">MSBUILD_PROPERTIES</span>
<span class="n">msb</span><span class="p">.</span><span class="nf">targets</span> <span class="ss">:Clean</span>
<span class="n">msb</span><span class="p">.</span><span class="nf">solution</span> <span class="o">=</span> <span class="no">SOLUTION_FILE</span>
<span class="n">msb</span><span class="p">.</span><span class="nf">verbosity</span> <span class="o">=</span> <span class="ss">:normal</span>
<span class="k">end</span>
<span class="n">msbuild</span> <span class="ss">:build</span><span class="o">=></span><span class="p">[</span><span class="ss">:clean</span><span class="p">]</span> <span class="k">do</span> <span class="o">|</span><span class="n">msb</span><span class="o">|</span>
<span class="n">msb</span><span class="p">.</span><span class="nf">properties</span> <span class="o">=</span> <span class="no">MSBUILD_PROPERTIES</span>
<span class="n">msb</span><span class="p">.</span><span class="nf">targets</span> <span class="ss">:Build</span>
<span class="n">msb</span><span class="p">.</span><span class="nf">solution</span> <span class="o">=</span> <span class="no">SOLUTION_FILE</span>
<span class="n">msb</span><span class="p">.</span><span class="nf">verbosity</span> <span class="o">=</span> <span class="ss">:normal</span>
<span class="k">end</span>
<span class="n">task</span> <span class="ss">:transform_config</span> <span class="k">do</span>
<span class="n">configHash</span> <span class="o">=</span> <span class="no">YAML</span><span class="p">.</span><span class="nf">load_file</span><span class="p">(</span><span class="s2">"templates/</span><span class="si">#{</span><span class="no">BUILD_CONFIG</span><span class="si">}</span><span class="s2">.yaml"</span><span class="p">)</span>
<span class="n">templateConfig</span> <span class="o">=</span> <span class="no">File</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="s2">"templates/web.config"</span><span class="p">)</span>
<span class="n">newConfig</span> <span class="o">=</span> <span class="n">templateConfig</span> <span class="o">%</span> <span class="n">configHash</span>
<span class="no">File</span><span class="p">.</span><span class="nf">write</span><span class="p">(</span><span class="no">WEBCONFIG_PATH</span><span class="p">,</span> <span class="n">newConfig</span><span class="p">)</span>
<span class="k">end</span>
</code></pre></div></div>
<p>This file has a new task which loads the settings from the yaml file into a hash. And then loads the contents of the web.config template as a string.</p>
<p>It then uses the <code class="language-plaintext highlighter-rouge">string % hash</code> method of string interpolation that has been available since Ruby 1.9.2</p>
<p>This mechanism requires that the hash keys are symbols and not strings which is why the keys in the yaml file have to begin with a colon.</p>
<h1 id="does-this-solve-my-problems">Does this solve my problems?</h1>
<p>More config yaml files can be added. Whole sections can be excluded from configs by being replaced with empty strings. And more importantly the project and solution files don't need to know about these configurations to support different values in different deployments.</p>
<p>There might be pain points here I haven't discovered in this example but I like what I see so far!</p>
</div>
<div class="mt-8">
<h1>More like this...</h1>
<div class="grid grid-cols-3 gap-4"></div>
</div>
</article>
</main>
<footer class="w-full h-4 bg-black text-white py-8 px-4">
<a class="no-underline text-white" href="https://pauldambra.dev/feed.xml">
<img class="inline w-6 h-6" src="/images/rss.svg" alt="the rss feed" />
<span>Subscribe to RSS feed</span>
</a>
</footer>
<script>
var tsl = document.getElementById("twitter-share-link");
tsl.addEventListener("click", function () {
ga("send", {
hitType: "social",
socialNetwork: "twitter",
socialAction: "tweet",
socialTarget: "https://pauldambra.dev/rake-transforms.html",
});
});
var fsl = document.getElementById("facebook-share-link");
fsl.addEventListener("click", function () {
ga("send", {
hitType: "social",
socialNetwork: "facebook",
socialAction: "share",
socialTarget: "https://pauldambra.dev/rake-transforms.html",
});
});
</script>
<script defer src="/register-service-worker.js"></script>
<link
href="https://fonts.googleapis.com/css?family=Khula&display=swap"
rel="stylesheet"
/>
</body>
</html>