Using pre-commit with Munki repos
Jan 4, 2025
7 minute read

In previous posts, I demonstrated the basics of pre-commit and recommended its use for linting AutoPkg recipes. This time, I’ll discuss how pre-commit can be a lifesaver for those who use Munki to deploy software.

Setup

You’ll need a Munki repository tracked by Git. Setting up pre-commit in your Munki repo is simple:

  1. Install pre-commit. I choose to do this with Homebrew:

    brew install pre-commit
    
  2. Create, commit, and push a .pre-commit-config.yaml file at the root of your Munki repository. To start, the contents of the file can be the following:

    1
    2
    3
    4
    5
    
    repos:
      - repo: https://github.com/homebysix/pre-commit-macadmin
        rev: v1.18.0
        hooks:
          - id: check-munki-pkgsinfo
    
  3. Activate the hooks in your Git repo:

    cd /path/to/your_munki_repo
    pre-commit install
    

First I’ll cover what you get by adding the check-munki-pkgsinfo hook, then I’ll show you how to customize it for your organization’s needs.

Check pkginfo files

The check-munki-pkgsinfo hook includes many sanity checks that are generally applicable to Munki pkginfo files. Some of these checks are inherited from others’ Munki linting scripts, and others were born from my own past mistakes and learnings.

As of this writing, the check-munki-pkgsinfo hook includes these checks:

  • The pkginfo file must be a valid plist.

  • The pkginfo must contain certain required keys. By default the required keys are name and description.

  • The key types must be what Munki expects. The list of pkginfo keys Munki supports is here; any keys that aren’t the expected type will produce an error.

  • No duplicate imports should be present in the repo. Duplicate imports are determined by the presence of a __N suffix (for example, Firefox-81.0.1__1.plist). See below for information on how to make this a warning instead of an error.

  • The values of certain keys must be valid. For example, the RestartAction key must be either RequireRestart, RequireShutdown, or RequireLogout. Any other value will produce an error.

  • Specific typos in key names will generate errors. For example, minimum_os_vers and min_os_version are both incorrect variations of the correct key, minimum_os_version.

  • Uninstall scripts must not be missing. If the pkginfo specifies an uninstall_method of uninstall_script, there must also be an uninstall_script key with a script defined.

  • Scripts must start with a shebang. You may optionally limit the shebang to a pre-approved list.

  • Paths in the items_to_copy list must omit trailing slashes.

  • Icons used by pkginfo files must be present in the repository.

If any of these checks fail, you’ll be prevented from committing the file(s) using git commit, as shown below.

% git commit -m "Add nopkg that triggers logout for FileVault" pkgsinfo/enable_filevault.plist
Check Munki Pkginfo Files................................................Failed
- hook id: check-munki-pkgsinfo
- exit code: 1

pkgsinfo/enable_filevault.plist: RestartAction key set to unexpected value: RequiredLogout

Once you’ve corrected the error, git commit will succeed as usual.

% git commit -m "Add nopkg that triggers logout for FileVault" pkgsinfo/enable_filevault.plist
Check Munki Pkginfo Files................................................Passed
[master (root-commit) c4ebfb8] Add nopkg that triggers logout for FileVault
 1 file changed, 62 insertions(+)
 create mode 100644 pkgsinfo/enable_filevault.plist

Customizing pkginfo checks

Although the basic checks above may be good enough for many organizations, customization is available if you’d like to fine-tune or personalize the checks.

In general, pre-commit hooks are customized by passing a list of arguments. These command-line arguments relay additional information to the check function.

Any valid yaml array will work for args. Three examples are shown below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# single line
args: ["--some-things", "one", "two", "three", "--"]

# grouped lines
args: [
  "--some-things", "one", "two", "three",
  "--more-things", "four", "five", "six",
  "--"
]

# multiple lines
args:
- "--some-things"
- "one"
- "two"
- "three"
- "--"

Tip: Quoting strings

I’ve chosen to quote all the examples on this page, because although YAML allows unquoted strings, it’s difficult to troubleshoot errors resulting from bad quoting. Save yourself some time and quote by default.

Tip: Ending arguments

When including an args list with multi-value arguments, it’s a good idea to ensure the final item in the array is --. This separator tells the command-line interpreter that the list of custom arguments are complete. You’ll see this separator used in all the examples in this post that have multi-part arguments.

Customizing required keys

If you want to specify pkginfo keys that should be required in addition to name and description, you can use the --required-keys argument, as shown here:

1
2
3
4
5
6
repos:
  - repo: https://github.com/homebysix/pre-commit-macadmin
    rev: v1.18.0
    hooks:
      - id: check-munki-pkgsinfo
        args: ["--required-keys", "name", "description", "category", "developer", "--"]

Blocking applications for packages

If a blocking_applications array doesn’t exist for a dmg installer, Munki determines the proper blocking apps to use based on the installs array. However many pkg installers only use a receipts array, not an installs array, so you may wish to require a blocking_applications array for pkg installers using this argument:

1
2
3
4
5
6
repos:
  - repo: https://github.com/homebysix/pre-commit-macadmin
    rev: v1.18.0
    hooks:
      - id: check-munki-pkgsinfo
        args: ["--require-pkg-blocking-apps"]

Note that an empty <array/> will satisfy this requirement, which Munki treats the same as if there is no blocking_applications key at all, for pkg installers.

Missing icon warnings

By default, icons referenced by pkginfo files that are absent from your repository will generate errors. If you wish to ignore these errors, the following option will make them non-failing warnings instead:

1
2
3
4
5
6
repos:
  - repo: https://github.com/homebysix/pre-commit-macadmin
    rev: v1.18.0
    hooks:
      - id: check-munki-pkgsinfo
        args: ["--warn-on-missing-icons"]

Duplicate import warnings

By default, files with the presence of a __N suffix (for example, Firefox-81.0.1__1.plist) in your repository will generate errors. However these may not actually be duplicates — perhaps they have different supported_architectures or other keys. If you wish to ignore these errors, the following option will make them non-failing warnings instead:

1
2
3
4
5
6
repos:
  - repo: https://github.com/homebysix/pre-commit-macadmin
    rev: v1.18.0
    hooks:
      - id: check-munki-pkgsinfo
        args: ["--warn-on-duplicate-imports"]

Allowed catalogs and categories

Checking for specific allowable catalogs and categories is not enabled by default, but you can enable this check in your .pre-commit-config.yaml file using the following arguments:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
repos:
  - repo: https://github.com/homebysix/pre-commit-macadmin
    rev: v1.18.0
    hooks:
      - id: check-munki-pkgsinfo
        args: [
          "--catalogs", "testing", "stable",
          "--categories", "Creativity", "Engineering", "Productivity", "Security", "Utilities",
          "--"
        ]

Valid shebangs

Scripts in Munki pkginfo files require a shebang in the first line in order to ensure they are interpreted by the proper scripting runtime. If you choose, you can define a pre-approved set of shebangs that you expect all scripts in your repo to use. Any shebangs not in this list will result in an error.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
repos:
  - repo: https://github.com/homebysix/pre-commit-macadmin
    rev: v1.18.0
    hooks:
      - id: check-munki-pkgsinfo
        args: [
          "--valid-shebangs",
            "#!/bin/bash",
            "#!/bin/sh",
            "#!/usr/local/bin/managed_python3",
            "#!/usr/local/munki/munki-python",
          "--"
        ]

Combining arguments

When combining arguments, just ensure the -- argument is the last one in the list. A working .pre-commit-config.yaml file that includes multiple of the above customizations may look like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
repos:
  - repo: https://github.com/homebysix/pre-commit-macadmin
    rev: v1.18.0
    hooks:
      - id: check-munki-pkgsinfo
        args: [
          "--required-keys",
            "name",
            "description",
            "category",
            "developer",
          "--catalogs",
            "testing",
            "stable",
          "--categories",
            "Creativity",
            "Engineering",
            "Productivity",
            "Security",
            "Utilities",
          "--valid-shebangs",
            "#!/bin/bash",
            "#!/bin/sh",
            "#!/usr/local/bin/managed_python3",
            "#!/usr/local/munki/munki-python",
          "--warn-on-missing-icons",
          "--warn-on-duplicate-imports",
          "--"
        ]

Check MunkiAdmin scripts

If you use MunkiAdmin, you may be excited to learn of its presave/postsave scripts feature, which can run scripts before or after saving files in your repository. The check-munkiadmin-scripts hook can be used to validate these scripts. This hook ensures that the scripts are executable and named properly.

Here’s how you can add the check-munkiadmin-scripts hook to your .pre-commit-config.yaml file:

1
2
3
4
5
repos:
  - repo: https://github.com/homebysix/pre-commit-macadmin
    rev: v1.18.0
    hooks:
      - id: check-munkiadmin-scripts

Rebuild Munki catalogs

This last hook runs the makecatalogs command to ensure all referenced packages are present and catalogs are freshly built.

1
2
3
4
5
repos:
  - repo: https://github.com/homebysix/pre-commit-macadmin
    rev: v1.18.0
    hooks:
      - id: munki-makecatalogs

Other helpful hooks

Many of the helpful hooks mentioned in my previous post about linting AutoPkg recipes are equally useful for Munki repos. Review the list here.

Conclusion

By integrating pre-commit hooks into your Munki repository, your client platform engineering team can ensure that your pkginfo files and MunkiAdmin scripts are consistently validated and free of common errors. This not only helps maintain the integrity of your repository but also saves time and reduces the risk of deployment issues.

You can inspect the code that drives the check-munki-pkgsinfo, check-munkiadmin-scripts, and munki-makecatalogs hooks on GitHub. If you have any questions or suggestions, I welcome issues and pull requests on the pre-commit-macadmin repository.