Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: renovatebot/renovate
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 39.202.0
Choose a base ref
...
head repository: renovatebot/renovate
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 39.203.1
Choose a head ref
  • 7 commits
  • 11 files changed
  • 4 contributors

Commits on Mar 14, 2025

  1. feat(datasource/conda): support calling prefix.dev (#34681)

    Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>
    trim21 and secustor authored Mar 14, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    843a27e View commit details

Commits on Mar 15, 2025

  1. feat(presets): add workaround for TJ actions (#34825)

    rarkins authored Mar 15, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    9c29091 View commit details
  2. chore: disable strict mkdocs (#34827)

    rarkins authored Mar 15, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    41335fc View commit details
  3. chore(deps): update linters to v9.22.0 (main) (#34822)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    renovate[bot] authored Mar 15, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    0d1bd9e View commit details
  4. chore(deps): update dependency @types/node to v22.13.10 (main) (#34828)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    renovate[bot] authored Mar 15, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    470f03c View commit details

Commits on Mar 16, 2025

  1. fix(presets): Revert "feat(presets): add workaround for TJ actions" (#…

    rarkins authored Mar 16, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    19fef1c View commit details
  2. chore(deps): update pdm-project/setup-pdm action to v4.3 (main) (#34836)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    renovate[bot] authored Mar 16, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    9b3ac17 View commit details
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -605,7 +605,7 @@ jobs:
os: ${{ runner.os }}

- name: Setup PDM
uses: pdm-project/setup-pdm@b2472ca4258a9ea3aee813980a0100a2261a42fc # v4.2
uses: pdm-project/setup-pdm@deb8d8a4e2a03aabcef6f2cc981923fc6b29ef99 # v4.3
with:
python-version-file: .python-version
version: ${{ env.PDM_VERSION }}
Original file line number Diff line number Diff line change
@@ -156,6 +156,7 @@ exports[`modules/datasource/conda/index > getReleases > processes real data 1`]
"version": "3.9.3",
},
{
"releaseTimestamp": "2020-02-28T11:46:01.948Z",
"version": "3.10.0",
},
{
151 changes: 151 additions & 0 deletions lib/modules/datasource/conda/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { DateTime } from 'luxon';
import { getPkgReleases } from '..';
import { EXTERNAL_HOST_ERROR } from '../../../constants/error-messages';
import { datasource, defaultRegistryUrl } from './common';
@@ -88,6 +89,7 @@ describe('modules/datasource/conda/index', () => {
html_url: 'http://anaconda.org/anaconda/pytest',
dev_url: 'https://github.com/pytest-dev/pytest/',
versions: ['2.7.0', '2.5.1', '2.6.0'],
files: [],
});
const config = {
registryUrls: [
@@ -112,5 +114,154 @@ describe('modules/datasource/conda/index', () => {
sourceUrl: 'https://github.com/pytest-dev/pytest',
});
});

it('supports channel from prefix.dev with null response', async () => {
httpMock
.scope('https://prefix.dev/api/graphql')
.post('')
.reply(200, { data: { package: { variants: null } } });

const config = {
packageName: 'pytest',
registryUrls: ['https://prefix.dev/conda-forge'],
};
const res = await getPkgReleases({
...config,
datasource,
});
expect(res).toBe(null);
});

it('supports channel from prefix.dev with multiple page responses', async () => {
// mock files
httpMock
.scope('https://prefix.dev/api/graphql')
.post('')
.once()
.reply(200, {
data: {
package: {
variants: {
pages: 2,
page: [
{
version: '0.0.5',
createdAt: DateTime.fromISO(
'2020-02-29T01:40:21Z',
).toString(),
yankedReason: null,
urls: [{ url: 'https://dev/url', kind: 'DEV' }],
},
{
version: '0.0.5',
createdAt: DateTime.fromISO(
'2020-02-29T01:40:20.840Z',
).toString(),
yankedReason: null,
urls: [{ url: 'https://home/url', kind: 'HOME' }],
},
{
version: '0.0.5',
createdAt: DateTime.fromISO(
'2020-02-29T01:40:23Z',
).toString(),
yankedReason: null,
},
{
version: '0.0.56',
createdAt: null,
yankedReason: null,
},
],
},
},
},
});
httpMock
.scope('https://prefix.dev/api/graphql')
.post('')
.once()
.reply(200, {
data: {
package: {
variants: {
pages: 2,
page: [
{
version: '0.0.7',
createdAt: DateTime.fromISO(
'2020-02-29T01:40:21Z',
).toString(),
yankedReason: null,
},
{
version: '0.0.8',
createdAt: DateTime.fromISO(
'2020-02-29T01:40:20.840Z',
).toString(),
yankedReason: null,
},
{
version: '0.0.10',
createdAt: DateTime.fromISO(
'2020-02-29T01:40:23Z',
).toString(),
yankedReason: null,
},
{
version: '0.0.560',
createdAt: null,
yankedReason: null,
},
],
},
},
},
});

const config = {
packageName: 'pytest',
registryUrls: ['https://prefix.dev/conda-forge'],
};
const res = await getPkgReleases({
...config,
datasource,
});
expect(res).toMatchObject({
registryUrl: 'https://prefix.dev/conda-forge',
homepage: 'https://home/url',
sourceUrl: 'https://dev/url',
releases: [
{
isDeprecated: false,
releaseTimestamp: '2020-02-29T01:40:21.000Z',
version: '0.0.5',
},
{
isDeprecated: false,
releaseTimestamp: '2020-02-29T01:40:21.000Z',
version: '0.0.7',
},
{
isDeprecated: false,
releaseTimestamp: '2020-02-29T01:40:20.840Z',
version: '0.0.8',
},
{
isDeprecated: false,
releaseTimestamp: '2020-02-29T01:40:23.000Z',
version: '0.0.10',
},
{
isDeprecated: false,
version: '0.0.56',
},
{
isDeprecated: false,
version: '0.0.560',
},
],
});
});
});
});
25 changes: 24 additions & 1 deletion lib/modules/datasource/conda/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { logger } from '../../../logger';
import { ExternalHostError } from '../../../types/errors/external-host-error';
import { coerceArray } from '../../../util/array';
import { cache } from '../../../util/cache/package/decorator';
import { HttpError } from '../../../util/http';
import { joinUrlParts } from '../../../util/url';
import { Timestamp } from '../../../util/timestamp';
import { ensureTrailingSlash, joinUrlParts } from '../../../util/url';
import { Datasource } from '../datasource';
import type { GetReleasesConfig, Release, ReleaseResult } from '../types';
import { datasource, defaultRegistryUrl } from './common';
import * as prefixDev from './prefix-dev';
import type { CondaPackage } from './types';

export class CondaDatasource extends Datasource {
@@ -43,6 +46,19 @@ export class CondaDatasource extends Datasource {
return null;
}

// fast.prefix.dev is a alias, deprecated, but still running.
// We expect registryUrl to be `https://prefix.dev/${channel}` here.
if (
registryUrl.startsWith('https://prefix.dev/') ||
registryUrl.startsWith('https://fast.prefix.dev/')
) {
// Since the registryUrl contains at least 3 `/` ,
// the channel varitable won't be undefined in any case.
const channel = ensureTrailingSlash(registryUrl).split('/').at(-2)!;

return prefixDev.getReleases(this.http, channel, packageName);
}

const url = joinUrlParts(registryUrl, packageName);

const result: ReleaseResult = {
@@ -57,9 +73,16 @@ export class CondaDatasource extends Datasource {
result.homepage = response.body.html_url;
result.sourceUrl = response.body.dev_url;

const releaseDate: Record<string, Timestamp> = {};
// we assume all packages are roughly released on the same time
for (const file of coerceArray(response.body.files)) {
releaseDate[file.version] ??= Timestamp.parse(file.upload_time);
}

response.body.versions.forEach((version: string) => {
const thisRelease: Release = {
version,
releaseTimestamp: releaseDate[version],
};
result.releases.push(thisRelease);
});
114 changes: 114 additions & 0 deletions lib/modules/datasource/conda/prefix-dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { logger } from '../../../logger';
import { isNotNullOrUndefined } from '../../../util/array';
import type { Http } from '../../../util/http';
import { MaybeTimestamp } from '../../../util/timestamp';
import type { Release, ReleaseResult } from '../types';
import { type File, PagedResponseSchema } from './schema/prefix-dev';

const MAX_PREFIX_DEV_GRAPHQL_PAGE = 100;

const query = `
query search($channel: String!, $package: String!, $page: Int = 0) {
package(channelName: $channel, name: $package) {
variants(limit: 500, page: $page) {
pages
page {
createdAt
version
yankedReason
urls {
url
kind
}
}
}
}
}
`;

export async function getReleases(
http: Http,
channel: string,
packageName: string,
): Promise<ReleaseResult | null> {
logger.debug(
{ channel, packageName },
'lookup package from prefix.dev graphql API',
);

const files = await getPagedResponse(http, query, {
channel,
package: packageName,
});

if (!files.length) {
return null;
}

let homepage: string | undefined = undefined;
let sourceUrl: string | undefined = undefined;

const releases: Record<string, Release> = {};
for (const file of files) {
const version = file.version;

homepage ??= file.urls.HOME;
sourceUrl ??= file.urls.DEV;

releases[version] ??= { version };

// we assume all packages are roughly released on the same time
releases[version].releaseTimestamp =
releases[version].releaseTimestamp ??
MaybeTimestamp.parse(file.createdAt);

// if the version has not been marked as deprecated, check other releases packages of the same version
if (!releases[version].isDeprecated) {
releases[version].isDeprecated = isNotNullOrUndefined(file.yankedReason);
}
}

return {
homepage,
sourceUrl,
releases: Object.values(releases),
};
}

async function getPagedResponse(
http: Http,
query: string,
data: any,
): Promise<File[]> {
const result: File[] = [];

for (let page = 0; page <= MAX_PREFIX_DEV_GRAPHQL_PAGE; page++) {
const res = await http.postJson(
'https://prefix.dev/api/graphql',
{
body: {
operationName: 'search',
query,
variables: {
...data,
page,
},
},
},
PagedResponseSchema,
);

const currentPage = res.body.data.package?.variants;
if (!currentPage) {
break;
}

result.push(...currentPage.page);

if (page >= currentPage.pages - 1) {
break;
}
}

return result;
}
35 changes: 32 additions & 3 deletions lib/modules/datasource/conda/readme.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,34 @@
This datasource returns releases from the specified [conda](https://docs.conda.io/en/latest/) registry.
This datasource returns releases for package from anaconda registry and prefix.dev. Other repositories are not supported currently.

The default registry is `https://api.anaconda.org/package/`, which queries a specific conda channel for a specific package.
This datasource support following cases:

Use `channel/packageName` as your `depName` when using this datasource.
Look up `numpy` in `conda-forge` channel on anaconda.

```
{
packageName: 'conda-forge/numpy',
}
```

Look up `numpy` in `conda-forge` channel from prefix.dev using API `https://prefix.dev/api/graphql`.

```
{
packageName: 'numpy',
registryUrls: ["https://prefix.dev/conda-forge/"]
}
```

### Multiple channels support

```
{
packageName: 'some-package',
registryUrls: [
"https://api.anaconda.org/package/conda-forge/",
"https://prefix.dev/conda-forge/",
]
}
```

The above example will lookup try to find the package on anaconda first, if the package can not be found on prefix.dev.
31 changes: 31 additions & 0 deletions lib/modules/datasource/conda/schema/prefix-dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { z } from 'zod';

export const File = z.object({
version: z.string(),
createdAt: z.string().nullable(),
yankedReason: z.string().nullable(),
urls: z
.array(z.object({ url: z.string(), kind: z.string() }))
.optional()
.default([])
.transform((urls) => {
return Object.fromEntries(urls.map((url) => [url.kind, url.url]));
}),
});

export type File = z.infer<typeof File>;

export const PagedResponseSchema = z.object({
data: z.object({
package: z
.object({
variants: z
.object({
pages: z.number(),
page: z.array(File),
})
.nullable(),
})
.nullable(),
}),
});
21 changes: 1 addition & 20 deletions lib/modules/datasource/conda/types.ts
Original file line number Diff line number Diff line change
@@ -12,8 +12,6 @@ export interface CondaPackage {
full_name: string;
owner: CondaPackageOwner;
home: string;
source_git_url: string;
source_git_tag: string;
app_type: Record<string, unknown>;
upvoted: number;
id: string;
@@ -36,7 +34,6 @@ export interface CondaPackage {
modified_at: string;
latest_version: CondaVersion;
summary: string;
license_url: string;
doc_url: string;
}

@@ -58,7 +55,7 @@ export interface CondaRelease {
}

export interface CondaFile {
description: string;
description?: string | null;
basename: string;
labels: string[];
dependencies: string[];
@@ -72,20 +69,4 @@ export interface CondaFile {
version: CondaVersion;
md5: string;
type: string;
attrs: {
build_number: number;
name: string;
license: string;
timestamp: number;
source_url: string;
platform: string;
depends: string[];
version: CondaVersion;
subdir: string;
build: string;
sha256: string;
arch: string;
md5: string;
size: number;
};
}
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -263,7 +263,7 @@
},
"devDependencies": {
"@containerbase/eslint-plugin": "1.1.4",
"@eslint/js": "9.21.0",
"@eslint/js": "9.22.0",
"@hyrious/marshal": "0.3.3",
"@ls-lint/ls-lint": "2.2.3",
"@openpgp/web-stream-tools": "0.1.3",
@@ -297,7 +297,7 @@
"@types/mdast": "3.0.15",
"@types/moo": "0.5.10",
"@types/ms": "2.1.0",
"@types/node": "22.13.9",
"@types/node": "22.13.10",
"@types/parse-link-header": "2.0.3",
"@types/punycode": "2.1.4",
"@types/semver": "7.5.8",
@@ -317,7 +317,7 @@
"conventional-changelog-conventionalcommits": "8.0.0",
"emojibase-data": "16.0.2",
"esbuild": "0.25.0",
"eslint": "9.21.0",
"eslint": "9.22.0",
"eslint-config-prettier": "10.1.1",
"eslint-formatter-gha": "1.5.2",
"eslint-import-resolver-typescript": "3.8.3",
213 changes: 110 additions & 103 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions tools/mkdocs.ts
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ program
logger.info('* running mkdocs build');
const args = ['run', 'mkdocs', 'build'];
if (opts.strict) {
args.push('--strict');
// args.push('--strict');
}
const res = exec('pdm', args, {
cwd: 'tools/mkdocs',
@@ -43,7 +43,7 @@ program
logger.info('* running mkdocs serve');
const args = ['run', 'mkdocs', 'serve'];
if (opts.strict) {
args.push('--strict');
// args.push('--strict');
}
const res = exec('pdm', args, {
cwd: 'tools/mkdocs',