Scott Hanselman

Lynx is dead - Long live Browsh for text-based internet browsing

July 13, '18 Comments [2] Posted in Docker | Open Source
Sponsored By

The standard for browsing the web over a text-=based terminal is Lynx, right? It's the legendary text web browser that you can read about at https://lynx.invisible-island.net/ or, even better, run right now with

docker run --rm -it nbrown/lynx lynx http://hanselman.com/

Awesome, right? But it's text. Lynx runs alt-text rather than images, and doesn't really take advantage of modern browser capabilities OR modern terminal capabilities.

Enter Browsh! https://www.brow.sh/

Browsh is a fully-modern text-based browser. It renders anything that a modern browser can; HTML5, CSS3, JS, video and even WebGL. Its main purpose is to be run on a remote server and accessed via SSH/Mosh

Imagine running your browser on a remote machine connected to full power while ssh'ing into your hosted browsh instance. I don't know about you, but my laptop is currently using 2 gigs of RAM for Chrome and it's basically just all fans. I might be able to get 12 hours of battery life if I hung out in tmux and used browsh! Not to mention the bandwidth savings. If I'm tethered or overseas on a 3G network, I can still get a great browsing experience and just barely sip data.

Browsing my blog with Browsh

You can even open new tabs! Check out the keybindings! You gotta try it. Works great on Windows 10 with the new console. Just run this one Docker command:

docker run -it --rm browsh/browsh

If you think this idea is silly, that's OK. I think it's brilliant and creative and exactly the kind of clever idea the internet needs. This solves an interesting browser in an interesting way...in fact it returns us back to the "dumb terminal" days, doesn't it?

There was a time when I my low-power machine waited for text from a refrigerator-sized machine. The fridge did the work and my terminal did the least.

Today my high-powered machine waits for text from another high-powered machine and then struggles to composite it all as 7 megs of JavaScript downloads from TheVerge.com. But I'm not bitter. ;)

Check out my podcast site on Browsh. Love it.

Tiny pixelated heads made with ASCII

If you agree that Browsh is amazing and special, consider donating! It's currently maintained by just one person and they just want $1000 a month on their Patreon to work on Browsh all the time! Go tell Tom on Twitter that you think is special, then give him some coins. What an exciting and artful project! I hope it continues!


Sponsor: Scale your Python for big data & big science with Intel® Distribution for Python. Near-native code speed. Use with NumPy, SciPy & scikit-learn. Get it Today!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

NuKeeper for automated NuGet Package Reference Updates on Build Servers

July 10, '18 Comments [10] Posted in DotNetCore | NuGet | Open Source
Sponsored By

Last week I looked at "dotnet outdated," a super useful .NET Core Global Tool for keeping a project's NuGet packages up to date. Since then I've discovered there's a whole BUNCH of great projects solving different aspects of the "minor version problem." I love this answer "Why?" from the NuKeeper (inspired by Greenkeeper) project with emphasis mine. NuKeeper will check for updates AND try to update your references for you! Why not automate the tedious!

NuGet package updates are a form of change that should be deployed, and we likewise want to change the cycle from "NuGet package updates are infrequent and contain lots of package changes, therefore NuGet package updates are hard and dangerous..." to "NuGet package updates are frequent and contain small changes, therefore NuGet package updates are easy and routine...".

Certainly no one is advocating updating the major versions of your dependent NuGet packages, but small compatible bug fixes come often and are often missed. Including a tool to discover - and optionally apply - these changes in a CI/CD (Continuous Integration/Continuous Deployment) pipeline can be a great timesaver.

Why do we deploy code changes frequently but seldom update NuGet packages?

Good question!

NuKeeper

NuKeeper is a .NET tool as well that you can install safely with:

dotnet tool install --global NuKeeper

Here it is running on my regularly updated podcast website that is running ASP.NET Core 2.1:

NuKeeper says I have 3 packages to update

Looks like three of my packages are out of date. NuKeeper shows what version I have and what I could update to, as well as how long an update has been available.

