diff --git a/lib/modules/versioning/api.ts b/lib/modules/versioning/api.ts index 7329e25b87fd77133e2b797153bc0ec49eac39d6..f9899d112ac0991f39d468b5842c571771aca20e 100644 --- a/lib/modules/versioning/api.ts +++ b/lib/modules/versioning/api.ts @@ -14,6 +14,7 @@ import * as ivy from './ivy'; import * as kubernetesApi from './kubernetes-api'; import * as loose from './loose'; import * as maven from './maven'; +import * as nixpkgs from './nixpkgs'; import * as node from './node'; import * as npm from './npm'; import * as nuget from './nuget'; @@ -50,6 +51,7 @@ api.set(ivy.id, ivy.api); api.set(kubernetesApi.id, kubernetesApi.api); api.set(loose.id, loose.api); api.set(maven.id, maven.api); +api.set(nixpkgs.id, nixpkgs.api); api.set(node.id, node.api); api.set(npm.id, npm.api); api.set(nuget.id, nuget.api); diff --git a/lib/modules/versioning/nixpkgs/index.spec.ts b/lib/modules/versioning/nixpkgs/index.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..c22e106982e390ef791ac3b75f4ce37963fb3119 --- /dev/null +++ b/lib/modules/versioning/nixpkgs/index.spec.ts @@ -0,0 +1,84 @@ +import { NixPkgsVersioning } from '.'; + +describe('modules/versioning/nixpkgs/index', () => { + const versioning = new NixPkgsVersioning(); + + test.each` + version | expected + ${undefined} | ${false} + ${null} | ${false} + ${''} | ${false} + ${'1.2.3'} | ${false} + ${'22.05'} | ${false} + ${'release-22.05'} | ${true} + ${'nixos-22.05'} | ${true} + ${'nixos-22.05-small'} | ${true} + ${'nixos-22.05-aarch64'} | ${true} + ${'nixos-22.05-aarch64-small'} | ${false} + ${'nixpkgs-22.05-darwin'} | ${true} + ${'nixpkgs-22.05-darwin-aarch64'} | ${false} + ${'nixos-unstable'} | ${true} + ${'nixos-unstable-small'} | ${true} + ${'nixpkgs-unstable'} | ${true} + ${'nixos-22.05.1234'} | ${false} + ${'nixos-22.05-1234'} | ${false} + ${'nixos-22.05-unknown'} | ${false} + ${'unknown-22.05'} | ${false} + ${'nixos-nixpkgs-22.05'} | ${false} + `('isValid("$version") === $expected', ({ version, expected }) => { + expect(versioning.isValid(version)).toBe(expected); + }); + + test.each` + version | expected + ${undefined} | ${false} + ${null} | ${false} + ${''} | ${false} + ${'release-22.05'} | ${true} + ${'nixos-22.05'} | ${true} + ${'nixos-22.05-small'} | ${true} + ${'nixos-22.05-aarch64'} | ${true} + ${'nixpkgs-22.05-darwin'} | ${true} + ${'nixos-unstable'} | ${false} + ${'nixos-unstable-small'} | ${false} + ${'nixpkgs-unstable'} | ${false} + `('isStable("$version") === $expected', ({ version, expected }) => { + expect(versioning.isStable(version)).toBe(expected); + }); + + test.each` + a | b | expected + ${'nixos-22.05'} | ${'nixos-22.05'} | ${true} + ${'nixos-22.05'} | ${'nixos-21.11'} | ${false} + ${'nixos-22.05'} | ${'nixos-unstable'} | ${false} + ${'nixos-unstable'} | ${'nixos-unstable'} | ${true} + ${'nixos-unstable-small'} | ${'nixos-unstable-small'} | ${true} + `('equals($a, $b) === $expected', ({ a, b, expected }) => { + expect(versioning.equals(a, b)).toBe(expected); + }); + + test.each` + versions | expected + ${['nixos-21.11', 'nixos-22.05', 'nixos-22.05-small', 'nixos-unstable', 'nixos-unstable-small']} | ${['nixos-21.11', 'nixos-22.05', 'nixos-22.05-small', 'nixos-unstable', 'nixos-unstable-small']} + `( + '$versions -> sortVersions -> $expected ', + ({ versions, expected }: { versions: string[]; expected: string[] }) => { + expect(versions.sort((a, b) => versioning.sortVersions(a, b))).toEqual( + expected + ); + } + ); + + test.each` + a | b | expected + ${'nixos-22.05'} | ${'nixos-22.05'} | ${true} + ${'nixos-22.05'} | ${'nixpkgs-22.05'} | ${false} + ${'nixos-22.05'} | ${'nixos-21.11'} | ${true} + ${'nixos-22.05'} | ${'nixos-unstable'} | ${true} + ${'nixos-22.05'} | ${'nixos-22.05-small'} | ${false} + ${'nixos-22.05'} | ${'nixos-22.05-aarch64'} | ${false} + ${'nixos-22.05'} | ${'nixos-22.05-darwin'} | ${false} + `('equals($a, $b) === $expected', ({ a, b, expected }) => { + expect(versioning.isCompatible(a, b)).toBe(expected); + }); +}); diff --git a/lib/modules/versioning/nixpkgs/index.ts b/lib/modules/versioning/nixpkgs/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..59928b60462503a0c0e8a1879356466f00ed422f --- /dev/null +++ b/lib/modules/versioning/nixpkgs/index.ts @@ -0,0 +1,71 @@ +import is from '@sindresorhus/is'; +import { RegExpVersion, RegExpVersioningApi } from '../regex'; +import type { VersioningApiConstructor } from '../types'; + +export const id = 'nixpkgs'; +export const displayName = 'Nixpkgs'; +export const urls = ['https://github.com/NixOS/nixpkgs']; +export const supportsRanges = false; + +export class NixPkgsVersioning extends RegExpVersioningApi { + private static readonly versionRegex = + '^(?<prefix>(nixos|nixpkgs|release))-((?<major>\\d{2})\\.(?<minor>\\d{2})|unstable)(-(?<suffix>(small|aarch64|darwin)))?$'; + + constructor() { + super(NixPkgsVersioning.versionRegex); + } + + protected override _parse(version: string): RegExpVersion | null { + const groups = this._config?.exec(version)?.groups; + + if (!groups) { + return null; + } + + const { prefix, major, minor, suffix } = groups; + const release = []; + + if (major) { + release.push(Number.parseInt(major, 10)); + } + + if (minor) { + release.push(Number.parseInt(minor, 10)); + } + + const compatibility = is.nonEmptyStringAndNotWhitespace(suffix) + ? `${prefix}-${suffix}` + : prefix; + + return { + release, + compatibility, + }; + } + + override isStable(version: string): boolean { + const parsed = this._parse(version); + return is.nonEmptyArray(parsed?.release); + } + + protected override _compare(version: string, other: string): number { + const left = this._parse(version); + const right = this._parse(other); + + // empty version is equal to 'unstable' + if (is.emptyArray(left?.release) && is.emptyArray(right?.release)) { + return 0; + } + if (is.emptyArray(left?.release)) { + return 1; + } + if (is.emptyArray(right?.release)) { + return -1; + } + return super._compare(version, other); + } +} + +export const api: VersioningApiConstructor = NixPkgsVersioning; + +export default api; diff --git a/lib/modules/versioning/nixpkgs/readme.md b/lib/modules/versioning/nixpkgs/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..5ab8950324b8686c561a21ba3cfb4f36b37288bd --- /dev/null +++ b/lib/modules/versioning/nixpkgs/readme.md @@ -0,0 +1,17 @@ +Nixpkgs versioning is designed to be used with the nix manager. + +NixOS releases follow the `YY.MM` pattern. +There are also some prefixes and suffixes allowed. +Using `22.05` as an example the allowed combination of prefixes and suffixes are: + +- `release-22.05` +- `nixos-22.05` +- `nixos-22.05-small` +- `nixos-22.05-aarch64` +- `nixpkgs-22.05-darwin` + +Additionally, there are some floating versions: + +- `nixos-unstable` +- `nixos-unstable-small` +- `nixpkgs-unstable`