| Comments

I’ve become a huge fan of DevOps and spending more time ensuring my own projects have a good CI/CD automation using GitHub Actions.  The team I work on in Visual Studio for .NET develops the “right click publish” feature that has become a tag line for DevOps folks (okay, maybe not in the post flattering way!).  We know that a LOT of developers use the Publish workflow in Visual Studio for their .NET applications for various reasons.  In reaching out to a sampling and discussing CI/CD we heard a lot of folks talking about they didn’t have the time to figure it out, it was too confusing, there was no simple way to get started, etc.  In this past release we aimed to improve that experience for those users of Publish to help them very quickly get started with CI/CD for their apps deploying to Azure.  Our new feature enables you to generate a GitHub Actions workflow file using the Publish wizard to walk you through it.  In the end you have a good getting started workflow.  I did a quick video on it to demonstrate how easy it is:

It really is that simple! 

Making it simple from the start

I have to admit though, as much as I have been doing this the YAML still is not sticking in my memory enough to type from scratch (dang you IntelliSense for making me lazy!).  There are also times where I’m not using Azure as my deployment but still want CI/CD to something like NuGet for my packages.  I still want that flexibility to get started quickly and ensure as my project grows I’m not waiting to the last minute to add more to my workflow.  I just saw Damian comment on this recently as well:

I totally agree!  Recently I found myself continuing to go to older repos to copy/paste from existing workflows I had.  Sure, I can do that because I’m good at copying/pasting, but it was just frustrating to switch context for even that little bit.  My searching may suck but I also didn’t see a quick solution to this either (please point out in my comments below if I missed a better solution!!!).  So I created a quick `dotnet new` way of doing this for my projects from the CLI.

Screenshot of terminal window with commands

I created a simple item template that can be called using the `dotnet new` command from the CLI.  Calling this in simplest form:

dotnet new workflow

will create a .github\workflows\foo.yaml file where you call it from (where ‘foo’ is the name of your folder) with the default content of a workflow for .NET Core that restores/builds/tests your project (using a default SDK version and ‘main’ as the branch).  You can customize the output a bit more with a command like:

dotnet new workflow --sdk-version 3.1.403 -n build -b your_branch_name

This will enable you to specify a specific SDK version, a specific name for the .yaml file, and the branch to monitor to trigger the workflow.  An example of the output is here:

name: "Build"

      - main
      - '**/*.md'
      - '**/*.gitignore'
      - '**/*.gitattributes'
      - main
      - '**/*.md'
      - '**/*.gitignore'
      - '**/*.gitattributes'
    if: github.event_name == 'push' && contains(toJson(github.event.commits), '***NO_CI***') == false && contains(toJson(github.event.commits), '[ci skip]') == false && contains(toJson(github.event.commits), '[skip ci]') == false
    name: Build 
    runs-on: ubuntu-latest
      DOTNET_NOLOGO: true

    - uses: actions/[email protected]
    - name: Setup .NET Core SDK
      uses: actions/[email protected]
        dotnet-version: 3.1.x

    - name: Restore
      run: dotnet restore

    - name: Build
      run: dotnet build --configuration Release --no-restore

    - name: Test
      run: dotnet test

You can see the areas that would be replaced by some input parameters on lines 6,13,38 here in this example (these are the defaults).  This isn’t meant to be your final workflow, but as Damian suggests, this is a good practice to start immediately from your “File…New Project” aspect and build up the workflow as you go along, rather than wait until the end to cobble everything together.  For me, now I just need to add my specific NuGet deployment steps when I’m ready to do so.

Installing and feature wishes

If you find this helpful feel free to install this template from NuGet using:

dotnet new --install TimHeuer.GitHubActions.Templates

You can find the package at TimHeuer.GitHubActions.Templates which also has the link to the repo if you see awesome changes or horrible bugs.  This is a simple item template so there are some limitations that I wish it would do automatically.  Honestly I started out making a global tool that would solve some of these but it felt a bit overkill.  For example:

  • It adds the template from where you are executing.  Actions need to be in the root of your repo, so you need to execute this in the root of your repo locally.  Otherwise it is just going to add some folders in random places that won’t work. 
  • It won’t auto-detect the SDK you are using.  Not horrible, but would be  nice to say “oh, you are a .NET 5 app, then this is the SDK you need”

