Dogs Chasing Squirrels

A software development blog

Tag Archives: TFS

Setting up a TFS 2017 Build Server’s Account

0

We have an on-premises TFS 2017 server with the package management plugin installed to host custom NuGet packages.

I happily set up TFS builds of my solution. I happily set up custom NuGet packages. Then I ran a build of a solution that made use of my custom packages. Imagine my surprise when the TFS build server was unable to download packages from its own TFS server! Furthermore, the error code was the rarely-seen “402 Payment Required”.

Now, it turns out that Package Management generally requires licenses. This hadn’t mattered because it’s free for Visual Studio Enterprise subscribers, which we all have through MSDN. The build server, however runs under its own service account which naturally doesn’t have an MSDN subscription.

How to have the build server run as a user with an MSDN subscription? After a support call, a guy from Microsoft helped me figure it out. Here it is for everybody with the same problem (and, for me, when the solution below expires in a year).

The solution

Basically, the solution is to get the build server to run under the Personal Access Token (PAT) of a user with an MSDN license.

Step 1. Generate a Personal Access Token

If you log into TFS 2017, in the corner under the settings there’s an “Access Tokens” setting.

Click “Add”.

Create a token. I made mine for a year, ensuring I would forget all this by the time it expires and that a year from now I’ll be confounded when all my builds break.

The personal access token will be a long string. Save it somewhere temporarily.

Step 2. Configure the build agent to use the PAT

If you already have the build agent set up, you’re going to have to remove it. Go to the folder and run:

.\config.cmd remove

It’s safest to delete the whole folder and recreate it from the Agent you downloaded from TFS. Until I removed the folder entirely this fix failed.

Once you’ve recreated the server, type

.\config.cmd

from PowerShell to start the process again.

This time, when it gets to “Enter authentication type (press enter for Integrated)” enter “PAT”.
It will ask you for the token. Enter the long string you got above.
Continue as normal.

Other Gotchas

The server will download NuGet packages with the license you’ve set up above but with the authorization of the user that the server is running as. If you find you’ve traded “Payment Required” for “Unauthorized”, make sure the build agent user has access as a package reader in Package Management’s Security settings.

TFS team adding colorizer features

0

It looks like the TFS team are adding colorization features to the TFS board. Hopefully this will make my colorizer plugin obsolete.

TFS Colorizer Stats

9

colorizer - chrome stats

As a developer, I can see some statistics about how my plugins are doing.  The Chrome extension is actually doing pretty well.  It’s getting about 11 downloads a week which is pretty good given that I haven’t really promoted it anywhere.

TFS Colorizer in the FIrefox Review Queue

My Firefox add-in is still in review.  When I submitted it to Mozilla almost two weeks ago I was asked if I wanted the 3-day preliminary review or the 10-day full review.  I picked the quick 3-day review.  you wouldn’t know it.  I moved from 57th place yesterday to 54th today.  Maybe they’re all watching the World Cup.  Maybe they’re in the World Cup.  Who knows.

TFS Colorizer Extension for Firefox

0

tfspreview

At least one of my colleagues uses Firefox, so I created the TFS colorizer as a Firefox extension.

The extension uses the new Firefox Add-On SDK.  Specifically, the extension uses the page-mod API to detect when a TFS board-like page is being displayed and then applies modifications to it.  I found it more difficult to create the extension for Firefox than I did for Chrome.  There were two tricky parts:

Options

There is no easy way to create a nice Options page with the Add-On SDK.  There’s a way to create an ugly one: the simple-prefs API.  It can list out some settings easily, but that’s not what I want.

In the end, I had to create a toolbar button and have that launch my options page.  This code sets up the button in the action bar and opens the options page when it’s clicked.  There’s some code in there to make sure the tab is only ever opened once.

var button = buttons.ActionButton( {
	id: "colorizer-options",
	label:	"TFS Colorizer",
	icon: {
		"16": "./icon_16.png",
		"32": "./icon_32.png",
		"64": "./icon_64.png"
	},
	/**
	 * This is called when our toolbar button is clicked.
	 */ 
	onClick: function ( state ) {
		try {
			// Get the options URL
			var url = self.data.url( "options.html" );
			// For each open tab...
			for ( var i = 0; i < tabs.length; i++ ) {
				var tab = tabs[i];
				// If this is our options tab...
				if ( tab.url == url ) {
					// Activate the tab
					tab.activate();
					// We're done
					return ;
				}
			}
			// We didn't find the options page open, above, so open it.
			tabs.open( url );
		} catch ( e ) {
			console.error( e.message );
		}
	}
});

I would have preferred that this show up in the Add-Ons “Options” sections since my extension doesn’t really require a button cluttering up the toolbar, but I didn’t see a better way.

Accessing Storage

Getting the user’s settings in and out of storage was also a trial.  In Firefox add-ons, you have two types of javascript files:

  • lib/main.js: the main entry point to the add-on.  This has access to the add-on APIs, such as the ones that store data, but does not have access to the browser page.
  • data/*.js a.k.a. content scripts: These have access to the browser page but they don’t have access to the APIs.

So you have a script that can load and store your user settings but won’t affect the page and a script that runs on the page but can’t access the user settings.  How to communicate between the two?  What I ended up using, and this was from the documentation, was the “port.on” and “port.emit” functionality to pass data between the two in a request/response model.  When the content page wanted to load settings from file, it would make a request via:

// Load settings
self.port.emit( "loadSettingsRequest", null );

Main.js would catch that request and issue a response:

pageMod.PageMod( {
	include: self.data.url( "options.html" ),
	contentScriptFile: [
		self.data.url("jquery-2.1.0.min.js"),
		self.data.url("common.js"),
		self.data.url("options.js")
	],
	contentScript: "TfsOptions.initialize();",
	onAttach: function (worker) {
		worker.port.on( "loadSettingsRequest",  function () {
			// Pull the settings from storage
			var json = ss.storage.settings;
			// Parse the json
			var settings;
			if ( null != json ) {
				settings = JSON.parse( json );
			} else {
				settings = null;
			}
			// Send the response
			worker.port.emit( "loadSettingsResponse", settings );
		} );

The content page would catch the response and take action:

self.port.on( "loadSettingsResponse",  function ( settings ) {
	try {
		// If the settings are null, use the defaults
		if ( null == settings ) {
			settings = TfsDefaults.defaultSettings;
		}
		// Populate the table with the settings
		TfsOptions.populateTable( $table, settings );
	} catch( e ) {
		console.error( e.message );
	}
} );

Note that in order to use the port.on/emit code, the content script uses “self” and the main script uses “worker”.  With these two things worked out, the rest was pretty straightforward and I was able re-use most of the existing code.

The code for the FireFox add-on is up on github.  I’m trying to get the extension into the Mozilla add-ons repository.  It’s currently undergoing their review process.

TFS Colorizer extension for Google Chrome

15

TFS Colorizer extension for Google Chrome

We use Microsoft’s Team Foundation Server at work.  It has a task board showing the development, testing, documentation, and other tasks that go into a release as cards in “Not Started”, “In Progress”, or “Done” columns.  The idea is to let you see the status of your project at a glance, but all the cards are the same color.  What’s the status of the release?  Are we waiting on development?  Testing?  UAT?  You can’t tell without reading every card title.  It would be better if, say, all development tasks were in green, all testing tasks were in orange, and all development tasks were in yellow.  Is the “Not Started” column filled with mostly green?  Yes?  Then we’re still waiting for development.  When we see the “Done” column filling up with green and the “In Progress” columns filling up with orange, we know we’ve entered the testing phase.  If you can colorize the cards on the board, you can see the status of your project at a glance.

That’s what this plugin does.  It lets you associate card colors with text contents.  If the card title starts with “Analysis” it’s red.  If it contains “Testing”, it’s orange, and so on.  It makes the TFS board far, far more useful.

Download the plugin here: TFS Colorizer

The code is up on github.