Tracing provenance
What the pipeline records of every run - the code at its commit, what it read and what it wrote - is there to be asked. This page is what the package asks of it: what the registry knows about a file, whether the data stores hold what it records, where a file came from, what was made from it, how one version supersedes another, and the crate that packs the files of a paper with the provenance of each. None of it needs a token, so it all works outside fair run, against the local registry or a remote one.
Holding the local registry
Outside a run, each of these functions holds the local registry up through a session of the FAIR CLI's while it works: a session starts the registry where nothing holds it, and the last to close stops one a session started. Calls in a DataPipeline.registry_session block share its session, given its endpoint first; fair registry start keeps the registry running until fair registry stop.
DataPipeline.registry_session() do registry
DataPipeline.identify(registry, "results.csv")
DataPipeline.provenance(registry, "results.csv")
endDataPipeline.registry_session — Function
registry_session(f; remote = nothing)Call f with the RegistryEndpoint of the local registry, held up for as long as f runs through a session of the FAIR CLI's, which this process owns and closes when f returns or throws, and return what f returns. The endpoint is the registry the session names, with the token in the file it names. A session starts the registry where nothing holds it, and the last to close stops one a session started; a registry started by fair registry start runs until fair registry stop.
Each function that reads or writes a registry outside a run - identify, provenance, downstream, crate, register_release!, raise_issue! outside a run - holds a session for the call when given no endpoint, and takes this endpoint first to share one:
DataPipeline.registry_session() do registry
DataPipeline.identify(registry, "figures/summary.pdf")
DataPipeline.provenance(registry, "figures/summary.pdf")
endWith remote, the name of a remote in the project's CLI configuration, f is given that remote's endpoint instead, holding nothing. Under fair run, whose own session holds the registry, nothing is opened, and f is given the endpoint the CLI's configuration names.
Asking what the registry knows about a file or a repository
DataPipeline.identify takes a file, or commits of a git repository, and asks the registry the FAIR CLI is configured to use, or any other, what it knows about them. A selection of commits holds its repository: the top-level folder of a clone, or the URL of its remote, by default the repository holding the current directory. No token is needed, so it works outside fair run:
DataPipeline.identify("results.csv") # the local registry
DataPipeline.identify("results.csv", remote = "origin") # a remote of this project
DataPipeline.identify("results.csv", superseded = true) # and the inputs behind it since superseded
DataPipeline.identify(DataPipeline.AncestorCommits()) # this checkout's commit and its ancestors
DataPipeline.identify(DataPipeline.NamedCommit("v0.55.0")) # one commit, by tag, branch, hash or release
# every run of this repository, including those made with uncommitted changes
DataPipeline.identify(DataPipeline.AllCommits(dirty = true))
# a repository with no clone, by the registry's record of it alone
DataPipeline.identify(DataPipeline.AllCommits(repo = "https://github.com/FAIRDataPipeline/DataPipeline.jl"))A file's identification carries the source of a file registered from elsewhere, with the address it was fetched from; the issues raised on it and, behind it, the issues raised on anything a run on the way read, or on a run's own code, config or script, each with the run it reaches the file through; with superseded = true it lists the inputs behind the file that a newer version of has been registered since, as outdated rather than wrong.
DataPipeline.identify — Function
identify(path; remote = nothing, superseded = false)
identify(registry, path; superseded = false)
identify(handle, path; superseded = false)
identify(commits; remote = nothing)
identify(registry, commits)
identify(handle, commits)Ask a registry what it knows about a file on disk, or about commits of a git repository.
For a file, return a FileIdentification: the data products it is registered as, where the registry expects to find it, whether a newer version of any of those data products exists, the source of any that came from elsewhere with where the file was fetched from, the issues raised against it, and the issues raised on anything behind it - the inputs read on the way to it, at the versions read, and the code, config and script of the runs on the way - each with the run it reaches the file through. With superseded = true, the inputs read on the way that a newer version of has been registered since are reported too, as outdated rather than wrong. isempty(result.objects) means the registry has no record of a file with these contents. The file is identified by the SHA-1 of its contents, as everything in the pipeline is, so a copy under another name is recognised and an edited file is not.
For commits, an AbstractCommitSelection - such as AncestorCommits(), the checked-out commit of the repository holding the current directory and its ancestors - return a RepositoryIdentification: the code runs made from the selected commits, with their outputs, and any issues raised against those commits. The repository is known to the registry by the URL of its git remote - the one named by git.remote in its .fair/cli-config.yaml, else origin - or by the URL the selection was given as its repo. Runs made with uncommitted changes are included only when the selection is made with dirty = true. When the checkout itself has uncommitted changes, AncestorCommits of the checked-out commit and CheckedOutCommit warn and use its commit as committed.
Arguments
path::String: the file to ask about.commits::AbstractCommitSelection: the commits to ask about:AncestorCommits,CheckedOutCommit,AllCommitsorNamedCommit, each holding its repository.registry::RegistryEndpoint: the registry to ask, which needs no token, e.g.RegistryEndpoint("http://127.0.0.1:8000/api/"); aDataRegistryHandlemay be given instead, and its registry is used.remote: with no registry given, the registry is the CLI's local registry, or the remote registry of that name in the current project's CLI configuration; seeRegistryEndpoint.superseded: for a file, whether to report the inputs behind it that have been superseded.
DataPipeline.FileIdentification — Type
FileIdentificationWhat a registry knows about one file on disk, as returned by identify. objects is empty when the registry has never been told about a file with these contents.
Fields
path: the file asked abouthash: its SHA-1, which is how the registry identifies itobjects: theRegisteredObjects registered with that hashprovenance: theTraceback from every data product the file is registered as, ornothingfor a file the registry does not knowupstream: everyUpstreamIssuethe trace finds, nearest the file firstoutdated: everyOutdatedInputthe trace finds, when asked for withsuperseded = true, elsenothing
DataPipeline.RegisteredObject — Type
RegisteredObjectOne registry object a file is registered as: its description, where the registry expects to find it, what data products it serves and what problems are recorded against it. An object with no data products is one of a code run's own files - a working config, a submission script or a repository.
Fields
description: the object's descriptionurl: the object's URL in the registryroot: the storage root the file is registered underlocal_root: whether that root is on this machinestored_path: the file's path within that rootdata_products: theDataProductRecords it serves, if anyissues: theIssueRecords against it and its components
DataPipeline.DataProductRecord — Type
DataProductRecordA data product a file is registered as.
Fields
namespace: the namespace it is registered inname: its registered nameversion: the version this file isnewest: the newest version of the same name in the same namespace, which isversionitself unless the registry holds a later oneurl: its URL in the registryexternal_object: the URL of its external object record, if it came from outside the pipeline, elsenothingsource: that external object as aTraceSource- its identifier, title and release, and where the file was fetched from - elsenothing
DataPipeline.UpstreamIssue — Type
UpstreamIssueAn issue identify found behind a file: raised on something a run on the way to the file read, at the version it read, or on a run's own code repository, working config or submission script.
Fields
issue: theTraceIssueon: theTraceTargetof the issue that lies upstream of the filethrough: theTraceRunit reaches the file through - the run that read the thing, or whose own file it ismaking: theTraceProductthat run made on the way to the fileinput:truewhen the thing is a data product the run read,falsewhen it is the run's repository, config or script
DataPipeline.OutdatedInput — Type
OutdatedInputA data product read on the way to a file, as identify finds with superseded = true, that a newer version of has been registered since.
Fields
input: theTraceProductread, withsuperseded_bythe newer versionthrough: theTraceRunthat read itmaking: theTraceProductthat run made on the way to the file
DataPipeline.IssueRecord — Type
IssueRecordA problem recorded against something a file is registered as.
Fields
severity: how bad it is, as the registry holds it (larger is worse)description: what the problem iscomponent: the name of the object component it was raised against, ornothingwhen raised against the file as a wholeurl: its registry URLuuid: its uuid
An IssueRecord names the issue to downstream, as its issue.
DataPipeline.RepositoryIdentification — Type
RepositoryIdentificationWhat a registry knows about a git repository, as returned by identify. commits is empty when no run was made from any of the commits selected.
Fields
path: the repository's top-level folder, or its URL when the selection named it by that aloneremote: the URL of the git remote the registry knows it byhead: the checked-out commit, ornothingwith no clonedirty: whether the working tree has uncommitted changes to tracked files;falsewith no cloneselection: theAbstractCommitSelectionasked forcommits: theRegisteredCommits selected, newest commit first; those the local clone does not have come last, newest first by their earliest run
DataPipeline.RegisteredCommit — Type
RegisteredCommitA commit of a git repository that the registry holds runs for.
Fields
sha: the commit's hashdirty: whether its runs were made from a working tree with uncommitted changes, which the registry records as<sha>-dirtydate: its commit date, in UTC, ornothingwhen the local clone does not have itobjects: the URLs of the registry objects that stand for itruns: theCodeRunRecords made from it, newest firstissues: theIssueRecords raised against itrelease: theTraceReleaseit is, ornothing
DataPipeline.CodeRunRecord — Type
CodeRunRecordA code run the registry holds.
Fields
uuid: its uuid, by whichfairandcoderuns.txtrefer to itrun_date: when it ran, in UTC, as the registry records itdescription: its descriptionurl: its URL in the registryoutputs: theDataProductRecords it wrote
DataPipeline.AbstractCommitSelection — Type
AbstractCommitSelectionCommits of a git repository: which commits, of which repository, and whether the runs made from them with uncommitted changes are included, which the registry records as <sha>-dirty. identify and downstream take one in place of a file, and raise_issue! takes one as a target. The selections are AncestorCommits, CheckedOutCommit, AllCommits and NamedCommit.
Each has a repo field and a dirty field, set by its constructor's keywords of the same names. repo is the repository: the top-level folder of a clone, as an absolute path, or the URL of its remote, which leaves the registry's record alone to go by. Given, a folder must be the top level of a repository; left out, it is the clone of the run open in this session, else the repository holding the current directory. A selection that needs a clone - the checked-out commit, or ancestors - cannot be made with a URL.
DataPipeline.AncestorCommits — Type
AncestorCommits(; of = nothing, including = true, repo = nothing,
dirty = false)Select a commit and every commit it descends from - the code it grew from - and, if dirty, the runs made from them with uncommitted changes too. Finding ancestors needs a clone holding the commit.
Arguments
of: the commit to start from, named asNamedCommitnames one: a tag, a branch, a commit hash or the version of a registered release of the code; or aRegisteredRelease, whose commit and clone it is, so thatreponeed not be given.nothing, the default, is the checked-out commit.including: whether that commit is selected itself; withfalse, only the commits before it, and so not the runs made from it with uncommitted changes either.repo: the clone, as for everyAbstractCommitSelection.dirty: whether the runs made with uncommitted changes are selected too.
DataPipeline.CheckedOutCommit — Type
CheckedOutCommit(; repo = nothing, dirty = false)Select only the checked-out commit of a clone and, if dirty, the runs made from it with uncommitted changes too. repo is the clone, as for every AbstractCommitSelection.
DataPipeline.AllCommits — Type
AllCommits(; repo = nothing, dirty = false)Select every commit of a repository that the registry holds runs for, whether or not the local clone has it, and, if dirty, the runs made from them with uncommitted changes too. repo is a clone or the URL of its remote, as for every AbstractCommitSelection.
DataPipeline.NamedCommit — Type
NamedCommit(name; repo = nothing, dirty = false)
NamedCommit(release; dirty = false)Select one commit by name: a full commit hash, as it is; a tag, a branch or an abbreviated hash, resolved by the local clone; or the version of a release of the code that the registry holds, with or without a leading v, which resolves with no clone at all. If dirty, the runs made from the commit with uncommitted changes too. repo is a clone or the URL of its remote, as for every AbstractCommitSelection; by URL, a tag or a branch is resolved by asking the remote, which needs the network and a remote that asks for no credentials, and an abbreviated hash does not resolve. A RegisteredRelease names its commit, of the clone it was registered from, else of its remote.
Checking the data store
DataPipeline.check_store checks the data stores on this machine - the folders of registered files that each project writes to - against the local registry: the registered files that are missing or whose contents have changed, the files there that the registry does not know, the storage locations that nothing uses, and the outputs a run left unfinished. It changes nothing.
DataPipeline.check_store() # hashing every registered file
DataPipeline.check_store(hashes = false) # whether each is there, reading none
DataPipeline.check_store(quiet = false) # every missing file, and the CLI's ownA store whose folder has gone is reported in one line, and missing files beyond a few are counted rather than listed. A changed file with more than one name was most likely written to through another. One with more than one name and the correct contents is reported as shared, since a write through any of its names would change it: a copy moved over it gives it a name of its own.
DataPipeline.check_store — Function
check_store(; hashes = true, quiet = true)
check_store(registry; hashes = true, quiet = true)
check_store(handle; hashes = true, quiet = true)Check the data stores on this machine against the local registry, and return a StoreCheck, shown as a report. A data store is a storage root that is a folder on this machine - a file:// root marked local, as fair and the APIs register each project's - and every one is checked. Found are the registered files that are missing, whose contents are not those registered, or that have another name - a hard link, through which writing to a file elsewhere changes the registered one; the files in a store that the registry does not know; the storage locations that nothing uses; and the outputs that a run left under their temporary names, dat-..., as one that fails before finalise does. The check changes nothing: it deletes, moves, fetches and registers nothing.
The calls that put a file in a data store, such as link_write! with a path, never link it. A copy of a shared file moved over it gives it a name of its own.
Arguments
registry: the registry whose data stores are checked, aRegistryEndpoint, which needs no token; aDataRegistryHandlemay be given instead, and its registry is used. With neither, the CLI's local registry, held through a session of the CLI's while the check runs.hashes: whether to hash each registered file, which reads every byte, to find those whose contents have changed; withfalse, only whether each is there is checked.quiet: whether the report leaves out the CLI's own files underjobs/- each run'scoderuns.txt, the working config of a job no run registered - and summarises the missing files rather than listing each, giving a store whose folder has gone in one line. The check holds every finding either way.
DataPipeline.StoreCheck — Type
StoreCheckWhat check_store found in the data stores on this machine, shown as a report.
Fields
roots: each data store checked, as(root, folder, exists, locations): its storage root, the folder that is, whether the folder exists, and how many storage locations the registry holds under itmissing: each registered file that is not there, as(path, location, hash): where it should be, the URL of its storage location and the SHA-1 registeredchanged: each registered file whose contents are not those registered, as(path, location, hash, found, links): also its SHA-1 now and how many names it has, more than one where it is hard-linked; empty when the check was made withhashes = falseshared: each registered file that has more than one name - a hard link, through which writing to a file elsewhere changes it - and is not inchanged, as(path, location, hash, links): also how many names it hasunknown: each file in a data store that the registry has no storage location for, other than those inunfinishedandcli_filesunused: each storage location that nothing uses - no object, and no source as where it was fetched from - as(path, location, hash); its file is not checked furtherunfinished: each output that a run left under its temporary name,dat-..., as(path, modified), its modification time in UTC; a run in progress has them toocli_files: each file under a store'sjobs/folder that is not registered, which the CLI keeps there, such as a run'scoderuns.txthashes: whether the registered files were hashed, so thatchangedwas checkedquiet: whether the report leaves out the CLI's files and summarises the missing files rather than listing each
Where a file came from
DataPipeline.provenance traces a data product back: the run that made it, what that run read, the runs that made those, and so on to the data registered from elsewhere, each with its source. It takes a file, or a data product named namespace:name@version as the pipeline names one, and prints as a tree, newest first, each data product once:
DataPipeline.provenance("figures/summary.pdf")
DataPipeline.provenance("testing:SEIRS_model/report/julia@v0.0.1")
DataPipeline.provenance("testing:SEIRS_model/report/julia", depth = 2) # two runs backProvenance of testing:SEIRS_model/report/julia@v0.0.1 sha1 c896cfb9
<- run a1b118f0 on 2026-10-15 11:33 UTC, github.com/FAIRDataPipeline/DataPipeline.jl.git at 34d3bdca
used testing:SEIRS_model/summary/julia@v0.0.1 sha1 b6ae4389
issue, severity 3: an issue over an input and an output
<- run 577160a1 on 2026-10-15 11:33 UTC, github.com/FAIRDataPipeline/DataPipeline.jl.git at 34d3bdca
used PSU:SEIRS_model/parameters@v1.0.0 sha1 6294a595 superseded by v1.0.1 from https://doi.org/10.1038/s41592-020-0856-2 (supplement)
issue, severity 2: an issue on the parameters
used testing:SEIRS_model/results/model_output/julia@v0.0.1 sha1 e8912ec2
<- run c30fbbdd on 2026-10-15 11:33 UTC, github.com/FAIRDataPipeline/DataPipeline.jl.git at 34d3bdca
used PSU:SEIRS_model/parameters@v1.0.0 (above)The value holds more than the tree prints - every data product, run and issue reached, keyed by registry URL - for a script to work over.
DataPipeline.provenance — Function
provenance(x; remote = nothing, depth = nothing)
provenance(registry, x; depth = nothing)
provenance(handle, x; depth = nothing)Trace where a data product came from: the run that made it, what that run read, the runs that made those, and so on back to the data products that no run made, each with its source. Return a Trace{Upstream}, which prints as a tree, and holds every data product, run and issue reached, keyed by registry URL.
x names the data product: a file, whose contents identify it as identify does, every data product it is registered as being a root of the trace; or namespace:name@version, as the pipeline names one, with namespace:name meaning its newest version. The registry is the one the FAIR CLI is configured to use, or the project's remote named by remote, or registry, or the one handle was opened on; no token is needed.
depth is how many runs back along any path to go. By default the trace goes to the end of every path, and a data product that no run made is a root; with depth given, a data product at that depth that a run made is marked beyond, and the tree says so.
Every data product's line says whether a newer version of its name has been registered since, and the issues raised on it; an issue raised on several things is one issue, with each of them among its targets.
DataPipeline.Trace — Type
Trace{D <: AbstractTraceDirection}What provenance and downstream return: the data products, runs and issues reached from one or more data products in one direction, D, each kept once by its registry URL. Printed as a tree from the roots.
Fields
registry: theRegistryEndpointit was read fromroots: the registry URLs of the data products it starts fromproducts: everyTraceProductreached, by URLruns: everyTraceRunreached, by URLissues: everyTraceIssueraised on any of them, by URLdepth: the number of runs along any path it was cut at, ornothingfor a trace that reaches the end of every path
DataPipeline.TraceProduct — Type
TraceProductOne version of a data product in a Trace.
Fields
url: its registry URL, the key it has in the tracenamespace,name,version: what names ithash: the SHA-1 of its file - for a code repository's release, its commit - ornothingfor a data product with no filelocation: where the registry says the file is, ornothingdescription: its description, ornothingformat: the extension of its file type, astxt, ornothingsource: itsTraceSource, ornothingwhen it has nonesuperseded_by: the highest version of its name in its namespace, when that is a newer one, elsenothingmade_by: the registry URL of the run in the trace that made it, ornothingwhen the trace holds nonebeyond:truewhen the trace was cut at this data product by itsdepth: a run that made it, going upstream, or that read it, going downstream, is not heldissues: the registry URLs of the issues raised on it or its components
DataPipeline.TraceRun — Type
TraceRunA code run in a Trace.
Fields
url: its registry URL, the key it has in the traceuuid: its uuiddate: when it started, in UTCdescription: its descriptionrepository: the URL of the code repository it ran from, ornothingcommit: the commit it ran at,<sha>-dirtyfor a working tree with uncommitted changes, ornothingrelease: theTraceReleasethat commit is, ornothingconfig: where the registry says its working config is, ornothingscript: where the registry says its submission script is, ornothinginputs: the registry URLs of the data products it read that the trace holdsoutputs: the registry URLs of the data products it wrote that the trace holdsobjects: the registry URLs of the objects that stand for its repository, config and script, those it has, which an issue on any of them namesissues: the registry URLs of the issues raised on its repository, config or script
DataPipeline.TraceIssue — Type
TraceIssueAn issue in a Trace: a problem recorded in the registry against one or more things, whether or not the trace holds them all.
Fields
url: its registry URL, the key it has in the traceuuid: its uuidseverity: how bad it is, larger for worsedescription: what the problem istargets: everything it is raised on, asTraceTargets
DataPipeline.TraceSource — Type
TraceSourceThe source of a data product, in a Trace or a DataProductRecord: the external object it was registered from.
Fields
url: the external object's registry URLidentifier: its DOI or other identifier, ornothingtitle: its title, ornothingversion: the source's own release version, ornothingdate: its release date, ornothinglocation: where the file was fetched from, ornothingprimary:truewhen the registered bytes are the identified item or one of its files,falsefor a supplement requested or derived from it
DataPipeline.TraceRelease — Type
TraceReleaseThe release of the code that a commit is, as a run in a Trace, or a commit that identify reports, was made from it; see register_release!.
Fields
name: the release's name, the path of the repository's remote, asFAIRDataPipeline/DataPipeline.jlversion: its version, the highest the registry holds for the commitwebsite: its web page, ornothingdoi: the DOI it is cited by, as a URL, ornothing
DataPipeline.TraceTarget — Type
TraceTargetOne thing a TraceIssue is raised on.
Fields
url: the registry URL of the data product, or of the object for a code repository, working config or submission scriptlabel: the data product asnamespace:name@vX.Y.Z, else the object's description and where it iscomponent: the named component the issue is on, ornothingfor the whole thing
What was made from a file
DataPipeline.downstream traces the other way: the runs that read a data product, what they wrote, the runs that read those, and on to the end of every path. It answers "I have found a problem in this - what must be made again?": every data product reached that no newer version has superseded. It starts from a data product, from everything the runs of selected commits wrote, or from everything an issue is raised on, and prints as the mirror image of provenance:
DataPipeline.downstream("PSU:SEIRS_model/parameters@v1.0.0")
DataPipeline.downstream(DataPipeline.NamedCommit("v0.55.0")) # what this release's runs made, and on
DataPipeline.downstream(issue = 12) # what an issue affectsDataPipeline.downstream — Function
downstream(x; remote = nothing, depth = nothing)
downstream(registry, x; depth = nothing)
downstream(handle, x; depth = nothing)
downstream(; issue, remote = nothing, depth = nothing)
downstream(registry; issue, depth = nothing)
downstream(handle; issue, depth = nothing)Trace what was made from a data product: the runs that read it, what they wrote, the runs that read those, and so on to the end of every path. Return a Trace{Downstream}, which prints as a tree, and holds every data product, run and issue reached, keyed by registry URL. What must be made again, now that a problem is known in the start, is every data product reached that no newer version has superseded.
x names the start: a file, whose contents identify it as identify does, every data product it is registered as being a root; or namespace:name@version, as the pipeline names one, with namespace:name meaning its newest version; or an AbstractCommitSelection, such as AncestorCommits(), every data product the runs of the commits it selects wrote being a root, the commits found as identify finds them. With issue, the start is everything the issue is raised on - each data product, at the version it is on, and everything the runs made whose code repository, working config or submission script it is on - so that what the problem affects is what the trace holds. The issue is a TraceIssue or an IssueRecord from a trace or identify, its uuid, its registry URL, or the number the registry's own pages show it by. The registry is the one the FAIR CLI is configured to use, or the project's remote named by remote, or registry, or the one handle was opened on; no token is needed.
depth is how many runs forward along any path to go. By default the trace goes to the end of every path; with depth given, a data product at that depth that a run read is marked beyond, and the tree says so. Every data product's line says whether a newer version of its name has been registered since, and the issues raised on it.
Superseding a version
Data is often not wrong but out of date: a dataset is updated, and what was made from the old version is worth making again, though the old version was right in its day. supersede = true on a write says so. Once the new version is registered, an issue reading Superseded by namespace:name@vX.Y.Z is raised on the version before it, at severity 0, the lowest, so that identify of anything made from the old version reports it, and downstream of the old version is what to make again:
link_write!(handle, "era5/t2m/2021", path = "cache/era5_t2m_2021.nc", doi = era5,
primary = false, supersede = true)Where there is nothing to supersede - the file is identical to the version before, or the name has no version before - nothing is raised and an info message says so.
Releases of the code
A run records the commit of the code it ran. DataPipeline.register_release! records that a commit is a release - its version read from the commit's tag, v1.2.0 say, its authors and licence from the first of the repository's codemeta.json, .zenodo.json, CITATION.cff and project file that it has - as the registry's release record and as a data product, <organisation>:<repository>@<version>, which the traces and the crate take as they take any data product. A release then names the code before it, so that a problem fixed in it can be raised on everything it was found in. Its DOI - doi = "10.5281/zenodo...", or for a repository with a .zenodo.json the Zenodo DOI of its tag's version, found there - is the data product's source; one that Zenodo has not minted yet is attached by calling register_release! again later:
release = DataPipeline.register_release!(DataPipeline.NamedCommit("v1.2.0"))
raise_issue!(DataPipeline.AncestorCommits(of = release, including = false),
"Bug X, fixed in v1.2.0")DataPipeline.register_release! — Function
register_release!(commit = CheckedOutCommit(); website = nothing,
remote = nothing)
register_release!(registry, commit = CheckedOutCommit(); website = nothing)
register_release!(handle, commit = CheckedOutCommit(); website = nothing)Register a commit of a code repository as a release of the code, and return the RegisteredRelease. The version is the commit's tag that reads as a semantic version - v1.2.0, 1.2.0-beta2 - written in full; a commit with none cannot be released.
Registered, each found rather than made where the registry holds it already: the repository's object at the commit, made as initialise makes one, with the authors, licence and keywords of the repository's metadata files; the registry's record that the commit is a release, named by the remote's path, as FAIRDataPipeline/DataPipeline.jl; and a data product of the release, <organisation>:<repository>@<version>, on the same object, so that a trace and a crate take the release as they take any data product. A second call on a release changes nothing.
The release's DOI, where it has one, is its data product's source: the version DOI given as doi, or, for a repository whose .zenodo.json says Zenodo archives its releases from GitHub, the DOI of the Zenodo version of its tag, looked up there. The DOI's metadata - its title, release date and description - describes the source, and is compared with the repository's metadata files: a difference in the authors, title, licence or version is warned of, an identifier one gives and the other lacks told of. A DOI given that cannot be looked up is an error; a Zenodo version not archived yet, or a lookup that cannot reach Zenodo or GitHub, is told of, and the release is registered without a source, which calling register_release! again attaches once it can.
A commit released already under another version - a beta, say, retagged as a release - has the new version's data product registered and its release record changed to the new version, where the registry allows it; where not, a warning says that the record keeps the old version.
While the session rehearses a run, what would be registered is printed, and nothing is.
Arguments
commit: the commit to release:CheckedOutCommit, the default, which a checkout with uncommitted changes cannot be, or aNamedCommit- a tag, a branch or a hash - whatever the checkout holds. Either holds its repository: a clone, or for aNamedCommitthe URL of its remote, whose tags are then listed over the network and, on GitHub, whose metadata files are read at the commit.website: the release's web page; by default, for a remote on GitHub, the page of the release of its tag.doi: the DOI of the version released, bare or as a URL - not a concept DOI standing for every version.registry::RegistryEndpoint: the registry to register it in, which needs its token; aDataRegistryHandlemay be given instead, and its registry is used.remote: with no registry given, the remote registry of that name in the current project's CLI configuration, else the CLI's local registry.
DataPipeline.RegisteredRelease — Type
RegisteredReleaseA release of the code that the registry holds, as register_release! returns it: the registry's record that a commit of a code repository is a release, and the data product registered with it, which carries its source.
Fields
url: the registry URL of the release record, which holdsversionunlessregister_release!warned that it could not be changedname: the release's name, the remote's path, asFAIRDataPipeline/DataPipeline.jlversion: the version releasedwebsite: the release's web page, ornothingpath: the top-level folder of the clone it was registered from, ornothingwhere it was registered by the remote's URLrepository: the URL of the repository's remotecommit: the commit releasedobject: the registry URL of the repository's object at that commit, which the release record and the data product are ondata_product: theDataProductRecordof the release's data product,<organisation>:<repository>@<version>source: the registry URL of the release's source, ornothing
The crate for a paper
DataPipeline.crate fetches the RO-Crate the registry builds for data products: a package of their files with the provenance of each, in which every run with its code at its commit, everything it read, and each data product with its source and its issues travel together. The paper's figures in one folder is the case in mind:
DataPipeline.crate("figures") # the metadata, parsed
DataPipeline.crate("figures", to = "paper.zip") # the zip, files packed
DataPipeline.crate("paper", strict = false) # the sources left out, and saidDataPipeline.crate — Function
crate(paths...; remote = nothing, depth = 100, level = nothing,
pack = nothing, to = nothing, strict = true)
crate(registry, paths...; depth = 100, level = nothing, pack = nothing,
to = nothing, strict = true)
crate(handle, paths...; depth = 100, level = nothing, pack = nothing,
to = nothing, strict = true)Fetch the RO-Crate the registry builds for data products: a package of their files with the provenance of each, as a crate's metadata describes it, in which every run with its code at its commit, everything it read, each data product with its source and its issues travel together.
Each of paths is a file, a folder, or a data product named namespace:name@version (namespace:name for its newest version). A file is identified by its contents, as identify identifies one, and every data product it is registered as is a root of the crate; a folder means every file under it, the paper's figures in one folder being the case in mind. Files and folders whose names begin with a dot are left out and reported. A file the registry does not know is an error; with strict = false such files are left out and reported, so that a folder may hold the paper's sources beside its figures.
depth is how many runs back the crate goes along any path, 100 by default. level and pack are the registry's: level 1 or 2, what travels with each file, and pack one of "none", "roots", "supplements" and "all", whose bytes a zip holds; left out, the registry's defaults apply.
Without to, return the crate's metadata, its ro-crate-metadata.json, parsed: a dictionary with "@context" and "@graph". With to, a path ending in .zip, save the crate there as that zip, the metadata and the files pack chooses, and return the path; a path ending in .json saves the metadata there. The registry is the one the FAIR CLI is configured to use, or the project's remote named by remote, or registry, or the one handle was opened on; no token is needed.
Index
DataPipeline.AbstractCommitSelectionDataPipeline.AllCommitsDataPipeline.AncestorCommitsDataPipeline.CheckedOutCommitDataPipeline.CodeRunRecordDataPipeline.DataProductRecordDataPipeline.FileIdentificationDataPipeline.IssueRecordDataPipeline.NamedCommitDataPipeline.OutdatedInputDataPipeline.RegisteredCommitDataPipeline.RegisteredObjectDataPipeline.RegisteredReleaseDataPipeline.RepositoryIdentificationDataPipeline.StoreCheckDataPipeline.TraceDataPipeline.TraceIssueDataPipeline.TraceProductDataPipeline.TraceReleaseDataPipeline.TraceRunDataPipeline.TraceSourceDataPipeline.TraceTargetDataPipeline.UpstreamIssueDataPipeline.check_storeDataPipeline.crateDataPipeline.downstreamDataPipeline.identifyDataPipeline.provenanceDataPipeline.register_release!DataPipeline.registry_session