Tag: Jenkins

Getting Started With Chocolatey 4 Business & Jenkins CI

I’ve had an argument with a colleague quite recently about the usage of open-source automation tools, especially Chocolatey in business environments. A keypoint of this argument was the integration of new/open tools in long-existing, mostly commercial software based workflows.

One of the main reasons to use Chocolatey in corporate environments is its ability to integrate seamlessly with already existent automation infrastructure. I’ve been able to integrate Chocolatey successfully with Jenkins CI, Finalbuilder, corporate internal windows services as well as simple ‘installer-batch-files’, a friend and coworker (flurl) is deploying a corporate internal management solution with Chocolatey.

The day I replaced the multi-100 line content of a legacy batch installer with a single line of

choco install {package} -y

was a really good day 🙂

In this blogpost I’m going to give you an idea of how you could get started with Chocolatey at your organization concerning two parts: a possible way to roll-out Chocolatey to your coworkers and a small collection of things to get started integrating Chocolatey with a CI-server (Jenkins, but probably applicable to anything else that does support PowerShell).

Deploying Chocolatey At Your Organization

You’ll want to make it as easy as possible, hence putting a .bat-file on a network share that’s accessible from everywhere in your org is probably a good idea.
If you’re just getting started with Choco I’d also suggest putting your first packages on such a share.
Let’s assume following share-layout:

  • \\your-server\Choco\install
  • \\your-server\Choco\packages

Go to https://chocolatey.org/packages and fetch the latest Chocolatey.nupkg file. Put that file together with this install.ps1 and this install.bat onto the Choco/install share.

You need to adapt the URLs and UNC-paths to the scripts inside the files to make them work in your environment.
Now you’re good to go, just double-click on install.bat from any machine and Chocolatey will be ready to use.
Notice that the community repository is removed during the installation progress and another (internal) repository is set up. For details on how this is done, check the contents of install.ps1.

Your First Packages

Doing a

choco list
now looks pretty boring, because there are no packages at your feed yet (the community repository has already been removed for corporate usage), so go ahead and download some .nupkg-Files from https://chocolatey.org/packages and put them into your  prepared network share.

Now you should be able to list the available packages with ‘choco list’, search for packages with ‘choco search’ and install packages with ‘choco install’.

Of course you can also create your own packages, just type

choco new {package name}
and see what happens.

So far, you’ve only been using OSS features, and you can use all this without limitation in a corporate environment, but there are some things you may need to consider: the packages you’ve pulled in from https://chocolatey.org probably rely on downloading external resources like .exe, .MSI or .zip files. You don’t want to do that in an organization, as you’ll want to have complete reliability in your solution, and downloading from the internet could have reliability issues (not to mention trust). There’s two options: manually download the required resources, changing the source code of the packages install.ps1 and repackage every single one of the required packages, or you could simple use package internalizer.

Package Internalizer

The best of the pack. If you’re using Chocolatey in a corporate environment, you’ll really dig this. Just type

choco download {packagename} --internalize
and let the magic happen. This will automatically download all needed assets and put them into the generated package, so you’ll achieve the maximum availability.

Just keep in mind that you’ll have to license all hosts that are consumers of packages you manage via internalization. (Chocolatey for Business starts at just $600 USD for up to 35 machines, and is $16/machine/year with volume discounts thereafter – see https://chocolatey.org/pricing)

Choco + Jenkins

Let’s automate the automation!

To be able to use the following jobs you’ll need to know the basics of Jenkins job configurations. You’ll need to set-up parameterized jobs with the PowerShell plugin, also Chocolatey should already be installed on the corresponding Jenkins nodes.

This job just updates all the Chocolatey packages on the server.

choco upgrade all -y

Yes, it’s as easy as that 🙂
This simple Jenkins-job allows you to internalize any package from the community-Feed with the click of a button:

# PowerShell script to internalize chocolatey packages from the community feed to an internal server using the business edition 'internalize' feature. This script is designed to be run from jenkins, P_* variables are defined in jenkins job!
# section CREDS
	$pkgs = $env:P_PKGLIST
	$uncshare = $env:P_UNC_SHARE
    $targetfolder = $env:P_DST_FOLDER
	$targetserver = $env:P_DST_SRV
	$apikey = $env:P_API_KEY

	$envtmp = $env:temp
	$tmpdir = "$envtmp\chocointernalize"
	$basefeed = "https://chocolatey.org/api/v2/"
# endsection

function InternalizePkg($pkg) {
	Push-Location $tmpdir
	choco download --internalize $pkg --resources-location="$uncshare\$pkg" --source="$basefeed" --no-progress
	$genpkg = ((Get-ChildItem *.nupkg -recurse).FullName | Select-String -Pattern $pkg)
    if ($targetfolder) {
        Write-Output "> copying package '$genpkg' to '$targetfolder'"
        if (-Not (Test-Path $targetfolder)) {
            New-Item $targetfolder -ItemType Directory -Force -Verbose            
        }
        Copy-Item $genpkg $targetfolder -Verbose -ErrorAction "Stop"
    } else {
        Write-Output "> pushing package '$genpkg' to '$targetserver'"
        choco push $genpkg --source="$targetserver" --api-key="$apikey" -Verbose
    }
    Write-Output "------------------------------------------------------------------------"
    Write-Output ""
	Pop-Location
}

if ((Test-Path $tmpdir)) {
	Remove-Item $tmpdir -Recurse -Force -Verbose
}
New-Item $tmpdir -ItemType Directory -Force -Verbose

$pkgs | ForEach-Object {
	InternalizePkg $_
}

Remove-Item $tmpdir -Recurse -Force -Verbose

 

This job reports what packages are outdated. (A newer version of that package is available at the community feed)


$mrecipient = $env:P_MAIL_REC
$msender = $env:P_MAIL_SEND
$msmtp = $env:P_SMTP_SERVER
$availPkgs = @()

#$chocoout = $(choco outdated)
$chocoout | ForEach-Object {
    $up = $_.Split("|")
    if ($up -And ($up[3] -ne "false")) {
			if ($up[1] -eq $up[2]) {
				$availPkgs += "$($up[0]): $($up[1]) -> $($up[2])"
			}
		} 
	
}

$res = $availPkgs | Format-Table | Out-String
if ($res) {
	Send-MailMessage -To $mrecipient -Subject "Chocolatey Packages Outdated!" -Body $res -Verbose -ErrorAction "Stop" -From $msender -SmtpServer $msmtp
}

Mind that this setup and these scripts are really minimalistic. When you’re working in an environment with a couple of users you may want additional feeds to create some logical package separation or access control. There are unimaginably many use-cases on how to interop with a command-line utility such as Chocolatey, but I just wanted to give you a quick dive-in how my first contact with Chocolatey looked like. (or how I wished it looked like to be honest ;-)).

Happy hacking!

Links: