diff --git a/doc/rewriting-services.md b/doc/rewriting-services.md index aa78113332..54c256a34e 100644 --- a/doc/rewriting-services.md +++ b/doc/rewriting-services.md @@ -89,10 +89,7 @@ tests are passing, though. the route using a `pattern`. A `pattern` (e.g. `pattern: ':param1/:param2'`) is the simplest way to declare the route, also the most readable, and will be useful for displaying a badge builder with fields in the front end and - generating badge URLs programmatically. One limitation to keep in mind is that, - at present, the trailing parameter of a pattern can't be optional. If the last - part of a route is optional, like a branch, you will need to use a `format` - regex string (e.g. `format: '([^/]+/[^/]+)'`). + generating badge URLs programmatically. 3. When creating the initial route, you can stub out the service. A minimal service extends BaseJsonService (or BaseService, or one of the others), and @@ -264,13 +261,7 @@ In either case, the service should throw e.g ## Convert the examples -1. Convert all the examples to `pattern`, `namedParams`, and - `staticPreview`. In some cases you can use the `pattern` inherited - from `route`, though in other cases you may need to specify a pattern - in the example. For example, when showing download badges for several - periods, you may want to render the example with an explicit `dt` - instead of `:which`. You will also need to specify a pattern for badges - that use a `format` regex in the route. +1. Convert all the examples to `pattern`, `namedParams`, and `staticExample`. In some cases you can use the `pattern` inherited from `route`, though in other cases you may need to specify a pattern in the example. For example, when showing download badges for several periods, you may want to render the example with an explicit `dt` instead of `:which`. You will also need to specify a pattern for badges that use a `format` regex in the route. 2. Open the frontend and check that the static preview badges look good. Remember, none of them are live. diff --git a/package-lock.json b/package-lock.json index 906b4380f1..6066bddc07 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12280,9 +12280,8 @@ "dev": true }, "path-to-regexp": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.4.0.tgz", - "integrity": "sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w==" + "version": "github:pillarjs/path-to-regexp#a33e7b7a5225ff7d301961a89439e9874674cbfa", + "from": "github:pillarjs/path-to-regexp#a33e7b7a5225ff7d301961a89439e9874674cbfa" }, "path-type": { "version": "2.0.0", diff --git a/package.json b/package.json index 21967277e8..da6f360a76 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "lodash.times": "^4.3.2", "moment": "^2.23.0", "node-env-flag": "^0.1.0", - "path-to-regexp": "^2.4.0", + "path-to-regexp": "pillarjs/path-to-regexp#a33e7b7a5225ff7d301961a89439e9874674cbfa", "pretty-bytes": "^5.0.0", "priorityqueuejs": "^1.0.0", "prom-client": "^11.2.1", diff --git a/services/appveyor/appveyor-base.js b/services/appveyor/appveyor-base.js index 4899a4ffdd..e7a82a628e 100644 --- a/services/appveyor/appveyor-base.js +++ b/services/appveyor/appveyor-base.js @@ -22,8 +22,8 @@ module.exports = class AppVeyorBase extends BaseJsonService { return 'build' } - async fetch({ repo, branch }) { - let url = `https://ci.appveyor.com/api/projects/${repo}` + async fetch({ user, repo, branch }) { + let url = `https://ci.appveyor.com/api/projects/${user}/${repo}` if (branch != null) { url += `/branch/${branch}` } @@ -37,8 +37,7 @@ module.exports = class AppVeyorBase extends BaseJsonService { static buildRoute(base) { return { base, - format: '([^/]+/[^/]+)(?:/(.+))?', - capture: ['repo', 'branch'], + pattern: ':user/:repo/:branch*', } } } diff --git a/services/appveyor/appveyor-ci.service.js b/services/appveyor/appveyor-ci.service.js index 5ebd4b57a3..b712a8da73 100644 --- a/services/appveyor/appveyor-ci.service.js +++ b/services/appveyor/appveyor-ci.service.js @@ -38,8 +38,8 @@ module.exports = class AppVeyorCi extends AppVeyorBase { } } - async handle({ repo, branch }) { - const data = await this.fetch({ repo, branch }) + async handle({ user, repo, branch }) { + const data = await this.fetch({ user, repo, branch }) if (!data.hasOwnProperty('build')) { // this project exists but no builds have been run on it yet return this.constructor.render({ status: 'no builds found' }) diff --git a/services/appveyor/appveyor-tests.service.js b/services/appveyor/appveyor-tests.service.js index ec387d695c..c3816e3dca 100644 --- a/services/appveyor/appveyor-tests.service.js +++ b/services/appveyor/appveyor-tests.service.js @@ -92,7 +92,7 @@ module.exports = class AppVeyorTests extends AppVeyorBase { } async handle( - { repo, branch }, + { user, repo, branch }, { compact_message: compactMessage, passed_label: passedLabel, @@ -101,7 +101,7 @@ module.exports = class AppVeyorTests extends AppVeyorBase { } ) { const isCompact = compactMessage !== undefined - const data = await this.fetch({ repo, branch }) + const data = await this.fetch({ user, repo, branch }) if (!data.hasOwnProperty('build')) { return { message: 'no builds found' } diff --git a/services/azure-devops/azure-devops-coverage.service.js b/services/azure-devops/azure-devops-coverage.service.js index d28528f28e..bec3dc0547 100644 --- a/services/azure-devops/azure-devops-coverage.service.js +++ b/services/azure-devops/azure-devops-coverage.service.js @@ -79,7 +79,7 @@ module.exports = class AzureDevOpsCoverage extends AzureDevOpsBase { }, { title: 'Azure DevOps coverage (branch)', - pattern: ':organization/:project/:definitionId/:branch', + pattern: ':organization/:project/:definitionId/:branch*', namedParams: { organization: 'swellaby', project: 'opensource', @@ -96,8 +96,7 @@ module.exports = class AzureDevOpsCoverage extends AzureDevOpsBase { static get route() { return { base: 'azure-devops/coverage', - format: '([^/]+)/([^/]+)/([^/]+)(?:/(.+))?', - capture: ['organization', 'project', 'definitionId', 'branch'], + pattern: ':organization/:project/:definitionId/:branch*', } } diff --git a/services/azure-devops/azure-devops-tests.service.js b/services/azure-devops/azure-devops-tests.service.js index ed0b5a21f8..13c0866b9d 100644 --- a/services/azure-devops/azure-devops-tests.service.js +++ b/services/azure-devops/azure-devops-tests.service.js @@ -108,7 +108,7 @@ module.exports = class AzureDevOpsTests extends AzureDevOpsBase { }, { title: 'Azure DevOps tests (branch)', - pattern: ':organization/:project/:definitionId/:branch', + pattern: ':organization/:project/:definitionId/:branch*', namedParams: { organization: 'azuredevops-powershell', project: 'azuredevops-powershell', @@ -176,8 +176,7 @@ module.exports = class AzureDevOpsTests extends AzureDevOpsBase { static get route() { return { base: 'azure-devops/tests', - format: '([^/]+)/([^/]+)/([^/]+)(?:/(.+))?', - capture: ['organization', 'project', 'definitionId', 'branch'], + pattern: ':organization/:project/:definitionId/:branch*', queryParams: [ 'compact_message', 'passed_label', diff --git a/services/date/date.service.js b/services/date/date.service.js index 45ff62b22e..333254fa6c 100644 --- a/services/date/date.service.js +++ b/services/date/date.service.js @@ -35,8 +35,7 @@ module.exports = class Date extends BaseService { static get route() { return { base: 'date', - format: '([0-9]+)', - capture: ['timestamp'], + pattern: ':timestamp([0-9]+)', } } diff --git a/services/github/github-manifest.service.js b/services/github/github-manifest.service.js index 5a617e8a77..3d4e518dc5 100644 --- a/services/github/github-manifest.service.js +++ b/services/github/github-manifest.service.js @@ -25,8 +25,7 @@ class GithubManifestVersion extends ConditionalGithubAuthService { static get route() { return { base: 'github/manifest-json/v', - format: '([^/]+)/([^/]+)/?([^/]+)?', - capture: ['user', 'repo', 'branch'], + pattern: ':user/:repo/:branch*', } } @@ -44,7 +43,7 @@ class GithubManifestVersion extends ConditionalGithubAuthService { }, { title: 'GitHub manifest version', - pattern: ':user/:repo/:branch', + pattern: ':user/:repo/:branch*', namedParams: { user: 'RedSparr0w', repo: 'IndieGala-Helper', diff --git a/services/github/github-package-json.service.js b/services/github/github-package-json.service.js index a91e9b2e7f..87ad2276c5 100644 --- a/services/github/github-package-json.service.js +++ b/services/github/github-package-json.service.js @@ -23,8 +23,7 @@ class GithubPackageJsonVersion extends ConditionalGithubAuthService { static get route() { return { base: 'github/package-json/v', - format: '([^/]+)/([^/]+)/?([^/]+)?', - capture: ['user', 'repo', 'branch'], + pattern: ':user/:repo/:branch*', } } @@ -38,8 +37,8 @@ class GithubPackageJsonVersion extends ConditionalGithubAuthService { documentation, }, { - title: 'GitHub package.json version', - pattern: ':user/:repo/:branch', + title: 'GitHub package.json version (branch)', + pattern: ':user/:repo/:branch*', namedParams: { user: 'IcedFrisby', repo: 'IcedFrisby', @@ -102,7 +101,7 @@ class DynamicGithubPackageJson extends ConditionalGithubAuthService { }, { title: 'GitHub package.json dynamic', - pattern: ':key/:user/:repo/:branch', + pattern: ':key/:user/:repo/:branch*', namedParams: { key: 'keywords', user: 'developit', diff --git a/services/gitlab/gitlab-pipeline-status.service.js b/services/gitlab/gitlab-pipeline-status.service.js index f9d812b17a..7212e14f84 100644 --- a/services/gitlab/gitlab-pipeline-status.service.js +++ b/services/gitlab/gitlab-pipeline-status.service.js @@ -24,11 +24,7 @@ module.exports = class GitlabPipelineStatus extends BaseSvgScrapingService { static get route() { return { base: 'gitlab/pipeline', - format: '([^/]+)/([^/]+)(?:/([^/]+))?', - capture: ['user', 'repo', 'branch'], - // Trailing optional parameters don't work. The issue relates to the `.` - // separator before the extension. - // pattern: ':user/:repo/:branch?', + pattern: ':user/:repo/:branch*', queryParams: ['gitlab_url'], } } @@ -43,7 +39,7 @@ module.exports = class GitlabPipelineStatus extends BaseSvgScrapingService { }, { title: 'Gitlab pipeline status (branch)', - pattern: ':user/:repo/:branch', + pattern: ':user/:repo/:branch*', namedParams: { user: 'gitlab-org', repo: 'gitlab-ce', diff --git a/services/jenkins/jenkins-plugin-installs.service.js b/services/jenkins/jenkins-plugin-installs.service.js index 2f20c945b6..ccf6137bfb 100644 --- a/services/jenkins/jenkins-plugin-installs.service.js +++ b/services/jenkins/jenkins-plugin-installs.service.js @@ -98,8 +98,7 @@ class JenkinsPluginInstalls extends BaseJsonService { static get route() { return { base: 'jenkins/plugin/i', - format: '([^/]+)/?([^/]+)?', - capture: ['plugin', 'version'], + pattern: ':plugin/:version?', } } @@ -117,7 +116,7 @@ class JenkinsPluginInstalls extends BaseJsonService { }), }, { - title: 'Jenkins Plugin installs', + title: 'Jenkins Plugin installs (version)', pattern: ':plugin/:version', namedParams: { plugin: 'view-job-filters', diff --git a/services/matrix/matrix.service.js b/services/matrix/matrix.service.js index c494431711..00745a5090 100644 --- a/services/matrix/matrix.service.js +++ b/services/matrix/matrix.service.js @@ -191,8 +191,7 @@ module.exports = class Matrix extends BaseJsonService { static get route() { return { base: 'matrix', - format: '([^/]+)', - capture: ['roomAlias'], + pattern: ':roomAlias', queryParams: ['server_fqdn'], } } diff --git a/services/npm/npm-base.js b/services/npm/npm-base.js index ac19ad6583..af016a2782 100644 --- a/services/npm/npm-base.js +++ b/services/npm/npm-base.js @@ -49,9 +49,7 @@ module.exports = class NpmBase extends BaseJsonService { if (withTag) { return { base, - // The trailing optional means this has to be a regex. - format: '(?:(@[^/]+)/)?([^/]*)/?([^/]*)', - capture: ['scope', 'packageName', 'tag'], + pattern: ':scope(@[^/]+)?/:packageName/:tag?', queryParams: ['registry_uri'], } } else { diff --git a/services/readthedocs/readthedocs.service.js b/services/readthedocs/readthedocs.service.js index 451123fdc9..3952f16503 100644 --- a/services/readthedocs/readthedocs.service.js +++ b/services/readthedocs/readthedocs.service.js @@ -18,8 +18,7 @@ module.exports = class ReadTheDocs extends BaseSvgScrapingService { static get route() { return { base: 'readthedocs', - format: '([^/]+)(?:/(.+))?', - capture: ['project', 'version'], + pattern: ':project/:version?', } } diff --git a/services/requires/requires.service.js b/services/requires/requires.service.js index 0394f41150..2983ac63ac 100644 --- a/services/requires/requires.service.js +++ b/services/requires/requires.service.js @@ -11,8 +11,7 @@ module.exports = class RequiresIo extends BaseJsonService { static get route() { return { base: 'requires', - format: '([^/]+)/([^/]+/[^/]+)(?:/(.+))?', - capture: ['service', 'repo', 'branch'], + pattern: ':service/:user/:repo/:branch*', } } @@ -20,13 +19,13 @@ module.exports = class RequiresIo extends BaseJsonService { return { label: 'requirements' } } - async handle({ service, repo, branch }) { - const { status } = await this.fetch({ service, repo, branch }) + async handle({ service, user, repo, branch }) { + const { status } = await this.fetch({ service, user, repo, branch }) return this.constructor.render({ status }) } - async fetch({ service, repo, branch }) { - const url = `https://requires.io/api/v1/status/${service}/${repo}` + async fetch({ service, user, repo, branch }) { + const url = `https://requires.io/api/v1/status/${service}/${user}/${repo}` return this._requestJson({ url, schema: statusSchema, diff --git a/services/shippable/shippable.service.js b/services/shippable/shippable.service.js index bb1470d4ee..fe77b9c315 100644 --- a/services/shippable/shippable.service.js +++ b/services/shippable/shippable.service.js @@ -46,8 +46,7 @@ module.exports = class Shippable extends BaseJsonService { static get route() { return { base: 'shippable', - format: '([^/]+)(?:/(.+))?', - capture: ['projectId', 'branch'], + pattern: ':projectId/:branch*', } } diff --git a/services/snyk/snyk-vulnerability-github.service.js b/services/snyk/snyk-vulnerability-github.service.js index 7abb04ca8a..878584ae7f 100644 --- a/services/snyk/snyk-vulnerability-github.service.js +++ b/services/snyk/snyk-vulnerability-github.service.js @@ -6,8 +6,7 @@ module.exports = class SnykVulnerabilityGitHub extends SynkVulnerabilityBase { static get route() { return { base: 'snyk/vulnerabilities/github', - format: '([^/]+)/([^/]+)(?:/(.+))?', - capture: ['user', 'repo', 'manifestFilePath'], + pattern: ':user/:repo/:manifestFilePath*', } } diff --git a/services/wordpress/wordpress-downloads.service.js b/services/wordpress/wordpress-downloads.service.js index 3708662703..89bbc7db93 100644 --- a/services/wordpress/wordpress-downloads.service.js +++ b/services/wordpress/wordpress-downloads.service.js @@ -89,8 +89,7 @@ function InstallsForExtensionType(extensionType) { static get route() { return { base: `wordpress/${extensionType}/installs`, - format: '(.+)', - capture: ['slug'], + pattern: ':slug', } } @@ -98,7 +97,6 @@ function InstallsForExtensionType(extensionType) { return [ { title: `Wordpress ${capt} Active Installs`, - pattern: ':slug', namedParams: { slug: exampleSlug }, staticPreview: this.render({ response: { active_installs: 300000 } }), }, @@ -143,8 +141,7 @@ function DownloadsForInterval(interval) { static get route() { return { base, - format: '(.*)', - capture: ['slug'], + pattern: ':slug', } } @@ -152,7 +149,6 @@ function DownloadsForInterval(interval) { return [ { title: 'WordPress Plugin Downloads', - pattern: ':slug', namedParams: { slug: 'bbpress' }, staticPreview: this.render({ downloads: 30000 }), }, diff --git a/services/wordpress/wordpress-platform.service.js b/services/wordpress/wordpress-platform.service.js index 59a104f6c2..3e1efe412c 100644 --- a/services/wordpress/wordpress-platform.service.js +++ b/services/wordpress/wordpress-platform.service.js @@ -114,8 +114,7 @@ class WordpressPluginTestedVersion extends BaseWordpressPlatform { static get route() { return { base: `wordpress/plugin/tested`, - format: '(.+)', - capture: ['slug'], + pattern: ':slug', } } @@ -136,8 +135,7 @@ class WordpressPluginTestedVersionAlias extends WordpressPluginTestedVersion { static get route() { return { base: `wordpress/v`, - format: '(.+)', - capture: ['slug'], + pattern: ':slug', } }