You can also restrict your updates by policy, so "age=3w" for packages over 3 weeks old (so you don't get overly fresh updates) or "change=minor" or "change=patch" if you trust your upstream packages to not break things in patch releases, etc.

NuKeeper is picking up steam and while (as of the time of this writing) its command line parameter style is a little unconventional, Anthony Steele and the team is very open to feedback with many improvements already in progress as this project matures!

The update functionality is somewhat experimental and currently does 1 update per local run, but I'm really enjoying the direction NuKeeper is going!

Automatic NuGet Updates via Pull Request

NuKeeper has a somewhat unique and clever feature called Repository Mode in that it can automatically issue a Pull Request against your repository with the changes needed to update your NuGet references. Check out this example PullRequest!

Anthony - the lead developer - points out that ideally you'd set up NuKeeper to send PRs for you. Automatic PRs are NuKeepers primary goal and use case!

The NuKeeperBot has automatically issued a PR with a list of packages to update

Again, it's early days, but between NuKeeper and "dotnet outdated," I'm feeling more in control of my package references than ever before! What are YOU using?


Sponsor: Scale your Python for big data & big science with Intel® Distribution for Python. Near-native code speed. Use with NumPy, SciPy & scikit-learn. Get it Today!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

dotnet outdated helps you keep your projects up to date

July 6, '18 Comments [6] Posted in DotNetCore | Open Source
Sponsored By

I've moved my podcast site over to ASP.NET Core 2.1 over the last few months. You might want to follow the saga by checking out some of the recent blog posts.

That's just a few of the posts. Be sure to check out the last several months' posts in the calendar view. Anyway, I've been trying lots of new open source tools and libraries like coverlet for .NET Core Code Coverage, and frankly, keeping my project files and dependencies up to date has sucked.

Npm has "npm outdated" and paket has "paket outdated," why doesn't dotnet Core have this also? Certainly at a macro level there's more things to consider as NuGet would need to find the outdated packages for UWP, C++, and a lot of other project types as well. However if we just focus on .NET Core as an initial/primary use case, Jerrie Pelser has "dotnet outdated" for us and it's fantastic!

Once you've got the .NET Core 2.1 SDK or newer, just install the tool globally with one line:

dotnet tool install --global dotnet-outdated

At this point I'll run "dotnet outdated" on my podcast website. While that's running, let me just point you to https://github.com/jerriep/dotnet-outdated as a lovely example of how to release a tool (no matter how big or small) on GitHub.

  • It has an AppVeyor CI link along with a badge showing you that it's passing its build and test suite. Nice.
  • It includes both a NuGet link to the released package AND a myGet link and badge to the dailies.
  • It's got clear installation and clear usage details.
  • Bonus points of screenshots. While not accessible to all, I admit personally that I'm more likely to feel that a project is well-maintained if there are clear screenshots that tell me "what am I gonna get with this tool?"

Here's the initial output on my Site and Tests.

dotnet outdated

After updating the patch versions, here's the output, this time as text. For some reason it's not seeing Coverlet's NuGet so I'm getting a "Cannot resolve latest version" error but I haven't debugged that yet.

» hanselminutes.core.tests
  [.NETCoreApp,Version=v2.1]
  Microsoft.AspNetCore.Mvc.Testing 2.1.1
  Microsoft.NET.Test.Sdk 15.7.2
  Selenium.Support 3.13.1
  Selenium.WebDriver 3.13.1
  Xunit.SkippableFact 1.3.6
  coverlet.msbuild 2.0.1 Cannot resolve latest version
  xunit 2.3.1
  xunit.runner.visualstudio 2.3.1

» hanselminutes.core
  [.NETCoreApp,Version=v2.1]
  BuildBundlerMinifier 2.8.391
  LazyCache 2.0.0-beta03
  LazyCache.AspNetCore 2.0.0-beta03
  Markdig 0.15.0
  Microsoft.ApplicationInsights.AspNetCore 2.4.0-beta2
  Microsoft.AspNetCore.App 2.1.1
  Microsoft.Extensions.Http.Polly 2.1.1
  Microsoft.NET.Test.Sdk 15.7.2

As with all projects and references, while things aren't *supposed* to break when you update a Major.Minor.Patch/Revision.build...things sometimes do. You should check your references and their associated websites and release notes to confirm that you know what's changed and you know what changes you're bringing in.

Shayne blogged about dotnet out-dated and points out the -vl (version lock) options that allows you to locking on Major or Minor versions. No need to take things you aren't ready to take.

All in all, a super useful tool that you should install TODAY.

dotnet tool install --global dotnet-outdated

The source is up at https://github.com/jerriep/dotnet-outdated if you want to leave issues or get involved.


Sponsor: Check out dotMemory Unit, a free unit testing framework for fighting all kinds of memory issues in your code. Extend your unit testing with the functionality of a memory profiler!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

The whole of WordPress compiled to .NET Core and a NuGet Package with PeachPie

July 3, '18 Comments [17] Posted in DotNetCore
Sponsored By

Compiling WordPress to .NET CoreWhy? Because it's awesome. Sometimes a project comes along that is impossibly ambitious and it works. I've blogged a little about Peachpie, the open source PHP compiler that runs PHP under .NET Core. It's a project hosted at https://www.peachpie.io.

But...why? Here's why:

  1. Performance: compiled code is fast and also optimized by the .NET Just-in-Time Compiler for your actual system. Additionally, the .NET performance profiler may be used to resolve bottlenecks.
  2. C# Extensibility: plugin functionality can be implemented in a separate C# project and/or PHP plugins may use .NET libraries.
  3. Sourceless distribution: after the compilation, most of the source files are not needed.
  4. Power of .NET: Peachpie allows the compiled WordPress clone to run in a .NET JIT'ted, secure and manageable environment, updated through windows update.
  5. No need to install PHP: Peachpie is a modern compiler platform and runtime distributed as a dependency to your .NET project. It is downloaded automatically on demand as a NuGet package or it can be even deployed standalone together with the compiled application as its library dependency.

A year ago you could very happily run Wordpress (a very NON-trivial PHP application, to be clear) under .NET Core using Peachpie. You would compile your PHP into an assembly and then do something like this in your Startup.cs:

public void Configure(IApplicationBuilder app)
{
    app.UseSession();

    app.UsePhp(new PhpRequestOptions(scriptAssemblyName: "peachweb"));
    app.UseDefaultFiles();
    app.UseStaticFiles();
}

And that's awesome. However, I noticed something on their GitHub recently, specifically under https://github.com/iolevel/wpdotnet-sdk. It says:

The solution compiles all of WordPress into a .NET assembly and additionally provides C# wrappers for utilization of compiled sources.

Whoa. Drink that in. The project consists of several parts:

  • wordpress contains sources of WordPress that are compiled into a single .NET Core assembly (wordpress.dll). Together with its content files it is packed into a NuGet package PeachPied.WordPress. The project additionally contains the "must-use" plugin peachpie-api.php which exposes the WordPress API to .NET.
  • PeachPied.WordPress.Sdk defines abstraction layer providing .NET interfaces over PHP WordPress instance. The interface is implemented and provided by peachpie-api.php.
  • PeachPied.WordPress.AspNetCore is an ASP.NET Core request handler that configures the ASP.NET pipeline to pass requests to compiled WordPress scripts. The configuration includes response caching, short URL mapping, various .NET enhancements and the settings of WordPress database.
  • app project is the executable demo ASP.NET Core web server making use of compiled WordPress.

They compiled the whole of WordPress into a NuGet Package.

YES.

  • The compiled website runs on .NET Core
  • You're using ASP.NET Core request handling and you can extend WordPress with C# plugins and themes

Seriously. Go get the .NET Core SDK version 2.1.301 over at https://dot.net and clone their repository locally from https://github.com/iolevel/wpdotnet-sdk.

Make sure you have a copy of mySQL running. I get one started FAST with Docker using this command:

docker run --name=mysql1 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=wordpress mysql --default-authentication-plugin=mysql_native_password

Then just "dotnet build" at the root of the project, then go into the app folder and "dotnet run." It will show up on localhost:5004.

NOTE: I needed to include the default authentication method to prevent the generic Wordpress "Cannot establish database connection." I also added the MYSQL_DATABASE environment variable so I could avoid logging initially using the mysql client and creating the database manually with "CREATE DATABASE wordpress."

Look at that. I have my mySQL in one terminal listening on 3306, and ASP.NET Core 2.1 running on port 5004 hosting freaking WordPress compiled into a single NuGet package.

Wordpress under .NET Core

Here's my bin folder:

WordPress as a single DLL

There's no PHP files which is a nice security bonus - not only are you running from the one assembly but there's no text files for any rogue plugins to modify or corrupt.

Here's the ASP.NET Core 2.1 app that hosts it, in full:

using System.IO;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using PeachPied.WordPress.AspNetCore;

namespace peachserver
{
    class Program
    {
        static void Main(string[] args)
        {
            // make sure cwd is not app\ but its parent:
            if (Path.GetFileName(Directory.GetCurrentDirectory()) == "app")
            {
                Directory.SetCurrentDirectory(Path.GetDirectoryName(Directory.GetCurrentDirectory()));
            }

            //
            var host = WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .UseUrls("http://*:5004/")
                .Build();

            host.Run();
        }
    }

    class Startup
    {
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IConfiguration configuration)
        {
            // settings:
            var wpconfig = new WordPressConfig();
            configuration
                .GetSection("WordPress")
                .Bind(wpconfig);

            //
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseWordPress(wpconfig);

            app.UseDefaultFiles();
        }
    }
}

