Adding a mod to the CKAN - HebaruSan/CKAN GitHub Wiki

Before anything else, thank you for wanting to contribute to CKAN.

This page is a wiki; please feel free to contribute, and be bold with your edits!

Express mode

There are two quick-and-easy ways to request a mod be added to CKAN. Most mod authors should use one of these options.

  1. Submit an issue containing details about the mod
  2. Upload your mod to SpaceDock and check the CKAN checkbox: SpaceDock new mod screen SpaceDock Add mod to CKAN checkbox

Both of these options will send a request to index your mod to the CKAN team. They will review it and make any changes needed to ensure the mod will install correctly, but unless they need to ask you questions, your work is complete!

If you're not the author, please contact the author and ask if it's OK with them to add the mod to CKAN before proceeding. Adding a mod to CKAN brings it to the attention of more users and can affect the maintainer's support burden, so we don't add mods against their authors' wishes.

If the author is on the opt-out list, then please don't bother them at all!

Advanced

If you're a CKAN team member or you really want to dig in to the technical side of CKAN metadata, then keep reading. If you need help, hop on Discord or the forum thread and ask.

Adding a mod to CKAN is a matter of writing a small JSON file to describe the mod, its relationship with other mods, and the installation process.

  1. Select an identifier; this must be a short, unique name for the mod that will identify the mod inside the system (end users will not see this name). It must only contain letters, digits, and dashes (-). Ideally it should match the name of the directory that you wish to copy to GameData.

  2. Create a file named <identifier>.netkan

  3. Fill in the file's contents with JSON metadata; a basic skeleton is:

    {
        "spec_version": "v1.4",
        "identifier":   "<identifier>",
        "license":      "<license string>",
        "resources": {
            "homepage": "<URL>"
        },
        "tags": [
            "<tag>"
        ]
    }

    The spec_version is the version of CKAN required to read the metadata.

    See the license list for values you can use for license.

    The homepage is the URL for support and discussion of your mod, usually a thread on the KSP forum.

    The tags list contains the names of groups to which your mod should belong, which the client can use for filtering. See Suggested Tags for details.

  4. Tell CKAN how to find your mod. Usually this is done with the $kref property. For SpaceDock:

        "$kref": "#/ckan/spacedock/123456",

    The number is the SpaceDock mod id from the URL for your mod.

    For GitHub:

        "$kref": "#/ckan/gitub/YourUserName/YourRepositoryName",
  5. Tell CKAN about your mod's compatibility. If you have a KSP-AVC .version file:

        "$vref": "#/ckan/ksp-avc",

    If your mod is compatible with one game version:

        "ksp_version": "1.9.1",

    If your mod is compatible with a range of versions:

        "ksp_version_min": "1.8",
        "ksp_version_max": "1.9",

    Note that mods hosted on SpaceDock will use the compatibility info entered into SpaceDock by default.

  6. Tell CKAN how to install your mod. If you just need it to extract a folder named after the identifier to GameData, you're done with this step. Otherwise, add one install stanza per folder to install:

        "install": [
            {
                "find":       "FolderA",
                "install_to": "GameData"
            },
            {
                "find":       "FolderB",
                "install_to": "GameData"
            }
        ],

    Don't use this to install any mods bundled in the archive (like ModuleManager). This will cause conflicts. Use a depends relationship instead (see next step).

  7. Specify relationships with other mods. If your mod requires another mod to be installed to work:

        "depends": [
            { "name": "ModuleManager" }
        ],

    If another mod is recommended but not required:

        "recommends": [
            { "name": "BDArmoryContinued" }
        ],

    If a mod is nice to have but not recommended:

        "suggests": [
            { "name": "KerbalEngineerRedux" }
        ],

    If your mod cannot work when another mod is installed:

        "conflicts": [
            { "name": "TweakScale" }
        ],

    In all of the above cases, the name field should be set to the identifier of the mod in question. You can find identifiers of active modules by searching the status page.

  8. Verify your metadata file.

    1. Download netkan.exe
    2. Run it to process your module:
      netkan.exe --verbose <identifier>.netkan
    3. If there's a problem, you'll see an error message. Otherwise, netkan.exe will produce a .ckan file (the mod's full/inflated metadata) in the same directory.
    4. Download ckan.exe
    5. Try installing the mod:
      ckan.exe install -c <identifier>-<version>.ckan
    6. View the files installed:
      ckan.exe show <identifier>
  9. Create a pull request in the NetKAN repository that adds your file

    1. Open the NetKAN folder in the NetKAN repo
    2. Click "Create new file"
    3. Set the file name to <identifier>.netkan
    4. Paste the contents of your .netkan file into the text box
    5. Click "Propose new file"
    6. In the comment box, add a description of your mod to plus any details the CKAN team might need to know to index it correctly
    7. Click "Create pull request"
    8. Validation checks will be run when your pull request is submitted, which will either pass with a green checkmark or fail with a red X (and an orange circle while in progress). If they fail, the errors can be viewed by clicking "Show all checks" → "Details" → "Console Output". You or a CKAN team member can then fix the errors by making further changes to the netkan file, which will re-run the validation. To re-run the validation without changing the netkan file, enter a comment of "#rebuild".
    9. Smile. A CKAN team member will review the file and either request changes or integrate your contribution into database. The mod will be listed in CKAN shortly thereafter.

NetKAN review checklist

When reviewing a new netkan file, make sure the following things are correct:

  • License - should match license inside ZIP or on forum thread
  • Homepage - should point to forum thread
  • $vref - set if ZIP contains a .version file
  • Tags
  • Dependencies / conflicts

The full spec

If you need it, the complete CKAN metadata spec is available, in both human readable and machine readable format. The CKAN provides both a lot of power and flexibility, so check out the spec for more things you can do and the ways to use them.

Internal .ckan files

Sometimes your mod's metadata might need to change due to underlying changes in a new release. For example, a new version of your mod may depend on a particular version of another mod, or it may introduce a conflict with some mod that doesn't apply to older versions. Or you may wish to change your install paths. It can be hard to figure out the timing of such changes so that the old version is not accidentally changed and the new version is not released under the old metadata.

In these cases you can put the version-specific metadata in your downloaded ZIP file, in a file with the .ckan extension. The indexing bot will read this file and add any properties it contains to that version's metadata. For example, if a new version requires Ringworld 0.1.0 and conflicts with TransferWindowPlanner, putting this file in the ZIP would take care of those requirements without affecting other versions:

{
    "spec_version": "v1.16",
    "depends": [
        { "name": "Ringworld", "version": "0.1.0" }
    ],
    "conflicts": [
        { "name": "TransferWindowPlanner" }
    ]
}

Note that an internal .ckan file can only add properties; it cannot override or remove properties that are set in your main netkan entry!

Editing tips

Using a capable text editor can help you create valid JSON (the data format used for .ckan and .netkan files).

GitHub's own Atom editor has two useful plugins, atom-linter and linter-jsonlint, which—when both are installed—will warn you about any errors. Select JSON as the grammar to use when editing .ckan and .netkan files; you configure this to happen automatically by installing the file-types add-on and adding this to your config.cson:

  "file-types":
    ckan: "source.json"
    netkan: "source.json"

Some useful snippets to add to Atom for netkan files can be found in this gist.

Troubleshooting

Bot status

The indexing bot's most recently checked mods and error messages are listed on this page:

http://status.ksp-ckan.space/

This is mostly useful for mods hosted on GitHub and SpaceDock, as mods hosted elsewhere cannot be checked for new releases automatically.

Note that the status page reflects only the bot's processing, and does not change when a mod's metadata is modified manually via pull requests on GitHub. However, such updates will be shown after the bot's next pass is completed.

Help! I need to overwrite another mod's files

Some mods need to change data from another mod. For example, Scatterer contains a file in GameData\scatterer\config\planetsList.cfg that specifies the visual effects to use for each celestial body. Planet packs often wish to configure these effects for their own custom planets.

By design, the CKAN does not allow overwriting files, nor does it allow installation order to be specified. This not only gives us a number of strong mathematical assurances (we can analyze dependencies as a set, rather than a graph), but it also means we can immediately detect conflicts, and we don't have to worry about mods installed "earlier" in the install overwriting those from "later" in the install when they're upgraded.

There are two main ways to handle this kind of requirement.

Module Manager

The best approach is to use Module Manager to make your changes without altering the original files. This results in simpler metadata in CKAN as well as easier manual installation (since users can simply copy both mods' files rather than carefully splicing and replacing some of them).

The planetsList.cfg file defines a KSP ConfigNode object called Scatterer_planetsList. A Module Manager config file can modify this object when the game is loaded without changing the original file, using the @ syntax to modify a node defined elsewhere:

@Scatterer_planetsList:AFTER[scatterer]
{
    @scattererCelestialBodies
    {
        Item
        {
            /// New planet data here
        }
    }
}

Separate modules for config files

If you can't use Module Manager, another option is to split out the configurable and non-configurable parts of the other mod into separate modules. In the case of Scatterer, the main Scatterer module does not install the config files; instead it depends upon other modules called Scatterer-config and Scatterer-sunflare, each of which installs config files from the same download separately. Installing all three modules together produces the same file structure as unzipping everything in the original archive.

A mod that wishes to provide its own complete replacement config (see SVE-Scatterer-Config) can indicate in its metadata that it is capable of replacing Scatterer-config and/or Scatterer-sunflare using the provides property, and prevent other configs from being installed alongside it with the conflicts property:

    "provides": [
        "Scatterer-config",
        "Scatterer-sunflare"
    ],
    "conflicts": [
        { "name": "Scatterer-config"   },
        { "name": "Scatterer-sunflare" }
    ],

This approach has been applied to some other mods in addition to Scatterer, such as Kerbalism and PlanetShine. Its biggest disadvantage is that it effectively freezes the directory structure of a mod as-is; if a mod author wishes to rename the swappable configuration folder, or overhaul how the mod is configured in general, then that release will fail to index in CKAN until the metadata is updated to reflect the new name (or worse, it might index successfully but then not install correctly).

⚠️ **GitHub.com Fallback** ⚠️