diff --git a/.gitignore b/.gitignore index 3d4ce7e..db912c2 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /target .vscode/ vendor/ +/spec.html diff --git a/Makefile b/Makefile index b1e3080..b2ca611 100644 --- a/Makefile +++ b/Makefile @@ -9,3 +9,9 @@ test: .PHONY: lint # Lint the project lint: .pre-commit-config.yaml @pre-commit run --show-diff-on-failure --color=always --all-files + +brew-install-gfm: + @brew install cmark-gfm + +spec.html: spec.md + cmark-gfm --to html --smart -e table -e footnotes -e strikethrough $< > $@ diff --git a/spec.md b/spec.md index c9c9574..0765dd0 100644 --- a/spec.md +++ b/spec.md @@ -1,446 +1,497 @@ -Name -==== +* **Source:** PostgreSQL Extension Network +* **RFC**: TBD +* **Version**: 2.0.0-draft1 +* **Status**: Draft +* **Category**: Standards Track +* **Published**: TBD +* **Authors**: + * David E. Wheeler, PGXN, Tembo -PGXN Meta Spec - The PGXN distribution metadata specification +# RFC TBD # +# PostgreSQL Extension Network Distribution Metadata Specification # -Version -======= +## Abstract ## -1.0.2 +This document describes version 2.0.0 of the [PGXN] source distribution +metadata specification, also known as the "PGXN Meta Spec." PGXN Metadata +ships with PGXN source distribution archives, and serves to describe the their +contents for the benefit of automated indexing, distribution, discovery, +full-text search, binary packaging, and more. -Synopsis -======== +## Status of This Memo ## -``` json -{ - "name": "pgTAP", - "abstract": "Unit testing for PostgreSQL", - "description": "pgTAP is a suite of database functions that make it easy to write TAP-emitting unit tests in psql scripts or xUnit-style test functions.", - "version": "0.26.0", - "maintainer": [ - "David E. Wheeler ", - "pgTAP List " - ], - "license": { - "PostgreSQL": "https://www.postgresql.org/about/licence" - }, - "prereqs": { - "runtime": { - "requires": { - "plpgsql": 0, - "PostgreSQL": "8.0.0" - }, - "recommends": { - "PostgreSQL": "8.4.0" - } - } - }, - "provides": { - "pgtap": { - "file": "sql/pgtap.sql", - "docfile": "doc/pgtap.mmd", - "version": "0.2.4", - "abstract": "Unit testing assertions for PostgreSQL" - }, - "schematap": { - "file": "sql/schematap.sql", - "docfile": "doc/schematap.mmd", - "version": "0.2.4", - "abstract": "Schema testing assertions for PostgreSQL" - } - }, - "resources": { - "homepage": "https://pgtap.org/", - "bugtracker": { - "web": "https://github.com/theory/pgtap/issues" - }, - "repository": { - "url": "https://github.com/theory/pgtap.git", - "web": "https://github.com/theory/pgtap", - "type": "git" - } - }, - "generated_by": "David E. Wheeler", - "meta-spec": { - "version": "1.0.0", - "url": "https://pgxn.org/meta/spec.txt" - }, - "tags": [ - "testing", - "unit testing", - "tap", - "tddd", - "test driven database development" - ] -} -``` +This is a Standards Track document. + +This RFC represents the consensus of the global community of PostgreSQL +extension developers, distributors, and packagers, generally referred to as +the "PostgreSQL Extension Ecosystem". It is formatted using the [Github +Flavored Markdown] variant of [Markdown], and the canonical copy will always +be found at [master.pgxn.org/meta/spec.txt]. A generated HTML-formatted copy +found at [pgxn.org/spec/] **MAY** also be considered canonical. + +Information about the current status of this document, any errata, and how to +provide feedback on it **MAY** be obtained from its [source code repository]. + +## Copyright Notice ## + +Copyright (c) 2010-2024 PGXN and the persons identified as the document +authors. All rights reserved. + +This RFC is distributed under the [CC BY-SA 4.0] license. + +Code Components extracted from this document **MUST** include the [PostgreSQL +License]. -Description -=========== - -This document describes version 1.0.0 of the PGXN distribution metadata -specification, also known as the "PGXN Meta Spec." It is formatted using the -[MultiMarkdown] variant of [Markdown], and the canonical copy may always be -found at [master.pgxn.org/meta/spec.txt]. A generated HTML-formatted copy -found at [pgxn.org/spec/] may also be considered canonical. - -This document is stable. Any revisions to this specification for typo -corrections and prose clarifications may be issued as "PGXN Meta Spec -1.0.*x*". These revisions will never change semantics or add or remove -specified behavior. - -Distribution metadata describe important properties of PGXN distributions. -Distribution building tools should create a metadata file in accordance -with this specification and include it with the distribution for use by -automated tools that index, examine, package, or install PGXN distributions. - -Terminology -=========== - -distribution -: The primary object described by the metadata. In the context of this - document it usually refers to a collection of extensions, source code, - utilities, tests, and/or documents that are distributed together for other - developers to use. Examples of distributions are [`semver`], [`pair`], and - [`pgTAP`]. - -extension -: A reusable library of code contained in a single file or within files - referenced by the [`CREATE EXTENSION` statement]. Extensions usually - contain one or more PostgreSQL objects --- such as data types, functions, - and operators --- and are often referred to by the name of a primary - object that can be mapped to the file name. For example, one might refer - to `pgTAP` instead of `sql/pgtap.sql`. - -consumer -: Code that reads a metadata file, deserializes it into a data structure in - memory, or interprets a data structure of metadata elements. - -producer -: Code that constructs a metadata data structure, serializes into a byte - stream and/or writes it to disk. - -must, should, may, etc. -: These terms are interpreted as described in [IETF RFC 2119]. - -Data Types -========== - -Fields in the [Structure](#Structure) section describe data elements, each of -which has an associated data type as described herein. There are four -primitive types: *Boolean*, *String*, *List*, and *Map*. Other types are -subtypes of primitives and define compound data structures or define -constraints on the values of a data element. - -Boolean -------- - -A *Boolean* is used to provide a true or false value. It **must** be +## Introduction ## + +Distribution metadata describe important properties of source code [archive +files][archive file] distributed on the PostgreSQL Extension Network, or +[PGXN]. Tools that build PGXN source distribution archives **MUST** create a +metadata file in accordance with this specification and include it in the +distribution archive for use by automated tools that index, examine, package, +or install PGXN source distributions. + +### Terminology ### + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", +"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be +interpreted as described in [IETF RFC 2119]. + +This document makes use of the following additional terms: + +#### Package #### + +A collection of extensions that are released, versioned, and distributed +together. + +#### Source Distribution #### + +An [archive file] of the source code for the release of a [Package](#package), +together with metadata defined by this spec, distributed for other developers +to build, install, and use. The file name of a Source Distribution consists of +the package name, a dash, and the version, e.g., `pgtap-1.14.3.zip`. + +Usually referred to as a "Distribution", including in this document. The full +term "Source Distribution" is used where necessary to distinguish from binary +distributions of a [Package](#package) (not covered by this RFC). + +#### Extension #### + +A software component that extends the capabilities of a PostgreSQL database or +cluster. Extensions **MAY** be `CREATE EXTENSION` [extensions], [background +workers], command-line apps, [loadable modules], shared libraries, and more. + +#### Consumer #### + +Code that reads a metadata file, deserializes it into a data structure in +memory, or interprets its elements. + +#### Producer #### + +Code that constructs a metadata data structure, serializes it into a byte +stream, and/or writes it to disk. + +### Data Types ### + +Properties in the [Structure](#structure) section describe data elements, each +of which has an associated data type as described herein. Each is based on the +primitive types defined by [JSON]: *object*, *array*, *string*, *number*, and +*boolean*. Other types are subtypes of these primitives and define compound +data structures or define constraints on the values of a data element. + +#### Boolean #### + +A *Boolean* is used to provide a true or false value. It **MUST** be represented as a defined (not `null`) value. -String ------- +#### String #### A *String* is data element containing a non-zero length sequence of Unicode characters. -List ----- +#### Array #### -A *List* is an ordered collection of zero or more data elements. Elements of a -List may be of mixed types. +An *Array* is an ordered collection of one or more data elements. Items in an +Array **MAY** be of mixed types. -Producers **must** represent List elements using a data structure which -unambiguously indicates that multiple values are possible, such as a -JavaScript array. +#### Object #### -Consumers expecting a List **must** consider a [String](#String) as equivalent -to a List of length 1. +An **Object** is an unordered set of key/value pairs, or "properties". +Property values are indexed by their corresponding [String](#string) keys. An +Object's values **MAY** be of mixed types. -Map ---- +#### Term #### -A *Map* is an unordered collection of zero or more data elements ("values"), -indexed by associated [String](#String) elements ("keys"). The Map’s value -elements may be of mixed types. +A *Term* is a [String](#string) that **MUST** be at least two characters long, +and contain no slash (`/`), backslash (`\`), control, or space characters. -License String --------------- +#### Tag #### -A *License String* is a subtype of [String](#String) with a restricted set of -values. Valid values are described in detail in the description of the -[license field](#license). +A *Tag* is a [String](#string) that **MUST** be at least two and no more than +255 characters long, and contain no slash (`/`), backslash (`\`), or control +characters. -Term ----- +#### URI #### -A *Term* is a subtype of [String](#String) that **must** be at least two -characters long contain no slash (`/`), backslash (`\`), control, or space -characters. +*URI* is a [String](#string) containing a valid Uniform Resource Identifier or +Locator as defined by [IETF RFC 3986]. -Tag ---- +#### Path #### -A *Tag* is a subtype of [String](#String) that **must** be fewer than 256 -characters long contain no slash (`/`), backslash (`\`), or control -characters. +*Path* is a [String](#string) with a relative file path that identifies a file +in the [Distribution](#source-distribution). The path **MUST** be specified +with unix conventions. -URI ---- +#### Version #### -*URI* is a subtype of [String](#String) containing a Uniform Resource -Identifier or Locator. +A *Version* is a [String](#string) containing a value that describes the +version number of extensions or distributions, and adhere to the format of the +[Semantic Versioning 2.0.0 Specification][semver] with the exception of [Build +metadata], which is reserved for use by downstream packaging systems. -Version -------- +#### Version Range #### -A *Version* is a subtype of [String](#String) containing a value that -describes the version number of extensions or distributions. Restrictions on -format are described in detail in the [Version Format](#Version.Format) -section. +A *Version Range* is a [String](#string) that describes a range of +[Versions](#version) that **MAY** be present or installed to fulfill +dependencies. -Version Range -------------- +The simplest format for a Version Range is just the [Versions](#version) +itself, e.g. `2.4.2`. This means that **at least** version 2.4.2 must be +present. Versions may also be truncated to their major or minor parts, as +appropriate. For example, `2.4` means that **at least** version 2.4.0 must be +present. -The *Version Range* type is a subtype of [String](#String). It describes a -range of Versions that may be present or installed to fulfill prerequisites. -It is specified in detail in the [Version Ranges](#Version.Ranges) section. +Alternatively, a version range **may** use the operators `<` (less than), `<=` +(less than or equal), `>` (greater than), `>=` (greater than or equal), `==` +(equal), and `!=` (not equal). For example, the specification `< 2` means that +any version less than version 2 is suitable. -Structure -========= +For more complicated situations, version specifications **may** be AND-ed +together using commas. The specification `>= 1.2, != 1.5.2, < 2.0` +indicates a version that must be **at least** 1.2, **less than** 2.0, and +**not equal to** 1.5.2. -The metadata structure is a data element of type [Map](#Map). This section -describes valid keys within the [Map](#Map). +#### License String #### -Any keys not described in this specification document (whether top-level or -within compound data structures described herein) are considered *custom keys* -and **must** begin with an "x" or "X" and be followed by an underscore; i.e., -they must match the pattern: `/\Ax_/i`. If a custom key refers to a compound -data structure, subkeys within it do not need an "x_" or "X_" prefix. +A *License String* is a [String](#string) identifying a licenses. Its values +are restricted to and defined by the [SPDX License List]. Examples: -Consumers of metadata may ignore any or all custom keys. All other keys not -described herein are invalid and should be ignored by consumers. Producers -must not generate or output invalid keys. +* `PostgreSQL` +* `MIT` +* `Apache-2.0` +* `BSD-2-Clause` +* `GPL-2.0-only` -For each key, an example is provided followed by a description. The -description begins with the version of spec in which the key was added or in -which the definition was modified, whether the key is *required* or -*optional*, and the data type of the corresponding data element. These items -are in parentheses, brackets, and braces, respectively. +#### License Expression #### -If a data type is a [Map](#Map) or [Map](#Map) subtype, valid subkeys will be -described as well. All examples are represented as [JSON]. +A *License Expression* is a [String](#string) that represents one or more +licenses by combining [License Strings](#license-string) into a single value. +The format is defined by [SPDX Standard License Expression]. Examples: - +A *purl* is a [String](#string) containing a valid package in the format +defined by the [purl spec]. All known [purl Types] **MAY** be used, as well as +`pgxn` for PGXN packages and `postgres` for PostgreSQL core [contrib] or +development packages. Some examples: -Required Fields ---------------- +* `pkg:pgxn/pgtap` +* `pkg:postgres:pg_regress` +* `pkg:generic/python3@3` +* `pkg:pypi/pyarrow@11.0.0` -### abstract ### +The version part of a purl, when present, will be interpreted as a [Version +Range](#version-range), allowing for flexible specification of supported +versions where necessary. Note that versions must be [percent-encoded]. For +example, this purl encodes `>=1.2,!=1.5.2,< 2.0`: -Example: +* `pkg:pgxn/pgmq@%3E%3D1.2%2C+%21%3D1.5.2%2C%3C+2.0` + +#### Platform #### + +A *Platform* is a [String](#string) that identifies a computing platform as a +one to three dash-delimited substrings: An OS name, the OS version, and the +architecture: `$os-$version-$architecture`. + +If the string contains no dash, it represents only the OS. If it contains a +single dash, the values represent the OS and the architecture. The complete +list of values will be determined by the [bulid farm animals]. Some likely +Examples: + +* `linux`: Any Linux +* `linux-amd64`: Any Linux on amd64/x86_64 +* `gnulinux-amd64`: [GNU] Linux on amd64/x86_64 +* `musllinux-1.2-arm64`: [musl] Linux v1.2 on arm64/aarch64 +* `darwin`: Any Darwin (macOS) +* `darwin-23.5.0-arm64`: Darwin (macOS) 23.5.0 on arm64/aarch64 + +## Structure + +The metadata structure is an [Object](#object). This section describes valid +properties of the [Object](#object). + +Any properties not described in this specification document (whether top-level +or within [Objects](#object) described herein) are considered *custom +properties* and **MUST** begin with an "x" or "X" and be followed by an +underscore; i.e., they **MUST** match the regular expression pattern +`^[xX]_.`. If a custom property refers to an [Object](#object), properties +within it do not need an "x_" or "X_" prefix. + +Metadata [Consumers](#consumer) **MAY** ignore any or all custom properties. +All other properties not described herein are invalid and **SHOULD** be +ignored by [Consumers](#consumer). [Producers](#producer) **MUST NOT** +generate or output invalid properties. + +For each property, one or more examples are provided followed by a +description. The description begins with the version of spec in which the +property was added or in which the definition was modified, whether the +property is **REQUIRED** or **OPTIONAL**, and the data type of the value. +These items are in parentheses, brackets, and braces, respectively. + +If a data type is an [Object](#object), valid sub-properties will be described +as well. + +All examples are represented as [JSON]. + + + +### Required Properties + +#### abstract #### ``` json "abstract": "Unit testing for PostgreSQL" ``` -(Spec 1) [required] {[String](#String)} +(Spec 1) [required] {[String](#string)} -This is a short description of the purpose of the distribution. +This is a short description of the purpose of the [Package](#package) provided +by the [Distribution](#source-distribution). -### maintainer ### - -Examples: +#### maintainers #### ```json -"maintainer": "David E. Wheeler " +"maintainers": [ + { + "name": "David E. Wheeler", + "url": "https://pgxn.org/user/theory" + } +] ``` ```json -"maintainer": [ - "David E. Wheeler ", - "Josh Berkus " +"maintainers": [ + { + "name": "David E. Wheeler", + "email": "theory@pgxn.org", + "url": "https://pgxn.org/user/theory" + }, + { + "name": "Josh Berkus", + "email": "jberkus@pgxn.org" + } ] ``` -(Spec 1) [required] {[List](#List) of one or more [Strings](#String)} +(Spec 2) [required] {[Array](#array) of [Objects]{#object}} -This [List](#List) indicates the person(s) to contact concerning the -distribution. The preferred form of the contact string is: +This property indicates the person(s) to contact concerning the +[Distribution](#source-distribution). Each [Object](#object) in the +[Array](#array) consists of the following properties: -``` -contact-name -``` +* **name**: The name of the maintainer. **REQUIRED**. +* **email**: The email address of the maintainer. +* **url**: The URL for the maintainer. -This field provides a general contact list independent of other structured -fields provided within the [resources](#resources) field, such as -`bugtracker`. The addressee(s) can be contacted for any purpose including but -not limited to: (security) problems with the distribution, questions about the -distribution, or bugs in the distribution. +Either `email` or `url` or both **MUST** be present. -A distribution’s original author is usually the contact listed within this -field. Co-maintainers, successor maintainers, or mailing lists devoted to the -distribution may also be listed in addition to or instead of the original -author. +This property provides a general contact list independent of other structured +fields provided within the [resources](#resources) field, such as `issues`. +The addressee(s) can be contacted for any purpose including but not limited +to: (security) problems with the [Distribution](#source-distribution), +questions about the [Distribution](#source-distribution), or bugs in the +[Distribution](#source-distribution). -### license ### +A [Distribution](#source-distribution)'s original author is usually the +contact listed within this field. Co-maintainers, successor maintainers, or +mailing lists devoted to the distribution **MAY** also be listed in addition +to or instead of the original author. -Examples: - -```json -"license": { - "PostgreSQL": "https://www.postgresql.org/about/licence" -} -``` - -```json -"license": { - "Perl 5": "https://dev.perl.org/licenses/", - "BSD": "https://www.opensource.org/licenses/bsd-license.html" -} -``` +#### license #### ``` json -"license": "perl_5" +"license": "MIT" ``` ``` json -"license": [ "apache_2_0", "mozilla_1_0" ] +"license": "MIT AND BSD-2-Clause" ``` -(Spec 1) [required] {[Map](#Map) or [List](#List) of one or more -[License Strings](#License.String)} +(Spec 1) [required] {[License String](#license-string) or [License Expression](#license-expression)} One or more licenses that apply to some or all of the files in the -distribution. If multiple licenses are listed, the distribution documentation -should be consulted to clarify the interpretation of multiple licenses. - -The [Map](#Map) type describes the license or licenses. Each subkey may be any -string naming a license. All values must be [URIs](#URI) that link to the -appropriate license. - -The [List](#List) type may be used as a shortcut to identify one or more -well-known licenses. The following list of [License Strings](#License.String) -are valid in the [List](#List) representation: - - string | description ---------------|------------------------------------------------------ - agpl_3 | GNU Affero General Public License, Version 3 - apache_1_1 | Apache Software License, Version 1.1 - apache_2_0 | Apache License, Version 2.0 - artistic_1 | Artistic License, (Version 1) - artistic_2 | Artistic License, Version 2.0 - bsd | BSD License (three-clause) - freebsd | FreeBSD License (two-clause) - gfdl_1_2 | GNU Free Documentation License, Version 1.2 - gfdl_1_3 | GNU Free Documentation License, Version 1.3 - gpl_1 | GNU General Public License, Version 1 - gpl_2 | GNU General Public License, Version 2 - gpl_3 | GNU General Public License, Version 3 - lgpl_2_1 | GNU Lesser General Public License, Version 2.1 - lgpl_3_0 | GNU Lesser General Public License, Version 3.0 - mit | MIT (aka X11) License - mozilla_1_0 | Mozilla Public License, Version 1.0 - mozilla_1_1 | Mozilla Public License, Version 1.1 - openssl | OpenSSL License - perl_5 | The Perl 5 License (Artistic 1 & GPL 1 or later) - postgresql | The PostgreSQL License - qpl_1_0 | Q Public License, Version 1.0 - ssleay | Original SSLeay License - sun | Sun Internet Standards Source License (SISSL) - zlib | zlib License - -The following [License Strings](#License.String) are also valid and indicate -other licensing not described above: - - string | description ---------------|------------------------------------------------------ - open_source | Other Open Source Initiative (OSI) approved license - restricted | Requires special permission from copyright holder - unrestricted | Not an OSI approved license, but not restricted - unknown | License not provided in metadata - -All other strings are invalid in the license [List](#List). - -### provides ### +[Distribution](#source-distribution). For [License +Expressions](#license-expression), the [Distribution](#source-distribution) +documentation **SHOULD** be consulted to clarify the interpretation of +multiple licenses. -Example: +#### contents #### ``` json -"provides": { - "pgtap": { - "file": "sql/pgtap.sql", - "docfile": "doc/pgtap.mmd", - "version": "0.2.4", - "abstract": "Unit testing assertions for PostgreSQL" +"contents": { + "extensions": { + "pair": { + "sql": "sql/pair.sql", + "doc": "doc/pair.md", + "abstract": "A key/value pair data type", + "preload": "session", + "tle": true, + "control": "pair.control" + } + } +``` + +``` json +"contents": { + "workers": { + "pair_pruner": { + "bin": "bin/pair_pruner", + "doc": "doc/pair_pruner.md", + "abstract": "A worker to periodically prune pairs" + } }, - "schematap": { - "file": "sql/schematap.sql", - "docfile": "doc/schematap.mmd", - "version": "0.2.4", - "abstract": "Schema testing assertions for PostgreSQL" + "modules": { + "lib_pair": { + "lib": "lib/lib_pair", + "doc": "doc/lib_pair.md", + "abstract": "A library hooking function calls to convert pairs to named parameters", + "load": "shared_preload_libraries" + } } } ``` -(Spec 1) [required] {[Map](#Map) of [Terms](#Term)} - -This describes all extensions provided by this distribution. This information -is used by PGXN to build indexes identifying in which distributions various -extensions can be found. - -The keys of `provides` are [Terms](#Term) that name the extensions found -within the distribution. The values are [Maps](#Map) with the following -subkeys: - -* **file**: The value must contain a relative file path from the root of the - distribution to the file containing the extension. The path **must be** - specified with unix conventions. Required. - -* **version**: This field contains a [Version](#Version) for the extension. - All extensions must have versions. Required. - -* **abstract**: A short [String](#String) value describing the extension. - Optional. - -* **docfile**: The value must contain a relative file path from the root of - the distribution to the file containing documentation for the extension. - The path **must be** specified with unix conventions. Optional. - -### meta-spec ### +``` json +"contents": { + "apps": { + "pair_rand": { + "bin": "bin/pair_rand", + "doc": "doc/pair_rand.md", + "abstract": "Command to generate random pairs of strings" + } + }, + "libraries": { + "ruby_pair": { + "dir": "lib/gems", + "abstract": "Ruby libraries required to run the extension" + } + } +} +``` -Example: +(Spec 1) [required] {[Object](#object) of [Objects](#object) of [Terms](#term)} + +A description of what's included in the [Package](#package) provided by the +[Distribution](#source-distribution). This information is used by [PGXN] to +build indexes identifying in which [Package](#package) various +[Extensions](#extension) can be found. + +The properties of `contents` identify the types of [Extensions](#extension) in +the [Distribution](#source-distribution). At least one property **MUST** be +present in the `contents` object. The properties are as follows: + +* **extensions**: [Object](#object) describing `CREATE EXTENSION` + [extensions]. Properties are extension name [Terms](#term) pointing to + [Objects](#object) with the following fields: + * **sql**: A [Path](#path) pointing to the SQL file used by `CREATE + EXTENSION`. **REQUIRED**. + * **control**: A [Path](#path) pointing to the [control file] used by + `CREATE EXTENSION`. **REQUIRED**. + * **doc**: A [Path](#path) pointing to the main documentation file for + the extension, which **SHOULD** be more than a README. + * **abstract**: A [String](#string) containing a short description of + the extension. + * **tle**: A [Boolean](#boolean) that, when `true`, indicates that the + extension can be used as a [trusted language extension]. +* **workers**: [Object](#object) describing [background workers]. Properties + are worker name [Terms](#term) pointing to [Objects](#object) with the + following properties: + * **src**: A [Path](#path) pointing to the main source file for the + background worker. **REQUIRED**. + * **doc**: A [Path](#path) pointing to the main documentation file for + the background worker, which **SHOULD** be more than a README. + * **abstract**: A [String](#string) containing a short description of + the background worker. +* **apps**: [Objects](#object) describing applications, command-line or + otherwise. Properties are are app name [Terms](#term) pointing to + [Objects](#object) with the following properties: + * **src**: A [Path](#path) pointing to the main source file for the app. + **REQUIRED**. + * **doc**: A [Path](#path) pointing to the main documentation file for + the app, which **SHOULD** be more than a README. + * **abstract**: A [String](#string) containing a short description of + the app. +* **modules**: [Objects](#object) describing [loadable modules] that can be + loaded into Postgres. Properties are module name [Terms](#term) pointing + to [Objects](#object) with the following properties: + * **src**: A [Path](#path) pointing to the main source file for the + module. **REQUIRED**. + * **doc**: A [Path](#path) pointing to the main documentation file for + the module, which **SHOULD** be more than a README. + * **abstract**: A [String](#string) containing a short description of + the module. + * **preload**: A [String](#string) that indicates that the extension's + libraries **MAY** be loaded in advance. Its three possible values are: + `shared`, `session`, and `local`. Extensions that require early or + late loading of their module **MAY** optionally append a space and + then either `early` or `late`. +* **libraries**: [Objects](#object) listing other libraries that **MAY** + ship in the package and need to be installed but are not [loadable + modules], such as a dynamic library used by an app. Properties are library + name [Terms](#term) pointing to [Objects](#object) with the following + properties: + * **src**: A [Path](#path) pointing to the main source file or directory + of files for the library. **REQUIRED**. + * **doc**: A [Path](#path) pointing to the main documentation file for + the library, which **SHOULD** be more than a README. + * **abstract**: A [String](#string) containing a short description of + the app. + +#### meta-spec #### ``` json "meta-spec": { - "version": "1.0.0", - "url": "https://pgxn.org/meta/spec.txt" + "version": "2.0.0", + "url": "https://pgxn.org/meta/v2/spec.txt" } ``` (Spec 1) [required] {[Map](#Map)} -This field indicates the [Version](#Version) of the PGXN Meta Spec that should -be used to interpret the metadata. Consumers must check this key as soon as -possible and abort further metadata processing if the meta-spec -[Version](#Version) is not supported by the consumer. +This field indicates the [Version](#Version) of the PGXN Meta Spec that +**SHOULD** be used to interpret the metadata. Consumers **MUST** check this +key as soon as possible and abort further metadata processing if the meta-spec +[Version](#version) is not supported by the consumer. -The following keys are valid, but only `version` is required. +The following properties are valid, but only `version` is **REQUIRED**. -* **version**: This subkey gives the integer [Version](#Version) of the PGXN - Meta Spec against which the document was generated. +* **version**: The [Version](#version) of the PGXN Meta Spec against which + the metadata object was generated. -* **url**: This is a [URI](#URI) of the metadata specification document - corresponding to the given version. This is strictly for human-consumption - and should not impact the interpretation of the document. +* **url**: The [URI](#uri) of the metadata specification corresponding to + the given version. This is strictly for human-consumption and **SHOULD + NOT** impact the interpretation of the metadata structure. -### name ### +#### name #### Example: @@ -450,41 +501,43 @@ Example: (Spec 1) [required] {[Term](#Term)} -This field is the name of the distribution. This is usually the same as the -name of the "main extension" in the distribution, but may be completely -unrelated to the extensions within the distribution. This value will be used -in the distribution file name on PGXN. +This property is the name of the [Package](#package) provided by the +[Distribution](#source-distribution). This is usually the same as the name of +the "main extension" in the [contents](#contents) of the [Package](#package), +but **MAY** be completely unrelated. This value will be used in the +[Distribution](#source-distribution) file name on [PGXN]. -### version ### - -Example: +#### version #### ``` json "version": "1.3.6" ``` -(Spec 1) [required] {[Version](#Version)} +(Spec 1) [required] {[Version](#version)} -This field gives the version of the distribution to which the metadata -structure refers. Its value must be a [Version](#Version). +This property gives the version of the [Distribution](#source-distribution) to +which the metadata structure refers. Its value **MUST** be a +[Version](#version). -Optional Fields ---------------- +All of the items listed in [contents](#contents) will be considered to have +this version; any references they make to a version, such as the [control +file], **SHOULD** be compatible with this version. -### description ### +### Optional Fields ### -Example: +#### description #### ``` json "description": "pgTAP is a suite of database functions that make it easy to write TAP-emitting unit tests in psql scripts or xUnit-style test functions." ``` -(Spec 1) [optional] {[String](#String)} +(Spec 1) [optional] {[String](#string)} A longer, more complete description of the purpose or intended use of the -distribution than the one provided by the `abstract` key. +[Package](#package) provided by the [Distribution](#source-distribution), +answering the question "what is this thing and what value is it?" -### generated_by ### +#### generated_by #### Example: @@ -492,363 +545,492 @@ Example: "generated_by": "Module::Build::PGXN version 0.42" ``` -(Spec 1) [optional] {[String](#String)} - -This field indicates the tool that was used to create this metadata. There are -no defined semantics for this field, but it is traditional to use a string in -the form "Software package version 1.23" or the maintainer’s name, if the file -was generated by hand. +(Spec 1) [optional] {[String](#string)} -### tags ### +This property indicates the tool that was used to create this metadata. There +are no defined semantics for this property, but it is traditional to use a +string in the form "Software package version 1.23", or the maintainer's name +if the metadata was generated by hand. -Example: +#### classification #### ``` json -"tags": [ "testing", "unit testing", "tap" ] +{ + "tags": [ + "testing", + "pair", + "parameter" + ], + "categories": [ + "Machine Learning" + ] +} ``` -(Spec 1) [optional] {[List](#List) of [Tags](#Tag)} - -A [List](#List) of keywords that describe this distribution. - -### no_index ### - -Example: +(Spec 2) [optional] {[Object](#object) of [Arrays](#array) of [Tags](#tag)} + +Classification metadata associates additional information about the +[Package](#package) provided by the [Distribution](#source-distribution) to +improve discovery. This [Object](#object) **MUST** contain at least one of the +following properties: + +* **tags**: An [Array](#array) of one or more keyword [Tags](#tag)s that + describe the distribution. +* **categories**: An [Array](#array) of at least one and no more than three + of the following [Strings](#string) that categorize the distribution: + * Analytics + * Auditing and Logging + * Change Data Capture + * Connectors + * Data and Transformations + * Debugging + * Index and Table Optimizations + * Machine Learning + * Metrics + * Orchestration + * Procedural Languages + * Query Optimizations + * Search + * Security + * Tooling and Admin + +#### ignore #### ``` json -"no_index": { - "file": [ "src/file.sql" ], - "directory": [ "src/private" ] -} +"ignore": [ + "/src/private", + "/src/file.sql", + "*.html" +] ``` -(Spec 1) [optional] {[Map](#Map)} - -This [Map](#Map) describes any files or directories that are private to the -packaging or implementation of the distribution and should be ignored by -indexing or search tools. +(Spec 2) [optional] {[Array](#Array) of [Strings](#string)} -Valid subkeys are as follows: +This [Array](#array) describes any files or directories that are private to +the [Distribution](#source-distribution) and **SHOULD** be ignored by indexing +or search tools. Values are [Paths](#path) or [Strings](#string) based on a +subset of the [gitignore format]. -* **file**: A [List](#List) of relative paths to files. Paths **must be** - specified with unix conventions. +#### dependencies #### -* **directory**: A [List](#List) of relative paths to directories. Paths - **must be** specified with unix conventions. - -### prereqs ### +``` json +"dependencies": { + "postgres": { + "version": "14" + }, +} +``` -Example: +``` json +"dependencies": { + "postgres": { + "version": ">= 12, < 17", + "with": [ "xml", "uuid", "perl" ] + }, + "pipeline": "pgxs", + "packages": { + "build": { + "requires": [ + "pkg:generic/awk", + "pkg:generic/perl@5.20" + ], + "recommends": [ + "pkg:generic/jq", + "pkg:generic/perl@5.40" + ] + } + } +} +``` ``` json -"prereqs": { - "runtime": { - "requires": { - "PostgreSQL": "8.0.0", - "PostGIS": "1.5.0" +"dependencies": { + "pipeline": "pgrx", + "platforms": [ + "linux-amd64", + "linux-amd64v3", + "gnulinux-arm64", + "musllinux-amd64", + "darwin-23.5.0-arm64" + ], + "packages": { + "configure": { + "requires": [ "pkg:cargo/cargo-pgrx@%3D0.11.4" ] }, - "recommends": { - "PostgreSQL": "8.4.0" + "test": { + "requires": [ + "pkg:postgres/pg_regress", + "pkg:postgres/plpgsql" + "pkg:pgxn/theory/pgtap@1.1.0" + ] }, - "suggests": { - "sha1": 0 + "run": { + "requires": [ + "pkg:postgres/plperl" + "pkg:pgxn/theory/hostname" + ] } + } +} +``` + +``` json +"dependencies": { + "postgres": { + "version": ">= 15, < 16" }, - "build": { - "requires": { - "prefix": 0 + "pipeline": "pgxs", + "platforms": [ + "linux-amd64", "linux-arm64", + "darwin-amd64", "darwin-arm64" + ], + "packages": { + "configure": { + "requires": { + "external": [ + "pkg:cargo/cargo-pgrx@%3D0.11.4", + "pkg:generic/bison", + "pkg:generic/cmake", + "pkg:generic/flex", + "pkg:generic/readline", + "pkg:generic/openssl", + "pkg:generic/pkg-config" + ] + } + }, + "run": { + "requires": [ + "pkg:generic/penblas", + "pkg:generic/python3", + "pkg:generic/readline", + "pkg:generic/openssl", + "pkg:generic/bison" + ], + "recommends": [ + "pkg:pypi/pyarrow@11.0.0", + "pkg:pypi/catboost", + "pkg:pypi/lightgbm", + "pkg:pypi/torch", + "pkg:pypi/torchaudio", + "pkg:pypi/torchvision", + "pkg:pypi/xgboost", + "pkg:pypi/accelerate", + "pkg:pypi/bitsandbytes", + "pkg:pypi/ctransformers", + "pkg:pypi/huggingface-hub", + "pkg:pypi/deepspeed", + "pkg:pypi/einops", + "pkg:pypi/optimum", + "pkg:pypi/peft", + "pkg:pypi/tokenizers", + "pkg:pypi/transformers", + "pkg:pypi/transformers-stream-generator", + "pkg:pypi/InstructorEmbedding", + "pkg:pypi/sentence-transformers", + "pkg:pypi/rouge", + "pkg:pypi/sacrebleu", + "pkg:pypi/sacremoses", + "pkg:pypi/datasets", + "pkg:pypi/orjson", + "pkg:pypi/langchain" + ] } }, - "test": { - "recommends": { - "pgTAP": 0 + "variations": [ + { + "where": { + "platforms": ["linux"] + }, + "dependencies": { + "packages": { + "run": { + "recommends": [ + "pkg:pypi/auto-gptq", + "pkg:pypi/xformers" + ] + } + } + } } - } -} + ] +}, ``` -(Spec 1) [optional] {[Map](#Map)} - -This is a [Map](#Map) that describes all the prerequisites of the -distribution. The keys are phases of activity, such as `configure`, `build`, -`test`, or `runtime`. Values are [Maps](#Map) in which the keys name the type -of prerequisite relationship such as `requires`, `recommends`, `suggests`, or -`conflicts`, and the values provide sets of prerequisite relations. The sets -of relations **must** be specified as [Maps](#Map) of extension names to -[Version Ranges](#Version.Ranges). - -The full definition for this field is given in the [Prereq Spec](#Prereq.Spec) -section. - -### release_status ### - -Example: +(Spec 2) [optional] {[Object](#object)} + +This property identifies dependencies required to configure, build, test, +install, and run the [Package](#package) provided by the +[Distribution](#source-distribution), expressed as [purls](#purl). These +include not only other extensions, but also external libraries, system +dependencies, and versions of PostgreSQL --- as well as any OS and +architectures ([arm64], [amd64], etc.). + +[Consumers](#consumer) **SHOULD** use this data to determine what dependencies +to install. + +Properties: + +* **platforms**: An [Array](#array) of one or more [Platform](#platform) + strings that identify OSes and architectures supported by the + [Package](#package) provided by the [Distribution](#source-distribution). + If this property is not present, [Consumers](#consumer) **SHOULD** assume + that the [Package](#package) supports any platform that PostgreSQL + supports. This property is typically needed only when the + [Package](#package) depends on platform-specific features. + +* **postgres**: An [Object](#object) describing the versions of PostgreSQL + required by the [Package](#package) provided by the + [Distribution](#source-distribution). The object supports the following + properties: + * **version**: A [Version Range](#version-range) identifying the + supported versions of PostgreSQL. **REQUIRED**. + * **with**: An [Array](#array) of [Terms](#term) that correspond + features that are required to be compiled into PostgreSQL. Each + corresponds to the appropriate `--with` [configure flags]. + **OPTIONAL**. + +* **pipeline**: A [Term](#term) identifying the build pipeline required to + configure, build, test, and install the [Package](#package) provided by + the [Distribution](#source-distribution). Supported values + **MAY** include: + + * pgxs + * meson + * pgrx + * autoconf + * gem + * cpan + * pip + * go + * rust + + If this field is not present, [Consumers](#consumer) **MAY** use + heuristics to ascertain the pipeline to use, such as the presence or + absence of a `configure.sh`, `Makefile`, or `Cargo.toml` file. + +* **packages**: An [Object](#object) defining dependencies required for + different phases of the build process. The supported property names are + `configure`, `build`, `test`, `run`, and `develop`. Values are + [Objects](#object) with at least one of the properties `requires`, + `recommends`, `suggests`, and `conflicts` pointing to [Arrays](#array) of + [purls](#purl) that identify the packages. + + See the [Package Spec](#packages-spec) for the full definition of this + property. + +* **variations**: An [Array](#array) of [Object](#object)s that define + dependency variations. Each object contains two properties: + * **where**: An [Object](#object) containing the subset of the + [dependencies](#dependencies) to identify a variation, such as + `{ "platforms": ["gnulinux-arm64", "gnulinux-amd64"] }` for Linux + configurations, or `{"postgres": { "version": ">= 16, < 17" }}` for + PostgreSQL versions. **MUST NOT** include a `variations` property. + * **dependencies**: An [Object](#object) containing the subset of + [dependencies](#dependencies) required for the `where` property's + configuration. **MUST NOT** include a `variations` property. + +#### resources #### ``` json -"release_status": "stable" +"resources": { + "homepage": "https://pair.example.com", + "issues": "https://github.com/example/pair/issues", + "docs": "https://pair.example.com/docs", + "support": "https://github.com/example/pair/discussions", + "repository": "https://github.com/example/pair", + "badges": [ + { + "alt": "Test Status", + "src": "https://test.packages.postgresql.org/github.com/example/pair.svg" + } + ] +} ``` -(Spec 1) [optional] {[String](#String)} - -This field specifies the release status of this distribution. It **must** have -one of the following values: +(Spec 2) [optional] {[Object](#object)} -* **stable**: Indicates an ordinary, "final" release that should be indexed - by PGXN. +This property provides external information about the [Package](#package) +provided by the [Distribution](#source-distribution). [Consumers](#consumer) +**MAY** use this data for links and displaying useful information about the +package. -* **testing**: Indicates a "beta" release that is substantially complete, - but has an elevated risk of bugs and requires additional testing. The - distribution should not be installed over a stable release without an - explicit request or other confirmation from a user. This release status - may also be used for "release candidate" versions of a distribution. +The `resources` object **MUST** contain at least one of the following +properties: -* **unstable**: Indicates an "alpha" release that is under active - development, but has been released for early feedback or testing and may - be missing features or may have serious bugs. The distribution should not - be installed over a stable release without an explicit request or other - confirmation from a user. +* **homepage**: [URI](#uri) for the official home of the project on the web. +* **issues**: [URI](#uri) for the package's issue tracking system. +* **repository**: [URI](#uri) for the package's source code repository. +* **docs**: [URI](#uri) for the package's documentation. +* **support**: [URI](#uri) for support resources and contacts for the + package. +* **badges**: An [Array](#array) of [Objects](#object) linking to badge + images that **SHOULD** follow the [Shields badge specification]. It + **MUST** have at least one entry, and all entries require two properties: + * **src**: The [URI](#uri) for the badge. + * **alt**: Alt text for the badge. -Consumers **may** use this field to determine how to index the distribution -for PGXN or other repositories. If this field is not present, consumers -**may** assume that the distribution status is "stable." - -### resources ### - -Example: +#### artifacts #### ``` json -"resources": { - "homepage": "https://pgxn.org/", - "bugtracker": { - "web": "https://github.com/theory/pgtap/issues", - "mailto": "pgxn-bugs@example.com" +[ + { + "type": "source", + "url": "https://github.com/theory/pg-pair/releases/download/v1.1.0/pair-1.1.0.zip", + "sha256": "2b9d2416096d2930be51e5332b70bcd97846947777a93e4a3d65fe1b5fd7b004" }, - "repository": { - "url": "git://github.com/theory/pgtap.git", - "web": "https://github.com/theory/pgtap/", - "type": "git" + { + "type": "binary", + "url": "https://github.com/theory/pg-pair/releases/download/v1.1.0/pair-1.1.0-linux-amd64.tar.gz", + "sha1": "12d9bc5cfb6bc3c453627eac69511f48be63cfc0" }, - "x_twitter": "https://twitter.com/pgtap/" -} + { + "type": "binary", + "url": "https://github.com/theory/pg-pair/releases/download/v1.1.0/pair-1.1.0-linux-arm64.tar.gz", + "sha1": "787dc39137f7d1510a33ab0a1b8905cd5f3f72d1" + } +] ``` -(Spec 1) [optional] {[Map](#Map)} - -This field describes resources related to this distribution. - -Valid subkeys include: - -* **homepage**: A [URI](#URI) for the official home of this project on the - web. - -* **bugtracker**: This entry describes the bug tracking system for this distribution. It is - a [Map](#Map) with the following valid keys: - - * **web**: a [URI](#uri) pointing to a web front-end for the bug - tracker - * **mailto**: an email address to which bug reports can be sent - -* **repository**: This entry describes the source control repository for this distribution. - It is a [Map](#Map) with the following valid keys: - - * **url**: a [URI](#uri) pointing to the repository itself - * **web**: a [URI](#uri) pointing to a web front-end for the repository - * **type**: a lowercase string indicating the VCS used - - Because a URI like `https://myrepo.example.com/` is ambiguous as to type, - producers should provide a `type` whenever a `url` key is given. The - `type` field should be the name of the most common program used to work - with the repository, e.g. git, svn, cvs, darcs, bzr or hg. - -Version Numbers -=============== - -Version Format --------------- - -This section defines the [Version](#Version) type, used by several -fields in the PGXN Meta Spec. - -Version numbers must be treated as strings, and adhere to the [Semantic -Versioning 2.0.0 Specification][semver]. Semantic versions take a -dotted-integer format consisting of three positive integers separated by full -stop characters (i.e. "dots", "periods" or "decimal points"). A "pre-release -version" *may* be denoted by appending a dash followed by an arbitrary ASCII -string immediately following the patch version. Please see [the -specification][semver] for all details on the format. - -Version Ranges --------------- - -Some fields (`prereqs`) indicate the particular version(s) of some other -extension that may be required as a prerequisite. This section details the -[Version Range](#Version.Range) type used to provide this information. - -The simplest format for a Version Range is just the version number itself, -e.g. `2.4.0`. This means that **at least** version 2.4.0 must be present. To -indicate that **any** version of a prerequisite is okay, even if the -prerequisite doesn’t define a version at all, use the version `0`. - -Alternatively, a version range **may** use the operators `<` (less than), `<=` -(less than or equal), `>` (greater than), `>=` (greater than or equal), `==` -(equal), and `!=` (not equal). For example, the specification `< 2.0.0` means -that any version of the prerequisite less than 2.0.0 is suitable. - -For more complicated situations, version specifications **may** be AND-ed -together using commas. The specification `>= 1.2.0, != 1.5.0, < 2.0.0` -indicates a version that must be **at least** 1.2.0, **less than** 2.0.0, and -**not equal to** 1.5.0. - -Prerequisites -============= - -Prereq Spec ------------ - -The `prereqs` key defines the relationship between a distribution and other -extensions. The prereq spec structure is a hierarchical data structure which -divides prerequisites into *Phases* of activity in the installation process -and *Relationships* that indicate how prerequisites should be resolved. - -For example, to specify that `pgtap` is required during the `test` phase, this -entry would appear in the distribution metadata: +(Spec 2) [optional] {[Array](#array)} + +An [Array](#array) of [Objects](#objects) describing links and checksums for +downloading the [Package](#package) provided by the +[Distribution](#source-distribution) in one or more formats, including source +code, binaries, system packages, and more. [Consumers](#consumer) my use this +information to determine the best option for installing an extension on a +particular system. Useful for projects that publish their own binaries, such +as in GitHub releases. + +The [Array](#array) **MUST** have at least one [Object](#object). The +properties of each [Object](#object) are: + +* **url**: A [URI](#uri) to download the artifact. **REQUIRED**. +* **sha256** or **sha512**: A [String](#string) containing a SHA-256 or + SHA-512 checksum in hex format. **REQUIRED**. +* **type**: The type of artifact. **MUST** be a single lowercase word + describing the artifact, such as none of `binary`, `source`, `rpm`, + `homebrew`, etc. **REQUIRED**. +* **platform**: A [Platform](#platform) string identifying the platform the + artifact was built for. **RECOMMENDED** for packages compiled for a + specific platform, such as a C [Extension](#extension) compiled for + `linux-arm64`. + +Each URL **MUST** properly resolve and the checksum **MUST** match. + +## Packages Spec ## + +The `packages` sub-property of the [dependencies](#dependencies) property +defines the relationship between a [Distribution](#source-distribution) and +external dependencies --- including other PGXN [Packages](#package), system +packages, and third-party packages --- expressed as [purls](#purl). The +structure is an [Object](#object) that specifies package dependencies into +*Phases* of activity in the installation process, and *Relationships* that +indicate how dependencies **SHOULD** be resolved. + +For example, to specify that the [PGXN] extension `pgtap` by user `theory` is +required during the `test` phase, this entry would appear in the +[Distribution](#source-distribution) metadata: ``` json -"prereqs": { +"packages": { "test": { - "requires": { - "pgtap": 0 - } + "requires": [ "pkg:pgxn/theory/pgtap" ] } } ``` -Note that the `prereqs` key may not be used to specify prerequisites -distributed outside PGXN or the PostgreSQL core and its contrib extensions. +All known [purl Types] **MAY** be used to identify dependencies and specific +versions. [Producers](#producer) **SHOULD** specify dependencies of two +additional types as appropriate: + +* **`pkg:pgxn`**: Packages distributed via [PGXN]. These **MUST** include + both the username and package name, e.g., `pkg:pgxn/theory/pair`. +* **`pkg:postgres`**: Dependencies distributed as part of the PostgreSQL + core, including [contrib] or development packages such as [auto_explain], + [dblink], [pg_regress] and [pg_isolation_regress]. Example: + `pkg:postgres/dblink`. + +[Producers](#producer) **SHOULD** avoid OS-specific [purls](#purl) such as +`pkg:rpm:/libreadline-dev` unless the package supports only OSes that provide +such packages. See the "variations" property of the +[dependencies](#dependencies) object for platform-specific dependency +specification. + +[Consumers](#consumer) **SHOULD** use [Repology] to resolve `pkg:generic` +[purls](#purl) to packages specific to the platform on which an extension is +being built. This is useful for specifying system dependencies that vary by +name and packaging system. Otherwise, they **MAY** use whatever techniques or +heuristics are appropriate to install dependencies. ### Phases ### -Requirements for regular use must be listed in the `runtime` phase. Other -requirements should be listed in the earliest stage in which they are required -and consumers must accumulate and satisfy requirements across phases before -executing the activity. For example, `build` requirements must also be -available during the `test` phase. +Requirements for regular use **MUST** be listed in the `runtime` phase. Other +requirements **SHOULD** be listed in the earliest stage in which they are +required, and [Consumers](#consumer) **MUST** accumulate and satisfy +requirements across phases before executing the action. For example, `build` +requirements **MUST** also be available during the `test` phase. - before action | requirements that must be met -----------------|--------------------------------- + before action | requirements that **MUST** be met +----------------|----------------------------------- ./configure | configure make | configure, runtime, build make test | configure, runtime, build, test -Consumers that install the distribution must ensure that *runtime* -requirements are also installed and may install dependencies from other +Consumers that install the [Package](#package) provided by the +[Distribution](#source-distribution) **MUST** ensure that *runtime* +requirements are also installed and **MAY** install dependencies from other phases. - after action | requirements that must be met -----------------|--------------------------------- + after action | requirements that **MUST** be met +----------------|----------------------------------- make install | runtime * **configure**: The configure phase occurs before any dynamic configuration - has been attempted. Extensions required by the configure phase **must** be - available for use before the distribution building tool has been executed. - -* **build**: The build phase is when the distribution’s source code is - compiled (if necessary) and otherwise made ready for installation. - -* **test**: The test phase is when the distribution’s automated test suite - is run. Any extension needed only for testing and not for subsequent use - should be listed here. - -* **runtime**: The runtime phase refers not only to when the distribution’s - contents are installed, but also to its continued use. Any extension that - is a prerequisite for regular use of this distribution should be indicated - here. - -* **develop**: The develop phase’s prereqs are extensions needed to work on - the distribution’s source code as its maintainer does. These tools might - be needed to build a release tarball, to run maintainer-only tests, or to - perform other tasks related to developing new versions of the - distribution. + has been attempted. Dependencies required by the configure phase **MUST** + be available for use before the build tool has been executed. + +* **build**: The build phase is when the + [Distribution](#source-distribution)'s source code is compiled (if + necessary) and otherwise made ready for installation. + +* **test**: The test phase is when the + [Distribution](#source-distribution)'s automated test suite is run. Any + dependency needed only for testing and not for subsequent use **SHOULD** + be listed here. + +* **runtime**: The runtime phase refers not only to when the contents of the + [Package](#package) provided by the [Distribution](#source-distribution) + are installed, but also to its continued use. Any package that is a + dependency for regular use of this [Package](#package) **SHOULD** be + indicated here. + +* **develop**: The develop phase's packages are needed to work on the + [Package](#package)'s source code as its maintainer does. These tools + might be needed to build a release archive, to run maintainer-only tests, + or to perform other tasks related to developing new versions of the + [Package](#package). ### Relationships ### -requires -: These dependencies **must** be installed for proper completion of the - phase. +* **requires**: These dependencies **MUST** be installed for proper + completion of the phase. -recommends -: Recommended dependencies are *strongly* encouraged and should be satisfied - except in resource constrained environments. +* **recommends**: **RECOMMENDED** dependencies are *strongly* encouraged and + **SHOULD** be satisfied except in resource constrained environments. -suggests -: These dependencies are optional, but are suggested for enhanced operation - of the described distribution. +* **suggests**: These dependencies are **OPTIONAL**, are suggested for + enhanced operation of the described distribution, and **MAY** be + satisfied. -conflicts -: These dependencies cannot be installed when the phase is in operation. - This is a very rare situation, and the conflicts relationship should be - used with great caution, or not at all. - -Merging and Resolving Prerequisites ------------------------------------ - -Whenever metadata consumers merge prerequisites, they should be merged in a -way that preserves the intended semantics of the prerequisite structure. -Generally, this means concatenating the version specifications using commas, -as described in the [Version Ranges](#Version.Ranges) section. - -A subtle error that can occur when resolving prerequisites comes from the way -that extensions in prerequisites are indexed to distribution files on PGXN. -When a extension is deleted from a distribution, prerequisites calling for -that extension could indicate that an older distribution should installed, -potentially overwriting files from a newer distribution. - -For example, say the PGXN index contained these extension-distribution -mappings: - - Extension | Version | Distribution -------------|---------|------------------ - pgtap | 0.25.0 | pgtap-0.25.0.zip - schematap | 0.25.0 | pgtap-0.25.0.zip - functap | 0.18.1 | pgtap-0.18.1.zip - -Note that functap was removed from the pgtap distribution sometime after -0.18.1. Consider the case where pgtap 0.25.0 is installed. If a distribution -specified "functap" as a prerequisite, it could result in -`pgtap-0.18.1.tar.gz` being installed, overwriting any files from -`pgtap-0.25.0.zip`. - -Consumers of metadata **should** test whether prerequisites would result in -installed module files being "downgraded" to an older version and **may** warn -users or ignore the prerequisite that would cause such a result. +* **conflicts**: These dependencies **MUST NOT** be installed when the phase + is in operation. This is a very rare situation, and the conflicts + relationship **SHOULD** be used with great caution, or not at all. Serialization ============= -Distribution metadata should be serialized as JSON-encoded data and packaged -with distributions as the file `META.json`. - -Notes For Implementors -====================== - -Comparing Version Numbers -------------------------- - -Following the [Semantic Versioning 2.0.0 Spec][semver], version numbers -**must** be strictly compared by splitting the [Version](#Version) string on -full stop characters (i.e. "dots", "periods" or "decimal points") and -comparing each of the three parts as integers. If a dash and prerelease ASCII -string has been appended to the third number, it will be extracted and -compared in ASCII-betical order, and in any event will be considered to be -less than an un-encumbered third integer of the same value. Some examples: - -``` -0.12.1 < 0.12.2 -1.42.0 > 1.41.99 -2.0.0 > 1.999.999 -2.0.0alpha3 < 2.0.0beta1 -2.0.0beta < 2.0.0 -``` +Distribution metadata **SHOULD** be serialized as JSON-encoded data and +packaged with distributions as the file `META.json`. See Also ======== @@ -861,20 +1043,53 @@ See Also Contributors ============ -The PGXN Meta Spec borrows heavily from the [CPAN Meta Spec], which was -originally written by Ken Williams in 2003 and has since been updated by Randy -Sims, David Golden, and Ricardo Signes. Ported to PGXN by David E. Wheeler. +The PGXN Meta Spec was originally based on the [CPAN Meta Spec], which was +written by Ken Williams in 2003 and has since been updated by Randy Sims, +David Golden, Ricardo Signes, Adam Kennedy, and contributors. - [MultiMarkdown]: https://fletcherpenney.net/multimarkdown/ + [PGXN]: https://pgxn.org "PostgreSQL Extension Network" + [source code repository]: https://github.org/pgxn/pgxn-meta-spec + [PostgreSQL License]: https://www.postgresql.org/about/licence/ + [CC BY-SA 4.0]: https://creativecommons.org/licenses/by-sa/4.0/ "Attribution-Sharealike 4.0 International" + [Github Flavored Markdown]: https://github.github.com/gfm/ [Markdown]: https://daringfireball.net/projects/markdown/ [master.pgxn.org/meta/spec.txt]: https://master.pgxn.org/meta/spec.txt [pgxn.org/spec/]: https://pgxn.org/spec/ + [archive file]: https://en.wikipedia.org/wiki/Archive_file + "Wikipedia: “Archive file”" [`semver`]: https://pgxn.org/dist/semver/ - [`pair`]: https://pgxn.org/dist/pair/ - [`pgTAP`]: https://pgxn.org/dist/pgtap/ + [`vector`]: https://pgxn.org/dist/vector/ + [`citus`]: https://pgxn.org/dist/citus/ [`CREATE EXTENSION` statement]: https://www.postgresql.org/docs/current/static/sql-createextension.html [IETF RFC 2119]: https://www.ietf.org/rfc/rfc2119.txt [JSON]: https://json.org/ + [IETF RFC 3986]: https://www.rfc-editor.org/info/rfc3986 + "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax" + [purl spec]: https://github.com/package-url/purl-spec/blob/master/PURL-SPECIFICATION.rst + "package-url/purl-spec: A minimal specification a “mostly universal” package URL" + [percent-encoded]: https://github.com/package-url/purl-spec/blob/master/PURL-SPECIFICATION.rst#character-encoding + "Package URL specification: Character encoding" + [purl Types]: https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst + "Package URL Type definitions" [semver]: https://semver.org/ + [SPDX License List]: https://github.com/spdx/license-list-data/ + [SPDX Standard License Expression]: https://spdx.github.io/spdx-spec/v3.0/annexes/SPDX-license-expressions/ + [control file]: https://www.postgresql.org/docs/current/extend-extensions.html + [trusted language extension]: https://github.com/aws/pg_tle + "pg_tle: Framework for building trusted language extensions for PostgreSQL" + [background workers]: https://www.postgresql.org/docs/current/bgworker.html + "PostgreSQL Docs: Background Worker Processes" + [loadable modules]: https://www.postgresql.org/docs/16/gist-extensibility.html + [gitignore format]: https://git-scm.com/docs/gitignore + [bulid farm animals]: https://buildfarm.postgresql.org/cgi-bin/show_members.pl + [configure flags]: https://www.postgresql.org/docs/current/install-make.html#CONFIGURE-OPTIONS-FEATURES + [Repology API]: https://repology.org/api "Repology, the packaging hub: API" + [contrib]: https://www.postgresql.org/docs/current/contrib.html + [auto_explain]: https://www.postgresql.org/docs/current/auto-explain.html + [dblink]: https://www.postgresql.org/docs/current/dblink.html + [pg_regress]: https://github.com/postgres/postgres/tree/master/src/test/regress + [pg_isolation_regress]: https://github.com/postgres/postgres/tree/master/src/test/isolation + [Shields badge specification]: https://github.com/badges/shields/blob/master/spec/SPECIFICATION.md [CPAN Meta Spec]: https://metacpan.org/pod/CPAN::Meta::Spec - [PGXN]: https://pgxn.org/ + [musl]: https://musl.libc.org/ + [GNU]: https://www.gnu.org/software/libc/