ResearchSoftwareMetadata documentation

Documentation for ResearchSoftwareMetadata.

Summary

ResearchSoftwareMetadata is a Julia package that provides a crosswalk between Project.toml, codemeta.json, .zenodo.json and the package LICENSE file, giving a consistent way of providing metadata for research software, so that the Julia General Registry, GitHub and Zenodo all pick up the same metadata, following the Research Software MetaData guidelines.

Installation

The package is registered in the General registry so can be built and installed with add. For example:

(@v1.12) pkg> add ResearchSoftwareMetadata
   Resolving package versions...
    Updating `~/.julia/environments/v1.12/Project.toml`
  [58378933] + ResearchSoftwareMetadata v0.3.0
    Updating `~/.julia/environments/v1.12/Manifest.toml`

(@v1.12) pkg>

Usage

First you need to add a small amount of additional metadata into your Project.toml file.

To capture the license you are using and propagate it throughout the metadata files and through your julia code, add an SPDX license identifier to the file:

license = "BSD-2-Clause"

All of the other metadata that this package uses lives in a single [rsmd] table. To supplement the metadata on the authors of the package, add the ORCID for each author and the ROR for the organisation(s) they are affiliated with. You can add as many authors and as much or as little information as you like about each one by adding additional [[rsmd.author_details]] blocks.

[rsmd]

    [[rsmd.author_details]]
    name = "Richard Reeve"
    orcid = "0000-0003-2589-8091"

        [[rsmd.author_details.affiliation]]
        ror = "00vtgdb53"

You can also optionally add a description of the package, keywords associated with it, the software category it belongs to, its repostatus.org development_status, and the DOIs of any publications associated with the package. All of these are propagated into codemeta.json and .zenodo.json, and any values already in codemeta.json but missing from Project.toml will be backfilled into it. Any of these keys found at the top level of Project.toml (the old layout) are automatically migrated into [rsmd]:

[rsmd]
keywords = ["julia", "metadata"]
category = "metadata"
description = "A package that does things"
development_status = "active"
publications = ["10.5281/zenodo.12789179"]

Then, from the root of your package, you can just run a crosswalk:

using Pkg

# Create a new project with ResearchSoftwareMetadata in it
Pkg.activate(; temp = true)
Pkg.add("ResearchSoftwareMetadata")

# Carry out a crosswalk between the different metadata formats
using ResearchSoftwareMetadata
ResearchSoftwareMetadata.crosswalk()

If you want to pass in some additional metadata (the category of the software, or the keywords associated with it, both of which are written back into [rsmd] in Project.toml), or you want to increase the package version during the crosswalk, you can do that as follows:

# Add in additional metadata
ResearchSoftwareMetadata.crosswalk(category = "metadata", keywords = ["julia", "metadata", "research software", "RSMD"])

# Increase version number during crosswalk
ResearchSoftwareMetadata.increase_patch() # Bump patch version (e.g. 0.4.1 -> 0.4.2)
ResearchSoftwareMetadata.increase_minor() # Bump minor version (e.g. 0.4.2 -> 0.5.0)
ResearchSoftwareMetadata.increase_major() # Bump major version (e.g. 0.5.0 -> 1.0.0)

You might also consider reformatting all of your julia code to a consistent format. A .JuliaFormatter.toml file in the package root defines what the formatting standard should be.

Pkg.add("JuliaFormatter")
Pkg.develop("MyPackage")
using JuliaFormatter
using MyPackage
format(MyPackage)

Automated checking

You can also make your package's own test suite check automatically that the metadata crosswalk is clean and the code is well formatted, by copying a few files from this package's test/ directory into your own. See Automated package checks for instructions.

Reference guide

ResearchSoftwareMetadata.ResearchSoftwareMetadataModule
ResearchSoftwareMetadata

ResearchSoftwareMetadata provides a crosswalk between Project.toml, codemeta.json, .zenodo.json and the package LICENSE file, so that consistent research software metadata can be picked up from a package by Julia's General registry, GitHub and Zenodo, following the FAIR-IMPACT Research Software MetaData (RSMD) guidelines. Project.toml is treated as the authoritative source of metadata wherever possible.

