Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

META6 specification only exists "de facto" #236

Open
JJ opened this issue Sep 29, 2020 · 53 comments
Open

META6 specification only exists "de facto" #236

JJ opened this issue Sep 29, 2020 · 53 comments
Labels
language Changes to the Raku Programming Language

Comments

@JJ
Copy link
Contributor

JJ commented Sep 29, 2020

The META6 format was defined in S22, and is arguably not part of the language. There's a single test for S22, but it does not really check an interpreter of that format, just that the format can be used correctly.
The interpreters of this format are, in general, external utilities

  • zef has probably got the most complete implementation, since it really needs it to find the correct dependencies.
  • META6 is not as complete, and until recently, it could not actually understand Associative values for depends. This is the one, BTW, used by Test::META, which is what we use to test p6c new modules.
  • Pakku::Meta was added yesterday to the ecosystem (it might have existed before as part of another distribution).

As far as I understand, there're no tests that cover all posibilities in S22, not even "currently adopted" possibilities. zef is the standard de facto, so the test we have now is "if it goes with zef, we're good". But not having a common set of (roast or roast-like) tests is an obstacle for evolution, should we need to extend it somehow (as was suggested here).

There are also a number of ambiguities that are not solved; mainly with the "depends" key and the "source-url" key. Build dependencies can appear in the depends → requires → key and in the build-depends key. Is there any precedence? Should we take both into account?

@JJ JJ added the meta Changes to this repo and the main document label Sep 29, 2020
@JJ JJ assigned jnthn Sep 29, 2020
@jonathanstowe
Copy link

I would say that it would probably benefit in the first place from a machine readable specification (probably JSON Schema,) with some annotation describing the roles and responsibilities of parsers, testers, installers, the core and so forth.

I'm guessing that extension could be achieved with JSON prefixes (e.g. prefix:name ,) but I'm not clear how these can be properly disambiguated like you might with XML Schema at the moment.

@JJ
Copy link
Contributor Author

JJ commented Sep 29, 2020

However, we should also check that meaning is what it should be, and resolve ambiguities, but yes, JSON Schema would be a nice first step.

@jonathanstowe
Copy link

I'm not going to share the whole generated schema right now because there are a couple of things that aren't expressed well in a simple schema, but it looks like people have already been extending it themselves without causing any great harm to the tools, here is the complete list of top level properties found in all the extent META files:

abstract
aoi
api
auth
author
authors
build
build-depends
builder
depends
description
dynamic_config
emulates
excludes
generated_by
history
license
meta6
meta-spec
meta-version
name
no_index
perl
prereqs
production
provides
raku
release_status
repo-type
resources
source
source-type
source-url
superseded-by
supersedes
support
tags
test-depends
version
x_serialization_backend

:-D

@jonathanstowe
Copy link

Interestingly it seems that at least seven of the META files that are fetched by the zef CPAN backend were generated by the Perl 5 toolchain which would explain some of the weirder outliers above.

@jonathanstowe
Copy link

Okay leaving out the ones that appear to be Perl 5 meta files we have:

aoi
api
auth
author
authority
authors
bin
build
build-depends
builder
creator
depends
description
emulates
excludes
history
licence
license
meta6
meta-version
name
perl
production
provides
raku
raku: 
repo-type
resource
resources
scripts
source
source-type
source-url
superseded-by
supersedes
support
tags
test-depends
version

The aoi is mine and the raku: appears to be all of the modules of @ramiroencinas for some reason. Altogether more sensible and I may be able to smack the generated schema into something useable.

@jonathanstowe
Copy link

The builder and build seem to be some extension that both zef and Distribution::Builder::MakeFromJSON know about but seem to be undocumented anywhere. The object version of requires seems to be similarly mostly undocumented and should be clarified in word and a schema rather than example and folklore.

I think however that I can get a schema that will validate most instances.

@JJ
Copy link
Contributor Author

JJ commented Sep 29, 2020 via email

@jonathanstowe
Copy link

Well, it would be stick it in it's own repository with tagged versions and so forth, probably the tags would align with some meta-version ....

@ugexe
Copy link
Contributor

ugexe commented Sep 29, 2020

We should be wary of specifying things raku does not itself use. For instance it would seem a bit odd to me for the roast to specify what source-url, an ecosystem specific field, is supposed to mean. Raku doesn’t even have a way to parse dependency specifications from depends (nor does it use them currently), so how can we reasonably spec that?

Having a schema and tooling seems perfectly reasonable. Speccing everything in the roast seems short sighted.

@jonathanstowe
Copy link

Personally, I'm not leaning toward speccing this in roast - I agree that is largely ecosystem specific, but it should be specified somewhere.

@ramiroencinas
Copy link

The raku: value isn't correct in some of my modules. I meant raku.
Can I correct it without breaking anything?

@JJ
Copy link
Contributor Author

JJ commented Sep 29, 2020 via email

@hythm7
Copy link

hythm7 commented Sep 29, 2020

It would be great if META6 can validate the depends section and its sub sections like hints as well, Something similar to what it does for support section.

@jonathanstowe
Copy link

The raku: value isn't correct in some of my modules. I meant raku.
Can I correct it without breaking anything?

Sure, if your modules are in the github ecosystem then you can just update in your repository, if they're in CPAN you may need to up the version and re-upload. 👍

@ugexe
Copy link
Contributor

ugexe commented Sep 29, 2020

fwiw I wrote a web service with a very naive and very incomplete validation using OpenAPI which might be useful for prototyping or bootstrapping such a validation service -- https://github.com/ugexe/Perl6-App--OpenAPI--META6Validator

@jonathanstowe
Copy link

It would be great if META6 can validate the depends section and its sub sections like hints as well, Something similar to what it does for support section.

The problem is that these things aren't completely specified anyway, that's what we're trying to get at here. Though META6 isn't actually designed as a validator per-se, it's just to facilitate validation by other modules.

@jonathanstowe
Copy link

This is my first cut at a schema that will validate at least some of the META6 in the wild:

{
   "$schema" : "http://json-schema.org/draft-04/schema#",
   "definitions" : {
      "dependency-specification" : {
         "items" : {
            "oneOf" : [
               {
                  "type" : "string"
               },
               {
                  "type" : "object",
                  "properties" : {
                     "name" : {
                        "oneOf" : [
                           {
                              "type" : "string"
                           },
                           {
                              "properties" : {
                                 "by-distro.name" : {
                                    "properties" : {},
                                    "type" : "object"
                                 }
                              },
                              "type" : "object"
                           }
                        ]
                     },
                     "from" : {
                           "type" : "string"
                     }
                  },
                  "required" : [
                     "name",
                     "from"
                  ]
               }
            ]
         },
         "type" : "array"
      },
      "dependency-specifications" : {
         "properties" : {
            "requires" : {
               "$ref" : "#/definitions/dependency-specification"
            },
            "recommends" : {
               "$ref" : "#/definitions/dependency-specification"
            }
         },
         "type" : "object",
         "required" : [
            "requires"
         ]
      }
   },
   "type" : "object",
   "properties" : {
      "api" : {
         "type" : [
            "string",
            "number"
         ]
      },
      "auth" : {
         "type" : "string"
      },
      "authors" : {
         "items" : {
            "type" : "string"
         },
         "type" : "array"
      },
      "build" : {
         "properties" : {
            "makefile-variables" : {
               "type" : "object"
            }
         },
         "type" : "object"
      },
      "build-depends" : {
         "items" : {
            "type" : "string"
         },
         "type" : "array"
      },
      "builder" : {
         "type" : "string"
      },
      "depends" : {
         "oneOf" : [
            {
               "type" : "array",
               "items" : {
                  "type" : "string"
               }
            },
            {
               "type" : "object",
               "properties" : {
                  "build" : {
                     "$ref" : "#/definitions/dependency-specifications"
                  },
                  "runtime" : {
                     "$ref" : "#/definitions/dependency-specifications"
                  },
                  "test" : {
                     "$ref" : "#/definitions/dependency-specifications"
                  }
               }
            }
         ]
      },
      "description" : {
         "type" : "string"
      },
      "emulates" : {
         "properties" : {},
         "type" : "object"
      },
      "excludes" : {
         "properties" : {},
         "type" : "object"
      },
      "history" : {
         "items" : {
            "type" : "string"
         },
         "type" : "array"
      },
      "license" : {
         "items" : {
            "type" : "string"
         },
         "type" : [
            "array",
            "string",
            "null"
         ]
      },
      "meta-version" : {
         "type" : [
            "number",
            "string"
         ]
      },
      "name" : {
         "type" : "string"
      },
      "perl" : {
         "type" : "string"
      },
      "production" : {
         "type" : "boolean"
      },
      "provides" : {
         "properties" : {},
         "type" : "object"
      },
      "raku" : {
         "type" : "string"
      },
      "repo-type" : {
         "type" : "string"
      },
      "resources" : {
         "items" : {
            "oneOf" : [
               {
                  "type" : "null"
               },
               {
                  "type" : "string"
               }
            ],
            "type" : "string"
         },
         "properties" : {},
         "type" : "array"
      },
      "source-type" : {
         "type" : "string"
      },
      "source-url" : {
         "type" : "string"
      },
      "superseded-by" : {
         "type" : "object",
         "properties" : { }
      },
      "supersedes" : {
         "type" : "object",
         "properties" : {}
      },
      "support" : {
         "type" : "object",
         "properties" : {
            "bugtracker" : {
               "type" : "string"
            },
            "email" : {
               "type" : "string"
            },
            "irc" : {
               "type" : "string"
            },
            "license" : {
               "type" : "string"
            },
            "source" : {
               "type" : "string"
            }
         }
      },
      "tags" : {
         "type" : "array",
         "items" : {
            "type" : "string"
         }
      },
      "test-depends" : {
         "type" : "array",
         "items" : {
            "type" : "string"
         }
      },
      "version" : {
         "type" : "string"
      }
   },
   "required" : [
      "auth",
      "authors",
      "depends",
      "description",
      "license",
      "meta-version",
      "name",
      "perl",
      "provides",
      "resources",
      "version"
   ]
}

