-
-
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 dependency badge for Pipenv applications [GithubPipenv] #4096
Changes from all commits
5ba2a8a
a5000b3
e79d0de
c205ad4
e851fb5
dbba874
ffe0582
fa853f7
9f8567a
f7caf7b
8732d30
af576df
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,202 @@ | ||
'use strict' | ||
|
||
const { renderVersionBadge } = require('../version') | ||
const { isLockfile, getDependencyVersion } = require('../pipenv-helpers') | ||
const { addv } = require('../text-formatters') | ||
const { ConditionalGithubAuthV3Service } = require('./github-auth-service') | ||
const { fetchJsonFromRepo } = require('./github-common-fetch') | ||
const { documentation: githubDocumentation } = require('./github-helpers') | ||
const { NotFound } = require('..') | ||
|
||
const keywords = ['pipfile'] | ||
|
||
const documentation = ` | ||
<p> | ||
<a href="https://github.com/pypa/pipenv">Pipenv</a> is a dependency | ||
manager for Python which manages a | ||
<a href="https://virtualenv.pypa.io/en/latest/">virtualenv</a> for | ||
projects. It adds/removes packages from your <code>Pipfile</code> as | ||
you install/uninstall packages and generates the ever-important | ||
<code>Pipfile.lock</code>, which can be checked in to source control | ||
in order to produce deterministic builds. | ||
</p> | ||
|
||
<p> | ||
The GitHub Pipenv badges are intended for applications using Pipenv | ||
which are hosted on GitHub. | ||
</p> | ||
|
||
<p> | ||
When <code>Pipfile.lock</code> is checked in, the <strong>GitHub Pipenv | ||
locked dependency version</strong> badge displays the locked version of | ||
a dependency listed in <code>[packages]</code> or | ||
<code>[dev-packages]</code> (or any of their transitive dependencies). | ||
</p> | ||
|
||
<p> | ||
Usually a Python version is specified in the <code>Pipfile</code>, which | ||
<code>pipenv lock</code> then places in <code>Pipfile.lock</code>. The | ||
<strong>GitHub Pipenv Python version</strong> badge displays that version. | ||
</p> | ||
|
||
${githubDocumentation} | ||
` | ||
|
||
class GithubPipenvLockedPythonVersion extends ConditionalGithubAuthV3Service { | ||
static get category() { | ||
return 'platform-support' | ||
} | ||
|
||
static get route() { | ||
return { | ||
base: 'github/pipenv/locked/python-version', | ||
pattern: ':user/:repo/:branch*', | ||
} | ||
} | ||
|
||
static get examples() { | ||
return [ | ||
{ | ||
title: 'GitHub Pipenv locked Python version', | ||
pattern: ':user/:repo', | ||
namedParams: { | ||
user: 'metabolize', | ||
repo: 'rq-dashboard-on-heroku', | ||
}, | ||
staticPreview: this.render({ version: '3.7' }), | ||
documentation, | ||
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. Will it be evident to end users (either from the I've never worked with 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 reckon it will probably be OK, but we could change from "GitHub Pipenv locked Python version" to "GitHub Pipenv Python version from Pipfile.lock" (etc) just to be super clear. 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. Yea, agreed, I approached this badge more from a developers perspective than usual and was thinking documentation would be helpful. In the long run some explanatory documentation could be useful on all our badges. 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 ended up not adding Pipfile.lock to the title, rather writing some pretty extensive docs of what the badge is for, designed for people who don't necessarily have any context. |
||
keywords, | ||
}, | ||
{ | ||
title: 'GitHub Pipenv locked Python version (branch)', | ||
pattern: ':user/:repo/:branch', | ||
namedParams: { | ||
user: 'metabolize', | ||
repo: 'rq-dashboard-on-heroku', | ||
branch: 'master', | ||
}, | ||
staticPreview: this.render({ version: '3.7', branch: 'master' }), | ||
documentation, | ||
keywords, | ||
}, | ||
] | ||
} | ||
|
||
static get defaultBadgeData() { | ||
return { | ||
label: 'python', | ||
} | ||
} | ||
|
||
static render({ version, branch }) { | ||
return renderVersionBadge({ | ||
version, | ||
tag: branch, | ||
defaultLabel: 'python', | ||
}) | ||
} | ||
|
||
async handle({ user, repo, branch }) { | ||
const { | ||
_meta: { | ||
requires: { python_version: version }, | ||
}, | ||
} = await fetchJsonFromRepo(this, { | ||
schema: isLockfile, | ||
user, | ||
repo, | ||
branch, | ||
filename: 'Pipfile.lock', | ||
}) | ||
if (version === undefined) { | ||
throw new NotFound({ prettyMessage: 'version not specified' }) | ||
} | ||
return this.constructor.render({ version, branch }) | ||
} | ||
} | ||
|
||
class GithubPipenvLockedDependencyVersion extends ConditionalGithubAuthV3Service { | ||
static get category() { | ||
return 'dependencies' | ||
} | ||
|
||
static get route() { | ||
return { | ||
base: 'github/pipenv/locked/dependency-version', | ||
pattern: ':user/:repo/:kind(dev)?/:packageName/:branch*', | ||
} | ||
} | ||
|
||
static get examples() { | ||
return [ | ||
{ | ||
title: 'GitHub Pipenv locked dependency version', | ||
pattern: ':user/:repo/:kind(dev)?/:packageName', | ||
namedParams: { | ||
user: 'metabolize', | ||
repo: 'rq-dashboard-on-heroku', | ||
packageName: 'flask', | ||
}, | ||
staticPreview: this.render({ | ||
dependency: 'flask', | ||
version: '1.1.1', | ||
}), | ||
documentation, | ||
keywords: ['python', ...keywords], | ||
}, | ||
{ | ||
title: 'GitHub Pipenv locked dependency version (branch)', | ||
pattern: ':user/:repo/:kind(dev)?/:packageName/:branch', | ||
namedParams: { | ||
user: 'metabolize', | ||
repo: 'rq-dashboard-on-heroku', | ||
kind: 'dev', | ||
packageName: 'black', | ||
branch: 'master', | ||
}, | ||
staticPreview: this.render({ dependency: 'black', version: '19.3b0' }), | ||
documentation, | ||
keywords: ['python', ...keywords], | ||
}, | ||
] | ||
} | ||
|
||
static get defaultBadgeData() { | ||
return { | ||
label: 'dependency', | ||
} | ||
} | ||
|
||
static render({ dependency, version, ref }) { | ||
return { | ||
label: dependency, | ||
message: version ? addv(version) : ref, | ||
color: 'blue', | ||
} | ||
} | ||
|
||
async handle({ user, repo, kind, branch, packageName }) { | ||
const lockfileData = await fetchJsonFromRepo(this, { | ||
schema: isLockfile, | ||
user, | ||
repo, | ||
branch, | ||
filename: 'Pipfile.lock', | ||
}) | ||
const { version, ref } = getDependencyVersion({ | ||
kind, | ||
wantedDependency: packageName, | ||
lockfileData, | ||
}) | ||
return this.constructor.render({ | ||
dependency: packageName, | ||
version, | ||
ref, | ||
}) | ||
} | ||
} | ||
|
||
module.exports = [ | ||
GithubPipenvLockedPythonVersion, | ||
GithubPipenvLockedDependencyVersion, | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
'use strict' | ||
|
||
const Joi = require('@hapi/joi') | ||
const { ServiceTester } = require('../tester') | ||
const { | ||
isVPlusDottedVersionAtLeastOne, | ||
isVPlusDottedVersionNClausesWithOptionalSuffix, | ||
} = require('../test-validators') | ||
|
||
// e.g. v19.3b0 | ||
const isBlackVersion = Joi.string().regex(/^v\d+(\.\d+)*(.*)?$/) | ||
const isShortSha = Joi.string().regex(/[0-9a-f]{7}/) | ||
|
||
const t = (module.exports = new ServiceTester({ | ||
id: 'GithubPipenv', | ||
title: 'GithubPipenv', | ||
pathPrefix: '/github/pipenv', | ||
})) | ||
|
||
t.create('Locked Python version') | ||
.get('/locked/python-version/metabolize/rq-dashboard-on-heroku.json') | ||
.expectBadge({ | ||
label: 'python', | ||
message: isVPlusDottedVersionAtLeastOne, | ||
}) | ||
|
||
t.create('Locked Python version (no pipfile.lock)') | ||
.get('/locked/python-version/metabolize/react-flexbox-svg.json') | ||
.expectBadge({ | ||
label: 'python', | ||
message: 'repo not found, branch not found, or Pipfile.lock missing', | ||
}) | ||
|
||
t.create('Locked Python version (pipfile.lock has no python version)') | ||
.get('/locked/python-version/fikovnik/ShiftIt.json') | ||
.expectBadge({ | ||
label: 'python', | ||
message: 'version not specified', | ||
}) | ||
|
||
t.create('Locked version of default dependency') | ||
.get( | ||
'/locked/dependency-version/metabolize/rq-dashboard-on-heroku/rq-dashboard.json' | ||
) | ||
.expectBadge({ | ||
label: 'rq-dashboard', | ||
message: isVPlusDottedVersionNClausesWithOptionalSuffix, | ||
}) | ||
|
||
t.create('Locked version of default dependency (branch)') | ||
.get( | ||
'/locked/dependency-version/metabolize/rq-dashboard-on-heroku/rq-dashboard/master.json' | ||
) | ||
.expectBadge({ | ||
label: 'rq-dashboard', | ||
message: isVPlusDottedVersionNClausesWithOptionalSuffix, | ||
}) | ||
|
||
t.create('Locked version of dev dependency') | ||
.get( | ||
'/locked/dependency-version/metabolize/rq-dashboard-on-heroku/dev/black.json' | ||
) | ||
.expectBadge({ | ||
label: 'black', | ||
message: isBlackVersion, | ||
}) | ||
|
||
t.create('Locked version of dev dependency (branch)') | ||
.get( | ||
'/locked/dependency-version/metabolize/rq-dashboard-on-heroku/dev/black/master.json' | ||
) | ||
.expectBadge({ | ||
label: 'black', | ||
message: isBlackVersion, | ||
}) | ||
|
||
t.create('Locked version of unknown dependency') | ||
.get( | ||
'/locked/dependency-version/metabolize/rq-dashboard-on-heroku/dev/i-made-this-up.json' | ||
) | ||
.expectBadge({ | ||
label: 'dependency', | ||
message: 'dev dependency not found', | ||
}) | ||
|
||
t.create('Locked version of VCS dependency') | ||
.get( | ||
'/locked/dependency-version/DemocracyClub/aggregator-api/dc-base-theme.json' | ||
) | ||
.expectBadge({ | ||
label: 'dc-base-theme', | ||
message: isShortSha, | ||
}) |
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 hadn't realized that
Pipfile
is TOML butPipfile.lock
is JSON, so I unnecessarily refactored this. However it'd help with #3960 and #4068 (comment) so seems worth keeping.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.
Nice!