I think the app.UseWordPress() is such a nice touch. ;)

I often get emails from .NET developers asking what blog engine they should consider. Today, I think you should look closely at Peachpie and strongly consider running WordPress under .NET Core. It's a wonderful open source project that brings two fantastic ecosystems together! I'm looking forward to exploring this project more and I'd encourage you to check it out and get involved with Peachpie.


Sponsor: Check out dotMemory Unit, a free unit testing framework for fighting all kinds of memory issues in your code. Extend your unit testing with the functionality of a memory profiler!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Detecting that a .NET Core app is running in a Docker Container and SkippableFacts in XUnit

June 29, '18 Comments [5] Posted in Docker | DotNetCore | Open Source
Sponsored By

Container Ship by NOAA used under CCI have moved my podcast site over to ASP.NET Core 2.1 and I've got it running in a Docker container. Take a moment a check out some of the blog posts, as I've been blogging as I've been learning.

I've added Unit Tests as well as Selenium Tests that are also run with the XUnit Unit Test Runner. However, I don't want those Selenium Tests that automate Google Chrome to run within the context of Docker.

I tried to add an Environment Variable within my Dockerfile like this:

ENV INDOCKER=1

I figured I'd check for that variable and conditionally skip tests. Simple, right? Well, I decided to actually READ the Dockerfiles that my ASP.NET Core 2.1 app uses. Remember, Dockerfiles (and the resulting images) are layered, and with all things .NET, are Open Source. 

