-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Packagist] Update Packagist service to use v2 api #6508
Changes from 4 commits
0993750
83935ed
ffaa723
c8692bc
4d3c20b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,12 +10,10 @@ const { | |
customServerDocumentationFragment, | ||
} = require('./packagist-base') | ||
|
||
const packageSchema = Joi.object() | ||
.pattern( | ||
/^/, | ||
const packageSchema = Joi.array() | ||
.items( | ||
Joi.object({ | ||
'default-branch': Joi.bool(), | ||
license: Joi.array().required(), | ||
license: Joi.array(), | ||
}).required() | ||
) | ||
.required() | ||
|
@@ -59,17 +57,22 @@ module.exports = class PackagistLicense extends BasePackagistService { | |
} | ||
|
||
transform({ json, user, repo }) { | ||
const branch = this.getDefaultBranch(json, user, repo) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can delete |
||
if (!branch) { | ||
throw new NotFound({ prettyMessage: 'default branch not found' }) | ||
const packageName = this.getPackageName(user, repo) | ||
|
||
const license = json.packages[packageName][0].license | ||
|
||
if (!license) { | ||
throw new NotFound({ prettyMessage: 'license not found' }) | ||
} | ||
const { license } = branch | ||
|
||
return { license } | ||
} | ||
|
||
async handle({ user, repo }, { server }) { | ||
const json = await this.fetch({ user, repo, schema, server }) | ||
|
||
const { license } = this.transform({ json, user, repo }) | ||
|
||
return renderLicenseBadge({ license }) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,20 +7,20 @@ const PackagistPhpVersion = require('./packagist-php-version.service') | |
describe('PackagistPhpVersion', function () { | ||
const json = { | ||
packages: { | ||
'frodo/the-one-package': { | ||
'1.0.0': { require: { php: '^5.6 || ^7' } }, | ||
'2.0.0': { require: { php: '^7.2' } }, | ||
'3.0.0': { require: { php: '^7.4 || 8' } }, | ||
'dev-main': { require: { php: '^8' }, 'default-branch': true }, | ||
}, | ||
'samwise/gardening': { | ||
'1.0.x-dev': {}, | ||
'2.0.x-dev': {}, | ||
}, | ||
'pippin/mischief': { | ||
'1.0.0': {}, | ||
'dev-main': { require: {}, 'default-branch': true }, | ||
}, | ||
Comment on lines
-11
to
-23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it typically concerns me when we have to modify tests as part of some other change. I realize that some updates are inevitable here since the new api has a different response structure, but I feel like there's more going on or at least that I'm missing some context (though I presume this is all branch related) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change is solely because of the change in response structure as seen in the diff. |
||
'frodo/the-one-package': [ | ||
{ | ||
version: '3.0.0', | ||
require: { php: '^7.4 || 8' }, | ||
}, | ||
{ | ||
version: '2.0.0', | ||
require: { php: '^7.2' }, | ||
}, | ||
{ | ||
version: '1.0.0', | ||
require: { php: '^5.6 || ^7' }, | ||
}, | ||
], | ||
}, | ||
} | ||
|
||
|
@@ -37,44 +37,66 @@ describe('PackagistPhpVersion', function () { | |
.with.property('prettyMessage', 'invalid version') | ||
}) | ||
|
||
it('should throw NotFound when version not specified and no default branch found', function () { | ||
expect(() => | ||
PackagistPhpVersion.prototype.transform({ | ||
json, | ||
user: 'samwise', | ||
repo: 'gardening', | ||
}) | ||
) | ||
.to.throw(NotFound) | ||
.with.property('prettyMessage', 'invalid version') | ||
}) | ||
|
||
it('should throw NotFound when PHP version not found on package when using default branch', function () { | ||
it('should throw NotFound when PHP version not found on package when using default release', function () { | ||
const specJson = { | ||
packages: { | ||
'frodo/the-one-package': [ | ||
{ | ||
version: '3.0.0', | ||
}, | ||
{ | ||
version: '2.0.0', | ||
require: { php: '^7.2' }, | ||
}, | ||
{ | ||
version: '1.0.0', | ||
require: { php: '^5.6 || ^7' }, | ||
}, | ||
], | ||
}, | ||
} | ||
expect(() => | ||
PackagistPhpVersion.prototype.transform({ | ||
json, | ||
user: 'pippin', | ||
repo: 'mischief', | ||
json: specJson, | ||
user: 'frodo', | ||
repo: 'the-one-package', | ||
}) | ||
) | ||
.to.throw(NotFound) | ||
.with.property('prettyMessage', 'version requirement not found') | ||
}) | ||
|
||
it('should throw NotFound when PHP version not found on package when using specified version', function () { | ||
it('should throw NotFound when PHP version not found on package when using specified release', function () { | ||
const specJson = { | ||
packages: { | ||
'frodo/the-one-package': [ | ||
{ | ||
version: '3.0.0', | ||
require: { php: '^7.4 || 8' }, | ||
}, | ||
{ | ||
version: '2.0.0', | ||
require: { php: '^7.2' }, | ||
}, | ||
{ | ||
version: '1.0.0', | ||
}, | ||
], | ||
}, | ||
} | ||
expect(() => | ||
PackagistPhpVersion.prototype.transform({ | ||
json, | ||
user: 'pippin', | ||
repo: 'mischief', | ||
json: specJson, | ||
user: 'frodo', | ||
repo: 'the-one-package', | ||
version: '1.0.0', | ||
}) | ||
) | ||
.to.throw(NotFound) | ||
.with.property('prettyMessage', 'version requirement not found') | ||
}) | ||
|
||
it('should return PHP version for the default branch', function () { | ||
it('should return PHP version for the default release', function () { | ||
expect( | ||
PackagistPhpVersion.prototype.transform({ | ||
json, | ||
|
@@ -83,19 +105,19 @@ describe('PackagistPhpVersion', function () { | |
}) | ||
) | ||
.to.have.property('phpVersion') | ||
.that.equals('^8') | ||
.that.equals('^7.4 || 8') | ||
}) | ||
|
||
it('should return PHP version for the specified branch', function () { | ||
it('should return PHP version for the specified release', function () { | ||
expect( | ||
PackagistPhpVersion.prototype.transform({ | ||
json, | ||
user: 'frodo', | ||
repo: 'the-one-package', | ||
version: '3.0.0', | ||
version: '2.0.0', | ||
}) | ||
) | ||
.to.have.property('phpVersion') | ||
.that.equals('^7.4 || 8') | ||
.that.equals('^7.2') | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,17 +12,12 @@ const { | |
customServerDocumentationFragment, | ||
} = require('./packagist-base') | ||
|
||
const packageSchema = Joi.object() | ||
.pattern( | ||
/^/, | ||
Joi.object({ | ||
version: Joi.string(), | ||
extra: Joi.object({ | ||
'branch-alias': Joi.object().pattern(/^/, Joi.string()), | ||
}), | ||
}).required() | ||
) | ||
.required() | ||
const packageSchema = Joi.array().items( | ||
Joi.object({ | ||
version: Joi.string(), | ||
extra: Joi.any(), | ||
}) | ||
) | ||
|
||
const schema = Joi.object({ | ||
packages: Joi.object().pattern(/^/, packageSchema).required(), | ||
|
@@ -90,25 +85,27 @@ class PackagistVersion extends BasePackagistService { | |
|
||
transform({ includePrereleases, json, user, repo }) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As noted on const packageSchema = Joi.array().items(
Joi.object({version: Joi.string().required()})
)
transform({ includePrereleases, json, user, repo }) {
const versionsData = json.packages[this.getPackageName(user, repo)]
const versions = versionsData.map( version => version.version)
if (includePrereleases) {
return { version: latest(versions) }
} else {
const stableVersion = latest(versions.filter(isStable))
return { version: stableVersion || latest(versions) }
}
} Then at that point, the logic for identifying the latest release is the same logic as in your There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Packagist do not have separate tagged version on different branch. Even the main branch is considered a development branch. The
Sometimes the tagged pre-release versions (e.g. v0.1.2) of libraries are published and used in production by others. In which case, the latest version would be "not stable" but is not shown on the |
||
const versionsData = json.packages[this.getPackageName(user, repo)] | ||
let versions = Object.keys(versionsData) | ||
|
||
let versions = [] | ||
const aliasesMap = {} | ||
versions.forEach(version => { | ||
const versionData = versionsData[version] | ||
if ( | ||
versionData.extra && | ||
versionData.extra['branch-alias'] && | ||
versionData.extra['branch-alias'][version] | ||
) { | ||
|
||
versionsData.forEach(version => { | ||
if (version.extra && version.extra['branch-alias']) { | ||
// eg, version is 'dev-master', mapped to '2.0.x-dev'. | ||
const validVersion = versionData.extra['branch-alias'][version] | ||
const validVersion = | ||
version.extra['branch-alias'][ | ||
Object.keys(version.extra['branch-alias']) | ||
] | ||
if ( | ||
aliasesMap[validVersion] === undefined || | ||
compare(aliasesMap[validVersion], validVersion) < 0 | ||
) { | ||
versions.push(validVersion) | ||
aliasesMap[validVersion] = version | ||
aliasesMap[validVersion] = version.version | ||
} | ||
} | ||
|
||
versions.push(version.version) | ||
}) | ||
|
||
versions = versions.filter(version => !/^dev-/.test(version)) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a need to drop
.required()
here? Is this because the new schema may not always define the key? If that's the case then I think in the transform function we need to account for that fact and throw a not found/invalid response errorThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new api endpoint now only returns the license array with the first item in the response (most recent release). At least that's what I've found in my testing. because of this, the schema validation would fail when the response contains more than 1 version. I do think that throwing a not found error would be good just in case there isn't a license at all for some reason. I'll add that in shortly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think ideally you would run the
MetadataMinifier::expand
logic on the response before validating the schema, and then you can restore therequired()
I'd say. Note that packagist.org does not enforce the presence of a license key, so it may well be missing if the package author did not include it. I'd not expect they'd display a shields.io license badge if they haven't defined a license though but who knows :)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Seldaek i thought about that too but I don’t think it would be possible with the way Shields makes a request since it’s shared with other services. Maybe with some sort of event hook system but that seems like overkill for this one situation.