diff --git a/doc/redirects.json b/doc/redirects.json index 8f45ed9add20b..41d1f5a9a3e9b 100644 --- a/doc/redirects.json +++ b/doc/redirects.json @@ -412,6 +412,9 @@ "sec-meta-identifiers-cpe": [ "index.html#sec-meta-identifiers-cpe" ], + "sec-meta-identifiers-purl": [ + "index.html#sec-meta-identifiers-purl" + ], "sec-modify-via-packageOverrides": [ "index.html#sec-modify-via-packageOverrides" ], @@ -932,6 +935,15 @@ "var-meta-identifiers-possibleCPEs": [ "index.html#var-meta-identifiers-possibleCPEs" ], + "var-meta-identifiers-purl": [ + "index.html#var-meta-identifiers-purl" + ], + "var-meta-identifiers-purlParts": [ + "index.html#var-meta-identifiers-purlParts" + ], + "var-meta-identifiers-purls": [ + "index.html#var-meta-identifiers-purls" + ], "var-meta-teams": [ "index.html#var-meta-teams" ], diff --git a/doc/release-notes/rl-2611.section.md b/doc/release-notes/rl-2611.section.md index ed4f8a8240f36..5a25672b31d6b 100644 --- a/doc/release-notes/rl-2611.section.md +++ b/doc/release-notes/rl-2611.section.md @@ -16,7 +16,11 @@ -- Create the first release note entry in this section! +- Package-URL (PURL, https://github.com/package-url/purl-spec) metadata identifier has been added for `fetchgit`, `fetchpypi` and `fetchFromGithub` fetchers. + `mkDerivation` has been adjusted to reuse this information. + Package-URLs allow reliably identifying and locating software packages. + Maintainers of derivations using the adapted fetchers should rely on the `drv.src.meta.identifiers.v1.purl` default identifier and can enhance their `drv.meta.identifiers.v1.purls` list once they would like to have additional identifiers. + Maintainers using `fetchurl` for `drv.src` are urged to adapt their `drv.meta.identifiers.purlParts` for proper identification. ## Nixpkgs Library {#sec-nixpkgs-release-26.11-lib} diff --git a/doc/stdenv/meta.chapter.md b/doc/stdenv/meta.chapter.md index 1fac5244af665..a88683ed37b72 100644 --- a/doc/stdenv/meta.chapter.md +++ b/doc/stdenv/meta.chapter.md @@ -334,3 +334,30 @@ A readonly attribute that concatenates all CPE parts in one string. #### `meta.identifiers.possibleCPEs` {#var-meta-identifiers-possibleCPEs} A readonly attribute containing the list of guesses for what CPE for this package can look like. It includes all variants of version handling mentioned above. Each item is an attrset with attributes `cpeParts` and `cpe` for each guess. + +### Package URL {#sec-meta-identifiers-purl} + +[Package-URL](https://github.com/package-url/purl-spec) (PURL) is a specification to reliably identify and locate software packages. +Through identification of software packages, additional (non-major) use cases are e.g. software license cross-verification via third party databases or initial vulnerability response management. +Package-URLs shall default to the `mkDerivation.src`, as the original consumed software package is the single source of truth. + +#### `meta.identifiers.purlParts` {#var-meta-identifiers-purlParts} + +This attribute contains an attribute set of all parts of the PURL for this package. + +* `type` mandatory [type](https://github.com/package-url/purl-spec/blob/18fd3e395dda53c00bc8b11fe481666dc7b3807a/docs/standard/summary.md) which needs to be provided +* `spec` specify the PURL in accordance with the [purl-spec](https://github.com/package-url/purl-spec/blob/18fd3e395dda53c00bc8b11fe481666dc7b3807a/purl-specification.md) + +#### `meta.identifiers.purl` {#var-meta-identifiers-purl} + +An extendable attribute which is built based on `purlParts`. +This is the main identifier of the software package. +For handling edge cases, consider using the list interface [`meta.identifiers.purls`](#var-meta-identifiers-purls). + +#### `meta.identifiers.purls` {#var-meta-identifiers-purls} + +An extendable list attribute which defaults to a single element equal to [`meta.identifiers.purl`](#var-meta-identifiers-purl). +It provides an interface for additional identifiers of `mkDerivation.src` or for identifiers of vendored dependencies inside `mkDerivation.src`, which maintainers may carefully consider to specify as well. + +Additional identifiers are generally not recommended, as they might cause maintenance overhead or diverge. +For example, a source distribution `pkg:github` may be hard to keep correctly aligned with the corresponding binary distribution `pkg:pypi`. diff --git a/pkgs/build-support/fetchgit/default.nix b/pkgs/build-support/fetchgit/default.nix index 5cf447e37a0de..3eb3f412d37d4 100644 --- a/pkgs/build-support/fetchgit/default.nix +++ b/pkgs/build-support/fetchgit/default.nix @@ -251,7 +251,18 @@ lib.makeOverridable ( ${if allowedRequisites != null then "allowedRequisites" else null} = allowedRequisites; }; - inherit preferLocalBuild meta; + inherit preferLocalBuild; + + meta = meta // { + identifiers = { + purlParts = { + type = "generic"; + # https://github.com/package-url/purl-spec/blob/18fd3e395dda53c00bc8b11fe481666dc7b3807a/types-doc/generic-definition.md + spec = "${name}?vcs_url=${url}@${(lib.revOrTag rev tag)}"; + }; + } + // meta.identifiers or { }; + }; env = { NIX_PREFETCH_GIT_CHECKOUT_HOOK = finalAttrs.postCheckout; diff --git a/pkgs/build-support/fetchgithub/default.nix b/pkgs/build-support/fetchgithub/default.nix index e12052e3d15de..1b0a1aa928051 100644 --- a/pkgs/build-support/fetchgithub/default.nix +++ b/pkgs/build-support/fetchgithub/default.nix @@ -89,6 +89,22 @@ decorate ( meta // { homepage = meta.homepage or baseUrl; + identifiers = { + purlParts = + if githubBase == "github.com" then + { + type = "github"; + # https://github.com/package-url/purl-spec/blob/18fd3e395dda53c00bc8b11fe481666dc7b3807a/types-doc/github-definition.md + spec = "${owner}/${repo}@${(lib.revOrTag rev tag)}"; + } + else + { + type = "generic"; + # https://github.com/package-url/purl-spec/blob/18fd3e395dda53c00bc8b11fe481666dc7b3807a/types-doc/generic-definition.md + spec = "${repo}?vcs_url=https://${githubBase}/${owner}/${repo}@${(lib.revOrTag rev tag)}"; + }; + } + // meta.identifiers or { }; } // lib.optionalAttrs (position != null) { # to indicate where derivation originates, similar to make-derivation.nix's mkDerivation diff --git a/pkgs/build-support/fetchpypi/default.nix b/pkgs/build-support/fetchpypi/default.nix index 71530bddff377..453883ac13f2e 100644 --- a/pkgs/build-support/fetchpypi/default.nix +++ b/pkgs/build-support/fetchpypi/default.nix @@ -51,6 +51,8 @@ lib.makeOverridable ( format ? "setuptools", sha256 ? "", hash ? "", + pname, + version, ... }@attrs: let @@ -60,8 +62,20 @@ lib.makeOverridable ( "hash" ] ); + meta = { + identifiers.purlParts = { + type = "pypi"; + # https://github.com/package-url/purl-spec/blob/18fd3e395dda53c00bc8b11fe481666dc7b3807a/types-doc/pypi-definition.md + spec = "${pname}@${version}"; + }; + }; in fetchurl { - inherit url sha256 hash; + inherit + url + sha256 + hash + meta + ; } ) diff --git a/pkgs/by-name/jq/jq/package.nix b/pkgs/by-name/jq/jq/package.nix index 31633d27ba033..70b6bb169fcea 100644 --- a/pkgs/by-name/jq/jq/package.nix +++ b/pkgs/by-name/jq/jq/package.nix @@ -139,5 +139,9 @@ stdenv.mkDerivation (finalAttrs: { ]; platforms = lib.platforms.unix; mainProgram = "jq"; + identifiers.purlParts = { + type = "github"; + spec = "jqlang/jq@jq-${finalAttrs.version}"; + }; }; }) diff --git a/pkgs/by-name/po/popt/package.nix b/pkgs/by-name/po/popt/package.nix index b7e84260c1b2b..abe07f84237b0 100644 --- a/pkgs/by-name/po/popt/package.nix +++ b/pkgs/by-name/po/popt/package.nix @@ -60,5 +60,9 @@ stdenv.mkDerivation (finalAttrs: { maintainers = with lib.maintainers; [ qyliss ]; license = lib.licenses.mit; platforms = lib.platforms.unix; + identifiers.purlParts = { + type = "github"; + spec = "rpm-software-management/popt@popt-${finalAttrs.version}-release"; + }; }; }) diff --git a/pkgs/development/ruby-modules/gem/default.nix b/pkgs/development/ruby-modules/gem/default.nix index a759f10138f38..ba2a5dddcb847 100644 --- a/pkgs/development/ruby-modules/gem/default.nix +++ b/pkgs/development/ruby-modules/gem/default.nix @@ -72,6 +72,13 @@ lib.makeOverridable ( attrs.source.remotes or [ "https://rubygems.org" ] ); inherit (attrs.source) sha256; + meta = { + identifiers.purlParts = { + type = "gem"; + # https://github.com/package-url/purl-spec/blob/18fd3e395dda53c00bc8b11fe481666dc7b3807a/types-doc/gem-definition.md + spec = "${gemName}@${version}?platform=${platform}"; + }; + }; } else if type == "git" then fetchgit { diff --git a/pkgs/stdenv/generic/check-meta.nix b/pkgs/stdenv/generic/check-meta.nix index 91e40c3651275..62b2abdf5b2f2 100644 --- a/pkgs/stdenv/generic/check-meta.nix +++ b/pkgs/stdenv/generic/check-meta.nix @@ -622,14 +622,37 @@ let cpe = makeCPE guessedParts; } ) possibleCPEPartsFuns; + + purlParts = attrs.meta.identifiers.purlParts or { }; + purlPartsFormatted = + if purlParts ? type && purlParts ? spec then "pkg:${purlParts.type}/${purlParts.spec}" else null; + + # search for a PURL in the following order: + purl = + # 1) locally set through API + if purlPartsFormatted != null then purlPartsFormatted else null; + + # search for a PURL in the following order: + purls = + # 1) locally overwritten through meta.identifiers.purls (e.g. extension of list) + attrs.meta.identifiers.purls or ( + # 2) locally set through API + if purlPartsFormatted != null then [ purlPartsFormatted ] else [ ] + ); + v1 = { - inherit cpeParts possibleCPEs; + inherit + cpeParts + possibleCPEs + purls + ; ${if cpe != null then "cpe" else null} = cpe; + ${if purl != null then "purl" else null} = purl; }; in v1 // { - inherit v1; + inherit v1 purlParts; }; # Expose the result of the checks for everyone to see.