Monday, May 18, 2015

Bookmarking future reading

A co-worker was passing around a link to a Mozilla document that provides A re-introduction to JavaScript and I don't want to lose the link. It looks to be a thorough article - which requires more time than I can currently dedicate to it, hence the bookmark post.

Nothing to read here, citizen. Move along.

Friday, April 3, 2015

Adventures (and frustrations) in NuGet package creation

I'm frustrated.

And disappointed.

Frustrated and disappointed. But more knowledgeable.

I spent a good part of today trying to get our CI build to create our NuGet packages so the resulting packages list their dependencies without developers having to manually edit the .nuspec file unless they have to. Unfortunately, I've failed, but I know a little more about how to interact with our TeamCity installation and the nuget pack command.

What I learned was that our build process invokes the nuget pack command which creates the package. Reviewing the documentation for that command I read about the IncludeReferencedProjects option which is described as doing the following:
Include referenced projects either as dependencies or as part of the package. If a referenced project has a corresponding nuspec file that has the same name as the project, then that referenced project is added as a dependency. Otherwise, the referenced project is added as part of the package.
"This is great!" I thought, "The solution I'm currently working on has project references that met that description. I won't have to explicitly declare the dependency."

What I was trying to do

Maybe a brief note about the solution is in order. It's for a WebAPI and has several projects in it, not all of which are published as NuGet packages. The projects are:
  • MyApp 
  • MyApp.Application
  • MyApp.Api
  • MyApp.Api.WebHost
  • MyApp.Repository
With the exception of MyApp.Api they each result in a NuGet package.  Mainly because even though we're moving to have all calls go through the MyApp.Api.WebHost which is the package that's automatically deployed to the web servers, there are some older projects that continue to need access to MyApp, MyApp.Application and MyApp.Repository.

As you would guess, there are project references between some of the projects. For example, MyApp.Api.WebHost references MyApp, MyApp.Application and MyApp.Repository. What we've been doing is modifying the web host project's .nuspec file to declare the dependencies on MyApp, MyApp.Application and MyApp.Repository.

What I tried

Given this configuration I thought the IncludeReferencedProjects option would allow us to only declare package dependencies that existed outside the solution.

So I sat with a co-worker who is very knowledgeable about the TeamCity templates we have. He showed me the how to include that option on the build step which creates the NuGet package. We copied the template to a temporary one to test with, added the option, associated the MyApp build to that template, modified the .nuspec file to remove the explicit package dependency declarations, committed the code, and sat back to see the results.

It didn't work.

