Automatic merging guidelines

These are the guidelines that a pull request must pass in order to be automatically merged.

All of those guidelines are enabled on the General registry (see AutoMerge.general_registry_config for the precise configuration of AutoMerge used by General).

For other registries, some of these guidelines can be disabled.

New packages

  1. The package name should be a valid Julia identifier (according to Base.isidentifier).
  2. The package name should start with an upper-case letter, contain only ASCII alphanumeric characters, and contain at least one lowercase letter.
  3. The name is at least 5 characters long.
  4. Name does not include "julia", start with "Ju", or end with "jl".
  5. Repo URL ends with /PackageName.jl.git.
  6. Version number is not allowed to contain prerelease data
  7. Version number is not allowed to contain build data
  8. There is an upper-bounded [compat] entry for julia that only includes a finite number of breaking releases of Julia.
  9. Dependencies: All dependencies should have [compat] entries that are upper-bounded and only include a finite number of breaking releases. For more information, please see the "Upper-bounded [compat] entries" subsection under "Additional information" below.
  10. Name is composed of ASCII characters only.
  11. Package installation: The package should be installable (Pkg.add("PackageName")).
  12. Code can be downloaded.
  13. License: The package should have an OSI-approved software license located in the top-level directory of the package code, e.g. in a file named LICENSE or LICENSE.md. This check is required for the General registry. For other registries, registry maintainers have the option to disable this check.
  14. src files and directories names are OK
  15. Package loading: The package should be loadable (import PackageName).
  16. Checks that the package's Project.toml (or JuliaProject.toml) exists, can be parsed, and is consistent with registration PR.
  17. Packages must not match the UUID of an existing package or stdlib.
  18. The package's UUID must conform to RFC 4122 / RFC 9562 standards. This means:
  • The version field (4 bits at positions 48-51) should be 1-8
  • The variant field (2 bits at positions 64-65) should be binary 10 (hex character 8, 9, a, or b at position 19)

Exception: Julia's uuid1() function has historically generated UUIDs with incorrect variant bits (binary 00 instead of 10). These UUIDs are accepted for backward compatibility with existing packages.

  1. Packages must not match the name of existing package up-to-case, since on case-insensitive filesystems, this will break the registry.
  2. To prevent confusion between similarly named packages, the names of new packages must also satisfy the following three checks: (for more information, please see the "Name similarity distance check" subsection under "Additional information" below)
    • the Damerau–Levenshtein distance between the package name and the name of any existing package must be at least 3.
    • the Damerau–Levenshtein distance between the lowercased version of a package name and the lowercased version of the name of any existing package must be at least 2.
    • and a visual distance from VisualStringDistances.jl between the package name and any existing package must exceeds a certain a hand-chosen threshold (currently 2.5).

These checks can be overridden by applying a label Override AutoMerge: name similarity is okay to the PR. This will turn off the check as long as the label is applied to the PR.

New versions of existing packages

  1. Version number: Should be a standard increment and not skip versions. This means incrementing the patch/minor/major version with +1 compared to previous (if any) releases. If, for example, 1.0.0 and 1.1.0 are existing versions, valid new versions are 1.0.1, 1.1.1, 1.2.0 and 2.0.0. Invalid new versions include 1.0.2 (skips 1.0.1), 1.3.0 (skips 1.2.0), 3.0.0 (skips 2.0.0) etc.
  2. Version number is not allowed to contain prerelease data
  3. Version number is not allowed to contain build data
  4. There is an upper-bounded [compat] entry for julia that only includes a finite number of breaking releases of Julia.
  5. Dependencies: All dependencies should have [compat] entries that are upper-bounded and only include a finite number of breaking releases. For more information, please see the "Upper-bounded [compat] entries" subsection under "Additional information" below.
  6. If it is a patch release on a post-1.0 package, then it does not narrow the [compat] range for julia.
  7. Package installation: The package should be installable (Pkg.add("PackageName")).
  8. Code can be downloaded.
  9. License: The package should have an OSI-approved software license located in the top-level directory of the package code, e.g. in a file named LICENSE or LICENSE.md. This check is required for the General registry. For other registries, registry maintainers have the option to disable this check.
  10. Checks that the package's Project.toml (or JuliaProject.toml) exists, can be parsed, and is consistent with registration PR.
  11. src files and directories names are OK
  12. Package loading: The package should be loadable (import PackageName).
  13. If this is a breaking change, release notes must be given that explain why this is a breaking change (i.e. mention "breaking" or "changelog"). To update the release notes, please see the "Providing and updating release notes" subsection under "Additional information" below.

Additional information

Upper-bounded [compat] entries

For example, the following [compat] entries meet the criteria for automatic merging:

[compat]
PackageA = "1"          # [1.0.0, 2.0.0), has upper bound (good)
PackageB = "0.1, 0.2"   # [0.1.0, 0.3.0), has upper bound (good)

The following [compat] entries do NOT meet the criteria for automatic merging:

[compat]
PackageC = ">=3"        # [3.0.0, ∞), no upper bound (bad)
PackageD = ">=0.4, <1"  # [0, ∞), no lower bound, no upper bound (very bad)

Please note: each [compat] entry must include only a finite number of breaking releases. Therefore, the following [compat] entries do NOT meet the criteria for automatic merging:

[compat]
PackageE = "0"          # includes infinitely many breaking 0.x releases of PackageE (bad)
PackageF = "0.2 - 0"    # includes infinitely many breaking 0.x releases of PackageF (bad)
PackageG = "0.2 - 1"    # includes infinitely many breaking 0.x releases of PackageG (bad)

See Pkg's documentation for specification of [compat] entries in your Project.toml file.

(Note: JLL dependencies are excluded from this criterion because they often have non-standard version numbering schemes; however, this may change in the future.)

You may find CompatHelper.jl and PackageCompatUI.jl helpful for maintaining up-to-date [compat] entries.

Testing that the package can be imported

AutoMerge tests whether the registered package/version can be imported. This is done using the lowest and highest Julia minor versions according to the Julia compat declared in Project.toml. For the chosen minor versions, the highest compatible patch version is used. There are two special cases:

  • For technical reasons 1.0.x versions cannot be used, so effectively 1.1 is the lowest considered minor version.

  • If a package only is compatible with a Julia version in prerelease testing phase, the highest available prerelease version (e.g. a beta or a release candidate) is used for import testing. Otherwise prereleases are not used.

Name similarity distance check

These checks and tolerances are subject to change in order to improve the process.

To test yourself that a tentative package name, say MyPackage meets these checks, you can use the following code (after adding the RegistryCI package to your Julia environment):

using RegistryCI, RegistryInstances
using AutoMerge
path_to_registry = joinpath(DEPOT_PATH[1], "registries", "General.toml")
all_pkg_names = AutoMerge.get_all_pkg_names(RegistryInstance(path_to_registry); keep_jll=false)
AutoMerge.meets_distance_check("MyPackage123", all_pkg_names)
(true, "")

where path_to_registry is a path to the registry of interest. For the General Julia registry, usually path_to_registry = joinpath(DEPOT_PATH[1], "registries", "General.toml") if you haven't changed your DEPOT_PATH (or path_to_registry = joinpath(DEPOT_PATH[1], "registries", "General") if you have an uncompressed registry at the directory there). This will return a boolean, indicating whether or not your tentative package name passed the check, as well as a string, indicating what the problem is in the event the check did not pass.

Note that these automerge guidelines are deliberately conservative: it is very possible for a perfectly good name to not pass the automatic checks. They simply exist to provide a fast path so that manual review is not required for every new package. False positives can be overridden with a PR label after manual review.

Providing and updating release notes

When invoking a registration with the @JuliaRegister bot, release notes can be added in the form

@JuliaRegistrator register

Release notes:

## Breaking changes

- Explanation of breaking change, ideally with upgrade tips
- ...

These can also be added/updated on the General PR by re-invoking with the above.

Doing this has two benefits:

  • helps explanations during the registration process, especially for breaking changes
  • release notes are picked up by TagBot such that they are added to the new release on the original repo

Automerge is disabled for breaking changes where release notes are not provided mentioning "breaking" (or "changelog" if there is a repository file that you prefer to direct users to).

List of all GitHub PR labels that can influence AutoMerge

AutoMerge reads certain labels on GitHub registration pull requests to influence its decisions. Specifically, these labels are:

  • Override AutoMerge: name similarity is okay
    • This label can be manually applied by folks with triage-level access to the registry repository.
    • AutoMerge skips the "name similarity check" on new package registration PRs with this label.
  • Override AutoMerge: package author approved
    • This label can be manually applied, but typically is applied by a separate Github Actions workflow which monitors the PR for comments by the package author, and applies this label if they write [merge approved].
    • This label currently only skips the "sequential version number" check in new versions. In the future, the author-approval mechanism may be used for other checks (on both "new version" registrations and also "new package" registrations).
      • When AutoMerge fails a check that can be skipped by author-approval, it will mention so in the comment, and direct authors to comment [merge approved] if they want to skip the check.