-
-
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
add [WingetVersion] Badge #10245
base: master
Are you sure you want to change the base?
add [WingetVersion] Badge #10245
Changes from 3 commits
7a22dbc
f71b6b8
d387631
d9963b5
6b70732
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 |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import Joi from 'joi' | ||
import gql from 'graphql-tag' | ||
import { latest, renderVersionBadge } from '../version.js' | ||
import { InvalidParameter, pathParam } from '../index.js' | ||
import { GithubAuthV4Service } from '../github/github-auth-service.js' | ||
import { transformErrors } from '../github/github-helpers.js' | ||
|
||
const schema = Joi.object({ | ||
data: Joi.object({ | ||
repository: Joi.object({ | ||
object: Joi.object({ | ||
entries: Joi.array().items( | ||
Joi.object({ | ||
type: Joi.string().required(), | ||
name: Joi.string().required(), | ||
}), | ||
), | ||
}) | ||
.allow(null) | ||
.required(), | ||
}).required(), | ||
}).required(), | ||
}).required() | ||
|
||
export default class WingetVersion extends GithubAuthV4Service { | ||
static category = 'version' | ||
|
||
static route = { | ||
base: 'winget/v', | ||
pattern: ':name', | ||
} | ||
|
||
static openApi = { | ||
'/winget/v/{name}': { | ||
get: { | ||
summary: 'WinGet Package Version', | ||
description: 'WinGet Community Repository', | ||
parameters: [ | ||
pathParam({ | ||
name: 'name', | ||
example: 'Microsoft.WSL', | ||
}), | ||
], | ||
}, | ||
}, | ||
} | ||
|
||
static defaultBadgeData = { | ||
label: 'winget', | ||
} | ||
|
||
async fetch({ name }) { | ||
const nameFirstLower = name[0].toLowerCase() | ||
const nameSlashed = name.replaceAll('.', '/') | ||
const path = `manifests/${nameFirstLower}/${nameSlashed}` | ||
const expression = `HEAD:${path}` | ||
return this._requestGraphql({ | ||
query: gql` | ||
query RepoFiles($expression: String!) { | ||
repository(owner: "microsoft", name: "winget-pkgs") { | ||
object(expression: $expression) { | ||
... on Tree { | ||
entries { | ||
type | ||
name | ||
} | ||
} | ||
} | ||
} | ||
} | ||
`, | ||
variables: { expression }, | ||
schema, | ||
transformErrors, | ||
}) | ||
} | ||
|
||
async handle({ name }) { | ||
try { | ||
const json = await this.fetch({ name }) | ||
if (json.data.repository.object === null) { | ||
throw new InvalidParameter({ | ||
prettyMessage: 'package not found', | ||
}) | ||
} | ||
const entries = json.data.repository.object.entries | ||
const directories = entries.filter(file => file.type === 'tree') | ||
const versions = directories.map(file => file.name) | ||
const version = latest(versions) | ||
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. Is there any way we could find out what the registry considers the "latest" version of a package? Do we have any info on how WinGet sorts versions? I'm a bit worried that there doesn't really seem to be any constraint on what a version "number" can be. Here's some examples that have one or more odd ones:
Given it seems a version number can be basically any string, it seems like this we are going to get this wrong in some cases. 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. Sorry for late response. I will investigate the update process in winget database 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. I could noy find meaningful source code of winget-pkgs pipeline but I found version comparesion in winget-cli, that are used when one package is provided by multiple multiple sources. I don't know if this compression is used by winget-pkgs pipeline and may not work well with some if your example packages but I think it's reasonable to use this comparesion. I will implement this compression in services/winget folder with unit tests. Version Implementation: https://github.com/microsoft/winget-cli/blob/ae566c7bf21cfcc75be7ec30e4036a30eede8396/src/AppInstallerSharedLib/Versions.cpp Use case in winget-cli: https://github.com/microsoft/winget-cli/blob/ae566c7bf21cfcc75be7ec30e4036a30eede8396/src/AppInstallerRepositoryCore/PackageVersionSelection.cpp#L82-L100 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. I have implemented in 6b70732 |
||
|
||
return renderVersionBadge({ version }) | ||
} catch (e) { | ||
anatawa12 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
console.log(e) | ||
throw e | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { isVPlusDottedVersionNClauses } from '../test-validators.js' | ||
import { createServiceTester } from '../tester.js' | ||
|
||
export const t = await createServiceTester() | ||
|
||
// basic test | ||
t.create('gets the package version of WSL') | ||
.get('/Microsoft.WSL.json') | ||
.expectBadge({ label: 'winget', message: isVPlusDottedVersionNClauses }) | ||
|
||
// test more than one dots | ||
t.create('gets the package version of .NET 8') | ||
.get('/Microsoft.DotNet.SDK.8.json') | ||
.expectBadge({ label: 'winget', message: isVPlusDottedVersionNClauses }) | ||
|
||
// test sort based on dotted version order instead of ASCII | ||
t.create('gets the latest version') | ||
.intercept(nock => | ||
nock('https://api.github.com/') | ||
.post('/graphql') | ||
.reply(200, { | ||
data: { | ||
repository: { | ||
object: { | ||
entries: [ | ||
{ | ||
type: 'tree', | ||
name: '0.1001.389.0', | ||
}, | ||
{ | ||
type: 'tree', | ||
name: '0.1101.416.0', | ||
}, | ||
{ | ||
type: 'tree', | ||
name: '0.1201.442.0', | ||
}, | ||
{ | ||
type: 'tree', | ||
name: '0.137.141.0', | ||
}, | ||
{ | ||
type: 'tree', | ||
name: '0.200.170.0', | ||
}, | ||
{ | ||
type: 'tree', | ||
name: '0.503.261.0', | ||
}, | ||
{ | ||
type: 'tree', | ||
name: '0.601.285.0', | ||
}, | ||
{ | ||
type: 'tree', | ||
name: '0.601.297.0', | ||
}, | ||
{ | ||
type: 'tree', | ||
name: '0.701.323.0', | ||
}, | ||
{ | ||
type: 'tree', | ||
name: '0.801.344.0', | ||
}, | ||
], | ||
}, | ||
}, | ||
}, | ||
}), | ||
) | ||
.get('/Microsoft.DevHome.json') | ||
.expectBadge({ label: 'winget', message: 'v0.1201.442.0' }) |
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.
👍