The resulting nupkg file doesn't list the dependencies. We then modified the way nuget was run to turn up the verbosity (-Verbosity detailed) and ran it again to see if we learned anything useful. All we saw in our build log was [pack] Dependencies: None. Then my co-worker noticed in the pack command examples that in addition to running nuget pack against the .nuspec file you can also run it against the .csproj file. So we tried that. That change resulted in a number of failing builds because the .csproj files had references to Visual Studio 10 and we're using VS2013 - doesn't make a difference to MSBuild because it knows what version it is, and it didn't matter to nuget pack when we targeted the .nuspec file (presumably because it didn't need it) but when we target the .csproj file it broke. So we changed the project files so:
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
became
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">12.0</VisualStudioVersion>

and
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
became
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v12.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />

Neither of these changes fixed the problem. We were continuing to see an error that read:
[pack] Microsoft.Build.Exceptions.InvalidProjectFileException: The imported project "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" was not found. Confirm that the path in the declaration is correct, and that the file exists on disk.  [the path to my .csproj file]
[pack]    at Microsoft.Build.Shared.ProjectErrorUtilities.ThrowInvalidProject(String errorSubCategoryResourceName, IElementLocation elementLocation, String resourceName, Object[] args)
[pack]    at Microsoft.Build.Shared.ProjectErrorUtilities.ThrowInvalidProject(IElementLocation elementLocation, String resourceName, Object arg0)
[pack]    at Microsoft.Build.Evaluation.Evaluator`4.ExpandAndLoadImports(String directoryOfImportingFile, String importExpressionEscaped, ProjectImportElement importElement)
[pack]    at Microsoft.Build.Evaluation.Evaluator`4.EvaluateImportElement(String directoryOfImportingFile, ProjectImportElement importElement)
[pack]    at Microsoft.Build.Evaluation.Evaluator`4.PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
[pack]    at Microsoft.Build.Evaluation.Evaluator`4.Evaluate()
[pack]    at Microsoft.Build.Evaluation.Evaluator`4.Evaluate(IEvaluatorData`4 data, ProjectRootElement root, ProjectLoadSettings loadSettings, Int32 maxNodeCount, PropertyDictionary`1 environmentProperties, ILoggingService loggingService, IItemFactory`2 itemFactory, IToolsetProvider toolsetProvider, ProjectRootElementCache projectRootElementCache, BuildEventContext buildEventContext, ProjectInstance projectInstanceIfAnyForDebuggerOnly)
[pack]    at Microsoft.Build.Evaluation.Project.ReevaluateIfNecessary(ILoggingService loggingServiceForEvaluation)
[pack]    at Microsoft.Build.Evaluation.Project.Initialize(IDictionary`2 globalProperties, String toolsVersion, String subToolsetVersion, ProjectLoadSettings loadSettings)
[pack]    at Microsoft.Build.Evaluation.Project..ctor(String projectFile, IDictionary`2 globalProperties, String toolsVersion, String subToolsetVersion, ProjectCollection projectCollection, ProjectLoadSettings loadSettings)
[pack]    at NuGet.Commands.PackCommand.BuildFromProjectFile(String path)
[pack]    at NuGet.Commands.PackCommand.BuildPackage(String path)
[pack]    at NuGet.Commands.PackCommand.ExecuteCommand()
[pack]    at NuGet.Commands.Command.Execute()
[pack]    at NuGet.Program.Main(String[] args)
[pack] Process exited with code 1


For some reason neither of us understood, the project file was still looking for version 10, even though the file on the build server had version 12 specified. We decided to change the way nuget pack was being called to include the property assignment of the VisualStudioVersion (-Properties Configuration=Release;VisualStudioVersion=12.0).

This got us a successful build and the resulting nupkg file started listing our dependencies as expected.

So the IncludeReferencedProjects option only appears to work when nuget pack targets the project file.

Short lived victory lap

After high fives all around we set about changing the real template for our CI builds. Once that was done we kicked off builds for the projects which used that template. What we found was that even with the changes we made related to the VisualStudioVersion, in both the properties passed from the nuget pack command and the project files, some of the builds kept failing because the version being sought was v10 not v12.

Observations before reverting

What we noticed was the problem seemed to occur when project A.1 was being packed but project A.1 referenced A.2 and the import line that was causing the exception was in project A.2.  For example, during the pack of project MyApp.Account.Api.WebHost the exception line was
[pack] Microsoft.Build.Exceptions.InvalidProjectFileException: The imported project "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" was not found. Confirm that the path in the declaration is correct, and that the file exists on disk.  F:\Agent\Work\3b114de58491d1e6\src\MyApp.Account.Api\MyApp.Account.Api.csproj

At this point we got stumped because all the project files had the hard coded v12.0 value. Somehow the import is being given the wrong path. We can't find the cause of it and after a half day we had to move on.

Appeal for advice

If anyone knows how we might successfully revisit this and work past the problems; either by telling us why the IncludeReferencedProjects option wasn't working from the .nuspec file or explaining what we have to do related to the VisualStudioVersion, (or something else we're not seeing that you know of) it would be appreciated. Tweet me.

Tuesday, March 24, 2015

"Coding like a Girl" - great read!

Last night I had the pleasure of attending the second anniversary party for the Girl Develop It! Burlington, VT chapter. It was a chance to see some friends I've made through the local developer community, meet some people in our industry who were new to me, and reconnect with a few of the people who I met the handful of times I was a TA for a GDI event. At one point a conversation I was involved in turned to the challenges of being a technical professional who chooses to dress in a more feminine manner. It was amazing to listen to these accomplished professionals discuss how their choice of outfit would, in many cases, predict how they would be received. At that point Kathleen Dollard recommended a blog post entitled "Coding Like a Girl".

I read it this morning and believe it is worth sharing. The anecdote shared in the post about the experience Tracy Chou, an engineer at Pinterest, had at a technical conference was facinating:
A couple years ago she attended a technical conference and on the first day, she wore a dress. When she walked around the conference, no one came up to talk to her. When she asked people very technical questions about their stack, questions she assumed would indicate that she was a programmer, she was brushed aside and told, “You wouldn’t understand.” She went back home that night really frustrated and flustered. She almost didn’t feel like going to the conference the next day. But she did and wore a nerdy tshirt and jeans instead, and she had a better experience that day. People assumed she was technical and didn’t dilute their explanations to her.
That an industry peer had to change her appearance in order to be taken seriously is disappointing to me as a guy - as a woman it must be infuriating.

I like to think I do a decent job when dealing with folks, I'm reasonably self aware. Yet I know there have been a few times where I've judged other guys who come to a tech event dressed in a suit and assume they're sales people and not "real" technical folks. If I've done that to another guy - with whom I have more in common - what biases do I have around a woman's appearance? Have they colored my interactions with anyone?

We can only do our best, I suppose. I'm going to try and be more aware of my own biases when it comes to appearance and adopt the advice offered in the post, "Assume people are as or more qualified than you" regardless of their appearance. I hope that you take a few minutes to read the blog post, too.

Saturday, March 14, 2015

A very important read for software professionals

Alan Stevens has a blog post that I think is a very important read for anyone who is a software professional. I think that this is an especially useful read for developers just entering the field. Do yourself a favor and take the time to read this.

Friday, February 6, 2015

Creating Visual Studio Templates

I spent most of yesterday creating a solution template for Visual Studio 2013 so our developers can begin a project with about an hour's worth of plumbing already done for them. It was an interesting task and one that gave me a lot of satisfaction having completed.  I like knowing that I've reduced developers' time for a 1 hour task to 5 minutes (more on why it's not less than that shortly).

First, there were a few links that proved invaluable:
The process I followed consisted of creating a solution that I was going to use as a reference point. It had all the projects, folders, classes, dependencies, etc. set up. Then I exported each project as a template and went through each one making sure my parameter substitutions were in place. I then tested each individual project template to ensure they behaved as expected. Finally, I hand-rolled a multi-project template that tied them together.  That part was simple enough.

Where I started to hit a snag was that the multi-project template behavior creates a sub-folder for the first project and within that a sub-folder for each project (rather than having the project folders all created as peers of the *.sln file). There doesn't appear to be a way to change that behavior, which is unfortunate, because it prevents NuGet dependencies from working properly.  So while the template creates everything in a matter of seconds, the developer then has to close Visual Studio, relocate five folders to the correct location and edit the *.sln file.  That's why the template only saves 91.5% of a developers time rather than 99.8%.

Still pretty good, though.

Wednesday, January 14, 2015

Getting to a command prompt from Windows Explorer

Many years ago there was a utility I had installed on my Windows95 or Windows NT box that added an item to the context menu of Windows Explorer allowing me to open a command window with the folder I had in focus as the working directory. Somewhere along the line between Windows Vista and Windows 7 (my current OS) that utility stopped working. I never followed up to find it again and got along without it - though I would miss it from time to time.

Last week a co-worker made me aware that functionality is available in Windows 7, but it's slightly hidden. I have no idea how long it's been an option but am very happy to know about it - and I like to share what makes me happy.

Normally, if you right-click on a folder in Windows Explorer you get the context menu. Here's a shot of what mine looks like:
Context menu
Context Menu

Yours probably looks similar. But what my co-worker pointed out was that if you hold down the shift key when you do the right-click the menu includes an extra item:
context menu after shift key is held down
Context Menu, now with shift key

I have no idea why this isn't just part of the regular context menu, but I'm happy to know it's there now.

Wednesday, December 10, 2014

On the heels of our recent WTF.JS session

Our most recent meeting at the VT .NET user group was a series of lightening talks covering different JavaScript frameworks. Today I was directed to TodoMvc which is a site where the same application has been implemented multiple times using different MV* JavaScript frameworks. It allows developers who are considering the various (and numerous) options to "kick the tires" and see which approach might work best for them.

Neat!