From 0009ecdc5c7040814981eefaf82454a44df5faa0 Mon Sep 17 00:00:00 2001 From: ccoVeille <3875889+ccoVeille@users.noreply.github.com> Date: Thu, 21 Nov 2024 23:11:05 +0100 Subject: [PATCH] provide a non-repository scoped version of [githubcodesearch] and redirect /search/user/repo/q to /search?query=q%20repo:user/repo --- services/github/github-search.service.js | 64 +++++++++++++++--------- services/github/github-search.tester.js | 17 +++++-- 2 files changed, 53 insertions(+), 28 deletions(-) diff --git a/services/github/github-search.service.js b/services/github/github-search.service.js index ea10fddd14708..8d89cada76fd9 100644 --- a/services/github/github-search.service.js +++ b/services/github/github-search.service.js @@ -1,5 +1,5 @@ import Joi from 'joi' -import { pathParams } from '../index.js' +import { queryParams, redirector } from '../index.js' import { metric } from '../text-formatters.js' import { nonNegativeInteger } from '../validators.js' import { GithubAuthV3Service } from './github-auth-service.js' @@ -7,33 +7,35 @@ import { documentation } from './github-helpers.js' const schema = Joi.object({ total_count: nonNegativeInteger }).required() -export default class GithubSearch extends GithubAuthV3Service { +const queryParamSchema = Joi.object({ + query: Joi.string().required(), +}).required() + +const codeSearchDocs = ` +For a full list of available filters and allowed values, +see GitHub's documentation on +[Searching code](https://docs.github.com/en/search-github/github-code-search/understanding-github-code-search-syntax)` + +class GitHubCodeSearch extends GithubAuthV3Service { static category = 'analysis' static route = { - base: 'github/search', - pattern: ':user/:repo/:query+', + base: 'github', + pattern: 'search', + queryParamSchema, } static openApi = { - '/github/search/{user}/{repo}/{query}': { + '/github/search': { get: { - summary: 'GitHub search hit counter', + summary: 'GitHub code search count', description: documentation, - parameters: pathParams( - { - name: 'user', - example: 'torvalds', - }, - { - name: 'repo', - example: 'linux', - }, - { - name: 'query', - example: 'goto', - }, - ), + parameters: queryParams({ + name: 'query', + description: codeSearchDocs, + example: 'goto language:javascript NOT is:fork NOT is:archived', + required: true, + }), }, }, } @@ -50,21 +52,35 @@ export default class GithubSearch extends GithubAuthV3Service { } } - async handle({ user, repo, query }) { + async handle(_routeParams, { query }) { const { total_count: totalCount } = await this._requestJson({ url: '/search/code', options: { searchParams: { - q: `${query} repo:${user}/${repo}`, + q: query, }, }, schema, httpErrors: { 401: 'auth required for search api', - 404: 'repo not found', - 422: 'repo not found', }, }) + return this.constructor.render({ query, totalCount }) } } + +const GitHubCodeSearchRedirect = redirector({ + category: 'analysis', + route: { + base: 'github/search', + pattern: ':user/:repo/:query+', + }, + transformPath: () => '/github/search', + transformQueryParams: ({ query, user, repo }) => ({ + query: `${query} repo:${user}/${repo}`, + }), + dateAdded: new Date('2024-11-29'), +}) + +export { GitHubCodeSearch, GitHubCodeSearchRedirect } diff --git a/services/github/github-search.tester.js b/services/github/github-search.tester.js index a220560a63d6b..060eb4766ea39 100644 --- a/services/github/github-search.tester.js +++ b/services/github/github-search.tester.js @@ -3,9 +3,18 @@ import { createServiceTester } from '../tester.js' export const t = await createServiceTester() t.create('hit counter') - .get('/badges/shields/async%20handle.json') + .get('/search.json?query=async%20handle') .expectBadge({ label: 'async handle counter', message: isMetric }) -t.create('hit counter for nonexistent repo') - .get('/badges/puppets/async%20handle.json') - .expectBadge({ label: 'async handle counter', message: '0' }) +t.create('hit counter, zero results') + .get('/search.json?query=async%20handle%20repo%3Abadges%2Fpuppets') + .expectBadge({ + label: 'async handle repo:badges/puppets counter', + message: '0', + }) + +t.create('legacy redirect') + .get('/search/badges/shields/async%20handle.svg') + .expectRedirect( + '/github/search.svg?query=async%20handle%20repo%3Abadges%2Fshields', + )