Both of these could be solved with more access to the project system and in a global tool, but again, they are minor in my eyes.  Maybe I’ll get around to solving them, but selfishly I’m good for now!

I just wanted to share this little tool that has become helpful for me, hope it helps you a bit!

| Comments

The other day I was given a peek at a company who implemented a full-frame Silverlight application that when I saw it it was one of those “wow” moments.  A lot of the public-facing Silverlight examples are very different from one another and sometimes you see some that are full Silverlight applications that really give you a glimpse of how people are thinking about using the platform and how creative you can get.  Colaab is one such example that I saw at PDC last year (check it out if you haven’t).

Another example is a recent one called SnapFlow.  SnapFlow itself is a tool to really make creating workflows simpler to the end user.  The way they have designed their product makes it easy to understand how to create a decision-driven workflow that can be exposed to your users (customers, employees, etc.).  Essentially they separate the workflow into Stages, Actions and Data – all integrated into a user interface that if you are an Office user, you would have no problem understanding.  The best part is…the entire user interface is Silverlight.  Take a look at the screen below:

All of that design surface is Silverlight with full drag around behavior, connecting stages together in a visual, intuitive manner.  The application is very responsive and incorporates a lot of features.  I highly recommend you view the simple walk through video below for a view into all of the features…everything you see is Silverlight:

What is cool in one of the features is that once you, the creator of the workflow, are complete, you can then deploy that workflow into your web site or other portal (the demonstration shows using Sharepoint for example).  So you could develop a workflow for gathering some data from your web site, and embed the generated Silverlight application on your site with absolutely no coding required on your part.  Your employees will be able to act upon that workflow given the permissions assigned to them which then triggers the next part of the workflow (duh, it’s a workflow!) based on the action chosen.

It’s a convenient use of workflow, both simple and complex.  I am really impressed with the use of Silvelright and how responsive and fluid the user experience is.  I have walked through the application a few times and send my beta feedback on some things that I’ve seen from a general usability standpoint and the company was responsive.

The team at SnapFlow also put up a blog, where one of their first posts is: Why Silverlight?  It is an interesting read from a customer standpoint demonstrating some of the pros/cons in their decision and use.

SnapFlow is in beta right now and you really can’t appreciate it just looking at a screen shot.  Sign up for the beta and try it out yourself to see how they’ve used Silverlight to implement these types of usability features.  It uses a lot: controls, user interaction (drag/drop), popup modals, data input/validation, connecting objects, etc. – it’s a great example.  Sign up for the beta to play around with it.

| Comments

while preparing for the code trip, we have several 'on-board' needs.  one of which is a quick method to get our content encoded for consumption by devices and frameworks (i.e., silverlight).  we want a smooth method so that we aren't boggled down with multiple tools opening and changing settings, cutting and pasting, etc.

so, inspired by my colleagues post about using workflow to automate, i set about the task.  we're going to be making several assumptions along our production, one of which is we know we'll have multiple video/audio sources and that there *will* be some post-edit being done.  but once we have that post edit completed, we'll want all videos to feel similar (size, quality, etc.) and encoded for multiple uses.  i've pretty much decided that there really are 3 formats that would suffice the world: WMV, MP4, MP3.  if we get all of these, we can accommodate most.  here's how i justify that:

    • WMV: we'll have standard (4:3) and widescreen (16:9) format for viewing offline as well as online via silverlight (we'll be using the widescreen online most likely).  we'll also have a Zune formatted version for quick updating.
    • MP4: itunes, ipod, mac viewing in both standard and widescreen formats
    • MP3: audio format beloved by all

so the first step is to tackle the how.  if you don't know, expression encoder has a command-line interface.  this is especially helpful for a few things, namely our batch processing (you can also save job files and send in a job to the command-line interface quickly).  so the first thing i did was wrap the input parameters into a windows workflow foundation activity.  luckily michael did a lot of this for me in his webcast :-).  it basically abstracts all the possible input parameters and enables you to optionally send them into the activity:

for the mp4 encoding i'm using a piece of software that also has an command-line interface.  this one isn't as flexible so given my two known encoding types i'm pretty much hard-wiring in some of the settings and only enabling the size parameters for alteration.

mp3 version -- let's get to that later.

now that i have my activities (one for WMV, one for MP4) in an activity library, i'm ready for a client tool.  for our purposes, we don't need a fancy GUI tool, so i settled for a command-line interface.  in my client i added a sequential workflow and then added my activities.  i re-used the WMV activity 3 times to alter the different settings and then use the output of them to feed into my MP4 activity (used twice).  the resulting visual workflow looks like this:

the input to the command line looks for a source WMV file, title, description, author, album.  these input parameters are sent as named parameters to the workflow activity:

var namedArguments = new Dictionary<string, object>();

namedArguments.Add("SourceFilename", args[0]);
namedArguments.Add("Title", args[1]);
namedArguments.Add("Description", args[2]);
namedArguments.Add("Author", args[3]);
namedArguments.Add("Album", args[4]);

which are then mapped to properties of the activities:

the activity libraries also expose a few other properties that i'm passing in to my commands.  for example, i want each video to have a bumper intro and then an icon overlay in the right location.  i'm able to pass in these parameters which then map to expression encoder properties.  i'm also able to tell it to make sure to letterbox content that isn't native 16:9 aspect ratio for the standard format encodings.  the result of these activities is that i have three WMV files appropriate for my use.  expression encoder also generates thumbnail images of a frame in each video.  i've not much use for them, so i added the last workflow code to simply clean up the jpeg images generate (delete them) from the output directory.

one problem i had was that expression encoder exposes a lot of properties but not for metadata individually.  i wanted to embed the appropriate metadata for the WMV files for the title, description, etc.  luckily there is one input parameter for encoder that i can append to my other custom ones, and that is "/Preset" which enables me to provide certain presets that will be passed in and here is where it allows me to make metadata a part of that preset.  the input parameter looks for a literal xml file so i have to create one.  i added the template as a resource in my project:

<?xml version="1.0" encoding="utf-8"?>
            Value="{0}" />
            Value="{1}" />
            Value="2008, Microsoft" />
            Value="{2}" />
            Value="{3}" />
            Value="{4}" />
            Value="{4}" />
            Value="Podcast" />
            Value="{5}" />

and then when the user executes the command-line interface, i take their input, merge it with the xml here and output a temporary xml file that is then passed into the named parameter dictionary for the workflow activity.  when no longer needed it is cleaned up (on the workflow completed event handler).  now my WMV file is complete with formats and metadata.

for the MP4 format i chose to use the resulting output of the WMV file and do a single pass there.  the settings for the tool weren't ideal for adding overlays, etc. so using the resulting WMV file and same bitrates i'm just passing in the resulting WMV and creating two MP4 formats.  boom.  done.  the metadata actually *was* parameters i could send into this tool, so it was easy to ensure that metadata was in there.

now, on to the MP3 format.  sigh.  what i need is a tool that will enable me an WMV or MP4 input and extract the audio-only track into an MP3 file.  i found all sorts of tools that will do this, but none that can be automated from a command-line.  this is my last resulting automation problem for now.  if anyone has tips on how to do this, i'll send you a prize :-).

now on to decisions.  while we'll have several formats to offer viewers, we also want to have feeds with enclosures for readers.  that brings us to a decision.  podcast formats for enclosures only enable one enclosure.  so, dear reader, what do we choose?  i figure we offer a WMV, MP4 and MP3 feed uniquely...but then which format do we supply?  is this a lame question?  the widescreen will be the best quality, but will it render okay on all devices/readers?  what do you choose?

anyhow, a fun little project i finished (except for the MP3 -- prize awaiting) and thought i'd share how it is accomplished.  one little command "encodepipe.exe <file> <title> <desc> <author> <album>" and a few short minutes later i have all the formats i need.  the next step is to automate upload to a content delivery network so i don't have to pick and choose uploading!

we just posted the schedule for our trip, so if you want to subscribe to the feed to be notified when we'll start putting out some content, that would be cool.  real-time updates via twitter as well.  see you on the road!