The entry points are ResearchSoftwareMetadata.crosswalk(), which enforces consistency across the metadata files and the julia source code, and ResearchSoftwareMetadata.increase_patch(), ResearchSoftwareMetadata.increase_minor() and ResearchSoftwareMetadata.increase_major(), which bump the package version and then re-run the crosswalk.

source
ResearchSoftwareMetadata.author_details_consistentMethod
ResearchSoftwareMetadata.author_details_consistent(details, proj_authors)

Check whether a reconstructed author_details array is consistent with the definitive authors entries in Project.toml. Every entry must match an author string by name (and email when it has one), and the counts must agree.

source
ResearchSoftwareMetadata.author_details_from_codemetaMethod
ResearchSoftwareMetadata.author_details_from_codemeta(cm_authors)

Reconstruct a Project.toml author_details array from the author array of a codemeta.json file. Each entry contains a name, plus an orcid, an email and an affiliation array where available.

source
ResearchSoftwareMetadata.author_details_from_zenodoMethod
ResearchSoftwareMetadata.author_details_from_zenodo(creators)

Reconstruct a Project.toml author_details array from the creators array of a .zenodo.json file. Each entry contains a name (reversing Zenodo's "Family, Given" format), plus an orcid and an affiliation array where available. Zenodo does not record email addresses.

source
ResearchSoftwareMetadata.check_doiMethod
ResearchSoftwareMetadata.check_doi(doi::String)

Check that a DOI resolves by querying the doi.org handle API. Returns true if it resolves and false if it does not exist. Throws an error if doi.org cannot be reached or returns an unexpected HTTP status.

source
ResearchSoftwareMetadata.crosswalkFunction
crosswalk(git_dir; category = nothing, keywords = nothing,
          build = false, update = false)

Runs a crosswalk across Project.toml, LICENSE, codemeta.json and .zenodo.json as well as the julia source files to enforce consistency between the different metadata formats. It logs warnings and errors if it identifies inconsistencies while it is editing the files. Project.toml is the authoritative source of metadata: as well as its standard fields, the optional keys description, keywords, category, development_status and publications (a vector of DOIs of associated papers) in its [rsmd] table are propagated into codemeta.json and .zenodo.json; values found only in codemeta.json are backfilled into Project.toml. Legacy top-level copies of these keys are migrated into [rsmd]. A missing author_details section is likewise constructed from codemeta.json or .zenodo.json, provided the information there is consistent with the definitive authors field. New entries in authors are propagated into rsmd.author_details (with a warning to add their ORCID and ROR affiliation there), codemeta.json and .zenodo.json, while authors in codemeta.json that are missing from authors are removed with an error. The software category can be set with the category argument, likewise the keywords argument can contain a vector of keyword strings; both take precedence over and are written back into Project.toml. The build argument sets the buildInstructions RSMD field - false leaves the instructions as is, true sets it to the same as the README, and a string sets it to that value. If update is true, changes to Project.toml (e.g. to the version or the license) are treated as deliberate and propagated to the other metadata files with @info messages instead of being reported as warnings or errors. If any remote metadata query (orcid.org, ror.org, spdx.org, doi.org or Julia's General registry) cannot be completed, the crosswalk throws an error and all files are left in their original state.

source
ResearchSoftwareMetadata.get_first_release_dateFunction
ResearchSoftwareMetadata.get_first_release_date()

Returns the first release date of this package on Julia's General Registry, or today's date if the package has not been registered yet. Throws an error if the registry cannot be reached or returns an unexpected HTTP status.

source
ResearchSoftwareMetadata.get_organisation_from_rorMethod
ResearchSoftwareMetadata.get_organisation_from_ror(ror::String)

Take a ROR from the user and query the ror.org API to return a Dict containing the relevant metadata or nothing if no such ROR exists. Throws an error if ror.org cannot be reached or returns an unexpected HTTP status.

source
ResearchSoftwareMetadata.get_os_from_workflowsFunction
ResearchSoftwareMetadata.get_os_from_workflows()

Returns the operating systems that the GitHub workflows associated with this package work on. This is presumed to represent the operating systems that the software runs on.

source
ResearchSoftwareMetadata.get_person_from_orcidMethod
ResearchSoftwareMetadata.get_person_from_orcid(orcid::String)

Take an ORCID from the user and query the orcid.org API to return a Dict containing the relevant metadata or nothing if no such ORCID exists. Throws an error if orcid.org cannot be reached or returns an unexpected HTTP status.

source
ResearchSoftwareMetadata.increase_majorFunction
increase_major()

Increases the Project.toml version number by a major number (e.g. 0.4.1 to 1.0.0), and then runs ResearchSoftwareMetadata.crosswalk() to propagate this information.

source
ResearchSoftwareMetadata.increase_minorFunction
increase_minor()

Increases the Project.toml version number by a minor number (e.g. 0.4.1 to 0.5.0), and then runs ResearchSoftwareMetadata.crosswalk() to propagate this information.

source
ResearchSoftwareMetadata.increase_patchFunction
increase_patch()

Increases the Project.toml version number by a patch (e.g. 0.4.1 to 0.4.2), and then runs ResearchSoftwareMetadata.crosswalk() to propagate this information.

source
ResearchSoftwareMetadata.migrate_rsmd!Method
ResearchSoftwareMetadata.migrate_rsmd!(project_d::AbstractDict)

Move any legacy top-level RSMD keys (description, keywords, category, development_status, publications, author_details) into the rsmd table, where they now live. Existing rsmd entries win on conflict. Returns the dictionary.

source
ResearchSoftwareMetadata.order_projectMethod
ResearchSoftwareMetadata.order_project(project_d::AbstractDict)

Take a parsed Project.toml dictionary and return it as an OrderedDict in canonical order — the order Pkg itself writes, applied recursively to nested tables — so that files written from it are not reordered when Pkg next edits them.

source
ResearchSoftwareMetadata.parse_authorMethod
ResearchSoftwareMetadata.parse_author(author::AbstractString)

Parse a Project.toml authors entry of the form "Name <email>" into a (name, email) tuple, where email is nothing if the entry contains no email address. Tolerates a missing closing bracket on the email.

source
ResearchSoftwareMetadata.project_key_orderMethod
ResearchSoftwareMetadata.project_key_order(key)

Sort key reproducing Pkg's Project.toml ordering: keys Pkg knows about sort by their position in its canonical list, all other keys sort alphabetically after them.

source
ResearchSoftwareMetadata.read_projectFunction
ResearchSoftwareMetadata.read_project()

Read a Project.toml file in, migrate any legacy top-level RSMD keys into the rsmd table, and return it in its canonical order in an OrderedDict.

source
ResearchSoftwareMetadata.reconcile!Method
ResearchSoftwareMetadata.reconcile!(project, codemeta, proj_key, cm_key;
                                    value = nothing, default = nothing,
                                    to_cm = identity, from_cm = identity,
                                    update = false)

Reconcile a metadata field between Project.toml (authoritative) and codemeta.json. An explicit value (e.g. from a keyword argument to crosswalk) takes precedence and is written into both; otherwise the Project.toml entry is used, fixing codemeta.json with a warning if it disagrees — or an informational message when update is true, meaning the Project.toml change is deliberate and should just propagate. If the field is missing from Project.toml but present in codemeta.json, it is backfilled into Project.toml. If it is absent from both, default is used for codemeta.json (when provided) without being backfilled. to_cm and from_cm convert values between the Project.toml and codemeta.json representations. Returns the Project.toml-side value, or nothing if the field is absent everywhere.

source
ResearchSoftwareMetadata.split_nameMethod
ResearchSoftwareMetadata.split_name(full_name::AbstractString)

Split a full name into given and family names, treating the last word as the family name. Returns a (givenName, familyName) tuple, where givenName is nothing if full_name contains only a single word.

source