aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNathan Kleyn <[email protected]>2024-12-18 14:39:51 +0000
committerGitHub <[email protected]>2024-12-18 14:39:51 +0000
commitca821eb0e7a26f96d0d40971d9badece90751fdc (patch)
tree268ce017f1db738ed735a25166a53e10024e60bd
parent2342d9f7967aff33a4ac1116e1ca805927f95d60 (diff)
downloadrenovate-ca821eb0e7a26f96d0d40971d9badece90751fdc.tar.gz
renovate-ca821eb0e7a26f96d0d40971d9badece90751fdc.zip
feat(bun): Add support for updating text-format lockfile when package.json changes (#33189)39.74.0
Co-authored-by: Rhys Arkins <[email protected]>
-rw-r--r--lib/modules/manager/bun/artifacts.spec.ts315
-rw-r--r--lib/modules/manager/bun/extract.spec.ts156
-rw-r--r--lib/modules/manager/bun/extract.ts7
-rw-r--r--lib/modules/manager/bun/index.ts2
4 files changed, 322 insertions, 158 deletions
diff --git a/lib/modules/manager/bun/artifacts.spec.ts b/lib/modules/manager/bun/artifacts.spec.ts
index 75a7797a4d4..99bd3b0e734 100644
--- a/lib/modules/manager/bun/artifacts.spec.ts
+++ b/lib/modules/manager/bun/artifacts.spec.ts
@@ -41,101 +41,198 @@ describe('modules/manager/bun/artifacts', () => {
expect(await updateArtifacts(updateArtifact)).toBeNull();
});
- it('skips if cannot read lock file', async () => {
- updateArtifact.updatedDeps = [
- { manager: 'bun', lockFiles: ['bun.lockb'] },
- ];
- expect(await updateArtifacts(updateArtifact)).toBeNull();
- });
+ describe('when using .lockb lockfile format', () => {
+ it('skips if cannot read lock file', async () => {
+ updateArtifact.updatedDeps = [
+ { manager: 'bun', lockFiles: ['bun.lockb'] },
+ ];
+ expect(await updateArtifacts(updateArtifact)).toBeNull();
+ });
- it('returns null if lock content unchanged', async () => {
- updateArtifact.updatedDeps = [
- { manager: 'bun', lockFiles: ['bun.lockb'] },
- ];
- const oldLock = Buffer.from('old');
- fs.readFile.mockResolvedValueOnce(oldLock as never);
- fs.readFile.mockResolvedValueOnce(oldLock as never);
- expect(await updateArtifacts(updateArtifact)).toBeNull();
- });
+ it('returns null if lock content unchanged', async () => {
+ updateArtifact.updatedDeps = [
+ { manager: 'bun', lockFiles: ['bun.lockb'] },
+ ];
+ const oldLock = Buffer.from('old');
+ fs.readFile.mockResolvedValueOnce(oldLock as never);
+ fs.readFile.mockResolvedValueOnce(oldLock as never);
+ expect(await updateArtifacts(updateArtifact)).toBeNull();
+ });
- it('returns updated lock content', async () => {
- updateArtifact.updatedDeps = [
- { manager: 'bun', lockFiles: ['bun.lockb'] },
- ];
- const oldLock = Buffer.from('old');
- fs.readFile.mockResolvedValueOnce(oldLock as never);
- const newLock = Buffer.from('new');
- fs.readFile.mockResolvedValueOnce(newLock as never);
- expect(await updateArtifacts(updateArtifact)).toEqual([
- {
- file: {
- path: 'bun.lockb',
- type: 'addition',
- contents: newLock,
+ it('returns updated lock content', async () => {
+ updateArtifact.updatedDeps = [
+ { manager: 'bun', lockFiles: ['bun.lockb'] },
+ ];
+ const oldLock = Buffer.from('old');
+ fs.readFile.mockResolvedValueOnce(oldLock as never);
+ const newLock = Buffer.from('new');
+ fs.readFile.mockResolvedValueOnce(newLock as never);
+ expect(await updateArtifacts(updateArtifact)).toEqual([
+ {
+ file: {
+ path: 'bun.lockb',
+ type: 'addition',
+ contents: newLock,
+ },
},
- },
- ]);
- });
+ ]);
+ });
- it('supports lockFileMaintenance', async () => {
- updateArtifact.updatedDeps = [
- { manager: 'bun', lockFiles: ['bun.lockb'] },
- ];
- updateArtifact.config.updateType = 'lockFileMaintenance';
- const oldLock = Buffer.from('old');
- fs.readFile.mockResolvedValueOnce(oldLock as never);
- const newLock = Buffer.from('new');
- fs.readFile.mockResolvedValueOnce(newLock as never);
- expect(await updateArtifacts(updateArtifact)).toEqual([
- {
- file: {
- path: 'bun.lockb',
- type: 'addition',
- contents: newLock,
+ it('supports lockFileMaintenance', async () => {
+ updateArtifact.updatedDeps = [
+ { manager: 'bun', lockFiles: ['bun.lockb'] },
+ ];
+ updateArtifact.config.updateType = 'lockFileMaintenance';
+ const oldLock = Buffer.from('old');
+ fs.readFile.mockResolvedValueOnce(oldLock as never);
+ const newLock = Buffer.from('new');
+ fs.readFile.mockResolvedValueOnce(newLock as never);
+ expect(await updateArtifacts(updateArtifact)).toEqual([
+ {
+ file: {
+ path: 'bun.lockb',
+ type: 'addition',
+ contents: newLock,
+ },
},
- },
- ]);
- });
+ ]);
+ });
- it('handles temporary error', async () => {
- const execError = new ExecError(TEMPORARY_ERROR, {
- cmd: '',
- stdout: '',
- stderr: '',
- options: { encoding: 'utf8' },
+ it('handles temporary error', async () => {
+ const execError = new ExecError(TEMPORARY_ERROR, {
+ cmd: '',
+ stdout: '',
+ stderr: '',
+ options: { encoding: 'utf8' },
+ });
+ updateArtifact.updatedDeps = [
+ { manager: 'bun', lockFiles: ['bun.lockb'] },
+ ];
+ const oldLock = Buffer.from('old');
+ fs.readFile.mockResolvedValueOnce(oldLock as never);
+ exec.mockRejectedValueOnce(execError);
+ await expect(updateArtifacts(updateArtifact)).rejects.toThrow(
+ TEMPORARY_ERROR,
+ );
+ });
+
+ it('handles full error', async () => {
+ const execError = new ExecError('nope', {
+ cmd: '',
+ stdout: '',
+ stderr: '',
+ options: { encoding: 'utf8' },
+ });
+ updateArtifact.updatedDeps = [
+ { manager: 'bun', lockFiles: ['bun.lockb'] },
+ ];
+ const oldLock = Buffer.from('old');
+ fs.readFile.mockResolvedValueOnce(oldLock as never);
+ exec.mockRejectedValueOnce(execError);
+ expect(await updateArtifacts(updateArtifact)).toEqual([
+ { artifactError: { lockFile: 'bun.lockb', stderr: 'nope' } },
+ ]);
});
- updateArtifact.updatedDeps = [
- { manager: 'bun', lockFiles: ['bun.lockb'] },
- ];
- const oldLock = Buffer.from('old');
- fs.readFile.mockResolvedValueOnce(oldLock as never);
- exec.mockRejectedValueOnce(execError);
- await expect(updateArtifacts(updateArtifact)).rejects.toThrow(
- TEMPORARY_ERROR,
- );
});
- it('handles full error', async () => {
- const execError = new ExecError('nope', {
- cmd: '',
- stdout: '',
- stderr: '',
- options: { encoding: 'utf8' },
+ describe('when using .lock lockfile format', () => {
+ it('skips if cannot read lock file', async () => {
+ updateArtifact.updatedDeps = [
+ { manager: 'bun', lockFiles: ['bun.lock'] },
+ ];
+ expect(await updateArtifacts(updateArtifact)).toBeNull();
+ });
+
+ it('returns null if lock content unchanged', async () => {
+ updateArtifact.updatedDeps = [
+ { manager: 'bun', lockFiles: ['bun.lock'] },
+ ];
+ const oldLock = Buffer.from('old');
+ fs.readFile.mockResolvedValueOnce(oldLock as never);
+ fs.readFile.mockResolvedValueOnce(oldLock as never);
+ expect(await updateArtifacts(updateArtifact)).toBeNull();
+ });
+
+ it('returns updated lock content', async () => {
+ updateArtifact.updatedDeps = [
+ { manager: 'bun', lockFiles: ['bun.lock'] },
+ ];
+ const oldLock = Buffer.from('old');
+ fs.readFile.mockResolvedValueOnce(oldLock as never);
+ const newLock = Buffer.from('new');
+ fs.readFile.mockResolvedValueOnce(newLock as never);
+ expect(await updateArtifacts(updateArtifact)).toEqual([
+ {
+ file: {
+ path: 'bun.lock',
+ type: 'addition',
+ contents: newLock,
+ },
+ },
+ ]);
+ });
+
+ it('supports lockFileMaintenance', async () => {
+ updateArtifact.updatedDeps = [
+ { manager: 'bun', lockFiles: ['bun.lock'] },
+ ];
+ updateArtifact.config.updateType = 'lockFileMaintenance';
+ const oldLock = Buffer.from('old');
+ fs.readFile.mockResolvedValueOnce(oldLock as never);
+ const newLock = Buffer.from('new');
+ fs.readFile.mockResolvedValueOnce(newLock as never);
+ expect(await updateArtifacts(updateArtifact)).toEqual([
+ {
+ file: {
+ path: 'bun.lock',
+ type: 'addition',
+ contents: newLock,
+ },
+ },
+ ]);
+ });
+
+ it('handles temporary error', async () => {
+ const execError = new ExecError(TEMPORARY_ERROR, {
+ cmd: '',
+ stdout: '',
+ stderr: '',
+ options: { encoding: 'utf8' },
+ });
+ updateArtifact.updatedDeps = [
+ { manager: 'bun', lockFiles: ['bun.lock'] },
+ ];
+ const oldLock = Buffer.from('old');
+ fs.readFile.mockResolvedValueOnce(oldLock as never);
+ exec.mockRejectedValueOnce(execError);
+ await expect(updateArtifacts(updateArtifact)).rejects.toThrow(
+ TEMPORARY_ERROR,
+ );
+ });
+
+ it('handles full error', async () => {
+ const execError = new ExecError('nope', {
+ cmd: '',
+ stdout: '',
+ stderr: '',
+ options: { encoding: 'utf8' },
+ });
+ updateArtifact.updatedDeps = [
+ { manager: 'bun', lockFiles: ['bun.lock'] },
+ ];
+ const oldLock = Buffer.from('old');
+ fs.readFile.mockResolvedValueOnce(oldLock as never);
+ exec.mockRejectedValueOnce(execError);
+ expect(await updateArtifacts(updateArtifact)).toEqual([
+ { artifactError: { lockFile: 'bun.lock', stderr: 'nope' } },
+ ]);
});
- updateArtifact.updatedDeps = [
- { manager: 'bun', lockFiles: ['bun.lockb'] },
- ];
- const oldLock = Buffer.from('old');
- fs.readFile.mockResolvedValueOnce(oldLock as never);
- exec.mockRejectedValueOnce(execError);
- expect(await updateArtifacts(updateArtifact)).toEqual([
- { artifactError: { lockFile: 'bun.lockb', stderr: 'nope' } },
- ]);
});
});
describe('bun command execution', () => {
it('check install options with configs', async () => {
+ const lockfileFormats = ['bun.lockb', 'bun.lock'];
const testCases = [
{
allowScripts: undefined,
@@ -184,38 +281,40 @@ describe('modules/manager/bun/artifacts', () => {
},
];
- for (const testCase of testCases) {
- GlobalConfig.set({
- ...globalConfig,
- allowScripts: testCase.allowScripts,
- });
- const updateArtifact: UpdateArtifact = {
- config: { ignoreScripts: testCase.ignoreScripts },
- newPackageFileContent: '',
- packageFileName: '',
- updatedDeps: [{ manager: 'bun', lockFiles: ['bun.lockb'] }],
- };
+ for (const lockFile of lockfileFormats) {
+ for (const testCase of testCases) {
+ GlobalConfig.set({
+ ...globalConfig,
+ allowScripts: testCase.allowScripts,
+ });
+ const updateArtifact: UpdateArtifact = {
+ config: { ignoreScripts: testCase.ignoreScripts },
+ newPackageFileContent: '',
+ packageFileName: '',
+ updatedDeps: [{ manager: 'bun', lockFiles: [lockFile] }],
+ };
- const oldLock = Buffer.from('old');
- fs.readFile.mockResolvedValueOnce(oldLock as never);
- const newLock = Buffer.from('new');
- fs.readFile.mockResolvedValueOnce(newLock as never);
+ const oldLock = Buffer.from('old');
+ fs.readFile.mockResolvedValueOnce(oldLock as never);
+ const newLock = Buffer.from('new');
+ fs.readFile.mockResolvedValueOnce(newLock as never);
- await updateArtifacts(updateArtifact);
+ await updateArtifacts(updateArtifact);
- expect(exec).toHaveBeenCalledWith(testCase.expectedCmd, {
- cwdFile: '',
- docker: {},
- toolConstraints: [
- {
- toolName: 'bun',
- },
- ],
- userConfiguredEnv: undefined,
- });
+ expect(exec).toHaveBeenCalledWith(testCase.expectedCmd, {
+ cwdFile: '',
+ docker: {},
+ toolConstraints: [
+ {
+ toolName: 'bun',
+ },
+ ],
+ userConfiguredEnv: undefined,
+ });
- exec.mockClear();
- GlobalConfig.reset();
+ exec.mockClear();
+ GlobalConfig.reset();
+ }
}
});
});
diff --git a/lib/modules/manager/bun/extract.spec.ts b/lib/modules/manager/bun/extract.spec.ts
index 8ca869f9c3a..b5135fa3eab 100644
--- a/lib/modules/manager/bun/extract.spec.ts
+++ b/lib/modules/manager/bun/extract.spec.ts
@@ -9,60 +9,120 @@ describe('modules/manager/bun/extract', () => {
expect(await extractAllPackageFiles({}, ['package.json'])).toEqual([]);
});
- it('ignores missing package.json file', async () => {
- expect(await extractAllPackageFiles({}, ['bun.lockb'])).toEqual([]);
- });
+ describe('when using the .lockb lockfile format', () => {
+ it('ignores missing package.json file', async () => {
+ expect(await extractAllPackageFiles({}, ['bun.lockb'])).toEqual([]);
+ });
- it('ignores invalid package.json file', async () => {
- (fs.readLocalFile as jest.Mock).mockResolvedValueOnce('invalid');
- expect(await extractAllPackageFiles({}, ['bun.lockb'])).toEqual([]);
- });
+ it('ignores invalid package.json file', async () => {
+ (fs.readLocalFile as jest.Mock).mockResolvedValueOnce('invalid');
+ expect(await extractAllPackageFiles({}, ['bun.lockb'])).toEqual([]);
+ });
- it('handles null response', async () => {
- fs.getSiblingFileName.mockReturnValueOnce('package.json');
- fs.readLocalFile.mockResolvedValueOnce(
- // This package.json returns null from the extractor
- JSON.stringify({
- _id: 1,
- _args: 1,
- _from: 1,
- }),
- );
- expect(await extractAllPackageFiles({}, ['bun.lockb'])).toEqual([]);
- });
+ it('handles null response', async () => {
+ fs.getSiblingFileName.mockReturnValueOnce('package.json');
+ fs.readLocalFile.mockResolvedValueOnce(
+ // This package.json returns null from the extractor
+ JSON.stringify({
+ _id: 1,
+ _args: 1,
+ _from: 1,
+ }),
+ );
+ expect(await extractAllPackageFiles({}, ['bun.lockb'])).toEqual([]);
+ });
- it('parses valid package.json file', async () => {
- fs.getSiblingFileName.mockReturnValueOnce('package.json');
- fs.readLocalFile.mockResolvedValueOnce(
- JSON.stringify({
- name: 'test',
- version: '0.0.1',
- dependencies: {
- dep1: '1.0.0',
+ it('parses valid package.json file', async () => {
+ fs.getSiblingFileName.mockReturnValueOnce('package.json');
+ fs.readLocalFile.mockResolvedValueOnce(
+ JSON.stringify({
+ name: 'test',
+ version: '0.0.1',
+ dependencies: {
+ dep1: '1.0.0',
+ },
+ }),
+ );
+ expect(await extractAllPackageFiles({}, ['bun.lockb'])).toMatchObject([
+ {
+ deps: [
+ {
+ currentValue: '1.0.0',
+ datasource: 'npm',
+ depName: 'dep1',
+ depType: 'dependencies',
+ prettyDepType: 'dependency',
+ },
+ ],
+ extractedConstraints: {},
+ lockFiles: ['bun.lockb'],
+ managerData: {
+ hasPackageManager: false,
+ packageJsonName: 'test',
+ },
+ packageFile: 'package.json',
+ packageFileVersion: '0.0.1',
},
- }),
- );
- expect(await extractAllPackageFiles({}, ['bun.lockb'])).toMatchObject([
- {
- deps: [
- {
- currentValue: '1.0.0',
- datasource: 'npm',
- depName: 'dep1',
- depType: 'dependencies',
- prettyDepType: 'dependency',
+ ]);
+ });
+ });
+
+ describe('when using the .lock lockfile format', () => {
+ it('ignores missing package.json file', async () => {
+ expect(await extractAllPackageFiles({}, ['bun.lock'])).toEqual([]);
+ });
+
+ it('ignores invalid package.json file', async () => {
+ (fs.readLocalFile as jest.Mock).mockResolvedValueOnce('invalid');
+ expect(await extractAllPackageFiles({}, ['bun.lock'])).toEqual([]);
+ });
+
+ it('handles null response', async () => {
+ fs.getSiblingFileName.mockReturnValueOnce('package.json');
+ fs.readLocalFile.mockResolvedValueOnce(
+ // This package.json returns null from the extractor
+ JSON.stringify({
+ _id: 1,
+ _args: 1,
+ _from: 1,
+ }),
+ );
+ expect(await extractAllPackageFiles({}, ['bun.lock'])).toEqual([]);
+ });
+
+ it('parses valid package.json file', async () => {
+ fs.getSiblingFileName.mockReturnValueOnce('package.json');
+ fs.readLocalFile.mockResolvedValueOnce(
+ JSON.stringify({
+ name: 'test',
+ version: '0.0.1',
+ dependencies: {
+ dep1: '1.0.0',
+ },
+ }),
+ );
+ expect(await extractAllPackageFiles({}, ['bun.lock'])).toMatchObject([
+ {
+ deps: [
+ {
+ currentValue: '1.0.0',
+ datasource: 'npm',
+ depName: 'dep1',
+ depType: 'dependencies',
+ prettyDepType: 'dependency',
+ },
+ ],
+ extractedConstraints: {},
+ lockFiles: ['bun.lock'],
+ managerData: {
+ hasPackageManager: false,
+ packageJsonName: 'test',
},
- ],
- extractedConstraints: {},
- lockFiles: ['bun.lockb'],
- managerData: {
- hasPackageManager: false,
- packageJsonName: 'test',
+ packageFile: 'package.json',
+ packageFileVersion: '0.0.1',
},
- packageFile: 'package.json',
- packageFileVersion: '0.0.1',
- },
- ]);
+ ]);
+ });
});
});
});
diff --git a/lib/modules/manager/bun/extract.ts b/lib/modules/manager/bun/extract.ts
index 9f41b23cb9a..6a8d8e8cdb6 100644
--- a/lib/modules/manager/bun/extract.ts
+++ b/lib/modules/manager/bun/extract.ts
@@ -18,7 +18,12 @@ export async function extractAllPackageFiles(
): Promise<PackageFile[]> {
const packageFiles: PackageFile<NpmManagerData>[] = [];
for (const matchedFile of matchedFiles) {
- if (!matchesFileName(matchedFile, 'bun.lockb')) {
+ if (
+ !(
+ matchesFileName(matchedFile, 'bun.lockb') ||
+ matchesFileName(matchedFile, 'bun.lock')
+ )
+ ) {
logger.warn({ matchedFile }, 'Invalid bun lockfile match');
continue;
}
diff --git a/lib/modules/manager/bun/index.ts b/lib/modules/manager/bun/index.ts
index b3130e04b37..f885639ad89 100644
--- a/lib/modules/manager/bun/index.ts
+++ b/lib/modules/manager/bun/index.ts
@@ -13,7 +13,7 @@ export const supersedesManagers = ['npm'];
export const supportsLockFileMaintenance = true;
export const defaultConfig = {
- fileMatch: ['(^|/)bun\\.lockb$'],
+ fileMatch: ['(^|/)bun\\.lockb?$'],
digest: {
prBodyDefinitions: {
Change: