<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tim Heuer</title>
    <description>The latest articles on DEV Community by Tim Heuer (@timheuer).</description>
    <link>https://dev.to/timheuer</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F74114%2F1beb89cc-8ef2-493d-8d0b-c85ccaeda749.jpg</url>
      <title>DEV Community: Tim Heuer</title>
      <link>https://dev.to/timheuer</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/timheuer"/>
    <language>en</language>
    <item>
      <title>Deploy a Blazor WASM site to Azure Storage using GitHub Actions</title>
      <dc:creator>Tim Heuer</dc:creator>
      <pubDate>Wed, 18 Dec 2019 21:50:44 +0000</pubDate>
      <link>https://dev.to/timheuer/deploy-a-blazor-wasm-site-to-azure-storage-using-github-actions-4on3</link>
      <guid>https://dev.to/timheuer/deploy-a-blazor-wasm-site-to-azure-storage-using-github-actions-4on3</guid>
      <description>&lt;p&gt;I’ve been spending a lot of time looking at the GitHub Actions experience for .NET developers.  Right now I’m still using Azure Pipelines for my project, &lt;a href="https://github.com/timheuer/alexa-skills-dotnet" rel="noopener noreferrer"&gt;Alexa.NET&lt;/a&gt;, in building, testing, and deploying to NuGet.  As the tools and process for using DevOps tools for CI/CD have so vastly improved over the years, I’ve become a huge advocate for this being the means for your build/deploy steps…YES, even as a single developer or a smaller team.  It simply really helps you get to a purer sense of preserving the ability for your code to live on, for others to accurately build it, and for you to have peace of mind that your code works as intended.  I’m just such a huge fan now.  That said, I still think there is a place for ‘right-click publish’ activities in inner-loop development.  In fact, I use it regularly for a few internal apps I’ve written.  For simple solutions that method works well, but I certainly don’t think I can right-click-publish a full solution to a Kubernetes environment though.  I’m currently researching new tooling ways to help those ‘publish to CI/CD’ from Visual Studio (would love your opinions here) so I’ve been spending a lot more time in GitHub Actions.  I decided to look at publishing a Blazor app to Azure Storage as a static site…here’s what I did.&lt;/p&gt;  &lt;h2&gt;Setting up the Storage endpoint&lt;/h2&gt;  &lt;p&gt;The first thing you need is an Azure Storage account.  Don’t have an Azure account, no worries you can get a &lt;a href="https://azure.com/free" rel="noopener noreferrer"&gt;Free Azure account&lt;/a&gt; easily which includes up to 5GB of Azure Blob Storage free for the first 12 months.  Worried about pricing afterwards?  Well check out the &lt;a href="https://azure.microsoft.com/en-us/pricing/calculator/?service=storage#storage91556251-d72c-4e8e-96b8-19ef29b05273" rel="noopener noreferrer"&gt;storage pricing calculator&lt;/a&gt; and I’m sure you’ll see that even at 1TB storage it is cost-effective means of storage.  But any rate, you need a storage account and here are the configuration you need.&lt;/p&gt;  &lt;p&gt;First, you may already have one.  As a developer do you create your infrastructure resources or are these provisioned for you by infra/devops roles in your company (leave comments)?  Earlier this year at Build we enabled &lt;a href="https://docs.microsoft.com/azure/storage/blobs/storage-blob-static-website" rel="noopener noreferrer"&gt;static website hosting in Azure Storage&lt;/a&gt;.  You first create a Storage resource (ensuring you choose v2 which is the default, but that is the version that enables this feature).  After you create your resource scroll on the left and you’ll see ‘Static website' section.  Here’s what the configuration looks like and let me explain a few areas here:&lt;/p&gt;  &lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fstaticconfig.png" class="article-body-image-wrapper"&gt;&lt;img title="Screenshot of the Static website configuration" alt="Screenshot of the Static website configuration" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fstaticconfig.png"&gt;&lt;/a&gt;    &lt;br&gt;All of this configuration is under the Static website area.  First you obviously need to enable it…that’s just toggling the enabled/disabled capability.  Enabling this now gets you two things: 2 endpoints (basically the URI to the website) and a specific blob contianer named $web where your static content needs to live.  The endpoints default map to this blob container without having to add a container name to the root URI.  Remember the &lt;strong&gt;resource group &lt;/strong&gt;you’ve given to your storage instance here, you will need that later.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;NOTE: You can later add CDN/custom domain to these endpoints, but I’m not covering those here.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The second thing you need is to set a default document and error page.  The default document for your SPA is your root entry point, and for most frameworks I’ve seen this is indeed index.html.  For Blazor WebAssembly (WASM) apps, this is also the default if you are using the template.  So you set the default document as ‘index.html’ and move on.  The error document path is another interesting one…you need to set this for SPA apps because right now the static website capability of Azure Storage does not account for custom routing rules.  What this means is that storage will throw an HTTP 404 error message when you go to something like /somepage where it actually doesn’t exist but your SPA framework knows how to handle it.  Until custom routing works on Azure Storage your error document becomes your route entry point.  So for this set the error document path to also be index.html for Blazor WASM.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;NOTE: Yes this isn’t ideal for routing.  On top of that it still does show an HTTP 404 actual network message even though your route is being handled.  Azure Storage team has heard this request…working on advocating for y’all.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;That’s it.  Now you have a storage endpoint with a blob container that you can begin putting your content in and browse to using your endpoint URI provided from the portal.  For a simple tool to navigate your storage, I’ve been using &lt;a href="https://azure.microsoft.com/features/storage-explorer/" rel="noopener noreferrer"&gt;Azure Storage Explorer&lt;/a&gt; and it is intuitive to me and works well to quickly navigate your storage account and containers (and supports multi-account!).  &lt;br&gt;&lt;/p&gt;  &lt;h2&gt;Setting up your Azure Service Principal credentials&lt;/h2&gt;  &lt;p&gt;The next thing you will need is a service principal credential.  This will be used to authenticate with your Azure account to be able to use DevOps tools to work on your behalf in your account.  It’s a simple process if you have a standard account.  I say this only because I know there might be some configurations for environments where you yourself don’t have access to create service principals and may need someone to create one on your behalf, or also there might be credentials you can already use.  Either way here is the process I used.&lt;/p&gt;  &lt;p&gt;I used the &lt;a href="https://docs.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest" rel="noopener noreferrer"&gt;Azure CLI&lt;/a&gt; so if you don’t have that installed go ahead and grab that and install it.  This should now be in your PATH environment and using your favorite terminal you should be able to start executing commands.  To start out, login to the CLI using `az login` – this will launch a browser for you to authenticate via your account and then issue the token in your environment so that for the remainder of your session you’ll be authenticated.  After logging in successfully running `az account show` will emit what subscription you are using and you’ll need the subscription ID later so grab that and put it somewhere on your scratch notepad for later command usage.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;NOTE: If you have more than one subscription and have not set a default subscription you should set that using the `&lt;a href="https://docs.microsoft.com/cli/azure/manage-azure-subscriptions-azure-cli?view=azure-cli-latest" rel="noopener noreferrer"&gt;az account set&lt;/a&gt;` command.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Now you can use the CLI to create a new service principal.  To do that issue this command:&lt;/p&gt;  &lt;pre class="brush: bash; toolbar: false; highlight: [2];"&gt;az ad sp create-for-rbac --name "myApp" --role contributor \
                            --scopes /subscriptions/{subscription-id}/resourceGroups/{resource-group} \
                            --sdk-auth
&lt;/pre&gt;

&lt;p&gt;Note on line 2 here that you need to replace {subscription-id} with your own actual subscription id (the GUID) and {resource-group} with the resource group name where your storage account is located.  On line 1 the “myApp” can be anything but I recommend making it meaningful as this is basically the account name of the principal.  The output of this command is your service principal.  The full JSON output.  Save this off in a place for now as we’ll need that later to configure GitHub Actions properly.  Great now to move on to the app!&lt;/p&gt;

&lt;h2&gt;Create your Blazor WASM app&lt;/h2&gt;

&lt;p&gt;I assume since you may be reading this far you aren’t new to Blazor and probably already have the tools.  As of this writing, Blazor WASM is still in preview so you have to install the templates separately to acquire them to show up in `dotnet new` and in Visual Studio File…New Project.  To do that from a terminal run:&lt;/p&gt;

&lt;pre&gt;dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.1.0-preview4.19579.2
&lt;/pre&gt;

&lt;p&gt;Then you will be able to create a new project.  I’m showing Visual Studio here and this is the WASM template:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fblazornpd.png" class="article-body-image-wrapper"&gt;&lt;img title="Screenshot of Blazor new project dialog" alt="Screenshot of Blazor new project dialog" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fblazornpd.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the dialog here you will see Blazor WebAssembly App and that’s what you will use.  Now you have a choice to have it ASP.NET Core hosted using that checkbox, which if you were going to do other things in ASP.NET maybe that’s what you want.  For the purposes of this article we are talking about just having the WASM app and having a place to host it that isn’t a web server with other content…just hosting static content and using storage to do so…so we aren’t checking that box.  The result will be a Blazor WASM app with no host.  Now let’s add that to GitHub.  If you are using Visual Studio 16.4+ you’ll be able to take advantage of an improved flow for pushing to GitHub.  Once you have your project, in the lower right click ‘Add to Source Control’ choosing Git and then you’ll see the panel to choose GitHub and create/push a repo right away.  You don’t have to go to GitHub site first and clone later…all in one step:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fnewgitflow.gif" class="article-body-image-wrapper"&gt;&lt;img title="Animation of Visual Studio GitHub flow" alt="Animation of Visual Studio GitHub flow" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fnewgitflow.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great!  Now we have our WASM project and we’ve created and pushed the current bits to a new GitHub repository.  Now to create the workflow.&lt;/p&gt;

&lt;h2&gt;Setup the GitHub Action Workflow&lt;/h2&gt;

&lt;p&gt;Now we’ve got an Azure Storage blob container, a service principal, a Blazor WASM project, and a GitHub repository…all set to configure the CI/CD flow now.  First let’s put that service principal as a secret in our repository.  In the settings of your repository navigate to the Secrets section and add a secret named AZURE_CREDENTIALS.  The content of this is the full content of your service principal (the JSON blob) that we generated earlier:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fgithubsecretconfig.png" class="article-body-image-wrapper"&gt;&lt;img title="Screenshot of GitHub Secrets configuration" alt="Screenshot of GitHub Secrets configuration" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fgithubsecretconfig.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This saves the secret for us to use in the workflow and reference as a variable.  You can add more secrets here if you’d like if you wanted to add your resource storage account name as well (probably a good idea).  Secrets are isolated to the original repository so no forks get the secrets at all.  Now that we have these let’s create the workflow file.&lt;/p&gt;

&lt;p&gt;Today, Visual Studio isn’t too helpful in authoring the YAML files (would love your feedback here too!) but a GitHub Action is just a YAML file in a specific location in your repository: .github/workflows/azure-storage-deploy.yaml.  The file name can be anything but putting it in this folder structure is what is required.  You can start in the GitHub repo itself using the Actions tab and through the online editor get &lt;em&gt;some&lt;/em&gt; level of completion assistance to help you navigate the YAML editing.  Go to the Actions tab in your repository and create a new workflow.  You’ll be offered a starter workflow based on what GitHub thinks your project is like.  As of this writing it thinks Blazor apps are Jekyll workflows so you’ll need to expand and either find the .NET Core one or just start from a blank workflow yourself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fworkflowstarter.png" class="article-body-image-wrapper"&gt;&lt;img title="Screenshot of GitHub Actions config" alt="Screenshot of GitHub Actions config" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fworkflowstarter.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Four my workflow I want to build, publish and deploy my app.  I’ve separated it into a build and deploy jobs.  You can read all about the various aspects of &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;GitHub Actions in their docs&lt;/a&gt; with regard to jobs and other syntax as I won’t try to expound upon that in this article.  Here is my full YAML for the entire workflow with some key areas highlighted:&lt;/p&gt;

&lt;pre class="brush: yaml; toolbar: false; highlight: [5,6,7,26,27,28,29,30,39,40,41,42,45,48,51,61];"&gt;name: .NET Core Build and Deploy

on: [push]

env:
  AZURE_RESOURCE_GROUP: blazor-deployment-samples
  BLOB_STORAGE_ACCOUNT_NAME: timheuerblazorwasm

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - name: Setup .NET Core
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: 3.1.100

    - name: Build with dotnet
      run: dotnet build --configuration Release
    
    - name: Publish with dotnet
      run: dotnet publish --configuration Release 
    
    - name: Publish artifacts
      uses: actions/upload-artifact@master
      with:
        name: webapp
        path: bin/Release/netstandard2.1/publish/BlazorApp27/dist

  deploy:
    needs: build
    name: Deploy
    runs-on: ubuntu-latest
    steps:

    # Download artifacts
    - name: Download artifacts
      uses: actions/download-artifact@master
      with:
        name: webapp

    # Authentication
    - name: Authenticate with Azure
      uses: azure/login@v1
      with:
        creds: `${{ secrets.AZURE_CREDENTIALS  }}`

    # Deploy to storage using CLI
    - name: Deploy to storage using CLI
      uses: azure/CLI@v1
      with:
        azcliversion: latest
        inlineScript: | 
          # show azure account being used
          az account show
          # az storage account upload
          az storage blob upload-batch --account-name `${{ env.BLOB_STORAGE_ACCOUNT_NAME }}` -s webapp -d \$web
          # az set content type of wasm file until this is fixed by default from Azure Storage
          az storage blob update --account-name `${{ env.BLOB_STORAGE_ACCOUNT_NAME }}` -c \$web -n _framework/wasm/mono.wasm --content-type application/wasm

&lt;/pre&gt;

&lt;p&gt;So a few things going on here, let’s talk about them.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Lines 5-7: these are ‘local’ environment variables I set up.  The storage account name is NOT the blob container name but the actual storage account name.  This ideally probably should be a Secret as mentioned above.  Environment variables can be set here and then placeholders reference them later.&lt;/li&gt;

  &lt;li&gt;Starting at line 9 is where the ‘build’ portion is here.  We checkout the code, acquire the SDK and run the build and publish commands.  On line 26-30 is a step where we put the publish output to a specific artifact location for later retrieval of steps.  This is good practice.&lt;/li&gt;

  &lt;li&gt;Lines 40-42 is where we are now in the ‘deploy’ step of our CD and we retrieve those artifacts we previously pushed and we set them as a name ‘webapp’ that the later will use in deployment&lt;/li&gt;

  &lt;li&gt;Line 45 is where we are going to first authenticate to Azure using our service principal retrieved from the Secrets.  The ‘secrets’ object is not something you have to define and is part of the workflow so you just add the property you want to retrieve&lt;/li&gt;

  &lt;li&gt;Line 51 is where we start the deployment to Azure using the CLI commands and our param ‘webapp’ as the source.  This is the CLI command for uploading batch to storage as described in the docs for `&lt;a href="https://docs.microsoft.com/cli/azure/storage/blob?view=azure-cli-latest#az-storage-blob-upload-batch" rel="noopener noreferrer"&gt;az storage blob upload-batch&lt;/a&gt;`&lt;/li&gt;

  &lt;li&gt;Line 61 is an additional step that we need for .wasm files.  I believe this to be a bug because there is logic in the CLI to correctly map the content-type but for some reason it is not working…so for now you need to set the content-type for .wasm to `application/wasm` or the Blazor app will not work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is made possible through a series of actions: checkout, dotnetcore, azure…all brining their functionality we can draw on and configure.  There are a &lt;a href="https://azure.microsoft.com/blog/github-actions-for-azure-is-now-generally-available/" rel="noopener noreferrer"&gt;bunch of Azure GitHub Actions&lt;/a&gt; we just released for specific tasks like deploying to App Service and such.  These don’t require CLI commands but rather just provide parameters to configure.  Because there is no Storage specific Action as of now, we can use the default CLI action to script what we want.  It is an enabler in lieu of a more strongly-typed action.  Now that we have this workflow YAML file complete we can commit and push to the repository.  In doing that we now have a CI/CD action that will trigger on any push (because that’s how we configured it).  We can see this action happening in my sample repo and you can see since we separate it in two jobs it will show them separately:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fdeploylogs.png" class="article-body-image-wrapper"&gt;&lt;img title="Screenshot of action deployment log" alt="Screenshot of action deployment log" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fdeploylogs.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;So now we have it complete end-to-end.  And subsequent check-in will trigger the workflow and deploy the bits to my storage account and I can now use my Azure Storage account as a host for my static website built on Blazor WASM.  This full YAML sample flow is available on my repo for this and you can examine it in more detail.&lt;/p&gt;

&lt;p&gt;I would love to know how y’all are coming along using GitHub Actions with your .NET projects.  Please comment below!  &lt;/p&gt;


&lt;p&gt;(this article &lt;a href="https://timheuer.com/blog/deploy-blazor-app-to-azure-using-github-actions/" rel="noopener noreferrer"&gt;cross-posted from timheuer.com&lt;/a&gt;)&lt;/p&gt;

</description>
      <category>azure</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>devops</category>
    </item>
    <item>
      <title>Building and Customizing the new Windows Terminal</title>
      <dc:creator>Tim Heuer</dc:creator>
      <pubDate>Tue, 14 May 2019 16:02:03 +0000</pubDate>
      <link>https://dev.to/timheuer/building-and-customizing-the-new-windows-terminal-16i9</link>
      <guid>https://dev.to/timheuer/building-and-customizing-the-new-windows-terminal-16i9</guid>
      <description>&lt;p&gt;I don’t like C++.  There I said it…got it out of the way.  It’s not a fair statement, as I know many people who do and think I’m crazy for not only writing code in C++.  As someone who didn’t come from a traditional computer science background, I just never ‘grew up’ on C or C++ as fundamentals.  &lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;NOTE: You can hear more about my journey (and others) to tech on the awesome &lt;strong&gt;&lt;a href="https://www.codenewbie.org" rel="noopener noreferrer"&gt;CodeNewbie&lt;/a&gt;&lt;/strong&gt; podcast.  Here’s my episode right here: &lt;a href="https://www.codenewbie.org/podcast/from-police-recruit-to-developer" rel="noopener noreferrer"&gt;From police recruit to developer&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Go ahead, insert ‘you’re not a real programmer’ comments below.  I’ve established enough thick skin over the years to hear that feedback.  Anyhow, I digress.  While I’m not a fan of C++ it really isn’t about the language but the iteration dev loop.  I’ve often found it slower than what I’d like and the mix/match of toolsets, settings, etc. has left a lot to be desired to me.  HOWEVER, all this said, looking at C++ code is an excellent way to learn and to actually appreciate more the language and code that others write.  No better source of learning development exists than code.&lt;/p&gt;
&lt;p&gt;Last week at the Microsoft Build conference a fun new project was unleashed to the developer community…a new &lt;strong&gt;&lt;a href="https://github.com/microsoft/Terminal/" rel="noopener noreferrer"&gt;Windows Terminal&lt;/a&gt;&lt;/strong&gt;.  AND it is Open Source!  &lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fterminal1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fterminal1.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I’ve never seen as much excitement about a terminal app in this ecosystem as I have the past 10 days.  So much fun.  First, here’s the team that brings you the Windows Terminal project:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Dear &lt;a href="https://twitter.com/hashtag/Build2019?src=hash&amp;amp;ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;#Build2019&lt;/a&gt; physical and virtual attendees &amp;amp; tweeps - thank you for attending our talks, visiting our booth, and asking/posting tons of great questions &amp;amp; comments. We appreciate you all.&lt;br&gt;&lt;br&gt;With love from the &lt;a href="https://twitter.com/hashtag/WSL?src=hash&amp;amp;ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;#WSL&lt;/a&gt; and &lt;a href="https://twitter.com/hashtag/Terminal?src=hash&amp;amp;ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;#Terminal&lt;/a&gt; teams&lt;br&gt;&lt;br&gt;Until next year 😜 &lt;a href="https://t.co/VayHovDnNJ" rel="noopener noreferrer"&gt;pic.twitter.com/VayHovDnNJ&lt;/a&gt;&lt;/p&gt;— Rich Tur-minal-ner-d (&lt;a class="mentioned-user" href="https://dev.to/richturn_ms"&gt;@richturn_ms&lt;/a&gt;) &lt;a href="https://twitter.com/richturn_ms/status/1126264083043328002?ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;May 8, 2019&lt;/a&gt;
&lt;/blockquote&gt; &lt;p&gt;Great people, passionate about making Windows a great development environment for no matter what you are developing.  This is also the team bringing you WSL and the new capabilities there!  So you want to try out the terminal…your first question is &lt;em&gt;Where can I get it?&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Building Windows Terminal&lt;/h2&gt;
&lt;p&gt;Well, for now it is source only.  This will likely change over the course of the next few months, but for now if you really want to try it out, you need to build it yourself.  The &lt;a href="https://github.com/microsoft/Terminal/" rel="noopener noreferrer"&gt;repository on GitHub&lt;/a&gt; has all the bits and instructions for you to do so.  I jumped on this right away like others but ran into a few bumps because I was using Visual Studio 2019.  Luckily this has been solved by &lt;a href="https://github.com/microsoft/Terminal/commit/af7316c130059ba15fe16ff0d13608d956a2b449" rel="noopener noreferrer"&gt;this PR&lt;/a&gt; to help make the scavenger hunt for dependencies less painful.  &lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;SIDE NOTE: If you have an open source or team-based project, do yourself a favor and add a .vsconfig file now.  Details: &lt;a href="https://devblogs.microsoft.com/setup/configure-visual-studio-across-your-organization-with-vsconfig/?WT.mc_id=blog-blog-timheuer" rel="noopener noreferrer"&gt;Configure Visual Studio across your organization with .vsconfig&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Basically the steps are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/windows/uwp/get-started/enable-your-device-for-development?WT.mc_id=docs-blog-timheuer" rel="noopener noreferrer"&gt;put your machine in developer mode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ensure you have some Git tools&lt;/li&gt;
&lt;li&gt;ensure you have the C++ tools (compilers, etc.) (&lt;a href="https://visualstudio.microsoft.com/?WT.mc_id=visualstudio-blog-timheuer" rel="noopener noreferrer"&gt;Visual Studio Community Edition&lt;/a&gt; is free to download/install and works)&lt;/li&gt;
&lt;li&gt;clone the repository&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/Terminal#building-the-code" rel="noopener noreferrer"&gt;update the submodules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;build the repo (using VS or the tools\bcz script)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you use Visual Studio 2019 (recommended by me) opening the OpenConsole.sln file should prompt you with a screen that will give you a note to ‘install’ the missing dependencies in the Solution Explorer:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fvsconfig-screenshot00.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fvsconfig-screenshot00.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you click Install it will run you through the missing components you may not have enabled for completing the build.  Finish that process.  Once done, you will have all the bits and can go back to the OpenConsole.sln project and choose ‘Build Solution’ and start the process.  Lots of stuff building for the first time so it will take a bit.  Now what?&lt;/p&gt;
&lt;h2&gt;Deploying/Running Windows Terminal&lt;/h2&gt;
&lt;p&gt;Building is step 1, now you want to run it.  Windows Terminal is a Universal Windows Platform (UWP) application and must be deployed first.  The &lt;em&gt;easiest&lt;/em&gt; way for doing this is from Visual Studio, but you may want to know what project!?  The &lt;strong&gt;Terminal\CascadiaPackage&lt;/strong&gt; project is the one you want and just right-click on that and choose Deploy.  This will deploy it to your machine (assuming you enabled developer mode).  And this will now be in your start menu:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fstartmenuterminal.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fstartmenuterminal.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Click/tap/whatever on that and you will launch Terminal for the first time!&lt;/p&gt;
&lt;h2&gt;Wait, where are the tabs I saw?&lt;/h2&gt;
&lt;p&gt;Ah, now that you have it running, let’s take a tour.  The settings right now are a JSON file that you can access via the settings menu.  How do you get the settings menu?  Hit CTRL + T to bring up the tab view and then you should have a drop-down menu in the upper right area:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fterminalmenupic.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fterminalmenupic.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you click Settings it will open up the profile.json file in the default editor on your machine configured for editing JSON files.  For me this was Visual Studio, but you can use Code or other editor as well.  This is editing your own profile for your terminal environment.  By default this JSON is void of white-space so you may want to format it to make it more readable.  In Visual Studio that is CTRL + K, CTRL + D and it will prettify it for you.  You’ll then see some initial settings in the top of the file:&lt;/p&gt;

