Cross-cutting Tip #2

Pin pac in a tool manifest, and stop trusting the pac on your PATH

Installing the Power Platform CLI into a .NET tool manifest pins the version, so the pac your pipeline runs is the pac you tested.

The pac CLI packs your solutions, unpacks them and imports your environment variables. On most machines, the version that runs is whichever one you installed last.

dotnet new tool-manifest and dotnet tool install Microsoft.PowerApps.CLI.Tool change that. They put a manifest into version control, and every machine and pipeline then runs the same build through dotnet tool restore. The entry carries the version and "rollForward": false, and that pair holds: I pinned a manifest to 2.11.2 with 2.13.1 already installed on the same box, and dotnet tool run pac help still reported 2.11.2.

Here is what bit me on the way to a pin that works.

The manifest is not where the guides put it

Every guide says .config/dotnet-tools.json. On .NET SDK 10.0.400, dotnet new tool-manifest writes dotnet-tools.json into the current directory instead - your repository root. Both layouts restore, and restore walks upwards, so a root manifest is still found from a subdirectory.

If you end up with both files, .config/dotnet-tools.json is the one that wins. Edit the root copy and nothing changes.

And when there is no manifest anywhere, the command does not fail. It prints Cannot find a manifest file. The list of searched paths:, lists every path it looked in, and exits 0. Your pipeline step passes, having restored nothing.

The version check that breaks a build

pac --version looks harmless. It prints the banner, then Error: Not a valid command. Try running 'pac [command] help'. and exits 1 - a red build from the most innocent-looking line in the script.

pac help exits 0 and carries the same Version: line.

dotnet tool run pac --help is worse than either. The .NET tool runner takes --help for itself, prints its own usage and exits 0, so the step passes and never mentions pac.

A pin the feed does not carry

Point the manifest at a version NuGet does not have and dotnet tool restore fails: Version 2.12.0 of package microsoft.powerapps.cli.tool is not found in NuGet feeds. After that pac will not run at all - Run "dotnet tool restore" to make the "pac" command available.

Fix the version in the file and run dotnet tool restore, or let dotnet tool install Microsoft.PowerApps.CLI.Tool rewrite the entry to the newest version for you. The pipeline stops either way, which is what you want - but the message names the version and not the file you have to edit.

The second pac on your machine

A global install is a second pac, and it is the one your shell finds first. With 2.11.2 installed globally while the manifest pinned 2.13.1, which pac pointed at ~/.dotnet/tools/pac and a bare pac help reported 2.11.2. A step that types pac ... gets that one. Only dotnet tool run honours the manifest.

What this install does not have

pac data is not a command in the .NET Tool build at all - Error: Not a valid command. The package group it does have is init, add-external-package, add-solution, add-reference, deploy and db-sync, with no show. The vendor’s install matrix puts those behind the Windows MSI or the VS Code extension. A manifest pins pac; it cannot add commands.