Skip to content

Recipe Writing Guidelines

Timothy Sutton edited this page Mar 27, 2014 · 16 revisions

The following is a set of guidelines that should be followed when writing your own recipes, especially if you wish to share them with others via a Git repository. The AutoPkg repo- commands make it easy to add and update recipes from others' repos.

Finding examples

There is quite a variety of tasks done to handle many common applications in the AutoPkg's own recipes repo. You can use existing, core AutoPkg processors to do things like:

  • download and cache from a URL
  • dynamically retrieve a URL from a Sparkle feed
  • mount DMGs
  • stage, copy, delete files
  • import into Munki, providing additional makepkginfo options
  • build flat installer packages with specific permissions, ownerships
  • extract version information, read/write/merge plists

Sometimes vendors make a stable URL available that always points to the latest version, for example Google Chrome. In other cases, a vendor may have written their own system to parse their own metadata feed structure, such as Bare Bones Software. In cases like the latter, it is almost always necessary to write a custom processor. There are also a number of processors in which HTML is scraped using a RegEx match for a predictable URL pattern (see Mozilla, Oracle Java 7, Puppet Labs).

Custom processors are written in Python. There is not yet documentation for writing your own, but hopefully these examples can get you started.

Separating recipe tasks

A number of the recipes in the AutoPkg recipes repo have both .munki and .pkg variants. Because both recipes need to first download the software that's going to be later processed, it's possible to define the download steps in one place as a "parent recipe", by setting the identifier of the parent recipe in the ParentRecipe top-level key in the recipe. The parent recipe's steps will run before the child recipe's.

A recipe may have a ParentRecipe, and that parent recipe may have a ParentRecipe of its own. For example, you could have one recipe (Foo.download.recipe) that downloads an item, a child recipe (Foo.pkg.recipe) that repackages the item, and child of that recipe (Foo.munki.recipe) that imports the pkg into your Munki repo.

There's no rule that your recipe(s) must be broken down into parent/child recipes if you only plan to ever use them with Munki, but by separating the tasks up front you make it easier should you or anyone else wish to add another variant to a recipe (for example, importing into some other software management system).

Identifiers

It's very important to decide on a unique identifier for the recipe that will remain fixed. The reverse-domain naming style should contain:

  • home of the repo (probably usually com.github.)
  • maintainer/org name (ie. a GitHub user name, Google Code project, etc.)
  • what the recipe does (ie. .download, .pkg, .munki)
  • the actual name of the software

For example: com.github.foo.pkg.app - written by user "foo", builds a pkg of "app."

When a recipe override is created by an AutoPkg user, it will use the recipe's identifier to identify your recipe as the ParentRecipe (as overrides are actually child recipes). This means that if you should change your identifier, the override will no longer be able to locate your recipe. So, unless your recipe is very new and you are resolving a conflict or confusion about the recipe's identifier, it's strongly recommended to never change your recipe identifier once it has been made publicly available.

Input variables

Your recipe may support additional parameters for pulling alternate versions, branches, languages, etc, and can do so via input variables. At other points in the recipe these values can be substituted in via enclosing % characters. For example, the Firefox.download recipe supports LOCALE and RELEASE input variables. You'll notice these are simply passed as arguments to the MozillaURLProvider processor.

Any custom input variables you support in the recipe should be clearly documented in the Description key.

Assuming you are sharing your recipe, consider these variable names to be your recipe's "API", because changing them will mean that the recipe will no longer be overridden as expected, for as long as a user is still overriding the old key name. The only time to change existing variable names might be for an entirely new recipe. Adding new variables to support new functionality in your recipe is ok, as long as existing functionality remains unchanged.

Versions

Sometimes a recipe may not be useful only for retrieving the latest update, but a specific previous version – especially if this version is a prerequisite to the latest update. For example, Office 2011 updates after 14.1.0 mostly require at least 14.1.0 to be installed first. Maybe you don't yet have this update in your repo and would like to get it the same way AutoPkg gets the latest updates. The recipe-specific processor included with the MSOffice2011Updates recipes makes use of the same metadata XML feed used by Microsoft's own Auto-Updater, and is therefore able to pull the same versions it exposes.

If your recipe is able to pull alternate versions, provide this capability with a VERSION Input variable, which defaults to latest.

If an intermediate update is required, it's possible to do a one-off override of VERSION with the -k/--key option:

autopkg run -k VERSION=14.1.0 MSOffice2011Updates.munki

For examples on how this is done in recipe-specific processors, the processors used for Office 2011 and Adobe Acrobat recipes are a good place to look.

Table of Contents

Clone this wiki locally