&lt;pre class="brush: css; toolbar: false; highlight: [5];"&gt;{
  "defaultProfile": "{a933a071-2a32-42c9-b03a-550845793252}",
  "initialRows": 30,
  "initialCols": 120,
  "alwaysShowTabs": true,
  "showTerminalTitleInTitlebar": true,
  "experimental_showTabsInTitlebar": false,
&lt;/pre&gt;
&lt;p&gt;If you change line 5 here like I did to true then you will always start with tabs even if only one console host is running.  When you save the profile.json file it will re-format to no whitespace FYI (there is a watcher on the file in the code) but the settings will become immediate.&lt;/p&gt;
&lt;h2&gt;Navigating the profile.json options&lt;/h2&gt;
&lt;p&gt;The profile file main meat is in the profiles themselves.  These drive what shells/consoles you can launch and their configuration.  For example here is a snippet of what mine looks like right now a bit:&lt;/p&gt;

&lt;pre&gt;{
  "defaultProfile": "{a933a071-2a32-42c9-b03a-550845793252}",
  "initialRows": 30,
  "initialCols": 120,
  "alwaysShowTabs": true,
  "showTerminalTitleInTitlebar": true,
  "experimental_showTabsInTitlebar": false,
  "profiles": [
    {
      "startingDirectory": "c:\\users\\timheuer\\documents\\github",
      "guid": "{b056b6a8-89ba-4868-86c6-2ea078cd4fdd}",
      "name": "cmd",
      "colorscheme": "UbuntuLegit",
      "historySize": 9001,
      "snapOnInput": true,
      "cursorColor": "#FFFFFF",
      "cursorHeight": 25,
      "cursorShape": "vintage",
      "commandline": "cmd.exe",
      "fontFace": "Cascadia Code",
      "fontSize": 12,
      "acrylicOpacity": 0.75,
      "useAcrylic": true,
      "closeOnExit": true,
      "padding": "0, 0, 0, 0",
      "icon": "ms-appdata:///roaming/cmd-icon.png"
    },
    {
      "startingDirectory": "c:\\users\\timheuer\\documents\\github",
      "guid": "{a933a071-2a32-42c9-b03a-550845793252}",
      "name": "PowerShell",
      "background": "#0C0C0C",
      "colorscheme": "UbuntuLegit",
      "historySize": 9001,
      "snapOnInput": true,
      "cursorColor": "#FFFFFF",
      "cursorHeight": 25,
      "cursorShape": "vintage",
      "commandline": "powershell.exe",
      "fontFace": "Meslo LG M for Powerline",
      "fontSize": 12,
      "acrylicOpacity": 0.75,
      "useAcrylic": true,
      "closeOnExit": true,
      "padding": "0, 0, 0, 0",
      "icon": "ms-appdata:///roaming/powershell_64.png"
    },
&lt;/pre&gt;
&lt;p&gt;While I don’t have all options enabled a &lt;a href="https://github.com/microsoft/Terminal/blob/master/src/cascadia/TerminalApp/Profile.cpp" rel="noopener noreferrer"&gt;little spelunking the source code&lt;/a&gt; helps you know what other options exist:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;name: the name of the particular profile.  Right now this is what shows in the drop-down menu shown previously.  There is an issue logged to perhaps make this the name of the tab as well.&lt;/li&gt;
&lt;li&gt;guid: the unique identifier of this profile.  Incidentally if you didn’t know and wanted to create your own profiles and need a GUID, VIsual Studio has a “Create GUID” tool available from the tools menu…choose registry format and then copy/paste&lt;/li&gt;
&lt;li&gt;colorscheme: this maps to the color scheme for this area…which is an array of colors that maps to the various foreground/background/text/highlight/etc. settings that are also configurable.  You can see in your profile file that Campbell and a few others (Solarized Dark/Light) are pre-configured.  You can use iterm2colors values to create a new scheme.&lt;/li&gt;
&lt;li&gt;foreground: the foreground, duh (overwriting colortable/scheme)&lt;/li&gt;
&lt;li&gt;background: the background, duh (overwriting colortable/scheme)&lt;/li&gt;
&lt;li&gt;colortable: an in-line version of the color array that would be within a scheme&lt;/li&gt;
&lt;li&gt;historySize: I honestly haven’t looked at this one yet in the code to know&lt;/li&gt;
&lt;li&gt;snapOnInput: I honestly haven’t looked at this one either&lt;/li&gt;
&lt;li&gt;cursorColor: color of the cursor style you chose&lt;/li&gt;
&lt;li&gt;cursorShape: different options to show the cursor: vintage (thick underscore), bar (vertial bar), underscore (thin underscore), filledBox, emptyBox&lt;/li&gt;
&lt;li&gt;cursorHeight: height for the cursor&lt;/li&gt;
&lt;li&gt;commandline: the command to run for the profile (full path or something that will be found in PATH)&lt;/li&gt;
&lt;li&gt;fontFace: the fond to use for this profile.  You may see in mine that I am using ‘Meslo LG M for Powerline’ to get the cool customizations of the prompt.  &lt;a href="https://gist.github.com/jchandra74/5b0c94385175c7a8d1cb39bc5157365e" rel="noopener noreferrer"&gt;Find more on how to do that here&lt;/a&gt; and it works in Windows Terminal&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;Note: the team will also be open sourcing a new font that will be used for the terminal, but is not yet available as of this post&lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;fontSize: size of the font&lt;/li&gt;
&lt;li&gt;acrylicOpacity: the opacity of the window if you choose to use the acrylic (transparency) feature.  value from 0-1&lt;/li&gt;
&lt;li&gt;useAcrylic: true/false if you want to use the transparency&lt;/li&gt;
&lt;li&gt;scrollbarState: hidden/visible are the options&lt;/li&gt;
&lt;li&gt;closeOnExit: true/false if you want the tab to close when you initiate the exit command for your host&lt;/li&gt;
&lt;li&gt;padding: this affects some of the output but honestly not working well right now, recommend leaving at 0,0,0,0&lt;/li&gt;
&lt;li&gt;startingDirectory: the startup directory for this profile.  I have mine configured with my github directory where all my code is instead of $home (which is default)&lt;/li&gt;
&lt;li&gt;icon: an icon that will show in the menu and the tab.  These live in your RoamingState directory (C:\Users\&amp;lt;yourusername&amp;gt;AppData\Local\Packages\WindowsTerminalDev_8wekyb3d8bbwe\RoamingState) and the format for the value is “ms-appdata:///roaming/&amp;lt;yourfilename&amp;gt;”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For now these are the available options that you should fitz around with to customize what you need to change.  I’ve messed around with these enough and got to where I want them to be for me right now.&lt;/p&gt;
&lt;h2&gt;Navigating the source and contributing&lt;/h2&gt;
&lt;p&gt;As I started this post about how I didn’t like C++, it is a good place to learn a lot.  The Windows Terminal source is a maze of someone else’s code and right now without a clear map.  So the best way is to really just dig in and follow a particular flow.  I find this is the best way to navigate any project source code: find one feature and try to find and follow it in the code.  For me, I was messing with the settings file so much and I hated using the menu with my mouse I wanted a keyboard shortcut.  I knew that CTRL + T launched a new tab, so hey I could implement a keyboard shortcut to launch the settings file quickly.  I first logged that feature as an issue on the project: &lt;a href="https://github.com/microsoft/Terminal/issues/683" rel="noopener noreferrer"&gt;Add keybinding for access to Settings&lt;/a&gt; and then went to work.  I knew that the new tab shortcut existed so I took my own advice: &lt;em&gt;follow the code!&lt;/em&gt;  After a few tries and navigating all the headers and various code files I submitted a PR to the project for my own issue: &lt;a href="https://github.com/microsoft/Terminal/pull/684/commits/c5cadf7b004ab4c380dabfe52c3458935df7383e" rel="noopener noreferrer"&gt;PR#684&lt;/a&gt;.  There were 6 files changed to add this key binding and if you look at the change I proposed, there was already a function I could call (same one the menu uses) and I really just needed to map the key binding and have it call the existing function.  Simple, but I learned a bit of how the current code is structured in the repository.&lt;/p&gt;
&lt;p&gt;So my recommendation would be to find something that you are seeing as a piece of existing functionality or something you want to add yourself and start looking at searching for where you think it might be.  You’ll quickly find out some of the structure around TerminalSettings, TerminalCore, TerminalControl, etc. and play around with making some changes.  Keep in mind this is active development and things will change around quite frequently.  The team even indicates much:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;⚠ &lt;strong&gt;Note&lt;/strong&gt;: The Command-Line Team is actively working out of this repository and will be periodically re-structuring the code to make it easier to comprehend, navigate, build, test, and contribute to, so &lt;strong&gt;DO expect significant changes to code layout on a regular basis&lt;/strong&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I have already been bitten a bit by a merge, but no big deal just fix up a few things and move along again!&lt;/p&gt;
&lt;h2&gt;What’s Next?&lt;/h2&gt;
&lt;p&gt;The team has a good aspiration of what they want to accomplish and just getting started.  Quality will improve, bugs will get fixed, consumption of the terminal will be better, etc.  Read the README file in the repository and engage with the team on Twitter (their contact info in the README).&lt;/p&gt;
&lt;p&gt;Hope this helps!&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;(this article &lt;a href="https://timheuer.com/blog/archive/2019/05/13/building-windows-terminal-navigating-source-and-profile-settings.aspx" rel="noopener noreferrer"&gt;cross-posted from timheuer.com&lt;/a&gt;)&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>opensource</category>
      <category>productivity</category>
      <category>bash</category>
    </item>
    <item>
      <title>How I solved Jessica’s NYC Parking Problem with Twitter, Twilio and NO CODE</title>
      <dc:creator>Tim Heuer</dc:creator>
      <pubDate>Fri, 19 Apr 2019 13:49:41 +0000</pubDate>
      <link>https://dev.to/azure/how-i-solved-jessica-s-nyc-parking-problem-with-twitter-twilio-and-no-code-2mgg</link>
      <guid>https://dev.to/azure/how-i-solved-jessica-s-nyc-parking-problem-with-twitter-twilio-and-no-code-2mgg</guid>
      <description>&lt;p&gt;I’ve been reading a lot of great content on &lt;a href="https://dev.to"&gt;dev.to&lt;/a&gt; lately (seriously you should go check it out and follow some tags…great community there) and came across this great headline “&lt;a href="https://dev.to/twitterdev/how-i-solved-my-nyc-parking-problem-with-python-the-search-tweets-api-and-twilio-1chp"&gt;How I Solved My NYC Parking Problem With Python, the Search Tweets API and Twilio&lt;/a&gt;” by &lt;a href="https://twitter.com/jessicagarson" rel="noopener noreferrer"&gt;Jessica Garson&lt;/a&gt;, a Developer Advocate at Twitter.  Jessica was trying to solve a problem that NYC folks have when trying to determine when to move their street-side parked cars each night due to ‘alternate  side regulations’ which determine when certain sides of roads can be used or the regulations won’t be enforced due to holidays, events, whatever. &lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fparkingsign.png" class="article-body-image-wrapper"&gt;&lt;img title="" alt="New York City parking sign" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fparkingsign.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; She delved into using Python, the Twitter Search APIs and Twilio to tie these all together.  Fun problem to solve and results in a text to Jessica whether she needs to worry about moving her car or not.  Immediately after reading it I though of the game show Name That Tune.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fname-that-tune.jpg" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Picture of Name That Tune game show" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fname-that-tune.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The premise of the game show is that contestants battle it out to who can identify a song based on the fewest amount of notes in a song.  So of course, it is 100% applicable to code, right?  Anyhow I thought to myself &lt;em&gt;Self, I can solve this problem in less effort and with NO code!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Immediately I went to work using &lt;a href="https://azure.microsoft.com/services/logic-apps/?WT.mc_id=docs-blog-timheuer" rel="noopener noreferrer"&gt;Azure Logic Apps&lt;/a&gt;.  Azure Logic Apps are a means to…well, let’s let the marketing people tell us what they are:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;Azure Logic Apps simplifies how you build automated scalable workflows that integrate apps and data across cloud services and on-premises systems.&lt;/em&gt; &lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Lots of buzzwords there but basically it’s workflow/orchestration platform that allows you to use ‘connectors’ between various inputs and outputs.  Logic Apps can be developed using code, but most are easily developed using no code and using the graphical connector tools.  If you’ve ever used/heard of &lt;a href="https://flow.microsoft.com/en-us/" rel="noopener noreferrer"&gt;Microsoft Office Flow&lt;/a&gt; this is powered by Azure Logic Apps underneath!  So immediately after reading the article I went to work.  I knew that Azure already had pre-build connectors for Twitter and Twilio and that I should be able to do this easily.  &lt;a href="https://docs.microsoft.com/azure/connectors/apis-list?WT.mc_id=docs-blog-timheuer" rel="noopener noreferrer"&gt;Connectors&lt;/a&gt; are pre-defined pieces of logic that help get access to events, data, and actions across other apps and platforms, in our case Twitter and Twilio!&lt;/p&gt;
&lt;p&gt;Jessica’s problem was fairly simple: Watch when the @NYCASP account tweets and if it indicates rules are ‘suspended’ then alert her with a text message.  Now this relies on @NYCASP account being consistent in their tweets and it turns out they are VERY consistent in them, so it’s easy to search for the simple terms as Jessica did.  So let’s do the same.  &lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Ftweets.jpg" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Screenshot of Twitter account for NYCASP" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Ftweets.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To get started I needed an &lt;a href="https://azure.microsoft.com/free/?WT.mc_id=freetrial-blog-timheuer" rel="noopener noreferrer"&gt;Azure account which is free to get started&lt;/a&gt; and there are a ton of services free that you can use forever.  I also still needed a Twilio account like Jessica notes so you still need that to get your Twilio credentials…be sure you have that.  With both of these in hand, let’s log in to the Azure Portal….we won’t even need any tools other than a browser to complete this app!&lt;/p&gt;
&lt;p&gt;In the portal you’ll create a new resource in Azure…search for Logic App and it will show up:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fcreatelogicapp.png" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Screenshot of Azure portal" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fcreatelogicapp.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You’ll need to provide a name, choose a resource group plan and a geographic location where you want this to live.  If you’ve never created any Azure resources before, a resource group is a container for certain compute resources to leverage.  For this, I recommend creating an App Service resource group and using a free plan that comes with your free trial account.  Then you can use this resource group for your Logic App.  Once you have that created navigate to that resource and you will see a page that welcomes you with a tutorial video and some options for pre-configured templates.  Thankfully one of the starting options is “When a new tweet is posted” so let’s use that one to help us get started as it will default add the &lt;a href="https://docs.microsoft.com/connectors/twitter/?WT.mc_id=docs-blog-timheuer" rel="noopener noreferrer"&gt;Twitter connector&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fnewtweetposted.png" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Screenshot of Azure Portal Logic App creation" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fnewtweetposted.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This dumps us into the Logic App designer, a graphical interface that helps us do the connections.  You’ll immediately see the first ‘trigger’ which is our Twitter one and it wants you to sign in to be able to use the functionality (think of this as authorizing use of the API).  Once you sign in click continue and you’ll get the options.  Now basically we want to look for when a new tweet is posted by @NYCASP on a time interval.  Their account is pretty consistent so I chose every four hours and used the ‘from:@NYCASP’ query language as the search text.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fnewtweetconfig.png" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Screenshot of Twitter connector" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fnewtweetconfig.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That’s it for Twitter.  No code successfully so far!  So now every 4 hours this will check for a new tweet from that account.  Now let’s do something with it!  In Jessica’s scenario we need to look at the tweet and act upon it only if a specific condition was met.  So let’s use that little “+” symbol on the designer and add a new action.  Search for 'Condition’ and you will see ‘Control’ come up as an option…select that, then you will see the Condition connector…choose that.  The condition connector gives us a simple decision tree: what is the condition, what do you want to do if true, what do you want to do if false:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fconditionblank.png" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Screenshot of Condition action connector" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fconditionblank.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the condition area where it says ‘Choose a value’ when you click in to there, data from the previous trigger will be made available to you and you can see all the details it exposes!  We will scroll and look for Tweet text and select that.  Change the oeprator to ‘contains’ and type in ‘suspended’ as the value.  It should look like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fconditionsuspended.png" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Screenshot of Condition action connector" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fconditionsuspended.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now we know that the tweet is telling us something about suspending…but Jessica wants to know if she has to move her car for tomorrow.  Let’s add another condition to now check to see if it contains ‘tomorrow’ in the text.  We follow the same steps in creating a new condition trigger and connecting it.  &lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;At this point we have a nested condition.  Could we have put them in the same one?  Probably, but I’m just following similarly Jessica’s flow.  &lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;It should look like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2F2ndcondition.png" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Screenshot of Condition Action connector" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2F2ndcondition.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now we know if both of those are true we need to send a text message.  Click the ‘Add an action’ button in the True condition and search for Twilio and select the ‘Send a Text Message’ action.  This will add the provided &lt;a href="https://docs.microsoft.com/connectors/twilio/?WT.mc_id=docs-blog-timheuer" rel="noopener noreferrer"&gt;Twilio connector&lt;/a&gt; which provides this functionality (and more).  Similarly like twitter you will see it and after selecting have to authenticate to your account to get the credentials.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Ftwiliosearch.png" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Screenshot of Twilio search for connector" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Ftwiliosearch.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After doing that you now simply enter the details of your text message.  For Twilio the From number must be your account SMS number unless you have premium services that enables you to do something more.  If you try to get fancy without premium services from them, this will fail.  Don’t get fancy…we’re just moving cars across the street remember?  Enter the text you want to send and to the phone number you want to send it to…done!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Ftwilioconfig.jpg" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Screenshot of Twilio connector" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Ftwilioconfig.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now on the false conditions we do still have to tell the Logic App what to do.  In these cases, unless you want to do more, again add an action and choose System, then look for ‘Terminate’ – it’s a simple action that basically just stops the flow and can log a message.  I configured mine like this on BOTH false conditions:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Ffaslecondition.png" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Screenshot of Terminate action connector" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Ffaslecondition.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That’s it, I’m done.  No code.  This took me longer to write this post then it did to actually do the Logic App the first time.  Now I waited.  And waited.  And waited.  I completed the logic app right after reading Jessica’s article and wanted to ‘naturally’ test this with the real deal tweets.  But no parking regulations were suspended.  My logs looked like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Flogs.png" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Screenshot of Azure log files" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Flogs.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UNTIL A FEW DAYS AGO!  My phone buzzed, I looked down and BOOM:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fsms.jpg" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Screenshot of SMS text message stating 'NYC Alt Parking Suspended Tomorrow'" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fsms.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://i.giphy.com/media/BlVnrxJgTGsUw/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Animated GIF image of people happily dancing" src="https://i.giphy.com/media/BlVnrxJgTGsUw/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I wonder if Jessica got a text message too!  I was so happy and I don’t even live in NYC or have to worry about moving my car to a different side of the street!  The logs of Logic Apps are pretty cool as well and also graphically follow your flow and show you input/output state along the way:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fsuccesslog2.png" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Screenshot of Logic App log" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fsuccesslog2.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So with no code and only a few steps to authenticate to Twitter and Twilio, I was able to use only a browser and complete the same task.  Did I win Name That Tune?  Who cares…doing software isn’t a competition, it’s fun and we get to use the tools and technology we feel most productive with.  For me, this was just a gut reaction to see if could be done as easily as I thought and indeed it could.  So yeah I won :-D.&lt;/p&gt;
&lt;p&gt;Check out more about the pieces I used to put this together and get your custom logic apps working:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://azure.microsoft.com/free/?WT.mc_id=freetrial-blog-timheuer" rel="noopener noreferrer"&gt;Azure Account&lt;/a&gt; – get one free&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/azure/logic-apps/?WT.mc_id=docs-blog-timheuer" rel="noopener noreferrer"&gt;Azure Logic Apps&lt;/a&gt; (docs/tutorials)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/connectors/twitter/?WT.mc_id=docs-blog-timheuer" rel="noopener noreferrer"&gt;Twitter connector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/connectors/twilio/?WT.mc_id=docs-blog-timheuer" rel="noopener noreferrer"&gt;Twilio connector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://azure.microsoft.com/services/app-service/?WT.mc_id=docs-blog-timheuer" rel="noopener noreferrer"&gt;Azure App Service&lt;/a&gt; (for the resource group)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/connectors/?WT.mc_id=docs-blog-timheuer" rel="noopener noreferrer"&gt;Over ~200 built-in connectors provided for Logic Apps&lt;/a&gt;!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hope this helps!&lt;/p&gt;

&lt;p&gt;(this article &lt;a href="http://timheuer.com/blog/archive/2019/04/19/how-i-solved-jessicas-nyc-parking-problem-with-twitter-twilio-and-azure.aspx" rel="noopener noreferrer"&gt;cross-posted from timheuer.com&lt;/a&gt;)&lt;/p&gt;

</description>
      <category>azure</category>
      <category>serverless</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Make people trust your NuGet Packages more with code signing!</title>
      <dc:creator>Tim Heuer</dc:creator>
      <pubDate>Fri, 05 Apr 2019 15:58:36 +0000</pubDate>
      <link>https://dev.to/timheuer/make-people-trust-your-nuget-packages-more-with-code-signing-4gfm</link>
      <guid>https://dev.to/timheuer/make-people-trust-your-nuget-packages-more-with-code-signing-4gfm</guid>
      <description>&lt;p&gt;Like most things in life, this all started with someone’s message on Twitter.&lt;/p&gt;

&lt;blockquote data-conversation="none"&gt;
&lt;p&gt;Blogged: Why NuGet Package Signing Is Not (Yet) for Me. &lt;a href="https://t.co/4RSes2Bo4r" rel="noopener noreferrer"&gt;https://t.co/4RSes2Bo4r&lt;/a&gt;&lt;br&gt;A close look at NuGet package signing feature, where it's useful, and in which ways it falls short.&lt;/p&gt;— Boom Haackalacka (@haacked) &lt;a href="https://twitter.com/haacked/status/1113477770284126209?ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;April 3, 2019&lt;/a&gt;
&lt;/blockquote&gt; &lt;p&gt;&lt;em&gt;You can code-sign a NuGet Package?&lt;/em&gt;  I don’t know why I didn’t know that other than I figured I had no idea that I should care or have even given a second thought to it.  But Phil’s article and subsequent discussion on Twitter made me just realize I should take a look at the flow.  After all more sage wisdom from Phil kicked me over the edge:&lt;/p&gt;

&lt;blockquote data-conversation="none"&gt;
&lt;p&gt;There’s no harm to anyone if you do sign your package.&lt;/p&gt;— Boom Haackalacka (@haacked) &lt;a href="https://twitter.com/haacked/status/1113504159376990208?ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;April 3, 2019&lt;/a&gt;
&lt;/blockquote&gt; &lt;p&gt;You’re right Phil, and how can you argue with that forehead…so let’s do this.  &lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;&lt;strong&gt;What is NuGet?&lt;/strong&gt;&lt;/em&gt; NuGet is a package management system that was primarily developed for .NET developers and has now become a de-facto package/release mechanism for that ecosystem.  What npm is to Node.js developers, NuGet is to .NET developers.  More info at &lt;a href="https://www.nuget.org" rel="noopener noreferrer"&gt;https://www.nuget.org&lt;/a&gt;.  &lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I’ve got a little library for helping .NET developers be more productive with creating Alexa apps, &lt;a href="https://www.nuget.org/packages/Alexa.NET/" rel="noopener noreferrer"&gt;Alexa.NET&lt;/a&gt;.  When I started this project I used to just have this on my local box and would build things using Visual Studio and manually upload the NuGet package.  Then people made fun of me.  And I ate my sorrows in boxes of Moon Pies.  Luckily I work with a bunch of talented folks and helped me see the light in DevOps and helped me establish a CI/CD pipeline using &lt;a href="https://azure.microsoft.com/solutions/devops/?WT.mc_id=acom-blog-timheuer" rel="noopener noreferrer"&gt;Azure DevOps&lt;/a&gt;.  Since then I’ve got my library building, a release approval flow, automated packaging/publishing to the NuGet servers.  I simply just check-in code and a new version is released.  Perfect.  Now I just want to add code-signing to the package.  Naturally I do what every professional developer does and Google’d went to read the docs about code signing NuGet packages.  Luckily there is some pretty good documentation on &lt;a href="https://docs.microsoft.com/nuget/create-packages/sign-a-package?WT.mc_id=docs-blog-timheuer" rel="noopener noreferrer"&gt;Signing NuGet Packages&lt;/a&gt;!  &lt;/p&gt;
&lt;p&gt;The first thing you need is a code-signing certificate.  There are many providers of these and different prices so pick your preferred provider.  I chose to use &lt;strong&gt;&lt;a href="https://www.digicert.com" rel="noopener noreferrer"&gt;DigiCert&lt;/a&gt;&lt;/strong&gt; for this one but have used other providers in the past.  The process for getting a code-signing cert is a bit more than just an average SSL certificate so be sure to follow the steps carefully.  Once you have that in place, export the DER and PFX versions as you will need both of these for this process.  Your provider should provide instructions on how to do this for you.&lt;/p&gt;
&lt;p&gt;Next up was to modify my Azure DevOps Pipeline.  I do my NuGet activity in a Release pipeline after a successful build and an approval step to actually complete the deployment.  My simple release pipeline looks like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fnugetsign-initialpipeline.png" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Screenshot of Azure DevOps NuGet Push definition" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fnugetsign-initialpipeline.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The signing is provided by the NuGet CLI and so I just needed to add another task to this flow right?  I added another one in and was going to just choose the ‘sign’ command as the configured option.  Well, the ‘sign’ command isn’t a selectable option in the task.  There is a &lt;a href="https://github.com/Microsoft/azure-pipelines-tasks/issues/7386?WT.mc_id=github-blog-timheuer" rel="noopener noreferrer"&gt;request to make this one of the default options for the Azure Pipeline Task&lt;/a&gt; right now but it isn’t in there yet.  So for this we will use the ‘custom’ option which allows us to pass in any command and args.  The docs already told me the commands that I would need: a certificate file being the minimum I would have to have.  Hmm, how am I going to have a certificate file in my CD pipeline?!  As it turns out there is a &lt;a href="https://docs.microsoft.com/azure/devops/pipelines/library/secure-files?view=azure-devops&amp;amp;WT.mc_id=docs-blog-timheuer" rel="noopener noreferrer"&gt;secure file storage in Azure Pipelines&lt;/a&gt; I can use! This allows me to upload a file that I can later reference in a pipeline using an argument.  Remember that PFX file we exported?  In your DevOps project under Pipelines there is a ‘Library’ menu option.  Going there takes you to where you can upload files and I uploaded my PFX file there:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fnugetsign-securefiles.png" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Screenshot of Azure DevOps Library" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fnugetsign-securefiles.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The next thing I need to do is also provide my password for that exported PFX file (you did export it with a password right!).  To do this I made use of &lt;a href="https://docs.microsoft.com/azure/devops/pipelines/library/variable-groups?view=azure-devops&amp;amp;tabs=yaml&amp;amp;WT.mc_id=docs-blog-timheuer" rel="noopener noreferrer"&gt;variable groups&lt;/a&gt; in Azure DevOps, created a group called CertificateValues and added my name/value pair there, marking the value as a secret.  As a variable group I can ‘link’ this group to any build/release definition without explicitly having the variable in those definitions.  This is super handy to share across definitions.  You can now &lt;a href="https://docs.microsoft.com/azure/devops/pipelines/library/variable-groups?tabs=yaml&amp;amp;amp;%3Bview=azure-devops&amp;amp;view=azure-devops&amp;amp;WT.mc_id=docs-blog-timheuer#link-secrets-from-an-azure-key-vault" rel="noopener noreferrer"&gt;link to an Azure KeyVault&lt;/a&gt; for secrets (more to come on that in a part 2 blog post here).  I’ve got my code signing cert (PFX) and my certificate password stored securely.  With these two things now I’m ready to continue on my definition.&lt;/p&gt;
&lt;p&gt;Now how will I get the file from the secure storage?!  As I read in the docs, there is a &lt;a href="https://docs.microsoft.com/azure/devops/pipelines/tasks/utility/download-secure-file?view=azure-devops&amp;amp;WT.mc_id=docs-blog-timheuer" rel="noopener noreferrer"&gt;Download Secure File&lt;/a&gt; task that I can add to my pipeline.  The configuration asks me what file to use and then in the Reference Name of the Output Variables area I give it a name I can use, in this case ‘Certificate’:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fnugetsign-downloadfile.png" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Screenshot of Azure DevOps Download Secure File" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fnugetsign-downloadfile.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This variable name allows me to use it later in my definitions as $(Certificate.secureFilePath) so I don’t have to fiddle around guessing where it downloaded to on the agent machine.  Now that we have that figured out, let’s move back to the signing task…remember that ‘custom’ one we talked about earlier.  In the custom task I specify in the Command and Arguments section the full command + arguments I need according to the docs.  My full definition looks like this:&lt;/p&gt;

&lt;pre&gt;sign $(System.ArtifactsDirectory)\$(Release.PrimaryArtifactSourceAlias)\drop\*.nupkg 
    -CertificatePath $(Certificate.secureFilePath) 
    -CertificatePassword $(CertificatePassword)  
    -Timestamper http://timestamp.digicert.com
&lt;/pre&gt;
&lt;p&gt;To explain a bit I’m using some pre-defined variables System.ArtifactsDirectory and Release.PrimaryArtifactSourceAlias to help build the path to where the drop folder is on the agent machine.  The others are from the secure files (Certificate.secureFilePath) and variable group (CertificatePassword) previously defined.  These translate to real values in the build (the secret is masked in the logs as shown below) and complete the task.  &lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fnugetsign-finaldefinition.png" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Screenshot of Azure DevOps release definition" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fnugetsign-finaldefinition.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here was my log output from today in fact:&lt;/p&gt;

&lt;pre&gt;2019-04-04T19:10:44.4785575Z ##[debug]exec tool: C:\hostedtoolcache\windows\NuGet\4.6.4\x64\nuget.exe
2019-04-04T19:10:44.4785807Z ##[debug]arguments:
2019-04-04T19:10:44.4786015Z ##[debug]   sign
2019-04-04T19:10:44.4786248Z ##[debug]   D:\a\r1\a\_Alexa.NET-master\drop\*.nupkg
2019-04-04T19:10:44.4786476Z ##[debug]   -CertificatePath
2019-04-04T19:10:44.4786687Z ##[debug]   D:\a\_temp\timheuer-digicert.pfx
2019-04-04T19:10:44.4786916Z ##[debug]   -CertificatePassword
2019-04-04T19:10:44.4787190Z ##[debug]   ***
2019-04-04T19:10:44.4787449Z ##[debug]   -Timestamper
2019-04-04T19:10:44.4787968Z ##[debug]   http://timestamp.digicert.com
2019-04-04T19:10:44.4789380Z ##[debug]   -NonInteractive
2019-04-04T19:10:44.4789939Z [command]C:\hostedtoolcache\windows\NuGet\4.6.4\x64\nuget.exe sign D:\a\r1\a\_Alexa.NET-master\drop\*.nupkg -CertificatePath D:\a\_temp\timheuer-digicert.pfx -CertificatePassword *** -Timestamper http://timestamp.digicert.com -NonInteractive
2019-04-04T19:10:52.6357013Z 
2019-04-04T19:10:52.6357916Z 
2019-04-04T19:10:52.6358659Z Signing package(s) with certificate:
&amp;lt;snip to remove cert data&amp;gt;
2019-04-04T19:10:52.6360408Z Valid from: 4/4/2019 12:00:00 AM to 4/7/2020 12:00:00 PM
2019-04-04T19:10:52.6360664Z 
2019-04-04T19:10:52.6360936Z Timestamping package(s) with:
2019-04-04T19:10:52.6361268Z http://timestamp.digicert.com
2019-04-04T19:10:52.6361576Z Package(s) signed successfully.
&lt;/pre&gt;
&lt;p&gt;Done!  Some simple added tasks and reading a few docs to get me having a signed NuGet package.  Now re-reading the docs on signed packages I have to upload my certificate to my NuGet profile to get it to be recognized.  This time I only need to provide the DER export.  Once provided and my package is published, I get a little badge next to the listing showing me that this is a signed package:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fnugetsign-versionlistingbadge.png" class="article-body-image-wrapper"&gt;&lt;img title="" alt="Screenshot of NuGet version history listing" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage2.timheuer.com%2Fnugetsign-versionlistingbadge.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This was a good exercise in helping me learn a few extra steps in Azure DevOps working with files and custom task variables.  Immediately as I was doing this, my friend &lt;strong&gt;&lt;a href="https://twitter.com/onovotny" rel="noopener noreferrer"&gt;Oren Novotny&lt;/a&gt;&lt;/strong&gt; couldn’t help but chastise me for this approach.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I am&lt;/p&gt;— Oren Novotny (@onovotny) &lt;a href="https://twitter.com/onovotny/status/1113549506551996418?ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;April 3, 2019&lt;/a&gt;
&lt;/blockquote&gt; &lt;p&gt;So stay tuned for a secondary approach using &lt;strong&gt;&lt;a href="https://azure.microsoft.com/services/key-vault/?WT.mc_id=acom-blog-timheuer" rel="noopener noreferrer"&gt;Azure KeyVault&lt;/a&gt;&lt;/strong&gt; completely to complete this without having to upload a certificate file.&lt;/p&gt;
&lt;br&gt;&lt;br&gt;&lt;p&gt;(this article &lt;a href="http://timheuer.com/blog/archive/2019/04/04/signing-nuget-package-using-azure-devops-pipelines.aspx" rel="noopener noreferrer"&gt;cross-posted from timheuer.com&lt;/a&gt;)&lt;/p&gt;

</description>
      <category>devops</category>
      <category>azure</category>
      <category>dotnet</category>
      <category>security</category>
    </item>
  </channel>
</rss>