The required keys are up for discussion obviously and there may be some detail missing in the polymorphic depends.

I'll stick some annotations in later.

@niner
Copy link

niner commented Sep 30, 2020 via email

@JJ
Copy link
Contributor Author

JJ commented Sep 30, 2020

build is builder-specific, i.e. it's a place designated for information that the module specified as builder will use. Currently the only builder implementation is Distribution::Builder::MakeFromJSON All information in build and depends is subject to System::Query collapsing, i.e. at any point you can specify an object with a by- something.property key and the whole object gets replaced with one of the appropriate values. The "somethings" in the key may be env, env-exists for checking environment variables or distro, kernel, backend for Raku's $*DISTRO, $*KERNEL, $*BACKEND objects respectively. E.g. the whole depends section may depend on the distro name. Or just the version of one of the dependencies may depend on the VM backend. The depends section may also contain alternatives via an object with an any key: "depends": [ "Foo", {"any": ["Bar", "Baz"]} ] ``` This (and much more) is specified in S22: https://github.com/Raku/old-design-docs/blob/master/S22-package-format.pod I don't understand why this is called "mostly undocumented"?

Apparently, because those documents needed some updating. Also, it's not anywhere else, and anyway design documents are, literally:

may be out of date... See docs.raku.org for documentation, or the official test suite.

The documentation in docs.raku.org about META6.json is not an specification, anyway.

The build-depends and test-depends keys are deprecated. The depends key itself is not required (after all a module may just not have any dependencies). Same for the resources key. I would argue that this is even true for the provides key. A distro may just contain resources and no modules. Or even more realistic, it can be just a collection of dependencies like Task::Galaxy.

Well, that might also be underdocumented. In this issue (from exactly one month ago), you can read:

test-depends isn't deprecated, and I'm not sure why anyone would assume it is.

So, maybe, just maybe, we would need a little specification here?

@niner
Copy link

niner commented Sep 30, 2020 via email

@jonathanstowe
Copy link

This (and much more) is specified in S22: https://github.com/Raku/old-design-docs/blob/master/S22-package-format.pod I don't understand why this is called "mostly undocumented"?

Largely the old-design-docs and the versioning information at the top of it :-D Might I suggest that, if it is considered a living document, we move it somewhere more obvious (maybe even part of the output of this issue.)

@JJ
Copy link
Contributor Author

JJ commented Sep 30, 2020

This (and much more) is specified in S22: https://github.com/Raku/old-design-docs/blob/master/S22-package-format.pod I don't understand why this is called "mostly undocumented"?

Largely the old-design-docs and the versioning information at the top of it :-D Might I suggest that, if it is considered a living document, we move it somewhere more obvious (maybe even part of the output of this issue.)

For instance, to a tool that helps us validate a META6.json including a JSON schema and its outcomes.

@jonathanstowe
Copy link

jonathanstowe commented Sep 30, 2020

All information in build and depends is subject to System::Query collapsing,

This part makes providing an exhaustive schema for a META6 and any static validation against such a schema rather tricky as it is the result of the collapsing that needs to be validated because, as I understand it, the collapsing can apply to any part of the JSON to produce a value. I think a validator would need a schema with annotations to indicate which parts are subject to collapsing, pre-process those parts with System::Query and then validate the resulting structure. This may also imply that for a properly comprehensive validation there needs to be something that does what System::Query does with the result but, rather than actually taking the values from the running system, would be able to reflect the properties being queried for and allow a validator to call the collapsing method with those values in turn, which sounds like a fun project for someone :-D

@JJ
Copy link
Contributor Author

JJ commented Sep 30, 2020

I really had to look up what you mean by System::Query "collapsing". Apparently it refers to this module. Again, we really need a specification with annotations for META6.json, so that we can enter deprecation cycles for some keys or whatever is needed to carry this forward.

jonathanstowe referenced this issue in Raku/old-design-docs Sep 30, 2020
An attempt at implementation has shows that using lists for dependency
alternatives causes confusion and is not self-documenting enough as the depends
section itself consists of a list. Using an object with an any key is more
clear and lends itself to future expansion.

Collapsing of system specific values has always been meant to also cover
dependencies. This is now stated explicitly and the details on what's available
described.

The build-depends and test-depends keys are deprecated. They should not have
been part of the v1 META spec. Leaving them in was just an oversight.
@jonathanstowe
Copy link

FWIW, it may be worthwhile actually writing a specification for what System::Query does too. Othewise we end up with another de facto thing in the chain.

@jonathanstowe
Copy link

pre-process those parts with System::Query and then validate the resulting structure.

This has a further implication that https://github.com/jonathanstowe/META6 may struggle to do all of the things that people are using it for if it is to parse a META6.json into a meaningful object with the depends and build pre-processed, which may preclude round-tripping to the same JSON with the original System::Query stuff if present.

@jonathanstowe
Copy link

I really had to look up what you mean by System::Query "collapsing".

Yeah, but for me this was the key piece of information that I was missing, once that was clear it all fell into place :-D

@jonathanstowe
Copy link

While I think about this, some thought might want to go into documenting a "roadmap" and versioning scheme for the META6. I'm thinking the versions (meta-version or implied as 0):

  • 0: as 6.c release : Array depends, build-depends, test-depends, meta-version or meta6 optional (default 0,)
  • 1: build, builder, Array or Object depends, meta-version required, api optional, perl or raku
  • 2: build-depends, test-depends and Array depends deprecated, only raku
  • 3: build-depends, test-depends removed, only Object depends etc

Obviously not exhaustive. Handling of the versions will have different implications for installers, validators, generators and other processors.

@JJ
Copy link
Contributor Author

JJ commented Oct 3, 2020

That meta-version proposal looks fine. I might want to add something about source-url and other places where we can find it; it's the other ambiguity I was asking about at the beginning.
But we might want to put it in the document, whatever that is. Do we have enough consensus to prepare a PR?

@jonathanstowe
Copy link

Oh yeah, looking at the source-url there does appear to be a number where meta-version is 1 and source-url is present, so it definitely can't be removed at 1, also in order to consider a roadmap toward removing it we'd need to confirm what the PAUSE/CPAN processor needs (the github ecosystem is somewhat more tractable.)

My current line of thinking is to create a schema for each version, document the versions explicitly and lay out the requirements of the different classes of META6 processors viz handling of the versions (which in itself may require a separate roadmap as to when support for a version may be dropped for e.g. an installer.)

I'm having a think about about how best to determine where to draw some of the version lines against what is presented in the wild, I'll get to making something over the weekend.

PR, not so sure, I'm thinking this should all go in its own repository.

@JJ
Copy link
Contributor Author

JJ commented Oct 3, 2020 via email

@jonathanstowe
Copy link

So regarding consensus I think it's good for "let's sort this out", probably want to get more input from the various vested interests (tools authors, module authors etc,) on the actual details of the specification as the versioning firms up, I'm not even sure I know all the places where the META6 is used by tools, modules and so forth beyond those that depend on the module META6.

@ugexe
Copy link
Contributor

ugexe commented Oct 3, 2020

Consider -- Raku implementations will be expected to consume a specific subset of META6.json data, so those parts of the spec are definitely owned by raku (and is even tested in the roast via CURFS loading distributions through their META6.json). Are the proposed meta-version changes expected to have any meaning to raku (rhetorical: I would suspect the ones mentioned in here would not)? If not then how can raku change the parts of the META6 spec it does own in a versioned manner without having to be aware of all these (what I'll call) ecosystem-not-raku specs? It almost seems like there needs to be two different meta versions... one for the 'core' and one (or more) for anything else outside of what raku would consume.

@lizmat lizmat unassigned jnthn Oct 5, 2020
@AlexDaniel AlexDaniel self-assigned this Oct 6, 2020
@AlexDaniel
Copy link
Member

This ticket talks about creating a specification for the META6.json file. The language tag is more fitting.

@AlexDaniel AlexDaniel added language Changes to the Raku Programming Language and removed meta Changes to this repo and the main document labels Oct 6, 2020
@AlexDaniel AlexDaniel removed their assignment Oct 6, 2020
@JJ
Copy link
Contributor Author

JJ commented Oct 6, 2020 via email

@AlexDaniel
Copy link
Member

Good point!

For reference: #45

@AlexDaniel AlexDaniel added fallback If no other label fits and removed language Changes to the Raku Programming Language labels Oct 6, 2020
@AlexDaniel AlexDaniel self-assigned this Oct 6, 2020
@vrurg
Copy link
Contributor

vrurg commented Oct 7, 2020

This spec is not part of the language. Maybe part of the ecosystem, but not the language.

Yet, META6 is so tightly bound to Raku that speccing the format alongside with the language would be the right thing to do. Raku must define a minimal META6 set which is sufficient for, say, a module to be available for installation by different Raku implementations.

Also, considering possible META6 extensions by 3rd party tools, it is better to take care of possible key name clashes beforehand as later it may pose serious risk of a tool failing on a module due to it using a key meant for another tool. Bad and incompatible tooling around a language would do bad for its reputation. So, not really speccing in the meaning of having tests, but a way to register new non-core keys should exists.

BTW, I'd really be happy to see extension keys using namespaces. Perhaps this should be considered a requirement.

Also, I think of changing files in old-design-docs as of a bad idea. That repo is now better be kept for pure historical purpose including cases when some language design decision is based upon an old spec or some argumentation inside it. I understand @niner reasoning about fixing META6 descirption while he has time for it. Unfortunately, under time pressure it is often really only two choices of either evading doing something or doing it a wrong way. But for now I'd like to have this fixed.

And perhaps the last consideration I have: META6 could be not the last entity which doesn't really belong to speccing yet tightly bound to the language. I can't really foresee what exactly could be standardized, but can't exclude the possibility itself.

With all the above in mind, I think a good thing to do would be to introduce addendums directory in roast which purpose would be to contain standards that are not really part of the language and core modules. To start with we can move the modified S22-package-format.pod in there and make it the first draft of META6 specification. The commits already made in the old-design-docs repo would then be reverted to restore the historical state of the file.

The way I see the final META6 spec is a paper with primary section defining the base set of keys sufficient for a project to be installed by any Raku implementation or packaging tool (as mentioned in the beginning of this comment). Then additional sections describe extensions supported by tools. A tool author may request adding new keys to the spec. This would make them reserved and protected from future re-use by other tools or by Raku language itself. Though if namespace use is made a requirement for extensions then it's only namespaces that would require registration.

JSON schema could be provided alongside with the paper or as a section of it.

Unless I missed something in the preceeding extensive discussion, the proposed solution should get most of the issues about META6 standard resolved.

@ugexe
Copy link
Contributor

ugexe commented Oct 7, 2020

The sufficient keys are simply name, auth, api, version, and provides. Literally nothing else is needed to install a distribution in raku.

@ugexe
Copy link
Contributor

ugexe commented Oct 7, 2020

Also I don’t agree that tooling authors should be able to make extensions to the spec. Extensions should work totally independent of any raku authority, else why is it an extension at all?

@niner
Copy link

niner commented Oct 7, 2020 via email

@AlexDaniel AlexDaniel added language Changes to the Raku Programming Language and removed fallback If no other label fits labels Oct 7, 2020
@AlexDaniel AlexDaniel removed their assignment Oct 7, 2020
@vrurg
Copy link
Contributor

vrurg commented Oct 8, 2020

The sufficient keys are simply name, auth, api, version, and provides. Literally nothing else is needed to install a distribution in raku.

What about *depends, resources, and few alike? Are they pure zef extensions we're not ought to standardize?

Also I don’t agree that tooling authors should be able to make extensions to the spec. Extensions should work totally independent of any raku authority, else why is it an extension at all?

It wouldn't oblige any tool developer to to anything. But if they wish to prevent future conflicts then formally made request to register an extension would most certainly be appreciated.

Similar situation with namespaces except that registering a namespace (again, purely at will of a developer) eases everybody's life in many ways.

@vrurg
Copy link
Contributor

vrurg commented Oct 8, 2020

These documents are useful. They would be even more useful if they were more up to date.

I wouldn't agree that keeping them up to date would make a lot of sense with respect to the resources used for the task. My view that the repo name is very much correctly reflects what value the papers have to the moment.

And anyway, what would be improved by taking the same document and putting it into an addition place? How would the availability of different versions of the same document reduce confusion?

I don't propose to have different versions of the same document. I propose to take the original and use it as a draft for a new paper. The final version of it should be very much different from the source simply due to the different purpose of it.

With regard to the synopsis content, to the best of my knowledge, it's only a subset of S22 which is currently supported. Perhaps it is yet to be decided if the rest of it should be implemented and consequently included into the final spec.

@ugexe
Copy link
Contributor

ugexe commented Oct 8, 2020

What about *depends, resources, and few alike? Are they pure zef extensions we're not ought to standardize?

yes resources belongs in there too along with the non-existing something for declaring e.g. bin/* (which is one of -- if not the -- biggest META6 format issues). depends it starts to get into a gray area because rakudo doesn't implement anything to parse them so I'm reluctant to put anything related to that in the roast (if you can parse them in the roast then why not just implement it in rakudo directly and test that)

But if they wish to prevent future conflicts then formally made request to register an extension would most certainly be appreciated.

I don't see it as a problem needs to be solved with that type centralization. We wouldn't e.g. allow users to register namespaces in GLOBAL to give an absurd example. An author of tools consuming non-standard fields from the META6.json would likely be aware they shouldn't call their special field a common name (which are documented), and that revelation to an unbeknownst tool author wouldn't seem like a big deal to anyone -- "put an underscore in front of it". You can't even register a module namespace right now... discussing a process for users to register a META6.json field in itself just feels like scope creep at this point in time.

@JJ
Copy link
Contributor Author

JJ commented Jan 4, 2021

Realizing now that we still have a "perl" key in META6, which is used by most distribution, along with a "raku" key some new distributions use.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
language Changes to the Raku Programming Language
Projects
None yet
Development

No branches or pull requests

9 participants