Looking at my own layers and exploring the source on Github, I see I'm using:

Nice, so I don't need to set anything to know I'm running .NET in a Container! I wouldn't have known any of this if I hadn't taken 15 minutes and exploring/asserted/confirmed my stack. Just because I'm running Docker containers doesn't mean it's not useful to take the time to KNOW what I'm running! Assert your assumptions and all that, right?

I added a little helper in my Tests:

private bool InDocker { get { return Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true";} }

Since I'm using XUnit, I decided to bring in the very useful helper Xunit.SkippableFact!

For example:

[SkippableFact]
public void LoadTheMainPageAndCheckTitle()
{
    Skip.If(InDocker, "We are in Docker, y'all!");
    Browser.Navigate().GoToUrl(Server.RootUri);
    Assert.StartsWith("Hanselminutes Technology Podcast - Fresh Air and Fresh Perspectives for Developers", Browser.Title);
}

SkippableFact lets me skip tests for basically any reason. I could help if I'm in Docker, as I'm doing here. Or, given that Selenium Tests will throw an "OpenQA.Selenium.WebDriverException" when it can't find the Selenium Web Driver, I could also do this, skipping because a specific Exception was through. Note this means it's a SKIP not a FAIL.

[SkippableFact(typeof(OpenQA.Selenium.WebDriverException))]
public void KevinScottTestThenGoHome()
{
   Browser.Navigate().GoToUrl(Server.RootUri + "/631/how-do-you-become-a-cto-with-microsofts-cto-kevin-scott");

   var headerSelector = By.TagName("h1");
   var link = Browser.FindElement(headerSelector);
   link.Click();
}

The results look like this:

Total tests: 22. Passed: 18. Failed: 0. Skipped: 4.
Test Run Successful.
Test execution time: 8.7878 Seconds

You could choose to Skip Tests if a backend, 3rd party API, or DB was down, but you still wanted to test as much as possible. I'm pretty happy with the results!


New Sponsor! Never type an invoice again! With DocSight OCR by ActivePDF, you’ll extract data from bills, invoices, PO’s & other documents using zonal data capture technology. Achieve Digital Transformation today!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.