Skip to content
Snippets Groups Projects
Unverified Commit bf6ac7d7 authored by Sergei Zharinov's avatar Sergei Zharinov Committed by GitHub
Browse files

fix(packagist): De-minify fields (#19863)

parent 142bebc1
No related branches found
No related tags found
No related merge requests found
...@@ -2,13 +2,74 @@ import type { ReleaseResult } from '../types'; ...@@ -2,13 +2,74 @@ import type { ReleaseResult } from '../types';
import { import {
ComposerRelease, ComposerRelease,
ComposerReleases, ComposerReleases,
MinifiedArray,
parsePackagesResponse, parsePackagesResponse,
parsePackagesResponses, parsePackagesResponses,
} from './schema'; } from './schema';
describe('modules/datasource/packagist/schema', () => { describe('modules/datasource/packagist/schema', () => {
describe('MinifiedArray', () => {
it('parses MinifiedArray', () => {
expect(MinifiedArray.parse([])).toEqual([]);
// Source: https://github.com/composer/metadata-minifier/blob/1.0.0/tests/MetadataMinifierTest.php
expect(
MinifiedArray.parse([
{
name: 'foo/bar',
version: '2.0.0',
version_normalized: '2.0.0.0',
type: 'library',
scripts: {
foo: 'bar',
},
license: ['MIT'],
},
{
version: '1.2.0',
version_normalized: '1.2.0.0',
license: ['GPL'],
homepage: 'https://example.org',
scripts: '__unset',
},
{
version: '1.0.0',
version_normalized: '1.0.0.0',
homepage: '__unset',
},
])
).toEqual([
{
name: 'foo/bar',
version: '2.0.0',
version_normalized: '2.0.0.0',
type: 'library',
scripts: {
foo: 'bar',
},
license: ['MIT'],
},
{
name: 'foo/bar',
version: '1.2.0',
version_normalized: '1.2.0.0',
type: 'library',
license: ['GPL'],
homepage: 'https://example.org',
},
{
name: 'foo/bar',
version: '1.0.0',
version_normalized: '1.0.0.0',
type: 'library',
license: ['GPL'],
},
]);
});
});
describe('ComposerRelease', () => { describe('ComposerRelease', () => {
it('rejects', () => { it('rejects ComposerRelease', () => {
expect(() => ComposerRelease.parse(null)).toThrow(); expect(() => ComposerRelease.parse(null)).toThrow();
expect(() => ComposerRelease.parse(undefined)).toThrow(); expect(() => ComposerRelease.parse(undefined)).toThrow();
expect(() => ComposerRelease.parse('')).toThrow(); expect(() => ComposerRelease.parse('')).toThrow();
...@@ -17,7 +78,7 @@ describe('modules/datasource/packagist/schema', () => { ...@@ -17,7 +78,7 @@ describe('modules/datasource/packagist/schema', () => {
expect(() => ComposerRelease.parse({ version: null })).toThrow(); expect(() => ComposerRelease.parse({ version: null })).toThrow();
}); });
it('parses', () => { it('parses ComposerRelease', () => {
expect(ComposerRelease.parse({ version: '' })).toEqual({ version: '' }); expect(ComposerRelease.parse({ version: '' })).toEqual({ version: '' });
expect(ComposerRelease.parse({ version: 'dev-main' })).toEqual({ expect(ComposerRelease.parse({ version: 'dev-main' })).toEqual({
version: 'dev-main', version: 'dev-main',
...@@ -50,14 +111,14 @@ describe('modules/datasource/packagist/schema', () => { ...@@ -50,14 +111,14 @@ describe('modules/datasource/packagist/schema', () => {
}); });
describe('ComposerReleases', () => { describe('ComposerReleases', () => {
it('rejects', () => { it('rejects ComposerReleases', () => {
expect(() => ComposerReleases.parse(null)).toThrow(); expect(() => ComposerReleases.parse(null)).toThrow();
expect(() => ComposerReleases.parse(undefined)).toThrow(); expect(() => ComposerReleases.parse(undefined)).toThrow();
expect(() => ComposerReleases.parse('')).toThrow(); expect(() => ComposerReleases.parse('')).toThrow();
expect(() => ComposerReleases.parse({})).toThrow(); expect(() => ComposerReleases.parse({})).toThrow();
}); });
it('parses', () => { it('parses ComposerReleases', () => {
expect(ComposerReleases.parse([])).toEqual([]); expect(ComposerReleases.parse([])).toEqual([]);
expect(ComposerReleases.parse([null])).toEqual([]); expect(ComposerReleases.parse([null])).toEqual([]);
expect(ComposerReleases.parse([1, 2, 3])).toEqual([]); expect(ComposerReleases.parse([1, 2, 3])).toEqual([]);
...@@ -69,7 +130,7 @@ describe('modules/datasource/packagist/schema', () => { ...@@ -69,7 +130,7 @@ describe('modules/datasource/packagist/schema', () => {
}); });
describe('parsePackageResponse', () => { describe('parsePackageResponse', () => {
it('parses', () => { it('parses package response', () => {
expect(parsePackagesResponse('foo/bar', null)).toEqual([]); expect(parsePackagesResponse('foo/bar', null)).toEqual([]);
expect(parsePackagesResponse('foo/bar', {})).toEqual([]); expect(parsePackagesResponse('foo/bar', {})).toEqual([]);
expect(parsePackagesResponse('foo/bar', { packages: '123' })).toEqual([]); expect(parsePackagesResponse('foo/bar', { packages: '123' })).toEqual([]);
...@@ -86,7 +147,7 @@ describe('modules/datasource/packagist/schema', () => { ...@@ -86,7 +147,7 @@ describe('modules/datasource/packagist/schema', () => {
}); });
describe('parsePackagesResponses', () => { describe('parsePackagesResponses', () => {
it('parses', () => { it('parses array of responses', () => {
expect(parsePackagesResponses('foo/bar', [null])).toBeNull(); expect(parsePackagesResponses('foo/bar', [null])).toBeNull();
expect(parsePackagesResponses('foo/bar', [{}])).toBeNull(); expect(parsePackagesResponses('foo/bar', [{}])).toBeNull();
expect( expect(
......
import is from '@sindresorhus/is';
import { z } from 'zod'; import { z } from 'zod';
import { logger } from '../../../logger'; import { logger } from '../../../logger';
import type { Release, ReleaseResult } from '../types'; import type { Release, ReleaseResult } from '../types';
export const MinifiedArray = z.array(z.record(z.unknown())).transform((xs) => {
// Ported from: https://github.com/composer/metadata-minifier/blob/main/src/MetadataMinifier.php#L17
if (xs.length === 0) {
return xs;
}
const prevVals: Record<string, unknown> = {};
for (const x of xs) {
for (const key of Object.keys(x)) {
prevVals[key] ??= undefined;
}
for (const key of Object.keys(prevVals)) {
const val = x[key];
if (val === '__unset') {
delete x[key];
prevVals[key] = undefined;
continue;
}
if (!is.undefined(val)) {
prevVals[key] = val;
continue;
}
if (!is.undefined(prevVals[key])) {
x[key] = prevVals[key];
continue;
}
}
}
return xs;
});
export type MinifiedArray = z.infer<typeof MinifiedArray>;
export const ComposerRelease = z export const ComposerRelease = z
.object({ .object({
version: z.string(), version: z.string(),
...@@ -37,7 +74,8 @@ export function parsePackagesResponse( ...@@ -37,7 +74,8 @@ export function parsePackagesResponse(
): ComposerReleases { ): ComposerReleases {
try { try {
const { packages } = ComposerPackagesResponse.parse(packagesResponse); const { packages } = ComposerPackagesResponse.parse(packagesResponse);
const releases = ComposerReleases.parse(packages[packageName]); const array = MinifiedArray.parse(packages[packageName]);
const releases = ComposerReleases.parse(array);
return releases; return releases;
} catch (err) { } catch (err) {
logger.debug( logger.debug(
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment