How to Command TFS with npm Scripts

How to Command TFS with npm Scripts

Automating your source control

In my article ‘Script the Pain Away’ I explained how I use npm scripts in my build process. But there is one other thing I have been struggling with for some time. And that is the communication between TFS and my scripts. In this article, I will explain what I have done to make peace between these two.

The Problem

In my company, we are using an older version of Team Foundation Server where local workspaces were not yet available. So the only option is to use server workspaces. This means files need to be checked out before writing to them. And when we are using npm scripts to update the version, this script will fail with a permission error.

What are you going to do when you don’t have one of those fancy distributed version-control systems that all the cool kids are talking about?

Integration with TFS

Since I’m using Visual Studio and it plays well with TFS, I started looking if Visual Studio has some tools to help us. And it ships with the command line tool tf.exe.

You can use version control commands to do nearly all tasks you can do in Visual Studio, and also several tasks that can’t be done in Visual Studio. You can use the tf.exe tool to run version control commands from a command prompt or within a script.

If we can call tf from the npm scripts, we might be able to solve our problem.

Config

We can add configuration parameters to the config section of package.json. Then we can call these in the scripts by prefixing with npm_packageconfig. Let’s add the path to the tf.exe tool to config.

"config": {
  "tf": "\"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Professional\\Common7\\IDE\\CommonExtensions
\\Microsoft\\TeamFoundation\\Team Explorer\\tf\""
}

Now we can call tf.exe in our scripts with $npm_package_config_tf and the command we need like checkout or add. For example, if we want to check out package-lock.json we can use:

$npm_package_config_tf vc checkout package-lock.json

We can run the command ‘tf vc help’ to list the available commands.

Hooks

Npm scripts come with pre- and post-hooks that sometimes are very handy. As the names suggest pre runs before and post runs after the script with the corresponding name.

I will use the pre-hook to check out package-lock.json before every install so that I don’t run into: npm WARN saveError EPERM: operation not permitted

"preinstall": "$npm_package_config_tf vc checkout package-lock.json"

Like this blog post? Share it on Twitter! 🐦

Combining Tasks

  • | pipes the results from one task to the next.
  • || Runs if the task before fails.
  • && Runs if the task before is successful.
  • & Runs tasks concurrently

What if we want to use this kind of script locally, but it is part of our production build? We don’t want to exit the build process, and we don’t want to install Visual Studio on the build server.

Photo by [Mark Eder](https://cdn.hashnode.com/res/hashnode/image/upload/v1618075373116/pvbD7uKhO.html) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)Photo by Mark Eder on Unsplash

Well, we can add || (double pipe) to our script which means that this script will only run if the first one fails. This is like using the double pipe for default values in JavaScript.

Using the double pipes, we can change our script to:

"preinstall": "$npm_package_config_tf vc checkout package-lock.json || npm -v",

Now if the command on the left side of the pipes fails, we will not exit but run the command on the right side. In this case, we output the version of npm.

VS Code

There is at least one more caveat when working with a more mature TFS server. Since VS Code only supports local workspaces, it will make life harder if you try to use it. I have not been able to get VS Code and my source control to work in tandem, so I have resigned and am working in Visual Studio.

If someone knows of a way to work in VS Code, please comment below. 🙏

Wrapper

Now everything works, but it feels a bit dirty. If people have different versions of Visual Studio the config parameter will not work. We should probably wrap this thing somehow. But let’s first see if somebody already did this.

The first package I find when searching on www.npmjs.com is called TFS and says it’s a NodeJS wrapper for TFS command line tool. Sounds like exactly what we are looking after. Not that many weekly downloads but the last publish was not too long ago so looks like its still alive. Let’s try it out!

We could either install it globally or add it to the devDependencies.

npm install -g tfs

And now we can change our preinstall script to:

"preinstall": "tfs checkout package-lock.json || npm -v"

The file is still checked out like with the config variable so we can use this package instead.

Add file

Another use case I needed to solve was adding a file to source control. When creating a library, a new library package is created. This ‘tgz-file’ is going to be used by other projects, so we need to add it to a package folder in our source control.

Run ‘tfs help’ for available commands. And the first command ‘tfs add’ is what we are looking for:

add [itemspec] [options]: Adds files and folders to version control.

This means we can add the script tfs add library.tgs after we have built and packed our library to add it to our source control.

Wrapping Up

I hope you picked up something useful from this article. Things you might have learned include but are not limited to:

  • Npm scripts can be used for source control.

  • Tf is a handy tool in Visual Studio.

  • There are npm packages for many many things.

  • VS Code does not support server workspaces.

Call to Action

I always enjoy feedback so please 👏, 📝 and tweet 🐦. Follow me on Twitter and Medium for blog updates.

Did you find this article valuable?

Support Michael Karén by becoming a sponsor. Any amount is appreciated!