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.214.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.215.0
Choose a head ref
  • 3 commits
  • 7 files changed
  • 3 contributors

Commits on Mar 25, 2025

  1. chore: remove an unused dev library @types/unist (#34997)

    secustor authored Mar 25, 2025
    Copy the full SHA
    ea15076 View commit details
  2. feat(devcontainer): extract known feature versions (#34999)

    viceice authored Mar 25, 2025
    Copy the full SHA
    8229c57 View commit details
  3. chore(deps): update dependency eslint-import-resolver-typescript to v…

    …4.2.1 (main) (#35002)
    
    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    renovate[bot] authored Mar 25, 2025
    Copy the full SHA
    bb08603 View commit details
84 changes: 84 additions & 0 deletions lib/modules/manager/devcontainer/extract.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { codeBlock } from 'common-tags';
import { GolangVersionDatasource } from '../../datasource/golang-version';
import { NodeVersionDatasource } from '../../datasource/node-version';
import { PythonVersionDatasource } from '../../datasource/python-version';
import { RubyVersionDatasource } from '../../datasource/ruby-version';
import { extractPackageFile } from '.';

describe('modules/manager/devcontainer/extract', () => {
@@ -364,5 +368,85 @@ describe('modules/manager/devcontainer/extract', () => {
],
});
});

it('parses known tool versions', () => {
// Arrange
const content = codeBlock`
{
"features": {
"ghcr.io/devcontainers/features/go:1": {"version": "1.24"},
"ghcr.io/devcontainers/features/node:1": {"version": "20"},
"ghcr.io/devcontainers/features/python:1": {"version": "3.12"},
"ghcr.io/devcontainers/features/ruby:1": {}
}
}`;
const extractConfig = {
registryAliases: {
'ghcr.io/devcontainers': 'some-registry.io/mirror',
},
};

// Act
const result = extractPackageFile(
content,
'devcontainer.json',
extractConfig,
);

// Assert
expect(result).toMatchObject({
deps: [
{
currentValue: '1',
datasource: 'docker',
depName: 'ghcr.io/devcontainers/features/go',
packageName: 'some-registry.io/mirror/features/go',
depType: 'feature',
},
{
currentValue: '1.24',
datasource: GolangVersionDatasource.id,
depName: 'go',
},
{
currentValue: '1',
datasource: 'docker',
depName: 'ghcr.io/devcontainers/features/node',
packageName: 'some-registry.io/mirror/features/node',
depType: 'feature',
},
{
currentValue: '20',
datasource: NodeVersionDatasource.id,
depName: 'node',
},
{
currentValue: '1',
datasource: 'docker',
depName: 'ghcr.io/devcontainers/features/python',
packageName: 'some-registry.io/mirror/features/python',
depType: 'feature',
},
{
currentValue: '3.12',
datasource: PythonVersionDatasource.id,
depName: 'python',
},
{
currentValue: '1',
datasource: 'docker',
depName: 'ghcr.io/devcontainers/features/ruby',
packageName: 'some-registry.io/mirror/features/ruby',
depType: 'feature',
},
{
currentValue: undefined,
datasource: RubyVersionDatasource.id,
depName: 'ruby',
skipReason: 'unspecified-version',
},
],
});
});
});
});
45 changes: 44 additions & 1 deletion lib/modules/manager/devcontainer/extract.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { logger } from '../../../logger';
import { GolangVersionDatasource } from '../../datasource/golang-version';
import { NodeVersionDatasource } from '../../datasource/node-version';
import { PythonVersionDatasource } from '../../datasource/python-version';
import { RubyVersionDatasource } from '../../datasource/ruby-version';
import { isValidDependency } from '../custom/utils';
import { getDep as getDockerDep } from '../dockerfile/extract';
import type {
@@ -33,7 +37,7 @@ export function extractPackageFile(
const features = file.features;

if (features) {
for (const feature of Object.keys(features)) {
for (const [feature, value] of Object.entries(features)) {
const featureDep = getDep(
feature,
packageFile,
@@ -43,6 +47,45 @@ export function extractPackageFile(
featureDep.depType = 'feature';
featureDep.pinDigests = false;
deps.push(featureDep);

let dep: PackageDependency;
switch (featureDep.depName) {
case 'ghcr.io/devcontainers/features/node':
dep = {
depName: 'node',
datasource: NodeVersionDatasource.id,
currentValue: value.version,
};
break;
case 'ghcr.io/devcontainers/features/go':
dep = {
depName: 'go',
datasource: GolangVersionDatasource.id,
currentValue: value.version,
};
break;
case 'ghcr.io/devcontainers/features/python':
dep = {
depName: 'python',
datasource: PythonVersionDatasource.id,
currentValue: value.version,
};
break;
case 'ghcr.io/devcontainers/features/ruby':
dep = {
depName: 'ruby',
datasource: RubyVersionDatasource.id,
currentValue: value.version,
};
break;
default:
// skip additional checks if not a known feature
continue;
}
if (!value.version) {
dep.skipReason = 'unspecified-version';
}
deps.push(dep);
continue;
}
logger.trace(
12 changes: 11 additions & 1 deletion lib/modules/manager/devcontainer/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import type { Category } from '../../../constants';
import { DockerDatasource } from '../../datasource/docker';
import { GolangVersionDatasource } from '../../datasource/golang-version';
import { NodeVersionDatasource } from '../../datasource/node-version';
import { PythonVersionDatasource } from '../../datasource/python-version';
import { RubyVersionDatasource } from '../../datasource/ruby-version';
export { extractPackageFile } from './extract';

export const name = 'Dev Container';
@@ -11,4 +15,10 @@ export const defaultConfig = {
fileMatch: ['^.devcontainer/devcontainer.json$', '^.devcontainer.json$'],
};

export const supportedDatasources = [DockerDatasource.id];
export const supportedDatasources = [
DockerDatasource.id,
GolangVersionDatasource.id,
NodeVersionDatasource.id,
PythonVersionDatasource.id,
RubyVersionDatasource.id,
];
2 changes: 2 additions & 0 deletions lib/modules/manager/devcontainer/readme.md
Original file line number Diff line number Diff line change
@@ -3,4 +3,6 @@ Extracts all Docker images from the `image` and `features` properties in these f
- `.devcontainer.json`
- `.devcontainer/devcontainer.json`

It extracts some known versions of the `features`, like `node` and `python`.

The `devcontainer` manager does _not_ support `build.dockerFile` or `dockerComposeFile` values as these are covered by the [`dockerfile`](../dockerfile/index.md) and [`docker-compose`](../docker-compose/index.md) managers respectively.
8 changes: 6 additions & 2 deletions lib/modules/manager/devcontainer/schema.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { z } from 'zod';
import { Jsonc } from '../../../util/schema-utils';
import { Jsonc, LooseRecord } from '../../../util/schema-utils';

export const DevContainerFile = Jsonc.pipe(
z.object({
image: z.string().optional(),
features: z.record(z.unknown()).optional(),
features: LooseRecord(
z.object({
version: z.string().optional(),
}),
).optional(),
}),
);

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -307,7 +307,6 @@
"@types/semver-utils": "1.1.3",
"@types/tar": "6.1.13",
"@types/tmp": "0.2.6",
"@types/unist": "2.0.11",
"@types/url-join": "4.0.3",
"@types/validate-npm-package-name": "4.0.2",
"@types/xmldoc": "1.1.9",
@@ -322,7 +321,7 @@
"eslint": "9.22.0",
"eslint-config-prettier": "10.1.1",
"eslint-formatter-gha": "1.5.2",
"eslint-import-resolver-typescript": "4.2.0",
"eslint-import-resolver-typescript": "4.2.1",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-promise": "7.2.1",
"expect-more-jest": "5.5.0",
27 changes: 12 additions & 15 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.