Use .jujuignore files to hide absolute symlinks in charms from juju

How absolute symlinks in charms can break your deployments?

If you try to build and deploy a charm that contains absolute symlinks,
you will find out that juju deploy aborts the deployment with an error
such as the following:

ERROR cannot deploy bundle: cannot repackage charm: symlink
"$the-symlink-name" is absolute: "$path-where-the-symlink-points-to"

Many charm authors use tox to run
python-based unit tests for the charms they maintain. Tools like tox tend to
create symlinks to the system python binaries within the charm folder. These
symlink files will get typically committed to version-control and, unless
somehow explicitly excluded, will end up in the charm archive causing the above
error to be emitted when either:

  • deploying the charm, or
  • while attempting to run functional unit-tests.

Excluding files/folders from charm archives using .jujuignore files

When an operator deploys a bundle, juju will retrieve the charm and
automatically repackage its contents into a fresh charm archive that gets
cached by the controller. So, how can we actually exclude the bits we don’t
really need from the generated charm archives? There are two documented
ways of achieving this:

  • Rely on the built-in exclusion list used by the charm archiving code (backwards-compatibility way).
  • Provide a .jujuignore file (the new way).

.jujuignore files allow charm authors to define their own set of exclusion
patterns using the same pattern syntax as .gitignore files. This feature is
available since juju 2.5.3 and in order to use it, charm authors need to
place a file named .jujuignore in the root folder of the charm.

Here is a quick summary of the syntax used in .jujuignore files together
with some useful examples:

  • A blank line matches no files, so it can serve as a separator for
    readability.
  • A line starting with # serves as a comment. Put a backslash (\) in
    front of the first hash for patterns that begin with a hash.
  • Trailing spaces are ignored unless they are quoted with backslash (\).
  • An optional prefix ! negates the pattern; any matching file excluded
    by a previous pattern will become included again.
  • If the pattern ends with a slash, it is removed but the rule will ONLY
    match directories. For example, foo/ will match a directory foo and
    paths underneath it, but will not match a regular file or a symbolic
    link named foo.
  • All other patterns are treated as shell globs. For details regarding
    the supported glob expressions please refer to the gobwas/glob package
    documentation.
  • A leading slash matches the beginning of the pathname. For example,
    /*.go matches foo.go but not pkg/foo.go.
  • Double-star patterns have a special meaning:
    • A leading ** followed by a slash means match in all directories.
      For example, **/foo matches file or directory foo anywhere, the
      same as pattern foo. **/foo/bar matches file or directory bar
      anywhere that is directly under directory foo.
    • A trailing /** matches everything inside. For example, abc/**
      matches all files inside directory abc but NOT abc.
    • A slash followed by two consecutive asterisks then a slash matches
      zero or more directories. For example, a/**/b matches a/b,
      a/x/b, a/x/y/b and so on.

Let’s now revisit the above example! With the above rules in mind, we can easily filter
out any tox-related resources from the generated charm archives by creating a .jujuignore
file with the following content:

# Ignore tox-related resources
.tox/