diff --git a/lib/datasource/api.ts b/lib/datasource/api.ts index 8cf870242519c5399b91a5d7bdb4f81494108453..cdcc24f13bb13cdb7ed5a5604675600993767122 100644 --- a/lib/datasource/api.ts +++ b/lib/datasource/api.ts @@ -24,7 +24,7 @@ import * as packagist from './packagist'; import * as pod from './pod'; import * as pypi from './pypi'; import * as repology from './repology'; -import * as rubyVersion from './ruby-version'; +import { RubyVersionDatasource } from './ruby-version'; import * as rubygems from './rubygems'; import * as sbtPackage from './sbt-package'; import * as sbtPlugin from './sbt-plugin'; @@ -61,7 +61,7 @@ api.set('packagist', packagist); api.set('pod', pod); api.set('pypi', pypi); api.set('repology', repology); -api.set('ruby-version', rubyVersion); +api.set('ruby-version', new RubyVersionDatasource()); api.set('rubygems', rubygems); api.set('sbt-package', sbtPackage); api.set('sbt-plugin', sbtPlugin); diff --git a/lib/datasource/ruby-version/index.spec.ts b/lib/datasource/ruby-version/index.spec.ts index 3efbd83d385eef60c8e986c089573f8b133ff21b..a4e94ce0b57941b8e00c854c5f9f8db263d06d11 100644 --- a/lib/datasource/ruby-version/index.spec.ts +++ b/lib/datasource/ruby-version/index.spec.ts @@ -1,10 +1,12 @@ import { getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; import { getName, loadFixture } from '../../../test/util'; -import { id as datasource } from '.'; +import { RubyVersionDatasource } from '.'; const rubyReleasesHtml = loadFixture('releases.html'); +const datasource = RubyVersionDatasource.id; + describe(getName(), () => { describe('getReleases', () => { it('parses real data', async () => { diff --git a/lib/datasource/ruby-version/index.ts b/lib/datasource/ruby-version/index.ts index f225b9fbca9bec49d792fabf2e0b507704742f83..9019d63c882ad0f560cdfcd53b481969c0c49aa2 100644 --- a/lib/datasource/ruby-version/index.ts +++ b/lib/datasource/ruby-version/index.ts @@ -1,58 +1,63 @@ import { ExternalHostError } from '../../types/errors/external-host-error'; -import * as packageCache from '../../util/cache/package'; +import { cache } from '../../util/cache/package/decorator'; import { parse } from '../../util/html'; -import { Http } from '../../util/http'; +import { HttpError } from '../../util/http/types'; import { isVersion, id as rubyVersioningId } from '../../versioning/ruby'; +import { Datasource } from '../datasource'; import type { GetReleasesConfig, ReleaseResult } from '../types'; -export const id = 'ruby-version'; -export const defaultRegistryUrls = ['https://www.ruby-lang.org/']; -export const customRegistrySupport = false; -export const defaultVersioning = rubyVersioningId; - -const http = new Http(id); - -export async function getReleases({ - registryUrl, -}: GetReleasesConfig): Promise<ReleaseResult | null> { - // First check the persistent cache - const cacheNamespace = 'datasource-ruby-version'; - const cachedResult = await packageCache.get<ReleaseResult>( - cacheNamespace, - 'all' - ); - // istanbul ignore if - if (cachedResult) { - return cachedResult; +export class RubyVersionDatasource extends Datasource { + static readonly id = 'ruby-version'; + + constructor() { + super(RubyVersionDatasource.id); } - try { + + readonly defaultRegistryUrls = ['https://www.ruby-lang.org/']; + + readonly customRegistrySupport = false; + + readonly defaultVersioning = rubyVersioningId; + + @cache({ namespace: `datasource-${RubyVersionDatasource.id}`, key: 'all' }) + async getReleases({ + registryUrl, + }: GetReleasesConfig): Promise<ReleaseResult | null> { const res: ReleaseResult = { homepage: 'https://www.ruby-lang.org', sourceUrl: 'https://github.com/ruby/ruby', releases: [], }; const rubyVersionsUrl = `${registryUrl}en/downloads/releases/`; - const response = await http.get(rubyVersionsUrl); - const root = parse(response.body); - const rows = root.querySelector('.release-list').querySelectorAll('tr'); - rows.forEach((row) => { - const tds = row.querySelectorAll('td'); - const columns: string[] = []; - tds.forEach((td) => columns.push(td.innerHTML)); - if (columns.length) { - const version = columns[0].replace('Ruby ', ''); - if (isVersion(version)) { - const releaseTimestamp = columns[1]; - const changelogUrl = columns[2] - .replace('<a href="', 'https://www.ruby-lang.org') - .replace('">more...</a>', ''); - res.releases.push({ version, releaseTimestamp, changelogUrl }); + try { + const response = await this.http.get(rubyVersionsUrl); + + const root = parse(response.body); + const rows = root.querySelector('.release-list').querySelectorAll('tr'); + rows.forEach((row) => { + const tds = row.querySelectorAll('td'); + const columns: string[] = []; + tds.forEach((td) => columns.push(td.innerHTML)); + if (columns.length) { + const version = columns[0].replace('Ruby ', ''); + if (isVersion(version)) { + const releaseTimestamp = columns[1]; + const changelogUrl = columns[2] + .replace('<a href="', 'https://www.ruby-lang.org') + .replace('">more...</a>', ''); + res.releases.push({ version, releaseTimestamp, changelogUrl }); + } } - } - }); - await packageCache.set(cacheNamespace, 'all', res, 15); + }); + } catch (err) { + this.handleGenericErrors(err); + } + return res; - } catch (err) { + } + + // eslint-disable-next-line class-methods-use-this + override handleSpecificErrors(err: HttpError): never | void { throw new ExternalHostError(err); } } diff --git a/lib/manager/ruby-version/extract.ts b/lib/manager/ruby-version/extract.ts index 57621bce2f2e16a7891d3f1d231bfca3420579b0..b71b58660ca41d24166219eef48a291067dcb2ae 100644 --- a/lib/manager/ruby-version/extract.ts +++ b/lib/manager/ruby-version/extract.ts @@ -1,4 +1,4 @@ -import * as datasourceRubyVersion from '../../datasource/ruby-version'; +import { RubyVersionDatasource } from '../../datasource/ruby-version'; import { logger } from '../../logger'; import type { PackageDependency, PackageFile } from '../types'; @@ -7,7 +7,7 @@ export function extractPackageFile(content: string): PackageFile { const dep: PackageDependency = { depName: 'ruby', currentValue: content.trim(), - datasource: datasourceRubyVersion.id, + datasource: RubyVersionDatasource.id, }; return { deps: [dep] }; }