Congratulations!

[Valid RSS] This is a valid RSS feed.

Recommendations

This feed is valid, but interoperability with the widest range of feed readers could be improved by implementing the following recommendations.

Source: http://www.hanselman.com/blog/SyndicationService.asmx/GetAtom

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <?xml-stylesheet type="text/xsl" href="http://feeds.hanselman.com/feedblitz_rss.xslt"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" version="2.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
  3.  <channel>
  4.    <title>Scott Hanselman's Blog</title>
  5.    <link>https://www.hanselman.com/blog/</link>
  6.    <description>Scott Hanselman on Programming, User Experience, The Zen of Computers and Life in General</description>
  7.    <image>
  8. <url>http://www.hanselman.com/blog/images/tinyheadshot2.jpg</url>
  9. <title>Scott Hanselman's Blog</title>
  10. <link>https://www.hanselman.com/blog/</link>
  11. </image>
  12.    <copyright>admin</copyright>
  13.    <lastBuildDate>Thu, 20 Sep 2018 21:58:00 GMT</lastBuildDate>
  14.    <generator>newtelligence dasBlog 4.0.0.0</generator>
  15.    <managingEditor>[email protected]</managingEditor>
  16.    <webMaster>[email protected]</webMaster>
  17. <meta xmlns="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
  18. <item>
  19. <feedburner:origLink>https://www.hanselman.com/blog/ScriptsToRemoveOldNETCoreSDKs.aspx</feedburner:origLink>
  20.      <trackback:ping>https://www.hanselman.com/blog/Trackback.aspx?guid=a48e3ed1-a525-4918-83e5-957fbab844ea</trackback:ping>
  21.      <pingback:server>https://www.hanselman.com/blog/pingback.aspx</pingback:server>
  22.      <pingback:target>https://www.hanselman.com/blog/PermaLink.aspx?guid=a48e3ed1-a525-4918-83e5-957fbab844ea</pingback:target>
  23.      <dc:creator>Scott Hanselman</dc:creator>
  24.      <wfw:comment>https://www.hanselman.com/blog/CommentView.aspx?guid=a48e3ed1-a525-4918-83e5-957fbab844ea</wfw:comment>
  25.      <wfw:commentRss>https://www.hanselman.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=a48e3ed1-a525-4918-83e5-957fbab844ea</wfw:commentRss>
  26.      <slash:comments>7</slash:comments>
  27.      <title>Scripts to remove old .NET Core SDKs</title>
  28.      <guid isPermaLink="false">https://www.hanselman.com/blog/PermaLink.aspx?guid=a48e3ed1-a525-4918-83e5-957fbab844ea</guid>
  29.      <link>http://feeds.hanselman.com/~/571134816/0/scotthanselman~Scripts-to-remove-old-NET-Core-SDKs.aspx</link>
  30.      <pubDate>Thu, 20 Sep 2018 21:58:00 GMT</pubDate>
  31.      <description><![CDATA[<div><p><img title="That's a lot of .NET Core installations" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; float: right; padding-top: 0px; padding-left: 0px; border-left: 0px; margin: 0px 0px 0px 5px; display: inline; padding-right: 0px" border="0" alt="That's a lot of .NET Core installations" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/1ab4cab7128c_D8FF/image_3c5ef846-6964-4627-9aae-d9467cf13a11.png" width="530" align="right" height="482">.NET Core is lovely. It's usage is skyrocketing, it's open source, and .NET Core 2.1 has some amazing performance improvements. Just <a href="https://blogs.msdn.microsoft.com/dotnet/2018/08/20/bing-com-runs-on-net-core-2-1/">upgrading from 2.0 to 2.1 gave Bing a 34% performance boost</a>. <p>However, for those of us who are installing multiple .NET Core SDKs side by side have noticed that they add-up if you are installing daily builds or very often. As of 2.x, .NET Core doesn't yet have an "uninstall all" or "uninstall all previews" option. There will be work done in .NET Core 3.0 that will mitigate this cumulative effect when you have lots of installers. <p align="left">If you're taking dailies and it's time to tidy up, the short answer <a href="https://twitter.com/DamianEdwards/status/1043939217145913344">per Damian Edwards is</a> "Delete them all, then nuke the dotnet folder in program files, then install the latest version." <p align="left">Here's a PowerShell Script you can run on Windows as admin that will aggressively uninstall .NET Core SDKs. <p align="left">Note the match at the top. Depending on your goals, you might want to change it to "Microsoft .NET Core SDK 2.1" or just "Microsoft .NET Core SDK 2."  <p align="left">Once it's all removed, then add the latest from <a title="https://www.microsoft.com/net/download/archives" href="https://www.microsoft.com/net/download/archives">https://www.microsoft.com/net/download/archives</a> <p align="left"><img title="A list of .NET Core SDKs" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="A list of .NET Core SDKs" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/1ab4cab7128c_D8FF/image_8219d0aa-e8c7-4ebb-af83-511ab7eb960c.png" width="402" height="237"> <p align="left">Here's the script, which is an <a href="https://github.com/dotnet/sdk/issues/2295#issuecomment-393553191">improvement on Andrew's comment here</a>. You can improve it as it's on GitHub here <a title="https://github.com/shanselman/RemoveDotNetCoreSDKInstallers" href="https://github.com/shanselman/RemoveDotNetCoreSDKInstallers">https://github.com/shanselman/RemoveDotNetCoreSDKInstallers</a>. This scripts currently requires you to hit YES as the MSIs elevate. It doesn't work right then you try /passive as a switch. I'm interesting if you can get a "torch all Core SDK installers and install LTS and Current" script working.<pre class="brush: ps; toolbar: false; auto-links: false;">$app = Get-WmiObject -Class Win32_Product | Where-Object {
  32.    $_.Name -match "Microsoft .NET Core SDK"
  33. }
  34. Write-Host $app.Name
  35. Write-Host $app.IdentifyingNumber
  36. pushd $env:SYSTEMROOT\System32
  37. $app.identifyingnumber |% { Start-Process msiexec -wait -ArgumentList "/x $_" }
  38. popd</pre>
  39. <p>This PowerShell is Windows-only, of course.
  40. <p>If you're on RHEL, Ubuntu/Debian, there are scripts here to try out <a title="https://github.com/dotnet/cli/tree/master/scripts/obtain/uninstall" href="https://github.com/dotnet/cli/tree/master/scripts/obtain/uninstall">https://github.com/dotnet/cli/tree/master/scripts/obtain/uninstall</a>
  41. <p>Let me know if this script works for you.
  42. <hr>
  43. <p><strong>Sponsor:</strong> Copy: <a href="https://hnsl.mn/2QMyhmf">Rider 2018.2 is here</a>! Publishing to IIS, Docker support in the debugger, built-in spell checking, MacBook Touch Bar support, full C# 7.3 support, advanced Unity support, and more.</p><br/><hr/>© 2018 Scott Hanselman. All rights reserved. <br/></div><div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="http://feeds.hanselman.com/_/28/571134816/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Share on Google+" href="http://feeds.hanselman.com/_/30/571134816/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/googleplus20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Tweet This" href="http://feeds.hanselman.com/_/24/571134816/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/twitter20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="http://feeds.hanselman.com/_/19/571134816/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="http://feeds.hanselman.com/_/20/571134816/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
  44. </description>
  45.      <comments>https://www.hanselman.com/blog/CommentView.aspx?guid=a48e3ed1-a525-4918-83e5-957fbab844ea</comments>
  46.      <category>DotNetCore</category><content:encoded><![CDATA[<div><p><img title="That's a lot of .NET Core installations" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; float: right; padding-top: 0px; padding-left: 0px; border-left: 0px; margin: 0px 0px 0px 5px; display: inline; padding-right: 0px" border="0" alt="That's a lot of .NET Core installations" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/1ab4cab7128c_D8FF/image_3c5ef846-6964-4627-9aae-d9467cf13a11.png" width="530" align="right" height="482">.NET Core is lovely. It's usage is skyrocketing, it's open source, and .NET Core 2.1 has some amazing performance improvements. Just <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://blogs.msdn.microsoft.com/dotnet/2018/08/20/bing-com-runs-on-net-core-2-1/">upgrading from 2.0 to 2.1 gave Bing a 34% performance boost</a>. <p>However, for those of us who are installing multiple .NET Core SDKs side by side have noticed that they add-up if you are installing daily builds or very often. As of 2.x, .NET Core doesn't yet have an "uninstall all" or "uninstall all previews" option. There will be work done in .NET Core 3.0 that will mitigate this cumulative effect when you have lots of installers. <p align="left">If you're taking dailies and it's time to tidy up, the short answer <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://twitter.com/DamianEdwards/status/1043939217145913344">per Damian Edwards is</a> "Delete them all, then nuke the dotnet folder in program files, then install the latest version." <p align="left">Here's a PowerShell Script you can run on Windows as admin that will aggressively uninstall .NET Core SDKs. <p align="left">Note the match at the top. Depending on your goals, you might want to change it to "Microsoft .NET Core SDK 2.1" or just "Microsoft .NET Core SDK 2."  <p align="left">Once it's all removed, then add the latest from <a title="https://www.microsoft.com/net/download/archives" href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.microsoft.com/net/download/archives">https://www.microsoft.com/net/download/archives</a> <p align="left"><img title="A list of .NET Core SDKs" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="A list of .NET Core SDKs" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/1ab4cab7128c_D8FF/image_8219d0aa-e8c7-4ebb-af83-511ab7eb960c.png" width="402" height="237"> <p align="left">Here's the script, which is an <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/dotnet/sdk/issues/2295#issuecomment-393553191">improvement on Andrew's comment here</a>. You can improve it as it's on GitHub here <a title="https://github.com/shanselman/RemoveDotNetCoreSDKInstallers" href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/shanselman/RemoveDotNetCoreSDKInstallers">https://github.com/shanselman/RemoveDotNetCoreSDKInstallers</a>. This scripts currently requires you to hit YES as the MSIs elevate. It doesn't work right then you try /passive as a switch. I'm interesting if you can get a "torch all Core SDK installers and install LTS and Current" script working.<pre class="brush: ps; toolbar: false; auto-links: false;">$app = Get-WmiObject -Class Win32_Product | Where-Object {
  47.    $_.Name -match "Microsoft .NET Core SDK"
  48. }
  49. Write-Host $app.Name
  50. Write-Host $app.IdentifyingNumber
  51. pushd $env:SYSTEMROOT\System32
  52. $app.identifyingnumber |% { Start-Process msiexec -wait -ArgumentList "/x $_" }
  53. popd</pre>
  54. <p>This PowerShell is Windows-only, of course.
  55. <p>If you're on RHEL, Ubuntu/Debian, there are scripts here to try out <a title="https://github.com/dotnet/cli/tree/master/scripts/obtain/uninstall" href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/dotnet/cli/tree/master/scripts/obtain/uninstall">https://github.com/dotnet/cli/tree/master/scripts/obtain/uninstall</a>
  56. <p>Let me know if this script works for you.
  57. <hr>
  58. <p><strong>Sponsor:</strong> Copy: <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://hnsl.mn/2QMyhmf">Rider 2018.2 is here</a>! Publishing to IIS, Docker support in the debugger, built-in spell checking, MacBook Touch Bar support, full C# 7.3 support, advanced Unity support, and more.</p>
  59. <br/><hr/>© 2018 Scott Hanselman. All rights reserved.
  60. <br/></div><Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="http://feeds.hanselman.com/~/i/571134816/0/scotthanselman">
  61. <div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="http://feeds.hanselman.com/_/28/571134816/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Share on Google+" href="http://feeds.hanselman.com/_/30/571134816/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/googleplus20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Tweet This" href="http://feeds.hanselman.com/_/24/571134816/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/twitter20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="http://feeds.hanselman.com/_/19/571134816/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="http://feeds.hanselman.com/_/20/571134816/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
  62. </content:encoded></item>
  63. <item>
  64. <feedburner:origLink>https://www.hanselman.com/blog/AzureDevOpsContinuousBuildDeployTestWithASPNETCore22PreviewInOneHour.aspx</feedburner:origLink>
  65.      <trackback:ping>https://www.hanselman.com/blog/Trackback.aspx?guid=b7264c1d-1775-49a3-89bf-a438e6b80781</trackback:ping>
  66.      <pingback:server>https://www.hanselman.com/blog/pingback.aspx</pingback:server>
  67.      <pingback:target>https://www.hanselman.com/blog/PermaLink.aspx?guid=b7264c1d-1775-49a3-89bf-a438e6b80781</pingback:target>
  68.      <dc:creator>Scott Hanselman</dc:creator>
  69.      <wfw:comment>https://www.hanselman.com/blog/CommentView.aspx?guid=b7264c1d-1775-49a3-89bf-a438e6b80781</wfw:comment>
  70.      <wfw:commentRss>https://www.hanselman.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=b7264c1d-1775-49a3-89bf-a438e6b80781</wfw:commentRss>
  71.      <slash:comments>10</slash:comments>
  72.      <title>Azure DevOps Continuous Build/Deploy/Test with ASP.NET Core 2.2 Preview in One Hour</title>
  73.      <guid isPermaLink="false">https://www.hanselman.com/blog/PermaLink.aspx?guid=b7264c1d-1775-49a3-89bf-a438e6b80781</guid>
  74.      <link>http://feeds.hanselman.com/~/570548572/0/scotthanselman~Azure-DevOps-Continuous-BuildDeployTest-with-ASPNET-Core-Preview-in-One-Hour.aspx</link>
  75.      <pubDate>Tue, 18 Sep 2018 21:57:00 GMT</pubDate>
  76.      <description><![CDATA[<div><p><a href="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/image_6.png"><img title="Hanselminutes Website" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: right; padding-top: 0px; padding-left: 0px; margin: 0px 0px 0px 5px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Hanselminutes Website" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/image_thumb_2.png" width="352" align="right" height="196"></a>I've been doing <a href="https://www.hanselman.com/blog/ContinuousIntegrationForNETPatrickCauldwellAndIWillBeAtPADNUGOnWedsApril27th2005.aspx">Continuous Integration and Deployment for well over 13 years</a>. We used a lot of custom scripts and a lovely tool called <a href="https://github.com/ccnet/CruiseControl.NET">CruiseControl.NET</a> to check out, build, test, and deploy our code.</p> <p>However, it's easy to get lulled into complacency. To get lazy. I don't set up Automated Continuous Integration and Deployment for all my little projects. But I should.</p> <p>I was manually deploying a change to my <a href="https://www.hanselminutes.com">podcast website</a> this evening via a git deploy to Azure App Service. Pushing to Azure this way via Git uses "<a href="https://azure.microsoft.com/en-us/resources/videos/what-is-kudu-with-david-ebbo/">Kudu</a>" to actually build the site. However, earlier this week I was also trying to update my site to .NET Core 2.2 which is in preview. Plus I have Unit Tests that aren't getting run during deploy.</p> <p>So look at it this way. My simple little podcast website with a few tests and the desire to use a preview .NET Core SDK means I've outgrown a basic "git push to prod" for deploy.</p> <p>I remembered that <a href="https://azure.microsoft.com/services/devops/?nav=min&amp;WT.mc_id=-blog-scottha"><strong>Azure DevOps</strong></a> (formerly VSTS) is out and<strong> offers free unlimited minutes for open source projects.</strong> I have no excuse for my sloppy builds and manual deploys. It also has unlimited free private repos, although I'm happy at GitHub and have no reason to move.</p> <p>It usually takes me 5-10 minutes for a manual build/test/deploy, so I gave myself an hour to see if I could get this same process automated in <a href="https://azure.microsoft.com/services/devops/?nav=min&amp;WT.mc_id=-blog-scottha">Azure DevOps</a>. I've never used this before and I wanted to see if I could do it quickly, and if it was intuitive.</p> <p>Let's review my goals.</p> <ul> <li>My source is in GitHub  <li>Build my ASP.NET Core 2.2 Web Site  <ul> <li>I want to build with .NET Core 2.2 which is <em>currently </em>in Preview.</li></ul> <li>Run my xUnit Unit Tests  <ul> <li>I have some Selenium Unit Tests that can't run in the cloud (at least, I haven't figured it out yet) so I need them skipped.</li></ul> <li>Deploy the resulting site to product in my Azure App Service</li></ul> <p>Cool. So I make a project and point Azure DevOps at my GitHub.</p> <p><a href="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(33)_4.png"><img title="Azure DevOps: Source code in GitHub" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Azure DevOps: Source code in GitHub" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(33)_thumb_1.png" width="642" height="448"></a></p> <p>They have a number of starter templates, so I was pleasantly surprised I didn't need manually build my Build Configuration myself. I'll pick ASP.NET app. I could pick Azure Web App for ASP.NET but I wanted a little more control.</p> <p><a href="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(36)_4.png"><img title="Select a template" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Select a template" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(36)_thumb_1.png" width="549" height="482"></a></p> <p>Now I've got a basic build pipeline. You can see it will use NuGet, get the packages, build the app, test the assemblies (if there are tests...more on that later) and the publish (zip) the build artifacts.</p> <p><a href="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(37)_4.png"><img title="Build Pipeline" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Build Pipeline" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(37)_thumb_1.png" width="609" height="482"></a></p> <p>I then clicked Save &amp; Queue...and it failed. Why? It says that I'm targeting .NET Core 2.2 and it doesn't support anything over 2.1. Shoot.</p> <p><a href="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(39)_4.png"><img title="Agent says it doesn't support .NET Core 2.2" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Agent says it doesn't support .NET Core 2.2" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(39)_thumb_1.png" width="642" height="456"></a></p> <p>Fortunately there's a pipeline element that I can add called ".NET Core Tool Installer" that will get specific versions of the .NET Core SDK.</p> <blockquote> <p><strong>NOTE:</strong> I've emailed the team that ".NET Tool Installer" is the wrong name. A .NET Tool is a totally different thing. This task should be called the ".NET Core SDK Installer." Because it wasn't, it took me a minute to find it and figure out what it does.</p></blockquote> <p>I'm using the SDK Agent version <em>2.22.2.100-preview2-009404</em> so I put that string into the properties.</p> <p><a href="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(41)_4.png"><img title="Install the .NET Core SDK custom version" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Install the .NET Core SDK custom version" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(41)_thumb_1.png" width="642" height="281"></a></p> <p>At this point it builds, but I get a test error. </p> <p>There's two problems with the tests. When I look at the logs I can see that the "testadapter.dll" that comes with xunit is mistakenly being pulled into the test runner! Why? Because the "Test Files" spec includes a VERY greedy glob in the form of **\*test*.dll. Perhaps testadapter shouldn't include the word test, but then it wouldn't be well-named.</p><pre>**\$(BuildConfiguration)\**\*test*.dll<br>!**\obj\**</pre>
  77. <p>My test DLLs are all named with "tests" in the filename so I'll change the glob to "**\$(BuildConfiguration)\**\*tests*.dll" to cast a less-wide net.</p>
  78. <p><a href="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(45)_4.png"><img title="Screenshot (45)" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Screenshot (45)" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(45)_thumb_1.png" width="514" height="482"></a></p>
  79. <p>I have four <a href="https://www.hanselman.com/blog/RealBrowserIntegrationTestingWithSeleniumStandaloneChromeAndASPNETCore21.aspx">Selenium Tests</a> for my ASP.NET Core site but I <a href="https://www.hanselman.com/blog/DetectingThatANETCoreAppIsRunningInADockerContainerAndSkippableFactsInXUnit.aspx">don't want them to run when the tests are run in a Docker Container</a> or, in this case, in the Cloud. (Until I figure out how)</p>
  80. <p>I use SkippableFacts from XUnit and do this:</p><pre class="brush: csharp; gutter: false; toolbar: false; auto-links: false;">public static class AreWe<br>{<br>    public static bool InDockerOrBuildServer { <br>        get { <br>            string retVal = Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER");<br>            string retVal2 = Environment.GetEnvironmentVariable("AGENT_NAME");<br>            return (<br>                (String.Compare(retVal, Boolean.TrueString, ignoreCase: true) == 0)  <br>                || <br>                (String.IsNullOrWhiteSpace(retVal2) == false));<br>        } <br>    }<br>}
  81. </pre>
  82. <p>Don't tease me. I like it. Now I can skip tests that I don't want running.</p><pre class="brush: csharp; gutter: false; toolbar: false; auto-links: false;">if (AreWe.InDockerOrBuildServer) return;</pre>
  83. <p>Now my tests run and I get a nice series of charts to show that fact.</p>
  84. <p><a href="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(46)_4.png"><img title="22 tests, 4 skipped" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="22 tests, 4 skipped" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(46)_thumb_1.png" width="642" height="319"></a></p>
  85. <p>I have it building and tests running.</p>
  86. <p>I could add the Deployment Step to the Build but Azure DevOps Pipelines includes a better way. I make a Release Pipeline that is separate. It takes Artifacts as input and runs n number of Stages.</p>
  87. <p><a href="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(48)_4.png"><img title="Creating a new Release Pipeline" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Creating a new Release Pipeline" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(48)_thumb_1.png" width="642" height="473"></a></p>
  88. <p>I take the Artifact from the Build (the zipped up binaries) and pass them through the pipeline into the Azure App Service Deploy step.</p>
  89. <p><a href="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(49)_4.png"><img title="Screenshot (49)" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Screenshot (49)" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(49)_thumb_1.png" width="642" height="251"></a></p>
  90. <p>Here's the deployment in progress.</p>
  91. <p><a href="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(53)_4.png"><img title="Manually Triggered Release" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Manually Triggered Release" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(53)_thumb_1.png" width="642" height="435"></a></p>
  92. <p>Cool! Now that it works and deploys, I can turn on Continuous Integration Build Triggers (via an automatic GitHub webhook) as well as Continuous Deployment triggers.</p>
  93. <p><a href="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/image_4.png"><img title="Continuous Deployment" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Continuous Deployment" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/image_thumb_1.png" width="642" height="375"></a></p>
  94. <p>Azure DevOps even includes badges that I can add to my readme.md so I always know by looking at GitHub if my site builds AND if it has successfully deployed.</p>
  95. <p><a href="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/image_10.png"><img title="4 releases, the final one succeeded" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="4 releases, the final one succeeded" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/image_thumb_3.png" width="642" height="393"></a></p>
  96. <p>Now I can see each release as it happens and if it's successful or not.</p>
  97. <p><a href="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(50)_7.png"><img title="Build Succeeded, Never Deployed" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Build Succeeded, Never Deployed" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(50)_thumb_2.png" width="599" height="482"></a></p>
  98. <p>To top it all off, now that I have all this data and these pipelines, I even put together a nice little dashboard in about a minute to show Deployment Status and Test Trends.</p>
  99. <p><a href="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/image_2.png"><img title="My build and deployment dashboard" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="My build and deployment dashboard" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/image_thumb.png" width="642" height="425"></a></p>
  100. <p>When I combine the DevOps Dashboard with my main Azure Dashboard I'm amazed at how much information I can get in so little effort. Consider that my podcast (my little business) is a one-person shop. </p><figure><img title="Azure Dashboard" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Azure Dashboard" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/image_9.png" width="1001" height="335"></figure>
  101. <p>And now I have a CI/CD pipeline with integrated testing gates that deploys worldwide. Many years ago this would have required a team and a lot of custom code.</p>
  102. <p> Today it took an hour. Awesome. </p>
  103. <p>I check into GitHub, kicks off a build, tests, emails me the results, and deploys the website if everything is cool. Of course, if I had another team member I could put in deployment gates or reviews, etc.</p>
  104. <hr>
  105. <p><strong>Sponsor:</strong> Copy: <a href="https://hnsl.mn/2QMyhmf">Rider 2018.2 is here</a>! Publishing to IIS, Docker support in the debugger, built-in spell checking, MacBook Touch Bar support, full C# 7.3 support, advanced Unity support, and more.</p><br/><hr/>© 2018 Scott Hanselman. All rights reserved. <br/></div><div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="http://feeds.hanselman.com/_/28/570548572/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Share on Google+" href="http://feeds.hanselman.com/_/30/570548572/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/googleplus20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Tweet This" href="http://feeds.hanselman.com/_/24/570548572/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/twitter20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="http://feeds.hanselman.com/_/19/570548572/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="http://feeds.hanselman.com/_/20/570548572/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
  106. </description>
  107.      <comments>https://www.hanselman.com/blog/CommentView.aspx?guid=b7264c1d-1775-49a3-89bf-a438e6b80781</comments>
  108.      <category>Azure</category>
  109.      <category>Open Source</category><content:encoded><![CDATA[<div><p><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/image_6.png"><img title="Hanselminutes Website" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: right; padding-top: 0px; padding-left: 0px; margin: 0px 0px 0px 5px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Hanselminutes Website" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/image_thumb_2.png" width="352" align="right" height="196"></a>I've been doing <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/ContinuousIntegrationForNETPatrickCauldwellAndIWillBeAtPADNUGOnWedsApril27th2005.aspx">Continuous Integration and Deployment for well over 13 years</a>. We used a lot of custom scripts and a lovely tool called <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/ccnet/CruiseControl.NET">CruiseControl.NET</a> to check out, build, test, and deploy our code.</p> <p>However, it's easy to get lulled into complacency. To get lazy. I don't set up Automated Continuous Integration and Deployment for all my little projects. But I should.</p> <p>I was manually deploying a change to my <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselminutes.com">podcast website</a> this evening via a git deploy to Azure App Service. Pushing to Azure this way via Git uses "<a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://azure.microsoft.com/en-us/resources/videos/what-is-kudu-with-david-ebbo/">Kudu</a>" to actually build the site. However, earlier this week I was also trying to update my site to .NET Core 2.2 which is in preview. Plus I have Unit Tests that aren't getting run during deploy.</p> <p>So look at it this way. My simple little podcast website with a few tests and the desire to use a preview .NET Core SDK means I've outgrown a basic "git push to prod" for deploy.</p> <p>I remembered that <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://azure.microsoft.com/services/devops/?nav=min&amp;WT.mc_id=-blog-scottha"><strong>Azure DevOps</strong></a> (formerly VSTS) is out and<strong> offers free unlimited minutes for open source projects.</strong> I have no excuse for my sloppy builds and manual deploys. It also has unlimited free private repos, although I'm happy at GitHub and have no reason to move.</p> <p>It usually takes me 5-10 minutes for a manual build/test/deploy, so I gave myself an hour to see if I could get this same process automated in <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://azure.microsoft.com/services/devops/?nav=min&amp;WT.mc_id=-blog-scottha">Azure DevOps</a>. I've never used this before and I wanted to see if I could do it quickly, and if it was intuitive.</p> <p>Let's review my goals.</p> <ul> <li>My source is in GitHub  <li>Build my ASP.NET Core 2.2 Web Site  <ul> <li>I want to build with .NET Core 2.2 which is <em>currently </em>in Preview.</li></ul> <li>Run my xUnit Unit Tests  <ul> <li>I have some Selenium Unit Tests that can't run in the cloud (at least, I haven't figured it out yet) so I need them skipped.</li></ul> <li>Deploy the resulting site to product in my Azure App Service</li></ul> <p>Cool. So I make a project and point Azure DevOps at my GitHub.</p> <p><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(33)_4.png"><img title="Azure DevOps: Source code in GitHub" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Azure DevOps: Source code in GitHub" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(33)_thumb_1.png" width="642" height="448"></a></p> <p>They have a number of starter templates, so I was pleasantly surprised I didn't need manually build my Build Configuration myself. I'll pick ASP.NET app. I could pick Azure Web App for ASP.NET but I wanted a little more control.</p> <p><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(36)_4.png"><img title="Select a template" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Select a template" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(36)_thumb_1.png" width="549" height="482"></a></p> <p>Now I've got a basic build pipeline. You can see it will use NuGet, get the packages, build the app, test the assemblies (if there are tests...more on that later) and the publish (zip) the build artifacts.</p> <p><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(37)_4.png"><img title="Build Pipeline" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Build Pipeline" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(37)_thumb_1.png" width="609" height="482"></a></p> <p>I then clicked Save &amp; Queue...and it failed. Why? It says that I'm targeting .NET Core 2.2 and it doesn't support anything over 2.1. Shoot.</p> <p><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(39)_4.png"><img title="Agent says it doesn't support .NET Core 2.2" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Agent says it doesn't support .NET Core 2.2" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(39)_thumb_1.png" width="642" height="456"></a></p> <p>Fortunately there's a pipeline element that I can add called ".NET Core Tool Installer" that will get specific versions of the .NET Core SDK.</p> <blockquote> <p><strong>NOTE:</strong> I've emailed the team that ".NET Tool Installer" is the wrong name. A .NET Tool is a totally different thing. This task should be called the ".NET Core SDK Installer." Because it wasn't, it took me a minute to find it and figure out what it does.</p></blockquote> <p>I'm using the SDK Agent version <em>2.22.2.100-preview2-009404</em> so I put that string into the properties.</p> <p><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(41)_4.png"><img title="Install the .NET Core SDK custom version" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Install the .NET Core SDK custom version" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(41)_thumb_1.png" width="642" height="281"></a></p> <p>At this point it builds, but I get a test error. </p> <p>There's two problems with the tests. When I look at the logs I can see that the "testadapter.dll" that comes with xunit is mistakenly being pulled into the test runner! Why? Because the "Test Files" spec includes a VERY greedy glob in the form of **\*test*.dll. Perhaps testadapter shouldn't include the word test, but then it wouldn't be well-named.</p><pre>**\$(BuildConfiguration)\**\*test*.dll
  110. <br>!**\obj\**</pre>
  111. <p>My test DLLs are all named with "tests" in the filename so I'll change the glob to "**\$(BuildConfiguration)\**\*tests*.dll" to cast a less-wide net.</p>
  112. <p><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(45)_4.png"><img title="Screenshot (45)" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Screenshot (45)" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(45)_thumb_1.png" width="514" height="482"></a></p>
  113. <p>I have four <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/RealBrowserIntegrationTestingWithSeleniumStandaloneChromeAndASPNETCore21.aspx">Selenium Tests</a> for my ASP.NET Core site but I <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/DetectingThatANETCoreAppIsRunningInADockerContainerAndSkippableFactsInXUnit.aspx">don't want them to run when the tests are run in a Docker Container</a> or, in this case, in the Cloud. (Until I figure out how)</p>
  114. <p>I use SkippableFacts from XUnit and do this:</p><pre class="brush: csharp; gutter: false; toolbar: false; auto-links: false;">public static class AreWe
  115. <br>{
  116. <br>    public static bool InDockerOrBuildServer {
  117. <br>        get {
  118. <br>            string retVal = Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER");
  119. <br>            string retVal2 = Environment.GetEnvironmentVariable("AGENT_NAME");
  120. <br>            return (
  121. <br>                (String.Compare(retVal, Boolean.TrueString, ignoreCase: true) == 0)  
  122. <br>                ||
  123. <br>                (String.IsNullOrWhiteSpace(retVal2) == false));
  124. <br>        }
  125. <br>    }
  126. <br>}
  127. </pre>
  128. <p>Don't tease me. I like it. Now I can skip tests that I don't want running.</p><pre class="brush: csharp; gutter: false; toolbar: false; auto-links: false;">if (AreWe.InDockerOrBuildServer) return;</pre>
  129. <p>Now my tests run and I get a nice series of charts to show that fact.</p>
  130. <p><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(46)_4.png"><img title="22 tests, 4 skipped" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="22 tests, 4 skipped" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(46)_thumb_1.png" width="642" height="319"></a></p>
  131. <p>I have it building and tests running.</p>
  132. <p>I could add the Deployment Step to the Build but Azure DevOps Pipelines includes a better way. I make a Release Pipeline that is separate. It takes Artifacts as input and runs n number of Stages.</p>
  133. <p><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(48)_4.png"><img title="Creating a new Release Pipeline" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Creating a new Release Pipeline" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(48)_thumb_1.png" width="642" height="473"></a></p>
  134. <p>I take the Artifact from the Build (the zipped up binaries) and pass them through the pipeline into the Azure App Service Deploy step.</p>
  135. <p><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(49)_4.png"><img title="Screenshot (49)" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Screenshot (49)" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(49)_thumb_1.png" width="642" height="251"></a></p>
  136. <p>Here's the deployment in progress.</p>
  137. <p><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(53)_4.png"><img title="Manually Triggered Release" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Manually Triggered Release" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(53)_thumb_1.png" width="642" height="435"></a></p>
  138. <p>Cool! Now that it works and deploys, I can turn on Continuous Integration Build Triggers (via an automatic GitHub webhook) as well as Continuous Deployment triggers.</p>
  139. <p><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/image_4.png"><img title="Continuous Deployment" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Continuous Deployment" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/image_thumb_1.png" width="642" height="375"></a></p>
  140. <p>Azure DevOps even includes badges that I can add to my readme.md so I always know by looking at GitHub if my site builds AND if it has successfully deployed.</p>
  141. <p><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/image_10.png"><img title="4 releases, the final one succeeded" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="4 releases, the final one succeeded" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/image_thumb_3.png" width="642" height="393"></a></p>
  142. <p>Now I can see each release as it happens and if it's successful or not.</p>
  143. <p><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(50)_7.png"><img title="Build Succeeded, Never Deployed" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Build Succeeded, Never Deployed" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/Screenshot%20(50)_thumb_2.png" width="599" height="482"></a></p>
  144. <p>To top it all off, now that I have all this data and these pipelines, I even put together a nice little dashboard in about a minute to show Deployment Status and Test Trends.</p>
  145. <p><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/image_2.png"><img title="My build and deployment dashboard" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="My build and deployment dashboard" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/image_thumb.png" width="642" height="425"></a></p>
  146. <p>When I combine the DevOps Dashboard with my main Azure Dashboard I'm amazed at how much information I can get in so little effort. Consider that my podcast (my little business) is a one-person shop. </p><figure><img title="Azure Dashboard" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="Azure Dashboard" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/b6f8d910d964_99EF/image_9.png" width="1001" height="335"></figure>
  147. <p>And now I have a CI/CD pipeline with integrated testing gates that deploys worldwide. Many years ago this would have required a team and a lot of custom code.</p>
  148. <p> Today it took an hour. Awesome. </p>
  149. <p>I check into GitHub, kicks off a build, tests, emails me the results, and deploys the website if everything is cool. Of course, if I had another team member I could put in deployment gates or reviews, etc.</p>
  150. <hr>
  151. <p><strong>Sponsor:</strong> Copy: <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://hnsl.mn/2QMyhmf">Rider 2018.2 is here</a>! Publishing to IIS, Docker support in the debugger, built-in spell checking, MacBook Touch Bar support, full C# 7.3 support, advanced Unity support, and more.</p>
  152. <br/><hr/>© 2018 Scott Hanselman. All rights reserved.
  153. <br/></div><Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="http://feeds.hanselman.com/~/i/570548572/0/scotthanselman">
  154. <div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="http://feeds.hanselman.com/_/28/570548572/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Share on Google+" href="http://feeds.hanselman.com/_/30/570548572/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/googleplus20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Tweet This" href="http://feeds.hanselman.com/_/24/570548572/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/twitter20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="http://feeds.hanselman.com/_/19/570548572/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="http://feeds.hanselman.com/_/20/570548572/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
  155. </content:encoded></item>
  156. <item>
  157. <feedburner:origLink>https://www.hanselman.com/blog/ACompleteContainerizedNETCoreApplicationMicroserviceThatIsAsSmallAsPossible.aspx</feedburner:origLink>
  158.      <trackback:ping>https://www.hanselman.com/blog/Trackback.aspx?guid=fa757b55-6aa0-4215-8f9a-e6b88bc476e0</trackback:ping>
  159.      <pingback:server>https://www.hanselman.com/blog/pingback.aspx</pingback:server>
  160.      <pingback:target>https://www.hanselman.com/blog/PermaLink.aspx?guid=fa757b55-6aa0-4215-8f9a-e6b88bc476e0</pingback:target>
  161.      <dc:creator>Scott Hanselman</dc:creator>
  162.      <wfw:comment>https://www.hanselman.com/blog/CommentView.aspx?guid=fa757b55-6aa0-4215-8f9a-e6b88bc476e0</wfw:comment>
  163.      <wfw:commentRss>https://www.hanselman.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=fa757b55-6aa0-4215-8f9a-e6b88bc476e0</wfw:commentRss>
  164.      <slash:comments>5</slash:comments>
  165.      <title>A complete containerized .NET Core Application microservice that is as small as possible</title>
  166.      <guid isPermaLink="false">https://www.hanselman.com/blog/PermaLink.aspx?guid=fa757b55-6aa0-4215-8f9a-e6b88bc476e0</guid>
  167.      <link>http://feeds.hanselman.com/~/569628958/0/scotthanselman~A-complete-containerized-NET-Core-Application-microservice-that-is-as-small-as-possible.aspx</link>
  168.      <pubDate>Fri, 14 Sep 2018 01:10:00 GMT</pubDate>
  169.      <description><![CDATA[<div><p>OK, maybe not technically a microservice, but that's a hot buzzword these days, right? A few weeks ago I blogged about <a href="https://www.hanselman.com/blog/ImprovementsOnASPNETCoreDeploymentsOnZeitsNowshAndMakingSmallContainerImages.aspx">Improvements on ASP.NET Core deployments on Zeit's now.sh and making small container images</a>. By the end I was able to cut my container size in half.</p> <p>The trimming I was using is experimental and very aggressive. If you app loads things at runtime - like ASP.NET Razor Pages sometimes does - you may end up getting weird errors at runtime when a Type is missing. <strong>Some types may have been trimmed away!</strong></p> <p>For example:</p><pre>fail: Microsoft.AspNetCore.Server.Kestrel[13]<br>      Connection id "0HLGQ1DIEF1KV", Request id "0HLGQ1DIEF1KV:00000001": An unhandled exception was thrown by the application.<br>System.TypeLoadException: Could not load type 'Microsoft.AspNetCore.Diagnostics.IExceptionHandlerPathFeature' from assembly 'Microsoft.Extensions.Primitives, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'.<br>   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)<br>   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine&amp; stateMachine)<br>   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)<br>   at Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware.Invoke(HttpContext context)<br>   at Microsoft.AspNetCore.Hosting.Internal.HostingApplication.ProcessRequestAsync(Context context)<br>   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)</pre>
  170. <p>Yikes!</p>
  171. <p>I'm doing a self-Contained deployment and then trim the result! Richard Lander has a <a href="https://github.com/dotnet/dotnet-docker/blob/master/samples/dotnetapp/Dockerfile.alpine-x64-selfcontained?WT.mc_id=-blog-scottha">great dockerfile example</a>. Note how he's doing the package addition with the dotnet CLI with "dotnet add package" and subsequent trim <em>within </em>the Dockerfile (as opposed to you adding it to your local development copy's csproj).</p>
  172. <p>I'm adding the Tree Trimming Linker in the Dockerfile, so the trimming happens when the container image is built. I'm using the dotnet command to "dotnet add package ILLink.Tasks. This means I don't need to reference the linker package at development time - it's all at container build time.</p><pre>FROM microsoft/dotnet:2.1-sdk-alpine AS build<br>WORKDIR /app<br><br># copy csproj and restore as distinct layers<br>COPY *.sln .<br>COPY nuget.config . <br>COPY superzeit/*.csproj ./superzeit/<br>RUN dotnet restore<br><br># copy everything else and build app<br>COPY . .<br>WORKDIR /app/superzeit<br>RUN dotnet build<br> <br>FROM build AS publish<br>WORKDIR /app/superzeit<br># add IL Linker package<br>RUN dotnet add package ILLink.Tasks -v 0.1.5-preview-1841731 -s https://dotnet.myget.org/F/dotnet-core/api/v3/index.json<br>RUN dotnet publish -c Release -o out -r linux-musl-x64 /p:ShowLinkerSizeComparison=true <br><br>FROM microsoft/dotnet:2.1-runtime-deps-alpine AS runtime<br>ENV DOTNET_USE_POLLING_FILE_WATCHER=true<br>WORKDIR /app<br>COPY --from=publish /app/superzeit/out ./<br>ENTRYPOINT ["dotnet", "superzeit.dll"]</pre>
  173. <p>I did end up hitting <a href="https://github.com/mono/linker/issues/314?WT.mc_id=-blog-scottha">this bug</a> in the Linker (it's not Released) but <a href="https://github.com/mono/linker/issues/314?WT.mc_id=-blog-scottha#issuecomment-417030818">there's an easy workaround</a>. I just need to set the property <code>CrossGenDuringPublish</code> to <code>false</code> in the project file.</p>
  174. <p>If you look at the <a href="https://github.com/dotnet/core/blob/master/samples/linker-instructions-advanced.md">Advanced Instructions for the Linker</a> you can see that you can "root" types or assemblies. Root means "don't mess with these or stuff that hangs off them." So I just need to exercise my app at runtime and make sure that all the types that my app needs are available, but no unnecessary ones.</p>
  175. <p>I added the Assemblies I wanted to keep (not remove) while trimming/linking to my project file:</p><pre class="brush: xml; gutter: false; toolbar: false; auto-links: false; highlight: [9];">&lt;Project Sdk="Microsoft.NET.Sdk.Web"&gt;<br><br>  &lt;PropertyGroup&gt;<br>    &lt;TargetFramework&gt;netcoreapp2.1&lt;/TargetFramework&gt;<br>    &lt;CrossGenDuringPublish&gt;false&lt;/CrossGenDuringPublish&gt;<br>  &lt;/PropertyGroup&gt;<br><br>  &lt;ItemGroup&gt;<br>    &lt;LinkerRootAssemblies Include="Microsoft.AspNetCore.Mvc.Razor.Extensions;Microsoft.Extensions.FileProviders.Composite;Microsoft.Extensions.Primitives;Microsoft.AspNetCore.Diagnostics.Abstractions" /&gt;<br>  &lt;/ItemGroup&gt; <br><br>  &lt;ItemGroup&gt;<br>    &lt;!-- this can be here, or can be done all at runtime in the Dockerfile --&gt;<br>    &lt;!-- &lt;PackageReference Include="ILLink.Tasks" Version="0.1.5-preview-1841731" /&gt;  --&gt;<br>    &lt;PackageReference Include="Microsoft.AspNetCore.App" /&gt;<br>  &lt;/ItemGroup&gt;<br><br>&lt;/Project&gt;</pre>
  176. <p>My strategy for figuring out which assemblies to "root" and exclude from trimming was literally to just iterate. Build, trim, test, add an assembly by reading the error message, and repeat.</p>
  177. <p>This sample ASP.NET Core app will deploy cleanly on Zeit with the smallest image footprint as possible. <a title="https://github.com/shanselman/superzeit" href="https://github.com/shanselman/superzeit">https://github.com/shanselman/superzeit</a></p>
  178. <p>Next I'll try an actual Microservice (as opposed to a complete website, which is what this is) and see how small I can get that. Such fun!</p>
  179. <p><strong>UPDATE:</strong> This technique works with "dotnet new webapi" as well and is about 73 megs per "docker images" and it's 34 megs when sent and squished through Zeit's "now" CLI.</p>
  180. <figure><img title="Small services!" style="display: inline" alt="Small services!" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/08a4897921d1_145DD/image_9ea15e6d-1b2f-4ee7-8724-bbf362dca95c.png" width="999" height="93"></figure>
  181. <p>
  182. <hr>
  183. </p>
  184. <p><strong>Sponsor: </strong><a href="https://hnsl.mn/2QnCAUI">Rider 2018.2 is here</a>! Publishing to IIS, Docker support in the debugger, built-in spell checking, MacBook Touch Bar support, full C# 7.3 support, advanced Unity support, and more.
  185. <br/><hr/>© 2018 Scott Hanselman. All rights reserved. <br/></div><div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="http://feeds.hanselman.com/_/28/569628958/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Share on Google+" href="http://feeds.hanselman.com/_/30/569628958/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/googleplus20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Tweet This" href="http://feeds.hanselman.com/_/24/569628958/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/twitter20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="http://feeds.hanselman.com/_/19/569628958/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="http://feeds.hanselman.com/_/20/569628958/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
  186. </description>
  187.      <comments>https://www.hanselman.com/blog/CommentView.aspx?guid=fa757b55-6aa0-4215-8f9a-e6b88bc476e0</comments>
  188.      <category>Docker</category>
  189.      <category>Open Source</category><content:encoded><![CDATA[<div><p>OK, maybe not technically a microservice, but that's a hot buzzword these days, right? A few weeks ago I blogged about <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/ImprovementsOnASPNETCoreDeploymentsOnZeitsNowshAndMakingSmallContainerImages.aspx">Improvements on ASP.NET Core deployments on Zeit's now.sh and making small container images</a>. By the end I was able to cut my container size in half.</p> <p>The trimming I was using is experimental and very aggressive. If you app loads things at runtime - like ASP.NET Razor Pages sometimes does - you may end up getting weird errors at runtime when a Type is missing. <strong>Some types may have been trimmed away!</strong></p> <p>For example:</p><pre>fail: Microsoft.AspNetCore.Server.Kestrel[13]
  190. <br>      Connection id "0HLGQ1DIEF1KV", Request id "0HLGQ1DIEF1KV:00000001": An unhandled exception was thrown by the application.
  191. <br>System.TypeLoadException: Could not load type 'Microsoft.AspNetCore.Diagnostics.IExceptionHandlerPathFeature' from assembly 'Microsoft.Extensions.Primitives, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'.
  192. <br>   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
  193. <br>   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine&amp; stateMachine)
  194. <br>   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
  195. <br>   at Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware.Invoke(HttpContext context)
  196. <br>   at Microsoft.AspNetCore.Hosting.Internal.HostingApplication.ProcessRequestAsync(Context context)
  197. <br>   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)</pre>
  198. <p>Yikes!</p>
  199. <p>I'm doing a self-Contained deployment and then trim the result! Richard Lander has a <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/dotnet/dotnet-docker/blob/master/samples/dotnetapp/Dockerfile.alpine-x64-selfcontained?WT.mc_id=-blog-scottha">great dockerfile example</a>. Note how he's doing the package addition with the dotnet CLI with "dotnet add package" and subsequent trim <em>within </em>the Dockerfile (as opposed to you adding it to your local development copy's csproj).</p>
  200. <p>I'm adding the Tree Trimming Linker in the Dockerfile, so the trimming happens when the container image is built. I'm using the dotnet command to "dotnet add package ILLink.Tasks. This means I don't need to reference the linker package at development time - it's all at container build time.</p><pre>FROM microsoft/dotnet:2.1-sdk-alpine AS build
  201. <br>WORKDIR /app
  202. <br>
  203. <br># copy csproj and restore as distinct layers
  204. <br>COPY *.sln .
  205. <br>COPY nuget.config .
  206. <br>COPY superzeit/*.csproj ./superzeit/
  207. <br>RUN dotnet restore
  208. <br>
  209. <br># copy everything else and build app
  210. <br>COPY . .
  211. <br>WORKDIR /app/superzeit
  212. <br>RUN dotnet build
  213. <br>
  214. <br>FROM build AS publish
  215. <br>WORKDIR /app/superzeit
  216. <br># add IL Linker package
  217. <br>RUN dotnet add package ILLink.Tasks -v 0.1.5-preview-1841731 -s https://dotnet.myget.org/F/dotnet-core/api/v3/index.json
  218. <br>RUN dotnet publish -c Release -o out -r linux-musl-x64 /p:ShowLinkerSizeComparison=true
  219. <br>
  220. <br>FROM microsoft/dotnet:2.1-runtime-deps-alpine AS runtime
  221. <br>ENV DOTNET_USE_POLLING_FILE_WATCHER=true
  222. <br>WORKDIR /app
  223. <br>COPY --from=publish /app/superzeit/out ./
  224. <br>ENTRYPOINT ["dotnet", "superzeit.dll"]</pre>
  225. <p>I did end up hitting <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/mono/linker/issues/314?WT.mc_id=-blog-scottha">this bug</a> in the Linker (it's not Released) but <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/mono/linker/issues/314?WT.mc_id=-blog-scottha#issuecomment-417030818">there's an easy workaround</a>. I just need to set the property <code>CrossGenDuringPublish</code> to <code>false</code> in the project file.</p>
  226. <p>If you look at the <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/dotnet/core/blob/master/samples/linker-instructions-advanced.md">Advanced Instructions for the Linker</a> you can see that you can "root" types or assemblies. Root means "don't mess with these or stuff that hangs off them." So I just need to exercise my app at runtime and make sure that all the types that my app needs are available, but no unnecessary ones.</p>
  227. <p>I added the Assemblies I wanted to keep (not remove) while trimming/linking to my project file:</p><pre class="brush: xml; gutter: false; toolbar: false; auto-links: false; highlight: [9];">&lt;Project Sdk="Microsoft.NET.Sdk.Web"&gt;
  228. <br>
  229. <br>  &lt;PropertyGroup&gt;
  230. <br>    &lt;TargetFramework&gt;netcoreapp2.1&lt;/TargetFramework&gt;
  231. <br>    &lt;CrossGenDuringPublish&gt;false&lt;/CrossGenDuringPublish&gt;
  232. <br>  &lt;/PropertyGroup&gt;
  233. <br>
  234. <br>  &lt;ItemGroup&gt;
  235. <br>    &lt;LinkerRootAssemblies Include="Microsoft.AspNetCore.Mvc.Razor.Extensions;Microsoft.Extensions.FileProviders.Composite;Microsoft.Extensions.Primitives;Microsoft.AspNetCore.Diagnostics.Abstractions" /&gt;
  236. <br>  &lt;/ItemGroup&gt;
  237. <br>
  238. <br>  &lt;ItemGroup&gt;
  239. <br>    &lt;!-- this can be here, or can be done all at runtime in the Dockerfile --&gt;
  240. <br>    &lt;!-- &lt;PackageReference Include="ILLink.Tasks" Version="0.1.5-preview-1841731" /&gt;  --&gt;
  241. <br>    &lt;PackageReference Include="Microsoft.AspNetCore.App" /&gt;
  242. <br>  &lt;/ItemGroup&gt;
  243. <br>
  244. <br>&lt;/Project&gt;</pre>
  245. <p>My strategy for figuring out which assemblies to "root" and exclude from trimming was literally to just iterate. Build, trim, test, add an assembly by reading the error message, and repeat.</p>
  246. <p>This sample ASP.NET Core app will deploy cleanly on Zeit with the smallest image footprint as possible. <a title="https://github.com/shanselman/superzeit" href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/shanselman/superzeit">https://github.com/shanselman/superzeit</a></p>
  247. <p>Next I'll try an actual Microservice (as opposed to a complete website, which is what this is) and see how small I can get that. Such fun!</p>
  248. <p><strong>UPDATE:</strong> This technique works with "dotnet new webapi" as well and is about 73 megs per "docker images" and it's 34 megs when sent and squished through Zeit's "now" CLI.</p>
  249. <figure><img title="Small services!" style="display: inline" alt="Small services!" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/08a4897921d1_145DD/image_9ea15e6d-1b2f-4ee7-8724-bbf362dca95c.png" width="999" height="93"></figure>
  250. <p>
  251. <hr>
  252. </p>
  253. <p><strong>Sponsor: </strong><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://hnsl.mn/2QnCAUI">Rider 2018.2 is here</a>! Publishing to IIS, Docker support in the debugger, built-in spell checking, MacBook Touch Bar support, full C# 7.3 support, advanced Unity support, and more.
  254.  
  255. <br/><hr/>© 2018 Scott Hanselman. All rights reserved.
  256. <br/></div><Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="http://feeds.hanselman.com/~/i/569628958/0/scotthanselman">
  257. <div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="http://feeds.hanselman.com/_/28/569628958/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Share on Google+" href="http://feeds.hanselman.com/_/30/569628958/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/googleplus20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Tweet This" href="http://feeds.hanselman.com/_/24/569628958/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/twitter20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="http://feeds.hanselman.com/_/19/569628958/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="http://feeds.hanselman.com/_/20/569628958/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
  258. </content:encoded></item>
  259. <item>
  260. <feedburner:origLink>https://www.hanselman.com/blog/HowDoYouUseSystemDrawingInNETCore.aspx</feedburner:origLink>
  261.      <trackback:ping>https://www.hanselman.com/blog/Trackback.aspx?guid=a1632299-b4e0-41c8-bc69-6ef049e9aece</trackback:ping>
  262.      <pingback:server>https://www.hanselman.com/blog/pingback.aspx</pingback:server>
  263.      <pingback:target>https://www.hanselman.com/blog/PermaLink.aspx?guid=a1632299-b4e0-41c8-bc69-6ef049e9aece</pingback:target>
  264.      <dc:creator>Scott Hanselman</dc:creator>
  265.      <wfw:comment>https://www.hanselman.com/blog/CommentView.aspx?guid=a1632299-b4e0-41c8-bc69-6ef049e9aece</wfw:comment>
  266.      <wfw:commentRss>https://www.hanselman.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=a1632299-b4e0-41c8-bc69-6ef049e9aece</wfw:commentRss>
  267.      <slash:comments>11</slash:comments>
  268.      <title>How do you use System.Drawing in .NET Core?</title>
  269.      <guid isPermaLink="false">https://www.hanselman.com/blog/PermaLink.aspx?guid=a1632299-b4e0-41c8-bc69-6ef049e9aece</guid>
  270.      <link>http://feeds.hanselman.com/~/569206030/0/scotthanselman~How-do-you-use-SystemDrawing-in-NET-Core.aspx</link>
  271.      <pubDate>Wed, 12 Sep 2018 01:38:00 GMT</pubDate>
  272.      <description><![CDATA[<div><p>I've been doing .NET image processing since the beginning. In fact I wrote about it <a href="https://www.hanselman.com/blog/CompositingTwoImagesIntoOneFromTheASPNETServerSide.aspx">over 13 years ago on this blog</a> when I talked about <a href="https://www.hanselman.com/blog/CompositingTwoImagesIntoOneFromTheASPNETServerSide.aspx">Compositing two images into one from the ASP.NET Server Side</a> and in it I used <a href="https://docs.microsoft.com/en-us/dotnet/api/system.drawing?view=netframework-4.7.2"><strong>System.Drawing</strong></a><strong> </strong>to do the work. For over a decade folks using System.Drawing were just using it as a thin wrapper over GDI (Graphics Device Interface) which were very old Win32 (Windows) unmanaged drawing APIs. We use them because they work fine.</p> <blockquote> <p><strong>.NET Conf: </strong>Join us <em>this week!</em> September 12-14, 2018 for <a href="https://www.dotnetconf.net/?WT.mc_id=-blog-scottha">.NET Conf</a>! It's a FREE, 3 day virtual developer event co-organized by the .NET Community and Microsoft. Watch <a href="https://www.dotnetconf.net/?WT.mc_id=-blog-scottha">all the sessions here</a>. Join a <a href="https://www.dotnetconf.net/Party/">virtual attendee party</a> after the last session ends on Day 1 where you can win prizes! <a href="https://www.dotnetconf.net/Agenda">Check out the schedule</a> here and <a href="https://www.dotnetconf.net/local-events/">attend a local event in your area</a> organized by .NET community influencers all over the world.</p></blockquote> <p><a href="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/d02a115b3277_121FF/dotnetbot_2.png"><img title="DotNetBot" style="float: right; display: inline" alt="DotNetBot" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/d02a115b3277_121FF/dotnetbot_thumb.png" width="250" align="right" height="281"></a>For a while there was a package called <a href="https://github.com/CoreCompat/CoreCompat">CoreCompat.System.Drawing</a> that was a .NET Core port of a Mono version of System.Drawing. </p> <p>However, since then <strong>Microsoft has released </strong><a href="https://www.nuget.org/packages/System.Drawing.Common"><strong>System.Drawing.Common</strong></a><strong> to provide access to GDI+ graphics functionality cross-platform.</strong></p> <p>There is a lot of existing code - mine included - that makes assumptions that .NET would only ever run on Windows. Using System.Drawing was one of those things. The "<a href="https://blogs.msdn.microsoft.com/dotnet/2017/11/16/announcing-the-windows-compatibility-pack-for-net-core/">Windows Compatibility Pack</a>" is a package meant for developers that need to port existing .NET Framework code to .NET Core. Some of the APIs remain Windows only but others will allow you to take existing code and make it cross-platform with a minimum of trouble.</p> <p>Here's a super simple app that resizes a PNG to 128x128. However, it's a .NET Core app and it runs in both Windows and Linux (Ubuntu!)</p><pre class="brush: csharp; gutter: false; toolbar: false; auto-links: false;">using System;<br>using System.Drawing;<br>using System.Drawing.Drawing2D;<br>using System.Drawing.Imaging;<br>using System.IO;<br><br>namespace imageresize<br>{<br>    class Program<br>    {<br>        static void Main(string[] args)<br>        {<br>            int width = 128;<br>            int height = 128;<br>            var file = args[0];<br>            Console.WriteLine($"Loading {file}");<br>            using(FileStream pngStream = new FileStream(args[0],FileMode.Open, FileAccess.Read))<br>            using(var image = new Bitmap(pngStream))<br>            {<br>                var resized = new Bitmap(width, height);<br>                using (var graphics = Graphics.FromImage(resized))<br>                {<br>                    graphics.CompositingQuality = CompositingQuality.HighSpeed;<br>                    graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;<br>                    graphics.CompositingMode = CompositingMode.SourceCopy;<br>                    graphics.DrawImage(image, 0, 0, width, height);<br>                    resized.Save($"resized-{file}", ImageFormat.Png);<br>                    Console.WriteLine($"Saving resized-{file} thumbnail");<br>                }       <br>            }     <br>        }<br>    }<br>}
  273. </pre>
  274. <p>Here it is running on Ubuntu:</p>
  275. <p><img title="Resizing Images on Ubuntu" style="display: inline" alt="Resizing Images on Ubuntu" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/d02a115b3277_121FF/image_3.png" width="640" height="148"></p>
  276. <p>NOTE that on Ubuntu (and other Linuxes) you may need to install some native dependencies as System.Drawing sits on top of native libraries</p><pre>sudo apt install libc6-dev <br>sudo apt install libgdiplus</pre>
  277. <p>There's lots of great options for image processing on .NET Core now! It's important to understand that this System.Drawing layer is great for existing System.Drawing code, but you probably shouldn't write NEW image management code with it. Instead, consider one of the great other open source options. </p>
  278. <ul>
  279. <li><a href="https://github.com/SixLabors/ImageSharp">ImageSharp</a> - A cross-platform library for the processing of image files; written in C#
  280. <ul>
  281. <li>Compared to <code>System.Drawing</code> ImageSharp has been able to develop something much more flexible, easier to code against, and much, much less prone to memory leaks. Gone are system-wide process-locks; ImageSharp images are thread-safe and fully supported in web environments.</li></ul></li></ul>
  282. <p>Here's how you'd resize something with ImageSharp:</p><pre class="brush: csharp; gutter: false; toolbar: false; auto-links: false;">using (Image&lt;Rgba32&gt; image = Image.Load("foo.jpg"))<br>{<br>    image.Mutate(x =&gt; x<br>         .Resize(image.Width / 2, image.Height / 2)<br>         .Grayscale());<br>    image.Save("bar.jpg"); // Automatic encoder selected based on extension.<br>}</pre>
  283. <ul>
  284. <li><a href="https://github.com/dlemstra/Magick.NET/">Magick.NET</a> -A .NET library on top of ImageMagick
  285. <li><a href="https://github.com/mono/SkiaSharp/">SkiaSharp</a> - A .NET wrapper on top of Google's cross-platform Skia library</li></ul>
  286. <p>It's awesome that there are so many choices with .NET Core now!</p>
  287. <p>
  288. <hr>
  289. <p><strong>Sponsor: </strong><a href="https://hnsl.mn/2QnCAUI">Rider 2018.2 is here</a>! Publishing to IIS, Docker support in the debugger, built-in spell checking, MacBook Touch Bar support, full C# 7.3 support, advanced Unity support, and more.</p><br/><hr/>© 2018 Scott Hanselman. All rights reserved. <br/></div><div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="http://feeds.hanselman.com/_/28/569206030/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Share on Google+" href="http://feeds.hanselman.com/_/30/569206030/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/googleplus20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Tweet This" href="http://feeds.hanselman.com/_/24/569206030/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/twitter20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="http://feeds.hanselman.com/_/19/569206030/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="http://feeds.hanselman.com/_/20/569206030/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
  290. </description>
  291.      <comments>https://www.hanselman.com/blog/CommentView.aspx?guid=a1632299-b4e0-41c8-bc69-6ef049e9aece</comments>
  292.      <category>DotNetCore</category>
  293.      <category>Open Source</category><content:encoded><![CDATA[<div><p>I've been doing .NET image processing since the beginning. In fact I wrote about it <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/CompositingTwoImagesIntoOneFromTheASPNETServerSide.aspx">over 13 years ago on this blog</a> when I talked about <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/CompositingTwoImagesIntoOneFromTheASPNETServerSide.aspx">Compositing two images into one from the ASP.NET Server Side</a> and in it I used <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://docs.microsoft.com/en-us/dotnet/api/system.drawing?view=netframework-4.7.2"><strong>System.Drawing</strong></a><strong> </strong>to do the work. For over a decade folks using System.Drawing were just using it as a thin wrapper over GDI (Graphics Device Interface) which were very old Win32 (Windows) unmanaged drawing APIs. We use them because they work fine.</p> <blockquote> <p><strong>.NET Conf: </strong>Join us <em>this week!</em> September 12-14, 2018 for <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.dotnetconf.net/?WT.mc_id=-blog-scottha">.NET Conf</a>! It's a FREE, 3 day virtual developer event co-organized by the .NET Community and Microsoft. Watch <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.dotnetconf.net/?WT.mc_id=-blog-scottha">all the sessions here</a>. Join a <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.dotnetconf.net/Party/">virtual attendee party</a> after the last session ends on Day 1 where you can win prizes! <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.dotnetconf.net/Agenda">Check out the schedule</a> here and <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.dotnetconf.net/local-events/">attend a local event in your area</a> organized by .NET community influencers all over the world.</p></blockquote> <p><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/d02a115b3277_121FF/dotnetbot_2.png"><img title="DotNetBot" style="float: right; display: inline" alt="DotNetBot" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/d02a115b3277_121FF/dotnetbot_thumb.png" width="250" align="right" height="281"></a>For a while there was a package called <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/CoreCompat/CoreCompat">CoreCompat.System.Drawing</a> that was a .NET Core port of a Mono version of System.Drawing. </p> <p>However, since then <strong>Microsoft has released </strong><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.nuget.org/packages/System.Drawing.Common"><strong>System.Drawing.Common</strong></a><strong> to provide access to GDI+ graphics functionality cross-platform.</strong></p> <p>There is a lot of existing code - mine included - that makes assumptions that .NET would only ever run on Windows. Using System.Drawing was one of those things. The "<a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://blogs.msdn.microsoft.com/dotnet/2017/11/16/announcing-the-windows-compatibility-pack-for-net-core/">Windows Compatibility Pack</a>" is a package meant for developers that need to port existing .NET Framework code to .NET Core. Some of the APIs remain Windows only but others will allow you to take existing code and make it cross-platform with a minimum of trouble.</p> <p>Here's a super simple app that resizes a PNG to 128x128. However, it's a .NET Core app and it runs in both Windows and Linux (Ubuntu!)</p><pre class="brush: csharp; gutter: false; toolbar: false; auto-links: false;">using System;
  294. <br>using System.Drawing;
  295. <br>using System.Drawing.Drawing2D;
  296. <br>using System.Drawing.Imaging;
  297. <br>using System.IO;
  298. <br>
  299. <br>namespace imageresize
  300. <br>{
  301. <br>    class Program
  302. <br>    {
  303. <br>        static void Main(string[] args)
  304. <br>        {
  305. <br>            int width = 128;
  306. <br>            int height = 128;
  307. <br>            var file = args[0];
  308. <br>            Console.WriteLine($"Loading {file}");
  309. <br>            using(FileStream pngStream = new FileStream(args[0],FileMode.Open, FileAccess.Read))
  310. <br>            using(var image = new Bitmap(pngStream))
  311. <br>            {
  312. <br>                var resized = new Bitmap(width, height);
  313. <br>                using (var graphics = Graphics.FromImage(resized))
  314. <br>                {
  315. <br>                    graphics.CompositingQuality = CompositingQuality.HighSpeed;
  316. <br>                    graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
  317. <br>                    graphics.CompositingMode = CompositingMode.SourceCopy;
  318. <br>                    graphics.DrawImage(image, 0, 0, width, height);
  319. <br>                    resized.Save($"resized-{file}", ImageFormat.Png);
  320. <br>                    Console.WriteLine($"Saving resized-{file} thumbnail");
  321. <br>                }      
  322. <br>            }    
  323. <br>        }
  324. <br>    }
  325. <br>}
  326. </pre>
  327. <p>Here it is running on Ubuntu:</p>
  328. <p><img title="Resizing Images on Ubuntu" style="display: inline" alt="Resizing Images on Ubuntu" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/d02a115b3277_121FF/image_3.png" width="640" height="148"></p>
  329. <p>NOTE that on Ubuntu (and other Linuxes) you may need to install some native dependencies as System.Drawing sits on top of native libraries</p><pre>sudo apt install libc6-dev
  330. <br>sudo apt install libgdiplus</pre>
  331. <p>There's lots of great options for image processing on .NET Core now! It's important to understand that this System.Drawing layer is great for existing System.Drawing code, but you probably shouldn't write NEW image management code with it. Instead, consider one of the great other open source options. </p>
  332. <ul>
  333. <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/SixLabors/ImageSharp">ImageSharp</a> - A cross-platform library for the processing of image files; written in C#
  334. <ul>
  335. <li>Compared to <code>System.Drawing</code> ImageSharp has been able to develop something much more flexible, easier to code against, and much, much less prone to memory leaks. Gone are system-wide process-locks; ImageSharp images are thread-safe and fully supported in web environments.</li></ul></li></ul>
  336. <p>Here's how you'd resize something with ImageSharp:</p><pre class="brush: csharp; gutter: false; toolbar: false; auto-links: false;">using (Image&lt;Rgba32&gt; image = Image.Load("foo.jpg"))
  337. <br>{
  338. <br>    image.Mutate(x =&gt; x
  339. <br>         .Resize(image.Width / 2, image.Height / 2)
  340. <br>         .Grayscale());
  341. <br>    image.Save("bar.jpg"); // Automatic encoder selected based on extension.
  342. <br>}</pre>
  343. <ul>
  344. <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/dlemstra/Magick.NET/">Magick.NET</a> -A .NET library on top of ImageMagick
  345. <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/mono/SkiaSharp/">SkiaSharp</a> - A .NET wrapper on top of Google's cross-platform Skia library</li></ul>
  346. <p>It's awesome that there are so many choices with .NET Core now!</p>
  347. <p>
  348. <hr>
  349. <p><strong>Sponsor: </strong><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://hnsl.mn/2QnCAUI">Rider 2018.2 is here</a>! Publishing to IIS, Docker support in the debugger, built-in spell checking, MacBook Touch Bar support, full C# 7.3 support, advanced Unity support, and more.</p>
  350. <br/><hr/>© 2018 Scott Hanselman. All rights reserved.
  351. <br/></div><Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="http://feeds.hanselman.com/~/i/569206030/0/scotthanselman">
  352. <div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="http://feeds.hanselman.com/_/28/569206030/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Share on Google+" href="http://feeds.hanselman.com/_/30/569206030/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/googleplus20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Tweet This" href="http://feeds.hanselman.com/_/24/569206030/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/twitter20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="http://feeds.hanselman.com/_/19/569206030/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="http://feeds.hanselman.com/_/20/569206030/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
  353. </content:encoded></item>
  354. <item>
  355. <feedburner:origLink>https://www.hanselman.com/blog/TheExtremelyPromisingStateOfDiabetesTechnologyIn2018.aspx</feedburner:origLink>
  356.      <trackback:ping>https://www.hanselman.com/blog/Trackback.aspx?guid=6b44c29b-2504-43a7-adde-23a4ba032845</trackback:ping>
  357.      <pingback:server>https://www.hanselman.com/blog/pingback.aspx</pingback:server>
  358.      <pingback:target>https://www.hanselman.com/blog/PermaLink.aspx?guid=6b44c29b-2504-43a7-adde-23a4ba032845</pingback:target>
  359.      <dc:creator>Scott Hanselman</dc:creator>
  360.      <wfw:comment>https://www.hanselman.com/blog/CommentView.aspx?guid=6b44c29b-2504-43a7-adde-23a4ba032845</wfw:comment>
  361.      <wfw:commentRss>https://www.hanselman.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=6b44c29b-2504-43a7-adde-23a4ba032845</wfw:commentRss>
  362.      <slash:comments>6</slash:comments>
  363.      <title>The Extremely Promising State of Diabetes Technology in 2018</title>
  364.      <guid isPermaLink="false">https://www.hanselman.com/blog/PermaLink.aspx?guid=6b44c29b-2504-43a7-adde-23a4ba032845</guid>
  365.      <link>http://feeds.hanselman.com/~/568851230/0/scotthanselman~The-Extremely-Promising-State-of-Diabetes-Technology-in.aspx</link>
  366.      <pubDate>Fri, 07 Sep 2018 01:23:00 GMT</pubDate>
  367.      <description><![CDATA[<div><p>This blog post is an update to these two Diabetes Technology blog posts:</p> <ul> <li><a href="https://www.hanselman.com/blog/ThePromisingStateOfDiabetesTechnologyIn2016.aspx">The Promising State of Diabetes Technology in 2016</a>  <li><a href="https://www.hanselman.com/blog/TheSadStateOfDiabetesTechnologyIn2012.aspx">The Sad State of Diabetes Technology in 2012</a></li></ul> <p>You might also enjoy this video of the talk I gave at <a href="https://www.webstock.org.nz/talks/solving-diabetes-open-source-artificial-pancreas/">WebStock 2018</a> on <a href="https://www.webstock.org.nz/talks/solving-diabetes-open-source-artificial-pancreas/">Solving Diabetes with an Open Source Artificial Pancreas</a>*.</p> <p>First, let me tell you that insulin is too expensive in the US.</p> <blockquote> <p>Between 2002 and 2013, the <a href="https://jamanetwork.com/journals/jama/fullarticle/2510902">price of insulin jumped</a>, with the typical cost for patients increasing from about $40 a vial to $130.</p></blockquote> <p><img title="Open Source Artificial Pancreas on iPhone" style="float: right; display: inline" alt="Open Source Artificial Pancreas on iPhone" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/d181bafac8b1_14937/phones_5a4afeef-5bb7-4d8d-87fd-acc902585a1d.png" width="371" align="right" height="733">For some of the newer insulins like the ones I use, I pay as much as $296 a bottle. I have a Health Savings Plan so this is often out of pocket until I hit the limit for the year. </p> <p>People in America are rationing insulin. This is <a href="https://twitter.com/maykeila_brooke/status/1038247265217929216">demonstrable fact</a>. I've personally mailed extra insulin to folks in need. I've meet young people who lost their insurance at age 26 and have had to skip shots to save vials of insulin.</p> <p>This is a problem, but on the technology side there's some extremely promising work happening, and it's we have really hit our stride in the last ten years. </p> <p>I wrote the <a href="http://copilotconsulting.com/mail-archives/pilot.1998/msg09007.html">first Glucose Management system for the PalmPilot in 1998 called GlucoPilot</a> and provided on the go in-depth analysis for the first time. The first thing that struck me was that the PalmPilot and the Blood Sugar Meter were the same size. Why did I need <em>two</em> devices with batteries, screens, buttons and a CPU? Why so many devices?  <p><strong>I've been told every year the a Diabetes Breakthrough is coming "in five years." It's been 25 years.</strong>  <p>In 2001 <a href="http://www.thefeaturearchives.com/topic/Archive/One_Guy__an_Insulin_Pump__and_8_PDAs.html">I went on a trip across the country with my wife, an insulin pump and 8 PDAs</a> (personal digital assistants, the "iPhones" of the time) and tried to manage my diabetes using all the latest wireless technology...this was the <strong>latest stuff 17 years ago</strong>. I had just moved from injections to an insulin pump. Even now in 2018 Insulin Pumps are expensive, mostly proprietary, and super expensive. In fact, many folks use insulin pumps in the states use out of warranty pumps purchased on Craigslist.  <p>Fast forward to 2018 and I've been using an <strong>Open Source Artificial Pancreas for two years.</strong></p> <ul> <li><a href="https://openaps.org/"><strong>OpenAPS</strong></a><strong> - Open Artificial Pancreas System. A platform for building a closed-loop with open tools. </strong> <ul> <li><a href="https://androidaps.readthedocs.io/en/latest/"><strong>AndroidAPS</strong></a><strong> - A branch of OpenAPS running on Android</strong></li></ul> <li><a href="https://www.loopdocs.org"><strong>Loop/LoopKit</strong></a><strong> - Open Source Artificial Pancreas running on the iPhone with a hardware bridge (RileyLink) to the pump. </strong> <ul> <li><strong>I run this pancreas, personally, and have for nearly 2 years.</strong></li></ul> <li><a href="https://www.youtube.com/watch?v=eQGWrdgu_fE"><strong>Watch Dana Lewis (the originator of OpenAPS) talk about OpenAPS at OSCON</strong></a><strong>!</strong></li></ul> <p>The results speak for themselves. While I do have bad sugars sometimes, and I do struggle, if you look at my blood work my HA1c (the long term measurement of "how I'm doing" shows non-diabetic levels. To be clear - I'm fully and completely Type 1 diabetic, I produce zero insulin of my own. I take between 40 and 50 Units of insulin every day, and have for the last 25 years...but I will <strong>likely die of old age.</strong></p> <center> <blockquote class="twitter-tweet" data-lang="en"> <p lang="en" dir="ltr">Open Source Artificial Pancreas === Diabetes results <a href="https://t.co/ZSsApTLRXq">pic.twitter.com/ZSsApTLRXq</a></p>— Scott Hanselman (@shanselman) <a href="https://twitter.com/shanselman/status/1038996542571466752?ref_src=twsrc%5Etfw">September 10, 2018</a></blockquote></center><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> <p>This is significant. Why? Because historically diabetics die of diabetes. While we wait (or more accurately, <a href="https://twitter.com/search?q=wearenotwaiting&amp;src=typd">#WeAreNotWaiting</a>) for a biological/medical solution to Type 1 diabetes, the DIY (Do It Yourself) community is just doing it ourselves. </p> <p>Building on open hardware, open software, and reverse-engineered protocols for proprietary hardware, the online diabetes community <em>literally has their choice of open source pancreases in 2018! </em>Who would have imagined it. You can choose your algorithms, your phone, your pump, your continuous glucose meter. </p> <blockquote> <p><strong>Today, in 2018, you can literally change the code and recompile a personal branch of your own pancreas.</strong></p></blockquote> <p>Watch my 2010 YouTube video "<a href="https://www.youtube.com/watch?v=jsxFbDIvQRw">I am Diabetic</a>" as I walk you through the medical hardware (pumps, needles, tubes, wires) in managing diabetes day to day. Then watch my 2018 talk on <a href="https://www.webstock.org.nz/talks/solving-diabetes-open-source-artificial-pancreas/">Solving Diabetes with an Open Source Artificial Pancreas</a>*.</p> <p>I believe that every diabetic should be offered a pump, a continuous glucose meter, and trained on some kind of artificial pancreas. A cloud based reporting system has also been a joy. My wife and family can see my sugar in real time when I'm away. My wife has even called me overseas to wake me up when I was in a bad sugar situation. </p> <p><img title="Artificial Pancreas generations" alt="Artificial Pancreas generations" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/Its-far-too-early-to-call-an-Insulin-Pum_E18A/app_6_steps_621_47a5d186-917b-48d9-8234-a68a6f7eea03.jpg"></p> <p>As the closed-hardware and closed-software medical companies work towards their own artificial pancreases, the open source community feel those companies would better serve us by opening up their protocols, using standard <a href="https://www.diabetestechnology.org/dtsec-standard-final.pdf">Bluetooth ISO profiles</a> and use <a href="https://www.diabetestechnology.org/dtsec-protection-profile-final.pdf">security best practices</a>. </p> <p>Looking at the table above, the open source community is squarely in #4 and moving quickly into #5. But why did we have to do this ourselves? We got tired of waiting.</p> <p>All in all, through open software and hardware, I can tell you that my life is SO MUCH BETTER than it was when I was first diagnosed. I figure we'll have this all figured out in about five years, right? ;)</p> <p>THANK YOU!</p> <h3>MORE DIABETES READING</h3> <ul> <li><a href="https://www.hanselman.com/blog/BridgingDexcomShareCGMReceiversAndNightscout.aspx">Bridging Dexcom Share CGM Receivers and Nightscout</a>  <li><a href="https://www.hanselman.com/blog/HackingDiabetes.aspx">Hacking Diabetes</a>  <li><a href="https://www.hanselman.com/blog/VisualizingYourRealtimeBloodSugarValuesANDAGitPromptOnWindowsPowerShellAndLinuxBash.aspx">Visualizing your real-time blood sugar values in Git</a><!--EndFragment-->  <li><a href="https://www.hanselman.com/blog/DiabetesTechnologyDexcomG5CGMReviewSoMuchWastedPotential.aspx">Diabetes Technology: Dexcom G5 CGM Review</a>  <li><a href="https://www.hanselman.com/blog/IntroducingWebTilesForMicrosoftBandMyDiabetesDataOnABand.aspx">Introducing Web Tiles for Microsoft Band - My diabetes data on a Band!</a>  <li><a href="https://www.hanselman.com/blog/DiabeticsItsFunToSayBionicPancreasButHowAboutARealityCheck.aspx">Diabetics: It's fun to say Bionic Pancreas but how about a reality check</a>  <li><a href="https://www.hanselman.com/blog/ItsWAYTooEarlyToCallThisInsulinPumpAnArtificialPancreas.aspx">It's WAY too early to call this Insulin Pump an Artificial Pancreas</a></li></ul> <p>* Yes there are some analogies, stretched metaphors, and oversimplifications in <a href="https://www.webstock.org.nz/talks/solving-diabetes-open-source-artificial-pancreas/">this talk</a>. This talk is an introduction to the space to the normally-sugared. If you are a diabetes expert you might watch and say...eh...ya, I mean, it kind of works like that. Please take the talk in in the thoughtful spirit it was intended.</p> <hr>  <p><strong>Sponsor:</strong> Get home early, eat supper on time and coach your kids in soccer. Moving workloads to Azure just got easy with Azure NetApp Files. <a href="https://hnsl.mn/2MNZRB0">Sign up to Preview Azure NetApp Files</a>!</p><br/><hr/>© 2018 Scott Hanselman. All rights reserved. <br/></div><div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="http://feeds.hanselman.com/_/28/568851230/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Share on Google+" href="http://feeds.hanselman.com/_/30/568851230/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/googleplus20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Tweet This" href="http://feeds.hanselman.com/_/24/568851230/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/twitter20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="http://feeds.hanselman.com/_/19/568851230/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="http://feeds.hanselman.com/_/20/568851230/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
  368. </description>
  369.      <comments>https://www.hanselman.com/blog/CommentView.aspx?guid=6b44c29b-2504-43a7-adde-23a4ba032845</comments>
  370.      <category>Diabetes</category><content:encoded><![CDATA[<div><p>This blog post is an update to these two Diabetes Technology blog posts:</p> <ul> <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/ThePromisingStateOfDiabetesTechnologyIn2016.aspx">The Promising State of Diabetes Technology in 2016</a>  <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/TheSadStateOfDiabetesTechnologyIn2012.aspx">The Sad State of Diabetes Technology in 2012</a></li></ul> <p>You might also enjoy this video of the talk I gave at <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.webstock.org.nz/talks/solving-diabetes-open-source-artificial-pancreas/">WebStock 2018</a> on <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.webstock.org.nz/talks/solving-diabetes-open-source-artificial-pancreas/">Solving Diabetes with an Open Source Artificial Pancreas</a>*.</p> <p>First, let me tell you that insulin is too expensive in the US.</p> <blockquote> <p>Between 2002 and 2013, the <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://jamanetwork.com/journals/jama/fullarticle/2510902">price of insulin jumped</a>, with the typical cost for patients increasing from about $40 a vial to $130.</p></blockquote> <p><img title="Open Source Artificial Pancreas on iPhone" style="float: right; display: inline" alt="Open Source Artificial Pancreas on iPhone" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/d181bafac8b1_14937/phones_5a4afeef-5bb7-4d8d-87fd-acc902585a1d.png" width="371" align="right" height="733">For some of the newer insulins like the ones I use, I pay as much as $296 a bottle. I have a Health Savings Plan so this is often out of pocket until I hit the limit for the year. </p> <p>People in America are rationing insulin. This is <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://twitter.com/maykeila_brooke/status/1038247265217929216">demonstrable fact</a>. I've personally mailed extra insulin to folks in need. I've meet young people who lost their insurance at age 26 and have had to skip shots to save vials of insulin.</p> <p>This is a problem, but on the technology side there's some extremely promising work happening, and it's we have really hit our stride in the last ten years. </p> <p>I wrote the <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~copilotconsulting.com/mail-archives/pilot.1998/msg09007.html">first Glucose Management system for the PalmPilot in 1998 called GlucoPilot</a> and provided on the go in-depth analysis for the first time. The first thing that struck me was that the PalmPilot and the Blood Sugar Meter were the same size. Why did I need <em>two</em> devices with batteries, screens, buttons and a CPU? Why so many devices?  <p><strong>I've been told every year the a Diabetes Breakthrough is coming "in five years." It's been 25 years.</strong>  <p>In 2001 <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~www.thefeaturearchives.com/topic/Archive/One_Guy__an_Insulin_Pump__and_8_PDAs.html">I went on a trip across the country with my wife, an insulin pump and 8 PDAs</a> (personal digital assistants, the "iPhones" of the time) and tried to manage my diabetes using all the latest wireless technology...this was the <strong>latest stuff 17 years ago</strong>. I had just moved from injections to an insulin pump. Even now in 2018 Insulin Pumps are expensive, mostly proprietary, and super expensive. In fact, many folks use insulin pumps in the states use out of warranty pumps purchased on Craigslist.  <p>Fast forward to 2018 and I've been using an <strong>Open Source Artificial Pancreas for two years.</strong></p> <ul> <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://openaps.org/"><strong>OpenAPS</strong></a><strong> - Open Artificial Pancreas System. A platform for building a closed-loop with open tools. </strong> <ul> <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://androidaps.readthedocs.io/en/latest/"><strong>AndroidAPS</strong></a><strong> - A branch of OpenAPS running on Android</strong></li></ul> <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.loopdocs.org"><strong>Loop/LoopKit</strong></a><strong> - Open Source Artificial Pancreas running on the iPhone with a hardware bridge (RileyLink) to the pump. </strong> <ul> <li><strong>I run this pancreas, personally, and have for nearly 2 years.</strong></li></ul> <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.youtube.com/watch?v=eQGWrdgu_fE"><strong>Watch Dana Lewis (the originator of OpenAPS) talk about OpenAPS at OSCON</strong></a><strong>!</strong></li></ul> <p>The results speak for themselves. While I do have bad sugars sometimes, and I do struggle, if you look at my blood work my HA1c (the long term measurement of "how I'm doing" shows non-diabetic levels. To be clear - I'm fully and completely Type 1 diabetic, I produce zero insulin of my own. I take between 40 and 50 Units of insulin every day, and have for the last 25 years...but I will <strong>likely die of old age.</strong></p> <center> <blockquote class="twitter-tweet" data-lang="en"> <p lang="en" dir="ltr">Open Source Artificial Pancreas === Diabetes results <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://t.co/ZSsApTLRXq">pic.twitter.com/ZSsApTLRXq</a></p>— Scott Hanselman (@shanselman) <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://twitter.com/shanselman/status/1038996542571466752?ref_src=twsrc%5Etfw">September 10, 2018</a></blockquote></center> <p>This is significant. Why? Because historically diabetics die of diabetes. While we wait (or more accurately, <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://twitter.com/search?q=wearenotwaiting&amp;src=typd">#WeAreNotWaiting</a>) for a biological/medical solution to Type 1 diabetes, the DIY (Do It Yourself) community is just doing it ourselves. </p> <p>Building on open hardware, open software, and reverse-engineered protocols for proprietary hardware, the online diabetes community <em>literally has their choice of open source pancreases in 2018! </em>Who would have imagined it. You can choose your algorithms, your phone, your pump, your continuous glucose meter. </p> <blockquote> <p><strong>Today, in 2018, you can literally change the code and recompile a personal branch of your own pancreas.</strong></p></blockquote> <p>Watch my 2010 YouTube video "<a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.youtube.com/watch?v=jsxFbDIvQRw">I am Diabetic</a>" as I walk you through the medical hardware (pumps, needles, tubes, wires) in managing diabetes day to day. Then watch my 2018 talk on <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.webstock.org.nz/talks/solving-diabetes-open-source-artificial-pancreas/">Solving Diabetes with an Open Source Artificial Pancreas</a>*.</p> <p>I believe that every diabetic should be offered a pump, a continuous glucose meter, and trained on some kind of artificial pancreas. A cloud based reporting system has also been a joy. My wife and family can see my sugar in real time when I'm away. My wife has even called me overseas to wake me up when I was in a bad sugar situation. </p> <p><img title="Artificial Pancreas generations" alt="Artificial Pancreas generations" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/Its-far-too-early-to-call-an-Insulin-Pum_E18A/app_6_steps_621_47a5d186-917b-48d9-8234-a68a6f7eea03.jpg"></p> <p>As the closed-hardware and closed-software medical companies work towards their own artificial pancreases, the open source community feel those companies would better serve us by opening up their protocols, using standard <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.diabetestechnology.org/dtsec-standard-final.pdf">Bluetooth ISO profiles</a> and use <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.diabetestechnology.org/dtsec-protection-profile-final.pdf">security best practices</a>. </p> <p>Looking at the table above, the open source community is squarely in #4 and moving quickly into #5. But why did we have to do this ourselves? We got tired of waiting.</p> <p>All in all, through open software and hardware, I can tell you that my life is SO MUCH BETTER than it was when I was first diagnosed. I figure we'll have this all figured out in about five years, right? ;)</p> <p>THANK YOU!</p> <h3>MORE DIABETES READING</h3> <ul> <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/BridgingDexcomShareCGMReceiversAndNightscout.aspx">Bridging Dexcom Share CGM Receivers and Nightscout</a>  <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/HackingDiabetes.aspx">Hacking Diabetes</a>  <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/VisualizingYourRealtimeBloodSugarValuesANDAGitPromptOnWindowsPowerShellAndLinuxBash.aspx">Visualizing your real-time blood sugar values in Git</a><!--EndFragment-->  <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/DiabetesTechnologyDexcomG5CGMReviewSoMuchWastedPotential.aspx">Diabetes Technology: Dexcom G5 CGM Review</a>  <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/IntroducingWebTilesForMicrosoftBandMyDiabetesDataOnABand.aspx">Introducing Web Tiles for Microsoft Band - My diabetes data on a Band!</a>  <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/DiabeticsItsFunToSayBionicPancreasButHowAboutARealityCheck.aspx">Diabetics: It's fun to say Bionic Pancreas but how about a reality check</a>  <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/ItsWAYTooEarlyToCallThisInsulinPumpAnArtificialPancreas.aspx">It's WAY too early to call this Insulin Pump an Artificial Pancreas</a></li></ul> <p>* Yes there are some analogies, stretched metaphors, and oversimplifications in <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.webstock.org.nz/talks/solving-diabetes-open-source-artificial-pancreas/">this talk</a>. This talk is an introduction to the space to the normally-sugared. If you are a diabetes expert you might watch and say...eh...ya, I mean, it kind of works like that. Please take the talk in in the thoughtful spirit it was intended.</p> <hr>  <p><strong>Sponsor:</strong> Get home early, eat supper on time and coach your kids in soccer. Moving workloads to Azure just got easy with Azure NetApp Files. <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://hnsl.mn/2MNZRB0">Sign up to Preview Azure NetApp Files</a>!</p>
  371. <br/><hr/>© 2018 Scott Hanselman. All rights reserved.
  372. <br/></div><Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="http://feeds.hanselman.com/~/i/568851230/0/scotthanselman">
  373. <div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="http://feeds.hanselman.com/_/28/568851230/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Share on Google+" href="http://feeds.hanselman.com/_/30/568851230/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/googleplus20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Tweet This" href="http://feeds.hanselman.com/_/24/568851230/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/twitter20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="http://feeds.hanselman.com/_/19/568851230/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="http://feeds.hanselman.com/_/20/568851230/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
  374. </content:encoded></item>
  375. <item>
  376. <feedburner:origLink>https://www.hanselman.com/blog/AlwaysBeClosingPullRequests.aspx</feedburner:origLink>
  377.      <trackback:ping>https://www.hanselman.com/blog/Trackback.aspx?guid=5ab851fa-8822-4c81-9212-2ca3e1bab078</trackback:ping>
  378.      <pingback:server>https://www.hanselman.com/blog/pingback.aspx</pingback:server>
  379.      <pingback:target>https://www.hanselman.com/blog/PermaLink.aspx?guid=5ab851fa-8822-4c81-9212-2ca3e1bab078</pingback:target>
  380.      <dc:creator>Scott Hanselman</dc:creator>
  381.      <wfw:comment>https://www.hanselman.com/blog/CommentView.aspx?guid=5ab851fa-8822-4c81-9212-2ca3e1bab078</wfw:comment>
  382.      <wfw:commentRss>https://www.hanselman.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=5ab851fa-8822-4c81-9212-2ca3e1bab078</wfw:commentRss>
  383.      <slash:comments>10</slash:comments>
  384.      <title>Always Be Closing...Pull Requests</title>
  385.      <guid isPermaLink="false">https://www.hanselman.com/blog/PermaLink.aspx?guid=5ab851fa-8822-4c81-9212-2ca3e1bab078</guid>
  386.      <link>http://feeds.hanselman.com/~/568168640/0/scotthanselman~Always-Be-ClosingPull-Requests.aspx</link>
  387.      <pubDate>Wed, 05 Sep 2018 01:41:00 GMT</pubDate>
  388.      <description><![CDATA[<div><p><img title="Always be closing" style="float: right; margin: 0px 0px 0px 5px; display: inline" alt="Always be closing" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/1ee98a908026_D13B/abc_7f0655e2-220d-4e06-a1fc-7b3a8cfe6dfb.jpg" width="396" align="right" height="274">I was looking at a Well Known Open Source Project on GitHub today. It had like 978 Pull Requests. A "PR" means "hey here's some code I did for your project, you can PULL it from here and merge it into your code!"</p> <p>But these were Open Pull Requests. Pending. Limbo Pull Requests. Dating back to 2015.</p> <h3>Why do Pull Requests stay open?</h3> <p>Why do projects keep Pull Requests open? What's a reasonable amount of time? Here's a few thoughts.</p> <ul> <li>PR as Call to Action  <ul> <li>PRs are a shout. They are HERE IS SOME CODE and they create work for the maintainer. They are needy things and require review and merging, but even worse, sometimes manual merging. Plus for folks new to Git and Open Source, asking them to "rebase on top of latest" may be enough for them to just give up.</li></ul> <li>Fear of Closing  <ul> <li>If you close a PR without merging it, it's a rejection. It's a statement that this work isn't going to be used, and there's always a chance that the person who did the work will feel pretty bad about it. </li></ul> <li>Abandoned  <ul> <li>Sometimes the originator of the PR disappears. The PR is effectively abandoned. These should be closed after a time.</li></ul> <li>Opened so long they can't be merged  <ul> <li>The problem with PRs that are open for long is that they become impossible to merge. The cost of understanding whether they are still relevant plus resolving the merge conflicts might be higher than the value of the PR itself.</li></ul> <li>Incorrectly created  <ul> <li>A PR originator may intent to change a single word (misspelling) but their PR changes CRs to LFs or Tabs to Spaces, it's a hassle.</li></ul> <li>Formatting  <ul> <li>It's generally considered poor form to send a PR out of the blue where one just ran a linter or formatter. If the project wanted that done they'd ask for it.</li></ul> <li>Totally not aligned with Roadmap  <ul> <li>If a PR shows up without context or communication, it may not be aligned with the direction of the project.</li></ul> <li>Surprise PR  <ul> <li>Unfortunately some PRs show up out of the blue with major changes, file moves, or no context. If a PR wasn't asked for, or if a PR wasn't requested, or borne of an Issue, you'll likely have trouble pushing it through.</li></ul></li></ul> <p>Thanks to Jon and Immo for their thoughts on this (likely incomplete) list. <a href="https://blog.jessfraz.com/post/the-art-of-closing/">Jess Frazelle</a> has a great post on "<a href="https://blog.jessfraz.com/post/the-art-of-closing/">The Art of Closing</a>" that I just found, and it includes a glorious gif from <a href="https://www.imdb.com/title/tt0104348/">Glengarry Glen Ross</a> where <a href="https://www.youtube.com/watch?v=AO_t7GtXO6w">Always Be Closing</a> comes from (warning, clip has dated and offensive language).</p> <p><a href="https://blog.jessfraz.com/post/the-art-of-closing/">Jess suggests a few ways</a> to Always Be Closing. </p> <p>Two things that can help make your open source project successful AND stay tidy!</p> <ul> <li>including a CONTRIBUTING.md</li> <ul> <li>GitHub has some good guidance <a href="https://help.github.com/articles/setting-up-your-project-for-healthy-contributions/">https://help.github.com/articles/setting-up-your-project-for-healthy-contributions/</a> and most of the dotnet repos have some decent contribution guidelines.</li> <li>I LOVE <a href="https://github.com/foosel">Gina Häußge's</a> <a href="https://github.com/foosel/OctoPrint/blob/master/CONTRIBUTING.md">Contributing.md</a> on her open source project "<a href="https://www.octoprint.org">OctoPrint</a>."</li></ul> <li>using Pull Request templates that give clear guidance on how to submit a successful pull request.</li> <ul> <li><a href="https://help.github.com/articles/creating-a-pull-request-template-for-your-repository">https://help.github.com/articles/creating-a-pull-request-template-for-your-repository</a> </li></ul> <li>Use bots to test and build PRs, sign CLAs (Contributor License Agreements) and move the ball forward.</li></ul> <p>What do you think? Why do PRs stay open?</p> <p> <hr> </p> <p><strong>Sponsor:</strong> Get home early, eat supper on time and coach your kids in soccer. Moving workloads to Azure just got easy with Azure NetApp Files. <a href="https://hnsl.mn/2MNZRB0">Sign up to Preview Azure NetApp Files</a>!</p><br/><hr/>© 2018 Scott Hanselman. All rights reserved. <br/></div><div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="http://feeds.hanselman.com/_/28/568168640/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Share on Google+" href="http://feeds.hanselman.com/_/30/568168640/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/googleplus20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Tweet This" href="http://feeds.hanselman.com/_/24/568168640/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/twitter20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="http://feeds.hanselman.com/_/19/568168640/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="http://feeds.hanselman.com/_/20/568168640/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
  389. </description>
  390.      <comments>https://www.hanselman.com/blog/CommentView.aspx?guid=5ab851fa-8822-4c81-9212-2ca3e1bab078</comments>
  391.      <category>Open Source</category><content:encoded><![CDATA[<div><p><img title="Always be closing" style="float: right; margin: 0px 0px 0px 5px; display: inline" alt="Always be closing" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/1ee98a908026_D13B/abc_7f0655e2-220d-4e06-a1fc-7b3a8cfe6dfb.jpg" width="396" align="right" height="274">I was looking at a Well Known Open Source Project on GitHub today. It had like 978 Pull Requests. A "PR" means "hey here's some code I did for your project, you can PULL it from here and merge it into your code!"</p> <p>But these were Open Pull Requests. Pending. Limbo Pull Requests. Dating back to 2015.</p> <h3>Why do Pull Requests stay open?</h3> <p>Why do projects keep Pull Requests open? What's a reasonable amount of time? Here's a few thoughts.</p> <ul> <li>PR as Call to Action  <ul> <li>PRs are a shout. They are HERE IS SOME CODE and they create work for the maintainer. They are needy things and require review and merging, but even worse, sometimes manual merging. Plus for folks new to Git and Open Source, asking them to "rebase on top of latest" may be enough for them to just give up.</li></ul> <li>Fear of Closing  <ul> <li>If you close a PR without merging it, it's a rejection. It's a statement that this work isn't going to be used, and there's always a chance that the person who did the work will feel pretty bad about it. </li></ul> <li>Abandoned  <ul> <li>Sometimes the originator of the PR disappears. The PR is effectively abandoned. These should be closed after a time.</li></ul> <li>Opened so long they can't be merged  <ul> <li>The problem with PRs that are open for long is that they become impossible to merge. The cost of understanding whether they are still relevant plus resolving the merge conflicts might be higher than the value of the PR itself.</li></ul> <li>Incorrectly created  <ul> <li>A PR originator may intent to change a single word (misspelling) but their PR changes CRs to LFs or Tabs to Spaces, it's a hassle.</li></ul> <li>Formatting  <ul> <li>It's generally considered poor form to send a PR out of the blue where one just ran a linter or formatter. If the project wanted that done they'd ask for it.</li></ul> <li>Totally not aligned with Roadmap  <ul> <li>If a PR shows up without context or communication, it may not be aligned with the direction of the project.</li></ul> <li>Surprise PR  <ul> <li>Unfortunately some PRs show up out of the blue with major changes, file moves, or no context. If a PR wasn't asked for, or if a PR wasn't requested, or borne of an Issue, you'll likely have trouble pushing it through.</li></ul></li></ul> <p>Thanks to Jon and Immo for their thoughts on this (likely incomplete) list. <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://blog.jessfraz.com/post/the-art-of-closing/">Jess Frazelle</a> has a great post on "<a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://blog.jessfraz.com/post/the-art-of-closing/">The Art of Closing</a>" that I just found, and it includes a glorious gif from <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.imdb.com/title/tt0104348/">Glengarry Glen Ross</a> where <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.youtube.com/watch?v=AO_t7GtXO6w">Always Be Closing</a> comes from (warning, clip has dated and offensive language).</p> <p><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://blog.jessfraz.com/post/the-art-of-closing/">Jess suggests a few ways</a> to Always Be Closing. </p> <p>Two things that can help make your open source project successful AND stay tidy!</p> <ul> <li>including a CONTRIBUTING.md</li> <ul> <li>GitHub has some good guidance <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://help.github.com/articles/setting-up-your-project-for-healthy-contributions/">https://help.github.com/articles/setting-up-your-project-for-healthy-contributions/</a> and most of the dotnet repos have some decent contribution guidelines.</li> <li>I LOVE <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/foosel">Gina Häußge's</a> <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/foosel/OctoPrint/blob/master/CONTRIBUTING.md">Contributing.md</a> on her open source project "<a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.octoprint.org">OctoPrint</a>."</li></ul> <li>using Pull Request templates that give clear guidance on how to submit a successful pull request.</li> <ul> <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://help.github.com/articles/creating-a-pull-request-template-for-your-repository">https://help.github.com/articles/creating-a-pull-request-template-for-your-repository</a> </li></ul> <li>Use bots to test and build PRs, sign CLAs (Contributor License Agreements) and move the ball forward.</li></ul> <p>What do you think? Why do PRs stay open?</p> <p> <hr> </p> <p><strong>Sponsor:</strong> Get home early, eat supper on time and coach your kids in soccer. Moving workloads to Azure just got easy with Azure NetApp Files. <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://hnsl.mn/2MNZRB0">Sign up to Preview Azure NetApp Files</a>!</p>
  392. <br/><hr/>© 2018 Scott Hanselman. All rights reserved.
  393. <br/></div><Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="http://feeds.hanselman.com/~/i/568168640/0/scotthanselman">
  394. <div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="http://feeds.hanselman.com/_/28/568168640/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Share on Google+" href="http://feeds.hanselman.com/_/30/568168640/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/googleplus20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Tweet This" href="http://feeds.hanselman.com/_/24/568168640/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/twitter20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="http://feeds.hanselman.com/_/19/568168640/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="http://feeds.hanselman.com/_/20/568168640/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
  395. </content:encoded></item>
  396. <item>
  397. <feedburner:origLink>https://www.hanselman.com/blog/InterestingBugsMSB3246ResolvedFileHasABadImageNoMetadataOrIsOtherwiseInaccessibleImageIsTooSmall.aspx</feedburner:origLink>
  398.      <trackback:ping>https://www.hanselman.com/blog/Trackback.aspx?guid=03bf0caa-a028-4194-a289-f209801a110e</trackback:ping>
  399.      <pingback:server>https://www.hanselman.com/blog/pingback.aspx</pingback:server>
  400.      <pingback:target>https://www.hanselman.com/blog/PermaLink.aspx?guid=03bf0caa-a028-4194-a289-f209801a110e</pingback:target>
  401.      <dc:creator>Scott Hanselman</dc:creator>
  402.      <wfw:comment>https://www.hanselman.com/blog/CommentView.aspx?guid=03bf0caa-a028-4194-a289-f209801a110e</wfw:comment>
  403.      <wfw:commentRss>https://www.hanselman.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=03bf0caa-a028-4194-a289-f209801a110e</wfw:commentRss>
  404.      <slash:comments>7</slash:comments>
  405.      <title>Interesting bugs - MSB3246: Resolved file has a bad image, no metadata, or is otherwise inaccessible. Image is too small.</title>
  406.      <guid isPermaLink="false">https://www.hanselman.com/blog/PermaLink.aspx?guid=03bf0caa-a028-4194-a289-f209801a110e</guid>
  407.      <link>http://feeds.hanselman.com/~/567201328/0/scotthanselman~Interesting-bugs-MSB-Resolved-file-has-a-bad-image-no-metadata-or-is-otherwise-inaccessible-Image-is-too-small.aspx</link>
  408.      <pubDate>Thu, 30 Aug 2018 22:41:00 GMT</pubDate>
  409.      <description><![CDATA[<div><p>I got a very strange warning recently when building a .NET Core app with "dotnet build."</p><pre>MSB3246: Resolved file has a bad image, no metadata, or is otherwise inaccessible. <br>Image is too small.</pre>
  410. <p><font face="Calibri"><a href="https://flic.kr/p/4SpmL6"><img title="Interesting Bug used under CC https://flic.kr/p/4SpmL6" style="float: right; margin: 0px 0px 0px 5px; display: inline" alt="Interesting Bug used under CC https://flic.kr/p/4SpmL6" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/253a588a4a6a_A468/image_3.png" width="240" align="right" height="223"></a>Eek! It's clear, in that something is "too small" but what? A file I guess? Maybe it's the wrong size?</font></p>
  411. <p><font face="Calibri">The error code is MSB3246 which is nice and googleable/searchable but it was confusing because I couldn't figure our what file specifically. It just felt vague.</font></p>
  412. <p><font face="Calibri">BUT!</font></p>
  413. <p><font face="Calibri">I had recently been overclocking my machine (overly aggressively, gulp, about 40%) and had a very nasty hard reboot. As a result I had a few dozen files get orphaned - specifically the files were zero'ed out! Zero is small, right?</font></p>
  414. <p>Turns out you can pass parameters over to MSBuild from "dotnet build" and see what MSBuild is doing internally. For example, you could </p><pre>/fileLoggerParameters:verbosity=diagnostic</pre>
  415. <p>but that's long. So how about:</p><pre>dotnet build /flp:v=diag</pre>
  416. <p>Cool. What deep logging do I see now?</p><pre>Primary reference "deliberately.zero.bytes.dll". (TaskId:41)<br>13:36:52.397 1:7&gt;C:\Program Files\dotnet\sdk\2.1.400\Microsoft.Common.CurrentVersion.targets(2110,5): warning MSB3246: Resolved file has a bad image, no metadata, or is otherwise inaccessible. Image is too small. [S:\work\zero-byte-ref\zero-byte-ref.csproj]<br> Resolved file path is "S:\work\zero-byte-ref\deliberately.zero.bytes.dll". (TaskId:41)<br> Reference found at search path location "{RawFileName}". (TaskId:41)</pre>
  417. <p>Now with "verbose" turned on I can see that one of the references is zero'ed out/corrupted/bad. I reinstalled .NET Core in my case and doubled checked all the DLLs/Assemblies that I was bringing in - I also ran chkdsk /f - and I was back in business!</p>
  418. <p>I hope this helps someone who might stumble on error MSB3246 and wonder what's up.</p>
  419. <p>Even better, thanks to <a href="https://github.com/Microsoft/msbuild/issues/3650">Rainer Sigwald who filed a bug</a> against <a href="https://github.com/Microsoft/msbuild/issues/3650#issue-353899954">MSBuild to update the error message</a> to be more clear. In the future I'll be able to debug this <em>without </em>changing verbosity!</p>
  420. <hr>
  421. <p><strong>Sponsor: </strong>Preview the <a href="https://hnsl.mn/2wl11dc">latest JetBrains Rider</a> with its built-in spell checking, initial Blazor support, partial C# 7.3 support, enhanced debugger, C# Interactive, and a redesigned Solution Explorer.
  422. <br/><hr/>© 2018 Scott Hanselman. All rights reserved. <br/></div><div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="http://feeds.hanselman.com/_/28/567201328/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Share on Google+" href="http://feeds.hanselman.com/_/30/567201328/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/googleplus20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Tweet This" href="http://feeds.hanselman.com/_/24/567201328/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/twitter20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="http://feeds.hanselman.com/_/19/567201328/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="http://feeds.hanselman.com/_/20/567201328/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
  423. </description>
  424.      <comments>https://www.hanselman.com/blog/CommentView.aspx?guid=03bf0caa-a028-4194-a289-f209801a110e</comments>
  425.      <category>DotNetCore</category><content:encoded><![CDATA[<div><p>I got a very strange warning recently when building a .NET Core app with "dotnet build."</p><pre>MSB3246: Resolved file has a bad image, no metadata, or is otherwise inaccessible.
  426. <br>Image is too small.</pre>
  427. <p><font face="Calibri"><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://flic.kr/p/4SpmL6"><img title="Interesting Bug used under CC https://flic.kr/p/4SpmL6" style="float: right; margin: 0px 0px 0px 5px; display: inline" alt="Interesting Bug used under CC https://flic.kr/p/4SpmL6" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/253a588a4a6a_A468/image_3.png" width="240" align="right" height="223"></a>Eek! It's clear, in that something is "too small" but what? A file I guess? Maybe it's the wrong size?</font></p>
  428. <p><font face="Calibri">The error code is MSB3246 which is nice and googleable/searchable but it was confusing because I couldn't figure our what file specifically. It just felt vague.</font></p>
  429. <p><font face="Calibri">BUT!</font></p>
  430. <p><font face="Calibri">I had recently been overclocking my machine (overly aggressively, gulp, about 40%) and had a very nasty hard reboot. As a result I had a few dozen files get orphaned - specifically the files were zero'ed out! Zero is small, right?</font></p>
  431. <p>Turns out you can pass parameters over to MSBuild from "dotnet build" and see what MSBuild is doing internally. For example, you could </p><pre>/fileLoggerParameters:verbosity=diagnostic</pre>
  432. <p>but that's long. So how about:</p><pre>dotnet build /flp:v=diag</pre>
  433. <p>Cool. What deep logging do I see now?</p><pre>Primary reference "deliberately.zero.bytes.dll". (TaskId:41)
  434. <br>13:36:52.397 1:7&gt;C:\Program Files\dotnet\sdk\2.1.400\Microsoft.Common.CurrentVersion.targets(2110,5): warning MSB3246: Resolved file has a bad image, no metadata, or is otherwise inaccessible. Image is too small. [S:\work\zero-byte-ref\zero-byte-ref.csproj]
  435. <br> Resolved file path is "S:\work\zero-byte-ref\deliberately.zero.bytes.dll". (TaskId:41)
  436. <br> Reference found at search path location "{RawFileName}". (TaskId:41)</pre>
  437. <p>Now with "verbose" turned on I can see that one of the references is zero'ed out/corrupted/bad. I reinstalled .NET Core in my case and doubled checked all the DLLs/Assemblies that I was bringing in - I also ran chkdsk /f - and I was back in business!</p>
  438. <p>I hope this helps someone who might stumble on error MSB3246 and wonder what's up.</p>
  439. <p>Even better, thanks to <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/Microsoft/msbuild/issues/3650">Rainer Sigwald who filed a bug</a> against <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/Microsoft/msbuild/issues/3650#issue-353899954">MSBuild to update the error message</a> to be more clear. In the future I'll be able to debug this <em>without </em>changing verbosity!</p>
  440. <hr>
  441. <p><strong>Sponsor: </strong>Preview the <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://hnsl.mn/2wl11dc">latest JetBrains Rider</a> with its built-in spell checking, initial Blazor support, partial C# 7.3 support, enhanced debugger, C# Interactive, and a redesigned Solution Explorer.
  442.  
  443. <br/><hr/>© 2018 Scott Hanselman. All rights reserved.
  444. <br/></div><Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="http://feeds.hanselman.com/~/i/567201328/0/scotthanselman">
  445. <div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="http://feeds.hanselman.com/_/28/567201328/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Share on Google+" href="http://feeds.hanselman.com/_/30/567201328/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/googleplus20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Tweet This" href="http://feeds.hanselman.com/_/24/567201328/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/twitter20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="http://feeds.hanselman.com/_/19/567201328/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="http://feeds.hanselman.com/_/20/567201328/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
  446. </content:encoded></item>
  447. <item>
  448. <feedburner:origLink>https://www.hanselman.com/blog/ImprovementsOnASPNETCoreDeploymentsOnZeitsNowshAndMakingSmallContainerImages.aspx</feedburner:origLink>
  449.      <trackback:ping>https://www.hanselman.com/blog/Trackback.aspx?guid=379aa462-0140-458a-b16a-e81170897629</trackback:ping>
  450.      <pingback:server>https://www.hanselman.com/blog/pingback.aspx</pingback:server>
  451.      <pingback:target>https://www.hanselman.com/blog/PermaLink.aspx?guid=379aa462-0140-458a-b16a-e81170897629</pingback:target>
  452.      <dc:creator>Scott Hanselman</dc:creator>
  453.      <wfw:comment>https://www.hanselman.com/blog/CommentView.aspx?guid=379aa462-0140-458a-b16a-e81170897629</wfw:comment>
  454.      <wfw:commentRss>https://www.hanselman.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=379aa462-0140-458a-b16a-e81170897629</wfw:commentRss>
  455.      <slash:comments>1</slash:comments>
  456.      <title>Improvements on ASP.NET Core deployments on Zeit's now.sh and making small container images</title>
  457.      <guid isPermaLink="false">https://www.hanselman.com/blog/PermaLink.aspx?guid=379aa462-0140-458a-b16a-e81170897629</guid>
  458.      <link>http://feeds.hanselman.com/~/566712676/0/scotthanselman~Improvements-on-ASPNET-Core-deployments-on-Zeits-nowsh-and-making-small-container-images.aspx</link>
  459.      <pubDate>Wed, 29 Aug 2018 01:45:00 GMT</pubDate>
  460.      <description><![CDATA[<div><p>Back in <a href="https://www.hanselman.com/blog/ZEITNowDeploymentsOfOpenSourceASPNETCoreWebAppsWithDocker.aspx">March of 2017 I blogged about Zeit</a> and their cool deployment system "<a href="https://www.hanselman.com/blog/ZEITNowDeploymentsOfOpenSourceASPNETCoreWebAppsWithDocker.aspx">now</a>." Zeit will take any folder and deploy it to the web easily. Better yet if you have a Dockerfile in that folder as Zeit will just use that for the deployment.</p><figure><img title="image" style="display: inline" alt="image" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/Improvement-ASP.NET-Core-deployments-.sh_13E3E/image_3.png" width="999" height="510"></figure>  <p><a href="http://zeit.co">Zeit's free Open Source account</a> has a limit of 100 megs for the resulting image, and with the right Dockerfile started ASP.NET Core apps are less than 77 megs. You just need to be smart about a few things. Additionally, it's running in a somewhat constrained environment so ASP.NET's assumptions around FileWatchers can occasionally cause you to see errors like</p><pre>at System.IO.FileSystemWatcher.StartRaisingEvents()<br> Unhandled Exception: System.IO.IOException: <br>The configured user limit (8192) on the number of inotify instances has been reached.<br> at System.IO.FileSystemWatcher.StartRaisingEventsIfNotDisposed(</pre>
  461. <p>While this environment variable is set by default for the "FROM microsoft/dotnet:2.1-sdk" Dockerfile, it's not set at runtime. That's dependent on your environment.</p>
  462. <p>Here's my Dockerfile for a simple project called SuperZeit. Note that the project is structured with a SLN file, which I recommend.</p>
  463. <p>Let me call our a few things. </p>
  464. <ul>
  465. <li>First, we're doing a Multi-stage build here.
  466. <ul>
  467. <li>The SDK is large. You don't want to deploy the compiler to your runtime image! </li></ul>
  468. <li>Second, the first copy commands just copy the sln and the csproj.
  469. <ul>
  470. <li>You don't need the source code to do a dotnet restore! (Did you know that?)
  471. <li>Not deploying source means that your docker builds will be MUCH faster as Docker will cache the steps and only regenerate things that change. Docker will only run dotnet restore again if the solution or project files change. Not the source.</li></ul>
  472. <li>Third, we are using the aspnetcore-runtime image here. Not the dotnetcore one.
  473. <ul>
  474. <li>That means this image includes the binaries for .NET Core and ASP.NET Core. We don't need or want to include them again.
  475. <li>If you were doing a publish with a the -r switch, you'd be doing a <em>self-contained build/publish</em>. You'd end up copying TWO .NET Core runtimes into a container! That'll cost you another 50-60 megs and it's just wasteful.
  476. <li>If you want to learn more, go explore the very good examples on the .NET Docker Repro on GitHub <a title="https://github.com/dotnet/dotnet-docker/tree/master/samples" href="https://github.com/dotnet/dotnet-docker/tree/master/samples">https://github.com/dotnet/dotnet-docker/tree/master/samples</a>
  477. <li><strong>Optimizing Container Size</strong>
  478. <ul>
  479. <li><a href="https://github.com/dotnet/dotnet-docker/blob/master/samples/dotnetapp/README.md">.NET Core Alpine Docker Sample</a> - This <a href="https://github.com/dotnet/dotnet-docker/blob/master/samples/dotnetapp/Dockerfile.alpine-x64">sample</a> builds, tests, and runs an application using Alpine.
  480. <li><a href="https://github.com/dotnet/dotnet-docker/blob/master/samples/dotnetapp/dotnet-docker-selfcontained.md">.NET Core self-contained Sample</a> - This <a href="https://github.com/dotnet/dotnet-docker/blob/master/samples/dotnetapp/Dockerfile.debian-x64-selfcontained">sample</a> builds and runs an application as a self-contained application.</li></ul></li></ul>
  481. <li>Finally, since some container systems like Zeit have modest settings for inotify instances (to avoid abuse, plus most folks don't use them as often as .NET Core does) you'll want to set ENV DOTNET_USE_POLLING_FILE_WATCHER=true which I do in the runtime image.</li></ul>
  482. <p>So starting from this Dockerfile:</p>
  483. <ul>
  484. <ul>
  485. <h5></h5></ul></ul><pre>FROM microsoft/dotnet:2.1-sdk-alpine AS build<br>WORKDIR /app<br><br># copy csproj and restore as distinct layers<br>COPY *.sln .<br>COPY superzeit/*.csproj ./superzeit/<br>RUN dotnet restore<br><br># copy everything else and build app<br>COPY . .<br>WORKDIR /app/superzeit<br>RUN dotnet build<br> <br>FROM build AS publish<br>WORKDIR /app/superzeit<br>RUN dotnet publish -c Release -o out  <br><br>FROM microsoft/dotnet:2.1-aspnetcore-runtime-alpine AS runtime<br>ENV DOTNET_USE_POLLING_FILE_WATCHER=true<br>WORKDIR /app<br>COPY --from=publish /app/superzeit/out ./<br>ENTRYPOINT ["dotnet", "superzeit.dll"]</pre>
  486. <p>Remember the layers of the Docker images, as if they were a call stack:</p>
  487. <ul>
  488. <li>Your app's files
  489. <li>ASP.NET Core Runtime
  490. <li>.NET Core Runtime
  491. <li>.NET Core native dependencies (OS specific)
  492. <li>OS image (Alpine, Ubuntu, etc)</li></ul>
  493. <p>For my little app I end up with a 76.8 meg image. If want I can add the experimental <a href="https://www.hanselman.com/blog/ExperimentalReducingTheSizeOfNETCoreApplicationsWithMonosLinker.aspx">.NET IL Trimmer</a>. It won't make a difference with this app as it's already pretty simple but it could with a larger one.</p>
  494. <p>BUT! What if we changed the layering to this?</p>
  495. <ul>
  496. <li>Your app's files along with a self-contained copy of ASP.NET Core and .NET Core
  497. <li>.NET Core native dependencies (OS specific)
  498. <li>OS image (Alpine, Ubuntu, etc)<!--EndFragment--></li></ul>
  499. <p>Then we could do a self-Contained deployment and then trim the result! Richard Lander has a <a href="https://github.com/dotnet/dotnet-docker/blob/master/samples/dotnetapp/Dockerfile.alpine-x64-selfcontained">great dockerfile example</a>. </p>
  500. <p>See how he's doing the package addition with the dotnet CLI with "dotnet add package" and subsequent trim <em>within </em>the Dockerfile (as opposed to you adding it to your local development copy's csproj). </p><pre>FROM microsoft/dotnet:2.1-sdk-alpine AS build<br>WORKDIR /app<br><br># copy csproj and restore as distinct layers<br>COPY *.sln .<br>COPY nuget.config . <br>COPY superzeit/*.csproj ./superzeit/<br>RUN dotnet restore<br><br># copy everything else and build app<br>COPY . .<br>WORKDIR /app/superzeit<br>RUN dotnet build<br> <br>FROM build AS publish<br>WORKDIR /app/superzeit<br># add IL Linker package<br>RUN dotnet add package ILLink.Tasks -v 0.1.5-preview-1841731 -s https://dotnet.myget.org/F/dotnet-core/api/v3/index.json<br>RUN dotnet publish -c Release -o out -r linux-musl-x64 /p:ShowLinkerSizeComparison=true <br><br>FROM microsoft/dotnet:2.1-runtime-deps-alpine AS runtime<br>ENV DOTNET_USE_POLLING_FILE_WATCHER=true<br>WORKDIR /app<br>COPY --from=publish /app/superzeit/out ./<br>ENTRYPOINT ["dotnet", "superzeit.dll"]</pre>
  501. <p>Now at this point, I'd want to see how small the IL Linker made my ultimate project. The goal is to be less than 75 megs. However, I think <a href="https://github.com/mono/linker/issues/314">I've hit this bug</a> so I will have to head to bed and check on it in the morning. </p>
  502. <p>The project is at <a title="https://github.com/shanselman/superzeit" href="https://github.com/shanselman/superzeit">https://github.com/shanselman/superzeit</a> and you can just clone and "docker build" and see the bug. </p>
  503. <p>However, if you check the comments in the Docker file and just use the a "FROM microsoft/dotnet:2.1-aspnetcore-runtime-alpine AS runtime" it works fine. I just <em>think </em>I can get it even smaller than 75 megs.</p>
  504. <p>Talk so you soon, Dear Reader! (I'll update this post when I find out about that bug...or perhaps my bug!)</p>
  505. <p><strong>UPDATE1 : </strong>The <a href="https://github.com/mono/linker/issues/314#issuecomment-417030818">linker works with this Workaround</a>. I need to set the property <code>CrossGenDuringPublish</code> to <code>false</code> in the project file. </p>
  506. <ul>
  507. <li>A standard ASP.NET Core "hello world" image ends up at around <strong>75 megs</strong> on Zeit.
  508. <li>A self-contained deployment with the runtime-deps images is about <strong>52 megs</strong>.
  509. <li>If you add trimming to that self-contained Alpine image the result is <strong>just 35 megs</strong>!</li></ul>
  510. <p><img title="35 meg ASP.NET Core image" style="display: inline" alt="35 meg ASP.NET Core image" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/Improvement-ASP.NET-Core-deployments-.sh_13E3E/image_5.png" width="640" height="170"></p>
  511. <p>I'm making some headway but <a href="https://github.com/aspnet/Home/issues/3475">still hitting an inotify issue with FileSystemWatchers</a>. More soon!</p>
  512. <p><strong>UPDATE2: </strong>After <a href="https://github.com/zeit/now-examples/pull/61">some bugs found and some hard work by our friends at Zeit</a> it looks like the inotify issue in the sentence above has been fixed. Looks like it was a misconfiguration - which is great! I was worried there was a larger architectural issue but there isn't.</p>
  513. <p>
  514. <hr>
  515. </p>
  516. <p><strong>Sponsor: </strong>Preview the <a href="https://hnsl.mn/2wl11dc">latest JetBrains Rider</a> with its built-in spell checking, initial Blazor support, partial C# 7.3 support, enhanced debugger, C# Interactive, and a redesigned Solution Explorer.</p><br/><hr/>© 2018 Scott Hanselman. All rights reserved. <br/></div><div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="http://feeds.hanselman.com/_/28/566712676/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Share on Google+" href="http://feeds.hanselman.com/_/30/566712676/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/googleplus20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Tweet This" href="http://feeds.hanselman.com/_/24/566712676/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/twitter20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="http://feeds.hanselman.com/_/19/566712676/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="http://feeds.hanselman.com/_/20/566712676/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
  517. </description>
  518.      <comments>https://www.hanselman.com/blog/CommentView.aspx?guid=379aa462-0140-458a-b16a-e81170897629</comments>
  519.      <category>ASP.NET</category>
  520.      <category>DotNetCore</category>
  521.      <category>Open Source</category><content:encoded><![CDATA[<div><p>Back in <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/ZEITNowDeploymentsOfOpenSourceASPNETCoreWebAppsWithDocker.aspx">March of 2017 I blogged about Zeit</a> and their cool deployment system "<a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/ZEITNowDeploymentsOfOpenSourceASPNETCoreWebAppsWithDocker.aspx">now</a>." Zeit will take any folder and deploy it to the web easily. Better yet if you have a Dockerfile in that folder as Zeit will just use that for the deployment.</p><figure><img title="image" style="display: inline" alt="image" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/Improvement-ASP.NET-Core-deployments-.sh_13E3E/image_3.png" width="999" height="510"></figure>  <p><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~zeit.co">Zeit's free Open Source account</a> has a limit of 100 megs for the resulting image, and with the right Dockerfile started ASP.NET Core apps are less than 77 megs. You just need to be smart about a few things. Additionally, it's running in a somewhat constrained environment so ASP.NET's assumptions around FileWatchers can occasionally cause you to see errors like</p><pre>at System.IO.FileSystemWatcher.StartRaisingEvents()
  522. <br> Unhandled Exception: System.IO.IOException:
  523. <br>The configured user limit (8192) on the number of inotify instances has been reached.
  524. <br> at System.IO.FileSystemWatcher.StartRaisingEventsIfNotDisposed(</pre>
  525. <p>While this environment variable is set by default for the "FROM microsoft/dotnet:2.1-sdk" Dockerfile, it's not set at runtime. That's dependent on your environment.</p>
  526. <p>Here's my Dockerfile for a simple project called SuperZeit. Note that the project is structured with a SLN file, which I recommend.</p>
  527. <p>Let me call our a few things. </p>
  528. <ul>
  529. <li>First, we're doing a Multi-stage build here.
  530. <ul>
  531. <li>The SDK is large. You don't want to deploy the compiler to your runtime image! </li></ul>
  532. <li>Second, the first copy commands just copy the sln and the csproj.
  533. <ul>
  534. <li>You don't need the source code to do a dotnet restore! (Did you know that?)
  535. <li>Not deploying source means that your docker builds will be MUCH faster as Docker will cache the steps and only regenerate things that change. Docker will only run dotnet restore again if the solution or project files change. Not the source.</li></ul>
  536. <li>Third, we are using the aspnetcore-runtime image here. Not the dotnetcore one.
  537. <ul>
  538. <li>That means this image includes the binaries for .NET Core and ASP.NET Core. We don't need or want to include them again.
  539. <li>If you were doing a publish with a the -r switch, you'd be doing a <em>self-contained build/publish</em>. You'd end up copying TWO .NET Core runtimes into a container! That'll cost you another 50-60 megs and it's just wasteful.
  540. <li>If you want to learn more, go explore the very good examples on the .NET Docker Repro on GitHub <a title="https://github.com/dotnet/dotnet-docker/tree/master/samples" href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/dotnet/dotnet-docker/tree/master/samples">https://github.com/dotnet/dotnet-docker/tree/master/samples</a>
  541. <li><strong>Optimizing Container Size</strong>
  542. <ul>
  543. <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/dotnet/dotnet-docker/blob/master/samples/dotnetapp/README.md">.NET Core Alpine Docker Sample</a> - This <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/dotnet/dotnet-docker/blob/master/samples/dotnetapp/Dockerfile.alpine-x64">sample</a> builds, tests, and runs an application using Alpine.
  544. <li><a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/dotnet/dotnet-docker/blob/master/samples/dotnetapp/dotnet-docker-selfcontained.md">.NET Core self-contained Sample</a> - This <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/dotnet/dotnet-docker/blob/master/samples/dotnetapp/Dockerfile.debian-x64-selfcontained">sample</a> builds and runs an application as a self-contained application.</li></ul></li></ul>
  545. <li>Finally, since some container systems like Zeit have modest settings for inotify instances (to avoid abuse, plus most folks don't use them as often as .NET Core does) you'll want to set ENV DOTNET_USE_POLLING_FILE_WATCHER=true which I do in the runtime image.</li></ul>
  546. <p>So starting from this Dockerfile:</p>
  547. <ul>
  548. <ul>
  549. <h5></h5></ul></ul><pre>FROM microsoft/dotnet:2.1-sdk-alpine AS build
  550. <br>WORKDIR /app
  551. <br>
  552. <br># copy csproj and restore as distinct layers
  553. <br>COPY *.sln .
  554. <br>COPY superzeit/*.csproj ./superzeit/
  555. <br>RUN dotnet restore
  556. <br>
  557. <br># copy everything else and build app
  558. <br>COPY . .
  559. <br>WORKDIR /app/superzeit
  560. <br>RUN dotnet build
  561. <br>
  562. <br>FROM build AS publish
  563. <br>WORKDIR /app/superzeit
  564. <br>RUN dotnet publish -c Release -o out  
  565. <br>
  566. <br>FROM microsoft/dotnet:2.1-aspnetcore-runtime-alpine AS runtime
  567. <br>ENV DOTNET_USE_POLLING_FILE_WATCHER=true
  568. <br>WORKDIR /app
  569. <br>COPY --from=publish /app/superzeit/out ./
  570. <br>ENTRYPOINT ["dotnet", "superzeit.dll"]</pre>
  571. <p>Remember the layers of the Docker images, as if they were a call stack:</p>
  572. <ul>
  573. <li>Your app's files
  574. <li>ASP.NET Core Runtime
  575. <li>.NET Core Runtime
  576. <li>.NET Core native dependencies (OS specific)
  577. <li>OS image (Alpine, Ubuntu, etc)</li></ul>
  578. <p>For my little app I end up with a 76.8 meg image. If want I can add the experimental <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://www.hanselman.com/blog/ExperimentalReducingTheSizeOfNETCoreApplicationsWithMonosLinker.aspx">.NET IL Trimmer</a>. It won't make a difference with this app as it's already pretty simple but it could with a larger one.</p>
  579. <p>BUT! What if we changed the layering to this?</p>
  580. <ul>
  581. <li>Your app's files along with a self-contained copy of ASP.NET Core and .NET Core
  582. <li>.NET Core native dependencies (OS specific)
  583. <li>OS image (Alpine, Ubuntu, etc)<!--EndFragment--></li></ul>
  584. <p>Then we could do a self-Contained deployment and then trim the result! Richard Lander has a <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/dotnet/dotnet-docker/blob/master/samples/dotnetapp/Dockerfile.alpine-x64-selfcontained">great dockerfile example</a>. </p>
  585. <p>See how he's doing the package addition with the dotnet CLI with "dotnet add package" and subsequent trim <em>within </em>the Dockerfile (as opposed to you adding it to your local development copy's csproj). </p><pre>FROM microsoft/dotnet:2.1-sdk-alpine AS build
  586. <br>WORKDIR /app
  587. <br>
  588. <br># copy csproj and restore as distinct layers
  589. <br>COPY *.sln .
  590. <br>COPY nuget.config .
  591. <br>COPY superzeit/*.csproj ./superzeit/
  592. <br>RUN dotnet restore
  593. <br>
  594. <br># copy everything else and build app
  595. <br>COPY . .
  596. <br>WORKDIR /app/superzeit
  597. <br>RUN dotnet build
  598. <br>
  599. <br>FROM build AS publish
  600. <br>WORKDIR /app/superzeit
  601. <br># add IL Linker package
  602. <br>RUN dotnet add package ILLink.Tasks -v 0.1.5-preview-1841731 -s https://dotnet.myget.org/F/dotnet-core/api/v3/index.json
  603. <br>RUN dotnet publish -c Release -o out -r linux-musl-x64 /p:ShowLinkerSizeComparison=true
  604. <br>
  605. <br>FROM microsoft/dotnet:2.1-runtime-deps-alpine AS runtime
  606. <br>ENV DOTNET_USE_POLLING_FILE_WATCHER=true
  607. <br>WORKDIR /app
  608. <br>COPY --from=publish /app/superzeit/out ./
  609. <br>ENTRYPOINT ["dotnet", "superzeit.dll"]</pre>
  610. <p>Now at this point, I'd want to see how small the IL Linker made my ultimate project. The goal is to be less than 75 megs. However, I think <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/mono/linker/issues/314">I've hit this bug</a> so I will have to head to bed and check on it in the morning. </p>
  611. <p>The project is at <a title="https://github.com/shanselman/superzeit" href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/shanselman/superzeit">https://github.com/shanselman/superzeit</a> and you can just clone and "docker build" and see the bug. </p>
  612. <p>However, if you check the comments in the Docker file and just use the a "FROM microsoft/dotnet:2.1-aspnetcore-runtime-alpine AS runtime" it works fine. I just <em>think </em>I can get it even smaller than 75 megs.</p>
  613. <p>Talk so you soon, Dear Reader! (I'll update this post when I find out about that bug...or perhaps my bug!)</p>
  614. <p><strong>UPDATE1 : </strong>The <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/mono/linker/issues/314#issuecomment-417030818">linker works with this Workaround</a>. I need to set the property <code>CrossGenDuringPublish</code> to <code>false</code> in the project file. </p>
  615. <ul>
  616. <li>A standard ASP.NET Core "hello world" image ends up at around <strong>75 megs</strong> on Zeit.
  617. <li>A self-contained deployment with the runtime-deps images is about <strong>52 megs</strong>.
  618. <li>If you add trimming to that self-contained Alpine image the result is <strong>just 35 megs</strong>!</li></ul>
  619. <p><img title="35 meg ASP.NET Core image" style="display: inline" alt="35 meg ASP.NET Core image" src="https://www.hanselman.com/blog/content/binary/Windows-Live-Writer/Improvement-ASP.NET-Core-deployments-.sh_13E3E/image_5.png" width="640" height="170"></p>
  620. <p>I'm making some headway but <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/aspnet/Home/issues/3475">still hitting an inotify issue with FileSystemWatchers</a>. More soon!</p>
  621. <p><strong>UPDATE2: </strong>After <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://github.com/zeit/now-examples/pull/61">some bugs found and some hard work by our friends at Zeit</a> it looks like the inotify issue in the sentence above has been fixed. Looks like it was a misconfiguration - which is great! I was worried there was a larger architectural issue but there isn't.</p>
  622. <p>
  623. <hr>
  624. </p>
  625. <p><strong>Sponsor: </strong>Preview the <a href="http://feeds.hanselman.com/~/t/0/0/scotthanselman/~https://hnsl.mn/2wl11dc">latest JetBrains Rider</a> with its built-in spell checking, initial Blazor support, partial C# 7.3 support, enhanced debugger, C# Interactive, and a redesigned Solution Explorer.</p>
  626. <br/><hr/>© 2018 Scott Hanselman. All rights reserved.
  627. <br/></div><Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="http://feeds.hanselman.com/~/i/566712676/0/scotthanselman">
  628. <div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="http://feeds.hanselman.com/_/28/566712676/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Share on Google+" href="http://feeds.hanselman.com/_/30/566712676/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/googleplus20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Tweet This" href="http://feeds.hanselman.com/_/24/566712676/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/twitter20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="http://feeds.hanselman.com/_/19/566712676/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="http://feeds.hanselman.com/_/20/566712676/scotthanselman"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
  629. </content:encoded></item>
  630. </channel></rss>
  631.  
  632.  

If you would like to create a banner that links to this page (i.e. this validation result), do the following:

  1. Download the "valid RSS" banner.

  2. Upload the image to your own server. (This step is important. Please do not link directly to the image on this server.)

  3. Add this HTML to your page (change the image src attribute if necessary):

If you would like to create a text link instead, here is the URL you can use:

http://www.feedvalidator.org/check.cgi?url=http%3A//www.hanselman.com/blog/SyndicationService.asmx/GetAtom

Copyright © 2002-9 Sam Ruby, Mark Pilgrim, Joseph Walton, and Phil Ringnalda