From 347c2d02d73d4e7d1e02310af39e9769e4715450 Mon Sep 17 00:00:00 2001 From: Malte Hviid-Magnussen Date: Tue, 9 May 2023 11:47:31 +0200 Subject: [PATCH 01/74] docs(gitlab): add hostType to registry hostRules guide (#22055) --- lib/modules/platform/gitlab/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/modules/platform/gitlab/index.md b/lib/modules/platform/gitlab/index.md index a4b6c25f42710f..31ab87bd630469 100644 --- a/lib/modules/platform/gitlab/index.md +++ b/lib/modules/platform/gitlab/index.md @@ -29,7 +29,7 @@ Remember to set `platform=gitlab` somewhere in your Renovate config file. If you're using a private [GitLab container registry](https://docs.gitlab.com/ee/user/packages/container_registry/), you must: -- Set the `RENOVATE_HOST_RULES` CI variable to `[{"matchHost": "${CI_REGISTRY}","username": "${GITLAB_USER_NAME}","password": "${RENOVATE_TOKEN}"}]`. +- Set the `RENOVATE_HOST_RULES` CI variable to `[{"matchHost": "${CI_REGISTRY}","username": "${GITLAB_USER_NAME}","password": "${RENOVATE_TOKEN}", "hostType": "docker"}]`. - Make sure the user that owns the `RENOVATE_TOKEN` PAT is a member of the corresponding GitLab projects/groups with the right permissions. - Make sure the `RENOVATE_TOKEN` PAT has the `read_registry` scope. From f63f3647ec03e004179e3a8847b65b68ac1c1090 Mon Sep 17 00:00:00 2001 From: Michael Kriese Date: Tue, 9 May 2023 11:50:37 +0200 Subject: [PATCH 02/74] test(manager/terraform): refactor some tests (#22039) --- lib/modules/manager/terraform/extract.spec.ts | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/lib/modules/manager/terraform/extract.spec.ts b/lib/modules/manager/terraform/extract.spec.ts index cbdea0323c7c01..62d7b53f00a3dd 100644 --- a/lib/modules/manager/terraform/extract.spec.ts +++ b/lib/modules/manager/terraform/extract.spec.ts @@ -404,15 +404,14 @@ describe('modules/manager/terraform/extract', () => { const res = await extractPackageFile(docker, 'docker.tf', {}); expect(res?.deps).toHaveLength(6); expect(res?.deps.filter((dep) => dep.skipReason)).toHaveLength(3); - expect(res?.deps).toIncludeAllPartialMembers([ + expect(res?.deps).toMatchObject([ { autoReplaceStringTemplate: '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', - currentValue: '1.7.8', datasource: 'docker', - depName: 'nginx', depType: 'docker_image', - replaceString: 'nginx:1.7.8', + replaceString: '${data.docker_registry_image.ubuntu.name}', + skipReason: 'contains-variable', }, { depType: 'docker_image', @@ -421,10 +420,11 @@ describe('modules/manager/terraform/extract', () => { { autoReplaceStringTemplate: '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentValue: '1.7.8', datasource: 'docker', + depName: 'nginx', depType: 'docker_image', - replaceString: '${data.docker_registry_image.ubuntu.name}', - skipReason: 'contains-variable', + replaceString: 'nginx:1.7.8', }, { autoReplaceStringTemplate: @@ -577,26 +577,7 @@ describe('modules/manager/terraform/extract', () => { const res = await extractPackageFile(helm, 'helm.tf', {}); expect(res?.deps).toHaveLength(8); expect(res?.deps.filter((dep) => dep.skipReason)).toHaveLength(2); - expect(res?.deps).toIncludeAllPartialMembers([ - { - currentValue: '1.0.1', - datasource: 'helm', - depName: 'redis', - depType: 'helm_release', - registryUrls: ['https://charts.helm.sh/stable'], - }, - { - datasource: 'helm', - depName: 'redis', - depType: 'helm_release', - registryUrls: ['https://charts.helm.sh/stable'], - }, - { - datasource: 'helm', - depName: './charts/example', - depType: 'helm_release', - skipReason: 'local-chart', - }, + expect(res?.deps).toMatchObject([ { currentValue: '4.0.1', datasource: 'helm', @@ -630,6 +611,25 @@ describe('modules/manager/terraform/extract', () => { depType: 'helm_release', packageName: 'public.ecr.aws/karpenter/karpenter', }, + { + datasource: 'helm', + depName: './charts/example', + depType: 'helm_release', + skipReason: 'local-chart', + }, + { + currentValue: '1.0.1', + datasource: 'helm', + depName: 'redis', + depType: 'helm_release', + registryUrls: ['https://charts.helm.sh/stable'], + }, + { + datasource: 'helm', + depName: 'redis', + depType: 'helm_release', + registryUrls: ['https://charts.helm.sh/stable'], + }, ]); }); From 004b383bd061df48521b1028d845841d3a757e6e Mon Sep 17 00:00:00 2001 From: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> Date: Tue, 9 May 2023 12:50:25 +0200 Subject: [PATCH 03/74] chore: add GitHub Actions VS Code extension (#21350) Co-authored-by: Sebastian Poxhofer --- .devcontainer/devcontainer.json | 3 ++- .vscode/extensions.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index ff52204e6e3a68..6daf80c6940f4a 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -19,7 +19,8 @@ "dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "orta.vscode-jest", - "EditorConfig.editorconfig" + "editorconfig.editorconfig", + "github.vscode-github-actions" ] } }, diff --git a/.vscode/extensions.json b/.vscode/extensions.json index e569c62d68ba77..a45d022d1c1ebc 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -3,6 +3,7 @@ "dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "orta.vscode-jest", - "EditorConfig.editorconfig" + "editorconfig.editorconfig", + "github.vscode-github-actions" ] } From 3f33995ab92ff0cf188ea407e7cef3b58fea869c Mon Sep 17 00:00:00 2001 From: Michael Kriese Date: Tue, 9 May 2023 17:26:00 +0200 Subject: [PATCH 04/74] feat(manager/terraform): support registry aliases for docker images and oci helm charts (#22022) Co-authored-by: Sebastian Poxhofer --- docs/usage/configuration-options.md | 1 + lib/modules/manager/dockerfile/extract.ts | 2 +- .../manager/terraform/__fixtures__/docker.tf | 4 ++ .../manager/terraform/__fixtures__/helm.tf | 8 ++++ lib/modules/manager/terraform/base.ts | 5 ++- lib/modules/manager/terraform/extract.spec.ts | 28 +++++++++++-- lib/modules/manager/terraform/extract.ts | 2 +- .../generic-docker-image-ref.spec.ts | 2 +- .../resources/generic-docker-image-ref.ts | 22 ++++++---- .../extractors/resources/helm-release.spec.ts | 2 +- .../extractors/resources/helm-release.ts | 40 ++++++++++++++----- 11 files changed, 89 insertions(+), 27 deletions(-) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 6b01f12bebe36b..d18d6dd44335e8 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -3140,6 +3140,7 @@ This feature works with the following managers: - [`kubernetes`](/modules/manager/kubernetes) - [`ansible`](/modules/manager/ansible) - [`droneci`](/modules/manager/droneci) +- [`terraform`](/modules/manager/terraform) ## registryUrls diff --git a/lib/modules/manager/dockerfile/extract.ts b/lib/modules/manager/dockerfile/extract.ts index 45a6fc56cf4e51..f62f281bf28198 100644 --- a/lib/modules/manager/dockerfile/extract.ts +++ b/lib/modules/manager/dockerfile/extract.ts @@ -182,7 +182,7 @@ export function getDep( ...getDep(`${value}/${groups.depName}`), replaceString: currentFrom, }; - dep.autoReplaceStringTemplate = getAutoReplaceTemplate(dep)!; + dep.autoReplaceStringTemplate = getAutoReplaceTemplate(dep); return dep; } } diff --git a/lib/modules/manager/terraform/__fixtures__/docker.tf b/lib/modules/manager/terraform/__fixtures__/docker.tf index de04d0cd91d607..4490a11bff41ea 100644 --- a/lib/modules/manager/terraform/__fixtures__/docker.tf +++ b/lib/modules/manager/terraform/__fixtures__/docker.tf @@ -12,6 +12,10 @@ resource "docker_image" "ignore_variable" { pull_triggers = ["${data.docker_registry_image.ubuntu.sha256_digest}"] } +resource "docker_image" "proxy" { + name = "hub.proxy.test/bitnami/nginx:1.24.0" +} + # docker_container resources # https://registry.terraform.io/providers/kreuzwerker/docker/latest/docs/resources/container diff --git a/lib/modules/manager/terraform/__fixtures__/helm.tf b/lib/modules/manager/terraform/__fixtures__/helm.tf index 6cae1674acbcaf..bef91bd3c646a3 100644 --- a/lib/modules/manager/terraform/__fixtures__/helm.tf +++ b/lib/modules/manager/terraform/__fixtures__/helm.tf @@ -53,3 +53,11 @@ resource "helm_release" "karpenter_oci_repo" { chart = "karpenter" version = "v0.22.1" } + +## chart in OCI registry +resource "helm_release" "proxy_oci_repo" { + name = "kube-prometheus" + repository = "oci://hub.proxy.test/bitnamicharts" + chart = "kube-prometheus" + version = "8.9.1" +} diff --git a/lib/modules/manager/terraform/base.ts b/lib/modules/manager/terraform/base.ts index 274052535b94aa..4947f14f8ddb8d 100644 --- a/lib/modules/manager/terraform/base.ts +++ b/lib/modules/manager/terraform/base.ts @@ -1,7 +1,7 @@ import is from '@sindresorhus/is'; import { regEx } from '../../../util/regex'; import { TerraformProviderDatasource } from '../../datasource/terraform-provider'; -import type { PackageDependency } from '../types'; +import type { ExtractConfig, PackageDependency } from '../types'; import type { TerraformDefinitionFile } from './hcl/types'; import type { ProviderLock } from './lockfile/types'; import { getLockedVersion, massageProviderLookupName } from './util'; @@ -20,7 +20,8 @@ export abstract class DependencyExtractor { */ abstract extract( hclRoot: TerraformDefinitionFile, - locks: ProviderLock[] + locks: ProviderLock[], + config: ExtractConfig ): PackageDependency[]; } diff --git a/lib/modules/manager/terraform/extract.spec.ts b/lib/modules/manager/terraform/extract.spec.ts index 62d7b53f00a3dd..c4e8246a9adc16 100644 --- a/lib/modules/manager/terraform/extract.spec.ts +++ b/lib/modules/manager/terraform/extract.spec.ts @@ -401,8 +401,10 @@ describe('modules/manager/terraform/extract', () => { }); it('extracts docker resources', async () => { - const res = await extractPackageFile(docker, 'docker.tf', {}); - expect(res?.deps).toHaveLength(6); + const res = await extractPackageFile(docker, 'docker.tf', { + registryAliases: { 'hub.proxy.test': 'index.docker.io' }, + }); + expect(res?.deps).toHaveLength(7); expect(res?.deps.filter((dep) => dep.skipReason)).toHaveLength(3); expect(res?.deps).toMatchObject([ { @@ -426,6 +428,15 @@ describe('modules/manager/terraform/extract', () => { depType: 'docker_image', replaceString: 'nginx:1.7.8', }, + { + autoReplaceStringTemplate: + 'hub.proxy.test/bitnami/nginx:{{#if newValue}}{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentValue: '1.24.0', + datasource: 'docker', + depName: 'index.docker.io/bitnami/nginx', + depType: 'docker_image', + replaceString: 'hub.proxy.test/bitnami/nginx:1.24.0', + }, { autoReplaceStringTemplate: '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', @@ -574,8 +585,10 @@ describe('modules/manager/terraform/extract', () => { }); it('extract helm releases', async () => { - const res = await extractPackageFile(helm, 'helm.tf', {}); - expect(res?.deps).toHaveLength(8); + const res = await extractPackageFile(helm, 'helm.tf', { + registryAliases: { 'hub.proxy.test': 'index.docker.io' }, + }); + expect(res?.deps).toHaveLength(9); expect(res?.deps.filter((dep) => dep.skipReason)).toHaveLength(2); expect(res?.deps).toMatchObject([ { @@ -617,6 +630,13 @@ describe('modules/manager/terraform/extract', () => { depType: 'helm_release', skipReason: 'local-chart', }, + { + currentValue: '8.9.1', + datasource: 'docker', + depName: 'kube-prometheus', + depType: 'helm_release', + packageName: 'index.docker.io/bitnamicharts/kube-prometheus', + }, { currentValue: '1.0.1', datasource: 'helm', diff --git a/lib/modules/manager/terraform/extract.ts b/lib/modules/manager/terraform/extract.ts index e15cc17af3d58b..ef6ac343891362 100644 --- a/lib/modules/manager/terraform/extract.ts +++ b/lib/modules/manager/terraform/extract.ts @@ -46,7 +46,7 @@ export async function extractPackageFile( const locks = await extractLocksForPackageFile(fileName); for (const extractor of passedExtractors) { - const deps = extractor.extract(hclMap, locks); + const deps = extractor.extract(hclMap, locks, config); dependencies.push(...deps); } diff --git a/lib/modules/manager/terraform/extractors/resources/generic-docker-image-ref.spec.ts b/lib/modules/manager/terraform/extractors/resources/generic-docker-image-ref.spec.ts index dc8e78c5e1f8a8..6d48a30c6a27d2 100644 --- a/lib/modules/manager/terraform/extractors/resources/generic-docker-image-ref.spec.ts +++ b/lib/modules/manager/terraform/extractors/resources/generic-docker-image-ref.spec.ts @@ -4,7 +4,7 @@ describe('modules/manager/terraform/extractors/resources/generic-docker-image-re const extractor = new GenericDockerImageRefExtractor(); it('return empty array if no resource is found', () => { - const res = extractor.extract({}); + const res = extractor.extract({}, [], {}); expect(res).toBeArrayOfSize(0); }); }); diff --git a/lib/modules/manager/terraform/extractors/resources/generic-docker-image-ref.ts b/lib/modules/manager/terraform/extractors/resources/generic-docker-image-ref.ts index eb3f4c97d92628..7e89f12fd8200e 100644 --- a/lib/modules/manager/terraform/extractors/resources/generic-docker-image-ref.ts +++ b/lib/modules/manager/terraform/extractors/resources/generic-docker-image-ref.ts @@ -1,8 +1,9 @@ import is from '@sindresorhus/is'; import { getDep } from '../../../dockerfile/extract'; -import type { PackageDependency } from '../../../types'; +import type { ExtractConfig, PackageDependency } from '../../../types'; import { DependencyExtractor } from '../../base'; import type { TerraformDefinitionFile } from '../../hcl/types'; +import type { ProviderLock } from '../../lockfile/types'; import { generic_image_resource } from './utils'; export class GenericDockerImageRefExtractor extends DependencyExtractor { @@ -10,7 +11,11 @@ export class GenericDockerImageRefExtractor extends DependencyExtractor { return generic_image_resource.map((value) => `"${value.type}"`); } - extract(hclMap: TerraformDefinitionFile): PackageDependency[] { + extract( + hclMap: TerraformDefinitionFile, + _locks: ProviderLock[], + config: ExtractConfig + ): PackageDependency[] { const resourceTypMap = hclMap.resource; if (is.nullOrUndefined(resourceTypMap)) { return []; @@ -28,7 +33,9 @@ export class GenericDockerImageRefExtractor extends DependencyExtractor { // loop over instances of a resource type for (const instance of Object.values(resourceInstancesMap).flat()) { - dependencies.push(...this.walkPath({ depType: type }, instance, path)); + dependencies.push( + ...this.walkPath({ depType: type }, instance, path, config) + ); } } return dependencies; @@ -45,7 +52,8 @@ export class GenericDockerImageRefExtractor extends DependencyExtractor { private walkPath( abstractDep: PackageDependency, parentElement: unknown, - leftPath: string[] + leftPath: string[], + config: ExtractConfig ): PackageDependency[] { const dependencies: PackageDependency[] = []; // if there are no path elements left, we have reached the end of the path @@ -59,7 +67,7 @@ export class GenericDockerImageRefExtractor extends DependencyExtractor { }, ]; } - const test = getDep(parentElement); + const test = getDep(parentElement, true, config.registryAliases); const dep: PackageDependency = { ...abstractDep, ...test, @@ -87,11 +95,11 @@ export class GenericDockerImageRefExtractor extends DependencyExtractor { if (is.array(element)) { for (const arrayElement of element) { dependencies.push( - ...this.walkPath(abstractDep, arrayElement, leftPath.slice(1)) + ...this.walkPath(abstractDep, arrayElement, leftPath.slice(1), config) ); } return dependencies; } - return this.walkPath(abstractDep, element, leftPath.slice(1)); + return this.walkPath(abstractDep, element, leftPath.slice(1), config); } } diff --git a/lib/modules/manager/terraform/extractors/resources/helm-release.spec.ts b/lib/modules/manager/terraform/extractors/resources/helm-release.spec.ts index 84f2451c8030bb..7c89c540df6adb 100644 --- a/lib/modules/manager/terraform/extractors/resources/helm-release.spec.ts +++ b/lib/modules/manager/terraform/extractors/resources/helm-release.spec.ts @@ -4,7 +4,7 @@ describe('modules/manager/terraform/extractors/resources/helm-release', () => { const extractor = new HelmReleaseExtractor(); it('return empty array if no resource is found', () => { - const res = extractor.extract({}); + const res = extractor.extract({}, [], {}); expect(res).toBeArrayOfSize(0); }); }); diff --git a/lib/modules/manager/terraform/extractors/resources/helm-release.ts b/lib/modules/manager/terraform/extractors/resources/helm-release.ts index c0c54a3b20ce8f..4e2ec94052ff35 100644 --- a/lib/modules/manager/terraform/extractors/resources/helm-release.ts +++ b/lib/modules/manager/terraform/extractors/resources/helm-release.ts @@ -1,12 +1,13 @@ import is from '@sindresorhus/is'; import { logger } from '../../../../../logger'; import { joinUrlParts } from '../../../../../util/url'; -import { DockerDatasource } from '../../../../datasource/docker'; import { HelmDatasource } from '../../../../datasource/helm'; +import { getDep } from '../../../dockerfile/extract'; import { isOCIRegistry } from '../../../helmv3/utils'; -import type { PackageDependency } from '../../../types'; +import type { ExtractConfig, PackageDependency } from '../../../types'; import { DependencyExtractor } from '../../base'; import type { TerraformDefinitionFile } from '../../hcl/types'; +import type { ProviderLock } from '../../lockfile/types'; import { checkIfStringIsPath } from '../../util'; export class HelmReleaseExtractor extends DependencyExtractor { @@ -14,7 +15,11 @@ export class HelmReleaseExtractor extends DependencyExtractor { return [`"helm_release"`]; } - override extract(hclMap: TerraformDefinitionFile): PackageDependency[] { + override extract( + hclMap: TerraformDefinitionFile, + _locks: ProviderLock[], + config: ExtractConfig + ): PackageDependency[] { const dependencies = []; const helmReleases = hclMap?.resource?.helm_release; @@ -46,19 +51,20 @@ export class HelmReleaseExtractor extends DependencyExtractor { } else if (isOCIRegistry(helmRelease.chart)) { // For oci charts, we remove the oci:// and use the docker datasource dep.depName = helmRelease.chart.replace('oci://', ''); - dep.datasource = DockerDatasource.id; + this.processOCI(dep.depName, config, dep); } else if (checkIfStringIsPath(helmRelease.chart)) { dep.skipReason = 'local-chart'; } else if (is.nonEmptyString(helmRelease.repository)) { if (isOCIRegistry(helmRelease.repository)) { - { - // For oci repos, we remove the oci://, join the chart name and use the docker datasource - dep.packageName = joinUrlParts( + // For oci charts, we remove the oci:// and use the docker datasource + this.processOCI( + joinUrlParts( helmRelease.repository.replace('oci://', ''), helmRelease.chart - ); - dep.datasource = DockerDatasource.id; - } + ), + config, + dep + ); } else { dep.registryUrls = [helmRelease.repository]; } @@ -67,4 +73,18 @@ export class HelmReleaseExtractor extends DependencyExtractor { return dependencies; } + + private processOCI( + depName: string, + config: ExtractConfig, + dep: PackageDependency + ): void { + const { depName: packageName, datasource } = getDep( + depName, + false, + config.registryAliases + ); + dep.packageName = packageName; + dep.datasource = datasource; + } } From 77bd389582cbd725720721c847cb4aa451febc50 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Tue, 9 May 2023 17:50:22 +0200 Subject: [PATCH 05/74] fix: RENOVATE_X_CLEAR_HOOKS --- lib/util/git/index.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/util/git/index.ts b/lib/util/git/index.ts index 806bda394b9889..1ab24e34acf71f 100644 --- a/lib/util/git/index.ts +++ b/lib/util/git/index.ts @@ -377,6 +377,10 @@ export function isCloned(): boolean { export async function syncGit(): Promise { if (gitInitialized) { + // istanbul ignore if + if (process.env.RENOVATE_X_CLEAR_HOOKS) { + await git.raw(['config', 'core.hooksPath', '/dev/null']); + } return; } gitInitialized = true; From 0755daa4818ed05e151afe8d35b3c43bd22529ca Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Tue, 9 May 2023 19:34:40 +0200 Subject: [PATCH 06/74] chore: add pr:discussion-first and needs-details label actions (#22060) --- .github/label-actions.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/label-actions.yml b/.github/label-actions.yml index e0f3205b11fd67..fc769f744e506f 100644 --- a/.github/label-actions.yml +++ b/.github/label-actions.yml @@ -178,6 +178,26 @@ The Renovate team +'pr:discussion-first': + comment: > + **Please create a GitHub Discussion before continuing with this PR.** + + + Thank you for your PR, but we need to discuss the requirements and implementation first. + This PR will be closed, but you can reopen it after the discussion has been resolved. + + + Thanks, The Renovate team + close: true + +'needs-details': + comment: > + Hi there, + + + This discussion is missing some details, making it difficult or impossible to help you. + Please try again to provide more details. + 'needs-discussion': unlabel: - 'type:bug' From decd35eaac04f81e90ee9cf6eadeddeca56bccd4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 10 May 2023 01:57:39 +0000 Subject: [PATCH 07/74] chore(deps): update dependency tar to v6.1.14 (#22064) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 3a6de6cd1a198e..ac4d8d9b3429aa 100644 --- a/package.json +++ b/package.json @@ -324,7 +324,7 @@ "rimraf": "5.0.0", "semantic-release": "21.0.2", "strip-ansi": "6.0.1", - "tar": "6.1.13", + "tar": "6.1.14", "tmp-promise": "3.0.3", "ts-jest": "29.1.0", "ts-node": "10.9.1", diff --git a/yarn.lock b/yarn.lock index 3320dcf3262f78..bfcda089a3488a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9867,7 +9867,19 @@ tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -tar@6.1.13, tar@^6.0.5, tar@^6.1.11, tar@^6.1.13, tar@^6.1.2: +tar@6.1.14: + version "6.1.14" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.14.tgz#e87926bec1cfe7c9e783a77a79f3e81c1cfa3b66" + integrity sha512-piERznXu0U7/pW7cdSn7hjqySIVTYT6F76icmFk7ptU7dDYlXTm5r9A6K04R2vU3olYgoKeo1Cg3eeu5nhftAw== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +tar@^6.0.5, tar@^6.1.11, tar@^6.1.13, tar@^6.1.2: version "6.1.13" resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.13.tgz#46e22529000f612180601a6fe0680e7da508847b" integrity sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw== From 198b2fdf2b7d5618e493bb9d13854d0a3b793586 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 10 May 2023 02:55:09 +0000 Subject: [PATCH 08/74] chore(deps): update dependency @types/tar to v6.1.5 (#22066) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index ac4d8d9b3429aa..0fe3870314db92 100644 --- a/package.json +++ b/package.json @@ -283,7 +283,7 @@ "@types/semver": "7.3.13", "@types/semver-stable": "3.0.0", "@types/semver-utils": "1.1.1", - "@types/tar": "6.1.4", + "@types/tar": "6.1.5", "@types/traverse": "0.6.32", "@types/url-join": "4.0.1", "@types/validate-npm-package-name": "4.0.0", diff --git a/yarn.lock b/yarn.lock index bfcda089a3488a..703a47d702b927 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3130,10 +3130,10 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== -"@types/tar@6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@types/tar/-/tar-6.1.4.tgz#cf8497e1ebdc09212fd51625cd2eb5ca18365ad1" - integrity sha512-Cp4oxpfIzWt7mr2pbhHT2OTXGMAL0szYCzuf8lRWyIMCgsx6/Hfc3ubztuhvzXHXgraTQxyOCmmg7TDGIMIJJQ== +"@types/tar@6.1.5": + version "6.1.5" + resolved "https://registry.yarnpkg.com/@types/tar/-/tar-6.1.5.tgz#90ccb3b6a35430e7427410d50eed564e85feaaff" + integrity sha512-qm2I/RlZij5RofuY7vohTpYNaYcrSQlN2MyjucQc7ZweDwaEWkdN/EeNh6e9zjK6uEm6PwjdMXkcj05BxZdX1Q== dependencies: "@types/node" "*" minipass "^4.0.0" From 93052ec9178a3ae57912703cdae2e9f959f36431 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Wed, 10 May 2023 06:30:12 +0200 Subject: [PATCH 09/74] feat: platform=local (#22010) Co-authored-by: Jamie Magee --- lib/config/presets/local/index.ts | 1 + lib/constants/platforms.ts | 3 +- lib/modules/platform/api.ts | 2 + lib/modules/platform/local/index.spec.ts | 128 +++++++++++++++++++++++ lib/modules/platform/local/index.ts | 123 ++++++++++++++++++++++ lib/modules/platform/local/scm.spec.ts | 68 ++++++++++++ lib/modules/platform/local/scm.ts | 51 +++++++++ lib/modules/platform/scm.ts | 2 + lib/util/fs/index.spec.ts | 5 + lib/util/fs/index.ts | 4 + lib/util/git/index.ts | 4 + lib/workers/global/autodiscover.spec.ts | 13 +++ lib/workers/global/autodiscover.ts | 13 +++ lib/workers/global/index.spec.ts | 9 ++ lib/workers/global/index.ts | 11 +- lib/workers/repository/process/index.ts | 2 +- package.json | 2 +- 17 files changed, 434 insertions(+), 7 deletions(-) create mode 100644 lib/modules/platform/local/index.spec.ts create mode 100644 lib/modules/platform/local/index.ts create mode 100644 lib/modules/platform/local/scm.spec.ts create mode 100644 lib/modules/platform/local/scm.ts diff --git a/lib/config/presets/local/index.ts b/lib/config/presets/local/index.ts index ac8e2a69703049..6f99390a6c676d 100644 --- a/lib/config/presets/local/index.ts +++ b/lib/config/presets/local/index.ts @@ -24,6 +24,7 @@ const resolvers = { gitea, github, gitlab, + local: null, } satisfies Record; export function getPreset({ diff --git a/lib/constants/platforms.ts b/lib/constants/platforms.ts index f3a1e71ac8b7ba..049155bd3ba43c 100644 --- a/lib/constants/platforms.ts +++ b/lib/constants/platforms.ts @@ -5,7 +5,8 @@ export type PlatformId = | 'bitbucket-server' | 'gitea' | 'github' - | 'gitlab'; + | 'gitlab' + | 'local'; export const GITHUB_API_USING_HOST_TYPES = [ 'github', diff --git a/lib/modules/platform/api.ts b/lib/modules/platform/api.ts index bb67f2c39432a4..973f6b75d39db6 100644 --- a/lib/modules/platform/api.ts +++ b/lib/modules/platform/api.ts @@ -6,6 +6,7 @@ import * as codecommit from './codecommit'; import * as gitea from './gitea'; import * as github from './github'; import * as gitlab from './gitlab'; +import * as local from './local'; import type { Platform } from './types'; const api = new Map(); @@ -18,3 +19,4 @@ api.set(codecommit.id, codecommit); api.set(gitea.id, gitea); api.set(github.id, github); api.set(gitlab.id, gitlab); +api.set(local.id, local); diff --git a/lib/modules/platform/local/index.spec.ts b/lib/modules/platform/local/index.spec.ts new file mode 100644 index 00000000000000..c226d334d79cbe --- /dev/null +++ b/lib/modules/platform/local/index.spec.ts @@ -0,0 +1,128 @@ +import * as platform from './index'; + +describe('modules/platform/local/index', () => { + describe('initPlatform', () => { + it('returns input', async () => { + expect(await platform.initPlatform({})).toMatchInlineSnapshot(` + { + "dryRun": "lookup", + "endpoint": "local", + "persistRepoData": true, + "requireConfig": "optional", + } + `); + }); + }); + + describe('getRepos', () => { + it('returns empty array', async () => { + expect(await platform.getRepos()).toEqual([]); + }); + }); + + describe('initRepo', () => { + it('returns object', async () => { + expect(await platform.initRepo()).toMatchInlineSnapshot(` + { + "defaultBranch": "", + "isFork": false, + "repoFingerprint": "", + } + `); + }); + }); + + describe('dummy functions', () => { + it('getRepoForceRebase', async () => { + expect(await platform.getRepoForceRebase()).toBe(false); + }); + + it('findIssue', async () => { + expect(await platform.findIssue()).toBeNull(); + }); + + it('getIssueList', async () => { + expect(await platform.getIssueList()).toEqual([]); + }); + + it('getRawFile', async () => { + expect(await platform.getRawFile()).toBeNull(); + }); + + it('getJsonFile', async () => { + expect(await platform.getJsonFile()).toBeNull(); + }); + + it('getPrList', async () => { + expect(await platform.getPrList()).toEqual([]); + }); + + it('ensureIssueClosing', async () => { + expect(await platform.ensureIssueClosing()).toBeUndefined(); + }); + + it('ensureIssue', async () => { + expect(await platform.ensureIssue()).toBeNull(); + }); + + it('massageMarkdown', () => { + expect(platform.massageMarkdown('foo')).toBe('foo'); + }); + + it('updatePr', async () => { + expect(await platform.updatePr()).toBeUndefined(); + }); + + it('mergePr', async () => { + expect(await platform.mergePr()).toBe(false); + }); + + it('addReviewers', async () => { + expect(await platform.addReviewers()).toBeUndefined(); + }); + + it('addAssignees', async () => { + expect(await platform.addAssignees()).toBeUndefined(); + }); + + it('createPr', async () => { + expect(await platform.createPr()).toBeNull(); + }); + + it('deleteLabel', async () => { + expect(await platform.deleteLabel()).toBeUndefined(); + }); + + it('setBranchStatus', async () => { + expect(await platform.setBranchStatus()).toBeUndefined(); + }); + + it('getBranchStatus', async () => { + expect(await platform.getBranchStatus()).toBe('red'); + }); + + it('getBranchStatusCheck', async () => { + expect(await platform.getBranchStatusCheck()).toBeNull(); + }); + + it('ensureCommentRemoval', async () => { + expect(await platform.ensureCommentRemoval()).toBeUndefined(); + }); + + it('ensureComment', async () => { + expect(await platform.ensureComment()).toBeFalse(); + }); + + it('getPr', async () => { + expect(await platform.getPr()).toBeNull(); + }); + + it('findPr', async () => { + expect(await platform.findPr()).toBeNull(); + }); + + it('getBranchPr', async () => { + expect(await platform.getBranchPr()).toBeNull(); + }); + }); +}); diff --git a/lib/modules/platform/local/index.ts b/lib/modules/platform/local/index.ts new file mode 100644 index 00000000000000..1c88d787371daf --- /dev/null +++ b/lib/modules/platform/local/index.ts @@ -0,0 +1,123 @@ +import type { BranchStatus } from '../../../types'; +import type { + Issue, + PlatformParams, + PlatformResult, + Pr, + RepoResult, +} from '../types'; + +export const id = 'local'; + +export function initPlatform(params: PlatformParams): Promise { + return Promise.resolve({ + dryRun: 'lookup', + endpoint: 'local', + persistRepoData: true, + requireConfig: 'optional', + }); +} + +export function getRepos(): Promise { + return Promise.resolve([]); +} + +export function initRepo(): Promise { + return Promise.resolve({ + defaultBranch: '', + isFork: false, + repoFingerprint: '', + }); +} + +export function getRepoForceRebase(): Promise { + return Promise.resolve(false); +} + +export function findIssue(): Promise { + return Promise.resolve(null); +} + +export function getIssueList(): Promise { + return Promise.resolve([]); +} + +export function getRawFile(): Promise { + return Promise.resolve(null); +} + +export function getJsonFile(): Promise | null> { + return Promise.resolve(null); +} + +export function getPrList(): Promise { + return Promise.resolve([]); +} + +export function ensureIssueClosing(): Promise { + return Promise.resolve(); +} + +export function ensureIssue(): Promise { + return Promise.resolve(null); +} + +export function massageMarkdown(input: string): string { + return input; +} + +export function updatePr(): Promise { + return Promise.resolve(); +} + +export function mergePr(): Promise { + return Promise.resolve(false); +} + +export function addReviewers(): Promise { + return Promise.resolve(); +} + +export function addAssignees(): Promise { + return Promise.resolve(); +} + +export function createPr(): Promise { + return Promise.resolve(null); +} + +export function deleteLabel(): Promise { + return Promise.resolve(); +} + +export function setBranchStatus(): Promise { + return Promise.resolve(); +} + +export function getBranchStatus(): Promise { + return Promise.resolve('red'); +} + +export function getBranchStatusCheck(): Promise { + return Promise.resolve(null); +} + +export function ensureCommentRemoval(): Promise { + return Promise.resolve(); +} + +export function ensureComment(): Promise { + return Promise.resolve(false); +} + +export function getPr(): Promise { + return Promise.resolve(null); +} + +export function findPr(): Promise { + return Promise.resolve(null); +} + +export function getBranchPr(): Promise { + return Promise.resolve(null); +} diff --git a/lib/modules/platform/local/scm.spec.ts b/lib/modules/platform/local/scm.spec.ts new file mode 100644 index 00000000000000..6549475ad55d93 --- /dev/null +++ b/lib/modules/platform/local/scm.spec.ts @@ -0,0 +1,68 @@ +import { execSync as _execSync } from 'node:child_process'; +import { mockedFunction } from '../../../../test/util'; +import { LocalFs } from './scm'; + +jest.mock('node:child_process'); +const execSync = mockedFunction(_execSync); + +describe('modules/platform/local/scm', () => { + let localFs: LocalFs; + + beforeEach(() => { + localFs = new LocalFs(); + }); + + describe('dummy functions', () => { + it('behindBaseBranch', async () => { + expect(await localFs.isBranchBehindBase('', '')).toBe(false); + }); + + it('isBranchModified', async () => { + expect(await localFs.isBranchModified('')).toBe(false); + }); + + it('isBranchConflicted', async () => { + expect(await localFs.isBranchConflicted('', '')).toBe(false); + }); + + it('branchExists', async () => { + expect(await localFs.branchExists('')).toBe(true); + }); + + it('getBranchCommit', async () => { + expect(await localFs.getBranchCommit('')).toBeNull(); + }); + + it('deleteBranch', async () => { + expect(await localFs.deleteBranch('')).toBeUndefined(); + }); + + it('commitAndPush', async () => { + expect(await localFs.commitAndPush({} as any)).toBeNull(); + }); + + it('checkoutBranch', async () => { + expect(await localFs.checkoutBranch('')).toBe(''); + }); + }); + + describe('getFileList', () => { + it('should return file list using git', async () => { + execSync.mockReturnValueOnce('file1\nfile2'); + expect(await localFs.getFileList()).toHaveLength(2); + }); + + it('should return file list using glob', async () => { + execSync.mockImplementationOnce(() => { + throw new Error(); + }); + jest.mock('glob', () => ({ + glob: jest + .fn() + .mockImplementation(() => Promise.resolve(['file1', 'file2'])), + })); + + expect(await localFs.getFileList()).toHaveLength(2); + }); + }); +}); diff --git a/lib/modules/platform/local/scm.ts b/lib/modules/platform/local/scm.ts new file mode 100644 index 00000000000000..5b01391572c110 --- /dev/null +++ b/lib/modules/platform/local/scm.ts @@ -0,0 +1,51 @@ +import { execSync } from 'node:child_process'; +import { glob } from 'glob'; +import { logger } from '../../../logger'; +import type { CommitFilesConfig, CommitSha } from '../../../util/git/types'; +import type { PlatformScm } from '../types'; + +let fileList: string[] | undefined; +export class LocalFs implements PlatformScm { + isBranchBehindBase(branchName: string, baseBranch: string): Promise { + return Promise.resolve(false); + } + isBranchModified(branchName: string): Promise { + return Promise.resolve(false); + } + isBranchConflicted(baseBranch: string, branch: string): Promise { + return Promise.resolve(false); + } + branchExists(branchName: string): Promise { + return Promise.resolve(true); + } + getBranchCommit(branchName: string): Promise { + return Promise.resolve(null); + } + deleteBranch(branchName: string): Promise { + return Promise.resolve(); + } + commitAndPush(commitConfig: CommitFilesConfig): Promise { + return Promise.resolve(null); + } + + async getFileList(): Promise { + try { + // fetch file list using git + const stdout = execSync('git ls-files', { encoding: 'utf-8' }); + logger.debug('Got file list using git'); + fileList = stdout.split('\n'); + } catch (err) { + logger.debug('Could not get file list using git, using glob instead'); + fileList ??= await glob('**', { + dot: true, + nodir: true, + }); + } + + return fileList; + } + + checkoutBranch(branchName: string): Promise { + return Promise.resolve(''); + } +} diff --git a/lib/modules/platform/scm.ts b/lib/modules/platform/scm.ts index 9a26a35594401d..8f80217ec36da5 100644 --- a/lib/modules/platform/scm.ts +++ b/lib/modules/platform/scm.ts @@ -3,6 +3,7 @@ import type { PlatformId } from '../../constants'; import { PLATFORM_NOT_FOUND } from '../../constants/error-messages'; import { DefaultGitScm } from './default-scm'; import { GithubScm } from './github/scm'; +import { LocalFs } from './local/scm'; import type { PlatformScm } from './types'; export const platformScmImpls = new Map>(); @@ -13,6 +14,7 @@ platformScmImpls.set('bitbucket-server', DefaultGitScm); platformScmImpls.set('gitea', DefaultGitScm); platformScmImpls.set('github', GithubScm); platformScmImpls.set('gitlab', DefaultGitScm); +platformScmImpls.set('local', LocalFs); let _scm: PlatformScm | undefined; diff --git a/lib/util/fs/index.spec.ts b/lib/util/fs/index.spec.ts index f200818843e2d7..361f4eff62dda9 100644 --- a/lib/util/fs/index.spec.ts +++ b/lib/util/fs/index.spec.ts @@ -134,6 +134,11 @@ describe('util/fs/index', () => { }); describe('deleteLocalFile', () => { + it('throws if platform is local', async () => { + GlobalConfig.set({ platform: 'local' }); + await expect(deleteLocalFile('foo/bar/file.txt')).rejects.toThrow(); + }); + it('deletes file', async () => { const filePath = `${localDir}/foo/bar/file.txt`; await fs.outputFile(filePath, 'foobar'); diff --git a/lib/util/fs/index.ts b/lib/util/fs/index.ts index 5493a6397f8493..2a9b2793975755 100644 --- a/lib/util/fs/index.ts +++ b/lib/util/fs/index.ts @@ -65,6 +65,10 @@ export async function writeLocalFile( } export async function deleteLocalFile(fileName: string): Promise { + // This a failsafe and hopefully will never be triggered + if (GlobalConfig.get('platform') === 'local') { + throw new Error('Cannot delete file when platform=local'); + } const localDir = GlobalConfig.get('localDir'); if (localDir) { const localFileName = ensureLocalPath(fileName); diff --git a/lib/util/git/index.ts b/lib/util/git/index.ts index 1ab24e34acf71f..5d086bef8612ca 100644 --- a/lib/util/git/index.ts +++ b/lib/util/git/index.ts @@ -383,6 +383,10 @@ export async function syncGit(): Promise { } return; } + // istanbul ignore if: failsafe + if (GlobalConfig.get('platform') === 'local') { + throw new Error('Cannot sync git when platform=local'); + } gitInitialized = true; const localDir = GlobalConfig.get('localDir')!; logger.debug(`Initializing git repository into ${localDir}`); diff --git a/lib/workers/global/autodiscover.spec.ts b/lib/workers/global/autodiscover.spec.ts index e401268d6fd148..ae75305ad695a9 100644 --- a/lib/workers/global/autodiscover.spec.ts +++ b/lib/workers/global/autodiscover.spec.ts @@ -25,6 +25,19 @@ describe('workers/global/autodiscover', () => { }); }); + it('throws if local and repositories defined', async () => { + config.platform = 'local'; + config.repositories = ['a']; + await expect(autodiscoverRepositories(config)).rejects.toThrow(); + }); + + it('returns local', async () => { + config.platform = 'local'; + expect((await autodiscoverRepositories(config)).repositories).toEqual([ + 'local', + ]); + }); + it('returns if not autodiscovering', async () => { expect(await autodiscoverRepositories(config)).toEqual(config); }); diff --git a/lib/workers/global/autodiscover.ts b/lib/workers/global/autodiscover.ts index 332961b82e1506..943f739d67f247 100644 --- a/lib/workers/global/autodiscover.ts +++ b/lib/workers/global/autodiscover.ts @@ -13,6 +13,19 @@ function repoName(value: string | { repository: string }): string { export async function autodiscoverRepositories( config: AllConfig ): Promise { + if (config.platform === 'local') { + if (config.repositories?.length) { + logger.debug( + { repositories: config.repositories }, + 'Found repositories when in local mode' + ); + throw new Error( + 'Invalid configuration: repositories list not supported when platform=local' + ); + } + config.repositories = ['local']; + return config; + } if (!config.autodiscover) { if (!config.repositories?.length) { logger.warn( diff --git a/lib/workers/global/index.spec.ts b/lib/workers/global/index.spec.ts index 8c371725b1569a..0bc6aec1add7c0 100644 --- a/lib/workers/global/index.spec.ts +++ b/lib/workers/global/index.spec.ts @@ -95,6 +95,15 @@ describe('workers/global/index', () => { expect(repositoryWorker.renovateRepository).not.toHaveBeenCalled(); }); + it('handles local', async () => { + parseConfigs.mockResolvedValueOnce({ + platform: 'local', + }); + await expect(globalWorker.start()).resolves.toBe(0); + expect(parseConfigs).toHaveBeenCalledTimes(1); + expect(repositoryWorker.renovateRepository).toHaveBeenCalledTimes(1); + }); + it('processes repositories', async () => { parseConfigs.mockResolvedValueOnce({ gitAuthor: 'a@b.com', diff --git a/lib/workers/global/index.ts b/lib/workers/global/index.ts index 52e7beb5ea9a67..80869a7426c87e 100644 --- a/lib/workers/global/index.ts +++ b/lib/workers/global/index.ts @@ -37,10 +37,13 @@ export async function getRepositoryConfig( ); // TODO: types (#7154) const platform = GlobalConfig.get('platform')!; - repoConfig.localDir = upath.join( - repoConfig.baseDir, - `./repos/${platform}/${repoConfig.repository}` - ); + repoConfig.localDir = + platform === 'local' + ? process.cwd() + : upath.join( + repoConfig.baseDir, + `./repos/${platform}/${repoConfig.repository}` + ); await fs.ensureDir(repoConfig.localDir); delete repoConfig.baseDir; return configParser.filterConfig(repoConfig, 'repository'); diff --git a/lib/workers/repository/process/index.ts b/lib/workers/repository/process/index.ts index 0593f539bc42bb..cced4e1702d921 100644 --- a/lib/workers/repository/process/index.ts +++ b/lib/workers/repository/process/index.ts @@ -108,7 +108,7 @@ export async function extractDependencies( branchList: [], packageFiles: null!, }; - if (config.baseBranches?.length) { + if (GlobalConfig.get('platform') !== 'local' && config.baseBranches?.length) { config.baseBranches = unfoldBaseBranches(config.baseBranches); logger.debug({ baseBranches: config.baseBranches }, 'baseBranches'); const extracted: Record> = {}; diff --git a/package.json b/package.json index 0fe3870314db92..78aa5863febcc9 100644 --- a/package.json +++ b/package.json @@ -196,6 +196,7 @@ "global-agent": "3.0.0", "good-enough-parser": "1.1.22", "got": "11.8.6", + "glob": "10.2.2", "graph-data-structure": "3.3.0", "handlebars": "4.7.7", "hasha": "5.2.2", @@ -307,7 +308,6 @@ "eslint-plugin-promise": "6.1.1", "eslint-plugin-typescript-enum": "2.1.0", "expect-more-jest": "5.5.0", - "glob": "10.2.2", "graphql": "16.6.0", "husky": "8.0.3", "jest": "29.5.0", From 32cb5e1ad7818cfd7573d75e7a62f9e793ac5255 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Wed, 10 May 2023 07:35:18 +0200 Subject: [PATCH 10/74] docs: local platform --- lib/modules/platform/local/index.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 lib/modules/platform/local/index.md diff --git a/lib/modules/platform/local/index.md b/lib/modules/platform/local/index.md new file mode 100644 index 00000000000000..7edadcb2770676 --- /dev/null +++ b/lib/modules/platform/local/index.md @@ -0,0 +1,20 @@ +# Local + +The "local" platform exists to allow users to perform dry runs against the local file system, such as to test out new config. + +## Usage + +Run `renovate --platform=local` in the directory you want Renovate to run in. +In this mode, Renovate will default to `dryRun=lookup`. +No "repositories" arguments should be provided, as you cannot run against multiple directories or run in the non-working directory. + +It is possible to run on both a git and non-git directory. +Config is optional - so it will run either with or without any "repo config" found. + +It does not do any "compare" or before and after analysis - if your purpose is to test a new config then you will need to manually compare. + +## Limitations + +- `local>` presets cannot be resolved. Normally these would point to the local platform such as GitHub, but in the case of running locally, it does not exist +- `baseBranches` are ignored +- Branch creation is not supported From 2e2570c2fd97a9254c330095a75e8a64db1a2d20 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Wed, 10 May 2023 07:38:03 +0200 Subject: [PATCH 11/74] feat(poetry): detect constraint from lock file (#22038) Co-authored-by: Mathieu Kniewallner --- .../manager/poetry/__fixtures__/poetry12.lock | 482 +++++++++++ .../poetry/__fixtures__/poetry142.lock | 18 + lib/modules/manager/poetry/artifacts.spec.ts | 786 +++++++++--------- lib/modules/manager/poetry/artifacts.ts | 56 +- lib/modules/manager/poetry/types.ts | 1 + 5 files changed, 941 insertions(+), 402 deletions(-) create mode 100644 lib/modules/manager/poetry/__fixtures__/poetry12.lock create mode 100644 lib/modules/manager/poetry/__fixtures__/poetry142.lock diff --git a/lib/modules/manager/poetry/__fixtures__/poetry12.lock b/lib/modules/manager/poetry/__fixtures__/poetry12.lock new file mode 100644 index 00000000000000..0bd5addc4f251e --- /dev/null +++ b/lib/modules/manager/poetry/__fixtures__/poetry12.lock @@ -0,0 +1,482 @@ +[[package]] +name = "attrs" +version = "22.2.0" +description = "Classes Without Boilerplate" +category = "dev" +optional = false +python-versions = ">=3.6" + +[metadata] +lock-version = "1.1" +python-versions = ">=3.8,<4.0" +content-hash = "8387ae7c79d1e9c796e33b5c4506682418457e8b0b55908ce811bb876dcb40fd" + +[metadata.files] +attrs = [ + {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, + {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, +] +certifi = [ + {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, + {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, +] +cfgv = [ + {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, + {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, +] +chardet = [ + {file = "chardet-5.1.0-py3-none-any.whl", hash = "sha256:362777fb014af596ad31334fde1e8c327dfdb076e1960d1694662d46a6917ab9"}, + {file = "chardet-5.1.0.tar.gz", hash = "sha256:0d62712b956bc154f85fb0a266e2a3c5913c2967e00348701b32411d6def31e5"}, +] +charset-normalizer = [ + {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, + {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, +] +click = [ + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, +] +colorama = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] +coverage = [ + {file = "coverage-7.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c90e73bdecb7b0d1cea65a08cb41e9d672ac6d7995603d6465ed4914b98b9ad7"}, + {file = "coverage-7.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e2926b8abedf750c2ecf5035c07515770944acf02e1c46ab08f6348d24c5f94d"}, + {file = "coverage-7.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57b77b9099f172804e695a40ebaa374f79e4fb8b92f3e167f66facbf92e8e7f5"}, + {file = "coverage-7.2.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:efe1c0adad110bf0ad7fb59f833880e489a61e39d699d37249bdf42f80590169"}, + {file = "coverage-7.2.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2199988e0bc8325d941b209f4fd1c6fa007024b1442c5576f1a32ca2e48941e6"}, + {file = "coverage-7.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:81f63e0fb74effd5be736cfe07d710307cc0a3ccb8f4741f7f053c057615a137"}, + {file = "coverage-7.2.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:186e0fc9cf497365036d51d4d2ab76113fb74f729bd25da0975daab2e107fd90"}, + {file = "coverage-7.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:420f94a35e3e00a2b43ad5740f935358e24478354ce41c99407cddd283be00d2"}, + {file = "coverage-7.2.2-cp310-cp310-win32.whl", hash = "sha256:38004671848b5745bb05d4d621526fca30cee164db42a1f185615f39dc997292"}, + {file = "coverage-7.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:0ce383d5f56d0729d2dd40e53fe3afeb8f2237244b0975e1427bfb2cf0d32bab"}, + {file = "coverage-7.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3eb55b7b26389dd4f8ae911ba9bc8c027411163839dea4c8b8be54c4ee9ae10b"}, + {file = "coverage-7.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d2b96123a453a2d7f3995ddb9f28d01fd112319a7a4d5ca99796a7ff43f02af5"}, + {file = "coverage-7.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:299bc75cb2a41e6741b5e470b8c9fb78d931edbd0cd009c58e5c84de57c06731"}, + {file = "coverage-7.2.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e1df45c23d4230e3d56d04414f9057eba501f78db60d4eeecfcb940501b08fd"}, + {file = "coverage-7.2.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:006ed5582e9cbc8115d2e22d6d2144a0725db542f654d9d4fda86793832f873d"}, + {file = "coverage-7.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d683d230b5774816e7d784d7ed8444f2a40e7a450e5720d58af593cb0b94a212"}, + {file = "coverage-7.2.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8efb48fa743d1c1a65ee8787b5b552681610f06c40a40b7ef94a5b517d885c54"}, + {file = "coverage-7.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4c752d5264053a7cf2fe81c9e14f8a4fb261370a7bb344c2a011836a96fb3f57"}, + {file = "coverage-7.2.2-cp311-cp311-win32.whl", hash = "sha256:55272f33da9a5d7cccd3774aeca7a01e500a614eaea2a77091e9be000ecd401d"}, + {file = "coverage-7.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:92ebc1619650409da324d001b3a36f14f63644c7f0a588e331f3b0f67491f512"}, + {file = "coverage-7.2.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5afdad4cc4cc199fdf3e18088812edcf8f4c5a3c8e6cb69127513ad4cb7471a9"}, + {file = "coverage-7.2.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0484d9dd1e6f481b24070c87561c8d7151bdd8b044c93ac99faafd01f695c78e"}, + {file = "coverage-7.2.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d530191aa9c66ab4f190be8ac8cc7cfd8f4f3217da379606f3dd4e3d83feba69"}, + {file = "coverage-7.2.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ac0f522c3b6109c4b764ffec71bf04ebc0523e926ca7cbe6c5ac88f84faced0"}, + {file = "coverage-7.2.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ba279aae162b20444881fc3ed4e4f934c1cf8620f3dab3b531480cf602c76b7f"}, + {file = "coverage-7.2.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:53d0fd4c17175aded9c633e319360d41a1f3c6e352ba94edcb0fa5167e2bad67"}, + {file = "coverage-7.2.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c99cb7c26a3039a8a4ee3ca1efdde471e61b4837108847fb7d5be7789ed8fd9"}, + {file = "coverage-7.2.2-cp37-cp37m-win32.whl", hash = "sha256:5cc0783844c84af2522e3a99b9b761a979a3ef10fb87fc4048d1ee174e18a7d8"}, + {file = "coverage-7.2.2-cp37-cp37m-win_amd64.whl", hash = "sha256:817295f06eacdc8623dc4df7d8b49cea65925030d4e1e2a7c7218380c0072c25"}, + {file = "coverage-7.2.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6146910231ece63facfc5984234ad1b06a36cecc9fd0c028e59ac7c9b18c38c6"}, + {file = "coverage-7.2.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:387fb46cb8e53ba7304d80aadca5dca84a2fbf6fe3faf6951d8cf2d46485d1e5"}, + {file = "coverage-7.2.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:046936ab032a2810dcaafd39cc4ef6dd295df1a7cbead08fe996d4765fca9fe4"}, + {file = "coverage-7.2.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e627dee428a176ffb13697a2c4318d3f60b2ccdde3acdc9b3f304206ec130ccd"}, + {file = "coverage-7.2.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4fa54fb483decc45f94011898727802309a109d89446a3c76387d016057d2c84"}, + {file = "coverage-7.2.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3668291b50b69a0c1ef9f462c7df2c235da3c4073f49543b01e7eb1dee7dd540"}, + {file = "coverage-7.2.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7c20b731211261dc9739bbe080c579a1835b0c2d9b274e5fcd903c3a7821cf88"}, + {file = "coverage-7.2.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5764e1f7471cb8f64b8cda0554f3d4c4085ae4b417bfeab236799863703e5de2"}, + {file = "coverage-7.2.2-cp38-cp38-win32.whl", hash = "sha256:4f01911c010122f49a3e9bdc730eccc66f9b72bd410a3a9d3cb8448bb50d65d3"}, + {file = "coverage-7.2.2-cp38-cp38-win_amd64.whl", hash = "sha256:c448b5c9e3df5448a362208b8d4b9ed85305528313fca1b479f14f9fe0d873b8"}, + {file = "coverage-7.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bfe7085783cda55e53510482fa7b5efc761fad1abe4d653b32710eb548ebdd2d"}, + {file = "coverage-7.2.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9d22e94e6dc86de981b1b684b342bec5e331401599ce652900ec59db52940005"}, + {file = "coverage-7.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:507e4720791977934bba016101579b8c500fb21c5fa3cd4cf256477331ddd988"}, + {file = "coverage-7.2.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bc4803779f0e4b06a2361f666e76f5c2e3715e8e379889d02251ec911befd149"}, + {file = "coverage-7.2.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db8c2c5ace167fd25ab5dd732714c51d4633f58bac21fb0ff63b0349f62755a8"}, + {file = "coverage-7.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4f68ee32d7c4164f1e2c8797535a6d0a3733355f5861e0f667e37df2d4b07140"}, + {file = "coverage-7.2.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d52f0a114b6a58305b11a5cdecd42b2e7f1ec77eb20e2b33969d702feafdd016"}, + {file = "coverage-7.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:797aad79e7b6182cb49c08cc5d2f7aa7b2128133b0926060d0a8889ac43843be"}, + {file = "coverage-7.2.2-cp39-cp39-win32.whl", hash = "sha256:db45eec1dfccdadb179b0f9ca616872c6f700d23945ecc8f21bb105d74b1c5fc"}, + {file = "coverage-7.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:8dbe2647bf58d2c5a6c5bcc685f23b5f371909a5624e9f5cd51436d6a9f6c6ef"}, + {file = "coverage-7.2.2-pp37.pp38.pp39-none-any.whl", hash = "sha256:872d6ce1f5be73f05bea4df498c140b9e7ee5418bfa2cc8204e7f9b817caa968"}, + {file = "coverage-7.2.2.tar.gz", hash = "sha256:36dd42da34fe94ed98c39887b86db9d06777b1c8f860520e21126a75507024f2"}, +] +deptry = [ + {file = "deptry-0.6.6-py3-none-any.whl", hash = "sha256:38c03085899339a43374ba51c845d6d1e3d3d2d003d8270d85f0c67f19775e36"}, + {file = "deptry-0.6.6.tar.gz", hash = "sha256:b968b459929ede5428d695c801f39d03c058de7fa7f855585ca8620a1ec3ae62"}, +] +distlib = [ + {file = "distlib-0.3.6-py2.py3-none-any.whl", hash = "sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e"}, + {file = "distlib-0.3.6.tar.gz", hash = "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46"}, +] +exceptiongroup = [ + {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, + {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, +] +filelock = [ + {file = "filelock-3.10.0-py3-none-any.whl", hash = "sha256:e90b34656470756edf8b19656785c5fea73afa1953f3e1b0d645cef11cab3182"}, + {file = "filelock-3.10.0.tar.gz", hash = "sha256:3199fd0d3faea8b911be52b663dfccceb84c95949dd13179aa21436d1a79c4ce"}, +] +ghp-import = [ + {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"}, + {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"}, +] +griffe = [ + {file = "griffe-0.25.5-py3-none-any.whl", hash = "sha256:1fb9edff48e66d4873014a2ebf21aca5f271d0006a4c937826e3cf592ffb3706"}, + {file = "griffe-0.25.5.tar.gz", hash = "sha256:11ea3403ef0560a1cbcf7f302eb5d21cf4c1d8ed3f8a16a75aa9f6f458caf3f1"}, +] +identify = [ + {file = "identify-2.5.21-py2.py3-none-any.whl", hash = "sha256:69edcaffa8e91ae0f77d397af60f148b6b45a8044b2cc6d99cafa5b04793ff00"}, + {file = "identify-2.5.21.tar.gz", hash = "sha256:7671a05ef9cfaf8ff63b15d45a91a1147a03aaccb2976d4e9bd047cbbc508471"}, +] +idna = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] +importlib-metadata = [ + {file = "importlib_metadata-6.0.0-py3-none-any.whl", hash = "sha256:7efb448ec9a5e313a57655d35aa54cd3e01b7e1fbcf72dce1bf06119420f5bad"}, + {file = "importlib_metadata-6.0.0.tar.gz", hash = "sha256:e354bedeb60efa6affdcc8ae121b73544a7aa74156d047311948f6d711cd378d"}, +] +iniconfig = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] +jinja2 = [ + {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, + {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, +] +markdown = [ + {file = "Markdown-3.3.7-py3-none-any.whl", hash = "sha256:f5da449a6e1c989a4cea2631aa8ee67caa5a2ef855d551c88f9e309f4634c621"}, + {file = "Markdown-3.3.7.tar.gz", hash = "sha256:cbb516f16218e643d8e0a95b309f77eb118cb138d39a4f27851e6a63581db874"}, +] +markupsafe = [ + {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-win32.whl", hash = "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-win32.whl", hash = "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-win32.whl", hash = "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-win32.whl", hash = "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-win32.whl", hash = "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed"}, + {file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"}, +] +mergedeep = [ + {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"}, + {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"}, +] +mkdocs = [ + {file = "mkdocs-1.4.2-py3-none-any.whl", hash = "sha256:c8856a832c1e56702577023cd64cc5f84948280c1c0fcc6af4cd39006ea6aa8c"}, + {file = "mkdocs-1.4.2.tar.gz", hash = "sha256:8947af423a6d0facf41ea1195b8e1e8c85ad94ac95ae307fe11232e0424b11c5"}, +] +mkdocs-autorefs = [ + {file = "mkdocs-autorefs-0.4.1.tar.gz", hash = "sha256:70748a7bd025f9ecd6d6feeba8ba63f8e891a1af55f48e366d6d6e78493aba84"}, + {file = "mkdocs_autorefs-0.4.1-py3-none-any.whl", hash = "sha256:a2248a9501b29dc0cc8ba4c09f4f47ff121945f6ce33d760f145d6f89d313f5b"}, +] +mkdocs-material = [ + {file = "mkdocs_material-8.5.11-py3-none-any.whl", hash = "sha256:c907b4b052240a5778074a30a78f31a1f8ff82d7012356dc26898b97559f082e"}, + {file = "mkdocs_material-8.5.11.tar.gz", hash = "sha256:b0ea0513fd8cab323e8a825d6692ea07fa83e917bb5db042e523afecc7064ab7"}, +] +mkdocs-material-extensions = [ + {file = "mkdocs_material_extensions-1.1.1-py3-none-any.whl", hash = "sha256:e41d9f38e4798b6617ad98ca8f7f1157b1e4385ac1459ca1e4ea219b556df945"}, + {file = "mkdocs_material_extensions-1.1.1.tar.gz", hash = "sha256:9c003da71e2cc2493d910237448c672e00cefc800d3d6ae93d2fc69979e3bd93"}, +] +mkdocstrings = [ + {file = "mkdocstrings-0.19.1-py3-none-any.whl", hash = "sha256:32a38d88f67f65b264184ea71290f9332db750d189dea4200cbbe408d304c261"}, + {file = "mkdocstrings-0.19.1.tar.gz", hash = "sha256:d1037cacb4b522c1e8c164ed5d00d724a82e49dcee0af80db8fb67b384faeef9"}, +] +mkdocstrings-python = [ + {file = "mkdocstrings-python-0.8.3.tar.gz", hash = "sha256:9ae473f6dc599339b09eee17e4d2b05d6ac0ec29860f3fc9b7512d940fc61adf"}, + {file = "mkdocstrings_python-0.8.3-py3-none-any.whl", hash = "sha256:4e6e1cd6f37a785de0946ced6eb846eb2f5d891ac1cc2c7b832943d3529087a7"}, +] +mypy = [ + {file = "mypy-0.981-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4bc460e43b7785f78862dab78674e62ec3cd523485baecfdf81a555ed29ecfa0"}, + {file = "mypy-0.981-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:756fad8b263b3ba39e4e204ee53042671b660c36c9017412b43af210ddee7b08"}, + {file = "mypy-0.981-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a16a0145d6d7d00fbede2da3a3096dcc9ecea091adfa8da48fa6a7b75d35562d"}, + {file = "mypy-0.981-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce65f70b14a21fdac84c294cde75e6dbdabbcff22975335e20827b3b94bdbf49"}, + {file = "mypy-0.981-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6e35d764784b42c3e256848fb8ed1d4292c9fc0098413adb28d84974c095b279"}, + {file = "mypy-0.981-cp310-cp310-win_amd64.whl", hash = "sha256:e53773073c864d5f5cec7f3fc72fbbcef65410cde8cc18d4f7242dea60dac52e"}, + {file = "mypy-0.981-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6ee196b1d10b8b215e835f438e06965d7a480f6fe016eddbc285f13955cca659"}, + {file = "mypy-0.981-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ad21d4c9d3673726cf986ea1d0c9fb66905258709550ddf7944c8f885f208be"}, + {file = "mypy-0.981-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d1debb09043e1f5ee845fa1e96d180e89115b30e47c5d3ce53bc967bab53f62d"}, + {file = "mypy-0.981-cp37-cp37m-win_amd64.whl", hash = "sha256:9f362470a3480165c4c6151786b5379351b790d56952005be18bdbdd4c7ce0ae"}, + {file = "mypy-0.981-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c9e0efb95ed6ca1654951bd5ec2f3fa91b295d78bf6527e026529d4aaa1e0c30"}, + {file = "mypy-0.981-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e178eaffc3c5cd211a87965c8c0df6da91ed7d258b5fc72b8e047c3771317ddb"}, + {file = "mypy-0.981-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:06e1eac8d99bd404ed8dd34ca29673c4346e76dd8e612ea507763dccd7e13c7a"}, + {file = "mypy-0.981-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa38f82f53e1e7beb45557ff167c177802ba7b387ad017eab1663d567017c8ee"}, + {file = "mypy-0.981-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:64e1f6af81c003f85f0dfed52db632817dabb51b65c0318ffbf5ff51995bbb08"}, + {file = "mypy-0.981-cp38-cp38-win_amd64.whl", hash = "sha256:e1acf62a8c4f7c092462c738aa2c2489e275ed386320c10b2e9bff31f6f7e8d6"}, + {file = "mypy-0.981-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b6ede64e52257931315826fdbfc6ea878d89a965580d1a65638ef77cb551f56d"}, + {file = "mypy-0.981-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eb3978b191b9fa0488524bb4ffedf2c573340e8c2b4206fc191d44c7093abfb7"}, + {file = "mypy-0.981-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77f8fcf7b4b3cc0c74fb33ae54a4cd00bb854d65645c48beccf65fa10b17882c"}, + {file = "mypy-0.981-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f64d2ce043a209a297df322eb4054dfbaa9de9e8738291706eaafda81ab2b362"}, + {file = "mypy-0.981-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2ee3dbc53d4df7e6e3b1c68ac6a971d3a4fb2852bf10a05fda228721dd44fae1"}, + {file = "mypy-0.981-cp39-cp39-win_amd64.whl", hash = "sha256:8e8e49aa9cc23aa4c926dc200ce32959d3501c4905147a66ce032f05cb5ecb92"}, + {file = "mypy-0.981-py3-none-any.whl", hash = "sha256:794f385653e2b749387a42afb1e14c2135e18daeb027e0d97162e4b7031210f8"}, + {file = "mypy-0.981.tar.gz", hash = "sha256:ad77c13037d3402fbeffda07d51e3f228ba078d1c7096a73759c9419ea031bf4"}, +] +mypy-extensions = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] +nodeenv = [ + {file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"}, + {file = "nodeenv-1.7.0.tar.gz", hash = "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b"}, +] +packaging = [ + {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, + {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, +] +platformdirs = [ + {file = "platformdirs-3.1.1-py3-none-any.whl", hash = "sha256:e5986afb596e4bb5bde29a79ac9061aa955b94fca2399b7aaac4090860920dd8"}, + {file = "platformdirs-3.1.1.tar.gz", hash = "sha256:024996549ee88ec1a9aa99ff7f8fc819bb59e2c3477b410d90a16d32d6e707aa"}, +] +pluggy = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] +pre-commit = [ + {file = "pre_commit-2.21.0-py2.py3-none-any.whl", hash = "sha256:e2f91727039fc39a92f58a588a25b87f936de6567eed4f0e673e0507edc75bad"}, + {file = "pre_commit-2.21.0.tar.gz", hash = "sha256:31ef31af7e474a8d8995027fefdfcf509b5c913ff31f2015b4ec4beb26a6f658"}, +] +py = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] +pygments = [ + {file = "Pygments-2.14.0-py3-none-any.whl", hash = "sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717"}, + {file = "Pygments-2.14.0.tar.gz", hash = "sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297"}, +] +pymdown-extensions = [ + {file = "pymdown_extensions-9.10-py3-none-any.whl", hash = "sha256:31eaa76ce6f96aabfcea98787c2fff2c5c0611b20a53a94213970cfbf05f02b8"}, + {file = "pymdown_extensions-9.10.tar.gz", hash = "sha256:562c38eee4ce3f101ce631b804bfc2177a8a76c7e4dc908871fb6741a90257a7"}, +] +pytest = [ + {file = "pytest-7.2.2-py3-none-any.whl", hash = "sha256:130328f552dcfac0b1cec75c12e3f005619dc5f874f0a06e8ff7263f0ee6225e"}, + {file = "pytest-7.2.2.tar.gz", hash = "sha256:c99ab0c73aceb050f68929bc93af19ab6db0558791c6a0715723abe9d0ade9d4"}, +] +pytest-cov = [ + {file = "pytest-cov-4.0.0.tar.gz", hash = "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"}, + {file = "pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"}, +] +python-dateutil = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] +pyyaml = [ + {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, + {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, + {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, + {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, + {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, + {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, + {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, + {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, + {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, + {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, + {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, + {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, + {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, + {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, + {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, + {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, + {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, +] +pyyaml-env-tag = [ + {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"}, + {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"}, +] +requests = [ + {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"}, + {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"}, +] +setuptools = [ + {file = "setuptools-67.6.0-py3-none-any.whl", hash = "sha256:b78aaa36f6b90a074c1fa651168723acbf45d14cb1196b6f02c0fd07f17623b2"}, + {file = "setuptools-67.6.0.tar.gz", hash = "sha256:2ee892cd5f29f3373097f5a814697e397cf3ce313616df0af11231e2ad118077"}, +] +six = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] +tomli = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] +tox = [ + {file = "tox-3.28.0-py2.py3-none-any.whl", hash = "sha256:57b5ab7e8bb3074edc3c0c0b4b192a4f3799d3723b2c5b76f1fa9f2d40316eea"}, + {file = "tox-3.28.0.tar.gz", hash = "sha256:d0d28f3fe6d6d7195c27f8b054c3e99d5451952b54abdae673b71609a581f640"}, +] +typing-extensions = [ + {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, + {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, +] +urllib3 = [ + {file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"}, + {file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"}, +] +virtualenv = [ + {file = "virtualenv-20.21.0-py3-none-any.whl", hash = "sha256:31712f8f2a17bd06234fa97fdf19609e789dd4e3e4bf108c3da71d710651adbc"}, + {file = "virtualenv-20.21.0.tar.gz", hash = "sha256:f50e3e60f990a0757c9b68333c9fdaa72d7188caa417f96af9e52407831a3b68"}, +] +watchdog = [ + {file = "watchdog-2.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1f1200d4ec53b88bf04ab636f9133cb703eb19768a39351cee649de21a33697"}, + {file = "watchdog-2.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:564e7739abd4bd348aeafbf71cc006b6c0ccda3160c7053c4a53b67d14091d42"}, + {file = "watchdog-2.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:95ad708a9454050a46f741ba5e2f3468655ea22da1114e4c40b8cbdaca572565"}, + {file = "watchdog-2.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a073c91a6ef0dda488087669586768195c3080c66866144880f03445ca23ef16"}, + {file = "watchdog-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aa8b028750b43e80eea9946d01925168eeadb488dfdef1d82be4b1e28067f375"}, + {file = "watchdog-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:964fd236cd443933268ae49b59706569c8b741073dbfd7ca705492bae9d39aab"}, + {file = "watchdog-2.3.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:91fd146d723392b3e6eb1ac21f122fcce149a194a2ba0a82c5e4d0ee29cd954c"}, + {file = "watchdog-2.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:efe3252137392a471a2174d721e1037a0e6a5da7beb72a021e662b7000a9903f"}, + {file = "watchdog-2.3.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:85bf2263290591b7c5fa01140601b64c831be88084de41efbcba6ea289874f44"}, + {file = "watchdog-2.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8f2df370cd8e4e18499dd0bfdef476431bcc396108b97195d9448d90924e3131"}, + {file = "watchdog-2.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ea5d86d1bcf4a9d24610aa2f6f25492f441960cf04aed2bd9a97db439b643a7b"}, + {file = "watchdog-2.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6f5d0f7eac86807275eba40b577c671b306f6f335ba63a5c5a348da151aba0fc"}, + {file = "watchdog-2.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b848c71ef2b15d0ef02f69da8cc120d335cec0ed82a3fa7779e27a5a8527225"}, + {file = "watchdog-2.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0d9878be36d2b9271e3abaa6f4f051b363ff54dbbe7e7df1af3c920e4311ee43"}, + {file = "watchdog-2.3.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4cd61f98cb37143206818cb1786d2438626aa78d682a8f2ecee239055a9771d5"}, + {file = "watchdog-2.3.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3d2dbcf1acd96e7a9c9aefed201c47c8e311075105d94ce5e899f118155709fd"}, + {file = "watchdog-2.3.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:03f342a9432fe08107defbe8e405a2cb922c5d00c4c6c168c68b633c64ce6190"}, + {file = "watchdog-2.3.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7a596f9415a378d0339681efc08d2249e48975daae391d58f2e22a3673b977cf"}, + {file = "watchdog-2.3.1-py3-none-manylinux2014_armv7l.whl", hash = "sha256:0e1dd6d449267cc7d6935d7fe27ee0426af6ee16578eed93bacb1be9ff824d2d"}, + {file = "watchdog-2.3.1-py3-none-manylinux2014_i686.whl", hash = "sha256:7a1876f660e32027a1a46f8a0fa5747ad4fcf86cb451860eae61a26e102c8c79"}, + {file = "watchdog-2.3.1-py3-none-manylinux2014_ppc64.whl", hash = "sha256:2caf77ae137935c1466f8cefd4a3aec7017b6969f425d086e6a528241cba7256"}, + {file = "watchdog-2.3.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:53f3e95081280898d9e4fc51c5c69017715929e4eea1ab45801d5e903dd518ad"}, + {file = "watchdog-2.3.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:9da7acb9af7e4a272089bd2af0171d23e0d6271385c51d4d9bde91fe918c53ed"}, + {file = "watchdog-2.3.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:8a4d484e846dcd75e96b96d80d80445302621be40e293bfdf34a631cab3b33dc"}, + {file = "watchdog-2.3.1-py3-none-win32.whl", hash = "sha256:a74155398434937ac2780fd257c045954de5b11b5c52fc844e2199ce3eecf4cf"}, + {file = "watchdog-2.3.1-py3-none-win_amd64.whl", hash = "sha256:5defe4f0918a2a1a4afbe4dbb967f743ac3a93d546ea4674567806375b024adb"}, + {file = "watchdog-2.3.1-py3-none-win_ia64.whl", hash = "sha256:4109cccf214b7e3462e8403ab1e5b17b302ecce6c103eb2fc3afa534a7f27b96"}, + {file = "watchdog-2.3.1.tar.gz", hash = "sha256:d9f9ed26ed22a9d331820a8432c3680707ea8b54121ddcc9dc7d9f2ceeb36906"}, +] +zipp = [ + {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, + {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, +] diff --git a/lib/modules/manager/poetry/__fixtures__/poetry142.lock b/lib/modules/manager/poetry/__fixtures__/poetry142.lock new file mode 100644 index 00000000000000..a0bee059f58a89 --- /dev/null +++ b/lib/modules/manager/poetry/__fixtures__/poetry142.lock @@ -0,0 +1,18 @@ +# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. + +[[package]] +name = "attrs" +version = "22.2.0" +description = "Classes Without Boilerplate" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, + {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.7" +content-hash = "9aaf819933593fe3f84ff37db4ed316090da9b491e66fd5108b2b33f32f683c3" diff --git a/lib/modules/manager/poetry/artifacts.spec.ts b/lib/modules/manager/poetry/artifacts.spec.ts index 733d5ad9870bdc..67cc4098f841dd 100644 --- a/lib/modules/manager/poetry/artifacts.spec.ts +++ b/lib/modules/manager/poetry/artifacts.spec.ts @@ -8,6 +8,7 @@ import * as docker from '../../../util/exec/docker'; import * as _hostRules from '../../../util/host-rules'; import * as _datasource from '../../datasource'; import type { UpdateArtifactsConfig } from '../types'; +import { getPoetryRequirement } from './artifacts'; import { updateArtifacts } from '.'; const pyproject1toml = Fixtures.get('pyproject.1.toml'); @@ -32,419 +33,440 @@ const adminConfig: RepoGlobalConfig = { const config: UpdateArtifactsConfig = {}; describe('modules/manager/poetry/artifacts', () => { - beforeEach(() => { - jest.resetAllMocks(); - env.getChildProcessEnv.mockReturnValue(envMock.basic); - GlobalConfig.set(adminConfig); - docker.resetPrefetchedImages(); - }); + describe('getPoetryRequirement', () => { + const poetry12lock = Fixtures.get('poetry12.lock'); + const poetry142lock = Fixtures.get('poetry142.lock'); - it('returns null if no poetry.lock found', async () => { - const execSnapshots = mockExecAll(); - const updatedDeps = [{ depName: 'dep1' }]; - expect( - await updateArtifacts({ - packageFileName: 'pyproject.toml', - updatedDeps, - newPackageFileContent: '', - config, - }) - ).toBeNull(); - expect(execSnapshots).toEqual([]); - }); + it('detects poetry from first line of poetry.lock', () => { + const pyprojectContent = ''; + expect(getPoetryRequirement(pyprojectContent, poetry142lock)).toBe( + '1.4.2' + ); + }); - it('returns null if updatedDeps is empty', async () => { - const execSnapshots = mockExecAll(); - expect( - await updateArtifacts({ - packageFileName: 'pyproject.toml', - updatedDeps: [], - newPackageFileContent: '', - config, - }) - ).toBeNull(); - expect(execSnapshots).toEqual([]); + it('detects poetry from metadata', () => { + const pyprojectContent = ''; + expect(getPoetryRequirement(pyprojectContent, poetry12lock)).toBe( + '<1.3.0' + ); + }); }); - it('returns null if unchanged', async () => { - const execSnapshots = mockExecAll(); - fs.ensureCacheDir.mockResolvedValueOnce('/tmp/renovate/cache/others/pip'); - fs.readLocalFile.mockResolvedValueOnce('Current poetry.lock'); - fs.readLocalFile.mockResolvedValueOnce('Current poetry.lock'); - const updatedDeps = [{ depName: 'dep1' }]; - expect( - await updateArtifacts({ - packageFileName: 'pyproject.toml', - updatedDeps, - newPackageFileContent: '', - config, - }) - ).toBeNull(); - expect(execSnapshots).toMatchObject([ - { - cmd: 'poetry update --lock --no-interaction dep1', - options: { - cwd: '/tmp/github/some/repo', - env: { PIP_CACHE_DIR: '/tmp/renovate/cache/others/pip' }, - }, - }, - ]); - }); + describe('updateArtifacts', () => { + beforeEach(() => { + jest.resetAllMocks(); + env.getChildProcessEnv.mockReturnValue(envMock.basic); + GlobalConfig.set(adminConfig); + docker.resetPrefetchedImages(); + }); - it('returns updated poetry.lock', async () => { - const execSnapshots = mockExecAll(); - // poetry.lock - fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); - fs.readLocalFile.mockResolvedValueOnce('[metadata]\n'); - fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); - const updatedDeps = [{ depName: 'dep1' }]; - expect( - await updateArtifacts({ - packageFileName: 'pyproject.toml', - updatedDeps, - newPackageFileContent: '{}', - config, - }) - ).toEqual([ - { - file: { - type: 'addition', - path: 'poetry.lock', - contents: 'New poetry.lock', + it('returns null if no poetry.lock found', async () => { + const execSnapshots = mockExecAll(); + const updatedDeps = [{ depName: 'dep1' }]; + expect( + await updateArtifacts({ + packageFileName: 'pyproject.toml', + updatedDeps, + newPackageFileContent: '', + config, + }) + ).toBeNull(); + expect(execSnapshots).toEqual([]); + }); + + it('returns null if updatedDeps is empty', async () => { + const execSnapshots = mockExecAll(); + expect( + await updateArtifacts({ + packageFileName: 'pyproject.toml', + updatedDeps: [], + newPackageFileContent: '', + config, + }) + ).toBeNull(); + expect(execSnapshots).toEqual([]); + }); + + it('returns null if unchanged', async () => { + const execSnapshots = mockExecAll(); + fs.ensureCacheDir.mockResolvedValueOnce('/tmp/renovate/cache/others/pip'); + fs.readLocalFile.mockResolvedValueOnce('Current poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce('Current poetry.lock'); + const updatedDeps = [{ depName: 'dep1' }]; + expect( + await updateArtifacts({ + packageFileName: 'pyproject.toml', + updatedDeps, + newPackageFileContent: '', + config, + }) + ).toBeNull(); + expect(execSnapshots).toMatchObject([ + { + cmd: 'poetry update --lock --no-interaction dep1', + options: { + cwd: '/tmp/github/some/repo', + env: { PIP_CACHE_DIR: '/tmp/renovate/cache/others/pip' }, + }, }, - }, - ]); - expect(execSnapshots).toMatchObject([ - { cmd: 'poetry update --lock --no-interaction dep1' }, - ]); - }); + ]); + }); - it('passes private credential environment vars', async () => { - // poetry.lock - fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); - fs.readLocalFile.mockResolvedValueOnce(null); - // pyproject.lock - fs.getSiblingFileName.mockReturnValueOnce('pyproject.lock'); - fs.readLocalFile.mockResolvedValueOnce('[metadata]\n'); - const execSnapshots = mockExecAll(); - fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); - hostRules.find.mockReturnValueOnce({ - username: 'usernameOne', - password: 'passwordOne', + it('returns updated poetry.lock', async () => { + const execSnapshots = mockExecAll(); + // poetry.lock + fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce('[metadata]\n'); + fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); + const updatedDeps = [{ depName: 'dep1' }]; + expect( + await updateArtifacts({ + packageFileName: 'pyproject.toml', + updatedDeps, + newPackageFileContent: '{}', + config, + }) + ).toEqual([ + { + file: { + type: 'addition', + path: 'poetry.lock', + contents: 'New poetry.lock', + }, + }, + ]); + expect(execSnapshots).toMatchObject([ + { cmd: 'poetry update --lock --no-interaction dep1' }, + ]); }); - hostRules.find.mockReturnValueOnce({ username: 'usernameTwo' }); - hostRules.find.mockReturnValueOnce({}); - hostRules.find.mockReturnValueOnce({ password: 'passwordFour' }); - const updatedDeps = [{ depName: 'dep1' }]; - expect( - await updateArtifacts({ - packageFileName: 'pyproject.toml', - updatedDeps, - newPackageFileContent: pyproject10toml, - config, - }) - ).toEqual([ - { - file: { - type: 'addition', - path: 'pyproject.lock', - contents: 'New poetry.lock', + + it('passes private credential environment vars', async () => { + // poetry.lock + fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce(null); + // pyproject.lock + fs.getSiblingFileName.mockReturnValueOnce('pyproject.lock'); + fs.readLocalFile.mockResolvedValueOnce('[metadata]\n'); + const execSnapshots = mockExecAll(); + fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); + hostRules.find.mockReturnValueOnce({ + username: 'usernameOne', + password: 'passwordOne', + }); + hostRules.find.mockReturnValueOnce({ username: 'usernameTwo' }); + hostRules.find.mockReturnValueOnce({}); + hostRules.find.mockReturnValueOnce({ password: 'passwordFour' }); + const updatedDeps = [{ depName: 'dep1' }]; + expect( + await updateArtifacts({ + packageFileName: 'pyproject.toml', + updatedDeps, + newPackageFileContent: pyproject10toml, + config, + }) + ).toEqual([ + { + file: { + type: 'addition', + path: 'pyproject.lock', + contents: 'New poetry.lock', + }, }, - }, - ]); - expect(hostRules.find.mock.calls).toHaveLength(4); - expect(execSnapshots).toMatchObject([ - { cmd: 'poetry update --lock --no-interaction dep1' }, - ]); - }); + ]); + expect(hostRules.find.mock.calls).toHaveLength(4); + expect(execSnapshots).toMatchObject([ + { cmd: 'poetry update --lock --no-interaction dep1' }, + ]); + }); - it('prioritizes pypi-scoped credentials', async () => { - const execSnapshots = mockExecAll(); - // poetry.lock - fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); - fs.readLocalFile.mockResolvedValueOnce(null); - // pyproject.lock - fs.getSiblingFileName.mockReturnValueOnce('pyproject.lock'); - fs.readLocalFile.mockResolvedValueOnce('[metadata]\n'); - fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); - hostRules.find.mockImplementation((search) => ({ - password: - search.hostType === 'pypi' ? 'scoped-password' : 'unscoped-password', - })); - const updatedDeps = [{ depName: 'dep1' }]; - expect( - await updateArtifacts({ - packageFileName: 'pyproject.toml', - updatedDeps, - newPackageFileContent: ` + it('prioritizes pypi-scoped credentials', async () => { + const execSnapshots = mockExecAll(); + // poetry.lock + fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce(null); + // pyproject.lock + fs.getSiblingFileName.mockReturnValueOnce('pyproject.lock'); + fs.readLocalFile.mockResolvedValueOnce('[metadata]\n'); + fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); + hostRules.find.mockImplementation((search) => ({ + password: + search.hostType === 'pypi' ? 'scoped-password' : 'unscoped-password', + })); + const updatedDeps = [{ depName: 'dep1' }]; + expect( + await updateArtifacts({ + packageFileName: 'pyproject.toml', + updatedDeps, + newPackageFileContent: ` [[tool.poetry.source]] name = "one" url = "some.url" `, - config, - }) - ).toEqual([ - { - file: { - type: 'addition', - path: 'pyproject.lock', - contents: 'New poetry.lock', + config, + }) + ).toEqual([ + { + file: { + type: 'addition', + path: 'pyproject.lock', + contents: 'New poetry.lock', + }, }, - }, - ]); - expect(execSnapshots).toMatchObject([ - { cmd: 'poetry update --lock --no-interaction dep1' }, - ]); - }); + ]); + expect(execSnapshots).toMatchObject([ + { cmd: 'poetry update --lock --no-interaction dep1' }, + ]); + }); - it('returns updated pyproject.lock', async () => { - const execSnapshots = mockExecAll(); - // poetry.lock - fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); - fs.readLocalFile.mockResolvedValueOnce(null); - // pyproject.lock - fs.getSiblingFileName.mockReturnValueOnce('pyproject.lock'); - fs.readLocalFile.mockResolvedValueOnce('[metadata]\n'); - fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); - const updatedDeps = [{ depName: 'dep1' }]; - expect( - await updateArtifacts({ - packageFileName: 'pyproject.toml', - updatedDeps, - newPackageFileContent: '{}', - config, - }) - ).toEqual([ - { - file: { - type: 'addition', - path: 'pyproject.lock', - contents: 'New poetry.lock', + it('returns updated pyproject.lock', async () => { + const execSnapshots = mockExecAll(); + // poetry.lock + fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce(null); + // pyproject.lock + fs.getSiblingFileName.mockReturnValueOnce('pyproject.lock'); + fs.readLocalFile.mockResolvedValueOnce('[metadata]\n'); + fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); + const updatedDeps = [{ depName: 'dep1' }]; + expect( + await updateArtifacts({ + packageFileName: 'pyproject.toml', + updatedDeps, + newPackageFileContent: '{}', + config, + }) + ).toEqual([ + { + file: { + type: 'addition', + path: 'pyproject.lock', + contents: 'New poetry.lock', + }, }, - }, - ]); - expect(execSnapshots).toMatchObject([ - { cmd: 'poetry update --lock --no-interaction dep1' }, - ]); - }); - - it('returns updated poetry.lock using docker', async () => { - GlobalConfig.set({ ...adminConfig, binarySource: 'docker' }); - const execSnapshots = mockExecAll(); - fs.ensureCacheDir.mockResolvedValueOnce('/tmp/renovate/cache/others/pip'); - // poetry.lock - fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); - fs.readLocalFile.mockResolvedValueOnce('[metadata]\n'); - fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); - // python - datasource.getPkgReleases.mockResolvedValueOnce({ - releases: [{ version: '2.7.5' }, { version: '3.4.2' }], - }); - // poetry - datasource.getPkgReleases.mockResolvedValueOnce({ - releases: [{ version: '1.2.0' }], + ]); + expect(execSnapshots).toMatchObject([ + { cmd: 'poetry update --lock --no-interaction dep1' }, + ]); }); - const updatedDeps = [{ depName: 'dep1' }]; - expect( - await updateArtifacts({ - packageFileName: 'pyproject.toml', - updatedDeps, - newPackageFileContent: pyproject1toml, - config: { - ...config, - constraints: { - python: '~2.7 || ^3.4', + + it('returns updated poetry.lock using docker', async () => { + GlobalConfig.set({ ...adminConfig, binarySource: 'docker' }); + const execSnapshots = mockExecAll(); + fs.ensureCacheDir.mockResolvedValueOnce('/tmp/renovate/cache/others/pip'); + // poetry.lock + fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce('[metadata]\n'); + fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); + // python + datasource.getPkgReleases.mockResolvedValueOnce({ + releases: [{ version: '2.7.5' }, { version: '3.4.2' }], + }); + // poetry + datasource.getPkgReleases.mockResolvedValueOnce({ + releases: [{ version: '1.2.0' }], + }); + const updatedDeps = [{ depName: 'dep1' }]; + expect( + await updateArtifacts({ + packageFileName: 'pyproject.toml', + updatedDeps, + newPackageFileContent: pyproject1toml, + config: { + ...config, + constraints: { + python: '~2.7 || ^3.4', + }, + }, + }) + ).toEqual([ + { + file: { + type: 'addition', + path: 'poetry.lock', + contents: 'New poetry.lock', }, }, - }) - ).toEqual([ - { - file: { - type: 'addition', - path: 'poetry.lock', - contents: 'New poetry.lock', + ]); + expect(execSnapshots).toMatchObject([ + { cmd: 'docker pull containerbase/sidecar' }, + { cmd: 'docker ps --filter name=renovate_sidecar -aq' }, + { + cmd: + 'docker run --rm --name=renovate_sidecar --label=renovate_child ' + + '-v "/tmp/github/some/repo":"/tmp/github/some/repo" ' + + '-v "/tmp/cache":"/tmp/cache" ' + + '-e PIP_CACHE_DIR ' + + '-e BUILDPACK_CACHE_DIR ' + + '-e CONTAINERBASE_CACHE_DIR ' + + '-w "/tmp/github/some/repo" ' + + 'containerbase/sidecar ' + + 'bash -l -c "' + + 'install-tool python 3.4.2 ' + + '&& ' + + 'install-tool poetry 1.2.0 ' + + '&& ' + + 'poetry update --lock --no-interaction dep1' + + '"', }, - }, - ]); - expect(execSnapshots).toMatchObject([ - { cmd: 'docker pull containerbase/sidecar' }, - { cmd: 'docker ps --filter name=renovate_sidecar -aq' }, - { - cmd: - 'docker run --rm --name=renovate_sidecar --label=renovate_child ' + - '-v "/tmp/github/some/repo":"/tmp/github/some/repo" ' + - '-v "/tmp/cache":"/tmp/cache" ' + - '-e PIP_CACHE_DIR ' + - '-e BUILDPACK_CACHE_DIR ' + - '-e CONTAINERBASE_CACHE_DIR ' + - '-w "/tmp/github/some/repo" ' + - 'containerbase/sidecar ' + - 'bash -l -c "' + - 'install-tool python 3.4.2 ' + - '&& ' + - 'install-tool poetry 1.2.0 ' + - '&& ' + - 'poetry update --lock --no-interaction dep1' + - '"', - }, - ]); - }); + ]); + }); - it('returns updated poetry.lock using docker (constraints)', async () => { - GlobalConfig.set({ ...adminConfig, binarySource: 'docker' }); - const execSnapshots = mockExecAll(); + it('returns updated poetry.lock using docker (constraints)', async () => { + GlobalConfig.set({ ...adminConfig, binarySource: 'docker' }); + const execSnapshots = mockExecAll(); - fs.ensureCacheDir.mockResolvedValueOnce('/tmp/renovate/cache/others/pip'); - // poetry.lock - fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); - fs.readLocalFile.mockResolvedValueOnce( - '[metadata]\npython-versions = "~2.7 || ^3.4"' - ); - fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); - // python - datasource.getPkgReleases.mockResolvedValueOnce({ - releases: [{ version: '2.7.5' }, { version: '3.3.2' }], - }); - // poetry - datasource.getPkgReleases.mockResolvedValueOnce({ - releases: [{ version: '1.0.0' }, { version: '1.2.0' }], - }); - const updatedDeps = [{ depName: 'dep1' }]; - expect( - await updateArtifacts({ - packageFileName: 'pyproject.toml', - updatedDeps, - newPackageFileContent: pyproject1toml, - config: { - ...config, - constraints: {}, + fs.ensureCacheDir.mockResolvedValueOnce('/tmp/renovate/cache/others/pip'); + // poetry.lock + fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce( + '[metadata]\npython-versions = "~2.7 || ^3.4"' + ); + fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); + // python + datasource.getPkgReleases.mockResolvedValueOnce({ + releases: [{ version: '2.7.5' }, { version: '3.3.2' }], + }); + // poetry + datasource.getPkgReleases.mockResolvedValueOnce({ + releases: [{ version: '1.0.0' }, { version: '1.2.0' }], + }); + const updatedDeps = [{ depName: 'dep1' }]; + expect( + await updateArtifacts({ + packageFileName: 'pyproject.toml', + updatedDeps, + newPackageFileContent: pyproject1toml, + config: { + ...config, + constraints: {}, + }, + }) + ).toEqual([ + { + file: { + type: 'addition', + path: 'poetry.lock', + contents: 'New poetry.lock', + }, }, - }) - ).toEqual([ - { - file: { - type: 'addition', - path: 'poetry.lock', - contents: 'New poetry.lock', + ]); + expect(execSnapshots).toMatchObject([ + { cmd: 'docker pull containerbase/sidecar' }, + { cmd: 'docker ps --filter name=renovate_sidecar -aq' }, + { + cmd: + 'docker run --rm --name=renovate_sidecar --label=renovate_child ' + + '-v "/tmp/github/some/repo":"/tmp/github/some/repo" ' + + '-v "/tmp/cache":"/tmp/cache" ' + + '-e PIP_CACHE_DIR ' + + '-e BUILDPACK_CACHE_DIR ' + + '-e CONTAINERBASE_CACHE_DIR ' + + '-w "/tmp/github/some/repo" ' + + 'containerbase/sidecar ' + + 'bash -l -c "' + + 'install-tool python 2.7.5 ' + + '&& ' + + 'install-tool poetry 1.2.0 ' + + '&& ' + + 'poetry update --lock --no-interaction dep1' + + '"', }, - }, - ]); - expect(execSnapshots).toMatchObject([ - { cmd: 'docker pull containerbase/sidecar' }, - { cmd: 'docker ps --filter name=renovate_sidecar -aq' }, - { - cmd: - 'docker run --rm --name=renovate_sidecar --label=renovate_child ' + - '-v "/tmp/github/some/repo":"/tmp/github/some/repo" ' + - '-v "/tmp/cache":"/tmp/cache" ' + - '-e PIP_CACHE_DIR ' + - '-e BUILDPACK_CACHE_DIR ' + - '-e CONTAINERBASE_CACHE_DIR ' + - '-w "/tmp/github/some/repo" ' + - 'containerbase/sidecar ' + - 'bash -l -c "' + - 'install-tool python 2.7.5 ' + - '&& ' + - 'install-tool poetry 1.2.0 ' + - '&& ' + - 'poetry update --lock --no-interaction dep1' + - '"', - }, - ]); - }); - - it('returns updated poetry.lock using install mode', async () => { - GlobalConfig.set({ ...adminConfig, binarySource: 'install' }); - const execSnapshots = mockExecAll(); - // poetry.lock - fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); - fs.readLocalFile.mockResolvedValueOnce( - '[metadata]\npython-versions = "~2.7 || ^3.4"' - ); - fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); - // python - datasource.getPkgReleases.mockResolvedValueOnce({ - releases: [{ version: '2.7.5' }, { version: '3.3.2' }], + ]); }); - // poetry - datasource.getPkgReleases.mockResolvedValueOnce({ - releases: [{ version: '1.2.0' }], - }); - const updatedDeps = [{ depName: 'dep1' }]; - expect( - await updateArtifacts({ - packageFileName: 'pyproject.toml', - updatedDeps, - newPackageFileContent: pyproject1toml, - config: { - ...config, - constraints: {}, - }, - }) - ).toEqual([ - { - file: { - type: 'addition', - path: 'poetry.lock', - contents: 'New poetry.lock', + + it('returns updated poetry.lock using install mode', async () => { + GlobalConfig.set({ ...adminConfig, binarySource: 'install' }); + const execSnapshots = mockExecAll(); + // poetry.lock + fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce( + '[metadata]\npython-versions = "~2.7 || ^3.4"' + ); + fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); + // python + datasource.getPkgReleases.mockResolvedValueOnce({ + releases: [{ version: '2.7.5' }, { version: '3.3.2' }], + }); + // poetry + datasource.getPkgReleases.mockResolvedValueOnce({ + releases: [{ version: '1.2.0' }], + }); + const updatedDeps = [{ depName: 'dep1' }]; + expect( + await updateArtifacts({ + packageFileName: 'pyproject.toml', + updatedDeps, + newPackageFileContent: pyproject1toml, + config: { + ...config, + constraints: {}, + }, + }) + ).toEqual([ + { + file: { + type: 'addition', + path: 'poetry.lock', + contents: 'New poetry.lock', + }, }, - }, - ]); + ]); - expect(execSnapshots).toMatchObject([ - { cmd: 'install-tool python 2.7.5' }, - { cmd: 'install-tool poetry 1.2.0' }, - { cmd: 'poetry update --lock --no-interaction dep1' }, - ]); - }); + expect(execSnapshots).toMatchObject([ + { cmd: 'install-tool python 2.7.5' }, + { cmd: 'install-tool poetry 1.2.0' }, + { cmd: 'poetry update --lock --no-interaction dep1' }, + ]); + }); - it('catches errors', async () => { - const execSnapshots = mockExecAll(); - // poetry.lock - fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); - fs.readLocalFile.mockResolvedValueOnce('Current poetry.lock'); - fs.writeLocalFile.mockImplementationOnce(() => { - throw new Error('not found'); + it('catches errors', async () => { + const execSnapshots = mockExecAll(); + // poetry.lock + fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce('Current poetry.lock'); + fs.writeLocalFile.mockImplementationOnce(() => { + throw new Error('not found'); + }); + const updatedDeps = [{ depName: 'dep1' }]; + expect( + await updateArtifacts({ + packageFileName: 'pyproject.toml', + updatedDeps, + newPackageFileContent: '{}', + config, + }) + ).toMatchObject([{ artifactError: { lockFile: 'poetry.lock' } }]); + expect(execSnapshots).toMatchObject([]); }); - const updatedDeps = [{ depName: 'dep1' }]; - expect( - await updateArtifacts({ - packageFileName: 'pyproject.toml', - updatedDeps, - newPackageFileContent: '{}', - config, - }) - ).toMatchObject([{ artifactError: { lockFile: 'poetry.lock' } }]); - expect(execSnapshots).toMatchObject([]); - }); - it('returns updated poetry.lock when doing lockfile maintenance', async () => { - const execSnapshots = mockExecAll(); - // poetry.lock - fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); - fs.readLocalFile.mockResolvedValueOnce('Old poetry.lock'); - fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); - expect( - await updateArtifacts({ - packageFileName: 'pyproject.toml', - updatedDeps: [], - newPackageFileContent: '{}', - config: { - ...config, - updateType: 'lockFileMaintenance', - }, - }) - ).toEqual([ - { - file: { - contents: 'New poetry.lock', - path: 'poetry.lock', - type: 'addition', + it('returns updated poetry.lock when doing lockfile maintenance', async () => { + const execSnapshots = mockExecAll(); + // poetry.lock + fs.getSiblingFileName.mockReturnValueOnce('poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce('Old poetry.lock'); + fs.readLocalFile.mockResolvedValueOnce('New poetry.lock'); + expect( + await updateArtifacts({ + packageFileName: 'pyproject.toml', + updatedDeps: [], + newPackageFileContent: '{}', + config: { + ...config, + updateType: 'lockFileMaintenance', + }, + }) + ).toEqual([ + { + file: { + contents: 'New poetry.lock', + path: 'poetry.lock', + type: 'addition', + }, }, - }, - ]); - expect(execSnapshots).toMatchObject([ - { cmd: 'poetry update --lock --no-interaction' }, - ]); + ]); + expect(execSnapshots).toMatchObject([ + { cmd: 'poetry update --lock --no-interaction' }, + ]); + }); }); }); diff --git a/lib/modules/manager/poetry/artifacts.ts b/lib/modules/manager/poetry/artifacts.ts index f0248841a781e9..0bcb3c721830a3 100644 --- a/lib/modules/manager/poetry/artifacts.ts +++ b/lib/modules/manager/poetry/artifacts.ts @@ -17,24 +17,12 @@ import { find } from '../../../util/host-rules'; import { regEx } from '../../../util/regex'; import { PypiDatasource } from '../../datasource/pypi'; import { dependencyPattern } from '../pip_requirements/extract'; -import type { - UpdateArtifact, - UpdateArtifactsConfig, - UpdateArtifactsResult, -} from '../types'; +import type { UpdateArtifact, UpdateArtifactsResult } from '../types'; import type { PoetryFile, PoetryLock, PoetrySource } from './types'; export function getPythonConstraint( - existingLockFileContent: string, - config: UpdateArtifactsConfig + existingLockFileContent: string ): string | undefined | null { - const { constraints = {} } = config; - const { python } = constraints; - - if (python) { - logger.debug('Using python constraint from config'); - return python; - } try { const data = parse(existingLockFileContent) as PoetryLock; if (is.string(data?.metadata?.['python-versions'])) { @@ -48,7 +36,35 @@ export function getPythonConstraint( const pkgValRegex = regEx(`^${dependencyPattern}$`); -export function getPoetryRequirement(pyProjectContent: string): string | null { +const poetryConstraint: Record = { + '1.0': '<1.1.0', + '1.1': '<1.3.0', + '2.0': '>=1.3.0', +}; + +export function getPoetryRequirement( + pyProjectContent: string, + existingLockFileContent: string +): undefined | string | null { + // Read Poetry version from first line of poetry.lock + const firstLine = existingLockFileContent.split('\n')[0]; + const poetryVersionMatch = firstLine.match(/by Poetry ([\d\\.]+)/); + if (poetryVersionMatch?.[1]) { + logger.debug('Using poetry version from poetry.lock header'); + return poetryVersionMatch[1]; + } + try { + const data = parse(existingLockFileContent) as PoetryLock; + const lockVersion = data?.metadata?.['lock-version']; + if (is.string(lockVersion)) { + if (poetryConstraint[lockVersion]) { + logger.debug('Using poetry version from poetry.lock metadata'); + return poetryConstraint[lockVersion]; + } + } + } catch (err) { + // Do nothing + } try { const pyproject: PoetryFile = parse(pyProjectContent); // https://python-poetry.org/docs/pyproject/#poetry-and-pep-517 @@ -173,12 +189,12 @@ export async function updateArtifacts({ .join(' ')}` ); } - const pythonConstraint = getPythonConstraint( - existingLockFileContent, - config - ); + const pythonConstraint = + config?.constraints?.python ?? + getPythonConstraint(existingLockFileContent); const poetryConstraint = - config.constraints?.poetry ?? getPoetryRequirement(newPackageFileContent); + config.constraints?.poetry ?? + getPoetryRequirement(newPackageFileContent, existingLockFileContent); const extraEnv = { ...getSourceCredentialVars(newPackageFileContent, packageFileName), PIP_CACHE_DIR: await ensureCacheDir('pip'), diff --git a/lib/modules/manager/poetry/types.ts b/lib/modules/manager/poetry/types.ts index 6fa510ad515f9c..0c2eaa792548a4 100644 --- a/lib/modules/manager/poetry/types.ts +++ b/lib/modules/manager/poetry/types.ts @@ -40,6 +40,7 @@ export interface PoetryLockSection { export interface PoetryLock { metadata?: { + 'lock-version'?: string; 'python-versions'?: string; }; package?: PoetryLockSection[]; From 06b8dcdca118d8af372b3107d96089f10410b652 Mon Sep 17 00:00:00 2001 From: Marcus Crane Date: Wed, 10 May 2023 17:39:20 +1200 Subject: [PATCH 12/74] feat(platform/github): Skip archived repos at earliest point when retrieving repo listings (#22057) --- lib/modules/platform/github/index.spec.ts | 12 ++++++++++++ lib/modules/platform/github/index.ts | 10 +++++++--- lib/modules/platform/github/types.ts | 1 + 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/modules/platform/github/index.spec.ts b/lib/modules/platform/github/index.spec.ts index 51b25a6d951557..0789f597bcb205 100644 --- a/lib/modules/platform/github/index.spec.ts +++ b/lib/modules/platform/github/index.spec.ts @@ -174,9 +174,15 @@ describe('modules/platform/github/index', () => { .reply(200, [ { full_name: 'a/b', + archived: false, }, { full_name: 'c/d', + archived: false, + }, + { + full_name: 'e/f', + archived: true, }, null, ]); @@ -227,9 +233,15 @@ describe('modules/platform/github/index', () => { repositories: [ { full_name: 'a/b', + archived: false, }, { full_name: 'c/d', + archived: false, + }, + { + full_name: 'e/f', + archived: true, }, null, ], diff --git a/lib/modules/platform/github/index.ts b/lib/modules/platform/github/index.ts index 8f5bdab301d5ab..1fb1e521a00e74 100644 --- a/lib/modules/platform/github/index.ts +++ b/lib/modules/platform/github/index.ts @@ -191,20 +191,24 @@ export async function getRepos(): Promise { try { if (platformConfig.isGHApp) { const res = await githubApi.getJson<{ - repositories: { full_name: string }[]; + repositories: GhRestRepo[]; }>(`installation/repositories?per_page=100`, { paginationField: 'repositories', paginate: 'all', }); return res.body.repositories .filter(is.nonEmptyObject) + .filter((repo) => !repo.archived) .map((repo) => repo.full_name); } else { - const res = await githubApi.getJson<{ full_name: string }[]>( + const res = await githubApi.getJson( `user/repos?per_page=100`, { paginate: 'all' } ); - return res.body.filter(is.nonEmptyObject).map((repo) => repo.full_name); + return res.body + .filter(is.nonEmptyObject) + .filter((repo) => !repo.archived) + .map((repo) => repo.full_name); } } catch (err) /* istanbul ignore next */ { logger.error({ err }, `GitHub getRepos error`); diff --git a/lib/modules/platform/github/types.ts b/lib/modules/platform/github/types.ts index fd06dcf31b2d82..ef01406661370b 100644 --- a/lib/modules/platform/github/types.ts +++ b/lib/modules/platform/github/types.ts @@ -26,6 +26,7 @@ export interface GhRestRepo { owner: { login: string; }; + archived: boolean; } export interface GhRestPr { From bf2f9db59d87f0b07290d4f35ce169c3eb494328 Mon Sep 17 00:00:00 2001 From: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> Date: Wed, 10 May 2023 11:28:57 +0200 Subject: [PATCH 13/74] docs: rewrite local platform (#22067) --- lib/modules/platform/local/index.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/modules/platform/local/index.md b/lib/modules/platform/local/index.md index 7edadcb2770676..15ede0932e21cb 100644 --- a/lib/modules/platform/local/index.md +++ b/lib/modules/platform/local/index.md @@ -1,20 +1,22 @@ # Local -The "local" platform exists to allow users to perform dry runs against the local file system, such as to test out new config. +With the "local" platform you can perform dry runs of Renovate against the local file system. +This can be handy when testing a new Renovate configuration for example. ## Usage -Run `renovate --platform=local` in the directory you want Renovate to run in. -In this mode, Renovate will default to `dryRun=lookup`. -No "repositories" arguments should be provided, as you cannot run against multiple directories or run in the non-working directory. +Run the `renovate --platform=local` command in the directory you want Renovate to run in. +In this mode, Renovate defaults to `dryRun=lookup`. -It is possible to run on both a git and non-git directory. -Config is optional - so it will run either with or without any "repo config" found. +Avoid giving "repositories" arguments, as this command can only run in a _single_ directory, and it can only run in the _current working_ directory. -It does not do any "compare" or before and after analysis - if your purpose is to test a new config then you will need to manually compare. +You may run the command above on "plain" directories, or "Git directories". +You don't need to provide any config, as the command will run with or without "repo config". + +The command doesn't do any "compare" - or before and after analysis - if you want to test a new config then you must manually compare. ## Limitations -- `local>` presets cannot be resolved. Normally these would point to the local platform such as GitHub, but in the case of running locally, it does not exist +- `local>` presets can't be resolved. Normally these would point to the local platform such as GitHub, but in the case of running locally, it does not exist - `baseBranches` are ignored - Branch creation is not supported From eec46d1880b9d972f6d5546cc83451a5b017e5e6 Mon Sep 17 00:00:00 2001 From: Johannes Feichtner <343448+Churro@users.noreply.github.com> Date: Wed, 10 May 2023 21:36:05 +0200 Subject: [PATCH 14/74] feat(gradle/manager): add support for Kotlin objects in `buildSrc` files (#21892) --- lib/modules/manager/gradle/extract.spec.ts | 120 ++++++++++++++++++ lib/modules/manager/gradle/extract.ts | 26 +++- lib/modules/manager/gradle/index.ts | 1 + lib/modules/manager/gradle/parser.spec.ts | 105 ++++++++++++++- lib/modules/manager/gradle/parser.ts | 29 +++++ .../manager/gradle/parser/assignments.ts | 2 +- .../manager/gradle/parser/common.spec.ts | 12 ++ lib/modules/manager/gradle/parser/common.ts | 12 ++ lib/modules/manager/gradle/parser/objects.ts | 54 ++++++++ lib/modules/manager/gradle/utils.ts | 5 + 10 files changed, 358 insertions(+), 8 deletions(-) create mode 100644 lib/modules/manager/gradle/parser/objects.ts diff --git a/lib/modules/manager/gradle/extract.spec.ts b/lib/modules/manager/gradle/extract.spec.ts index e5f314711d3bd6..94c9a4f1b18865 100644 --- a/lib/modules/manager/gradle/extract.spec.ts +++ b/lib/modules/manager/gradle/extract.spec.ts @@ -120,6 +120,126 @@ describe('modules/manager/gradle/extract', () => { ]); }); + it('resolves cross-file Kotlin objects', async () => { + const fsMock = { + 'buildSrc/src/main/kotlin/Deps.kt': codeBlock` + object Libraries { + const val jacksonAnnotations = "com.fasterxml.jackson.core:jackson-annotations:\${Versions.jackson}" + const val rxjava: String = "io.reactivex.rxjava2:rxjava:" + Versions.rxjava + const val jCache = "javax.cache:cache-api:1.1.0" + private const val shadowVersion = "7.1.2" + + object Kotlin { + const val version = GradleDeps.Kotlin.version + const val stdlibJdk = "org.jetbrains.kotlin:kotlin-stdlib:$version" + } + + object Android { + object Tools { + private const val version = "4.1.2" + const val buildGradle = "com.android.tools.build:gradle:$version" + } + } + + val modulePlugins = mapOf( + "shadow" to shadowVersion + ) + + object Test { + private const val version = "1.3.0-rc01" + const val core = "androidx.test:core:\${Test.version}" + + object Espresso { + private const val version = "3.3.0-rc01" + const val espressoCore = "androidx.test.espresso:espresso-core:$version" + } + + object Androidx { + const val coreKtx = "androidx.test:core-ktx:$version" + } + } + } + `, + 'buildSrc/src/main/kotlin/GradleDeps.kt': codeBlock` + object GradleDeps { + object Kotlin { + const val version = "1.8.10" + } + } + `, + 'buildSrc/src/main/kotlin/Versions.kt': codeBlock` + object Versions { + const val jackson = "2.9.10" + const val rxjava: String = "1.2.3" + } + `, + }; + mockFs(fsMock); + + const res = await extractAllPackageFiles( + partial(), + Object.keys(fsMock) + ); + + expect(res).toMatchObject([ + { + packageFile: 'buildSrc/src/main/kotlin/Deps.kt', + deps: [ + { + depName: 'javax.cache:cache-api', + currentValue: '1.1.0', + groupName: 'Libraries.jCache', + }, + { + depName: 'com.android.tools.build:gradle', + currentValue: '4.1.2', + groupName: 'Libraries.Android.Tools.version', + }, + { + depName: 'androidx.test:core', + currentValue: '1.3.0-rc01', + groupName: 'Libraries.Test.version', + }, + { + depName: 'androidx.test.espresso:espresso-core', + currentValue: '3.3.0-rc01', + groupName: 'Libraries.Test.Espresso.version', + }, + { + depName: 'androidx.test:core-ktx', + currentValue: '1.3.0-rc01', + groupName: 'Libraries.Test.version', + }, + ], + }, + { + packageFile: 'buildSrc/src/main/kotlin/GradleDeps.kt', + deps: [ + { + depName: 'org.jetbrains.kotlin:kotlin-stdlib', + currentValue: '1.8.10', + groupName: 'GradleDeps.Kotlin.version', + }, + ], + }, + { + packageFile: 'buildSrc/src/main/kotlin/Versions.kt', + deps: [ + { + depName: 'com.fasterxml.jackson.core:jackson-annotations', + currentValue: '2.9.10', + groupName: 'Versions.jackson', + }, + { + depName: 'io.reactivex.rxjava2:rxjava', + currentValue: '1.2.3', + groupName: 'Versions.rxjava', + }, + ], + }, + ]); + }); + it('inherits gradle variables', async () => { const fsMock = { 'gradle.properties': 'foo=1.0.0', diff --git a/lib/modules/manager/gradle/extract.ts b/lib/modules/manager/gradle/extract.ts index e0a76398b747fa..a75d6a9098b430 100644 --- a/lib/modules/manager/gradle/extract.ts +++ b/lib/modules/manager/gradle/extract.ts @@ -9,7 +9,7 @@ import { parseGcv, usesGcv, } from './extract/consistent-versions-plugin'; -import { parseGradle, parseProps } from './parser'; +import { parseGradle, parseKotlinSource, parseProps } from './parser'; import { REGISTRY_URLS } from './parser/common'; import type { GradleManagerData, @@ -19,6 +19,7 @@ import type { import { getVars, isGradleScriptFile, + isKotlinSourceFile, isPropsFile, isTOMLFile, reorderFiles, @@ -94,6 +95,15 @@ async function parsePackageFiles( ) { const deps = parseGcv(packageFile, fileContents); extractedDeps.push(...deps); + } else if (isKotlinSourceFile(packageFile)) { + const vars = getVars(varRegistry, packageFileDir); + const { vars: gradleVars, deps } = parseKotlinSource( + content, + vars, + packageFile + ); + updateVars(varRegistry, '/', gradleVars); + extractedDeps.push(...deps); } else if (isGradleScriptFile(packageFile)) { const vars = getVars(varRegistry, packageFileDir); const { @@ -123,11 +133,14 @@ export async function extractAllPackageFiles( const packageFilesByName: Record = {}; const packageRegistries: PackageRegistry[] = []; const extractedDeps: PackageDependency[] = []; - const gradleFiles = reorderFiles(packageFiles); + const kotlinSourceFiles = packageFiles.filter(isKotlinSourceFile); + const gradleFiles = reorderFiles( + packageFiles.filter((e) => !kotlinSourceFiles.includes(e)) + ); await parsePackageFiles( config, - gradleFiles, + [...kotlinSourceFiles, ...kotlinSourceFiles, ...gradleFiles], extractedDeps, packageFilesByName, packageRegistries @@ -161,9 +174,10 @@ export async function extractAllPackageFiles( dep.registryUrls = getRegistryUrlsForDep(packageRegistries, dep); if (!dep.depType) { - dep.depType = key.startsWith('buildSrc') - ? 'devDependencies' - : 'dependencies'; + dep.depType = + key.startsWith('buildSrc') && !kotlinSourceFiles.length + ? 'devDependencies' + : 'dependencies'; } } diff --git a/lib/modules/manager/gradle/index.ts b/lib/modules/manager/gradle/index.ts index ad83ff7f60ba5d..82419fa6f81868 100644 --- a/lib/modules/manager/gradle/index.ts +++ b/lib/modules/manager/gradle/index.ts @@ -14,6 +14,7 @@ export const defaultConfig = { '\\.gradle(\\.kts)?$', '(^|/)gradle\\.properties$', '(^|/)gradle/.+\\.toml$', + '(^|/)buildSrc/.+\\.kt$', '\\.versions\\.toml$', // The two below is for gradle-consistent-versions plugin `(^|/)versions.props$`, diff --git a/lib/modules/manager/gradle/parser.spec.ts b/lib/modules/manager/gradle/parser.spec.ts index 4cf790ce64404f..fe948df16dd442 100644 --- a/lib/modules/manager/gradle/parser.spec.ts +++ b/lib/modules/manager/gradle/parser.spec.ts @@ -2,7 +2,7 @@ import is from '@sindresorhus/is'; import { codeBlock } from 'common-tags'; import { Fixtures } from '../../../../test/fixtures'; import { fs, logger } from '../../../../test/util'; -import { parseGradle, parseProps } from './parser'; +import { parseGradle, parseKotlinSource, parseProps } from './parser'; import { GRADLE_PLUGINS, REGISTRY_URLS } from './parser/common'; jest.mock('../../../util/fs'); @@ -930,4 +930,107 @@ describe('modules/manager/gradle/parser', () => { expect(deps).toMatchObject([output].filter(is.truthy)); }); }); + + describe('Kotlin object notation', () => { + it('simple objects', () => { + const input = codeBlock` + object Versions { + const val baz = "1.2.3" + } + + object Libraries { + val deps = mapOf("api" to "org.slf4j:slf4j-api:\${Versions.baz}") + val dep: String = "foo:bar:" + Versions.baz + } + `; + + const res = parseKotlinSource(input); + expect(res).toMatchObject({ + vars: { + 'Versions.baz': { + key: 'Versions.baz', + value: '1.2.3', + }, + }, + deps: [ + { + depName: 'org.slf4j:slf4j-api', + groupName: 'Versions.baz', + currentValue: '1.2.3', + }, + { + depName: 'foo:bar', + groupName: 'Versions.baz', + currentValue: '1.2.3', + }, + ], + }); + }); + + it('nested objects', () => { + const input = codeBlock` + object Deps { + const val kotlinVersion = "1.5.31" + + object Kotlin { + val stdlib = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:\${Deps.kotlinVersion}" + } + + object Test { + private const val version = "1.3.0-rc01" + const val core = "androidx.test:core:\${Deps.Test.version}" + + object Espresso { + private const val version = "3.3.0-rc01" + const val espressoCore = "androidx.test.espresso:espresso-core:$version" + } + + object Androidx { + const val coreKtx = "androidx.test:core-ktx:$version" + } + } + } + `; + + const res = parseKotlinSource(input); + expect(res).toMatchObject({ + vars: { + 'Deps.kotlinVersion': { + key: 'Deps.kotlinVersion', + value: '1.5.31', + }, + 'Deps.Test.version': { + key: 'Deps.Test.version', + value: '1.3.0-rc01', + }, + 'Deps.Test.Espresso.version': { + key: 'Deps.Test.Espresso.version', + value: '3.3.0-rc01', + }, + }, + deps: [ + { + depName: 'org.jetbrains.kotlin:kotlin-stdlib-jdk7', + currentValue: '1.5.31', + groupName: 'Deps.kotlinVersion', + }, + { + depName: 'androidx.test:core', + currentValue: '1.3.0-rc01', + groupName: 'Deps.Test.version', + }, + { + depName: 'androidx.test.espresso:espresso-core', + currentValue: '3.3.0-rc01', + groupName: 'Deps.Test.Espresso.version', + }, + { + depName: 'androidx.test:core-ktx', + currentValue: '1.3.0-rc01', + groupName: 'Deps.Test.version', + }, + ], + }); + }); + }); }); diff --git a/lib/modules/manager/gradle/parser.ts b/lib/modules/manager/gradle/parser.ts index 1d4d3914b989eb..a3824ed8a2d0e7 100644 --- a/lib/modules/manager/gradle/parser.ts +++ b/lib/modules/manager/gradle/parser.ts @@ -5,6 +5,7 @@ import { qApplyFrom } from './parser/apply-from'; import { qAssignments } from './parser/assignments'; import { qDependencies, qLongFormDep } from './parser/dependencies'; import { setParseGradleFunc } from './parser/handlers'; +import { qKotlinMultiObjectVarAssignment } from './parser/objects'; import { qPlugins } from './parser/plugins'; import { qRegistryUrls } from './parser/registry-urls'; import { qVersionCatalogs } from './parser/version-catalogs'; @@ -77,6 +78,34 @@ export function parseGradle( return { deps, urls, vars }; } +export function parseKotlinSource( + input: string, + initVars: PackageVariables = {}, + packageFile = '' +): { vars: PackageVariables; deps: PackageDependency[] } { + let vars: PackageVariables = { ...initVars }; + const deps: PackageDependency[] = []; + + const query = q.tree({ + type: 'root-tree', + maxDepth: 1, + search: qKotlinMultiObjectVarAssignment, + }); + + const parsedResult = groovy.query(input, query, { + ...ctx, + packageFile, + globalVars: vars, + }); + + if (parsedResult) { + deps.push(...parsedResult.deps); + vars = { ...vars, ...parsedResult.globalVars }; + } + + return { deps, vars }; +} + const propWord = '[a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*)*'; const propRegex = regEx( `^(?\\s*(?${propWord})\\s*[= :]\\s*['"]?)(?[^\\s'"]+)['"]?\\s*$` diff --git a/lib/modules/manager/gradle/parser/assignments.ts b/lib/modules/manager/gradle/parser/assignments.ts index 91da408fb475c8..424be4895e8c80 100644 --- a/lib/modules/manager/gradle/parser/assignments.ts +++ b/lib/modules/manager/gradle/parser/assignments.ts @@ -138,7 +138,7 @@ const qKotlinMapOfExpr = ( ); // val versions = mapOf("foo1" to "bar1", "foo2" to "bar2", "foo3" to "bar3") -const qKotlinMultiMapOfVarAssignment = qVariableAssignmentIdentifier +export const qKotlinMultiMapOfVarAssignment = qVariableAssignmentIdentifier .op('=') .sym('mapOf') .tree({ diff --git a/lib/modules/manager/gradle/parser/common.spec.ts b/lib/modules/manager/gradle/parser/common.spec.ts index 77a7df15e851c5..6915f7339d4b3a 100644 --- a/lib/modules/manager/gradle/parser/common.spec.ts +++ b/lib/modules/manager/gradle/parser/common.spec.ts @@ -121,11 +121,23 @@ describe('modules/manager/gradle/parser/common', () => { }); it('findVariable', () => { + ctx.tmpNestingDepth = [token, token]; ctx.globalVars = { foo: { key: 'foo', value: 'bar' }, + 'test.foo': { key: 'test.foo', value: 'bar2' }, + 'test.test.foo3': { key: 'test.test.foo3', value: 'bar3' }, }; expect(findVariable('unknown-global-var', ctx)).toBeUndefined(); + expect(findVariable('foo3', ctx)).toStrictEqual( + ctx.globalVars['test.test.foo3'] + ); + expect(findVariable('test.foo', ctx)).toStrictEqual( + ctx.globalVars['test.foo'] + ); + expect(findVariable('foo', ctx)).toStrictEqual(ctx.globalVars['test.foo']); + + ctx.tmpNestingDepth = []; expect(findVariable('foo', ctx)).toStrictEqual(ctx.globalVars['foo']); }); diff --git a/lib/modules/manager/gradle/parser/common.ts b/lib/modules/manager/gradle/parser/common.ts index 6379bb5644893c..6f92589544e793 100644 --- a/lib/modules/manager/gradle/parser/common.ts +++ b/lib/modules/manager/gradle/parser/common.ts @@ -116,6 +116,18 @@ export function findVariable( ctx: Ctx, variables: PackageVariables = ctx.globalVars ): VariableData | undefined { + if (ctx.tmpNestingDepth.length) { + const prefixParts = ctx.tmpNestingDepth.map((token) => token.value); + for (let idx = ctx.tmpNestingDepth.length; idx > 0; idx -= 1) { + const prefix = prefixParts.slice(0, idx).join('.'); + const identifier = `${prefix}.${name}`; + + if (variables[identifier]) { + return variables[identifier]; + } + } + } + return variables[name]; } diff --git a/lib/modules/manager/gradle/parser/objects.ts b/lib/modules/manager/gradle/parser/objects.ts new file mode 100644 index 00000000000000..b1d0f0c862e358 --- /dev/null +++ b/lib/modules/manager/gradle/parser/objects.ts @@ -0,0 +1,54 @@ +import { parser, query as q } from 'good-enough-parser'; +import type { Ctx } from '../types'; +import { qKotlinMultiMapOfVarAssignment } from './assignments'; +import { + cleanupTempVars, + coalesceVariable, + increaseNestingDepth, + prependNestingDepth, + qValueMatcher, + qVariableAssignmentIdentifier, + reduceNestingDepth, + storeInTokenMap, + storeVarToken, +} from './common'; +import { handleAssignment } from './handlers'; + +const qKotlinSingleObjectVarAssignment = q.alt( + // val dep = mapOf("qux" to "foo:bar:\${Versions.baz}") + qKotlinMultiMapOfVarAssignment, + // val dep: String = "foo:bar:" + Versions.baz + qVariableAssignmentIdentifier + .opt(q.op(':').sym('String')) + .op('=') + .handler(prependNestingDepth) + .handler(coalesceVariable) + .handler((ctx) => storeInTokenMap(ctx, 'keyToken')) + .join(qValueMatcher) + .handler((ctx) => storeInTokenMap(ctx, 'valToken')) + .handler(handleAssignment) + .handler(cleanupTempVars) +); + +// object foo { ... } +const qKotlinMultiObjectExpr = ( + search: q.QueryBuilder +): q.QueryBuilder => + q.alt( + q.sym('object').sym(storeVarToken).tree({ + type: 'wrapped-tree', + maxDepth: 1, + startsWith: '{', + endsWith: '}', + preHandler: increaseNestingDepth, + search, + postHandler: reduceNestingDepth, + }), + qKotlinSingleObjectVarAssignment + ); + +export const qKotlinMultiObjectVarAssignment = qKotlinMultiObjectExpr( + qKotlinMultiObjectExpr( + qKotlinMultiObjectExpr(qKotlinSingleObjectVarAssignment) + ) +).handler(cleanupTempVars); diff --git a/lib/modules/manager/gradle/utils.ts b/lib/modules/manager/gradle/utils.ts index bed8720663dc5f..06b8476d8d5572 100644 --- a/lib/modules/manager/gradle/utils.ts +++ b/lib/modules/manager/gradle/utils.ts @@ -113,6 +113,11 @@ export function isPropsFile(path: string): boolean { return filename === 'gradle.properties'; } +export function isKotlinSourceFile(path: string): boolean { + const filename = upath.basename(path).toLowerCase(); + return filename.endsWith('.kt'); +} + export function isTOMLFile(path: string): boolean { const filename = upath.basename(path).toLowerCase(); return filename.endsWith('.toml'); From 08233ff7054a87608f704edeaaa1f93b0093c73f Mon Sep 17 00:00:00 2001 From: horihel Date: Thu, 11 May 2023 07:15:33 +0200 Subject: [PATCH 15/74] feat(platform/azure): Recreate Auto-Approve on PR-Update (#22028) Signed-off-by: Heiko Helmle Co-authored-by: Jamie Magee Co-authored-by: Rhys Arkins --- .../azure/__snapshots__/index.spec.ts.snap | 10 +++-- lib/modules/platform/azure/index.spec.ts | 39 ++++++++++++++++++- lib/modules/platform/azure/index.ts | 16 ++++++++ 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/lib/modules/platform/azure/__snapshots__/index.spec.ts.snap b/lib/modules/platform/azure/__snapshots__/index.spec.ts.snap index 21858fbbb4b3cc..3be9ce9411245c 100644 --- a/lib/modules/platform/azure/__snapshots__/index.spec.ts.snap +++ b/lib/modules/platform/azure/__snapshots__/index.spec.ts.snap @@ -274,7 +274,7 @@ exports[`modules/platform/azure/index initRepo should initialise the config for } `; -exports[`modules/platform/azure/index updatePr(prNo, title, body) should close the PR 1`] = ` +exports[`modules/platform/azure/index updatePr(prNo, title, body, platformOptions) should close the PR 1`] = ` [ [ { @@ -288,7 +288,9 @@ exports[`modules/platform/azure/index updatePr(prNo, title, body) should close t ] `; -exports[`modules/platform/azure/index updatePr(prNo, title, body) should reopen the PR 1`] = ` +exports[`modules/platform/azure/index updatePr(prNo, title, body, platformOptions) should re-approve the PR 1`] = `undefined`; + +exports[`modules/platform/azure/index updatePr(prNo, title, body, platformOptions) should reopen the PR 1`] = ` [ [ { @@ -308,7 +310,7 @@ exports[`modules/platform/azure/index updatePr(prNo, title, body) should reopen ] `; -exports[`modules/platform/azure/index updatePr(prNo, title, body) should update the PR 1`] = ` +exports[`modules/platform/azure/index updatePr(prNo, title, body, platformOptions) should update the PR 1`] = ` [ [ { @@ -321,7 +323,7 @@ exports[`modules/platform/azure/index updatePr(prNo, title, body) should update ] `; -exports[`modules/platform/azure/index updatePr(prNo, title, body) should update the PR without description 1`] = ` +exports[`modules/platform/azure/index updatePr(prNo, title, body, platformOptions) should update the PR without description 1`] = ` [ [ { diff --git a/lib/modules/platform/azure/index.spec.ts b/lib/modules/platform/azure/index.spec.ts index da8a998a7b702e..29493cd2421217 100644 --- a/lib/modules/platform/azure/index.spec.ts +++ b/lib/modules/platform/azure/index.spec.ts @@ -812,7 +812,7 @@ describe('modules/platform/azure/index', () => { }); }); - describe('updatePr(prNo, title, body)', () => { + describe('updatePr(prNo, title, body, platformOptions)', () => { it('should update the PR', async () => { await initRepo({ repository: 'some/repo' }); const updatePullRequest = jest.fn(); @@ -881,6 +881,43 @@ describe('modules/platform/azure/index', () => { }); expect(updatePullRequest.mock.calls).toMatchSnapshot(); }); + + it('should re-approve the PR', async () => { + await initRepo({ repository: 'some/repo' }); + const prResult = { + pullRequestId: 456, + createdBy: { + id: 123, + url: 'user-url', + }, + }; + const prUpdateResult = { + reviewerUrl: prResult.createdBy.url, + vote: AzurePrVote.Approved, + isFlagged: false, + isRequired: false, + }; + const updateFn = jest.fn(() => prUpdateResult); + azureApi.gitApi.mockImplementationOnce( + () => + ({ + updatePullRequest: jest.fn(() => prResult), + createPullRequestReviewer: updateFn, + getPullRequestById: jest.fn(() => ({ + pullRequestId: prResult.pullRequestId, + createdBy: prResult.createdBy, + })), + } as any) + ); + const pr = await azure.updatePr({ + number: prResult.pullRequestId, + prTitle: 'The Title', + prBody: 'Hello world', + platformOptions: { autoApprove: true }, + }); + expect(updateFn).toHaveBeenCalled(); + expect(pr).toMatchSnapshot(); + }); }); describe('ensureComment', () => { diff --git a/lib/modules/platform/azure/index.ts b/lib/modules/platform/azure/index.ts index b1eb1430369d14..f5b39106638bb2 100644 --- a/lib/modules/platform/azure/index.ts +++ b/lib/modules/platform/azure/index.ts @@ -506,6 +506,7 @@ export async function updatePr({ prTitle: title, prBody: body, state, + platformOptions, }: UpdatePrConfig): Promise { logger.debug(`updatePr(${prNo}, ${title}, body)`); @@ -527,6 +528,21 @@ export async function updatePr({ } else if (state === 'closed') { objToUpdate.status = PullRequestStatus.Abandoned; } + if (platformOptions?.autoApprove) { + const pr = await azureApiGit.getPullRequestById(prNo, config.project); + await azureApiGit.createPullRequestReviewer( + { + reviewerUrl: pr.createdBy!.url, + vote: AzurePrVote.Approved, + isFlagged: false, + isRequired: false, + }, + config.repoId, + // TODO #7154 + pr.pullRequestId!, + pr.createdBy!.id! + ); + } await azureApiGit.updatePullRequest(objToUpdate, config.repoId, prNo); } From b5d87c67b368610fd5c95d1740725578bec74249 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Thu, 11 May 2023 09:40:02 +0200 Subject: [PATCH 16/74] fix(regex): limit regex manager iterations to 10k to avoid OoM (#22084) --- lib/modules/manager/regex/utils.spec.ts | 14 ++++++++++++++ lib/modules/manager/regex/utils.ts | 8 +++++++- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 lib/modules/manager/regex/utils.spec.ts diff --git a/lib/modules/manager/regex/utils.spec.ts b/lib/modules/manager/regex/utils.spec.ts new file mode 100644 index 00000000000000..8e40e3a5ff69db --- /dev/null +++ b/lib/modules/manager/regex/utils.spec.ts @@ -0,0 +1,14 @@ +import { regEx } from '../../../util/regex'; +import * as utils from './utils'; + +describe('modules/manager/regex/utils', () => { + it('does not crash for lazy regex', () => { + const lazyMatch = regEx('(?.*?)', 'g'); + expect( + utils.regexMatchAll( + lazyMatch, + '1f699d2bfc99bbbe4c1ed5bb8fc21e6911d69c6e\n' + ) + ).toBeArray(); + }); +}); diff --git a/lib/modules/manager/regex/utils.ts b/lib/modules/manager/regex/utils.ts index 8f9a2743fcd219..ca5470b9f0d37f 100644 --- a/lib/modules/manager/regex/utils.ts +++ b/lib/modules/manager/regex/utils.ts @@ -85,12 +85,18 @@ export function regexMatchAll( ): RegExpMatchArray[] { const matches: RegExpMatchArray[] = []; let matchResult: RegExpMatchArray | null; + let iterations = 0; + const maxIterations = 10000; do { matchResult = regex.exec(content); if (matchResult) { matches.push(matchResult); } - } while (matchResult); + iterations += 1; + } while (matchResult && iterations < maxIterations); + if (iterations === maxIterations) { + logger.warn('Max iterations reached for matchStrings'); + } return matches; } From ebf064e75bf98b01b59c37d62212fb2388fcd8aa Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Thu, 11 May 2023 04:26:59 -0600 Subject: [PATCH 17/74] chore(utils/array): add isNotNullOrUndefined (#22081) --- lib/util/array.spec.ts | 12 ++++++++++++ lib/util/array.ts | 9 +++++++++ 2 files changed, 21 insertions(+) create mode 100644 lib/util/array.spec.ts diff --git a/lib/util/array.spec.ts b/lib/util/array.spec.ts new file mode 100644 index 00000000000000..57356be7de65df --- /dev/null +++ b/lib/util/array.spec.ts @@ -0,0 +1,12 @@ +import { isNotNullOrUndefined } from './array'; + +describe('util/array', () => { + it.each` + a | exp + ${null} | ${false} + ${undefined} | ${false} + ${{ name: 'foo' }} | ${true} + `('.isNotNullOrUndefined', ({ a, exp }) => { + expect(isNotNullOrUndefined(a)).toEqual(exp); + }); +}); diff --git a/lib/util/array.ts b/lib/util/array.ts index 6862260bc20bc5..0175fabf26f8e4 100644 --- a/lib/util/array.ts +++ b/lib/util/array.ts @@ -10,3 +10,12 @@ export function coerceArray(input: T[] | null | undefined): T[] { export function sortNumeric(a: number, b: number): number { return a - b; } + +// Useful for filtering an array so that it includes values that are not null or +// undefined. This predicate acts as a type guard so that the resulting type for +// `values.filter(isNotNullOrUndefined)` is `T[]`. +export function isNotNullOrUndefined( + value: T | undefined | null +): value is T { + return !is.nullOrUndefined(value); +} From a2e036e3349d1712cc0027919b7b1bda5401141b Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Thu, 11 May 2023 11:00:20 -0400 Subject: [PATCH 18/74] feat(vulnerabilities): set, maintain and expose vulnerabilitySeverity for templated fields (#21939) --- lib/config/index.spec.ts | 55 ++++---- lib/config/types.ts | 3 + lib/config/utils.ts | 11 ++ lib/modules/manager/types.ts | 1 + lib/util/template/index.ts | 3 + lib/util/vulnerability/utils.spec.ts | 129 ++++++++++++++++++ lib/util/vulnerability/utils.ts | 26 ++++ lib/workers/repository/process/types.ts | 6 + .../repository/process/vulnerabilities.ts | 73 +++++++--- 9 files changed, 264 insertions(+), 43 deletions(-) create mode 100644 lib/util/vulnerability/utils.spec.ts create mode 100644 lib/util/vulnerability/utils.ts diff --git a/lib/config/index.spec.ts b/lib/config/index.spec.ts index 41deb82830f776..001ea8c8b53488 100644 --- a/lib/config/index.spec.ts +++ b/lib/config/index.spec.ts @@ -1,4 +1,5 @@ import { getConfig } from './defaults'; +import { filterConfig, getManagerConfig, mergeChildConfig } from './index'; jest.mock('../modules/datasource/npm'); try { @@ -11,7 +12,7 @@ const defaultConfig = getConfig(); describe('config/index', () => { describe('mergeChildConfig(parentConfig, childConfig)', () => { - it('merges', async () => { + it('merges', () => { const parentConfig = { ...defaultConfig }; const childConfig = { foo: 'bar', @@ -20,15 +21,14 @@ describe('config/index', () => { schedule: ['on monday'], }, }; - const configParser = await import('./index'); - const config = configParser.mergeChildConfig(parentConfig, childConfig); + const config = mergeChildConfig(parentConfig, childConfig); expect(config.foo).toBe('bar'); expect(config.rangeStrategy).toBe('replace'); expect(config.lockFileMaintenance.schedule).toEqual(['on monday']); expect(config.lockFileMaintenance).toMatchSnapshot(); }); - it('merges packageRules', async () => { + it('merges packageRules', () => { const parentConfig = { ...defaultConfig }; Object.assign(parentConfig, { packageRules: [{ a: 1 }, { a: 2 }], @@ -36,14 +36,13 @@ describe('config/index', () => { const childConfig = { packageRules: [{ a: 3 }, { a: 4 }], }; - const configParser = await import('./index'); - const config = configParser.mergeChildConfig(parentConfig, childConfig); + const config = mergeChildConfig(parentConfig, childConfig); expect(config.packageRules.map((rule) => rule.a)).toMatchObject([ 1, 2, 3, 4, ]); }); - it('merges constraints', async () => { + it('merges constraints', () => { const parentConfig = { ...defaultConfig }; Object.assign(parentConfig, { constraints: { @@ -56,8 +55,7 @@ describe('config/index', () => { node: '<15', }, }; - const configParser = await import('./index'); - const config = configParser.mergeChildConfig(parentConfig, childConfig); + const config = mergeChildConfig(parentConfig, childConfig); expect(config.constraints).toMatchSnapshot(); expect(config.constraints.node).toBe('<15'); }); @@ -75,39 +73,48 @@ describe('config/index', () => { expect(config.packageRules).toHaveLength(2); }); - it('handles null child packageRules', async () => { + it('handles null child packageRules', () => { const parentConfig = { ...defaultConfig }; parentConfig.packageRules = [{ a: 3 }, { a: 4 }]; - const configParser = await import('./index'); - const config = configParser.mergeChildConfig(parentConfig, {}); + const config = mergeChildConfig(parentConfig, {}); expect(config.packageRules).toHaveLength(2); }); - it('handles undefined childConfig', async () => { + it('handles undefined childConfig', () => { const parentConfig = { ...defaultConfig }; - const configParser = await import('./index'); - const config = configParser.mergeChildConfig(parentConfig, undefined); + const config = mergeChildConfig(parentConfig, undefined); expect(config).toMatchObject(parentConfig); }); - it('getManagerConfig()', async () => { + it('getManagerConfig()', () => { const parentConfig = { ...defaultConfig }; - const configParser = await import('./index'); - const config = configParser.getManagerConfig(parentConfig, 'npm'); + const config = getManagerConfig(parentConfig, 'npm'); expect(config).toContainEntries([ ['fileMatch', ['(^|/)package\\.json$']], ['rollbackPrs', true], ]); - expect( - configParser.getManagerConfig(parentConfig, 'html') - ).toContainEntries([['fileMatch', ['\\.html?$']]]); + expect(getManagerConfig(parentConfig, 'html')).toContainEntries([ + ['fileMatch', ['\\.html?$']], + ]); }); - it('filterConfig()', async () => { + it('filterConfig()', () => { const parentConfig = { ...defaultConfig }; - const configParser = await import('./index'); - const config = configParser.filterConfig(parentConfig, 'pr'); + const config = filterConfig(parentConfig, 'pr'); expect(config).toBeObject(); }); + + it('highest vulnerabilitySeverity maintained when config is vulnerability alert', () => { + const parentConfig = { ...defaultConfig }; + Object.assign(parentConfig, { + isVulnerabilityAlert: true, + vulnerabilitySeverity: 'HIGH', + }); + const childConfig = { + vulnerabilitySeverity: 'CRITICAL', + }; + const config = mergeChildConfig(parentConfig, childConfig); + expect(config.vulnerabilitySeverity).toBe('CRITICAL'); + }); }); }); diff --git a/lib/config/types.ts b/lib/config/types.ts index 0df00b27a9a688..4286c5a512e242 100644 --- a/lib/config/types.ts +++ b/lib/config/types.ts @@ -251,6 +251,7 @@ export interface RenovateConfig warnings?: ValidationMessage[]; vulnerabilityAlerts?: RenovateSharedConfig; osvVulnerabilityAlerts?: boolean; + vulnerabilitySeverity?: string; regexManagers?: RegExManager[]; fetchReleaseNotes?: boolean; @@ -309,6 +310,7 @@ export interface PackageRule UpdateConfig, Record { description?: string | string[]; + isVulnerabilityAlert?: boolean; matchFiles?: string[]; matchPaths?: string[]; matchLanguages?: string[]; @@ -333,6 +335,7 @@ export interface PackageRule matchUpdateTypes?: UpdateType[]; matchConfidence?: MergeConfidence[]; registryUrls?: string[] | null; + vulnerabilitySeverity?: string; } export interface ValidationMessage { diff --git a/lib/config/utils.ts b/lib/config/utils.ts index 106d9e168f1453..140d5f0df030a6 100644 --- a/lib/config/utils.ts +++ b/lib/config/utils.ts @@ -1,4 +1,5 @@ import { logger } from '../logger'; +import { getHighestVulnerabilitySeverity } from '../util/vulnerability/utils'; import * as options from './options'; import type { RenovateConfig } from './types'; @@ -13,6 +14,15 @@ export function mergeChildConfig< const parentConfig = structuredClone(parent); const childConfig = structuredClone(child); const config: Record = { ...parentConfig, ...childConfig }; + + // Ensure highest severity survives parent / child merge + if (config?.isVulnerabilityAlert) { + config.vulnerabilitySeverity = getHighestVulnerabilitySeverity( + parent, + child + ); + } + for (const option of options.getOptions()) { if ( option.mergeable && @@ -20,6 +30,7 @@ export function mergeChildConfig< parentConfig[option.name] ) { logger.trace(`mergeable option: ${option.name}`); + if (option.name === 'constraints') { config[option.name] = { ...parentConfig[option.name], diff --git a/lib/modules/manager/types.ts b/lib/modules/manager/types.ts index 6e26451238eff8..dfb040005aaee0 100644 --- a/lib/modules/manager/types.ts +++ b/lib/modules/manager/types.ts @@ -174,6 +174,7 @@ export interface Upgrade> extends PackageDependency { isLockFileMaintenance?: boolean; isRemediation?: boolean; isVulnerabilityAlert?: boolean; + vulnerabilitySeverity?: string; registryUrls?: string[] | null; currentVersion?: string; replaceString?: string; diff --git a/lib/util/template/index.ts b/lib/util/template/index.ts index f3e4a8809c7e6f..da16eaa90f8cfd 100644 --- a/lib/util/template/index.ts +++ b/lib/util/template/index.ts @@ -100,6 +100,7 @@ export const allowedFields = { isRange: 'true if the new value is a range', isSingleVersion: 'true if the upgrade is to a single version rather than a range', + isVulnerabilityAlert: 'true if the upgrade is a vulnerability alert', logJSON: 'ChangeLogResult object for the upgrade', manager: 'The (package) manager which detected the dependency', newDigest: 'The new digest value', @@ -143,6 +144,8 @@ export const allowedFields = { version: 'The version number of the changelog', versioning: 'The versioning scheme in use', versions: 'An array of ChangeLogRelease objects in the upgrade', + vulnerabilitySeverity: + 'The severity for a vulnerability alert upgrade (eg: LOW, MODERATE, HIGH, CRITICAL)', }; const prBodyFields = [ diff --git a/lib/util/vulnerability/utils.spec.ts b/lib/util/vulnerability/utils.spec.ts new file mode 100644 index 00000000000000..0d9aa2ee34bae1 --- /dev/null +++ b/lib/util/vulnerability/utils.spec.ts @@ -0,0 +1,129 @@ +import { getHighestVulnerabilitySeverity } from './utils'; + +describe('util/vulnerability/utils', () => { + it('parent CRITICAL vulnerability severity rating is maintained', () => { + const parentConfig = { + vulnerabilitySeverity: 'CRITICAL', + }; + + const childConfig = { + vulnerabilitySeverity: 'MODERATE', + }; + + const severity = getHighestVulnerabilitySeverity(parentConfig, childConfig); + + expect(severity).toBe('CRITICAL'); + }); + + it('child CRITICAL vulnerability severity rating is maintained', () => { + const parentConfig = { + vulnerabilitySeverity: 'MODERATE', + }; + + const childConfig = { + vulnerabilitySeverity: 'CRITICAL', + }; + + const severity = getHighestVulnerabilitySeverity(parentConfig, childConfig); + + expect(severity).toBe('CRITICAL'); + }); + + it('parent HIGH vulnerability severity rating is maintained', () => { + const parentConfig = { + vulnerabilitySeverity: 'HIGH', + }; + + const childConfig = { + vulnerabilitySeverity: 'MODERATE', + }; + + const severity = getHighestVulnerabilitySeverity(parentConfig, childConfig); + + expect(severity).toBe('HIGH'); + }); + + it('child HIGH vulnerability severity rating is maintained', () => { + const parentConfig = { + vulnerabilitySeverity: 'MODERATE', + }; + + const childConfig = { + vulnerabilitySeverity: 'HIGH', + }; + + const severity = getHighestVulnerabilitySeverity(parentConfig, childConfig); + + expect(severity).toBe('HIGH'); + }); + + it('parent MODERATE vulnerability severity rating is maintained', () => { + const parentConfig = { + vulnerabilitySeverity: 'MODERATE', + }; + + const childConfig = { + vulnerabilitySeverity: 'LOW', + }; + + const severity = getHighestVulnerabilitySeverity(parentConfig, childConfig); + + expect(severity).toBe('MODERATE'); + }); + + it('child MODERATE vulnerability severity rating is maintained', () => { + const parentConfig = { + vulnerabilitySeverity: 'LOW', + }; + + const childConfig = { + vulnerabilitySeverity: 'MODERATE', + }; + + const severity = getHighestVulnerabilitySeverity(parentConfig, childConfig); + + expect(severity).toBe('MODERATE'); + }); + + it('parent LOW vulnerability severity rating is maintained', () => { + const parentConfig = { + vulnerabilitySeverity: 'LOW', + }; + + const childConfig = { + vulnerabilitySeverity: undefined, + }; + + const severity = getHighestVulnerabilitySeverity(parentConfig, childConfig); + + expect(severity).toBe('LOW'); + }); + + it('child LOW vulnerability severity rating is maintained', () => { + const parentConfig = { + vulnerabilitySeverity: undefined, + }; + + const childConfig = { + vulnerabilitySeverity: 'LOW', + }; + + const severity = getHighestVulnerabilitySeverity(parentConfig, childConfig); + + expect(severity).toBe('LOW'); + }); + + it('handled undefined parent and child vulnerability severity', () => { + const parentConfig = { + vulnerabilitySeverity: undefined, + }; + + const childConfig = { + vulnerabilitySeverity: undefined, + }; + + const severity = getHighestVulnerabilitySeverity(parentConfig, childConfig); + + expect(severity).toBeUndefined(); + }); +}); diff --git a/lib/util/vulnerability/utils.ts b/lib/util/vulnerability/utils.ts new file mode 100644 index 00000000000000..5607a6de9237b8 --- /dev/null +++ b/lib/util/vulnerability/utils.ts @@ -0,0 +1,26 @@ +const severityOrder: Record = { + LOW: 1, + MODERATE: 2, + HIGH: 3, + CRITICAL: 4, +}; + +export function getHighestVulnerabilitySeverity< + T extends Record, + TChild extends Record | undefined +>(parent: T, child: TChild): string { + const parentVulSeverity = parent.vulnerabilitySeverity?.toUpperCase(); + const childVulSeverity = child?.vulnerabilitySeverity?.toUpperCase(); + + if (childVulSeverity === undefined) { + return parentVulSeverity; + } + + if (parentVulSeverity === undefined) { + return childVulSeverity; + } + + return severityOrder[parentVulSeverity] >= severityOrder[childVulSeverity] + ? parentVulSeverity + : childVulSeverity; +} diff --git a/lib/workers/repository/process/types.ts b/lib/workers/repository/process/types.ts index fd739b99a7d1c3..e59c569da1d8ab 100644 --- a/lib/workers/repository/process/types.ts +++ b/lib/workers/repository/process/types.ts @@ -17,3 +17,9 @@ export interface DependencyVulnerabilities { versioningApi: VersioningApi; vulnerabilities: Vulnerability[]; } + +export interface SeverityDetails { + cvssVector: string; + score: string; + severityLevel?: string; +} diff --git a/lib/workers/repository/process/vulnerabilities.ts b/lib/workers/repository/process/vulnerabilities.ts index b3745a7692d463..93483f716a0009 100644 --- a/lib/workers/repository/process/vulnerabilities.ts +++ b/lib/workers/repository/process/vulnerabilities.ts @@ -18,7 +18,11 @@ import { import { sanitizeMarkdown } from '../../../util/markdown'; import * as p from '../../../util/promises'; import { regEx } from '../../../util/regex'; -import type { DependencyVulnerabilities, Vulnerability } from './types'; +import type { + DependencyVulnerabilities, + SeverityDetails, + Vulnerability, +} from './types'; export class Vulnerabilities { private osvOffline: OsvOffline | undefined; @@ -454,12 +458,19 @@ export class Vulnerabilities { logger.debug( `Setting allowed version ${fixedVersion} to fix vulnerability ${vulnerability.id} in ${packageName} ${depVersion}` ); + + const severityDetails = this.extractSeverityDetails( + vulnerability, + affected + ); + return { matchDatasources: [datasource], matchPackageNames: [packageName], matchCurrentVersion: depVersion, allowedVersions: fixedVersion, isVulnerabilityAlert: true, + vulnerabilitySeverity: severityDetails.severityLevel?.toUpperCase(), prBodyNotes: this.generatePrBodyNotes(vulnerability, affected), force: { ...packageFileConfig.vulnerabilityAlerts, @@ -513,24 +524,16 @@ export class Vulnerabilities { content += `#### Details\n${details ?? 'No details.'}\n`; content += '#### Severity\n'; - const cvssVector = - vulnerability.severity?.find((e) => e.type === 'CVSS_V3')?.score ?? - vulnerability.severity?.[0]?.score ?? - (affected.database_specific?.cvss as string); // RUSTSEC - if (cvssVector) { - const [baseScore, severity] = this.evaluateCvssVector(cvssVector); - const score = baseScore ? `${baseScore} / 10 (${severity})` : 'Unknown'; - content += `- CVSS Score: ${score}\n`; - content += `- Vector String: \`${cvssVector}\`\n`; - } else if ( - vulnerability.id.startsWith('GHSA-') && - vulnerability.database_specific?.severity - ) { - const severity = vulnerability.database_specific.severity as string; - content += - severity.charAt(0).toUpperCase() + - severity.slice(1).toLowerCase() + - '\n'; + const severityDetails = this.extractSeverityDetails( + vulnerability, + affected + ); + + if (severityDetails.cvssVector) { + content += `- CVSS Score: ${severityDetails.score}\n`; + content += `- Vector String: \`${severityDetails.cvssVector}\`\n`; + } else if (severityDetails.severityLevel) { + content += `${severityDetails.severityLevel}\n`; } else { content += 'Unknown severity.\n'; } @@ -558,4 +561,36 @@ export class Vulnerabilities { return [sanitizeMarkdown(content)]; } + + private extractSeverityDetails( + vulnerability: Osv.Vulnerability, + affected: Osv.Affected + ): SeverityDetails { + let severityLevel: string | undefined; + let score = 'Unknown'; + + const cvssVector = + vulnerability.severity?.find((e) => e.type === 'CVSS_V3')?.score ?? + vulnerability.severity?.[0]?.score ?? + (affected.database_specific?.cvss as string); // RUSTSEC + + if (cvssVector) { + const [baseScore, severity] = this.evaluateCvssVector(cvssVector); + severityLevel = severity; + score = baseScore ? `${baseScore} / 10 (${severityLevel})` : 'Unknown'; + } else if ( + vulnerability.id.startsWith('GHSA-') && + vulnerability.database_specific?.severity + ) { + const severity = vulnerability.database_specific.severity as string; + severityLevel = + severity.charAt(0).toUpperCase() + severity.slice(1).toLowerCase(); + } + + return { + cvssVector, + score, + severityLevel, + }; + } } From 15dacb54a76d0a433cc2e8b90722b9b4496524de Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 11 May 2023 20:32:39 +0200 Subject: [PATCH 19/74] chore(deps): update dependency type-fest to v3.10.0 (#22101) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 78aa5863febcc9..7b012059da5637 100644 --- a/package.json +++ b/package.json @@ -328,7 +328,7 @@ "tmp-promise": "3.0.3", "ts-jest": "29.1.0", "ts-node": "10.9.1", - "type-fest": "3.9.0", + "type-fest": "3.10.0", "typescript": "5.0.4", "unified": "9.2.2" }, diff --git a/yarn.lock b/yarn.lock index 703a47d702b927..eb7f397258a0b1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10128,10 +10128,10 @@ type-detect@4.0.8, type-detect@^4.0.8: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -type-fest@3.9.0, type-fest@^3.8.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-3.9.0.tgz#36a9e46e6583649f9e6098b267bc577275e9e4f4" - integrity sha512-hR8JP2e8UiH7SME5JZjsobBlEiatFoxpzCP+R3ZeCo7kAaG1jXQE5X/buLzogM6GJu8le9Y4OcfNuIQX0rZskA== +type-fest@3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-3.10.0.tgz#d75f17a22be8816aea6315ab2739fe1c0c211863" + integrity sha512-hmAPf1datm+gt3c2mvu0sJyhFy6lTkIGf0GzyaZWxRLnabQfPUqg6tF95RPg6sLxKI7nFLGdFxBcf2/7+GXI+A== type-fest@^0.13.1: version "0.13.1" @@ -10173,6 +10173,11 @@ type-fest@^2.0.0, type-fest@^2.12.2, type-fest@^2.5.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== +type-fest@^3.8.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-3.9.0.tgz#36a9e46e6583649f9e6098b267bc577275e9e4f4" + integrity sha512-hR8JP2e8UiH7SME5JZjsobBlEiatFoxpzCP+R3ZeCo7kAaG1jXQE5X/buLzogM6GJu8le9Y4OcfNuIQX0rZskA== + typed-array-length@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" From 9b96e073913d9bab31a268ef7149134494843c82 Mon Sep 17 00:00:00 2001 From: Liora Milbaum Date: Fri, 12 May 2023 06:59:16 +0200 Subject: [PATCH 20/74] chore(regex-managers): Support Contailerfile (#22115) --- lib/config/presets/internal/regex-managers.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/config/presets/internal/regex-managers.ts b/lib/config/presets/internal/regex-managers.ts index d3021f96ee7649..c4574bcc09ac44 100644 --- a/lib/config/presets/internal/regex-managers.ts +++ b/lib/config/presets/internal/regex-managers.ts @@ -7,7 +7,10 @@ export const presets: Record = { description: 'Update `_VERSION` variables in Dockerfiles.', regexManagers: [ { - fileMatch: ['(^|/|\\.)Dockerfile$', '(^|/)Dockerfile[^/]*$'], + fileMatch: [ + '(^|/|\\.)([Dd]ocker|[Cc]ontainer)file$', + '(^|/)([Dd]ocker|[Cc]ontainer)file[^/]*$', + ], matchStrings: [ '# renovate: datasource=(?[a-z-]+?) depName=(?[^\\s]+?)(?: (lookupName|packageName)=(?[^\\s]+?))?(?: versioning=(?[^\\s]+?))?(?: registryUrl=(?[^\\s]+?))?\\s(?:ENV|ARG) .+?_VERSION[ =]"?(?.+?)"?\\s', ], From b02856b1fce818ad5f2e8cb1cc70805fa7033c6a Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Fri, 12 May 2023 08:18:49 +0200 Subject: [PATCH 21/74] fix: massage rebase check PR comment (#22079) --- lib/modules/platform/azure/index.ts | 4 ++++ lib/modules/platform/bitbucket-server/index.ts | 4 ++++ lib/modules/platform/bitbucket/index.ts | 4 ++++ lib/modules/platform/codecommit/index.ts | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/lib/modules/platform/azure/index.ts b/lib/modules/platform/azure/index.ts index f5b39106638bb2..3790df6c7524fa 100644 --- a/lib/modules/platform/azure/index.ts +++ b/lib/modules/platform/azure/index.ts @@ -775,6 +775,10 @@ export function massageMarkdown(input: string): string { 'you tick the rebase/retry checkbox', 'rename PR to start with "rebase!"' ) + .replace( + 'checking the rebase/retry box above', + 'renaming the PR to start with "rebase!"' + ) .replace(regEx(`\n---\n\n.*?.*?\n`), '') .replace(regEx(//g), ''); } diff --git a/lib/modules/platform/bitbucket-server/index.ts b/lib/modules/platform/bitbucket-server/index.ts index b8258e58043656..5ce4aa5e9a443f 100644 --- a/lib/modules/platform/bitbucket-server/index.ts +++ b/lib/modules/platform/bitbucket-server/index.ts @@ -974,6 +974,10 @@ export function massageMarkdown(input: string): string { 'you tick the rebase/retry checkbox', 'rename PR to start with "rebase!"' ) + .replace( + 'checking the rebase/retry box above', + 'renaming the PR to start with "rebase!"' + ) .replace(regEx(/<\/?summary>/g), '**') .replace(regEx(/<\/?details>/g), '') .replace(regEx(`\n---\n\n.*?.*?(\n|$)`), '') diff --git a/lib/modules/platform/bitbucket/index.ts b/lib/modules/platform/bitbucket/index.ts index b76e66576851c6..979384249c6666 100644 --- a/lib/modules/platform/bitbucket/index.ts +++ b/lib/modules/platform/bitbucket/index.ts @@ -519,6 +519,10 @@ export function massageMarkdown(input: string): string { 'you tick the rebase/retry checkbox', 'by renaming this PR to start with "rebase!"' ) + .replace( + 'checking the rebase/retry box above', + 'renaming the PR to start with "rebase!"' + ) .replace(regEx(/<\/?summary>/g), '**') .replace(regEx(/<\/?(details|blockquote)>/g), '') .replace(regEx(`\n---\n\n.*?.*?\n`), '') diff --git a/lib/modules/platform/codecommit/index.ts b/lib/modules/platform/codecommit/index.ts index e689415cb39457..0e93116c889c0b 100644 --- a/lib/modules/platform/codecommit/index.ts +++ b/lib/modules/platform/codecommit/index.ts @@ -307,6 +307,10 @@ export function massageMarkdown(input: string): string { 'you tick the rebase/retry checkbox', 'rename PR to start with "rebase!"' ) + .replace( + 'checking the rebase/retry box above', + 'renaming the PR to start with "rebase!"' + ) .replace(regEx(/<\/?summary>/g), '**') .replace(regEx(/<\/?details>/g), '') .replace(regEx(`\n---\n\n.*?.*?\n`), '') From e371ddb9ca1fd6cff84317cfc242a8516eeca4a5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 12 May 2023 08:59:32 +0000 Subject: [PATCH 22/74] chore(deps): update dependency @types/node to v18.16.4 (#22121) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7b012059da5637..231bad645da803 100644 --- a/package.json +++ b/package.json @@ -279,7 +279,7 @@ "@types/marshal": "0.5.1", "@types/moo": "0.5.5", "@types/nock": "10.0.3", - "@types/node": "18.16.3", + "@types/node": "18.16.4", "@types/parse-link-header": "2.0.1", "@types/semver": "7.3.13", "@types/semver-stable": "3.0.0", diff --git a/yarn.lock b/yarn.lock index eb7f397258a0b1..1efc8e9ae0f91b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3061,11 +3061,16 @@ dependencies: "@types/node" "*" -"@types/node@*", "@types/node@18.16.3": +"@types/node@*": version "18.16.3" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.3.tgz#6bda7819aae6ea0b386ebc5b24bdf602f1b42b01" integrity sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q== +"@types/node@18.16.4": + version "18.16.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.4.tgz#dfb38f0f3fb045fca84ffa7783233c63009d8a92" + integrity sha512-LUhvPmAKAbgm+p/K11IWszLZVoZDlMF4NRmqbhEzDz/CnCuehPkZXwZbBCKGJsgjnuVejotBwM7B3Scrq4EqDw== + "@types/node@^13.7.0": version "13.13.52" resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.52.tgz#03c13be70b9031baaed79481c0c0cfb0045e53f7" From 6585875119dbfc90dc1074d073ba61ea4223f645 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 12 May 2023 09:50:51 +0000 Subject: [PATCH 23/74] chore(deps): update dependency @types/node to v18.16.8 (#22124) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 231bad645da803..1f0666f57a3bf9 100644 --- a/package.json +++ b/package.json @@ -279,7 +279,7 @@ "@types/marshal": "0.5.1", "@types/moo": "0.5.5", "@types/nock": "10.0.3", - "@types/node": "18.16.4", + "@types/node": "18.16.8", "@types/parse-link-header": "2.0.1", "@types/semver": "7.3.13", "@types/semver-stable": "3.0.0", diff --git a/yarn.lock b/yarn.lock index 1efc8e9ae0f91b..8a68d67d06b67b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3066,10 +3066,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.3.tgz#6bda7819aae6ea0b386ebc5b24bdf602f1b42b01" integrity sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q== -"@types/node@18.16.4": - version "18.16.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.4.tgz#dfb38f0f3fb045fca84ffa7783233c63009d8a92" - integrity sha512-LUhvPmAKAbgm+p/K11IWszLZVoZDlMF4NRmqbhEzDz/CnCuehPkZXwZbBCKGJsgjnuVejotBwM7B3Scrq4EqDw== +"@types/node@18.16.8": + version "18.16.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.8.tgz#fcd9bd0a793aba2701caff4aeae7c988d4da6ce5" + integrity sha512-p0iAXcfWCOTCBbsExHIDFCfwsqFwBTgETJveKMT+Ci3LY9YqQCI91F5S+TB20+aRCXpcWfvx5Qr5EccnwCm2NA== "@types/node@^13.7.0": version "13.13.52" From 2aae5118b941a7639135e083d3c7cdb962da061f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 12 May 2023 10:40:21 +0000 Subject: [PATCH 24/74] build(deps): update dependency @renovatebot/osv-offline to v1.2.5 (#22126) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 1f0666f57a3bf9..96a630697c56d0 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "@opentelemetry/sdk-trace-node": "1.12.0", "@opentelemetry/semantic-conventions": "1.12.0", "@qnighy/marshal": "0.1.3", - "@renovatebot/osv-offline": "1.2.4", + "@renovatebot/osv-offline": "1.2.5", "@renovatebot/pep440": "2.1.15", "@renovatebot/ruby-semver": "3.0.1", "@sindresorhus/is": "4.6.0", diff --git a/yarn.lock b/yarn.lock index 8a68d67d06b67b..928f04e5d55747 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2487,20 +2487,20 @@ "@renovate/eslint-plugin@file:./tools/eslint": version "0.0.0" -"@renovatebot/osv-offline-db@1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@renovatebot/osv-offline-db/-/osv-offline-db-1.3.2.tgz#960f687fce4555f3d802ff855318eeb9d34a9215" - integrity sha512-02sMhxKjmRvHm6HIdTEyVIAIdEdYWLOU/ecQuiP2hvgXg28P6GWj/BkAbQ8GU0uLfBMZiqB4DK9MKoI4wx7BJw== +"@renovatebot/osv-offline-db@1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@renovatebot/osv-offline-db/-/osv-offline-db-1.3.3.tgz#371d0a22ece6b2f1012c525dfd4005ee4e6580f1" + integrity sha512-Q7PNdRbMio2GYFqanuHByln20viVpyNhE4CmcY6ly2TVx42YbuRBrZ57JY5RVid0icArVagkW4mjrDh9CawOgA== dependencies: - "@seald-io/nedb" "^4.0.1" + "@seald-io/nedb" "^4.0.2" -"@renovatebot/osv-offline@1.2.4": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@renovatebot/osv-offline/-/osv-offline-1.2.4.tgz#cf2d79e8aabf3b15570c8a3178372a3df04ef7b9" - integrity sha512-9r97Fn8dmdbAtqNAM4z3ECyxo6cpcQ1acMuAQoFcC0xemuFlzkrP+BY0KI/U/qQG2IojEfW+9TU+C3o0ZDS94w== +"@renovatebot/osv-offline@1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@renovatebot/osv-offline/-/osv-offline-1.2.5.tgz#40bdb5c22eb1cd66ec3a79d3a25de40fbdce6bb4" + integrity sha512-PRzSyAhel/coD68Z8WK5nFw9UJ8vLCvQQb+aRzwwmMEuSzAbe1FnVbvEZ/wae3sDy57nvMuVhk358InMYHYyVQ== dependencies: "@octokit/rest" "^19.0.7" - "@renovatebot/osv-offline-db" "1.3.2" + "@renovatebot/osv-offline-db" "1.3.3" adm-zip "~0.5.10" fs-extra "^11.1.1" got "^11.8.6" @@ -2522,10 +2522,10 @@ resolved "https://registry.yarnpkg.com/@seald-io/binary-search-tree/-/binary-search-tree-1.0.3.tgz#165a9a456eaa30d15885b25db83861bcce2c6a74" integrity sha512-qv3jnwoakeax2razYaMsGI/luWdliBLHTdC6jU55hQt1hcFqzauH/HsBollQ7IR4ySTtYhT+xyHoijpA16C+tA== -"@seald-io/nedb@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@seald-io/nedb/-/nedb-4.0.1.tgz#bfd62b5468e6b03e4f3a16dabd12c9d55aab8856" - integrity sha512-E2l7EUEMkSO3WLydRxRWjVWzijzWehzKmy/q9ekbgaOOQjYD7zHdS8z3KsM8+aQ910agfREZCR+3YCc5Xuc9dg== +"@seald-io/nedb@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@seald-io/nedb/-/nedb-4.0.2.tgz#44bc5f9b86e44f7434c5af8064cc7f8e079fc3a8" + integrity sha512-gJ91fT1sgh2cLXYVcTSh7khZ8LdemI8+SojCdpZ5wy+DUQ4fSrEwGqOwbdV49NDs2BBO6GeBpSb8CnhG2IW1rw== dependencies: "@seald-io/binary-search-tree" "^1.0.3" localforage "^1.9.0" From 976a5a1a8273e9932f9f9cc879f5a949ff1e1751 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Sat, 13 May 2023 02:52:09 -0400 Subject: [PATCH 25/74] feat(bitbucket): add paginate http option (#22135) --- lib/util/http/bitbucket.spec.ts | 30 +++++++++++++ lib/util/http/bitbucket.ts | 80 ++++++++++++++++++++++++++++++--- 2 files changed, 103 insertions(+), 7 deletions(-) diff --git a/lib/util/http/bitbucket.spec.ts b/lib/util/http/bitbucket.spec.ts index ac7bb06e010322..7f74909d1c8175 100644 --- a/lib/util/http/bitbucket.spec.ts +++ b/lib/util/http/bitbucket.spec.ts @@ -55,4 +55,34 @@ describe('util/http/bitbucket', () => { statusCode: 200, }); }); + + it('paginates', async () => { + httpMock + .scope(baseUrl) + .get('/some-url') + .reply(200, { + values: ['a'], + page: '1', + next: `${baseUrl}/some-url?page=2`, + }) + .get('/some-url?page=2') + .reply(200, { + values: ['b', 'c'], + page: '2', + next: `${baseUrl}/some-url?page=3`, + }) + .get('/some-url?page=3') + .reply(200, { + values: ['d'], + page: '3', + }); + const res = await api.getJson('some-url', { paginate: true }); + expect(res.body).toEqual({ + page: '1', + pagelen: 4, + size: 4, + values: ['a', 'b', 'c', 'd'], + next: undefined, + }); + }); }); diff --git a/lib/util/http/bitbucket.ts b/lib/util/http/bitbucket.ts index 628ef154cba1fe..15bea99b04860a 100644 --- a/lib/util/http/bitbucket.ts +++ b/lib/util/http/bitbucket.ts @@ -1,4 +1,7 @@ -import type { HttpOptions, HttpResponse, InternalHttpOptions } from './types'; +import is from '@sindresorhus/is'; +import type { PagedResult } from '../../modules/platform/bitbucket/types'; +import { parseUrl, resolveBaseUrl } from '../url'; +import type { HttpOptions, HttpResponse } from './types'; import { Http } from '.'; let baseUrl = 'https://api.bitbucket.org/'; @@ -7,16 +10,79 @@ export const setBaseUrl = (url: string): void => { baseUrl = url; }; -export class BitbucketHttp extends Http { - constructor(type = 'bitbucket', options?: HttpOptions) { +export interface BitbucketHttpOptions extends HttpOptions { + paginate?: boolean; +} + +export class BitbucketHttp extends Http { + constructor(type = 'bitbucket', options?: BitbucketHttpOptions) { super(type, options); } - protected override request( - url: string | URL, - options?: InternalHttpOptions + protected override async request( + path: string, + options?: BitbucketHttpOptions ): Promise> { const opts = { baseUrl, ...options }; - return super.request(url, opts); + + const result = await super.request(path, opts); + + if (opts.paginate && isPagedResult(result.body)) { + const resultBody = result.body as PagedResult; + + let nextPage = getPageFromURL(resultBody.next); + + while (is.nonEmptyString(nextPage)) { + const nextPath = getNextPagePath(path, nextPage); + + // istanbul ignore if + if (is.nullOrUndefined(nextPath)) { + break; + } + + const nextResult = await super.request>( + nextPath, + options + ); + + resultBody.values.push(...nextResult.body.values); + + nextPage = getPageFromURL(nextResult.body?.next); + } + + // Override other page-related attributes + resultBody.pagelen = resultBody.values.length; + resultBody.size = resultBody.values.length; + resultBody.next = undefined; + } + + return result; } } + +function getPageFromURL(url: string | undefined): string | null { + const resolvedURL = parseUrl(url); + + if (is.nullOrUndefined(resolvedURL)) { + return null; + } + + return resolvedURL.searchParams.get('page'); +} + +function getNextPagePath(path: string, nextPage: string): string | null { + const resolvedURL = parseUrl(resolveBaseUrl(baseUrl, path)); + + // istanbul ignore if + if (is.nullOrUndefined(resolvedURL)) { + return null; + } + + resolvedURL.searchParams.set('page', nextPage); + + return resolvedURL.toString(); +} + +function isPagedResult(obj: any): obj is PagedResult { + return is.nonEmptyObject(obj) && Array.isArray(obj.values); +} From d82a81115398a55edf3d8e99970628ec7f8e591d Mon Sep 17 00:00:00 2001 From: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> Date: Sat, 13 May 2023 13:15:05 +0200 Subject: [PATCH 26/74] docs(config template editing): bump to v18 of React in example (#22162) --- docs/usage/configuration-templates.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/usage/configuration-templates.md b/docs/usage/configuration-templates.md index d20c501df41b9e..ae35c8b6a8194a 100644 --- a/docs/usage/configuration-templates.md +++ b/docs/usage/configuration-templates.md @@ -14,8 +14,8 @@ If you change the `branchPrefix` while you have ignored some upgrades (closed PR `branchName` default value is `{{{branchPrefix}}}{{{additionalBranchPrefix}}}{{{branchTopic}}}`. -The most common branch name you will see looks like this: `renovate/react-17.x`. -In this example, the `branchPrefix` is the default `renovate/`, `additionalBranchPrefix` is empty, and `branchTopic` is `react-17.x`. +The most common branch name you will see looks like this: `renovate/react-18.x`. +In this example, the `branchPrefix` is the default `renovate/`, `additionalBranchPrefix` is empty, and `branchTopic` is `react-18.x`. Most users will be happy with the default `branchPrefix` of `renovate/`, but you can change this if you don't like the default. Say you don't want the forward slashes, in that case you would use `renovate-` as your `branchPrefix`. @@ -47,7 +47,7 @@ You may want to edit this. If you think your new `commitMessageTopic` is helpful for others, please [open a PR](https://github.com/renovatebot/renovate/pulls). `commitMessageExtra` refers to the version being updated to. -e.g. `to v17` for a major upgrade, or `to v17.0.2` for a patch update. +e.g. `to v18` for a major upgrade, or `to v18.0.2` for a patch update. It can be empty in some cases, like if the action/topic doesn't change a package version, e.g. `Pin Docker digests`. `commitMessageSuffix` defaults to empty but is currently used in two cases: From 0e27bd18cffa3ad684766e830c50f74dfb2b881f Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Sat, 13 May 2023 08:19:24 -0400 Subject: [PATCH 27/74] feat(bitbucket): use paginated effective default reviewers response (#22164) --- lib/modules/platform/bitbucket/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/modules/platform/bitbucket/index.ts b/lib/modules/platform/bitbucket/index.ts index 979384249c6666..17fe0cd5bc36a0 100644 --- a/lib/modules/platform/bitbucket/index.ts +++ b/lib/modules/platform/bitbucket/index.ts @@ -802,7 +802,10 @@ export async function createPr({ if (platformOptions?.bbUseDefaultReviewers) { const reviewersResponse = ( await bitbucketHttp.getJson>( - `/2.0/repositories/${config.repository}/effective-default-reviewers` + `/2.0/repositories/${config.repository}/effective-default-reviewers`, + { + paginate: true, + } ) ).body; reviewers = reviewersResponse.values.map((reviewer: EffectiveReviewer) => ({ From fc73b078dc2a994c6bdf4e301141670dc55cb4a4 Mon Sep 17 00:00:00 2001 From: Sebastian Krebs Date: Sat, 13 May 2023 20:12:36 +0200 Subject: [PATCH 28/74] feat: commitMessageLowerCase (#20930) Co-authored-by: Michael Kriese Co-authored-by: Rhys Arkins --- docs/usage/configuration-options.md | 5 +++++ lib/config/options/index.ts | 7 +++++++ lib/config/types.ts | 1 + lib/modules/platform/azure/index.ts | 4 +++- lib/modules/platform/bitbucket-server/index.ts | 2 +- lib/modules/platform/bitbucket/index.ts | 2 +- lib/modules/platform/codecommit/index.ts | 4 +++- lib/modules/platform/github/index.ts | 2 +- lib/modules/platform/gitlab/index.ts | 2 +- lib/workers/repository/updates/generate.ts | 4 ++-- 10 files changed, 25 insertions(+), 8 deletions(-) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index d18d6dd44335e8..2ba14ca9de3e8e 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -448,6 +448,11 @@ Check out the default value for `commitMessage` to understand how this field is This is used to alter `commitMessage` and `prTitle` without needing to copy/paste the whole string. The "extra" is usually an identifier of the new version, e.g. "to v1.3.2" or "to tag 9.2". +## commitMessageLowerCase + +With `semanticCommits` pr- and commit-titles will by default (`"auto"`) be converted to all-lowercase. +Set this to `"never"` to leave the titles untouched, allowing uppercase characters in semantic commit titles. + ## commitMessagePrefix This is used to alter `commitMessage` and `prTitle` without needing to copy/paste the whole string. diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts index a020d9dae72157..0e05c187ba51cf 100644 --- a/lib/config/options/index.ts +++ b/lib/config/options/index.ts @@ -1549,6 +1549,13 @@ const options: RenovateOptions[] = [ type: 'string', default: 'deps', }, + { + name: 'commitMessageLowerCase', + description: 'Lowercase PR- and commit titles.', + type: 'string', + allowedValues: ['auto', 'never'], + default: 'auto', + }, // PR Behaviour { name: 'rollbackPrs', diff --git a/lib/config/types.ts b/lib/config/types.ts index 4286c5a512e242..ad5908b00e24b9 100644 --- a/lib/config/types.ts +++ b/lib/config/types.ts @@ -78,6 +78,7 @@ export interface RenovateSharedConfig { automergeSchedule?: string[]; semanticCommits?: 'auto' | 'enabled' | 'disabled'; semanticCommitScope?: string | null; + commitMessageLowerCase?: 'auto' | 'never'; semanticCommitType?: string; suppressNotifications?: string[]; timezone?: string; diff --git a/lib/modules/platform/azure/index.ts b/lib/modules/platform/azure/index.ts index 3790df6c7524fa..def6948ea10b12 100644 --- a/lib/modules/platform/azure/index.ts +++ b/lib/modules/platform/azure/index.ts @@ -307,7 +307,9 @@ export async function findPr({ ); if (prTitle) { - prsFiltered = prsFiltered.filter((item) => item.title === prTitle); + prsFiltered = prsFiltered.filter( + (item) => item.title.toUpperCase() === prTitle.toUpperCase() + ); } switch (state) { diff --git a/lib/modules/platform/bitbucket-server/index.ts b/lib/modules/platform/bitbucket-server/index.ts index 5ce4aa5e9a443f..9da5a7fff7a2eb 100644 --- a/lib/modules/platform/bitbucket-server/index.ts +++ b/lib/modules/platform/bitbucket-server/index.ts @@ -289,7 +289,7 @@ const isRelevantPr = (branchName: string, prTitle: string | null | undefined, state: string) => (p: Pr): boolean => p.sourceBranch === branchName && - (!prTitle || p.title === prTitle) && + (!prTitle || p.title.toUpperCase() === prTitle.toUpperCase()) && matchesState(p.state, state); // TODO: coverage (#9624) diff --git a/lib/modules/platform/bitbucket/index.ts b/lib/modules/platform/bitbucket/index.ts index 17fe0cd5bc36a0..b12eb09a114dae 100644 --- a/lib/modules/platform/bitbucket/index.ts +++ b/lib/modules/platform/bitbucket/index.ts @@ -293,7 +293,7 @@ export async function findPr({ const pr = prList.find( (p) => p.sourceBranch === branchName && - (!prTitle || p.title === prTitle) && + (!prTitle || p.title.toUpperCase() === prTitle.toUpperCase()) && matchesState(p.state, state) ); if (pr) { diff --git a/lib/modules/platform/codecommit/index.ts b/lib/modules/platform/codecommit/index.ts index 0e93116c889c0b..6ce173083c4901 100644 --- a/lib/modules/platform/codecommit/index.ts +++ b/lib/modules/platform/codecommit/index.ts @@ -208,7 +208,9 @@ export async function findPr({ ); if (prTitle) { - prsFiltered = prsFiltered.filter((item) => item.title === prTitle); + prsFiltered = prsFiltered.filter( + (item) => item.title.toUpperCase() === prTitle.toUpperCase() + ); } switch (state) { diff --git a/lib/modules/platform/github/index.ts b/lib/modules/platform/github/index.ts index 1fb1e521a00e74..a82a532eb04a29 100644 --- a/lib/modules/platform/github/index.ts +++ b/lib/modules/platform/github/index.ts @@ -716,7 +716,7 @@ export async function findPr({ return false; } - if (prTitle && prTitle !== p.title) { + if (prTitle && prTitle.toUpperCase() !== p.title.toUpperCase()) { return false; } diff --git a/lib/modules/platform/gitlab/index.ts b/lib/modules/platform/gitlab/index.ts index 24b69b9865ed25..eb3af69a208e34 100644 --- a/lib/modules/platform/gitlab/index.ts +++ b/lib/modules/platform/gitlab/index.ts @@ -752,7 +752,7 @@ export async function findPr({ prList.find( (p: { sourceBranch: string; title: string; state: string }) => p.sourceBranch === branchName && - (!prTitle || p.title === prTitle) && + (!prTitle || p.title.toUpperCase() === prTitle.toUpperCase()) && matchesState(p.state, state) ) ?? null ); diff --git a/lib/workers/repository/updates/generate.ts b/lib/workers/repository/updates/generate.ts index 3dd6b922615837..e02cf5012b7c20 100644 --- a/lib/workers/repository/updates/generate.ts +++ b/lib/workers/repository/updates/generate.ts @@ -226,7 +226,7 @@ export function generateBranchConfig( regEx(/to vv(\d)/), 'to v$1' ); - if (upgrade.toLowerCase) { + if (upgrade.toLowerCase && upgrade.commitMessageLowerCase !== 'never') { // We only need to lowercase the first line const splitMessage = upgrade.commitMessage.split(newlineRegex); splitMessage[0] = splitMessage[0].toLowerCase(); @@ -249,7 +249,7 @@ export function generateBranchConfig( ); throw new Error(CONFIG_SECRETS_EXPOSED); } - if (upgrade.toLowerCase) { + if (upgrade.toLowerCase && upgrade.commitMessageLowerCase !== 'never') { upgrade.prTitle = upgrade.prTitle.toLowerCase(); } } else { From e74e4809df03046757284d4cfacbf1ff8ba94932 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Sun, 14 May 2023 08:09:08 +0200 Subject: [PATCH 29/74] chore: change some auto-comment labels --- .github/label-actions.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/label-actions.yml b/.github/label-actions.yml index fc769f744e506f..5e85dbe2729290 100644 --- a/.github/label-actions.yml +++ b/.github/label-actions.yml @@ -23,12 +23,12 @@ The Renovate team -'logs:problem': +'needs-logs': comment: > Hi there, - We found a problem with the logs. + This issue or discussion is missing some logs, making it difficult or impossible to help you. Depending on which situation applies follow one, some or all of these instructions. @@ -219,9 +219,9 @@ lock: true lock-reason: 'resolved' -'needs-code-formatting': +'format-code-comments': comment: > - Hi, please format your code or logs so they're readable. + Hi, please format any copy/pasted code or logs so they're readable. You can find a Markdown code formatting guide [here](https://www.markdownguide.org/basic-syntax/#code) as well as some GitHub-specific information formatting code blocks [here](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks). From 85fbad1029d4a10ff07b93152324b68b8a9fd990 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 01:14:30 +0000 Subject: [PATCH 30/74] docs: update references to renovate/renovate to v35.82.0 (#22223) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- docs/usage/docker.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/docker.md b/docs/usage/docker.md index c28ce0c59b73ee..be4ba4f94da90b 100644 --- a/docs/usage/docker.md +++ b/docs/usage/docker.md @@ -388,7 +388,7 @@ To get access to the token a custom Renovate Docker image is needed that include The Dockerfile to create such an image can look like this: ```Dockerfile -FROM renovate/renovate:35.73.0 +FROM renovate/renovate:35.82.0 # Include the "Docker tip" which you can find here https://cloud.google.com/sdk/docs/install # under "Installation" for "Debian/Ubuntu" RUN ... From 019c75caab2eeeeb86a88fb409f6749a56f4e8b4 Mon Sep 17 00:00:00 2001 From: Sebastian Poxhofer Date: Mon, 15 May 2023 09:51:05 +0200 Subject: [PATCH 31/74] feat(manager/pep621): implement manager (#22082) Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> --- lib/modules/datasource/pypi/index.ts | 6 +- lib/modules/manager/api.ts | 2 + .../__fixtures__/pyproject_pdm_sources.toml | 33 +++ .../__fixtures__/pyproject_with_pdm.toml | 37 +++ lib/modules/manager/pep621/extract.spec.ts | 267 ++++++++++++++++++ lib/modules/manager/pep621/extract.ts | 51 ++++ lib/modules/manager/pep621/index.ts | 8 + .../manager/pep621/processors/index.ts | 3 + lib/modules/manager/pep621/processors/pdm.ts | 42 +++ .../manager/pep621/processors/types.ts | 12 + lib/modules/manager/pep621/readme.md | 11 + lib/modules/manager/pep621/schema.ts | 35 +++ lib/modules/manager/pep621/types.ts | 6 + lib/modules/manager/pep621/utils.spec.ts | 39 +++ lib/modules/manager/pep621/utils.ts | 101 +++++++ 15 files changed, 650 insertions(+), 3 deletions(-) create mode 100644 lib/modules/manager/pep621/__fixtures__/pyproject_pdm_sources.toml create mode 100644 lib/modules/manager/pep621/__fixtures__/pyproject_with_pdm.toml create mode 100644 lib/modules/manager/pep621/extract.spec.ts create mode 100644 lib/modules/manager/pep621/extract.ts create mode 100644 lib/modules/manager/pep621/index.ts create mode 100644 lib/modules/manager/pep621/processors/index.ts create mode 100644 lib/modules/manager/pep621/processors/pdm.ts create mode 100644 lib/modules/manager/pep621/processors/types.ts create mode 100644 lib/modules/manager/pep621/readme.md create mode 100644 lib/modules/manager/pep621/schema.ts create mode 100644 lib/modules/manager/pep621/types.ts create mode 100644 lib/modules/manager/pep621/utils.spec.ts create mode 100644 lib/modules/manager/pep621/utils.ts diff --git a/lib/modules/datasource/pypi/index.ts b/lib/modules/datasource/pypi/index.ts index 44acf798b116db..6757b39e594391 100644 --- a/lib/modules/datasource/pypi/index.ts +++ b/lib/modules/datasource/pypi/index.ts @@ -21,9 +21,9 @@ export class PypiDatasource extends Datasource { override readonly customRegistrySupport = true; - override readonly defaultRegistryUrls = [ - process.env.PIP_INDEX_URL ?? 'https://pypi.org/pypi/', - ]; + static readonly defaultURL = + process.env.PIP_INDEX_URL ?? 'https://pypi.org/pypi/'; + override readonly defaultRegistryUrls = [PypiDatasource.defaultURL]; override readonly defaultVersioning = pep440.id; diff --git a/lib/modules/manager/api.ts b/lib/modules/manager/api.ts index 41dc108d9d1d8c..fcd8aca94e6e2a 100644 --- a/lib/modules/manager/api.ts +++ b/lib/modules/manager/api.ts @@ -58,6 +58,7 @@ import * as npm from './npm'; import * as nuget from './nuget'; import * as nvm from './nvm'; import * as osgi from './osgi'; +import * as pep621 from './pep621'; import * as pipCompile from './pip-compile'; import * as pip_requirements from './pip_requirements'; import * as pip_setup from './pip_setup'; @@ -146,6 +147,7 @@ api.set('npm', npm); api.set('nuget', nuget); api.set('nvm', nvm); api.set('osgi', osgi); +api.set('pep621', pep621); api.set('pip-compile', pipCompile); api.set('pip_requirements', pip_requirements); api.set('pip_setup', pip_setup); diff --git a/lib/modules/manager/pep621/__fixtures__/pyproject_pdm_sources.toml b/lib/modules/manager/pep621/__fixtures__/pyproject_pdm_sources.toml new file mode 100644 index 00000000000000..a09c836f392278 --- /dev/null +++ b/lib/modules/manager/pep621/__fixtures__/pyproject_pdm_sources.toml @@ -0,0 +1,33 @@ +[project] +name = "pdm" +dynamic = ["version"] +requires-python = ">=3.7" +license = {text = "MIT"} +dependencies = [ + "blinker", + "packaging>=20.9,!=22.0", +] +readme = "README.md" + +[project.optional-dependencies] +pytest = [ + "pytest>12", +] + +[tool.pdm.dev-dependencies] +test = [ + "pytest-rerunfailures>=10.2", +] +tox = [ + "tox-pdm>=0.5", +] + +[[tool.pdm.source]] +url = "https://private-site.org/pypi/simple" +verify_ssl = true +name = "internal" + +[[tool.pdm.source]] +url = "https://private.pypi.org/simple" +verify_ssl = true +name = "pypi" diff --git a/lib/modules/manager/pep621/__fixtures__/pyproject_with_pdm.toml b/lib/modules/manager/pep621/__fixtures__/pyproject_with_pdm.toml new file mode 100644 index 00000000000000..915cf6063ca561 --- /dev/null +++ b/lib/modules/manager/pep621/__fixtures__/pyproject_with_pdm.toml @@ -0,0 +1,37 @@ +[project] +name = "pdm" +dynamic = ["version"] +requires-python = ">=3.7" +license = {text = "MIT"} +dependencies = [ + "blinker", + "packaging>=20.9,!=22.0", + "rich>=12.3.0", + "virtualenv==20.0.0", + "pyproject-hooks", + "unearth>=0.9.0", + "tomlkit>=0.11.1,<1", + "installer<0.8,>=0.7", + "cachecontrol[filecache]>=0.12.11", + "tomli>=1.1.0; python_version < \"3.11\"", + "typing-extensions; python_version < \"3.8\"", + "importlib-metadata>=3.6; python_version < \"3.10\"", +] +readme = "README.md" + +[project.optional-dependencies] +pytest = [ + "pytest>12", + "pytest-mock", +] + +[tool.pdm.dev-dependencies] +test = [ + "pdm[pytest]", + "pytest-rerunfailures>=10.2", +] +tox = [ + "tox", + "tox-pdm>=0.5", + "", # fail to parse +] diff --git a/lib/modules/manager/pep621/extract.spec.ts b/lib/modules/manager/pep621/extract.spec.ts new file mode 100644 index 00000000000000..75e1ad6e2745bc --- /dev/null +++ b/lib/modules/manager/pep621/extract.spec.ts @@ -0,0 +1,267 @@ +import { codeBlock } from 'common-tags'; +import { Fixtures } from '../../../../test/fixtures'; +import { extractPackageFile } from './extract'; + +const pdmPyProject = Fixtures.get('pyproject_with_pdm.toml'); +const pdmSourcesPyProject = Fixtures.get('pyproject_pdm_sources.toml'); + +describe('modules/manager/pep621/extract', () => { + describe('extractPackageFile()', () => { + it('should return null for empty content', function () { + const result = extractPackageFile('', 'pyproject.toml'); + expect(result).toBeNull(); + }); + + it('should return null for invalid toml', function () { + const result = extractPackageFile( + codeBlock` + [project] + name = + `, + 'pyproject.toml' + ); + expect(result).toBeNull(); + }); + + it('should return dependencies for valid content', function () { + const result = extractPackageFile(pdmPyProject, 'pyproject.toml'); + + const dependencies = result?.deps.filter( + (dep) => dep.depType === 'project.dependencies' + ); + expect(dependencies).toEqual([ + { + packageName: 'blinker', + depName: 'blinker', + datasource: 'pypi', + depType: 'project.dependencies', + skipReason: 'any-version', + }, + { + packageName: 'packaging', + depName: 'packaging', + datasource: 'pypi', + depType: 'project.dependencies', + currentValue: '>=20.9,!=22.0', + }, + { + packageName: 'rich', + depName: 'rich', + datasource: 'pypi', + depType: 'project.dependencies', + currentValue: '>=12.3.0', + }, + { + packageName: 'virtualenv', + depName: 'virtualenv', + datasource: 'pypi', + depType: 'project.dependencies', + currentValue: '==20.0.0', + }, + { + packageName: 'pyproject-hooks', + depName: 'pyproject-hooks', + datasource: 'pypi', + depType: 'project.dependencies', + skipReason: 'any-version', + }, + { + packageName: 'unearth', + depName: 'unearth', + datasource: 'pypi', + depType: 'project.dependencies', + currentValue: '>=0.9.0', + }, + { + packageName: 'tomlkit', + depName: 'tomlkit', + datasource: 'pypi', + depType: 'project.dependencies', + currentValue: '>=0.11.1,<1', + }, + { + packageName: 'installer', + depName: 'installer', + datasource: 'pypi', + depType: 'project.dependencies', + currentValue: '<0.8,>=0.7', + }, + { + packageName: 'cachecontrol', + depName: 'cachecontrol', + datasource: 'pypi', + depType: 'project.dependencies', + currentValue: '>=0.12.11', + }, + { + packageName: 'tomli', + depName: 'tomli', + datasource: 'pypi', + depType: 'project.dependencies', + currentValue: '>=1.1.0', + }, + { + packageName: 'typing-extensions', + depName: 'typing-extensions', + datasource: 'pypi', + depType: 'project.dependencies', + skipReason: 'any-version', + }, + { + packageName: 'importlib-metadata', + depName: 'importlib-metadata', + datasource: 'pypi', + depType: 'project.dependencies', + currentValue: '>=3.6', + }, + ]); + + const optionalDependencies = result?.deps.filter( + (dep) => dep.depType === 'project.optional-dependencies' + ); + expect(optionalDependencies).toEqual([ + { + packageName: 'pytest', + datasource: 'pypi', + depType: 'project.optional-dependencies', + currentValue: '>12', + depName: 'pytest/pytest', + }, + { + packageName: 'pytest-mock', + datasource: 'pypi', + depType: 'project.optional-dependencies', + skipReason: 'any-version', + depName: 'pytest/pytest-mock', + }, + ]); + + const pdmDevDependencies = result?.deps.filter( + (dep) => dep.depType === 'tool.pdm.dev-dependencies' + ); + expect(pdmDevDependencies).toEqual([ + { + packageName: 'pdm', + datasource: 'pypi', + depType: 'tool.pdm.dev-dependencies', + skipReason: 'any-version', + depName: 'test/pdm', + }, + { + packageName: 'pytest-rerunfailures', + datasource: 'pypi', + depType: 'tool.pdm.dev-dependencies', + currentValue: '>=10.2', + depName: 'test/pytest-rerunfailures', + }, + { + packageName: 'tox', + datasource: 'pypi', + depType: 'tool.pdm.dev-dependencies', + skipReason: 'any-version', + depName: 'tox/tox', + }, + { + packageName: 'tox-pdm', + datasource: 'pypi', + depType: 'tool.pdm.dev-dependencies', + currentValue: '>=0.5', + depName: 'tox/tox-pdm', + }, + ]); + }); + + it('should return dependencies with overwritten pypi registryUrl', function () { + const result = extractPackageFile(pdmSourcesPyProject, 'pyproject.toml'); + + expect(result?.deps).toEqual([ + { + packageName: 'blinker', + depName: 'blinker', + datasource: 'pypi', + depType: 'project.dependencies', + skipReason: 'any-version', + registryUrls: [ + 'https://private-site.org/pypi/simple', + 'https://private.pypi.org/simple', + ], + }, + { + packageName: 'packaging', + depName: 'packaging', + datasource: 'pypi', + depType: 'project.dependencies', + currentValue: '>=20.9,!=22.0', + registryUrls: [ + 'https://private-site.org/pypi/simple', + 'https://private.pypi.org/simple', + ], + }, + { + packageName: 'pytest', + datasource: 'pypi', + depType: 'project.optional-dependencies', + currentValue: '>12', + depName: 'pytest/pytest', + registryUrls: [ + 'https://private-site.org/pypi/simple', + 'https://private.pypi.org/simple', + ], + }, + { + packageName: 'pytest-rerunfailures', + datasource: 'pypi', + depType: 'tool.pdm.dev-dependencies', + currentValue: '>=10.2', + depName: 'test/pytest-rerunfailures', + registryUrls: [ + 'https://private-site.org/pypi/simple', + 'https://private.pypi.org/simple', + ], + }, + { + packageName: 'tox-pdm', + datasource: 'pypi', + depType: 'tool.pdm.dev-dependencies', + currentValue: '>=0.5', + depName: 'tox/tox-pdm', + registryUrls: [ + 'https://private-site.org/pypi/simple', + 'https://private.pypi.org/simple', + ], + }, + ]); + }); + + it('should return dependencies with original pypi registryUrl', function () { + const result = extractPackageFile( + codeBlock` + [project] + dependencies = [ + "packaging>=20.9,!=22.0", + ] + + [[tool.pdm.source]] + url = "https://private-site.org/pypi/simple" + verify_ssl = true + name = "internal" + `, + 'pyproject.toml' + ); + + expect(result?.deps).toEqual([ + { + packageName: 'packaging', + depName: 'packaging', + datasource: 'pypi', + depType: 'project.dependencies', + currentValue: '>=20.9,!=22.0', + registryUrls: [ + 'https://pypi.org/pypi/', + 'https://private-site.org/pypi/simple', + ], + }, + ]); + }); + }); +}); diff --git a/lib/modules/manager/pep621/extract.ts b/lib/modules/manager/pep621/extract.ts new file mode 100644 index 00000000000000..09064595188470 --- /dev/null +++ b/lib/modules/manager/pep621/extract.ts @@ -0,0 +1,51 @@ +import toml from '@iarna/toml'; +import { logger } from '../../../logger'; +import type { + ExtractConfig, + PackageDependency, + PackageFileContent, +} from '../types'; +import { processors } from './processors'; +import { PyProject, PyProjectSchema } from './schema'; +import { parseDependencyGroupRecord, parseDependencyList } from './utils'; + +export function extractPackageFile( + content: string, + fileName: string, + config?: ExtractConfig +): PackageFileContent | null { + logger.trace({ fileName }, 'pep621.extractPackageFile'); + + const deps: PackageDependency[] = []; + + let def: PyProject; + try { + const jsonMap = toml.parse(content); + def = PyProjectSchema.parse(jsonMap); + } catch (err) { + logger.warn( + { fileName, err }, + `Failed to parse and validate pyproject file` + ); + return null; + } + + // pyProject standard definitions + deps.push( + ...parseDependencyList('project.dependencies', def.project?.dependencies) + ); + deps.push( + ...parseDependencyGroupRecord( + 'project.optional-dependencies', + def.project?.['optional-dependencies'] + ) + ); + + // process specific tool sets + let processedDeps = deps; + for (const processor of processors) { + processedDeps = processor.process(def, processedDeps); + } + + return processedDeps.length ? { deps: processedDeps } : null; +} diff --git a/lib/modules/manager/pep621/index.ts b/lib/modules/manager/pep621/index.ts new file mode 100644 index 00000000000000..9b1adb54893e40 --- /dev/null +++ b/lib/modules/manager/pep621/index.ts @@ -0,0 +1,8 @@ +import { PypiDatasource } from '../../datasource/pypi'; +export { extractPackageFile } from './extract'; + +export const supportedDatasources = [PypiDatasource.id]; + +export const defaultConfig = { + fileMatch: ['(^|/)pyproject\\.toml$'], +}; diff --git a/lib/modules/manager/pep621/processors/index.ts b/lib/modules/manager/pep621/processors/index.ts new file mode 100644 index 00000000000000..ba80de12ccbe20 --- /dev/null +++ b/lib/modules/manager/pep621/processors/index.ts @@ -0,0 +1,3 @@ +import { PdmProcessor } from './pdm'; + +export const processors = [new PdmProcessor()]; diff --git a/lib/modules/manager/pep621/processors/pdm.ts b/lib/modules/manager/pep621/processors/pdm.ts new file mode 100644 index 00000000000000..e362694b55a745 --- /dev/null +++ b/lib/modules/manager/pep621/processors/pdm.ts @@ -0,0 +1,42 @@ +import is from '@sindresorhus/is'; +import { PypiDatasource } from '../../../datasource/pypi'; +import type { PackageDependency } from '../../types'; +import type { PyProject } from '../schema'; +import { parseDependencyGroupRecord } from '../utils'; +import type { PyProjectProcessor } from './types'; + +export class PdmProcessor implements PyProjectProcessor { + process(project: PyProject, deps: PackageDependency[]): PackageDependency[] { + const pdm = project.tool?.pdm; + if (is.nullOrUndefined(pdm)) { + return deps; + } + + deps.push( + ...parseDependencyGroupRecord( + 'tool.pdm.dev-dependencies', + pdm['dev-dependencies'] + ) + ); + + const pdmSource = pdm.source; + if (is.nullOrUndefined(pdmSource)) { + return deps; + } + + // add pypi default url, if there is no source declared with the name `pypi`. https://daobook.github.io/pdm/pyproject/tool-pdm/#specify-other-sources-for-finding-packages + const containsPyPiUrl = pdmSource.some((value) => value.name === 'pypi'); + const registryUrls: string[] = []; + if (!containsPyPiUrl) { + registryUrls.push(PypiDatasource.defaultURL); + } + for (const source of pdmSource) { + registryUrls.push(source.url); + } + for (const dep of deps) { + dep.registryUrls = registryUrls; + } + + return deps; + } +} diff --git a/lib/modules/manager/pep621/processors/types.ts b/lib/modules/manager/pep621/processors/types.ts new file mode 100644 index 00000000000000..dbe645396e76c2 --- /dev/null +++ b/lib/modules/manager/pep621/processors/types.ts @@ -0,0 +1,12 @@ +import type { PackageDependency } from '../../types'; +import type { PyProject } from '../schema'; + +export interface PyProjectProcessor { + /** + * Extracts additional dependencies and/or modifies existing ones based on the tool configuration. + * If no relevant section for the processor exists, then it should return the received dependencies unmodified. + * @param project PyProject object + * @param deps List of already extracted/processed dependencies + */ + process(project: PyProject, deps: PackageDependency[]): PackageDependency[]; +} diff --git a/lib/modules/manager/pep621/readme.md b/lib/modules/manager/pep621/readme.md new file mode 100644 index 00000000000000..1b52481f7d6b97 --- /dev/null +++ b/lib/modules/manager/pep621/readme.md @@ -0,0 +1,11 @@ +This manager supports updating dependencies inside of `pyproject.toml` files. + +Outside standard dependencies, following toolsets are supported: + +- `pdm` + +Available `depType`s: + +- `project.dependencies` +- `project.optional-dependencies` +- `tool.pdm.dev-dependencies` diff --git a/lib/modules/manager/pep621/schema.ts b/lib/modules/manager/pep621/schema.ts new file mode 100644 index 00000000000000..04dcc6609ce98c --- /dev/null +++ b/lib/modules/manager/pep621/schema.ts @@ -0,0 +1,35 @@ +import { z } from 'zod'; + +export type PyProject = z.infer; + +const DependencyListSchema = z.array(z.string()).optional(); +const DependencyRecordSchema = z + .record(z.string(), z.array(z.string())) + .optional(); + +export const PyProjectSchema = z.object({ + project: z + .object({ + dependencies: DependencyListSchema, + 'optional-dependencies': DependencyRecordSchema, + }) + .optional(), + tool: z + .object({ + pdm: z + .object({ + 'dev-dependencies': DependencyRecordSchema, + source: z + .array( + z.object({ + url: z.string(), + name: z.string(), + verify_ssl: z.boolean().optional(), + }) + ) + .optional(), + }) + .optional(), + }) + .optional(), +}); diff --git a/lib/modules/manager/pep621/types.ts b/lib/modules/manager/pep621/types.ts new file mode 100644 index 00000000000000..1e68aa19818a84 --- /dev/null +++ b/lib/modules/manager/pep621/types.ts @@ -0,0 +1,6 @@ +export interface Pep508ParseResult { + packageName: string; + currentValue?: string; + extras?: string[]; + marker?: string; +} diff --git a/lib/modules/manager/pep621/utils.spec.ts b/lib/modules/manager/pep621/utils.spec.ts new file mode 100644 index 00000000000000..6029a7b8ec8a51 --- /dev/null +++ b/lib/modules/manager/pep621/utils.spec.ts @@ -0,0 +1,39 @@ +import is from '@sindresorhus/is'; +import { parsePEP508 } from './utils'; + +describe('modules/manager/pep621/utils', () => { + describe('parsePEP508()', () => { + it.each` + value | success | packageName | currentValue | extras | marker + ${''} | ${false} | ${undefined} | ${undefined} | ${undefined} | ${undefined} + ${undefined} | ${false} | ${undefined} | ${undefined} | ${undefined} | ${undefined} + ${null} | ${false} | ${undefined} | ${undefined} | ${undefined} | ${undefined} + ${'blinker'} | ${true} | ${'blinker'} | ${undefined} | ${undefined} | ${undefined} + ${'packaging==20.0.0'} | ${true} | ${'packaging'} | ${'==20.0.0'} | ${undefined} | ${undefined} + ${'packaging>=20.9,!=22.0'} | ${true} | ${'packaging'} | ${'>=20.9,!=22.0'} | ${undefined} | ${undefined} + ${'cachecontrol[filecache]>=0.12.11'} | ${true} | ${'cachecontrol'} | ${'>=0.12.11'} | ${['filecache']} | ${undefined} + ${'tomli>=1.1.0; python_version < "3.11"'} | ${true} | ${'tomli'} | ${'>=1.1.0'} | ${undefined} | ${'python_version < "3.11"'} + ${'typing-extensions; python_version < "3.8"'} | ${true} | ${'typing-extensions'} | ${undefined} | ${undefined} | ${'python_version < "3.8"'} + ${'typing-extensions[test-feature]; python_version < "3.8"'} | ${true} | ${'typing-extensions'} | ${undefined} | ${['test-feature']} | ${'python_version < "3.8"'} + `( + '(parse $value"', + ({ value, success, packageName, currentValue, extras, marker }) => { + const result = parsePEP508(value); + + const expected = is.truthy(success) + ? clear({ packageName, currentValue, extras, marker }) + : null; + expect(result).toEqual(expected); + } + ); + }); +}); + +function clear(a: any) { + Object.keys(a).forEach((key) => { + if (a[key] === undefined) { + delete a[key]; + } + }); + return a; +} diff --git a/lib/modules/manager/pep621/utils.ts b/lib/modules/manager/pep621/utils.ts new file mode 100644 index 00000000000000..8741c28dd46a21 --- /dev/null +++ b/lib/modules/manager/pep621/utils.ts @@ -0,0 +1,101 @@ +import is from '@sindresorhus/is'; +import { logger } from '../../../logger'; +import { regEx } from '../../../util/regex'; +import { PypiDatasource } from '../../datasource/pypi'; +import type { PackageDependency } from '../types'; +import type { Pep508ParseResult } from './types'; + +const pep508Regex = regEx( + /^(?[A-Z0-9._-]+)\s*(\[(?[A-Z0-9,._-]+)\])?\s*(?[^;]+)?(;\s*(?.*))?/i +); + +export function parsePEP508( + value: string | null | undefined +): Pep508ParseResult | null { + if (is.nullOrUndefined(value)) { + return null; + } + + const regExpExec = pep508Regex.exec(value); + if ( + is.nullOrUndefined(regExpExec) || + is.nullOrUndefined(regExpExec?.groups) + ) { + logger.trace(`Pep508 could not be extracted`); + return null; + } + + const result: Pep508ParseResult = { + packageName: regExpExec.groups.packageName, + }; + if (is.nonEmptyString(regExpExec.groups.currentValue)) { + result.currentValue = regExpExec.groups.currentValue; + } + if (is.nonEmptyString(regExpExec.groups.marker)) { + result.marker = regExpExec.groups.marker; + } + if (is.nonEmptyString(regExpExec.groups.extras)) { + result.extras = regExpExec.groups.extras.split(','); + } + + return result; +} + +export function pep508ToPackageDependency( + depType: string, + value: string +): PackageDependency | null { + const parsed = parsePEP508(value); + if (is.nullOrUndefined(parsed)) { + return null; + } + + const dep: PackageDependency = { + packageName: parsed.packageName, + depName: parsed.packageName, + datasource: PypiDatasource.id, + depType, + }; + + if (is.nullOrUndefined(parsed.currentValue)) { + dep.skipReason = 'any-version'; + } else { + dep.currentValue = parsed.currentValue; + } + return dep; +} + +export function parseDependencyGroupRecord( + depType: string, + records: Record | null | undefined +): PackageDependency[] { + if (is.nullOrUndefined(records)) { + return []; + } + + const deps: PackageDependency[] = []; + for (const [groupName, pep508Strings] of Object.entries(records)) { + for (const dep of parseDependencyList(depType, pep508Strings)) { + deps.push({ ...dep, depName: `${groupName}/${dep.packageName!}` }); + } + } + return deps; +} + +export function parseDependencyList( + depType: string, + list: string[] | null | undefined +): PackageDependency[] { + if (is.nullOrUndefined(list)) { + return []; + } + + const deps: PackageDependency[] = []; + for (const element of list) { + const dep = pep508ToPackageDependency(depType, element); + if (is.truthy(dep)) { + deps.push(dep); + } + } + return deps; +} From 5b5a1e9534017c1fc3215466f5b3614eb18c751a Mon Sep 17 00:00:00 2001 From: Sergei Zharinov Date: Mon, 15 May 2023 11:17:35 +0300 Subject: [PATCH 32/74] fix(composer): Fix excessive parsing error logging (#22089) --- lib/modules/manager/composer/schema.ts | 50 +++++++++++++++++++------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/lib/modules/manager/composer/schema.ts b/lib/modules/manager/composer/schema.ts index fb8c2a8af2c9d7..5d0ac8e7e4f817 100644 --- a/lib/modules/manager/composer/schema.ts +++ b/lib/modules/manager/composer/schema.ts @@ -26,19 +26,26 @@ export type ComposerRepo = z.infer; export const GitRepo = z.object({ type: z.enum(['vcs', 'git']).transform(() => 'git' as const), url: z.string(), + name: z.string().optional(), }); export type GitRepo = z.infer; export const PathRepo = z.object({ type: z.literal('path'), url: z.string(), + name: z.string().optional(), }); export type PathRepo = z.infer; +export const PackageRepo = z.object({ + type: z.literal('package'), +}); + export const Repo = z.discriminatedUnion('type', [ ComposerRepo, GitRepo, PathRepo, + PackageRepo, ]); export type Repo = z.infer; @@ -46,6 +53,7 @@ export const NamedRepo = z.discriminatedUnion('type', [ ComposerRepo, GitRepo.extend({ name: z.string() }), PathRepo.extend({ name: z.string() }), + PackageRepo, ]); export type NamedRepo = z.infer; @@ -54,7 +62,7 @@ export type DisablePackagist = z.infer; export const ReposRecord = LooseRecord(z.union([Repo, z.literal(false)]), { onError: ({ error: err }) => { - logger.warn({ err }, 'Composer: error parsing repositories object'); + logger.debug({ err }, 'Composer: error parsing repositories object'); }, }).transform((repos) => { const result: (NamedRepo | DisablePackagist)[] = []; @@ -83,7 +91,7 @@ export type ReposRecord = z.infer; export const ReposArray = LooseArray( z.union([ - NamedRepo, + Repo, z .union([ z.object({ packagist: z.literal(false) }), @@ -93,17 +101,28 @@ export const ReposArray = LooseArray( ]), { onError: ({ error: err }) => { - logger.warn({ err }, 'Composer: error parsing repositories array'); + logger.debug({ err }, 'Composer: error parsing repositories array'); }, } -).transform((repos) => repos.filter((x): x is NamedRepo => x !== null)); +).transform((repos) => { + const result: (NamedRepo | DisablePackagist)[] = []; + for (let idx = 0; idx < repos.length; idx++) { + const repo = repos[idx]; + if (repo.type === 'path' || repo.type === 'git') { + result.push({ name: `__${idx}`, ...repo }); + } else { + result.push(repo); + } + } + return result; +}); export type ReposArray = z.infer; export const Repos = z .union([ReposRecord, ReposArray]) .default([]) // Prevents warnings for packages without repositories field .catch(({ error: err }) => { - logger.warn({ err }, 'Composer: repositories parsing error'); + logger.debug({ err }, 'Composer: invalid "repositories" field'); return []; }) .transform((repos) => { @@ -210,13 +229,20 @@ export const ComposerExtract = z lockfile: z .string() .transform((lockfileName) => readLocalFile(lockfileName, 'utf8')) - .pipe(Json) - .pipe(Lockfile) - .nullable() - .catch(({ error: err }) => { - logger.warn({ err }, 'Composer: lockfile parsing error'); - return null; - }), + .pipe( + z.union([ + z.null(), + z + .string() + .pipe(Json) + .pipe(Lockfile) + .nullable() + .catch(({ error: err }) => { + logger.debug({ err }, 'Composer: lockfile parsing error'); + return null; + }), + ]) + ), }) ) .transform(({ file, lockfile, lockfileName }) => { From b08130791e6d519fedcfb4c2663534a8d6e5cfdc Mon Sep 17 00:00:00 2001 From: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> Date: Mon, 15 May 2023 10:39:53 +0200 Subject: [PATCH 33/74] docs(pep621): improve sentences (#22231) --- lib/modules/manager/pep621/readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/modules/manager/pep621/readme.md b/lib/modules/manager/pep621/readme.md index 1b52481f7d6b97..96fcde1007a12a 100644 --- a/lib/modules/manager/pep621/readme.md +++ b/lib/modules/manager/pep621/readme.md @@ -1,6 +1,6 @@ -This manager supports updating dependencies inside of `pyproject.toml` files. +This manager supports updating dependencies inside `pyproject.toml` files. -Outside standard dependencies, following toolsets are supported: +In addition to standard dependencies, these toolsets are also supported: - `pdm` From 9f9c1d9f9dca9a32a2de362da0cde1d5bc9689ec Mon Sep 17 00:00:00 2001 From: IKEDA Sho Date: Mon, 15 May 2023 18:53:23 +0900 Subject: [PATCH 34/74] feat(manager): add cpanfile manager (#21152) --- lib/modules/manager/api.ts | 2 + lib/modules/manager/cpanfile/extract.spec.ts | 285 +++++++++++++++++++ lib/modules/manager/cpanfile/extract.ts | 16 ++ lib/modules/manager/cpanfile/index.ts | 17 ++ lib/modules/manager/cpanfile/language.ts | 44 +++ lib/modules/manager/cpanfile/parser.ts | 146 ++++++++++ lib/modules/manager/cpanfile/readme.md | 1 + 7 files changed, 511 insertions(+) create mode 100644 lib/modules/manager/cpanfile/extract.spec.ts create mode 100644 lib/modules/manager/cpanfile/extract.ts create mode 100644 lib/modules/manager/cpanfile/index.ts create mode 100644 lib/modules/manager/cpanfile/language.ts create mode 100644 lib/modules/manager/cpanfile/parser.ts create mode 100644 lib/modules/manager/cpanfile/readme.md diff --git a/lib/modules/manager/api.ts b/lib/modules/manager/api.ts index fcd8aca94e6e2a..939a55fe1c58d6 100644 --- a/lib/modules/manager/api.ts +++ b/lib/modules/manager/api.ts @@ -19,6 +19,7 @@ import * as cloudbuild from './cloudbuild'; import * as cocoapods from './cocoapods'; import * as composer from './composer'; import * as conan from './conan'; +import * as cpanfile from './cpanfile'; import * as depsEdn from './deps-edn'; import * as dockerCompose from './docker-compose'; import * as dockerfile from './dockerfile'; @@ -108,6 +109,7 @@ api.set('cloudbuild', cloudbuild); api.set('cocoapods', cocoapods); api.set('composer', composer); api.set('conan', conan); +api.set('cpanfile', cpanfile); api.set('deps-edn', depsEdn); api.set('docker-compose', dockerCompose); api.set('dockerfile', dockerfile); diff --git a/lib/modules/manager/cpanfile/extract.spec.ts b/lib/modules/manager/cpanfile/extract.spec.ts new file mode 100644 index 00000000000000..5235cf3a594f95 --- /dev/null +++ b/lib/modules/manager/cpanfile/extract.spec.ts @@ -0,0 +1,285 @@ +import { codeBlock } from 'common-tags'; +import { extractPackageFile } from './extract'; + +describe('modules/manager/cpanfile/extract', () => { + describe('extractPackageFile()', () => { + it('returns null for empty', () => { + expect(extractPackageFile('', 'cpanfile')).toBeNull(); + expect(extractPackageFile('nothing here', 'cpanfile')).toBeNull(); + }); + + describe('parse perl', () => { + test.each` + version | expected + ${'5.012005'} | ${'5.012005'} + ${`'5.008001'`} | ${'5.008001'} + ${`"5.008001"`} | ${'5.008001'} + `('$version', ({ version, expected }) => { + expect( + extractPackageFile( + `requires 'perl', ${version as string};`, + 'cpanfile' + ) + ).toEqual({ + deps: [ + { + versioning: 'perl', + depName: 'perl', + packageName: 'Perl/perl5', + currentValue: expected, + datasource: 'github-tags', + extractVersion: '^v(?\\S+)', + }, + ], + extractedConstraints: { perl: expected }, + }); + }); + }); + + it('parse modules with requires', () => { + expect( + extractPackageFile( + codeBlock` + requires 'Try::Tiny'; + requires 'URI', '1.59'; + requires 'HTTP::Tiny', 0.034; + requires "Capture::Tiny" => "0"; + `, + 'cpanfile' + ) + ).toEqual({ + deps: [ + { + datasource: 'cpan', + depName: 'Try::Tiny', + skipReason: 'no-version', + }, + { + datasource: 'cpan', + depName: 'URI', + currentValue: '1.59', + }, + { + datasource: 'cpan', + depName: 'HTTP::Tiny', + currentValue: '0.034', + }, + { + datasource: 'cpan', + depName: 'Capture::Tiny', + currentValue: '0', + }, + ], + }); + }); + + it('parse modules with recommends', () => { + expect( + extractPackageFile( + codeBlock` + recommends 'Crypt::URandom'; + recommends 'HTTP::XSCookies', '0.000015'; + `, + 'cpanfile' + ) + ).toEqual({ + deps: [ + { + datasource: 'cpan', + depName: 'Crypt::URandom', + skipReason: 'no-version', + }, + { + datasource: 'cpan', + depName: 'HTTP::XSCookies', + currentValue: '0.000015', + }, + ], + }); + }); + + it('parse modules with suggests', () => { + expect( + extractPackageFile( + codeBlock` + suggests 'Test::MockTime::HiRes', '0.06'; + suggests 'Authen::Simple::Passwd'; + `, + 'cpanfile' + ) + ).toEqual({ + deps: [ + { + datasource: 'cpan', + depName: 'Test::MockTime::HiRes', + currentValue: '0.06', + }, + { + datasource: 'cpan', + depName: 'Authen::Simple::Passwd', + skipReason: 'no-version', + }, + ], + }); + }); + + describe('parse modules with phases', () => { + test('configure phase', () => { + expect( + extractPackageFile( + codeBlock` + on 'configure' => sub { + requires "ExtUtils::MakeMaker" => "0"; + }; + `, + 'cpanfile' + ) + ).toEqual({ + deps: [ + { + datasource: 'cpan', + depName: 'ExtUtils::MakeMaker', + currentValue: '0', + depType: 'configure', + }, + ], + }); + }); + + test('build phase', () => { + expect( + extractPackageFile( + codeBlock` + on build => sub { + requires 'Test::More', '0.98'; + }; + `, + 'cpanfile' + ) + ).toEqual({ + deps: [ + { + datasource: 'cpan', + depName: 'Test::More', + currentValue: '0.98', + depType: 'build', + }, + ], + }); + }); + + test('test phase', () => { + expect( + extractPackageFile( + codeBlock` + on test => sub { + requires 'Test::More', '0.88'; + requires 'Test::Requires'; + }; + `, + 'cpanfile' + ) + ).toEqual({ + deps: [ + { + datasource: 'cpan', + depName: 'Test::More', + currentValue: '0.88', + depType: 'test', + }, + { + datasource: 'cpan', + depName: 'Test::Requires', + depType: 'test', + skipReason: 'no-version', + }, + ], + }); + }); + + test('runtime phase', () => { + expect( + extractPackageFile( + codeBlock` + on runtime => sub { + suggests 'FCGI'; + suggests 'FCGI::ProcManager'; + }; + `, + 'cpanfile' + ) + ).toEqual({ + deps: [ + { + datasource: 'cpan', + depName: 'FCGI', + depType: 'runtime', + skipReason: 'no-version', + }, + { + datasource: 'cpan', + depName: 'FCGI::ProcManager', + depType: 'runtime', + skipReason: 'no-version', + }, + ], + }); + }); + + test('develop phase', () => { + expect( + extractPackageFile( + codeBlock` + on 'develop' => sub { + requires "IPC::Open3" => "0"; + requires "Term::Table" => "0.013"; + }; + `, + 'cpanfile' + ) + ).toEqual({ + deps: [ + { + datasource: 'cpan', + depName: 'IPC::Open3', + currentValue: '0', + depType: 'develop', + }, + { + datasource: 'cpan', + depName: 'Term::Table', + currentValue: '0.013', + depType: 'develop', + }, + ], + }); + }); + }); + + describe('parse modules with phase shortcuts', () => { + test.each` + shortcut | phase + ${'configure_requires'} | ${'configure'} + ${'build_requires'} | ${'build'} + ${'test_requires'} | ${'test'} + ${'author_requires'} | ${'develop'} + `('$shortcut', ({ shortcut, phase }) => { + expect( + extractPackageFile( + `${shortcut as string} 'Capture::Tiny', '0.12';`, + 'cpanfile' + ) + ).toEqual({ + deps: [ + { + datasource: 'cpan', + depName: 'Capture::Tiny', + currentValue: '0.12', + depType: phase, + }, + ], + }); + }); + }); + }); +}); diff --git a/lib/modules/manager/cpanfile/extract.ts b/lib/modules/manager/cpanfile/extract.ts new file mode 100644 index 00000000000000..6caee1cc7ca16d --- /dev/null +++ b/lib/modules/manager/cpanfile/extract.ts @@ -0,0 +1,16 @@ +import type { PackageFileContent } from '../types'; +import { parse } from './parser'; + +export function extractPackageFile( + content: string, + packageFile?: string +): PackageFileContent | null { + const result = parse(content); + if (!result?.deps.length) { + return null; + } + + const { deps, perlVersion } = result; + const extractedConstraints = perlVersion ? { perl: perlVersion } : undefined; + return { deps, ...(extractedConstraints && { extractedConstraints }) }; +} diff --git a/lib/modules/manager/cpanfile/index.ts b/lib/modules/manager/cpanfile/index.ts new file mode 100644 index 00000000000000..3d09e935f5b5c3 --- /dev/null +++ b/lib/modules/manager/cpanfile/index.ts @@ -0,0 +1,17 @@ +import { CpanDatasource } from '../../datasource/cpan'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; + +export { extractPackageFile } from './extract'; + +export const displayName = 'cpanfile'; +export const url = + 'https://metacpan.org/dist/Module-CPANfile/view/lib/cpanfile.pod'; + +export const defaultConfig = { + fileMatch: ['(^|/)cpanfile$'], +}; + +export const supportedDatasources = [ + CpanDatasource.id, + GithubTagsDatasource.id, +]; diff --git a/lib/modules/manager/cpanfile/language.ts b/lib/modules/manager/cpanfile/language.ts new file mode 100644 index 00000000000000..9a7f00a31d365f --- /dev/null +++ b/lib/modules/manager/cpanfile/language.ts @@ -0,0 +1,44 @@ +import { lexer as l, lang, parser as p } from 'good-enough-parser'; + +/** + * @see https://perldoc.perl.org/perldata#Scalar-value-constructors + */ +const bindigit = '[01]'; +const octdigit = '[0-7]'; +const digit = '[0-9]'; +const nonzerodigit = '[1-9]'; +const hexdigit = `(?:${digit}|[a-fA-F])`; + +const bininteger = `(?:0[bB](?:_?${bindigit})+)`; +const octinteger = `(?:0(?:_?${octdigit})+)`; +const hexinteger = `(?:0[xX](?:_?${hexdigit})+)`; +const decinteger = `(?:${nonzerodigit}(?:_?${digit})*|0+(?:_?0)*)`; +const integer = `(?:${decinteger}|${bininteger}|${octinteger}|${hexinteger})`; + +const digitpart = `(?:${digit}(?:_?${digit})*)`; +const fraction = `(?:\\.${digitpart})`; +const exponent = `(?:[eE][-+]?${digitpart})`; +const pointfloat = `(?:${digitpart}?${fraction}|${digitpart}\\.)`; +const exponentfloat = `(?:(?:${digitpart}|${pointfloat})${exponent})`; +const floatnumber = `(?:${pointfloat}|${exponentfloat})`; + +const numbers = new RegExp(`(?:${floatnumber}|${integer})`); + +const lexer: l.LexerConfig = { + joinLines: null, + comments: [{ type: 'line-comment', startsWith: '#' }], + symbols: /[_a-zA-Z][_a-zA-Z0-9]*/, + numbers, + operators: ['==', '>=', '>', '=>', ',', ';'], + brackets: [ + { startsWith: '{', endsWith: '}' }, + { startsWith: '(', endsWith: ')' }, + ], + strings: [{ startsWith: "'" }, { startsWith: '"' }], +}; + +const parser: p.ParserConfig = { + useIndentBlocks: false, +}; + +export const cpanfile = lang.createLang({ lexer, parser }); diff --git a/lib/modules/manager/cpanfile/parser.ts b/lib/modules/manager/cpanfile/parser.ts new file mode 100644 index 00000000000000..da9014421700a7 --- /dev/null +++ b/lib/modules/manager/cpanfile/parser.ts @@ -0,0 +1,146 @@ +import { query as q } from 'good-enough-parser'; +import { CpanDatasource } from '../../datasource/cpan'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; +import * as perlVersioning from '../../versioning/perl'; +import type { PackageDependency } from '../types'; +import { cpanfile } from './language'; + +interface Ctx { + deps: PackageDependency[]; + + perlVersion?: string; + + phase?: string; + tempPhase?: string; + + depName?: string; + currentValue?: string; +} + +// requires perl, '5.36.1'; +// requires 'perl' => 5.036001; +const perlVersionMatch = q + .sym('requires') + .alt(q.sym('perl'), q.str('perl')) + .alt(q.op(','), q.op('=>')) + .alt( + q.num((ctx, { value: perlVersion }) => ({ ...ctx, perlVersion })), + q.str((ctx, { value: perlVersion }) => ({ ...ctx, perlVersion })) + ) + .op(';') + .handler((ctx) => { + if (ctx.perlVersion) { + ctx.deps.push({ + depName: 'perl', + packageName: 'Perl/perl5', + currentValue: ctx.perlVersion, + datasource: GithubTagsDatasource.id, + versioning: perlVersioning.id, + extractVersion: '^v(?\\S+)', + }); + } + return ctx; + }); + +const requirementMatch = q.sym(/^(?:requires|recommends|suggests)$/); + +const phasedRequiresMatch = q.sym( + /^(?:configure|build|test|author)_requires$/, + (ctx, { value: phase }) => { + ctx.tempPhase = phase.replace(/_requires/, '').replace(/author/, 'develop'); + return ctx; + } +); + +// requires 'Foo::Bar'; +// +// requires 'Foo::Bar', '1.23'; +// recommends 'Foo::Bar', '1.23'; +// suggests 'Foo::Bar', '1.23'; +// +// configure_requires 'Foo::Bar' => 1.023; +// build_requires 'Foo::Bar' => 1.023; +// test_requires 'Foo::Bar' => 1.023; +// author_requires 'Foo::Bar' => 1.023; +const moduleMatch = q + .alt(requirementMatch, phasedRequiresMatch) + .str((ctx, { value: depName }) => ({ ...ctx, depName })) + .opt( + q.alt(q.op(','), q.op('=>')).alt( + q.num((ctx, { value: currentValue }) => ({ ...ctx, currentValue })), + q.str((ctx, { value }) => { + const currentValue = value.replace(/^(?:\s*(?:==|>=|>))?\s*v/, ''); + return { ...ctx, currentValue }; + }) + ) + ) + .op(';') + .handler((ctx) => { + const { phase, tempPhase, depName, currentValue } = ctx; + + delete ctx.tempPhase; + delete ctx.depName; + delete ctx.currentValue; + + if (depName) { + const dep: PackageDependency = { + depName, + }; + if (currentValue) { + dep.currentValue = currentValue; + } else { + dep.skipReason = 'no-version'; + } + if (phase) { + dep.depType = phase; + } else if (tempPhase) { + dep.depType = tempPhase; + } + + dep.datasource = CpanDatasource.id; + ctx.deps.push(dep); + } + + return ctx; + }); + +const phaseRegex = /^(?:configure|build|test|runtime|develop)/; + +const phaseMatch = q.alt( + q.sym(phaseRegex, (ctx, { value: phase }) => ({ ...ctx, phase })), + q.str(phaseRegex, (ctx, { value: phase }) => ({ ...ctx, phase })) +); + +// on 'configure' => sub { +// on build => sub { +// on 'test' => sub { +// on runtime => sub { +// on 'develop' => sub { +const onMatch = q + .sym('on') + .join(phaseMatch) + .op('=>') + .sym('sub') + .tree({ + type: 'wrapped-tree', + maxDepth: 1, + search: moduleMatch, + }) + .handler((ctx) => { + delete ctx.phase; + return ctx; + }); + +const query = q.tree({ + type: 'root-tree', + maxDepth: 4, + search: q.alt(perlVersionMatch, moduleMatch, onMatch), +}); + +export function parse( + content: string +): Pick | null { + return cpanfile.query(content, query, { + deps: [], + }); +} diff --git a/lib/modules/manager/cpanfile/readme.md b/lib/modules/manager/cpanfile/readme.md new file mode 100644 index 00000000000000..8653ea9f51b192 --- /dev/null +++ b/lib/modules/manager/cpanfile/readme.md @@ -0,0 +1 @@ +The `cpanfile` manager is used to extract dependencies from `cpanfile`. From a732b39985784c0e7bd77bcca3800446e82eae66 Mon Sep 17 00:00:00 2001 From: Sergei Zharinov Date: Mon, 15 May 2023 15:16:51 +0300 Subject: [PATCH 35/74] fix(rubygems): Remove verbose debug logging (#22235) --- lib/modules/datasource/rubygems/versions-datasource.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/modules/datasource/rubygems/versions-datasource.ts b/lib/modules/datasource/rubygems/versions-datasource.ts index 5122bd759a8b36..1e56a5d89958e8 100644 --- a/lib/modules/datasource/rubygems/versions-datasource.ts +++ b/lib/modules/datasource/rubygems/versions-datasource.ts @@ -45,15 +45,7 @@ const Lines = z } } return { packageName, deletedVersions, addedVersions }; - }), - { - onError: ({ error: err, input }) => { - logger.debug( - { err, input }, - 'Rubygems: failed to parse some version lines' - ); - }, - } + }) ) ); type Lines = z.infer; From d54ecb1f7f4c5d59655dacc836617462041881ed Mon Sep 17 00:00:00 2001 From: Andy Roth Date: Mon, 15 May 2023 09:21:57 -0700 Subject: [PATCH 36/74] feat(asdf): Add support for more ASDF plugins (#21942) Co-authored-by: Michael Kriese --- lib/modules/manager/asdf/extract.spec.ts | 81 ++++++++++++++++++- .../manager/asdf/upgradeable-tooling.ts | 78 ++++++++++++++++++ 2 files changed, 158 insertions(+), 1 deletion(-) diff --git a/lib/modules/manager/asdf/extract.spec.ts b/lib/modules/manager/asdf/extract.spec.ts index 4b9e67bf232326..931981f69c5491 100644 --- a/lib/modules/manager/asdf/extract.spec.ts +++ b/lib/modules/manager/asdf/extract.spec.ts @@ -43,10 +43,13 @@ describe('modules/manager/asdf/extract', () => { it('can handle multiple tools in one file', () => { const res = extractPackageFile( - codeBlock`argocd 2.5.4 + codeBlock` +adr-tools 3.0.0 +argocd 2.5.4 awscli 2.8.6 bun 0.2.2 cargo-make 0.36.2 +checkov 2.3.3 clojure 1.11.1.1182 crystal 1.6.1 dart 2.19.3 @@ -58,9 +61,12 @@ elixir 1.14.1 elm 0.19.1 erlang 25.1.2 flutter 3.7.6 +flux2 0.41.2 gauche 0.9.12 gohugo extended_0.104.3 golang 1.19.2 +golangci-lint 1.52.2 +hadolint 2.12.0 haskell 9.4.2 helm 3.10.1 helmfile 0.147.0 @@ -70,6 +76,7 @@ java adoptopenjdk-16.0.0+36 julia 1.8.2 just 1.7.0 kotlin 1.7.20 +kubectl 1.26.3 kustomize 4.5.7 lua 5.4.4 nim 1.6.8 @@ -79,6 +86,7 @@ perl 5.37.5 php 8.1.12 pnpm 7.26.2 poetry 1.3.2 +pre-commit 3.3.1 pulumi 3.57.1 python 3.11.0 ruby 3.1.2 @@ -87,7 +95,10 @@ scala 3.2.1 shellcheck 0.8.0 shfmt 3.5.1 terraform 1.3.3 +terraform-docs 0.16.0 terragrunt 0.43.2 +tflint 0.44.1 +tfsec 1.28.1 trivy 0.33.0 zig 0.9.1 maestro 1.24.0 @@ -98,6 +109,12 @@ dummy 1.2.3 ); expect(res).toEqual({ deps: [ + { + currentValue: '3.0.0', + datasource: 'github-tags', + packageName: 'npryce/adr-tools', + depName: 'adr-tools', + }, { currentValue: '2.5.4', datasource: 'github-releases', @@ -124,6 +141,12 @@ dummy 1.2.3 packageName: 'sagiegurari/cargo-make', depName: 'cargo-make', }, + { + currentValue: '2.3.3', + datasource: 'github-tags', + packageName: 'bridgecrewio/checkov', + depName: 'checkov', + }, { currentValue: '1.11.1.1182', datasource: 'github-tags', @@ -195,6 +218,13 @@ dummy 1.2.3 datasource: 'flutter-version', depName: 'flutter', }, + { + currentValue: '0.41.2', + datasource: 'github-tags', + packageName: 'fluxcd/flux2', + depName: 'flux2', + extractVersion: '^v(?.+)', + }, { currentValue: '0.9.12', datasource: 'docker', @@ -215,6 +245,20 @@ dummy 1.2.3 depName: 'golang', extractVersion: '^go(?\\S+)', }, + { + currentValue: '1.52.2', + datasource: 'github-tags', + packageName: 'golangci/golangci-lint', + depName: 'golangci-lint', + extractVersion: '^v(?.+)', + }, + { + currentValue: '2.12.0', + datasource: 'github-tags', + packageName: 'hadolint/hadolint', + depName: 'hadolint', + extractVersion: '^v(?.+)', + }, { currentValue: '9.4.2', datasource: 'github-tags', @@ -276,6 +320,13 @@ dummy 1.2.3 depName: 'kotlin', extractVersion: '^(Kotlin |v)(?\\S+)', }, + { + currentValue: '1.26.3', + datasource: 'github-tags', + packageName: 'kubernetes/kubernetes', + depName: 'kubectl', + extractVersion: '^v(?.+)', + }, { currentValue: '4.5.7', datasource: 'github-releases', @@ -335,6 +386,13 @@ dummy 1.2.3 packageName: 'poetry', depName: 'poetry', }, + { + currentValue: '3.3.1', + datasource: 'github-tags', + packageName: 'pre-commit/pre-commit', + depName: 'pre-commit', + extractVersion: '^v(?.+)', + }, { currentValue: '3.57.1', datasource: 'github-releases', @@ -389,6 +447,13 @@ dummy 1.2.3 depName: 'terraform', extractVersion: '^v(?\\S+)', }, + { + currentValue: '0.16.0', + datasource: 'github-tags', + packageName: 'terraform-docs/terraform-docs', + depName: 'terraform-docs', + extractVersion: '^v(?.+)', + }, { currentValue: '0.43.2', datasource: 'github-releases', @@ -396,6 +461,20 @@ dummy 1.2.3 depName: 'terragrunt', extractVersion: '^v(?\\S+)', }, + { + currentValue: '0.44.1', + datasource: 'github-tags', + packageName: 'terraform-linters/tflint', + depName: 'tflint', + extractVersion: '^v(?.+)', + }, + { + currentValue: '1.28.1', + datasource: 'github-tags', + packageName: 'aquasecurity/tfsec', + depName: 'tfsec', + extractVersion: '^v(?.+)', + }, { currentValue: '0.33.0', datasource: 'github-releases', diff --git a/lib/modules/manager/asdf/upgradeable-tooling.ts b/lib/modules/manager/asdf/upgradeable-tooling.ts index 921d1274af0276..3aefeb62c8dc30 100644 --- a/lib/modules/manager/asdf/upgradeable-tooling.ts +++ b/lib/modules/manager/asdf/upgradeable-tooling.ts @@ -38,6 +38,13 @@ const hugoDefinition: ToolingDefinition = { }; export const upgradeableTooling: Record = { + 'adr-tools': { + asdfPluginUrl: 'https://gitlab.com/td7x/asdf/adr-tools.git', + config: { + datasource: GithubTagsDatasource.id, + packageName: 'npryce/adr-tools', + }, + }, argocd: { asdfPluginUrl: 'https://github.com/beardix/asdf-argocd', config: { @@ -68,6 +75,13 @@ export const upgradeableTooling: Record = { packageName: 'sagiegurari/cargo-make', }, }, + checkov: { + asdfPluginUrl: 'https://github.com/bosmak/asdf-checkov.git', + config: { + datasource: GithubTagsDatasource.id, + packageName: 'bridgecrewio/checkov', + }, + }, clojure: { asdfPluginUrl: 'https://github.com/asdf-community/asdf-clojure', config: { @@ -148,6 +162,14 @@ export const upgradeableTooling: Record = { datasource: FlutterVersionDatasource.id, }, }, + flux2: { + asdfPluginUrl: 'https://github.com/tablexi/asdf-flux2.git', + config: { + datasource: GithubTagsDatasource.id, + packageName: 'fluxcd/flux2', + extractVersion: '^v(?.+)', + }, + }, gauche: { asdfPluginUrl: 'https://github.com/sakuro/asdf-gauche', config: { @@ -164,6 +186,22 @@ export const upgradeableTooling: Record = { extractVersion: '^go(?\\S+)', }, }, + 'golangci-lint': { + asdfPluginUrl: 'https://github.com/hypnoglow/asdf-golangci-lint.git', + config: { + datasource: GithubTagsDatasource.id, + packageName: 'golangci/golangci-lint', + extractVersion: '^v(?.+)', + }, + }, + hadolint: { + asdfPluginUrl: 'https://github.com/looztra/asdf-hadolint.git', + config: { + datasource: GithubTagsDatasource.id, + packageName: 'hadolint/hadolint', + extractVersion: '^v(?.+)', + }, + }, haskell: { asdfPluginUrl: 'https://github.com/asdf-community/asdf-haskell', config: { @@ -247,6 +285,14 @@ export const upgradeableTooling: Record = { extractVersion: '^(Kotlin |v)(?\\S+)', }, }, + kubectl: { + asdfPluginUrl: 'https://github.com/Banno/asdf-kubectl.git', + config: { + datasource: GithubTagsDatasource.id, + packageName: 'kubernetes/kubernetes', + extractVersion: '^v(?.+)', + }, + }, kustomize: { asdfPluginUrl: 'https://github.com/Banno/asdf-kustomize', config: { @@ -316,6 +362,14 @@ export const upgradeableTooling: Record = { packageName: 'poetry', }, }, + 'pre-commit': { + asdfPluginUrl: 'https://github.com/jonathanmorley/asdf-pre-commit.git', + config: { + datasource: GithubTagsDatasource.id, + packageName: 'pre-commit/pre-commit', + extractVersion: '^v(?.+)', + }, + }, pulumi: { asdfPluginUrl: 'https://github.com/canha/asdf-pulumi.git', config: { @@ -399,6 +453,14 @@ export const upgradeableTooling: Record = { extractVersion: '^v(?\\S+)', }, }, + 'terraform-docs': { + asdfPluginUrl: 'https://github.com/looztra/asdf-terraform-docs.git', + config: { + datasource: GithubTagsDatasource.id, + packageName: 'terraform-docs/terraform-docs', + extractVersion: '^v(?.+)', + }, + }, terragrunt: { asdfPluginUrl: 'https://github.com/ohmer/asdf-terragrunt', config: { @@ -407,6 +469,22 @@ export const upgradeableTooling: Record = { extractVersion: '^v(?\\S+)', }, }, + tflint: { + asdfPluginUrl: 'https://github.com/skyzyx/asdf-tflint.git', + config: { + datasource: GithubTagsDatasource.id, + packageName: 'terraform-linters/tflint', + extractVersion: '^v(?.+)', + }, + }, + tfsec: { + asdfPluginUrl: 'https://github.com/woneill/asdf-tfsec.git', + config: { + datasource: GithubTagsDatasource.id, + packageName: 'aquasecurity/tfsec', + extractVersion: '^v(?.+)', + }, + }, trivy: { asdfPluginUrl: 'https://github.com/zufardhiyaulhaq/asdf-trivy', config: { From e765e72e7cfe8a2d3d4bd00055eafd7aada34f2c Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Mon, 15 May 2023 20:03:31 +0200 Subject: [PATCH 37/74] feat(yarn): handle yarn 3 lock file for updateLockedDependency (#21966) Co-authored-by: Michael Kriese --- .../yarn-lock/__fixtures__/3.yarn.lock | 49 +++++++++-- .../yarn-lock/get-locked.spec.ts | 41 ++------- .../locked-dependency/yarn-lock/get-locked.ts | 83 +++++++++++++++---- 3 files changed, 116 insertions(+), 57 deletions(-) diff --git a/lib/modules/manager/npm/update/locked-dependency/yarn-lock/__fixtures__/3.yarn.lock b/lib/modules/manager/npm/update/locked-dependency/yarn-lock/__fixtures__/3.yarn.lock index 15ed204e76c285..370eb3df7bd6a8 100644 --- a/lib/modules/manager/npm/update/locked-dependency/yarn-lock/__fixtures__/3.yarn.lock +++ b/lib/modules/manager/npm/update/locked-dependency/yarn-lock/__fixtures__/3.yarn.lock @@ -1,11 +1,46 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! +__metadata: + version: 7 + cacheKey: 9 -"@actions/core@1.6.0", "@actions/core@^1.2.0", "@actions/core@^1.2.6": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.6.0.tgz#0568e47039bfb6a9170393a73f3b7eb3b22462cb" - integrity sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw== +"@actions/core@npm:^1.2.6": + version: 1.2.6 + resolution: "@actions/core@npm:1.2.6" + checksum: 034e57fcb5f944d5fb0ef55be1b212dd88e23d1a50aaffda874cb94e8f4bfa633a66f108f26e81a7cce287cd2b349aa88c97d2023135c8879495326db37a7feb + languageName: node + linkType: hard + +"@algolia/autocomplete-core@npm:1.7.1": + version: 1.7.1 + resolution: "@algolia/autocomplete-core@npm:1.7.1" + dependencies: + "@algolia/autocomplete-shared": "npm:1.7.1" + checksum: db772275618c3844b411a66195403f2b118758b52b94fd292fef9569b3e1d90ee1bfdee7473a90e114e8ee58e867fa197f011721ebc704ed3cd253b2edcc78e4 + languageName: node + linkType: hard + +"@algolia/autocomplete-preset-algolia@npm:1.7.1": + version: 1.7.1 + resolution: "@algolia/autocomplete-preset-algolia@npm:1.7.1" dependencies: - "@actions/http-client" "^1.0.11" + "@algolia/autocomplete-shared": "npm:1.7.1" + peerDependencies: + "@algolia/client-search": ^4.9.1 + algoliasearch: ^4.9.1 + checksum: b110379b1bf49a230a35cbf167c858d480f196480474ef954a64e822c46e5e2a39eae2440a2c1c5f6beb96f51f8a5c75ba05586defa611a4cf32b4208ad29ce2 + languageName: node + linkType: hard +"@strictsoftware/typedoc-plugin-monorepo@patch:@strictsoftware/typedoc-plugin-monorepo@^0.2.2#./.patches/@strictsoftware/typedoc-plugin-monorepo.patch::locator=%40yarnpkg%2Fgatsby%40workspace%3Apackages%2Fgatsby": + version: 0.2.2 + resolution: "@strictsoftware/typedoc-plugin-monorepo@patch:@strictsoftware/typedoc-plugin-monorepo@npm%3A0.2.2#./.patches/@strictsoftware/typedoc-plugin-monorepo.patch::version=0.2.2&hash=dc07b1&locator=%40yarnpkg%2Fgatsby%40workspace%3Apackages%2Fgatsby" + dependencies: + highlight.js: "npm:^9.15.6" + marked: "npm:^0.8.0" + peerDependencies: + typedoc: ">=0.8 <1.0" + checksum: 25b9eb5ad9e5028c7cf320ab6c458af535ed2ec3e1bdfd7d71daf1f8cb33ae684823064a889a63695db4686c2830bd118f792282b82d31e579c4a1e495ce473a + languageName: node + linkType: hard diff --git a/lib/modules/manager/npm/update/locked-dependency/yarn-lock/get-locked.spec.ts b/lib/modules/manager/npm/update/locked-dependency/yarn-lock/get-locked.spec.ts index 3d6e8aa598037a..0995f696e188db 100644 --- a/lib/modules/manager/npm/update/locked-dependency/yarn-lock/get-locked.spec.ts +++ b/lib/modules/manager/npm/update/locked-dependency/yarn-lock/get-locked.spec.ts @@ -26,46 +26,19 @@ describe('modules/manager/npm/update/locked-dependency/yarn-lock/get-locked', () }); it('finds scoped', () => { - expect(getLockedDependencies(yarnLock3, '@actions/core', '1.6.0')) + expect(getLockedDependencies(yarnLock3, '@actions/core', '1.2.6')) .toMatchInlineSnapshot(` [ - { - "constraint": "1.6.0", - "depName": "@actions/core", - "depNameConstraint": "@actions/core@1.6.0", - "entry": { - "dependencies": { - "@actions/http-client": "^1.0.11", - }, - "integrity": "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw==", - "resolved": "https://registry.yarnpkg.com/@actions/core/-/core-1.6.0.tgz#0568e47039bfb6a9170393a73f3b7eb3b22462cb", - "version": "1.6.0", - }, - }, - { - "constraint": "^1.2.0", - "depName": "@actions/core", - "depNameConstraint": "@actions/core@^1.2.0", - "entry": { - "dependencies": { - "@actions/http-client": "^1.0.11", - }, - "integrity": "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw==", - "resolved": "https://registry.yarnpkg.com/@actions/core/-/core-1.6.0.tgz#0568e47039bfb6a9170393a73f3b7eb3b22462cb", - "version": "1.6.0", - }, - }, { "constraint": "^1.2.6", "depName": "@actions/core", - "depNameConstraint": "@actions/core@^1.2.6", + "depNameConstraint": "@actions/core@npm:^1.2.6", "entry": { - "dependencies": { - "@actions/http-client": "^1.0.11", - }, - "integrity": "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw==", - "resolved": "https://registry.yarnpkg.com/@actions/core/-/core-1.6.0.tgz#0568e47039bfb6a9170393a73f3b7eb3b22462cb", - "version": "1.6.0", + "checksum": "034e57fcb5f944d5fb0ef55be1b212dd88e23d1a50aaffda874cb94e8f4bfa633a66f108f26e81a7cce287cd2b349aa88c97d2023135c8879495326db37a7feb", + "languageName": "node", + "linkType": "hard", + "resolution": "@actions/core@npm:1.2.6", + "version": "1.2.6", }, }, ] diff --git a/lib/modules/manager/npm/update/locked-dependency/yarn-lock/get-locked.ts b/lib/modules/manager/npm/update/locked-dependency/yarn-lock/get-locked.ts index 84da024089bd32..7f4f5fa73db189 100644 --- a/lib/modules/manager/npm/update/locked-dependency/yarn-lock/get-locked.ts +++ b/lib/modules/manager/npm/update/locked-dependency/yarn-lock/get-locked.ts @@ -1,8 +1,26 @@ import { logger } from '../../../../../../logger'; import type { YarnLock, YarnLockEntrySummary } from './types'; -// Finds matching dependencies withing a package lock file of sub-entry -export function getLockedDependencies( +export function parseEntry(depNameConstraint: string): { + entryName: string; + constraint: string; +} | null { + let entryName: string; + let constraint: string; + const split = depNameConstraint.split('@'); + if (split.length === 2) { + [entryName, constraint] = split; + } else if (split.length === 3) { + entryName = '@' + split[1]; + constraint = split[2]; + } else { + logger.debug({ depNameConstraint }, 'Unexpected depNameConstraint'); + return null; + } + return { entryName, constraint }; +} + +export function getYarn1LockedDependencies( yarnLock: YarnLock, depName: string, currentVersion: string @@ -10,22 +28,12 @@ export function getLockedDependencies( const res: YarnLockEntrySummary[] = []; try { for (const [depNameConstraint, entry] of Object.entries(yarnLock)) { - let entryName: string; - let constraint: string; - const split = depNameConstraint.split('@'); - // istanbul ignore else - if (split.length === 2) { - [entryName, constraint] = split; - } else if (split.length === 3) { - entryName = '@' + split[1]; - constraint = split[2]; - } else { - logger.debug( - { depNameConstraint, entry }, - 'Unexpected depNameConstraint' - ); + const parsed = parseEntry(depNameConstraint); + // istanbul ignore if + if (!parsed) { continue; } + const { entryName, constraint } = parsed; if (entryName === depName && entry?.version === currentVersion) { res.push({ entry, depNameConstraint, depName, constraint }); } @@ -35,3 +43,46 @@ export function getLockedDependencies( } return res; } + +export function getYarn2LockedDependencies( + yarnLock: YarnLock, + depName: string, + currentVersion: string +): YarnLockEntrySummary[] { + const res: YarnLockEntrySummary[] = []; + try { + for (const [fullConstraint, entry] of Object.entries(yarnLock)) { + if (fullConstraint === '__metadata') { + continue; + } + for (const subConstraint of fullConstraint.split(', ')) { + const depNameConstraint = subConstraint; + const parsed = parseEntry(depNameConstraint); + // istanbul ignore if + if (!parsed) { + continue; + } + const { entryName } = parsed; + const constraint = parsed.constraint.replace(/^npm:/, ''); + if (entryName === depName && entry?.version === currentVersion) { + res.push({ entry, depNameConstraint, depName, constraint }); + } + } + } + } catch (err) /* istanbul ignore next */ { + logger.warn({ err }, 'getLockedDependencies() error'); + } + return res; +} + +// Finds matching dependencies withing a package lock file of sub-entry +export function getLockedDependencies( + yarnLock: YarnLock, + depName: string, + currentVersion: string +): YarnLockEntrySummary[] { + if ('__metadata' in yarnLock) { + return getYarn2LockedDependencies(yarnLock, depName, currentVersion); + } + return getYarn1LockedDependencies(yarnLock, depName, currentVersion); +} From 7b8adff55642f0989c0c7fb10097f3dc881e61c3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 18:55:14 +0000 Subject: [PATCH 38/74] build(deps): update dependency @renovatebot/osv-offline to v1.2.6 (#22241) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 96a630697c56d0..f532d4a2048871 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "@opentelemetry/sdk-trace-node": "1.12.0", "@opentelemetry/semantic-conventions": "1.12.0", "@qnighy/marshal": "0.1.3", - "@renovatebot/osv-offline": "1.2.5", + "@renovatebot/osv-offline": "1.2.6", "@renovatebot/pep440": "2.1.15", "@renovatebot/ruby-semver": "3.0.1", "@sindresorhus/is": "4.6.0", diff --git a/yarn.lock b/yarn.lock index 928f04e5d55747..c9d272e44f5384 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2494,10 +2494,10 @@ dependencies: "@seald-io/nedb" "^4.0.2" -"@renovatebot/osv-offline@1.2.5": - version "1.2.5" - resolved "https://registry.yarnpkg.com/@renovatebot/osv-offline/-/osv-offline-1.2.5.tgz#40bdb5c22eb1cd66ec3a79d3a25de40fbdce6bb4" - integrity sha512-PRzSyAhel/coD68Z8WK5nFw9UJ8vLCvQQb+aRzwwmMEuSzAbe1FnVbvEZ/wae3sDy57nvMuVhk358InMYHYyVQ== +"@renovatebot/osv-offline@1.2.6": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@renovatebot/osv-offline/-/osv-offline-1.2.6.tgz#66a4ff071c52e38c7fb9837cf9b9efe8b4f6025e" + integrity sha512-0FXihAGhDRAXfqtnEWsz8EH+3vEJpH5zB6FZD48tsK+puz43e6tI4obQGcylhMBToV7ex9M7tU4ukChkHwOGcg== dependencies: "@octokit/rest" "^19.0.7" "@renovatebot/osv-offline-db" "1.3.3" @@ -2505,7 +2505,7 @@ fs-extra "^11.1.1" got "^11.8.6" luxon "^3.3.0" - node-fetch "^2.6.9" + node-fetch "^2.6.10" "@renovatebot/pep440@2.1.15": version "2.1.15" @@ -7928,7 +7928,14 @@ node-emoji@^1.11.0: dependencies: lodash "^4.17.21" -node-fetch@^2.6.7, node-fetch@^2.6.9: +node-fetch@^2.6.10: + version "2.6.11" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.11.tgz#cde7fc71deef3131ef80a738919f999e6edfff25" + integrity sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@^2.6.7: version "2.6.9" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== From a8978e43d02a9fd11fe8376022aa5be3871edcac Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 19:53:30 +0000 Subject: [PATCH 39/74] chore(deps): update dependency @types/semver to v7.5.0 (#22242) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f532d4a2048871..2390b7fe44a22d 100644 --- a/package.json +++ b/package.json @@ -281,7 +281,7 @@ "@types/nock": "10.0.3", "@types/node": "18.16.8", "@types/parse-link-header": "2.0.1", - "@types/semver": "7.3.13", + "@types/semver": "7.5.0", "@types/semver-stable": "3.0.0", "@types/semver-utils": "1.1.1", "@types/tar": "6.1.5", diff --git a/yarn.lock b/yarn.lock index c9d272e44f5384..85d4f724c5ce3f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3113,7 +3113,12 @@ resolved "https://registry.yarnpkg.com/@types/semver-utils/-/semver-utils-1.1.1.tgz#4260b9ce13344725069a1ff86bd2f4d6c70a443e" integrity sha512-WLZZQdwo5P+H6R+bDDCFqFSlP5Jtk6gyXpE0R0KAVQbcMGmxpVsNX8dah640hY4+PpRG2+Ph3dcwDHzrOAOZ7A== -"@types/semver@7.3.13", "@types/semver@^7.1.0", "@types/semver@^7.3.12": +"@types/semver@7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" + integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== + +"@types/semver@^7.1.0", "@types/semver@^7.3.12": version "7.3.13" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== From 3218eb134fd538182b146ec289760bac20df926d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 20:41:46 +0000 Subject: [PATCH 40/74] build(deps): update dependency semver to v7.5.1 (#22243) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2390b7fe44a22d..c906d4a1cda5f4 100644 --- a/package.json +++ b/package.json @@ -226,7 +226,7 @@ "remark": "13.0.0", "remark-github": "10.1.0", "safe-stable-stringify": "2.4.3", - "semver": "7.5.0", + "semver": "7.5.1", "semver-stable": "3.0.0", "semver-utils": "1.1.4", "shlex": "2.1.2", diff --git a/yarn.lock b/yarn.lock index 85d4f724c5ce3f..a09381d0d97d9a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9361,7 +9361,14 @@ semver-utils@1.1.4: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@7.5.0, semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.1.2, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.0: +semver@7.5.1: + version "7.5.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.1.tgz#c90c4d631cf74720e46b21c1d37ea07edfab91ec" + integrity sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw== + dependencies: + lru-cache "^6.0.0" + +semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.1.2, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.0: version "7.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.0.tgz#ed8c5dc8efb6c629c88b23d41dc9bf40c1d96cd0" integrity sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA== From b360417b6d40efd5edaf5270cae6f86ca1f09170 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 21:38:59 +0000 Subject: [PATCH 41/74] build(deps): update dependency good-enough-parser to v1.1.23 (#22246) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index c906d4a1cda5f4..6aee9738415b72 100644 --- a/package.json +++ b/package.json @@ -194,7 +194,7 @@ "git-url-parse": "13.1.0", "github-url-from-git": "1.5.0", "global-agent": "3.0.0", - "good-enough-parser": "1.1.22", + "good-enough-parser": "1.1.23", "got": "11.8.6", "glob": "10.2.2", "graph-data-structure": "3.3.0", diff --git a/yarn.lock b/yarn.lock index a09381d0d97d9a..b29a49f3c42d5e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5750,14 +5750,14 @@ globrex@^0.1.2: resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098" integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg== -good-enough-parser@1.1.22: - version "1.1.22" - resolved "https://registry.yarnpkg.com/good-enough-parser/-/good-enough-parser-1.1.22.tgz#1fcab50b385ead49cb89a847868631d588bc5716" - integrity sha512-fI4qWIeyqjleGazMcXnqgtvG8qBJGUoj5CtraqaUpZmk94ztMab6irx3Yz+EsJKKgIrwkSBM69WHLngfhAe7hg== +good-enough-parser@1.1.23: + version "1.1.23" + resolved "https://registry.yarnpkg.com/good-enough-parser/-/good-enough-parser-1.1.23.tgz#f80441698261d6d1722ca52cf1184bb504ac5d76" + integrity sha512-QUcQZutczESpdo2w9BMG6VpLFoq9ix7ER5HLM1mAdZdri2F3eISkCb8ep84W6YOo0grYWJdyT/8JkYqGjQfSSQ== dependencies: "@thi.ng/zipper" "1.0.3" "@types/moo" "0.5.5" - klona "2.0.5" + klona "2.0.6" moo "0.5.2" gopd@^1.0.1: @@ -7013,10 +7013,10 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -klona@2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" - integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== +klona@2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.6.tgz#85bffbf819c03b2f53270412420a4555ef882e22" + integrity sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA== leven@^3.1.0: version "3.1.0" From f86fa3af8f0cfeb6c4c22390bbbeb39f511ccb0b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 21:39:49 +0000 Subject: [PATCH 42/74] chore(deps): update codecov/codecov-action action to v3.1.4 (#22245) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8f63d1a60ddb5f..7b3f881a4421d5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -97,7 +97,7 @@ jobs: run: yarn jest --ci --coverage ${{ env.coverage }} - name: Codecov - uses: codecov/codecov-action@894ff025c7b54547a9a2a1e9f228beae737ad3c2 # v3.1.3 + uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4 if: always() && env.coverage == 'true' - name: E2E Test From ae75c8372c0bcc1e39f3e4e97f242d7a88dba81f Mon Sep 17 00:00:00 2001 From: Natsuki Ikeguchi Date: Tue, 16 May 2023 13:14:50 +0900 Subject: [PATCH 43/74] feat: Add rjsf as a monorepo (#22248) Signed-off-by: Natsuki Ikeguchi --- lib/config/presets/internal/monorepo.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/config/presets/internal/monorepo.ts b/lib/config/presets/internal/monorepo.ts index 122df520a6aec5..9b9767961eb07b 100644 --- a/lib/config/presets/internal/monorepo.ts +++ b/lib/config/presets/internal/monorepo.ts @@ -206,6 +206,7 @@ const repoGroups = { 'reg-suit': 'https://github.com/reg-viz/reg-suit', remark: 'https://github.com/remarkjs/remark', remix: 'https://github.com/remix-run/remix', + rjsf: 'https://github.com/rjsf-team/react-jsonschema-form', router5: 'https://github.com/router5/router5', 'rust-futures': 'https://github.com/rust-lang/futures-rs', 'rust-wasm-bindgen': 'https://github.com/rustwasm/wasm-bindgen', From 2e7aa4324068b53562fb92bbac14032a933777d9 Mon Sep 17 00:00:00 2001 From: Alex Hatzenbuhler Date: Tue, 16 May 2023 00:01:16 -0500 Subject: [PATCH 44/74] fix: Add changelogUrl for gradle-semver-plugin (#20441) Co-authored-by: Michael Kriese --- lib/modules/datasource/metadata-manual.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/modules/datasource/metadata-manual.ts b/lib/modules/datasource/metadata-manual.ts index 84ead99902cdba..f475f5e8072cbe 100644 --- a/lib/modules/datasource/metadata-manual.ts +++ b/lib/modules/datasource/metadata-manual.ts @@ -94,6 +94,10 @@ export const manualSourceUrls: Record> = { kubernetes: { node: 'https://github.com/nodejs/node', }, + maven: { + 'com.figure.gradle.semver-plugin:com.figure.gradle.semver-plugin.gradle.plugin': + 'https://github.com/FigureTechnologies/gradle-semver-plugin', + }, npm: { node: 'https://github.com/nodejs/node', }, From 7e5f98b204a03ab4d3dd535acddfcb41adfc01ae Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 May 2023 06:40:07 +0000 Subject: [PATCH 45/74] build(deps): update aws-sdk-js-v3 monorepo to v3.332.0 (#22253) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 12 +- yarn.lock | 1427 +++++++++++++++++++++++++------------------------- 2 files changed, 723 insertions(+), 716 deletions(-) diff --git a/package.json b/package.json index 6aee9738415b72..7897f5367472d9 100644 --- a/package.json +++ b/package.json @@ -135,12 +135,12 @@ "node": "^18.12.0 || >=20.0.0" }, "dependencies": { - "@aws-sdk/client-codecommit": "3.312.0", - "@aws-sdk/client-ec2": "3.312.0", - "@aws-sdk/client-ecr": "3.312.0", - "@aws-sdk/client-iam": "3.312.0", - "@aws-sdk/client-rds": "3.314.0", - "@aws-sdk/client-s3": "3.312.0", + "@aws-sdk/client-codecommit": "3.332.0", + "@aws-sdk/client-ec2": "3.332.0", + "@aws-sdk/client-ecr": "3.332.0", + "@aws-sdk/client-iam": "3.332.0", + "@aws-sdk/client-rds": "3.332.0", + "@aws-sdk/client-s3": "3.332.0", "@breejs/later": "4.1.0", "@cdktf/hcl2json": "0.16.1", "@cheap-glitch/mi-cron": "1.0.1", diff --git a/yarn.lock b/yarn.lock index b29a49f3c42d5e..ec4975f0fa98ad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -109,12 +109,12 @@ "@aws-sdk/util-utf8-browser" "^3.0.0" tslib "^1.11.1" -"@aws-sdk/abort-controller@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/abort-controller/-/abort-controller-3.310.0.tgz#0da2d29b823daa03b7c1f0b43de1f030583b4f51" - integrity sha512-v1zrRQxDLA1MdPim159Vx/CPHqsB4uybSxRi1CnfHO5ZjHryx3a5htW2gdGAykVCul40+yJXvfpufMrELVxH+g== +"@aws-sdk/abort-controller@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/abort-controller/-/abort-controller-3.329.0.tgz#f311f79cad1040b84b853c5e9386ea2e069e571a" + integrity sha512-hzrjPNQcJoSPe0oS20V5i98oiEZSM3mKNiR6P3xHTHTPI/F23lyjGZ+/CSkCmJbSWfGZ5sHZZcU6AWuS7xBdTw== dependencies: - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" "@aws-sdk/chunked-blob-reader@3.310.0": @@ -124,582 +124,582 @@ dependencies: tslib "^2.5.0" -"@aws-sdk/client-codecommit@3.312.0": - version "3.312.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-codecommit/-/client-codecommit-3.312.0.tgz#e29c3d504b2d65aaccb4a4e8d12e736115ad5893" - integrity sha512-DZ8Ci6REIqBKJLeDN1qk+MgRs0KBPnNvfT0Ktw+3dyykbpo20X8xabcUDpV7l1C1qwTYFAg2vC0xbdbx9O2LOg== +"@aws-sdk/client-codecommit@3.332.0": + version "3.332.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-codecommit/-/client-codecommit-3.332.0.tgz#dc1783c75ba22d96e171ca4e47ce77408bb8a27c" + integrity sha512-sNJTxXQabZXoDCWEEjCThLui6Cos4CXiJvkzMcprnttg1EeocOI233fPIBJrD/RXRjZLIJMdW6Hxy6E2O9yCOQ== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/client-sts" "3.312.0" - "@aws-sdk/config-resolver" "3.310.0" - "@aws-sdk/credential-provider-node" "3.310.0" - "@aws-sdk/fetch-http-handler" "3.310.0" - "@aws-sdk/hash-node" "3.310.0" - "@aws-sdk/invalid-dependency" "3.310.0" - "@aws-sdk/middleware-content-length" "3.310.0" - "@aws-sdk/middleware-endpoint" "3.310.0" - "@aws-sdk/middleware-host-header" "3.310.0" - "@aws-sdk/middleware-logger" "3.310.0" - "@aws-sdk/middleware-recursion-detection" "3.310.0" - "@aws-sdk/middleware-retry" "3.310.0" - "@aws-sdk/middleware-serde" "3.310.0" - "@aws-sdk/middleware-signing" "3.310.0" - "@aws-sdk/middleware-stack" "3.310.0" - "@aws-sdk/middleware-user-agent" "3.310.0" - "@aws-sdk/node-config-provider" "3.310.0" - "@aws-sdk/node-http-handler" "3.310.0" - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/smithy-client" "3.310.0" - "@aws-sdk/types" "3.310.0" - "@aws-sdk/url-parser" "3.310.0" + "@aws-sdk/client-sts" "3.332.0" + "@aws-sdk/config-resolver" "3.329.0" + "@aws-sdk/credential-provider-node" "3.332.0" + "@aws-sdk/fetch-http-handler" "3.329.0" + "@aws-sdk/hash-node" "3.329.0" + "@aws-sdk/invalid-dependency" "3.329.0" + "@aws-sdk/middleware-content-length" "3.329.0" + "@aws-sdk/middleware-endpoint" "3.329.0" + "@aws-sdk/middleware-host-header" "3.329.0" + "@aws-sdk/middleware-logger" "3.329.0" + "@aws-sdk/middleware-recursion-detection" "3.329.0" + "@aws-sdk/middleware-retry" "3.329.0" + "@aws-sdk/middleware-serde" "3.329.0" + "@aws-sdk/middleware-signing" "3.329.0" + "@aws-sdk/middleware-stack" "3.329.0" + "@aws-sdk/middleware-user-agent" "3.332.0" + "@aws-sdk/node-config-provider" "3.329.0" + "@aws-sdk/node-http-handler" "3.329.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/smithy-client" "3.329.0" + "@aws-sdk/types" "3.329.0" + "@aws-sdk/url-parser" "3.329.0" "@aws-sdk/util-base64" "3.310.0" "@aws-sdk/util-body-length-browser" "3.310.0" "@aws-sdk/util-body-length-node" "3.310.0" - "@aws-sdk/util-defaults-mode-browser" "3.310.0" - "@aws-sdk/util-defaults-mode-node" "3.310.0" - "@aws-sdk/util-endpoints" "3.310.0" - "@aws-sdk/util-retry" "3.310.0" - "@aws-sdk/util-user-agent-browser" "3.310.0" - "@aws-sdk/util-user-agent-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.329.0" + "@aws-sdk/util-defaults-mode-node" "3.329.0" + "@aws-sdk/util-endpoints" "3.332.0" + "@aws-sdk/util-retry" "3.329.0" + "@aws-sdk/util-user-agent-browser" "3.329.0" + "@aws-sdk/util-user-agent-node" "3.329.0" "@aws-sdk/util-utf8" "3.310.0" tslib "^2.5.0" uuid "^8.3.2" -"@aws-sdk/client-ec2@3.312.0": - version "3.312.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-ec2/-/client-ec2-3.312.0.tgz#df61677afcade8069221e13f4e94dd8f85aec246" - integrity sha512-WybuBygd5v9MfZ1gNnzRkS5ArnoG4wclkHhC1gUb4ylNqptzN9gezUgTR1l9Nfr9V6487r/O0yao2VcdUApAZg== +"@aws-sdk/client-ec2@3.332.0": + version "3.332.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-ec2/-/client-ec2-3.332.0.tgz#886894ed2d31457b3cb463109378f0d184d6ff8a" + integrity sha512-CKKzcxrFN3/yAw6rTG4/WUUxewTw8Yo08SN7T97uXVjqomoCn7ikqRtjESDFD7bsoELCJCDzH/ofJVkm2wnQjQ== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/client-sts" "3.312.0" - "@aws-sdk/config-resolver" "3.310.0" - "@aws-sdk/credential-provider-node" "3.310.0" - "@aws-sdk/fetch-http-handler" "3.310.0" - "@aws-sdk/hash-node" "3.310.0" - "@aws-sdk/invalid-dependency" "3.310.0" - "@aws-sdk/middleware-content-length" "3.310.0" - "@aws-sdk/middleware-endpoint" "3.310.0" - "@aws-sdk/middleware-host-header" "3.310.0" - "@aws-sdk/middleware-logger" "3.310.0" - "@aws-sdk/middleware-recursion-detection" "3.310.0" - "@aws-sdk/middleware-retry" "3.310.0" - "@aws-sdk/middleware-sdk-ec2" "3.311.0" - "@aws-sdk/middleware-serde" "3.310.0" - "@aws-sdk/middleware-signing" "3.310.0" - "@aws-sdk/middleware-stack" "3.310.0" - "@aws-sdk/middleware-user-agent" "3.310.0" - "@aws-sdk/node-config-provider" "3.310.0" - "@aws-sdk/node-http-handler" "3.310.0" - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/smithy-client" "3.310.0" - "@aws-sdk/types" "3.310.0" - "@aws-sdk/url-parser" "3.310.0" + "@aws-sdk/client-sts" "3.332.0" + "@aws-sdk/config-resolver" "3.329.0" + "@aws-sdk/credential-provider-node" "3.332.0" + "@aws-sdk/fetch-http-handler" "3.329.0" + "@aws-sdk/hash-node" "3.329.0" + "@aws-sdk/invalid-dependency" "3.329.0" + "@aws-sdk/middleware-content-length" "3.329.0" + "@aws-sdk/middleware-endpoint" "3.329.0" + "@aws-sdk/middleware-host-header" "3.329.0" + "@aws-sdk/middleware-logger" "3.329.0" + "@aws-sdk/middleware-recursion-detection" "3.329.0" + "@aws-sdk/middleware-retry" "3.329.0" + "@aws-sdk/middleware-sdk-ec2" "3.329.0" + "@aws-sdk/middleware-serde" "3.329.0" + "@aws-sdk/middleware-signing" "3.329.0" + "@aws-sdk/middleware-stack" "3.329.0" + "@aws-sdk/middleware-user-agent" "3.332.0" + "@aws-sdk/node-config-provider" "3.329.0" + "@aws-sdk/node-http-handler" "3.329.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/smithy-client" "3.329.0" + "@aws-sdk/types" "3.329.0" + "@aws-sdk/url-parser" "3.329.0" "@aws-sdk/util-base64" "3.310.0" "@aws-sdk/util-body-length-browser" "3.310.0" "@aws-sdk/util-body-length-node" "3.310.0" - "@aws-sdk/util-defaults-mode-browser" "3.310.0" - "@aws-sdk/util-defaults-mode-node" "3.310.0" - "@aws-sdk/util-endpoints" "3.310.0" - "@aws-sdk/util-retry" "3.310.0" - "@aws-sdk/util-user-agent-browser" "3.310.0" - "@aws-sdk/util-user-agent-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.329.0" + "@aws-sdk/util-defaults-mode-node" "3.329.0" + "@aws-sdk/util-endpoints" "3.332.0" + "@aws-sdk/util-retry" "3.329.0" + "@aws-sdk/util-user-agent-browser" "3.329.0" + "@aws-sdk/util-user-agent-node" "3.329.0" "@aws-sdk/util-utf8" "3.310.0" - "@aws-sdk/util-waiter" "3.310.0" + "@aws-sdk/util-waiter" "3.329.0" fast-xml-parser "4.1.2" tslib "^2.5.0" uuid "^8.3.2" -"@aws-sdk/client-ecr@3.312.0": - version "3.312.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-ecr/-/client-ecr-3.312.0.tgz#8425c3305e8e2353f9ec39468bed88e21b44bb15" - integrity sha512-MeVhOOm73m9WPXT+6RIQqrHermOtf6S3QmpdZRHOBj5IVZ+004e+Hxe1sbJZY2TG/r90vDtcU9LwTwQQhbyLKQ== +"@aws-sdk/client-ecr@3.332.0": + version "3.332.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-ecr/-/client-ecr-3.332.0.tgz#a19c3bd6e6f768bb2502671251145f02dd150f7d" + integrity sha512-HnOXI8k3SgnbWfK2iExcW3jUEwJBL687IFvYXmHz9nGcbDhrxluVWStC1X8YkB/ftaRCNFw7U/g5pcZiyOESAw== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/client-sts" "3.312.0" - "@aws-sdk/config-resolver" "3.310.0" - "@aws-sdk/credential-provider-node" "3.310.0" - "@aws-sdk/fetch-http-handler" "3.310.0" - "@aws-sdk/hash-node" "3.310.0" - "@aws-sdk/invalid-dependency" "3.310.0" - "@aws-sdk/middleware-content-length" "3.310.0" - "@aws-sdk/middleware-endpoint" "3.310.0" - "@aws-sdk/middleware-host-header" "3.310.0" - "@aws-sdk/middleware-logger" "3.310.0" - "@aws-sdk/middleware-recursion-detection" "3.310.0" - "@aws-sdk/middleware-retry" "3.310.0" - "@aws-sdk/middleware-serde" "3.310.0" - "@aws-sdk/middleware-signing" "3.310.0" - "@aws-sdk/middleware-stack" "3.310.0" - "@aws-sdk/middleware-user-agent" "3.310.0" - "@aws-sdk/node-config-provider" "3.310.0" - "@aws-sdk/node-http-handler" "3.310.0" - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/smithy-client" "3.310.0" - "@aws-sdk/types" "3.310.0" - "@aws-sdk/url-parser" "3.310.0" + "@aws-sdk/client-sts" "3.332.0" + "@aws-sdk/config-resolver" "3.329.0" + "@aws-sdk/credential-provider-node" "3.332.0" + "@aws-sdk/fetch-http-handler" "3.329.0" + "@aws-sdk/hash-node" "3.329.0" + "@aws-sdk/invalid-dependency" "3.329.0" + "@aws-sdk/middleware-content-length" "3.329.0" + "@aws-sdk/middleware-endpoint" "3.329.0" + "@aws-sdk/middleware-host-header" "3.329.0" + "@aws-sdk/middleware-logger" "3.329.0" + "@aws-sdk/middleware-recursion-detection" "3.329.0" + "@aws-sdk/middleware-retry" "3.329.0" + "@aws-sdk/middleware-serde" "3.329.0" + "@aws-sdk/middleware-signing" "3.329.0" + "@aws-sdk/middleware-stack" "3.329.0" + "@aws-sdk/middleware-user-agent" "3.332.0" + "@aws-sdk/node-config-provider" "3.329.0" + "@aws-sdk/node-http-handler" "3.329.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/smithy-client" "3.329.0" + "@aws-sdk/types" "3.329.0" + "@aws-sdk/url-parser" "3.329.0" "@aws-sdk/util-base64" "3.310.0" "@aws-sdk/util-body-length-browser" "3.310.0" "@aws-sdk/util-body-length-node" "3.310.0" - "@aws-sdk/util-defaults-mode-browser" "3.310.0" - "@aws-sdk/util-defaults-mode-node" "3.310.0" - "@aws-sdk/util-endpoints" "3.310.0" - "@aws-sdk/util-retry" "3.310.0" - "@aws-sdk/util-user-agent-browser" "3.310.0" - "@aws-sdk/util-user-agent-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.329.0" + "@aws-sdk/util-defaults-mode-node" "3.329.0" + "@aws-sdk/util-endpoints" "3.332.0" + "@aws-sdk/util-retry" "3.329.0" + "@aws-sdk/util-user-agent-browser" "3.329.0" + "@aws-sdk/util-user-agent-node" "3.329.0" "@aws-sdk/util-utf8" "3.310.0" - "@aws-sdk/util-waiter" "3.310.0" + "@aws-sdk/util-waiter" "3.329.0" tslib "^2.5.0" -"@aws-sdk/client-iam@3.312.0": - version "3.312.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-iam/-/client-iam-3.312.0.tgz#dd66540cd5ecbdf65bb4853c2511159d0bc4a1a7" - integrity sha512-x2jF7teKZ/DbrRreVdLTddJOKDDJ81TVKGklJyB4YJgARAlrwfxxC7jAp9sF+T/HlnZ2HmLkdn1Tan4rVTetEA== +"@aws-sdk/client-iam@3.332.0": + version "3.332.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-iam/-/client-iam-3.332.0.tgz#fb311fdf00947d44ca073662db24f4153ae81038" + integrity sha512-V8vbA0o2+uHIyXnaSCFkZCPX13Gbqom4AdPjn7izf8cCTTW6CInjckZGQczqohEXxOx46RGxKlmulftplQ80Og== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/client-sts" "3.312.0" - "@aws-sdk/config-resolver" "3.310.0" - "@aws-sdk/credential-provider-node" "3.310.0" - "@aws-sdk/fetch-http-handler" "3.310.0" - "@aws-sdk/hash-node" "3.310.0" - "@aws-sdk/invalid-dependency" "3.310.0" - "@aws-sdk/middleware-content-length" "3.310.0" - "@aws-sdk/middleware-endpoint" "3.310.0" - "@aws-sdk/middleware-host-header" "3.310.0" - "@aws-sdk/middleware-logger" "3.310.0" - "@aws-sdk/middleware-recursion-detection" "3.310.0" - "@aws-sdk/middleware-retry" "3.310.0" - "@aws-sdk/middleware-serde" "3.310.0" - "@aws-sdk/middleware-signing" "3.310.0" - "@aws-sdk/middleware-stack" "3.310.0" - "@aws-sdk/middleware-user-agent" "3.310.0" - "@aws-sdk/node-config-provider" "3.310.0" - "@aws-sdk/node-http-handler" "3.310.0" - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/smithy-client" "3.310.0" - "@aws-sdk/types" "3.310.0" - "@aws-sdk/url-parser" "3.310.0" + "@aws-sdk/client-sts" "3.332.0" + "@aws-sdk/config-resolver" "3.329.0" + "@aws-sdk/credential-provider-node" "3.332.0" + "@aws-sdk/fetch-http-handler" "3.329.0" + "@aws-sdk/hash-node" "3.329.0" + "@aws-sdk/invalid-dependency" "3.329.0" + "@aws-sdk/middleware-content-length" "3.329.0" + "@aws-sdk/middleware-endpoint" "3.329.0" + "@aws-sdk/middleware-host-header" "3.329.0" + "@aws-sdk/middleware-logger" "3.329.0" + "@aws-sdk/middleware-recursion-detection" "3.329.0" + "@aws-sdk/middleware-retry" "3.329.0" + "@aws-sdk/middleware-serde" "3.329.0" + "@aws-sdk/middleware-signing" "3.329.0" + "@aws-sdk/middleware-stack" "3.329.0" + "@aws-sdk/middleware-user-agent" "3.332.0" + "@aws-sdk/node-config-provider" "3.329.0" + "@aws-sdk/node-http-handler" "3.329.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/smithy-client" "3.329.0" + "@aws-sdk/types" "3.329.0" + "@aws-sdk/url-parser" "3.329.0" "@aws-sdk/util-base64" "3.310.0" "@aws-sdk/util-body-length-browser" "3.310.0" "@aws-sdk/util-body-length-node" "3.310.0" - "@aws-sdk/util-defaults-mode-browser" "3.310.0" - "@aws-sdk/util-defaults-mode-node" "3.310.0" - "@aws-sdk/util-endpoints" "3.310.0" - "@aws-sdk/util-retry" "3.310.0" - "@aws-sdk/util-user-agent-browser" "3.310.0" - "@aws-sdk/util-user-agent-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.329.0" + "@aws-sdk/util-defaults-mode-node" "3.329.0" + "@aws-sdk/util-endpoints" "3.332.0" + "@aws-sdk/util-retry" "3.329.0" + "@aws-sdk/util-user-agent-browser" "3.329.0" + "@aws-sdk/util-user-agent-node" "3.329.0" "@aws-sdk/util-utf8" "3.310.0" - "@aws-sdk/util-waiter" "3.310.0" + "@aws-sdk/util-waiter" "3.329.0" fast-xml-parser "4.1.2" tslib "^2.5.0" -"@aws-sdk/client-rds@3.314.0": - version "3.314.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-rds/-/client-rds-3.314.0.tgz#8e9cc272a2acfbbc3c976dec1db13f84c4b2fc44" - integrity sha512-+jvimITTzmDkMNwAh2vV4+r22GZWF1TCdCiQqB1+djApmfifUFSEGyDrNRpHOKYeBhDR6mHPVC+qW5hs8XWr6A== +"@aws-sdk/client-rds@3.332.0": + version "3.332.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-rds/-/client-rds-3.332.0.tgz#beb502f6c62f139065981daed90ba4c5a08be6b8" + integrity sha512-idI0Bt5HyUo3Wqcero3VDxRZb0HyZG2Tc8xJHvb29KSFwHezBWQDLi9jbuSMId6HPlA3/IGyQ1ixLEHtJDgICQ== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/client-sts" "3.312.0" - "@aws-sdk/config-resolver" "3.310.0" - "@aws-sdk/credential-provider-node" "3.310.0" - "@aws-sdk/fetch-http-handler" "3.310.0" - "@aws-sdk/hash-node" "3.310.0" - "@aws-sdk/invalid-dependency" "3.310.0" - "@aws-sdk/middleware-content-length" "3.310.0" - "@aws-sdk/middleware-endpoint" "3.310.0" - "@aws-sdk/middleware-host-header" "3.310.0" - "@aws-sdk/middleware-logger" "3.310.0" - "@aws-sdk/middleware-recursion-detection" "3.310.0" - "@aws-sdk/middleware-retry" "3.310.0" - "@aws-sdk/middleware-sdk-rds" "3.310.0" - "@aws-sdk/middleware-serde" "3.310.0" - "@aws-sdk/middleware-signing" "3.310.0" - "@aws-sdk/middleware-stack" "3.310.0" - "@aws-sdk/middleware-user-agent" "3.310.0" - "@aws-sdk/node-config-provider" "3.310.0" - "@aws-sdk/node-http-handler" "3.310.0" - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/smithy-client" "3.310.0" - "@aws-sdk/types" "3.310.0" - "@aws-sdk/url-parser" "3.310.0" + "@aws-sdk/client-sts" "3.332.0" + "@aws-sdk/config-resolver" "3.329.0" + "@aws-sdk/credential-provider-node" "3.332.0" + "@aws-sdk/fetch-http-handler" "3.329.0" + "@aws-sdk/hash-node" "3.329.0" + "@aws-sdk/invalid-dependency" "3.329.0" + "@aws-sdk/middleware-content-length" "3.329.0" + "@aws-sdk/middleware-endpoint" "3.329.0" + "@aws-sdk/middleware-host-header" "3.329.0" + "@aws-sdk/middleware-logger" "3.329.0" + "@aws-sdk/middleware-recursion-detection" "3.329.0" + "@aws-sdk/middleware-retry" "3.329.0" + "@aws-sdk/middleware-sdk-rds" "3.329.0" + "@aws-sdk/middleware-serde" "3.329.0" + "@aws-sdk/middleware-signing" "3.329.0" + "@aws-sdk/middleware-stack" "3.329.0" + "@aws-sdk/middleware-user-agent" "3.332.0" + "@aws-sdk/node-config-provider" "3.329.0" + "@aws-sdk/node-http-handler" "3.329.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/smithy-client" "3.329.0" + "@aws-sdk/types" "3.329.0" + "@aws-sdk/url-parser" "3.329.0" "@aws-sdk/util-base64" "3.310.0" "@aws-sdk/util-body-length-browser" "3.310.0" "@aws-sdk/util-body-length-node" "3.310.0" - "@aws-sdk/util-defaults-mode-browser" "3.310.0" - "@aws-sdk/util-defaults-mode-node" "3.310.0" - "@aws-sdk/util-endpoints" "3.310.0" - "@aws-sdk/util-retry" "3.310.0" - "@aws-sdk/util-user-agent-browser" "3.310.0" - "@aws-sdk/util-user-agent-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.329.0" + "@aws-sdk/util-defaults-mode-node" "3.329.0" + "@aws-sdk/util-endpoints" "3.332.0" + "@aws-sdk/util-retry" "3.329.0" + "@aws-sdk/util-user-agent-browser" "3.329.0" + "@aws-sdk/util-user-agent-node" "3.329.0" "@aws-sdk/util-utf8" "3.310.0" - "@aws-sdk/util-waiter" "3.310.0" + "@aws-sdk/util-waiter" "3.329.0" fast-xml-parser "4.1.2" tslib "^2.5.0" -"@aws-sdk/client-s3@3.312.0": - version "3.312.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.312.0.tgz#d5f286f38db04612dad46407d0115e7a5755e8a1" - integrity sha512-aqlll2g7eKwV0j+IAK4Ly7c0CRVSI712VTdItAWpLSQPw1VVUP9IKaIsBTiigoOBCJq+fb2+ufFrSTUAPdEzPQ== +"@aws-sdk/client-s3@3.332.0": + version "3.332.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.332.0.tgz#99488145424265e87e55cbc740f3bed8751116ed" + integrity sha512-4AkbBPGjFkIvN15l9uDHcry3kwMknpl0b7mqFaNQqQJR2OyFJnr7US/KyeTjwijJAuU+f7lKz8QMTtBcghJm3w== dependencies: "@aws-crypto/sha1-browser" "3.0.0" "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/client-sts" "3.312.0" - "@aws-sdk/config-resolver" "3.310.0" - "@aws-sdk/credential-provider-node" "3.310.0" - "@aws-sdk/eventstream-serde-browser" "3.310.0" - "@aws-sdk/eventstream-serde-config-resolver" "3.310.0" - "@aws-sdk/eventstream-serde-node" "3.310.0" - "@aws-sdk/fetch-http-handler" "3.310.0" - "@aws-sdk/hash-blob-browser" "3.310.0" - "@aws-sdk/hash-node" "3.310.0" - "@aws-sdk/hash-stream-node" "3.310.0" - "@aws-sdk/invalid-dependency" "3.310.0" - "@aws-sdk/md5-js" "3.310.0" - "@aws-sdk/middleware-bucket-endpoint" "3.310.0" - "@aws-sdk/middleware-content-length" "3.310.0" - "@aws-sdk/middleware-endpoint" "3.310.0" - "@aws-sdk/middleware-expect-continue" "3.310.0" - "@aws-sdk/middleware-flexible-checksums" "3.310.0" - "@aws-sdk/middleware-host-header" "3.310.0" - "@aws-sdk/middleware-location-constraint" "3.310.0" - "@aws-sdk/middleware-logger" "3.310.0" - "@aws-sdk/middleware-recursion-detection" "3.310.0" - "@aws-sdk/middleware-retry" "3.310.0" - "@aws-sdk/middleware-sdk-s3" "3.310.0" - "@aws-sdk/middleware-serde" "3.310.0" - "@aws-sdk/middleware-signing" "3.310.0" - "@aws-sdk/middleware-ssec" "3.310.0" - "@aws-sdk/middleware-stack" "3.310.0" - "@aws-sdk/middleware-user-agent" "3.310.0" - "@aws-sdk/node-config-provider" "3.310.0" - "@aws-sdk/node-http-handler" "3.310.0" - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/signature-v4-multi-region" "3.310.0" - "@aws-sdk/smithy-client" "3.310.0" - "@aws-sdk/types" "3.310.0" - "@aws-sdk/url-parser" "3.310.0" + "@aws-sdk/client-sts" "3.332.0" + "@aws-sdk/config-resolver" "3.329.0" + "@aws-sdk/credential-provider-node" "3.332.0" + "@aws-sdk/eventstream-serde-browser" "3.329.0" + "@aws-sdk/eventstream-serde-config-resolver" "3.329.0" + "@aws-sdk/eventstream-serde-node" "3.329.0" + "@aws-sdk/fetch-http-handler" "3.329.0" + "@aws-sdk/hash-blob-browser" "3.329.0" + "@aws-sdk/hash-node" "3.329.0" + "@aws-sdk/hash-stream-node" "3.329.0" + "@aws-sdk/invalid-dependency" "3.329.0" + "@aws-sdk/md5-js" "3.329.0" + "@aws-sdk/middleware-bucket-endpoint" "3.329.0" + "@aws-sdk/middleware-content-length" "3.329.0" + "@aws-sdk/middleware-endpoint" "3.329.0" + "@aws-sdk/middleware-expect-continue" "3.329.0" + "@aws-sdk/middleware-flexible-checksums" "3.331.0" + "@aws-sdk/middleware-host-header" "3.329.0" + "@aws-sdk/middleware-location-constraint" "3.329.0" + "@aws-sdk/middleware-logger" "3.329.0" + "@aws-sdk/middleware-recursion-detection" "3.329.0" + "@aws-sdk/middleware-retry" "3.329.0" + "@aws-sdk/middleware-sdk-s3" "3.329.0" + "@aws-sdk/middleware-serde" "3.329.0" + "@aws-sdk/middleware-signing" "3.329.0" + "@aws-sdk/middleware-ssec" "3.329.0" + "@aws-sdk/middleware-stack" "3.329.0" + "@aws-sdk/middleware-user-agent" "3.332.0" + "@aws-sdk/node-config-provider" "3.329.0" + "@aws-sdk/node-http-handler" "3.329.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/signature-v4-multi-region" "3.329.0" + "@aws-sdk/smithy-client" "3.329.0" + "@aws-sdk/types" "3.329.0" + "@aws-sdk/url-parser" "3.329.0" "@aws-sdk/util-base64" "3.310.0" "@aws-sdk/util-body-length-browser" "3.310.0" "@aws-sdk/util-body-length-node" "3.310.0" - "@aws-sdk/util-defaults-mode-browser" "3.310.0" - "@aws-sdk/util-defaults-mode-node" "3.310.0" - "@aws-sdk/util-endpoints" "3.310.0" - "@aws-sdk/util-retry" "3.310.0" - "@aws-sdk/util-stream-browser" "3.310.0" - "@aws-sdk/util-stream-node" "3.310.0" - "@aws-sdk/util-user-agent-browser" "3.310.0" - "@aws-sdk/util-user-agent-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.329.0" + "@aws-sdk/util-defaults-mode-node" "3.329.0" + "@aws-sdk/util-endpoints" "3.332.0" + "@aws-sdk/util-retry" "3.329.0" + "@aws-sdk/util-stream-browser" "3.329.0" + "@aws-sdk/util-stream-node" "3.331.0" + "@aws-sdk/util-user-agent-browser" "3.329.0" + "@aws-sdk/util-user-agent-node" "3.329.0" "@aws-sdk/util-utf8" "3.310.0" - "@aws-sdk/util-waiter" "3.310.0" + "@aws-sdk/util-waiter" "3.329.0" "@aws-sdk/xml-builder" "3.310.0" fast-xml-parser "4.1.2" tslib "^2.5.0" -"@aws-sdk/client-sso-oidc@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.310.0.tgz#f71eeb9cc73c13661728cf88d8513b0209b6d265" - integrity sha512-3GKaRSfMD3OiYWGa+qg5KvJw0nLV0Vu7zRiulLuKDvgmWw3SNJKn3frWlmq/bKFUKahLsV8zozbeJItxtKAD6g== +"@aws-sdk/client-sso-oidc@3.332.0": + version "3.332.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.332.0.tgz#8875ce4834d5d0decefadec828e32cbc0465fc30" + integrity sha512-tz8k8Yqm4TScIfit0Tum2zWAq1md+gZKr747CSixd4Zwcp7Vwh75cRoL7Rz1ZHSEn1Yo983MWREevVez3SubLw== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/config-resolver" "3.310.0" - "@aws-sdk/fetch-http-handler" "3.310.0" - "@aws-sdk/hash-node" "3.310.0" - "@aws-sdk/invalid-dependency" "3.310.0" - "@aws-sdk/middleware-content-length" "3.310.0" - "@aws-sdk/middleware-endpoint" "3.310.0" - "@aws-sdk/middleware-host-header" "3.310.0" - "@aws-sdk/middleware-logger" "3.310.0" - "@aws-sdk/middleware-recursion-detection" "3.310.0" - "@aws-sdk/middleware-retry" "3.310.0" - "@aws-sdk/middleware-serde" "3.310.0" - "@aws-sdk/middleware-stack" "3.310.0" - "@aws-sdk/middleware-user-agent" "3.310.0" - "@aws-sdk/node-config-provider" "3.310.0" - "@aws-sdk/node-http-handler" "3.310.0" - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/smithy-client" "3.310.0" - "@aws-sdk/types" "3.310.0" - "@aws-sdk/url-parser" "3.310.0" + "@aws-sdk/config-resolver" "3.329.0" + "@aws-sdk/fetch-http-handler" "3.329.0" + "@aws-sdk/hash-node" "3.329.0" + "@aws-sdk/invalid-dependency" "3.329.0" + "@aws-sdk/middleware-content-length" "3.329.0" + "@aws-sdk/middleware-endpoint" "3.329.0" + "@aws-sdk/middleware-host-header" "3.329.0" + "@aws-sdk/middleware-logger" "3.329.0" + "@aws-sdk/middleware-recursion-detection" "3.329.0" + "@aws-sdk/middleware-retry" "3.329.0" + "@aws-sdk/middleware-serde" "3.329.0" + "@aws-sdk/middleware-stack" "3.329.0" + "@aws-sdk/middleware-user-agent" "3.332.0" + "@aws-sdk/node-config-provider" "3.329.0" + "@aws-sdk/node-http-handler" "3.329.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/smithy-client" "3.329.0" + "@aws-sdk/types" "3.329.0" + "@aws-sdk/url-parser" "3.329.0" "@aws-sdk/util-base64" "3.310.0" "@aws-sdk/util-body-length-browser" "3.310.0" "@aws-sdk/util-body-length-node" "3.310.0" - "@aws-sdk/util-defaults-mode-browser" "3.310.0" - "@aws-sdk/util-defaults-mode-node" "3.310.0" - "@aws-sdk/util-endpoints" "3.310.0" - "@aws-sdk/util-retry" "3.310.0" - "@aws-sdk/util-user-agent-browser" "3.310.0" - "@aws-sdk/util-user-agent-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.329.0" + "@aws-sdk/util-defaults-mode-node" "3.329.0" + "@aws-sdk/util-endpoints" "3.332.0" + "@aws-sdk/util-retry" "3.329.0" + "@aws-sdk/util-user-agent-browser" "3.329.0" + "@aws-sdk/util-user-agent-node" "3.329.0" "@aws-sdk/util-utf8" "3.310.0" tslib "^2.5.0" -"@aws-sdk/client-sso@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.310.0.tgz#1ead31442c34ed660479ea9317faab4f1fa47130" - integrity sha512-netFap3Mp9I7bzAjsswHPA5WEbQtNMmXvW9/IVb7tmf85/esXCWindtyI43e/Xerut9ZVyEACPBFn30CLLE2xQ== +"@aws-sdk/client-sso@3.332.0": + version "3.332.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.332.0.tgz#e22fa9ded125cce75ca2cd63d3f3f9a6b8dfaa77" + integrity sha512-4q1Nko8M6YVANdEiLYvdv1qb00j4xN4ppE/6d4xpGp7DxHYlm0GA762h0/TR2dun+2I+SMnwj4Fv6BxOmzBaEw== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/config-resolver" "3.310.0" - "@aws-sdk/fetch-http-handler" "3.310.0" - "@aws-sdk/hash-node" "3.310.0" - "@aws-sdk/invalid-dependency" "3.310.0" - "@aws-sdk/middleware-content-length" "3.310.0" - "@aws-sdk/middleware-endpoint" "3.310.0" - "@aws-sdk/middleware-host-header" "3.310.0" - "@aws-sdk/middleware-logger" "3.310.0" - "@aws-sdk/middleware-recursion-detection" "3.310.0" - "@aws-sdk/middleware-retry" "3.310.0" - "@aws-sdk/middleware-serde" "3.310.0" - "@aws-sdk/middleware-stack" "3.310.0" - "@aws-sdk/middleware-user-agent" "3.310.0" - "@aws-sdk/node-config-provider" "3.310.0" - "@aws-sdk/node-http-handler" "3.310.0" - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/smithy-client" "3.310.0" - "@aws-sdk/types" "3.310.0" - "@aws-sdk/url-parser" "3.310.0" + "@aws-sdk/config-resolver" "3.329.0" + "@aws-sdk/fetch-http-handler" "3.329.0" + "@aws-sdk/hash-node" "3.329.0" + "@aws-sdk/invalid-dependency" "3.329.0" + "@aws-sdk/middleware-content-length" "3.329.0" + "@aws-sdk/middleware-endpoint" "3.329.0" + "@aws-sdk/middleware-host-header" "3.329.0" + "@aws-sdk/middleware-logger" "3.329.0" + "@aws-sdk/middleware-recursion-detection" "3.329.0" + "@aws-sdk/middleware-retry" "3.329.0" + "@aws-sdk/middleware-serde" "3.329.0" + "@aws-sdk/middleware-stack" "3.329.0" + "@aws-sdk/middleware-user-agent" "3.332.0" + "@aws-sdk/node-config-provider" "3.329.0" + "@aws-sdk/node-http-handler" "3.329.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/smithy-client" "3.329.0" + "@aws-sdk/types" "3.329.0" + "@aws-sdk/url-parser" "3.329.0" "@aws-sdk/util-base64" "3.310.0" "@aws-sdk/util-body-length-browser" "3.310.0" "@aws-sdk/util-body-length-node" "3.310.0" - "@aws-sdk/util-defaults-mode-browser" "3.310.0" - "@aws-sdk/util-defaults-mode-node" "3.310.0" - "@aws-sdk/util-endpoints" "3.310.0" - "@aws-sdk/util-retry" "3.310.0" - "@aws-sdk/util-user-agent-browser" "3.310.0" - "@aws-sdk/util-user-agent-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.329.0" + "@aws-sdk/util-defaults-mode-node" "3.329.0" + "@aws-sdk/util-endpoints" "3.332.0" + "@aws-sdk/util-retry" "3.329.0" + "@aws-sdk/util-user-agent-browser" "3.329.0" + "@aws-sdk/util-user-agent-node" "3.329.0" "@aws-sdk/util-utf8" "3.310.0" tslib "^2.5.0" -"@aws-sdk/client-sts@3.312.0": - version "3.312.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.312.0.tgz#7b49a04bab2d12a8ca566ef579fd887b71986498" - integrity sha512-t0U7vRvWaMjrzBUo6tPrHe6HE97Blqx+b4GOjFbcbLtzxLlcRfhnWJik0Lp8hJtVqzNoN5mL4OeYgK7CRpL/Sw== +"@aws-sdk/client-sts@3.332.0": + version "3.332.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.332.0.tgz#15bb163319d3da69f152f80fb4583eabe73e0e30" + integrity sha512-uVobnXIzMcEhwBDyk6iOt36N/TRNI8hwq7MQugjYGj7Inma9g4vnR09hXJ24HxyKCoVUoIgMbEguQ43+/+uvDQ== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/config-resolver" "3.310.0" - "@aws-sdk/credential-provider-node" "3.310.0" - "@aws-sdk/fetch-http-handler" "3.310.0" - "@aws-sdk/hash-node" "3.310.0" - "@aws-sdk/invalid-dependency" "3.310.0" - "@aws-sdk/middleware-content-length" "3.310.0" - "@aws-sdk/middleware-endpoint" "3.310.0" - "@aws-sdk/middleware-host-header" "3.310.0" - "@aws-sdk/middleware-logger" "3.310.0" - "@aws-sdk/middleware-recursion-detection" "3.310.0" - "@aws-sdk/middleware-retry" "3.310.0" - "@aws-sdk/middleware-sdk-sts" "3.310.0" - "@aws-sdk/middleware-serde" "3.310.0" - "@aws-sdk/middleware-signing" "3.310.0" - "@aws-sdk/middleware-stack" "3.310.0" - "@aws-sdk/middleware-user-agent" "3.310.0" - "@aws-sdk/node-config-provider" "3.310.0" - "@aws-sdk/node-http-handler" "3.310.0" - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/smithy-client" "3.310.0" - "@aws-sdk/types" "3.310.0" - "@aws-sdk/url-parser" "3.310.0" + "@aws-sdk/config-resolver" "3.329.0" + "@aws-sdk/credential-provider-node" "3.332.0" + "@aws-sdk/fetch-http-handler" "3.329.0" + "@aws-sdk/hash-node" "3.329.0" + "@aws-sdk/invalid-dependency" "3.329.0" + "@aws-sdk/middleware-content-length" "3.329.0" + "@aws-sdk/middleware-endpoint" "3.329.0" + "@aws-sdk/middleware-host-header" "3.329.0" + "@aws-sdk/middleware-logger" "3.329.0" + "@aws-sdk/middleware-recursion-detection" "3.329.0" + "@aws-sdk/middleware-retry" "3.329.0" + "@aws-sdk/middleware-sdk-sts" "3.329.0" + "@aws-sdk/middleware-serde" "3.329.0" + "@aws-sdk/middleware-signing" "3.329.0" + "@aws-sdk/middleware-stack" "3.329.0" + "@aws-sdk/middleware-user-agent" "3.332.0" + "@aws-sdk/node-config-provider" "3.329.0" + "@aws-sdk/node-http-handler" "3.329.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/smithy-client" "3.329.0" + "@aws-sdk/types" "3.329.0" + "@aws-sdk/url-parser" "3.329.0" "@aws-sdk/util-base64" "3.310.0" "@aws-sdk/util-body-length-browser" "3.310.0" "@aws-sdk/util-body-length-node" "3.310.0" - "@aws-sdk/util-defaults-mode-browser" "3.310.0" - "@aws-sdk/util-defaults-mode-node" "3.310.0" - "@aws-sdk/util-endpoints" "3.310.0" - "@aws-sdk/util-retry" "3.310.0" - "@aws-sdk/util-user-agent-browser" "3.310.0" - "@aws-sdk/util-user-agent-node" "3.310.0" + "@aws-sdk/util-defaults-mode-browser" "3.329.0" + "@aws-sdk/util-defaults-mode-node" "3.329.0" + "@aws-sdk/util-endpoints" "3.332.0" + "@aws-sdk/util-retry" "3.329.0" + "@aws-sdk/util-user-agent-browser" "3.329.0" + "@aws-sdk/util-user-agent-node" "3.329.0" "@aws-sdk/util-utf8" "3.310.0" fast-xml-parser "4.1.2" tslib "^2.5.0" -"@aws-sdk/config-resolver@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/config-resolver/-/config-resolver-3.310.0.tgz#c02dce96546d5cd25551bc89907b27224e16ca7f" - integrity sha512-8vsT+/50lOqfDxka9m/rRt6oxv1WuGZoP8oPMk0Dt+TxXMbAzf4+rejBgiB96wshI1k3gLokYRjSQZn+dDtT8g== +"@aws-sdk/config-resolver@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/config-resolver/-/config-resolver-3.329.0.tgz#f4283c9c8e61752cecad8cfaebb4db52ac1bbf60" + integrity sha512-Oj6eiT3q+Jn685yvUrfRi8PhB3fb81hasJqdrsEivA8IP8qAgnVUTJzXsh8O2UX8UM2MF6A1gTgToSgneJuw2Q== dependencies: - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" "@aws-sdk/util-config-provider" "3.310.0" - "@aws-sdk/util-middleware" "3.310.0" + "@aws-sdk/util-middleware" "3.329.0" tslib "^2.5.0" -"@aws-sdk/credential-provider-env@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.310.0.tgz#c52694fb276341db6ce4e816cf9ca90fa5830dad" - integrity sha512-vvIPQpI16fj95xwS7M3D48F7QhZJBnnCgB5lR+b7So+vsG9ibm1mZRVGzVpdxCvgyOhHFbvrby9aalNJmmIP1A== +"@aws-sdk/credential-provider-env@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.329.0.tgz#54bb313de01324e302b5927733083a4c93ed9962" + integrity sha512-B4orC9hMt9hG82vAR0TAnQqjk6cFDbO2S14RdzUj2n2NPlGWW4Blkv3NTo86K0lq011VRhtqaLcuTwn5EJD5Sg== dependencies: - "@aws-sdk/property-provider" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/property-provider" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/credential-provider-imds@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.310.0.tgz#d8fb1223fee7e289a81e28177fe55dedf4d2745e" - integrity sha512-baxK7Zp6dai5AGW01FIW27xS2KAaPUmKLIXv5SvFYsUgXXvNW55im4uG3b+2gA0F7V+hXvVBH08OEqmwW6we5w== +"@aws-sdk/credential-provider-imds@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.329.0.tgz#566b21c37f5e89730ef3b4229f0824b4c455f669" + integrity sha512-ggPlnd7QROPTid0CwT01TYYGvstRRTpzTGsQ/B31wkh30IrRXE81W3S4xrOYuqQD3u0RnflSxnvhs+EayJEYjg== dependencies: - "@aws-sdk/node-config-provider" "3.310.0" - "@aws-sdk/property-provider" "3.310.0" - "@aws-sdk/types" "3.310.0" - "@aws-sdk/url-parser" "3.310.0" + "@aws-sdk/node-config-provider" "3.329.0" + "@aws-sdk/property-provider" "3.329.0" + "@aws-sdk/types" "3.329.0" + "@aws-sdk/url-parser" "3.329.0" tslib "^2.5.0" -"@aws-sdk/credential-provider-ini@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.310.0.tgz#c317c803b78d6b322a440de15069b35b88c737e5" - integrity sha512-gtRz7I+4BBpwZ3tc6UIt5lQuiAFnkpOibxHh95x1M6HDxBjm+uqD6RPZYVH+dULZPYXOtOTsHV0IGjrcV0sSRg== - dependencies: - "@aws-sdk/credential-provider-env" "3.310.0" - "@aws-sdk/credential-provider-imds" "3.310.0" - "@aws-sdk/credential-provider-process" "3.310.0" - "@aws-sdk/credential-provider-sso" "3.310.0" - "@aws-sdk/credential-provider-web-identity" "3.310.0" - "@aws-sdk/property-provider" "3.310.0" - "@aws-sdk/shared-ini-file-loader" "3.310.0" - "@aws-sdk/types" "3.310.0" +"@aws-sdk/credential-provider-ini@3.332.0": + version "3.332.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.332.0.tgz#03c77480a94d07784c789eeca44ca67c0900ba4a" + integrity sha512-DTW6d6rcqizPVyvcIrwvxecQ7e5GONtVc5Wyf0RTfqf41sDOVZYmn6G+zEFSpBLW0975uZbJS0lyLWtJe2VujQ== + dependencies: + "@aws-sdk/credential-provider-env" "3.329.0" + "@aws-sdk/credential-provider-imds" "3.329.0" + "@aws-sdk/credential-provider-process" "3.329.0" + "@aws-sdk/credential-provider-sso" "3.332.0" + "@aws-sdk/credential-provider-web-identity" "3.329.0" + "@aws-sdk/property-provider" "3.329.0" + "@aws-sdk/shared-ini-file-loader" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/credential-provider-node@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.310.0.tgz#e4f69cf95e839c626c41e23b1d8b3cd24c667d8e" - integrity sha512-FrOztUcOq2Sp32xGtJvxfvdlmuAeoxIu/AElHzV1bkx6Pzo9DkQBhXrSQ+JFSpI++weOD4ZGFhAvgbgUOT4VAg== - dependencies: - "@aws-sdk/credential-provider-env" "3.310.0" - "@aws-sdk/credential-provider-imds" "3.310.0" - "@aws-sdk/credential-provider-ini" "3.310.0" - "@aws-sdk/credential-provider-process" "3.310.0" - "@aws-sdk/credential-provider-sso" "3.310.0" - "@aws-sdk/credential-provider-web-identity" "3.310.0" - "@aws-sdk/property-provider" "3.310.0" - "@aws-sdk/shared-ini-file-loader" "3.310.0" - "@aws-sdk/types" "3.310.0" +"@aws-sdk/credential-provider-node@3.332.0": + version "3.332.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.332.0.tgz#bfd4fa8855dd3cf80f1e0d8d160966441e44c4a7" + integrity sha512-KkBayS9k4WyJTvC86ngeRM+RmWxNCS1BHvudkR6PLXfnsNPDzxySDVY0UgxVhbNYDYsO561fXZt9ccpKyVWjgg== + dependencies: + "@aws-sdk/credential-provider-env" "3.329.0" + "@aws-sdk/credential-provider-imds" "3.329.0" + "@aws-sdk/credential-provider-ini" "3.332.0" + "@aws-sdk/credential-provider-process" "3.329.0" + "@aws-sdk/credential-provider-sso" "3.332.0" + "@aws-sdk/credential-provider-web-identity" "3.329.0" + "@aws-sdk/property-provider" "3.329.0" + "@aws-sdk/shared-ini-file-loader" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/credential-provider-process@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.310.0.tgz#0b2ee77f0c48262442d2768044d72332a4ad8884" - integrity sha512-h73sg6GPMUWC+3zMCbA1nZ2O03nNJt7G96JdmnantiXBwHpRKWW8nBTLzx5uhXn6hTuTaoQRP/P+oxQJKYdMmA== +"@aws-sdk/credential-provider-process@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.329.0.tgz#5c07b2f4c67cb97190c69d4af5890c9db3f8a31d" + integrity sha512-5oO220qoFc2pMdZDQa6XN/mVhp669I3+LqMbbscGtX/UgLJPSOb7YzPld9Wjv12L5rf+sD3G1PF3LZXO0vKLFA== dependencies: - "@aws-sdk/property-provider" "3.310.0" - "@aws-sdk/shared-ini-file-loader" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/property-provider" "3.329.0" + "@aws-sdk/shared-ini-file-loader" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/credential-provider-sso@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.310.0.tgz#86ab095ede5024a4e16aabaf3b2fa92d61656b8d" - integrity sha512-nXkpT8mrM/wRqSiz/a4p9U2UrOKyfZXhbPHIHyQj8K+uLjsYS+WPuH287J4A5Q57A6uarTrj5RjHmVeZVLaHmg== - dependencies: - "@aws-sdk/client-sso" "3.310.0" - "@aws-sdk/property-provider" "3.310.0" - "@aws-sdk/shared-ini-file-loader" "3.310.0" - "@aws-sdk/token-providers" "3.310.0" - "@aws-sdk/types" "3.310.0" +"@aws-sdk/credential-provider-sso@3.332.0": + version "3.332.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.332.0.tgz#ed12b58d30b6ee359462c7e78672734af22fe713" + integrity sha512-SaKXl48af3n6LRitcaEqbeg1YDXwQ0A5QziC1xQyYPraEIj3IZ/GyTjx04Lo2jxNYHuEOE8u4aTw1+IK1GDKbg== + dependencies: + "@aws-sdk/client-sso" "3.332.0" + "@aws-sdk/property-provider" "3.329.0" + "@aws-sdk/shared-ini-file-loader" "3.329.0" + "@aws-sdk/token-providers" "3.332.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/credential-provider-web-identity@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.310.0.tgz#c9fa09b0068027e58d31178e3fa06bf4e9ae9d36" - integrity sha512-H4SzuZXILNhK6/IR1uVvsUDZvzc051hem7GLyYghBCu8mU+tq28YhKE8MfSroi6eL2e5Vujloij1OM2EQQkPkw== +"@aws-sdk/credential-provider-web-identity@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.329.0.tgz#5610293c03bc4c323dfcae522c545c20e2d8dd86" + integrity sha512-lcEibZD7AlutCacpQ6DyNUqElZJDq+ylaIo5a8MH9jGh7Pg2WpDg0Sy+B6FbGCkVn4eIjdHxeX54JM245nhESg== dependencies: - "@aws-sdk/property-provider" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/property-provider" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/eventstream-codec@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-codec/-/eventstream-codec-3.310.0.tgz#a5def3633f7ccdc3d477fd0b05e2eb31c5598ed9" - integrity sha512-clIeSgWbZbxwtsxZ/yoedNM0/kJFSIjjHPikuDGhxhqc+vP6TN3oYyVMFrYwFaTFhk2+S5wZcWYMw8Op1pWo+A== +"@aws-sdk/eventstream-codec@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-codec/-/eventstream-codec-3.329.0.tgz#6bdfd69ad54352309535f53352017e932b9f643b" + integrity sha512-1r+6MNfye0za35FNLxMR5V9zpKY1lyzwySyu7o7aj8lnStBaCcjOEe7iHboP/z3DH73KJbxR++O2N+UC/XHFrg== dependencies: "@aws-crypto/crc32" "3.0.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" "@aws-sdk/util-hex-encoding" "3.310.0" tslib "^2.5.0" -"@aws-sdk/eventstream-serde-browser@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-browser/-/eventstream-serde-browser-3.310.0.tgz#02aef0262b5f740a1c8ffbdeb8459542f90c14dd" - integrity sha512-3S6ziuQVALgEyz0TANGtYDVeG8ArK4Y05mcgrs8qUTmsvlDIXX37cR/DvmVbNB76M4IrsZeSAIajL9644CywkA== +"@aws-sdk/eventstream-serde-browser@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-browser/-/eventstream-serde-browser-3.329.0.tgz#3ba7866a691905e2af8a89c1f562f91fb3779ef9" + integrity sha512-oWFSn4o6sxlbFF0AIuDJYf7N0fkiOyWvYgRW3VTX9FSbd66f/KnDspdxIasaDPDUzJl5YRMwUvQbPWw8y9ZQfQ== dependencies: - "@aws-sdk/eventstream-serde-universal" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/eventstream-serde-universal" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/eventstream-serde-config-resolver@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.310.0.tgz#e4e2358f36b9eb6d37da0a0f0d3fc32da91ad6b4" - integrity sha512-8s1Qdn9STj+sV75nUp9yt0W6fHS4BZ2jTm4Z/1Pcbvh2Gqs0WjH5n2StS+pDW5Y9J/HSGBl0ogmUr5lC5bXFHg== +"@aws-sdk/eventstream-serde-config-resolver@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.329.0.tgz#8498747fa40c8cf159181da043fd9b0ae949deb7" + integrity sha512-iQguqvTtxWXAIniaWmmAO0Qy8080fqnS309p9jbYzz7KaT90sNSCX+CxGFHPy5F0QY36uklDdHn1d1fwWTZciA== dependencies: - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/eventstream-serde-node@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-node/-/eventstream-serde-node-3.310.0.tgz#6e0fbc400bac677c77b946fd2a5cb00b57503c0e" - integrity sha512-kSnRomCgW43K9TmQYuwN9+AoYPnhyOKroanUMyZEzJk7rpCPMj4OzaUpXfDYOvznFNYn7NLaH6nHLJAr0VPlJA== +"@aws-sdk/eventstream-serde-node@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-node/-/eventstream-serde-node-3.329.0.tgz#8faf03049bde8772cf75c3831a78df160bbb6ad3" + integrity sha512-+DFia0wdZiHpdOKjBcl1baZjtzPKf4U4MvOpsUpC6CeW1kSy0hoikKzJstNvRb1qxrTSamElT4gKkMHxxVhPBQ== dependencies: - "@aws-sdk/eventstream-serde-universal" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/eventstream-serde-universal" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/eventstream-serde-universal@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-universal/-/eventstream-serde-universal-3.310.0.tgz#d0f95eaafb8fd09d9a21aec8f23b7f3cee2bb19a" - integrity sha512-Qyjt5k/waV5cDukpgT824ISZAz5U0pwzLz5ztR409u85AGNkF/9n7MS+LSyBUBSb0WJ5pUeSD47WBk+nLq9Nhw== +"@aws-sdk/eventstream-serde-universal@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-universal/-/eventstream-serde-universal-3.329.0.tgz#c4e4bd786c8e111db8636e76f343c1c08a076c07" + integrity sha512-n9UzW6HKAhVD5wuz3FMC1ew3VI/vUvRSPXGUpKReMiR2z+YyjmuW8UM4nn7q6i7A/I4QHBt1TC/ax/J2yupgPg== dependencies: - "@aws-sdk/eventstream-codec" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/eventstream-codec" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/fetch-http-handler@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.310.0.tgz#f31006b7b3103683d72e177cd27d80354f7a37c4" - integrity sha512-Bi9vIwzdkw1zMcvi/zGzlWS9KfIEnAq4NNhsnCxbQ4OoIRU9wvU+WGZdBBhxg0ZxZmpp1j1aZhU53lLjA07MHw== +"@aws-sdk/fetch-http-handler@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.329.0.tgz#5aee0c9a32ad8ff4fa96c6869bba68c345818532" + integrity sha512-9jfIeJhYCcTX4ScXOueRTB3S/tVce0bRsKxKDP0PnTxnGYOwKXoM9lAPmiYItzYmQ/+QzjTI8xfkA9Usz2SK/Q== dependencies: - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/querystring-builder" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/querystring-builder" "3.329.0" + "@aws-sdk/types" "3.329.0" "@aws-sdk/util-base64" "3.310.0" tslib "^2.5.0" -"@aws-sdk/hash-blob-browser@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/hash-blob-browser/-/hash-blob-browser-3.310.0.tgz#762a56ae655e3bcd0ba46bbc39e8b370b1067629" - integrity sha512-OoR8p0cbypToysLT0v3o2oyjy6+DKrY7GNCAzHOHJK9xmqXCt+DsjKoPeiY7o1sWX2aN6Plmvubj/zWxMKEn/A== +"@aws-sdk/hash-blob-browser@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/hash-blob-browser/-/hash-blob-browser-3.329.0.tgz#a90a73998dd017b80952743a3901d5036e142506" + integrity sha512-F5HwXYYSpJtUJqmCRKbz/xwDdOyxKpu69TlfsliECLvAQiQGMh2GO1wGm7grolgTROVVqLYRKk2TSJl/WBg1pw== dependencies: "@aws-sdk/chunked-blob-reader" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/hash-node@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/hash-node/-/hash-node-3.310.0.tgz#4c1c89b9a2da3bb9783de84f0b762cc055b90d67" - integrity sha512-NvE2fhRc8GRwCXBfDehxVAWCmVwVMILliAKVPAEr4yz2CkYs0tqU51S48x23dtna07H4qHtgpeNqVTthcIQOEQ== +"@aws-sdk/hash-node@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/hash-node/-/hash-node-3.329.0.tgz#91ef8b1b55e1a438c367f63747673bf146a00499" + integrity sha512-6RmnWXNWpi7yAs0oRDQlkMn2wfXOStr/8kTCgiAiqrk1KopGSBkC2veKiKRSfv02FTd1yV/ISqYNIRqW1VLyxg== dependencies: - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" "@aws-sdk/util-buffer-from" "3.310.0" "@aws-sdk/util-utf8" "3.310.0" tslib "^2.5.0" -"@aws-sdk/hash-stream-node@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/hash-stream-node/-/hash-stream-node-3.310.0.tgz#3845d813a7de476c56fac492a50ffa8af265f120" - integrity sha512-ZoXdybNgvMz1Hl6k/e32xVL3jmG5p2IEk5mTtLfFEuskTJ74Z+VMYKkkF1whyy7KQfH83H+TQGnsGtlRCchQKw== +"@aws-sdk/hash-stream-node@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/hash-stream-node/-/hash-stream-node-3.329.0.tgz#137b2bc825a7435514b30a89299b68f33c6e7e9b" + integrity sha512-blSZcb/hJyw3c1bH2Hc1aRoRgruNhRK/qc2svq5kXQFW+qBI5O4fwJayKSdo62/Wh2ejR/N06teYQ9haQLVJEA== dependencies: - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" "@aws-sdk/util-utf8" "3.310.0" tslib "^2.5.0" -"@aws-sdk/invalid-dependency@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/invalid-dependency/-/invalid-dependency-3.310.0.tgz#b96da9b9f63b12d1c390f9a06eeb28840fcb5b3c" - integrity sha512-1s5RG5rSPXoa/aZ/Kqr5U/7lqpx+Ry81GprQ2bxWqJvWQIJ0IRUwo5pk8XFxbKVr/2a+4lZT/c3OGoBOM1yRRA== +"@aws-sdk/invalid-dependency@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/invalid-dependency/-/invalid-dependency-3.329.0.tgz#83dc33de710f80eba5e084a82aab656c1d240352" + integrity sha512-UXynGusDxN/HxLma5ByJ7u+XnuMd47NbHOjJgYsaAjb1CVZT7hEPXOB+mcZ+Ku7To5SCOKu2QbRn7m4bGespBg== dependencies: - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" "@aws-sdk/is-array-buffer@3.310.0": @@ -709,328 +709,335 @@ dependencies: tslib "^2.5.0" -"@aws-sdk/md5-js@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/md5-js/-/md5-js-3.310.0.tgz#14e3d570d92808e68ccc0db8d7492ebdb93f15b5" - integrity sha512-x5sRBUrEfLWAS1EhwbbDQ7cXq6uvBxh3qR2XAsnGvFFceTeAadk7cVogWxlk3PC+OCeeym7c3/6Bv2HQ2f1YyQ== +"@aws-sdk/md5-js@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/md5-js/-/md5-js-3.329.0.tgz#25a6b417ecba04ed4e6b299ad5db0e5ab59c9603" + integrity sha512-newSeHd+CO2hNmXhQOrUk5Y1hH7BsJ5J4IldcqHKY93UwWqvQNiepRowSa2bV5EuS1qx3kfXhD66PFNRprrIlQ== dependencies: - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" "@aws-sdk/util-utf8" "3.310.0" tslib "^2.5.0" -"@aws-sdk/middleware-bucket-endpoint@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.310.0.tgz#5dd9b028498a0492c3e773c0aca10d6ded929fc6" - integrity sha512-uJJfHI7v4AgbJZRLtyI8ap2QRWkBokGc3iyUoQ+dVNT3/CE2ZCu694A6W+H0dRqg79dIE+f9CRNdtLGa/Ehhvg== +"@aws-sdk/middleware-bucket-endpoint@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.329.0.tgz#cae414055e1ff7e2f724f7da2feabb93ffffc3a7" + integrity sha512-h3/JdK+FmJ/nxLcd8QciJYLy0B4QRsYqqxSffXJ7DYlDjEhUgvVpfGdVgAYHrTtOP8rHSG/K7l7iY7QqTaZpuw== dependencies: - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/types" "3.329.0" "@aws-sdk/util-arn-parser" "3.310.0" "@aws-sdk/util-config-provider" "3.310.0" tslib "^2.5.0" -"@aws-sdk/middleware-content-length@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-content-length/-/middleware-content-length-3.310.0.tgz#cc9b6c25c10736cec41d0219c94b57cfdb4582a3" - integrity sha512-P8tQZxgDt6CAh1wd/W6WPzjc+uWPJwQkm+F7rAwRlM+k9q17HrhnksGDKcpuuLyIhPQYdmOMIkpKVgXGa4avhQ== +"@aws-sdk/middleware-content-length@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-content-length/-/middleware-content-length-3.329.0.tgz#cadd0c3ba7fe3d0b21812523bb7d7f7526c9c700" + integrity sha512-7kCd+CvY/4KbyXB0uyL7jCwPjMi2yERMALFdEH9dsUciwmxIQT6eSc4aF6wImC4UrbafaqmXvvHErABKMVBTKA== dependencies: - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/middleware-endpoint@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.310.0.tgz#d4bf8ac3cd4800af789d6bcb469b7e8cfa10badb" - integrity sha512-Z+N2vOL8K354/lstkClxLLsr6hCpVRh+0tCMXrVj66/NtKysCEZ/0b9LmqOwD9pWHNiI2mJqXwY0gxNlKAroUg== +"@aws-sdk/middleware-endpoint@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.329.0.tgz#50c5f71afa3b6d3062d3b542279009454898314e" + integrity sha512-hdJRoNdCM0BT4W+rrtee+kfFRgGPGXQDgtbIQlf/FuuuYz2sdef7/SYWr0mxuncnVBW5WkYSPP8h6q07whSKbg== dependencies: - "@aws-sdk/middleware-serde" "3.310.0" - "@aws-sdk/types" "3.310.0" - "@aws-sdk/url-parser" "3.310.0" - "@aws-sdk/util-middleware" "3.310.0" + "@aws-sdk/middleware-serde" "3.329.0" + "@aws-sdk/types" "3.329.0" + "@aws-sdk/url-parser" "3.329.0" + "@aws-sdk/util-middleware" "3.329.0" tslib "^2.5.0" -"@aws-sdk/middleware-expect-continue@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.310.0.tgz#0b5421d5fddb2c0ebf8e5c9c6122d01b159dad45" - integrity sha512-l3d1z2gt+gINJDnPSyu84IxfzjzPfCQrqC1sunw2cZGo/sXtEiq698Q3SiTcO2PGP4LBQAy2RHb5wVBJP708CQ== +"@aws-sdk/middleware-expect-continue@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.329.0.tgz#2a69584020b9c93926b83735fbd9741de117a586" + integrity sha512-E/Jp2KijdR/BwF4s899xcSN4/bbHqYznwmBRL5PiHI+HImA6aZ11qTP8kPt5U5p0l2j5iTmW3FpMnByQKJP5Dw== dependencies: - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/middleware-flexible-checksums@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.310.0.tgz#1bebffe42c4109e255716507b63dc964f84b16a5" - integrity sha512-5ndnLgzgGVpWkmHBAiYkagHqiSuow8q62J4J6E2PzaQ77+fm8W3nfdy7hK5trHokEyouCZdxT/XK/IRhgj/4PA== +"@aws-sdk/middleware-flexible-checksums@3.331.0": + version "3.331.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.331.0.tgz#41878726e7b2da175bfb5b5eb688123c7fb7cce3" + integrity sha512-rdRa4yvyqSQ/HDCh4p1Glv8Y/uRNuIwmOG4nDuL6/GYK1BQdpUpbgrhsszPormku10SnbAdsaWGmVhy3qlUSCQ== dependencies: "@aws-crypto/crc32" "3.0.0" "@aws-crypto/crc32c" "3.0.0" "@aws-sdk/is-array-buffer" "3.310.0" - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/types" "3.329.0" "@aws-sdk/util-utf8" "3.310.0" tslib "^2.5.0" -"@aws-sdk/middleware-host-header@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.310.0.tgz#bdd4fbffb58b331bda517df8340aa8b44ce55550" - integrity sha512-QWSA+46/hXorXyWa61ic2K7qZzwHTiwfk2e9mRRjeIRepUgI3qxFjsYqrWtrOGBjmFmq0pYIY8Bb/DCJuQqcoA== +"@aws-sdk/middleware-host-header@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.329.0.tgz#22b1a6d91f3f281ef802f21f2ab0b426526d6066" + integrity sha512-JrHeUdTIpTCfXDo9JpbAbZTS1x4mt63CCytJRq0mpWp+FlP9hjckBcNxWdR/wSKEzP9pDRnTri638BOwWH7O8w== dependencies: - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/middleware-location-constraint@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.310.0.tgz#6a24fa717bff47932d22071861c55421766ecca7" - integrity sha512-LFm0JTQWwTPWL/tZU2wsQTl8J5PpDEkXjEhaXVKamtyH0xhysRqd+0n92n65dc8oztAuQkb9xUbErGn5b6gsew== +"@aws-sdk/middleware-location-constraint@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.329.0.tgz#8f6e21c2eee990579e3ac06bdbb8b89f2cde49a4" + integrity sha512-iUTkyXyhchqoEPkdMZSkHhRQmXe0El1+r9oOw8y9JN6IY0T1bnaqUlerGXzb/tQUeENk9OXYuvDHExegHjEWug== dependencies: - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/middleware-logger@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.310.0.tgz#8cc6381f49ef867cae1364b8517f939629e4dd9d" - integrity sha512-Lurm8XofrASBRnAVtiSNuDSRsRqPNg27RIFLLsLp/pqog9nFJ0vz0kgdb9S5Z+zw83Mm+UlqOe6D8NTUNp4fVg== +"@aws-sdk/middleware-logger@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.329.0.tgz#fa8adc07928da24e713e384d4a32c8d0e36f96ee" + integrity sha512-lKeeTXsYC1NiwmxrXsZepcwNXPoQxTNNbeD1qaCELPGK2cJlrGoeAP2YRWzpwO2kNZWrDLaGAPT/EUEhqw+d1w== dependencies: - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/middleware-recursion-detection@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.310.0.tgz#020c986ed8da751bd613fd84c8c8a805c89e0952" - integrity sha512-SuB75/xk/gyue24gkriTwO2jFd7YcUGZDClQYuRejgbXSa3CO0lWyawQtfLcSSEBp9izrEVXuFH24K1eAft5nQ== +"@aws-sdk/middleware-recursion-detection@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.329.0.tgz#afa676f26f9a050cd3d57a2efa2b0247a6e1d614" + integrity sha512-0/TYOJwrj1Z8s+Y7thibD23hggBq/K/01NwPk32CwWG/G+1vWozs5DefknEl++w0vuV+39pkY4KHI8m/+wOCpg== dependencies: - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/middleware-retry@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-retry/-/middleware-retry-3.310.0.tgz#12e95e962875d44af4acbdebe02db337a1ad5c35" - integrity sha512-oTPsRy2W4s+dfxbJPW7Km+hHtv/OMsNsVfThAq8DDYKC13qlr1aAyOqGLD+dpBy2aKe7ss517Sy2HcHtHqm7/g== - dependencies: - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/service-error-classification" "3.310.0" - "@aws-sdk/types" "3.310.0" - "@aws-sdk/util-middleware" "3.310.0" - "@aws-sdk/util-retry" "3.310.0" +"@aws-sdk/middleware-retry@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-retry/-/middleware-retry-3.329.0.tgz#326fb0b7442d665689d311fba43eb49a510d2939" + integrity sha512-cB3D7GlhHUcHGOlygOYxD9cPhwsTYEAMcohK38An8+RHNp6VQEWezzLFCmHVKUSeCQ+wkjZfPA40jOG0rbjSgQ== + dependencies: + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/service-error-classification" "3.329.0" + "@aws-sdk/types" "3.329.0" + "@aws-sdk/util-middleware" "3.329.0" + "@aws-sdk/util-retry" "3.329.0" tslib "^2.5.0" uuid "^8.3.2" -"@aws-sdk/middleware-sdk-ec2@3.311.0": - version "3.311.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-ec2/-/middleware-sdk-ec2-3.311.0.tgz#313f7e4874be5a0dd07e65c7d2fb9df4807ae230" - integrity sha512-q4VjgBxJCBYpJAV7MDFP8JIvvhMcc2k1mm8RmFkl0YQj0iBQIa6i4+sQ+yoJ/jfwiCrPwSzN7TMrGFcq7fmPDw== - dependencies: - "@aws-sdk/middleware-endpoint" "3.310.0" - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/signature-v4" "3.310.0" - "@aws-sdk/smithy-client" "3.310.0" - "@aws-sdk/types" "3.310.0" - "@aws-sdk/util-format-url" "3.310.0" +"@aws-sdk/middleware-sdk-ec2@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-ec2/-/middleware-sdk-ec2-3.329.0.tgz#c219d61909d70bb023040e9f77058ef6b34f2e9e" + integrity sha512-V0AAfaNIFz1cLVayLGp+9KjoaIjnAgLd4y6yZKy6M5g6pCpxPKB9hfFjepgpX35xfFnaChS7UqBEUd/PbegcUA== + dependencies: + "@aws-sdk/middleware-endpoint" "3.329.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/signature-v4" "3.329.0" + "@aws-sdk/smithy-client" "3.329.0" + "@aws-sdk/types" "3.329.0" + "@aws-sdk/util-format-url" "3.329.0" tslib "^2.5.0" -"@aws-sdk/middleware-sdk-rds@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-rds/-/middleware-sdk-rds-3.310.0.tgz#2ecf880063ade9bae8abcfd4fefb386ab29ceb50" - integrity sha512-V1nUsjggGLjy+Hx/z/7tb6bnfzZ1Kx4ikOdYVlTidnSCWZdh+kFE5Em16f5Q3erwG5Sil4Uxk0vpj+MSFP5MKA== - dependencies: - "@aws-sdk/middleware-endpoint" "3.310.0" - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/signature-v4" "3.310.0" - "@aws-sdk/types" "3.310.0" - "@aws-sdk/util-format-url" "3.310.0" +"@aws-sdk/middleware-sdk-rds@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-rds/-/middleware-sdk-rds-3.329.0.tgz#b7fc6afce0f9899b296d8a6fb9ce9752db21fa78" + integrity sha512-SwID8UbVAKWX/UKL4PGOqRezMG6i8DtARi2252iDRTWE66i+WSjv5XRlxgE++GxfFuwtzO6QM+YdyCPaJGmpgw== + dependencies: + "@aws-sdk/middleware-endpoint" "3.329.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/signature-v4" "3.329.0" + "@aws-sdk/types" "3.329.0" + "@aws-sdk/util-format-url" "3.329.0" tslib "^2.5.0" -"@aws-sdk/middleware-sdk-s3@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.310.0.tgz#9f060e961ccc462ea5ca8c24cb0845d655b00d24" - integrity sha512-QK9x9g2ksg0hOjjYgqddeFcn5ctUEGdxJVu4OumPXceulefMcSO2jyH2qTybYSA93nqNQFdFmg5wQfvIRUWFCQ== +"@aws-sdk/middleware-sdk-s3@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.329.0.tgz#e5b99d7a9074a069c5f75afdce0b91c8b9855112" + integrity sha512-Uo8dLXLDpOb3BnLVl0mkTPiVXlNzNGOXOVtpihvYhF2Z+hGFJW1Ro3aUDbVEsFHu753r2Lss4dLiq1fzREeBKA== dependencies: - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/types" "3.329.0" "@aws-sdk/util-arn-parser" "3.310.0" tslib "^2.5.0" -"@aws-sdk/middleware-sdk-sts@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.310.0.tgz#2001b421f317404ca98d4a1cfea408b7a64c35f5" - integrity sha512-+5PFwlYNLvLLIfw0ASAoWV/iIF8Zv6R6QGtyP0CclhRSvNjgbQDVnV0g95MC5qvh+GB/Yjlkt8qAjLSPjHfsrQ== +"@aws-sdk/middleware-sdk-sts@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.329.0.tgz#50056cca7688e708e3db6bd66203878bc373ff7d" + integrity sha512-bqtZuhkH8pANb2Gb4FEM1p27o+BoDBmVhEWm8sWH+APsyOor3jc6eUG2GxkfoO6D5tGNIuyCC/GuvW9XDIe4Kg== dependencies: - "@aws-sdk/middleware-signing" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/middleware-signing" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/middleware-serde@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-serde/-/middleware-serde-3.310.0.tgz#e334031b66a1a155375ec901478b26570fbe1783" - integrity sha512-RNeeTVWSLTaentUeCgQKZhAl+C6hxtwD78cQWS10UymWpQFwbaxztzKUu4UQS5xA2j6PxwPRRUjqa4jcFjfLsg== +"@aws-sdk/middleware-serde@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-serde/-/middleware-serde-3.329.0.tgz#f822d7419953ba5d31104262724034340908dd28" + integrity sha512-tvM9NdPuRPCozPjTGNOeYZeLlyx3BcEyajrkRorCRf1YzG/mXdB6I1stote7i4q1doFtYTz0sYL8bqW3LUPn9A== dependencies: - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/middleware-signing@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.310.0.tgz#bd62d5623c80f6318b0d738c44780875500c911a" - integrity sha512-f9mKq+XMdW207Af3hKjdTnpNhdtwqWuvFs/ZyXoOkp/g1MY1O6L23Jy6i52m29LxbT4AuNRG1oKODfXM0vYVjQ== - dependencies: - "@aws-sdk/property-provider" "3.310.0" - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/signature-v4" "3.310.0" - "@aws-sdk/types" "3.310.0" - "@aws-sdk/util-middleware" "3.310.0" +"@aws-sdk/middleware-signing@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.329.0.tgz#25011abb0911c1a23840d8d228676758f5b55926" + integrity sha512-bL1nI+EUcF5B1ipwDXxiKL+Uw02Mbt/TNX54PbzunBGZIyO6DZG/H+M3U296bYbvPlwlZhp26O830g6K7VEWsA== + dependencies: + "@aws-sdk/property-provider" "3.329.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/signature-v4" "3.329.0" + "@aws-sdk/types" "3.329.0" + "@aws-sdk/util-middleware" "3.329.0" tslib "^2.5.0" -"@aws-sdk/middleware-ssec@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.310.0.tgz#6a1da92cbc1734604295149c0d8cfed47f6e0fd3" - integrity sha512-CnEwNKVpd5bXnrCKPaePF8mWTA9ET21OMBb54y9b0fd8K02zoOcdBz4DWfh1SjFD4HkgCdja4egd8l2ivyvqmw== +"@aws-sdk/middleware-ssec@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.329.0.tgz#c5bef2aca924c694e0ce03e8d1676b6d1885c0d4" + integrity sha512-XtDA/P2Sf79scu4a7tG77QC3VLtAGq/pit73x+qwctnI4gBgZlQ+FpE15d89ulntd7rIaD4v6tVU0bAg/L3PIQ== dependencies: - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/middleware-stack@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-stack/-/middleware-stack-3.310.0.tgz#06c83963998fbdc83e99b67a7a138529312a6224" - integrity sha512-010O1PD+UAcZVKRvqEusE1KJqN96wwrf6QsqbRM0ywsKQ21NDweaHvEDlds2VHpgmofxkRLRu/IDrlPkKRQrRg== +"@aws-sdk/middleware-stack@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-stack/-/middleware-stack-3.329.0.tgz#745150a190cc025d0bd7a52c0db5580c05dbbb54" + integrity sha512-2huFLhJ45td2nuiIOjpc9JKJbFNn5CYmw9U8YDITTcydpteRN62CzCpeqroDvF89VOLWxh0ZFtuLCGUr7liSWQ== dependencies: tslib "^2.5.0" -"@aws-sdk/middleware-user-agent@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.310.0.tgz#2aa3982cbc5e9c137024cec47914e86610ab0a09" - integrity sha512-x3IOwSwSbwKidlxRk3CNVHVUb06SRuaELxggCaR++QVI8NU6qD/l4VHXKVRvbTHiC/cYxXE/GaBDgQVpDR7V/g== +"@aws-sdk/middleware-user-agent@3.332.0": + version "3.332.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.332.0.tgz#6f2de9579b09dd7feeab27ef8a18c236694ad903" + integrity sha512-rSL1xP4QmcMOsunN1p5ZDR9GT3vvoSCnYa4iPvMSjP8Jx7l4ff/aVctwfZkMs/up12+68Jqwj4TvtaCvCFXdUA== dependencies: - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/types" "3.310.0" - "@aws-sdk/util-endpoints" "3.310.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/types" "3.329.0" + "@aws-sdk/util-endpoints" "3.332.0" tslib "^2.5.0" -"@aws-sdk/node-config-provider@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/node-config-provider/-/node-config-provider-3.310.0.tgz#ba8fb41af2db0316291ba9002267627553ec65ac" - integrity sha512-T/Pp6htc6hq/Cq+MLNDSyiwWCMVF6GqbBbXKVlO5L8rdHx4sq9xPdoPveZhGWrxvkanjA6eCwUp6E0riBOSVng== +"@aws-sdk/node-config-provider@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/node-config-provider/-/node-config-provider-3.329.0.tgz#32666077565924354a2216a5343ee768d3107eea" + integrity sha512-hg9rGNlkzh8aeR/sQbijrkFx2BIO53j4Z6qDxPNWwSGpl05jri1VHxHx2HZMwgbY6Zy/DSguETN/BL8vdFqyLg== dependencies: - "@aws-sdk/property-provider" "3.310.0" - "@aws-sdk/shared-ini-file-loader" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/property-provider" "3.329.0" + "@aws-sdk/shared-ini-file-loader" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/node-http-handler@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/node-http-handler/-/node-http-handler-3.310.0.tgz#bd8e72c1c7cf4b48c2a21851f638ad5e63001787" - integrity sha512-irv9mbcM9xC2xYjArQF5SYmHBMu4ciMWtGsoHII1nRuFOl9FoT4ffTvEPuLlfC6pznzvKt9zvnm6xXj7gDChKg== +"@aws-sdk/node-http-handler@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/node-http-handler/-/node-http-handler-3.329.0.tgz#6dc721e6a9df7baebefd145295ef1a8bf1000a51" + integrity sha512-OrjaHjU2ZTPfoHa5DruRvTIbeHH/cc0wvh4ml+FwDpWaPaBpOhLiluhZ3anqX1l5QjrXNiQnL8FxSM5OV/zVCA== dependencies: - "@aws-sdk/abort-controller" "3.310.0" - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/querystring-builder" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/abort-controller" "3.329.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/querystring-builder" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/property-provider@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/property-provider/-/property-provider-3.310.0.tgz#5fae8a4c11bda052afa9747d47b031f1c4f0f246" - integrity sha512-3lxDb0akV6BBzmFe4nLPaoliQbAifyWJhuvuDOu7e8NzouvpQXs0275w9LePhhcgjKAEVXUIse05ZW2DLbxo/g== +"@aws-sdk/property-provider@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/property-provider/-/property-provider-3.329.0.tgz#069dda84e132c9d4eca1a4ae37c62f7a650a0046" + integrity sha512-1cHLTV6yyMGaMSWWDW/p4vTkJ1cc5BOEO+A0eHuAcoSOk+LDe9IKhUG3/ZOvvYKQYcqIj5jjGSni/noXNCl/qw== dependencies: - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/protocol-http@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/protocol-http/-/protocol-http-3.310.0.tgz#855c3314cba7ff3024a9a9701ca3c641691d997e" - integrity sha512-fgZ1aw/irQtnrsR58pS8ThKOWo57Py3xX6giRvwSgZDEcxHfVzuQjy9yPuV++v04fdmdtgpbGf8WfvAAJ11yXQ== +"@aws-sdk/protocol-http@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/protocol-http/-/protocol-http-3.329.0.tgz#a8a7e01477831961f5f040fe607c3552f9ccb013" + integrity sha512-0rLEHY6QTHTUUcVxzGbPUSmCKlXWplxT/fcYRh0bcc5MBK4naKfcQft1O6Ajp8uqs/9YPZ7XCVCn90pDeJfeaw== dependencies: - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/querystring-builder@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-builder/-/querystring-builder-3.310.0.tgz#5307ea52c3a4a1ae6818bbb6987cc6fce68b043f" - integrity sha512-ZHH8GV/80+pWGo7DzsvwvXR5xVxUHXUvPJPFAkhr6nCf78igdoF8gR10ScFoEKbtEapoNTaZlKHPXxpD8aPG7A== +"@aws-sdk/querystring-builder@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-builder/-/querystring-builder-3.329.0.tgz#c6e6dd03dcd4378d1fbee576ce2a81dd94ac46a6" + integrity sha512-UWgMKkS5trliaDJG4nPv3onu8Y0aBuwRo7RdIgggguOiU8pU6pq1I113nH2FBNWy+Me1bwf+bcviJh0pCo6bEg== dependencies: - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" "@aws-sdk/util-uri-escape" "3.310.0" tslib "^2.5.0" -"@aws-sdk/querystring-parser@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-parser/-/querystring-parser-3.310.0.tgz#438183927e0b06e7c2ee004a1681b8d37c22e104" - integrity sha512-YkIznoP6lsiIUHinx++/lbb3tlMURGGqMpo0Pnn32zYzGrJXA6eC3D0as2EcMjo55onTfuLcIiX4qzXes2MYOA== +"@aws-sdk/querystring-parser@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-parser/-/querystring-parser-3.329.0.tgz#dbbf2fd23ff0dfa2e4663fa414de1d5e60814896" + integrity sha512-9mkK+FB7snJ2G7H3CqtprDwYIRhzm6jEezffCwUWrC+lbqHBbErbhE9IeU/MKxILmf0RbC2riXEY1MHGspjRrQ== dependencies: - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/service-error-classification@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/service-error-classification/-/service-error-classification-3.310.0.tgz#352c1db426dcf54a44393bc9a0607dde796b2abb" - integrity sha512-PuyC7k3qfIKeH2LCnDwbttMOKq3qAx4buvg0yfnJtQOz6t1AR8gsnAq0CjKXXyfkXwNKWTqCpE6lVNUIkXgsMw== +"@aws-sdk/service-error-classification@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/service-error-classification/-/service-error-classification-3.329.0.tgz#32db59091ff28f14e526cee738bc14e32a6850f6" + integrity sha512-TSNr0flOcCLe71aPp7MjblKNGsmxpTU4xR5772MDX9Cz9GUTNZCPFtvrcqd+wzEPP/AC7XwNXe8KjoXooZImUQ== -"@aws-sdk/shared-ini-file-loader@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.310.0.tgz#07e9c8e8e8bb0de7ed19b8cea908c920a493c9c9" - integrity sha512-N0q9pG0xSjQwc690YQND5bofm+4nfUviQ/Ppgan2kU6aU0WUq8KwgHJBto/YEEI+VlrME30jZJnxtOvcZJc2XA== +"@aws-sdk/shared-ini-file-loader@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.329.0.tgz#190eb922860d49b4259b20ca6df4d20769544802" + integrity sha512-e0hyd75fbjMd4aCoRwpP2/HR+0oScwogErVArIkq3F42c/hyNCQP3sph4JImuXIjuo6HNnpKpf20CEPPhNna8A== dependencies: - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/signature-v4-multi-region@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.310.0.tgz#36eb96aa9170994ed1c5551952d2ec2d5e40c4c7" - integrity sha512-q8W+RIomTS/q85Ntgks/CoDElwqkC9+4OCicee5YznNHjQ4gtNWhUkYIyIRWRmXa/qx/AUreW9DM8FAecCOdng== +"@aws-sdk/signature-v4-multi-region@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.329.0.tgz#6ccf1255358a49c1393e6f7c8cd43800827eb37e" + integrity sha512-SiK1ez8Ns61ulDm0MJsTOSGNJNOMNoPgfA9i+Uu/VMCBkotZASuxrcSWW8seQnLEynWLerjUF9CYpCQuCqKn9w== dependencies: - "@aws-sdk/protocol-http" "3.310.0" - "@aws-sdk/signature-v4" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/protocol-http" "3.329.0" + "@aws-sdk/signature-v4" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/signature-v4@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4/-/signature-v4-3.310.0.tgz#ad26426d3f72fa18e6808a36f827beb72d12bf2d" - integrity sha512-1M60P1ZBNAjCFv9sYW29OF6okktaeibWyW3lMXqzoHF70lHBZh+838iUchznXUA5FLabfn4jBFWMRxlAXJUY2Q== +"@aws-sdk/signature-v4@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4/-/signature-v4-3.329.0.tgz#8d40683189678f49504169c923e8342247b1da70" + integrity sha512-9EnLoyOD5nFtCRAp+QRllDgQASCfY7jLHVhwht7jzwE80wE65Z9Ym5Z/mwTd4IyTz/xXfCvcE2VwClsBt0Ybdw== dependencies: "@aws-sdk/is-array-buffer" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" "@aws-sdk/util-hex-encoding" "3.310.0" - "@aws-sdk/util-middleware" "3.310.0" + "@aws-sdk/util-middleware" "3.329.0" "@aws-sdk/util-uri-escape" "3.310.0" "@aws-sdk/util-utf8" "3.310.0" tslib "^2.5.0" -"@aws-sdk/smithy-client@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/smithy-client/-/smithy-client-3.310.0.tgz#04fca042ffc120c35eeea1335fa055d39f1bd7bd" - integrity sha512-UHMFvhoB2RLzsTb0mQe1ofvBUg/+/JEu1uptavxf/hEpEKZnRAaHH5FNkTG+mbFd/olay/QFjqNcMD6t8LcsNQ== +"@aws-sdk/smithy-client@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/smithy-client/-/smithy-client-3.329.0.tgz#54705963939855c87ae6e6c88196d23e819d728e" + integrity sha512-7E0fGpBKxwFqHHAOqNbgNsHSEmCZLuvmU9yvG9DXKVzrS4P48O/PfOro123WpcFZs3STyOVgH8wjUPftHAVKmg== dependencies: - "@aws-sdk/middleware-stack" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/middleware-stack" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/token-providers@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.310.0.tgz#2d0b0d3ef729f6cdc6a0cc859e80bb9efea2d8fa" - integrity sha512-G1JvB+2v8k900VJFkKVQXgLGF50ShOEIPxfK1gSQLkSU85vPwGIAANs1KvnlW08FsNbWp3+sKca4kfYKsooXMw== +"@aws-sdk/token-providers@3.332.0": + version "3.332.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.332.0.tgz#d014556ad93c0e43bb20237a3c5e85e9eed612a2" + integrity sha512-fccbg6OSl0l658pxl2p1MoU9gEePo5B361+JNaN0zfRMu7c5HBXCpdl4djlFxAHjltrX9f1+BKqfGHYgI3h8SQ== + dependencies: + "@aws-sdk/client-sso-oidc" "3.332.0" + "@aws-sdk/property-provider" "3.329.0" + "@aws-sdk/shared-ini-file-loader" "3.329.0" + "@aws-sdk/types" "3.329.0" + tslib "^2.5.0" + +"@aws-sdk/types@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.329.0.tgz#bc20659abfcd666954196c3a24ad47785db80dd3" + integrity sha512-wFBW4yciDfzQBSFmWNaEvHShnSGLMxSu9Lls6EUf6xDMavxSB36bsrVRX6CyAo/W0NeIIyEOW1LclGPgJV1okg== dependencies: - "@aws-sdk/client-sso-oidc" "3.310.0" - "@aws-sdk/property-provider" "3.310.0" - "@aws-sdk/shared-ini-file-loader" "3.310.0" - "@aws-sdk/types" "3.310.0" tslib "^2.5.0" -"@aws-sdk/types@3.310.0", "@aws-sdk/types@^3.222.0": +"@aws-sdk/types@^3.222.0": version "3.310.0" resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.310.0.tgz#b83a0580feb38b58417abb8b4ed3eae1a0cb7bc1" integrity sha512-j8eamQJ7YcIhw7fneUfs8LYl3t01k4uHi4ZDmNRgtbmbmTTG3FZc2MotStZnp3nZB6vLiPF1o5aoJxWVvkzS6A== dependencies: tslib "^2.5.0" -"@aws-sdk/url-parser@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/url-parser/-/url-parser-3.310.0.tgz#928c9eac2e3d74c3c5db4c6e364a1de00185dcaa" - integrity sha512-mCLnCaSB9rQvAgx33u0DujLvr4d5yEm/W5r789GblwwQnlNXedVu50QRizMLTpltYWyAUoXjJgQnJHmJMaKXhw== +"@aws-sdk/url-parser@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/url-parser/-/url-parser-3.329.0.tgz#a2862834a832ec1d379791f5233e378b75fc63ad" + integrity sha512-/VcfL7vNJKJGSjYYHVQF3bYCDFs4fSzB7j5qeVDwRdWr870gE7O1Dar+sLWBRKFF3AX+4VzplqzUfpu9t44JVA== dependencies: - "@aws-sdk/querystring-parser" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/querystring-parser" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" "@aws-sdk/util-arn-parser@3.310.0": @@ -1077,43 +1084,43 @@ dependencies: tslib "^2.5.0" -"@aws-sdk/util-defaults-mode-browser@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.310.0.tgz#db82bfdf339eea0bc8b1b059dfe9b62e5d3adbf4" - integrity sha512-Mr2AoQsjAYNM5oAS2YJlYJqhiCvkFV/hu48slOZgbY4G7ueW4cM0DPkR16wqjcRCGqZ4JmAZB8Q5R0DMrLjhOQ== +"@aws-sdk/util-defaults-mode-browser@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.329.0.tgz#49fc6836e85968ff86917c56c82fc9ef595c0565" + integrity sha512-2iSiy/pzX3OXMhtSxtAzOiEFr3viQEFnYOTeZuiheuyS+cea2L79F6SlZ1110b/nOIU/UOrxxtz83HVad8YFMQ== dependencies: - "@aws-sdk/property-provider" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/property-provider" "3.329.0" + "@aws-sdk/types" "3.329.0" bowser "^2.11.0" tslib "^2.5.0" -"@aws-sdk/util-defaults-mode-node@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.310.0.tgz#aee459c2da09e2c6e85c6db0406565312f45ccbb" - integrity sha512-JyBlvhQGR8w8NpFRZZXRVTDesafFKTu/gTWjcoxP7twa+fYHSIgPPFGnlcJ/iHaucjamSaWi5EQ+YQmnSZ8yHA== - dependencies: - "@aws-sdk/config-resolver" "3.310.0" - "@aws-sdk/credential-provider-imds" "3.310.0" - "@aws-sdk/node-config-provider" "3.310.0" - "@aws-sdk/property-provider" "3.310.0" - "@aws-sdk/types" "3.310.0" +"@aws-sdk/util-defaults-mode-node@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.329.0.tgz#2296652bcacd56c6abe159194aae283738a796b2" + integrity sha512-7A6C7YKjkZtmKtH29isYEtOCbhd7IcXPP8lftN8WAWlLOiZE4gV7PHveagUj7QserJzgRKGwwTQbBj53n18HYg== + dependencies: + "@aws-sdk/config-resolver" "3.329.0" + "@aws-sdk/credential-provider-imds" "3.329.0" + "@aws-sdk/node-config-provider" "3.329.0" + "@aws-sdk/property-provider" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/util-endpoints@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.310.0.tgz#fea8757038b62d49dacd653061ba04a2ea102a36" - integrity sha512-zG+/d/O5KPmAaeOMPd6bW1abifdT0H03f42keLjYEoRZzYtHPC5DuPE0UayiWGckI6BCDgy0sRKXCYS49UNFaQ== +"@aws-sdk/util-endpoints@3.332.0": + version "3.332.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.332.0.tgz#e360f65d240c97661988e20f15bb5bca160f773a" + integrity sha512-nQx7AiOroMU2hj6h+umWOSZ+WECwxupaxFUK/PPKGW6NY/VdQE6LluYnXOtF5awlr8w1nPksT0Lq05PZutMDLA== dependencies: - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" -"@aws-sdk/util-format-url@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-format-url/-/util-format-url-3.310.0.tgz#4f89c18a23ec6515f50100deced5f236512c4e15" - integrity sha512-NBOvmvvVR3ydquHmznfgtakiSgDhq8Ww6fq8TUaEjM+Es6+iqY4AwZo0rZ9xTX3GpCcoZy391HUi6kiXRAFzuA== +"@aws-sdk/util-format-url@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-format-url/-/util-format-url-3.329.0.tgz#2856379da026adc6355d63bdf6f207a4f8b7c6cb" + integrity sha512-FMokjI10Vzpfb+jeJ0y6TnutPcyessdEz6aKMwn5Ee8etnHaEVDXf5tp8bPZ5ii5WRWwgNNrAa+IkJ2KH4E43g== dependencies: - "@aws-sdk/querystring-builder" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/querystring-builder" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" "@aws-sdk/util-hex-encoding@3.310.0": @@ -1130,40 +1137,40 @@ dependencies: tslib "^2.5.0" -"@aws-sdk/util-middleware@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-middleware/-/util-middleware-3.310.0.tgz#713c5bfa296f4cf707150a0a1e911afd50dcf939" - integrity sha512-FTSUKL/eRb9X6uEZClrTe27QFXUNNp7fxYrPndZwk1hlaOP5ix+MIHBcI7pIiiY/JPfOUmPyZOu+HetlFXjWog== +"@aws-sdk/util-middleware@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-middleware/-/util-middleware-3.329.0.tgz#0d4056c8479d80760778928e807ff74c57fcead3" + integrity sha512-RhBOBaxzkTUghi4MSqr8S5qeeBCjgJ0XPJ6jIYkVkj1saCmqkuZCgl3zFaYdyhdxxPV6nflkFer+1HUoqT+Fqw== dependencies: tslib "^2.5.0" -"@aws-sdk/util-retry@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-retry/-/util-retry-3.310.0.tgz#4cdc35e2dfdacf2d928ab474ba8b67bbadd6be3c" - integrity sha512-FwWGhCBLfoivTMUHu1LIn4NjrN9JLJ/aX5aZmbcPIOhZVFJj638j0qDgZXyfvVqBuBZh7M8kGq0Oahy3dp69OA== +"@aws-sdk/util-retry@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-retry/-/util-retry-3.329.0.tgz#20b71504dd907e70a457cd56dcd131d08d6de39c" + integrity sha512-+3VQ9HZLinysnmryUs9Xjt1YVh4TYYHLt30ilu4iUnIHFQoamdzIbRCWseSVFPCxGroen9M9qmAleAsytHEKuA== dependencies: - "@aws-sdk/service-error-classification" "3.310.0" + "@aws-sdk/service-error-classification" "3.329.0" tslib "^2.5.0" -"@aws-sdk/util-stream-browser@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-stream-browser/-/util-stream-browser-3.310.0.tgz#223e60f7711f7a20fdc944e1b72c8dd4c1da28cf" - integrity sha512-bysXZHwFwvbqOTCScCdCnoLk1K3GCo0HRIYEZuL7O7MHrQmfaYRXcaft/p22+GUv9VeFXS/eJJZ5r4u32az94w== +"@aws-sdk/util-stream-browser@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-stream-browser/-/util-stream-browser-3.329.0.tgz#a85d5f0fecc0817e0b6ff0721a6de774bd1b3890" + integrity sha512-UF1fJNfgrdJLMxn8ZlfPkYdv7hoLvVgSk3GHgxYA4OQs5zKCzeZgVrbxtE147LxWwJbxi3Qf04vnaEHwzVESpg== dependencies: - "@aws-sdk/fetch-http-handler" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/fetch-http-handler" "3.329.0" + "@aws-sdk/types" "3.329.0" "@aws-sdk/util-base64" "3.310.0" "@aws-sdk/util-hex-encoding" "3.310.0" "@aws-sdk/util-utf8" "3.310.0" tslib "^2.5.0" -"@aws-sdk/util-stream-node@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-stream-node/-/util-stream-node-3.310.0.tgz#088c59b7f346669f501ce0ad08cda7e88de0ba1f" - integrity sha512-hueAXFK0GVvnfYFgqbF7587xZfMZff5jlIFZOHqx7XVU7bl7qrRUCnphHk8H6yZ7RoQbDPcfmHJgtEoAJg1T1Q== +"@aws-sdk/util-stream-node@3.331.0": + version "3.331.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-stream-node/-/util-stream-node-3.331.0.tgz#3412a6cbf94085ef59827d248c8664449afb2e4f" + integrity sha512-5YUatdh4vgkv7VFY+lSkF+b+6EFkiHvy+dlucfGoJEOcEzuA/NBZYebWbcJ5TiR6z3cQdA23OTyZz3ZofZY1hw== dependencies: - "@aws-sdk/node-http-handler" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/node-http-handler" "3.329.0" + "@aws-sdk/types" "3.329.0" "@aws-sdk/util-buffer-from" "3.310.0" tslib "^2.5.0" @@ -1174,22 +1181,22 @@ dependencies: tslib "^2.5.0" -"@aws-sdk/util-user-agent-browser@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.310.0.tgz#48d463a93351b78b678df324f3518a9798029c44" - integrity sha512-yU/4QnHHuQ5z3vsUqMQVfYLbZGYwpYblPiuZx4Zo9+x0PBkNjYMqctdDcrpoH9Z2xZiDN16AmQGK1tix117ZKw== +"@aws-sdk/util-user-agent-browser@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.329.0.tgz#6c3353a68f5d3d420156fabdcfab3bf4160f383b" + integrity sha512-8hLSmMCl8aw2++0Zuba8ELq8FkK6/VNyx470St201IpMn2GMbQMDl/rLolRKiTgji6wc+T3pOTidkJkz8/cIXA== dependencies: - "@aws-sdk/types" "3.310.0" + "@aws-sdk/types" "3.329.0" bowser "^2.11.0" tslib "^2.5.0" -"@aws-sdk/util-user-agent-node@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.310.0.tgz#ebefbedc5a4759adc958885741628ec0de1ab197" - integrity sha512-Ra3pEl+Gn2BpeE7KiDGpi4zj7WJXZA5GXnGo3mjbi9+Y3zrbuhJAbdZO3mO/o7xDgMC6ph4xCTbaSGzU6b6EDg== +"@aws-sdk/util-user-agent-node@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.329.0.tgz#eb0930a1f3315fa6ea6f72e4007bbfce1202a3e5" + integrity sha512-C50Zaeodc0+psEP+L4WpElrH8epuLWJPVN4hDOTORcM0cSoU2o025Ost9mbcU7UdoHNxF9vitLnzORGN9SHolg== dependencies: - "@aws-sdk/node-config-provider" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/node-config-provider" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" "@aws-sdk/util-utf8-browser@^3.0.0": @@ -1207,13 +1214,13 @@ "@aws-sdk/util-buffer-from" "3.310.0" tslib "^2.5.0" -"@aws-sdk/util-waiter@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-waiter/-/util-waiter-3.310.0.tgz#a410739cfc637af9ccea21de079d00652e9b8363" - integrity sha512-AV5j3guH/Y4REu+Qh3eXQU9igljHuU4XjX2sADAgf54C0kkhcCCkkiuzk3IsX089nyJCqIcj5idbjdvpnH88Vw== +"@aws-sdk/util-waiter@3.329.0": + version "3.329.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-waiter/-/util-waiter-3.329.0.tgz#4e0d457548661e210cf716f8b18ff16a4dbd17c7" + integrity sha512-MIGs7snNL0ZV55zo1BDVPlrmbinUGV3260hp6HrW4zUbpYVoeIOGeewtrwAsF6FJ+vpZCxljPBB0X2jYR7Q7ZQ== dependencies: - "@aws-sdk/abort-controller" "3.310.0" - "@aws-sdk/types" "3.310.0" + "@aws-sdk/abort-controller" "3.329.0" + "@aws-sdk/types" "3.329.0" tslib "^2.5.0" "@aws-sdk/xml-builder@3.310.0": From 2cc2474388b8e8e985c35888d41b54b80163cbe4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 May 2023 06:43:24 +0000 Subject: [PATCH 46/74] build(deps): update dependency @renovatebot/osv-offline to v1.2.7 (#22252) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 7897f5367472d9..d3f55b20f24bbf 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "@opentelemetry/sdk-trace-node": "1.12.0", "@opentelemetry/semantic-conventions": "1.12.0", "@qnighy/marshal": "0.1.3", - "@renovatebot/osv-offline": "1.2.6", + "@renovatebot/osv-offline": "1.2.7", "@renovatebot/pep440": "2.1.15", "@renovatebot/ruby-semver": "3.0.1", "@sindresorhus/is": "4.6.0", diff --git a/yarn.lock b/yarn.lock index ec4975f0fa98ad..f8181d5ce99ff3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2494,20 +2494,20 @@ "@renovate/eslint-plugin@file:./tools/eslint": version "0.0.0" -"@renovatebot/osv-offline-db@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@renovatebot/osv-offline-db/-/osv-offline-db-1.3.3.tgz#371d0a22ece6b2f1012c525dfd4005ee4e6580f1" - integrity sha512-Q7PNdRbMio2GYFqanuHByln20viVpyNhE4CmcY6ly2TVx42YbuRBrZ57JY5RVid0icArVagkW4mjrDh9CawOgA== +"@renovatebot/osv-offline-db@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@renovatebot/osv-offline-db/-/osv-offline-db-1.4.0.tgz#45f4b580dd80012d78beac1188bece21d02b910a" + integrity sha512-VqR66WlewMLnDOVmnEAHIFZuATG46LwvNu6ZPjH0sEaH6bCqNxfJ6kBMFEiJOWWjGOxI1u2F+nr1vtdixC9UwA== dependencies: "@seald-io/nedb" "^4.0.2" -"@renovatebot/osv-offline@1.2.6": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@renovatebot/osv-offline/-/osv-offline-1.2.6.tgz#66a4ff071c52e38c7fb9837cf9b9efe8b4f6025e" - integrity sha512-0FXihAGhDRAXfqtnEWsz8EH+3vEJpH5zB6FZD48tsK+puz43e6tI4obQGcylhMBToV7ex9M7tU4ukChkHwOGcg== +"@renovatebot/osv-offline@1.2.7": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@renovatebot/osv-offline/-/osv-offline-1.2.7.tgz#88e6d7cd29c51fd60587b39344604116dec019fb" + integrity sha512-1ibPY7iqEsVSnM5Z0G+vWTGj+haPYfYwBB8XgTPPcMYdeUYSYYrFK4cVXxuJxjQ6fWDA/boNhHjy1OEYE4IyZg== dependencies: "@octokit/rest" "^19.0.7" - "@renovatebot/osv-offline-db" "1.3.3" + "@renovatebot/osv-offline-db" "1.4.0" adm-zip "~0.5.10" fs-extra "^11.1.1" got "^11.8.6" From dc077f3f6f218dbe57ca69eb2c7490f4e1d8debc Mon Sep 17 00:00:00 2001 From: fredrondina Date: Tue, 16 May 2023 07:54:09 -0500 Subject: [PATCH 47/74] fix(gitlab): ignoreApprovals add check for existingAnyApproverRule (#22237) --- lib/modules/platform/gitlab/index.spec.ts | 57 +++++++++++++++++++++++ lib/modules/platform/gitlab/index.ts | 20 +++++++- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/lib/modules/platform/gitlab/index.spec.ts b/lib/modules/platform/gitlab/index.spec.ts index de8b8b466c2ce0..500e7ccb6b8603 100644 --- a/lib/modules/platform/gitlab/index.spec.ts +++ b/lib/modules/platform/gitlab/index.spec.ts @@ -1713,6 +1713,63 @@ describe('modules/platform/gitlab/index', () => { `); }); + it('will modify a rule of type any_approvers, if such a rule exists', async () => { + await initPlatform('13.3.6-ee'); + httpMock + .scope(gitlabApiHost) + .post('/api/v4/projects/undefined/merge_requests') + .reply(200, { + id: 1, + iid: 12345, + title: 'some title', + }) + .get('/api/v4/projects/undefined/merge_requests/12345') + .reply(200) + .get('/api/v4/projects/undefined/merge_requests/12345') + .reply(200, { + merge_status: 'can_be_merged', + pipeline: { + id: 29626725, + sha: '2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f', + ref: 'patch-28', + status: 'success', + }, + }) + .put('/api/v4/projects/undefined/merge_requests/12345/merge') + .reply(200) + .get('/api/v4/projects/undefined/merge_requests/12345/approval_rules') + .reply(200, [ + { + name: 'AnyApproverRule', + rule_type: 'any_approver', + id: 50005, + }, + ]) + .put( + '/api/v4/projects/undefined/merge_requests/12345/approval_rules/50005' + ) + .reply(200); + expect( + await gitlab.createPr({ + sourceBranch: 'some-branch', + targetBranch: 'master', + prTitle: 'some-title', + prBody: 'the-body', + labels: [], + platformOptions: { + usePlatformAutomerge: true, + gitLabIgnoreApprovals: true, + }, + }) + ).toStrictEqual({ + id: 1, + iid: 12345, + number: 12345, + sourceBranch: 'some-branch', + title: 'some title', + }); + }); + it('does not try to create already existing approval rule', async () => { await initPlatform('13.3.6-ee'); httpMock diff --git a/lib/modules/platform/gitlab/index.ts b/lib/modules/platform/gitlab/index.ts index eb3af69a208e34..4f1cdf8527a0c9 100644 --- a/lib/modules/platform/gitlab/index.ts +++ b/lib/modules/platform/gitlab/index.ts @@ -530,7 +530,25 @@ export async function getPrList(): Promise { async function ignoreApprovals(pr: number): Promise { try { const url = `projects/${config.repository}/merge_requests/${pr}/approval_rules`; - const { body: rules } = await gitlabApi.getJson<{ name: string }[]>(url); + const { body: rules } = await gitlabApi.getJson< + { + name: string; + rule_type: string; + id: number; + }[] + >(url); + + const existingAnyApproverRule = rules?.find( + ({ rule_type }) => rule_type === 'any_approver' + ); + + if (existingAnyApproverRule) { + await gitlabApi.putJson(`${url}/${existingAnyApproverRule.id}`, { + body: { ...existingAnyApproverRule, approvals_required: 0 }, + }); + return; + } + const ruleName = 'renovateIgnoreApprovals'; const zeroApproversRule = rules?.find(({ name }) => name === ruleName); if (!zeroApproversRule) { From 115ed870abce470aab44f697e6bb8ff88a6556d9 Mon Sep 17 00:00:00 2001 From: Sergei Zharinov Date: Tue, 16 May 2023 17:18:46 +0300 Subject: [PATCH 48/74] fix(logger): Represent Zod errors in friendlier format (#22238) --- lib/logger/utils.spec.ts | 141 ++++++++++++++++++++++++++++++++++++++- lib/logger/utils.ts | 68 +++++++++++++++++++ 2 files changed, 208 insertions(+), 1 deletion(-) diff --git a/lib/logger/utils.spec.ts b/lib/logger/utils.spec.ts index 376584700b8f40..ac944c5ad2ca9c 100644 --- a/lib/logger/utils.spec.ts +++ b/lib/logger/utils.spec.ts @@ -1,4 +1,9 @@ -import { sanitizeValue, validateLogLevel } from './utils'; +import { z } from 'zod'; +import prepareError, { + prepareZodIssues, + sanitizeValue, + validateLogLevel, +} from './utils'; describe('logger/utils', () => { afterEach(() => { @@ -46,4 +51,138 @@ describe('logger/utils', () => { `('sanitizeValue("$input") == "$output"', ({ input, output }) => { expect(sanitizeValue(input)).toBe(output); }); + + describe('prepareError', () => { + function getError( + schema: T, + input: unknown + ): z.ZodError | null { + try { + schema.parse(input); + } catch (error) { + if (error instanceof z.ZodError) { + return error; + } + } + throw new Error('Expected error'); + } + + function prepareIssues( + schema: T, + input: unknown + ): unknown | null { + const error = getError(schema, input); + return error ? prepareZodIssues(error.format()) : null; + } + + it('prepareZodIssues', () => { + expect(prepareIssues(z.string(), 42)).toBe( + 'Expected string, received number' + ); + + expect(prepareIssues(z.string().array(), 42)).toBe( + 'Expected array, received number' + ); + + expect( + prepareIssues(z.string().array(), ['foo', 'bar', 42, 42, 42, 42, 42]) + ).toEqual({ + '2': 'Expected string, received number', + '3': 'Expected string, received number', + '4': 'Expected string, received number', + ___: '... 2 more', + }); + + expect( + prepareIssues(z.record(z.string()), { + foo: 'foo', + bar: 'bar', + key1: 42, + key2: 42, + key3: 42, + key4: 42, + key5: 42, + }) + ).toEqual({ + key1: 'Expected string, received number', + key2: 'Expected string, received number', + key3: 'Expected string, received number', + ___: '... 2 more', + }); + + expect( + prepareIssues( + z.object({ + foo: z.object({ + bar: z.string(), + }), + }), + { foo: { bar: [], baz: 42 } } + ) + ).toEqual({ + foo: { + bar: 'Expected string, received array', + }, + }); + + expect( + prepareIssues( + z.discriminatedUnion('type', [ + z.object({ type: z.literal('foo') }), + z.object({ type: z.literal('bar') }), + ]), + { type: 'baz' } + ) + ).toEqual({ + type: "Invalid discriminator value. Expected 'foo' | 'bar'", + }); + + expect( + prepareIssues( + z.discriminatedUnion('type', [ + z.object({ type: z.literal('foo') }), + z.object({ type: z.literal('bar') }), + ]), + {} + ) + ).toEqual({ + type: "Invalid discriminator value. Expected 'foo' | 'bar'", + }); + + expect( + prepareIssues( + z.discriminatedUnion('type', [ + z.object({ type: z.literal('foo') }), + z.object({ type: z.literal('bar') }), + ]), + 42 + ) + ).toBe('Expected object, received number'); + }); + + it('prepareError', () => { + const err = getError( + z.object({ + foo: z.object({ + bar: z.object({ + baz: z.string(), + }), + }), + }), + { foo: { bar: { baz: 42 } } } + ); + + expect(prepareError(err!)).toEqual({ + issues: { + foo: { + bar: { + baz: 'Expected string, received number', + }, + }, + }, + message: 'Schema error', + stack: expect.stringMatching(/^ZodError: Schema error/), + }); + }); + }); }); diff --git a/lib/logger/utils.ts b/lib/logger/utils.ts index 4d0297cedb823b..84144229650e37 100644 --- a/lib/logger/utils.ts +++ b/lib/logger/utils.ts @@ -3,6 +3,7 @@ import is from '@sindresorhus/is'; import bunyan from 'bunyan'; import fs from 'fs-extra'; import { RequestError as HttpError } from 'got'; +import { ZodError } from 'zod'; import { redactedFields, sanitize } from '../util/sanitize'; import type { BunyanRecord, BunyanStream } from './types'; @@ -46,7 +47,74 @@ const contentFields = [ 'yarnLockParsed', ]; +type ZodShortenedIssue = + | null + | string + | string[] + | { + [key: string]: ZodShortenedIssue; + }; + +export function prepareZodIssues(input: unknown): ZodShortenedIssue { + // istanbul ignore if + if (!is.plainObject(input)) { + return null; + } + + let err: null | string | string[] = null; + if (is.array(input._errors, is.string)) { + // istanbul ignore else + if (input._errors.length === 1) { + err = input._errors[0]; + } else if (input._errors.length > 1) { + err = input._errors; + } else { + err = null; + } + } + delete input._errors; + + if (is.emptyObject(input)) { + return err; + } + + const output: Record = {}; + const entries = Object.entries(input); + for (const [key, value] of entries.slice(0, 3)) { + const child = prepareZodIssues(value); + if (child !== null) { + output[key] = child; + } + } + + if (entries.length > 3) { + output['___'] = `... ${entries.length - 3} more`; + } + + return output; +} + +export function prepareZodError(err: ZodError): Record { + // istanbul ignore next + Object.defineProperty(err, 'message', { + get: () => 'Schema error', + set: (_) => { + _; + }, + }); + + return { + message: err.message, + stack: err.stack, + issues: prepareZodIssues(err.format()), + }; +} + export default function prepareError(err: Error): Record { + if (err instanceof ZodError) { + return prepareZodError(err); + } + const response: Record = { ...err, }; From 63fa54c7607d7c92215978059af90e125d62601b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 May 2023 15:13:05 +0000 Subject: [PATCH 49/74] build(deps): update dependency @renovatebot/osv-offline to v1.2.8 (#22266) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index d3f55b20f24bbf..3c3ef1c2fb1dc6 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "@opentelemetry/sdk-trace-node": "1.12.0", "@opentelemetry/semantic-conventions": "1.12.0", "@qnighy/marshal": "0.1.3", - "@renovatebot/osv-offline": "1.2.7", + "@renovatebot/osv-offline": "1.2.8", "@renovatebot/pep440": "2.1.15", "@renovatebot/ruby-semver": "3.0.1", "@sindresorhus/is": "4.6.0", diff --git a/yarn.lock b/yarn.lock index f8181d5ce99ff3..32e90a16f69a32 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2501,10 +2501,10 @@ dependencies: "@seald-io/nedb" "^4.0.2" -"@renovatebot/osv-offline@1.2.7": - version "1.2.7" - resolved "https://registry.yarnpkg.com/@renovatebot/osv-offline/-/osv-offline-1.2.7.tgz#88e6d7cd29c51fd60587b39344604116dec019fb" - integrity sha512-1ibPY7iqEsVSnM5Z0G+vWTGj+haPYfYwBB8XgTPPcMYdeUYSYYrFK4cVXxuJxjQ6fWDA/boNhHjy1OEYE4IyZg== +"@renovatebot/osv-offline@1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@renovatebot/osv-offline/-/osv-offline-1.2.8.tgz#069cc078c414a5737bd963a39bc7d5cf196e2b7a" + integrity sha512-y0I1RQKUf0VI2XLuG8kr5j37NGxqOVcaFG9ozgwd9CGyGF1KMaaCOv6+MiQayeppcPNUGU6jBisI2XMQRneBmg== dependencies: "@octokit/rest" "^19.0.7" "@renovatebot/osv-offline-db" "1.4.0" @@ -2512,7 +2512,7 @@ fs-extra "^11.1.1" got "^11.8.6" luxon "^3.3.0" - node-fetch "^2.6.10" + node-fetch "^2.6.11" "@renovatebot/pep440@2.1.15": version "2.1.15" @@ -7940,7 +7940,7 @@ node-emoji@^1.11.0: dependencies: lodash "^4.17.21" -node-fetch@^2.6.10: +node-fetch@^2.6.11: version "2.6.11" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.11.tgz#cde7fc71deef3131ef80a738919f999e6edfff25" integrity sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w== From e1e5f7f7d09e5bb7f2be6861fa3a6f9855331db5 Mon Sep 17 00:00:00 2001 From: IKEDA Sho Date: Wed, 17 May 2023 00:31:42 +0900 Subject: [PATCH 50/74] fix(changelog): correct excactReleaseRegex (#22265) --- .../update/pr/changelog/github.spec.ts | 19 ++++++++++++++++++- .../update/pr/changelog/source-github.ts | 2 +- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/workers/repository/update/pr/changelog/github.spec.ts b/lib/workers/repository/update/pr/changelog/github.spec.ts index 8571c684606ae6..ee6fe19cee6109 100644 --- a/lib/workers/repository/update/pr/changelog/github.spec.ts +++ b/lib/workers/repository/update/pr/changelog/github.spec.ts @@ -366,6 +366,10 @@ describe('workers/repository/update/pr/changelog/github', () => { { version: '1.0.1' }, { version: 'correctPrefix/target@1.0.1' }, { version: 'wrongPrefix/target-1.0.1' }, + { version: 'v1.0.2' }, + { version: '1.0.2' }, + { version: 'correctPrefix/target-1.0.2' }, + { version: 'wrongPrefix/target@1.0.2' }, ]) ); @@ -376,9 +380,10 @@ describe('workers/repository/update/pr/changelog/github', () => { endpoint: 'https://api.github.com/', versioning: 'npm', currentVersion: '1.0.0', - newVersion: '1.0.1', + newVersion: '1.0.2', sourceUrl: 'https://github.com/chalk/chalk', releases: [ + { version: '1.0.2', gitRef: '789012' }, { version: '1.0.1', gitRef: '123456' }, { version: '0.1.1', gitRef: 'npm_1.0.0' }, ], @@ -398,6 +403,18 @@ describe('workers/repository/update/pr/changelog/github', () => { packageName: 'correctPrefix/target', }, versions: [ + { + version: '1.0.2', + date: undefined, + changes: [], + compare: { + url: 'https://github.com/chalk/chalk/compare/correctPrefix/target@1.0.1...correctPrefix/target-1.0.2', + }, + releaseNotes: { + url: 'https://github.com/chalk/chalk/compare/correctPrefix/target@1.0.1...correctPrefix/target-1.0.2', + notesSourceUrl: '', + }, + }, { version: '1.0.1', date: undefined, diff --git a/lib/workers/repository/update/pr/changelog/source-github.ts b/lib/workers/repository/update/pr/changelog/source-github.ts index 19ed0f561d3388..9b7bc2922b6668 100644 --- a/lib/workers/repository/update/pr/changelog/source-github.ts +++ b/lib/workers/repository/update/pr/changelog/source-github.ts @@ -195,7 +195,7 @@ function findTagOfRelease( tags: string[] ): string | undefined { const regex = regEx(`(?:${packageName}|release)[@-]`, undefined, false); - const excactReleaseRegex = regEx(`${packageName}[@-_]v?${depNewVersion}`); + const excactReleaseRegex = regEx(`${packageName}[@\\-_]v?${depNewVersion}`); const exactTagsList = tags.filter((tag) => { return excactReleaseRegex.test(tag); }); From 1c822181977c3bcd63e5b1f5715314580afceb22 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Tue, 16 May 2023 11:38:23 -0400 Subject: [PATCH 51/74] feat(vulnerabilities): handle medium and unknown severities (#22257) Co-authored-by: Jamie Magee --- lib/util/string.ts | 11 ++++++++ lib/util/template/index.ts | 2 +- lib/util/vulnerability/utils.spec.ts | 28 +++++++++++++++++++ lib/util/vulnerability/utils.ts | 2 ++ lib/workers/repository/process/types.ts | 2 +- .../process/vulnerabilities.spec.ts | 2 +- .../repository/process/vulnerabilities.ts | 22 +++++++-------- 7 files changed, 54 insertions(+), 15 deletions(-) diff --git a/lib/util/string.ts b/lib/util/string.ts index 4030956cdd923c..7a4d7d87608fb4 100644 --- a/lib/util/string.ts +++ b/lib/util/string.ts @@ -56,3 +56,14 @@ export function looseEquals( export function isDockerDigest(input: string): boolean { return /^sha256:[a-f0-9]{64}$/i.test(input); } + +export function titleCase(input: string): string { + const words = input.toLowerCase().split(' '); + + for (let i = 0; i < words.length; i++) { + const word = words[i]; + words[i] = word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); + } + + return words.join(' '); +} diff --git a/lib/util/template/index.ts b/lib/util/template/index.ts index da16eaa90f8cfd..5c3e1261e29a73 100644 --- a/lib/util/template/index.ts +++ b/lib/util/template/index.ts @@ -145,7 +145,7 @@ export const allowedFields = { versioning: 'The versioning scheme in use', versions: 'An array of ChangeLogRelease objects in the upgrade', vulnerabilitySeverity: - 'The severity for a vulnerability alert upgrade (eg: LOW, MODERATE, HIGH, CRITICAL)', + 'The severity for a vulnerability alert upgrade (LOW, MEDIUM, MODERATE, HIGH, CRITICAL, UNKNOWN)', }; const prBodyFields = [ diff --git a/lib/util/vulnerability/utils.spec.ts b/lib/util/vulnerability/utils.spec.ts index 0d9aa2ee34bae1..4ba086a5394d85 100644 --- a/lib/util/vulnerability/utils.spec.ts +++ b/lib/util/vulnerability/utils.spec.ts @@ -85,6 +85,20 @@ describe('util/vulnerability/utils', () => { expect(severity).toBe('MODERATE'); }); + it('child MEDIUM vulnerability severity rating is maintained', () => { + const parentConfig = { + vulnerabilitySeverity: 'LOW', + }; + + const childConfig = { + vulnerabilitySeverity: 'MEDIUM', + }; + + const severity = getHighestVulnerabilitySeverity(parentConfig, childConfig); + + expect(severity).toBe('MEDIUM'); + }); + it('parent LOW vulnerability severity rating is maintained', () => { const parentConfig = { vulnerabilitySeverity: 'LOW', @@ -113,6 +127,20 @@ describe('util/vulnerability/utils', () => { expect(severity).toBe('LOW'); }); + it('child UNKNOWN vulnerability severity rating is maintained', () => { + const parentConfig = { + vulnerabilitySeverity: 'CRITICAL', + }; + + const childConfig = { + vulnerabilitySeverity: 'UNKNOWN', + }; + + const severity = getHighestVulnerabilitySeverity(parentConfig, childConfig); + + expect(severity).toBe('UNKNOWN'); + }); + it('handled undefined parent and child vulnerability severity', () => { const parentConfig = { vulnerabilitySeverity: undefined, diff --git a/lib/util/vulnerability/utils.ts b/lib/util/vulnerability/utils.ts index 5607a6de9237b8..bc451a7db53658 100644 --- a/lib/util/vulnerability/utils.ts +++ b/lib/util/vulnerability/utils.ts @@ -1,8 +1,10 @@ const severityOrder: Record = { LOW: 1, + MEDIUM: 2, MODERATE: 2, HIGH: 3, CRITICAL: 4, + UNKNOWN: 5, }; export function getHighestVulnerabilitySeverity< diff --git a/lib/workers/repository/process/types.ts b/lib/workers/repository/process/types.ts index e59c569da1d8ab..c0de869e16ab17 100644 --- a/lib/workers/repository/process/types.ts +++ b/lib/workers/repository/process/types.ts @@ -21,5 +21,5 @@ export interface DependencyVulnerabilities { export interface SeverityDetails { cvssVector: string; score: string; - severityLevel?: string; + severityLevel: string; } diff --git a/lib/workers/repository/process/vulnerabilities.spec.ts b/lib/workers/repository/process/vulnerabilities.spec.ts index acfb0424435dba..eb63590dea7a21 100644 --- a/lib/workers/repository/process/vulnerabilities.spec.ts +++ b/lib/workers/repository/process/vulnerabilities.spec.ts @@ -944,7 +944,7 @@ describe('workers/repository/process/vulnerabilities', () => { No details. #### Severity - Unknown severity. + Unknown #### References No references. diff --git a/lib/workers/repository/process/vulnerabilities.ts b/lib/workers/repository/process/vulnerabilities.ts index 93483f716a0009..9ff98a803dfb6a 100644 --- a/lib/workers/repository/process/vulnerabilities.ts +++ b/lib/workers/repository/process/vulnerabilities.ts @@ -18,6 +18,7 @@ import { import { sanitizeMarkdown } from '../../../util/markdown'; import * as p from '../../../util/promises'; import { regEx } from '../../../util/regex'; +import { titleCase } from '../../../util/string'; import type { DependencyVulnerabilities, SeverityDetails, @@ -470,7 +471,7 @@ export class Vulnerabilities { matchCurrentVersion: depVersion, allowedVersions: fixedVersion, isVulnerabilityAlert: true, - vulnerabilitySeverity: severityDetails.severityLevel?.toUpperCase(), + vulnerabilitySeverity: severityDetails.severityLevel, prBodyNotes: this.generatePrBodyNotes(vulnerability, affected), force: { ...packageFileConfig.vulnerabilityAlerts, @@ -481,9 +482,7 @@ export class Vulnerabilities { private evaluateCvssVector(vector: string): [string, string] { try { const parsedCvss: CvssScore = parseCvssVector(vector); - const severityLevel = - parsedCvss.cvss3OverallSeverityText.charAt(0).toUpperCase() + - parsedCvss.cvss3OverallSeverityText.slice(1); + const severityLevel = parsedCvss.cvss3OverallSeverityText; return [parsedCvss.baseScore.toFixed(1), severityLevel]; } catch (err) { @@ -532,10 +531,8 @@ export class Vulnerabilities { if (severityDetails.cvssVector) { content += `- CVSS Score: ${severityDetails.score}\n`; content += `- Vector String: \`${severityDetails.cvssVector}\`\n`; - } else if (severityDetails.severityLevel) { - content += `${severityDetails.severityLevel}\n`; } else { - content += 'Unknown severity.\n'; + content += `${titleCase(severityDetails.severityLevel)}\n`; } content += `\n#### References\n${ @@ -566,7 +563,7 @@ export class Vulnerabilities { vulnerability: Osv.Vulnerability, affected: Osv.Affected ): SeverityDetails { - let severityLevel: string | undefined; + let severityLevel = 'UNKNOWN'; let score = 'Unknown'; const cvssVector = @@ -576,15 +573,16 @@ export class Vulnerabilities { if (cvssVector) { const [baseScore, severity] = this.evaluateCvssVector(cvssVector); - severityLevel = severity; - score = baseScore ? `${baseScore} / 10 (${severityLevel})` : 'Unknown'; + severityLevel = severity.toUpperCase(); + score = baseScore + ? `${baseScore} / 10 (${titleCase(severityLevel)})` + : 'Unknown'; } else if ( vulnerability.id.startsWith('GHSA-') && vulnerability.database_specific?.severity ) { const severity = vulnerability.database_specific.severity as string; - severityLevel = - severity.charAt(0).toUpperCase() + severity.slice(1).toLowerCase(); + severityLevel = severity.toUpperCase(); } return { From 90100df29bef260951e80f0c37eb9031a1f0cdb5 Mon Sep 17 00:00:00 2001 From: Ivan Josipovic <9521987+IvanJosipovic@users.noreply.github.com> Date: Tue, 16 May 2023 10:38:58 -0700 Subject: [PATCH 52/74] feat: add maui to monorepo:dotnet (#22269) --- lib/config/presets/internal/monorepo.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/config/presets/internal/monorepo.ts b/lib/config/presets/internal/monorepo.ts index 9b9767961eb07b..40c136d2fd828c 100644 --- a/lib/config/presets/internal/monorepo.ts +++ b/lib/config/presets/internal/monorepo.ts @@ -73,6 +73,7 @@ const repoGroups = { 'https://github.com/dotnet/aspnetcore', 'https://github.com/dotnet/efcore', 'https://github.com/dotnet/extensions', + 'https://github.com/dotnet/maui', 'https://github.com/dotnet/runtime', ], 'dotnet-azure-ad-identitymodel-extensions': From f2977e4f55197eeb173638173bd1cb4eb5eb528d Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Tue, 16 May 2023 19:49:22 +0200 Subject: [PATCH 53/74] fix(cache): include upgrade details in pr fingerprint (#22271) --- lib/workers/repository/update/pr/pr-fingerprint.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/workers/repository/update/pr/pr-fingerprint.ts b/lib/workers/repository/update/pr/pr-fingerprint.ts index ccc55276a2b539..5e71b179454af9 100644 --- a/lib/workers/repository/update/pr/pr-fingerprint.ts +++ b/lib/workers/repository/update/pr/pr-fingerprint.ts @@ -45,6 +45,9 @@ export function generatePrFingerprintConfig( const filteredUpgrades = config.upgrades.map((upgrade) => { return { depName: upgrade.depName, + displayFrom: upgrade.displayFrom, + displayTo: upgrade.displayTo, + displayPending: upgrade.displayPending, gitRef: upgrade.gitRef, hasReleaseNotes: upgrade.hasReleaseNotes, prBodyDefinitions: upgrade.prBodyDefinitions, From 3016a6cff9f4e6ca367bc41482102efb9646a280 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 17 May 2023 00:50:07 +0000 Subject: [PATCH 54/74] build(deps): update dependency glob to v10.2.3 (#22276) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 3c3ef1c2fb1dc6..70b8e4caed820d 100644 --- a/package.json +++ b/package.json @@ -196,7 +196,7 @@ "global-agent": "3.0.0", "good-enough-parser": "1.1.23", "got": "11.8.6", - "glob": "10.2.2", + "glob": "10.2.3", "graph-data-structure": "3.3.0", "handlebars": "4.7.7", "hasha": "5.2.2", diff --git a/yarn.lock b/yarn.lock index 32e90a16f69a32..86cdeec2054ffb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5638,7 +5638,18 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@10.2.2, glob@^10.0.0, glob@^10.2.2: +glob@10.2.3: + version "10.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.2.3.tgz#aa6765963fe6c5936d5c2e00943e7af06302a1a7" + integrity sha512-Kb4rfmBVE3eQTAimgmeqc2LwSnN0wIOkkUL6HmxEFxNJ4fHghYHVbFba/HcGcRjE6s9KoMNK3rSOwkL4PioZjg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^2.0.3" + minimatch "^9.0.0" + minipass "^5.0.0" + path-scurry "^1.7.0" + +glob@^10.0.0, glob@^10.2.2: version "10.2.2" resolved "https://registry.yarnpkg.com/glob/-/glob-10.2.2.tgz#ce2468727de7e035e8ecf684669dc74d0526ab75" integrity sha512-Xsa0BcxIC6th9UwNjZkhrMtNo/MnyRL8jGCP+uEwhA5oFOCY1f2s1/oNKY47xQ0Bg5nkjsfAEIej1VeH62bDDQ== From fd87414cb68fc322853f195cbb4167221f044408 Mon Sep 17 00:00:00 2001 From: Michael Kriese Date: Wed, 17 May 2023 05:53:45 +0200 Subject: [PATCH 55/74] chore: run label action on prs (#22227) --- .github/workflows/label-actions.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/label-actions.yml b/.github/workflows/label-actions.yml index fbdde3bb903832..e266ffa46be6e2 100644 --- a/.github/workflows/label-actions.yml +++ b/.github/workflows/label-actions.yml @@ -5,11 +5,14 @@ on: types: [labeled] discussion: types: [labeled] + pull_request_target: + types: [labeled] permissions: contents: read issues: write discussions: write + pull-requests: write jobs: reaction: @@ -18,4 +21,3 @@ jobs: - uses: dessant/label-actions@074b96a62f35c226ecb38e840f44941bde0343a6 # v3.0.0 with: github-token: ${{ github.token }} - process-only: 'issues, discussions' From 64b6e16763b210638730c3c304e9a923526e6d90 Mon Sep 17 00:00:00 2001 From: Liora Milbaum Date: Wed, 17 May 2023 10:05:35 +0200 Subject: [PATCH 56/74] refactor(gitpod): dropping gitpod (#22274) --- .gitpod.yml | 7 --- docs/development/remote-development.md | 72 +------------------------- 2 files changed, 1 insertion(+), 78 deletions(-) delete mode 100644 .gitpod.yml diff --git a/.gitpod.yml b/.gitpod.yml deleted file mode 100644 index 7c7efce0d8beca..00000000000000 --- a/.gitpod.yml +++ /dev/null @@ -1,7 +0,0 @@ -tasks: - - init: > - nvm install 18 && - nvm use 18 && - yarn install && - yarn run build - command: yarn run start diff --git a/docs/development/remote-development.md b/docs/development/remote-development.md index 24d2ba815b0577..d3f6c4ca0f3683 100644 --- a/docs/development/remote-development.md +++ b/docs/development/remote-development.md @@ -29,77 +29,7 @@ You'll use the same code editor and have the same config as all other developers - Waiting for the remote container to start - If your internet is down you can't work -- If Gitpod or Codespaces is down you can't work - -## Gitpod - -You can use [Gitpod](https://gitpod.io/) for light development work like: - -- Editing the docs -- Running ESLint, Prettier - -For proper development, use GitHub Codespaces. - -The config file for Gitpod is `.gitpod.yml` in the root of the repository. - -Gitpod gives you 500 free credits each month, which is enough for about 50 hours of work. - -### Gitpod tips - -- Use `yarn jest` to run the tests on Gitpod - -### Known problems with Gitpod - -There are two failing tests when running `yarn jest` on Gitpod: - -```bash -Summary of all failing tests - FAIL lib/util/git/index.spec.ts (635.102 s, 319 MB heap size) - ● util/git/index › isBranchModified() › should return false when author matches - - expected true to be false or Boolean(false) - - 283 | - 284 | it('should return false when author matches', async () => { - > 285 | expect(await git.isBranchModified('renovate/future_branch')).toBeFalse(); - | ^ - 286 | expect(await git.isBranchModified('renovate/future_branch')).toBeFalse(); - 287 | }); - 288 | - - at Object. (lib/util/git/index.spec.ts:285:68) - - ● util/git/index › isBranchModified() › should return false when author is ignored - - expected true to be false or Boolean(false) - - 291 | gitIgnoredAuthors: ['custom@example.com'], - 292 | }); - > 293 | expect(await git.isBranchModified('renovate/custom_author')).toBeFalse(); - | ^ - 294 | }); - 295 | - 296 | it('should return true when custom author is unknown', async () => { - - at Object. (lib/util/git/index.spec.ts:293:68) - - FAIL test/static-files.spec.ts (14.506 s, 288 MB heap size) - ● static-files › has same static files in lib and dist - - thrown: "Exceeded timeout of 10000 ms for a test. - Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test." - - 36 | jest.setTimeout(10 * 1000); - 37 | - > 38 | it('has same static files in lib and dist', async () => { - | ^ - 39 | expect(await getFiles('dist')).toEqual(await getFiles('lib')); - 40 | }); - 41 | }); - - at test/static-files.spec.ts:38:3 - at Object. (test/static-files.spec.ts:34:1) -``` +- If Codespaces is down you can't work ## GitHub Codespaces From cd5abc87b805cde887121e5da18db42f3217e6e4 Mon Sep 17 00:00:00 2001 From: Sergei Zharinov Date: Wed, 17 May 2023 11:12:20 +0300 Subject: [PATCH 57/74] refactor(rubygems): Use schema for fallback API (#21933) --- .../rubygems/__fixtures__/rails/info.json | 2 +- .../rubygems/__snapshots__/index.spec.ts.snap | 2375 +---------------- lib/modules/datasource/rubygems/get.ts | 291 +- lib/modules/datasource/rubygems/index.spec.ts | 8 +- lib/modules/datasource/rubygems/types.ts | 44 - lib/util/http/index.ts | 17 +- 6 files changed, 171 insertions(+), 2566 deletions(-) delete mode 100644 lib/modules/datasource/rubygems/types.ts diff --git a/lib/modules/datasource/rubygems/__fixtures__/rails/info.json b/lib/modules/datasource/rubygems/__fixtures__/rails/info.json index 844ef31bf05509..40b11b0cd0d43c 100644 --- a/lib/modules/datasource/rubygems/__fixtures__/rails/info.json +++ b/lib/modules/datasource/rubygems/__fixtures__/rails/info.json @@ -1 +1 @@ -{"name":"rails","downloads":156058530,"version":"5.2.2","version_downloads":385084,"platform":"ruby","authors":"David Heinemeier Hansson","info":"Ruby on Rails is a full-stack web framework optimized for programmer happiness and sustainable productivity. It encourages beautiful code by favoring convention over configuration.","licenses":["MIT"],"metadata":{},"sha":"d9ff5d9be16ee277dfc8f3c760bf171aa497d8685ec5c8988fba21a3dbd72cd5","project_uri":"https://rubygems.org/gems/rails","gem_uri":"https://rubygems.org/gems/rails-5.2.2.gem","homepage_uri":"http://rubyonrails.org","wiki_uri":"","documentation_uri":"http://api.rubyonrails.org","mailing_list_uri":"http://groups.google.com/group/rubyonrails-talk","source_code_uri":"http://github.com/rails/rails","bug_tracker_uri":"http://github.com/rails/rails/issues","changelog_uri":null,"dependencies":{"development":[],"runtime":[{"name":"actioncable","requirements":"= 5.2.2"},{"name":"actionmailer","requirements":"= 5.2.2"},{"name":"actionpack","requirements":"= 5.2.2"},{"name":"actionview","requirements":"= 5.2.2"},{"name":"activejob","requirements":"= 5.2.2"},{"name":"activemodel","requirements":"= 5.2.2"},{"name":"activerecord","requirements":"= 5.2.2"},{"name":"activestorage","requirements":"= 5.2.2"},{"name":"activesupport","requirements":"= 5.2.2"},{"name":"bundler","requirements":"\u003e= 1.3.0"},{"name":"railties","requirements":"= 5.2.2"},{"name":"sprockets-rails","requirements":"\u003e= 2.0.0"}]}} +{"name":"rails","downloads":156058530,"version":"5.2.2","version_downloads":385084,"platform":"ruby","authors":"David Heinemeier Hansson","info":"Ruby on Rails is a full-stack web framework optimized for programmer happiness and sustainable productivity. It encourages beautiful code by favoring convention over configuration.","licenses":["MIT"],"metadata":{},"sha":"d9ff5d9be16ee277dfc8f3c760bf171aa497d8685ec5c8988fba21a3dbd72cd5","project_uri":"https://rubygems.org/gems/rails","gem_uri":"https://rubygems.org/gems/rails-5.2.2.gem","homepage_uri":"http://rubyonrails.org","wiki_uri":"","documentation_uri":"http://api.rubyonrails.org","mailing_list_uri":"http://groups.google.com/group/rubyonrails-talk","source_code_uri":"http://github.com/rails/rails","bug_tracker_uri":"http://github.com/rails/rails/issues","changelog_uri":"https://www.railschangelog.com/","dependencies":{"development":[],"runtime":[{"name":"actioncable","requirements":"= 5.2.2"},{"name":"actionmailer","requirements":"= 5.2.2"},{"name":"actionpack","requirements":"= 5.2.2"},{"name":"actionview","requirements":"= 5.2.2"},{"name":"activejob","requirements":"= 5.2.2"},{"name":"activemodel","requirements":"= 5.2.2"},{"name":"activerecord","requirements":"= 5.2.2"},{"name":"activestorage","requirements":"= 5.2.2"},{"name":"activesupport","requirements":"= 5.2.2"},{"name":"bundler","requirements":"\u003e= 1.3.0"},{"name":"railties","requirements":"= 5.2.2"},{"name":"sprockets-rails","requirements":"\u003e= 2.0.0"}]}} diff --git a/lib/modules/datasource/rubygems/__snapshots__/index.spec.ts.snap b/lib/modules/datasource/rubygems/__snapshots__/index.spec.ts.snap index 2233e2de00dcf0..523f011b849207 100644 --- a/lib/modules/datasource/rubygems/__snapshots__/index.spec.ts.snap +++ b/lib/modules/datasource/rubygems/__snapshots__/index.spec.ts.snap @@ -5,1359 +5,1020 @@ exports[`modules/datasource/rubygems/index getReleases returns a dep for GitHub "registryUrl": "https://rubygems.pkg.github.com/example", "releases": [ { - "rubyPlatform": "ruby", "version": "0.8.0", }, { - "rubyPlatform": "ruby", "version": "0.8.5", }, { - "rubyPlatform": "ruby", "version": "0.9.0", }, { - "rubyPlatform": "ruby", "version": "0.9.1", }, { - "rubyPlatform": "ruby", "version": "0.9.2", }, { - "rubyPlatform": "ruby", "version": "0.9.3", }, { - "rubyPlatform": "ruby", "version": "0.9.4", }, { - "rubyPlatform": "ruby", "version": "0.9.4.1", }, { - "rubyPlatform": "ruby", "version": "0.9.5", }, { - "rubyPlatform": "ruby", "version": "0.10.0", }, { - "rubyPlatform": "ruby", "version": "0.10.1", }, { - "rubyPlatform": "ruby", "version": "0.11.0", }, { - "rubyPlatform": "ruby", "version": "0.11.1", }, { - "rubyPlatform": "ruby", "version": "0.12.0", }, { - "rubyPlatform": "ruby", "version": "0.12.1", }, { - "rubyPlatform": "ruby", "version": "0.13.0", }, { - "rubyPlatform": "ruby", "version": "0.13.1", }, { - "rubyPlatform": "ruby", "version": "0.14.1", }, { - "rubyPlatform": "ruby", "version": "0.14.2", }, { - "rubyPlatform": "ruby", "version": "0.14.3", }, { - "rubyPlatform": "ruby", "version": "0.14.4", }, { - "rubyPlatform": "ruby", "version": "1.0.0", }, { - "rubyPlatform": "ruby", "version": "1.1.0", }, { - "rubyPlatform": "ruby", "version": "1.1.1", }, { - "rubyPlatform": "ruby", "version": "1.1.2", }, { - "rubyPlatform": "ruby", "version": "1.1.3", }, { - "rubyPlatform": "ruby", "version": "1.1.4", }, { - "rubyPlatform": "ruby", "version": "1.1.5", }, { - "rubyPlatform": "ruby", "version": "1.1.6", }, { - "rubyPlatform": "ruby", "version": "1.2.0", }, { - "rubyPlatform": "ruby", "version": "1.2.1", }, { - "rubyPlatform": "ruby", "version": "1.2.2", }, { - "rubyPlatform": "ruby", "version": "1.2.3", }, { - "rubyPlatform": "ruby", "version": "1.2.4", }, { - "rubyPlatform": "ruby", "version": "1.2.5", }, { - "rubyPlatform": "ruby", "version": "1.2.6", }, { - "rubyPlatform": "ruby", "version": "2.0.0", }, { - "rubyPlatform": "ruby", "version": "2.0.1", }, { - "rubyPlatform": "ruby", "version": "2.0.2", }, { - "rubyPlatform": "ruby", "version": "2.0.4", }, { - "rubyPlatform": "ruby", "version": "2.0.5", }, { - "rubyPlatform": "ruby", "version": "2.1.0", }, { - "rubyPlatform": "ruby", "version": "2.1.1", }, { - "rubyPlatform": "ruby", "version": "2.1.2", }, { - "rubyPlatform": "ruby", "version": "2.2.2", }, { - "rubyPlatform": "ruby", "version": "2.2.3", }, { - "rubyPlatform": "ruby", "version": "2.3.2", }, { - "rubyPlatform": "ruby", "version": "2.3.3", }, { - "rubyPlatform": "ruby", "version": "2.3.4", }, { - "rubyPlatform": "ruby", "version": "2.3.5", }, { - "rubyPlatform": "ruby", "version": "2.3.6", }, { - "rubyPlatform": "ruby", "version": "2.3.7", }, { - "rubyPlatform": "ruby", "version": "2.3.8.pre1", }, { - "rubyPlatform": "ruby", "version": "2.3.8", }, { - "rubyPlatform": "ruby", "version": "2.3.9.pre", }, { - "rubyPlatform": "ruby", "version": "2.3.9", }, { - "rubyPlatform": "ruby", "version": "2.3.10", }, { - "rubyPlatform": "ruby", "version": "2.3.11", }, { - "rubyPlatform": "ruby", "version": "2.3.12", }, { - "rubyPlatform": "ruby", "version": "2.3.14", }, { - "rubyPlatform": "ruby", "version": "2.3.15", }, { - "rubyPlatform": "ruby", "version": "2.3.16", }, { - "rubyPlatform": "ruby", "version": "2.3.17", }, { - "rubyPlatform": "ruby", "version": "2.3.18", }, { - "rubyPlatform": "ruby", "version": "3.0.0.beta", }, { - "rubyPlatform": "ruby", "version": "3.0.0.beta2", }, { - "rubyPlatform": "ruby", "version": "3.0.0.beta3", }, { - "rubyPlatform": "ruby", "version": "3.0.0.beta4", }, { - "rubyPlatform": "ruby", "version": "3.0.0.rc", }, { - "rubyPlatform": "ruby", "version": "3.0.0.rc2", }, { - "rubyPlatform": "ruby", "version": "3.0.0", }, { - "rubyPlatform": "ruby", "version": "3.0.1", }, { - "rubyPlatform": "ruby", "version": "3.0.2", }, { - "rubyPlatform": "ruby", "version": "3.0.3", }, { - "rubyPlatform": "ruby", "version": "3.0.4.rc1", }, { - "rubyPlatform": "ruby", "version": "3.0.4", }, { - "rubyPlatform": "ruby", "version": "3.0.5.rc1", }, { - "rubyPlatform": "ruby", "version": "3.0.5", }, { - "rubyPlatform": "ruby", "version": "3.0.6.rc1", }, { - "rubyPlatform": "ruby", "version": "3.0.6.rc2", }, { - "rubyPlatform": "ruby", "version": "3.0.6", }, { - "rubyPlatform": "ruby", "version": "3.0.7.rc1", }, { - "rubyPlatform": "ruby", "version": "3.0.7.rc2", }, { - "rubyPlatform": "ruby", "version": "3.0.7", }, { - "rubyPlatform": "ruby", "version": "3.0.8.rc1", }, { - "rubyPlatform": "ruby", "version": "3.0.8.rc2", }, { - "rubyPlatform": "ruby", "version": "3.0.8.rc4", }, { - "rubyPlatform": "ruby", "version": "3.0.8", }, { - "rubyPlatform": "ruby", "version": "3.0.9.rc1", }, { - "rubyPlatform": "ruby", "version": "3.0.9.rc3", }, { - "rubyPlatform": "ruby", "version": "3.0.9.rc4", }, { - "rubyPlatform": "ruby", "version": "3.0.9.rc5", }, { - "rubyPlatform": "ruby", "version": "3.0.9", }, { - "rubyPlatform": "ruby", "version": "3.0.10.rc1", }, { - "rubyPlatform": "ruby", "version": "3.0.10", }, { - "rubyPlatform": "ruby", "version": "3.0.11", }, { - "rubyPlatform": "ruby", "version": "3.0.12.rc1", }, { - "rubyPlatform": "ruby", "version": "3.0.12", }, { - "rubyPlatform": "ruby", "version": "3.0.13.rc1", }, { - "rubyPlatform": "ruby", "version": "3.0.13", }, { - "rubyPlatform": "ruby", "version": "3.0.14", }, { - "rubyPlatform": "ruby", "version": "3.0.15", }, { - "rubyPlatform": "ruby", "version": "3.0.16", }, { - "rubyPlatform": "ruby", "version": "3.0.17", }, { - "rubyPlatform": "ruby", "version": "3.0.18", }, { - "rubyPlatform": "ruby", "version": "3.0.19", }, { - "rubyPlatform": "ruby", "version": "3.0.20", }, { - "rubyPlatform": "ruby", "version": "3.1.0.beta1", }, { - "rubyPlatform": "ruby", "version": "3.1.0.rc1", }, { - "rubyPlatform": "ruby", "version": "3.1.0.rc2", }, { - "rubyPlatform": "ruby", "version": "3.1.0.rc3", }, { - "rubyPlatform": "ruby", "version": "3.1.0.rc4", }, { - "rubyPlatform": "ruby", "version": "3.1.0.rc5", }, { - "rubyPlatform": "ruby", "version": "3.1.0.rc6", }, { - "rubyPlatform": "ruby", "version": "3.1.0.rc8", }, { - "rubyPlatform": "ruby", "version": "3.1.0", }, { - "rubyPlatform": "ruby", "version": "3.1.1.rc1", }, { - "rubyPlatform": "ruby", "version": "3.1.1.rc2", }, { - "rubyPlatform": "ruby", "version": "3.1.1.rc3", }, { - "rubyPlatform": "ruby", "version": "3.1.1", }, { - "rubyPlatform": "ruby", "version": "3.1.2.rc1", }, { - "rubyPlatform": "ruby", "version": "3.1.2.rc2", }, { - "rubyPlatform": "ruby", "version": "3.1.2", }, { - "rubyPlatform": "ruby", "version": "3.1.3", }, { - "rubyPlatform": "ruby", "version": "3.1.4.rc1", }, { - "rubyPlatform": "ruby", "version": "3.1.4", }, { - "rubyPlatform": "ruby", "version": "3.1.5.rc1", }, { - "rubyPlatform": "ruby", "version": "3.1.5", }, { - "rubyPlatform": "ruby", "version": "3.1.6", }, { - "rubyPlatform": "ruby", "version": "3.1.7", }, { - "rubyPlatform": "ruby", "version": "3.1.8", }, { - "rubyPlatform": "ruby", "version": "3.1.9", }, { - "rubyPlatform": "ruby", "version": "3.1.10", }, { - "rubyPlatform": "ruby", "version": "3.1.11", }, { - "rubyPlatform": "ruby", "version": "3.1.12", }, { - "rubyPlatform": "ruby", "version": "3.2.0.rc1", }, { - "rubyPlatform": "ruby", "version": "3.2.0.rc2", }, { - "rubyPlatform": "ruby", "version": "3.2.0", }, { - "rubyPlatform": "ruby", "version": "3.2.1", }, { - "rubyPlatform": "ruby", "version": "3.2.2.rc1", }, { - "rubyPlatform": "ruby", "version": "3.2.2", }, { - "rubyPlatform": "ruby", "version": "3.2.3.rc1", }, { - "rubyPlatform": "ruby", "version": "3.2.3.rc2", }, { - "rubyPlatform": "ruby", "version": "3.2.3", }, { - "rubyPlatform": "ruby", "version": "3.2.4.rc1", }, { - "rubyPlatform": "ruby", "version": "3.2.4", }, { - "rubyPlatform": "ruby", "version": "3.2.5", }, { - "rubyPlatform": "ruby", "version": "3.2.6", }, { - "rubyPlatform": "ruby", "version": "3.2.7.rc1", }, { - "rubyPlatform": "ruby", "version": "3.2.7", }, { - "rubyPlatform": "ruby", "version": "3.2.8.rc1", }, { - "rubyPlatform": "ruby", "version": "3.2.8.rc2", }, { - "rubyPlatform": "ruby", "version": "3.2.8", }, { - "rubyPlatform": "ruby", "version": "3.2.9.rc1", }, { - "rubyPlatform": "ruby", "version": "3.2.9.rc2", }, { - "rubyPlatform": "ruby", "version": "3.2.9.rc3", }, { - "rubyPlatform": "ruby", "version": "3.2.9", }, { - "rubyPlatform": "ruby", "version": "3.2.10", }, { - "rubyPlatform": "ruby", "version": "3.2.11", }, { - "rubyPlatform": "ruby", "version": "3.2.12", }, { - "rubyPlatform": "ruby", "version": "3.2.13.rc1", }, { - "rubyPlatform": "ruby", "version": "3.2.13.rc2", }, { - "rubyPlatform": "ruby", "version": "3.2.13", }, { - "rubyPlatform": "ruby", "version": "3.2.14.rc1", }, { - "rubyPlatform": "ruby", "version": "3.2.14.rc2", }, { - "rubyPlatform": "ruby", "version": "3.2.14", }, { - "rubyPlatform": "ruby", "version": "3.2.15.rc1", }, { - "rubyPlatform": "ruby", "version": "3.2.15.rc2", }, { - "rubyPlatform": "ruby", "version": "3.2.15.rc3", }, { - "rubyPlatform": "ruby", "version": "3.2.15", }, { - "rubyPlatform": "ruby", "version": "3.2.16", }, { - "rubyPlatform": "ruby", "version": "3.2.17", }, { - "rubyPlatform": "ruby", "version": "3.2.18", }, { - "rubyPlatform": "ruby", "version": "3.2.19", }, { - "rubyPlatform": "ruby", "version": "3.2.20", }, { - "rubyPlatform": "ruby", "version": "3.2.21", }, { - "rubyPlatform": "ruby", "version": "3.2.22", }, { - "rubyPlatform": "ruby", "version": "3.2.22.1", }, { - "rubyPlatform": "ruby", "version": "3.2.22.2", }, { - "rubyPlatform": "ruby", "version": "3.2.22.3", }, { - "rubyPlatform": "ruby", "version": "3.2.22.4", }, { - "rubyPlatform": "ruby", "version": "3.2.22.5", }, { - "rubyPlatform": "ruby", "version": "4.0.0.beta1", }, { - "rubyPlatform": "ruby", "version": "4.0.0.rc1", }, { - "rubyPlatform": "ruby", "version": "4.0.0.rc2", }, { - "rubyPlatform": "ruby", "version": "4.0.0", }, { - "rubyPlatform": "ruby", "version": "4.0.1.rc1", }, { - "rubyPlatform": "ruby", "version": "4.0.1.rc2", }, { - "rubyPlatform": "ruby", "version": "4.0.1.rc3", }, { - "rubyPlatform": "ruby", "version": "4.0.1.rc4", }, { - "rubyPlatform": "ruby", "version": "4.0.1", }, { - "rubyPlatform": "ruby", "version": "4.0.2", }, { - "rubyPlatform": "ruby", "version": "4.0.3", }, { - "rubyPlatform": "ruby", "version": "4.0.4.rc1", }, { - "rubyPlatform": "ruby", "version": "4.0.4", }, { - "rubyPlatform": "ruby", "version": "4.0.5", }, { - "rubyPlatform": "ruby", "version": "4.0.6.rc1", }, { - "rubyPlatform": "ruby", "version": "4.0.6.rc2", }, { - "rubyPlatform": "ruby", "version": "4.0.6.rc3", }, { - "rubyPlatform": "ruby", "version": "4.0.6", }, { - "rubyPlatform": "ruby", "version": "4.0.7", }, { - "rubyPlatform": "ruby", "version": "4.0.8", }, { - "rubyPlatform": "ruby", "version": "4.0.9", }, { - "rubyPlatform": "ruby", "version": "4.0.10.rc1", }, { - "rubyPlatform": "ruby", "version": "4.0.10.rc2", }, { - "rubyPlatform": "ruby", "version": "4.0.10", }, { - "rubyPlatform": "ruby", "version": "4.0.11", }, { - "rubyPlatform": "ruby", "version": "4.0.11.1", }, { - "rubyPlatform": "ruby", "version": "4.0.12", }, { - "rubyPlatform": "ruby", "version": "4.0.13.rc1", }, { - "rubyPlatform": "ruby", "version": "4.0.13", }, { - "rubyPlatform": "ruby", "version": "4.1.0.beta1", }, { - "rubyPlatform": "ruby", "version": "4.1.0.beta2", }, { - "rubyPlatform": "ruby", "version": "4.1.0.rc1", }, { - "rubyPlatform": "ruby", "version": "4.1.0.rc2", }, { - "rubyPlatform": "ruby", "version": "4.1.0", }, { - "rubyPlatform": "ruby", "version": "4.1.1", }, { - "rubyPlatform": "ruby", "version": "4.1.2.rc1", }, { - "rubyPlatform": "ruby", "version": "4.1.2.rc2", }, { - "rubyPlatform": "ruby", "version": "4.1.2.rc3", }, { - "rubyPlatform": "ruby", "version": "4.1.2", }, { - "rubyPlatform": "ruby", "version": "4.1.3", }, { - "rubyPlatform": "ruby", "version": "4.1.4", }, { - "rubyPlatform": "ruby", "version": "4.1.5", }, { - "rubyPlatform": "ruby", "version": "4.1.6.rc1", }, { - "rubyPlatform": "ruby", "version": "4.1.6.rc2", }, { - "rubyPlatform": "ruby", "version": "4.1.6", }, { - "rubyPlatform": "ruby", "version": "4.1.7", }, { - "rubyPlatform": "ruby", "version": "4.1.7.1", }, { - "rubyPlatform": "ruby", "version": "4.1.8", }, { - "rubyPlatform": "ruby", "version": "4.1.9.rc1", }, { - "rubyPlatform": "ruby", "version": "4.1.9", }, { - "rubyPlatform": "ruby", "version": "4.1.10.rc1", }, { - "rubyPlatform": "ruby", "version": "4.1.10.rc2", }, { - "rubyPlatform": "ruby", "version": "4.1.10.rc3", }, { - "rubyPlatform": "ruby", "version": "4.1.10.rc4", }, { - "rubyPlatform": "ruby", "version": "4.1.10", }, { - "rubyPlatform": "ruby", "version": "4.1.11", }, { - "rubyPlatform": "ruby", "version": "4.1.12.rc1", }, { - "rubyPlatform": "ruby", "version": "4.1.12", }, { - "rubyPlatform": "ruby", "version": "4.1.13.rc1", }, { - "rubyPlatform": "ruby", "version": "4.1.13", }, { - "rubyPlatform": "ruby", "version": "4.1.14.rc1", }, { - "rubyPlatform": "ruby", "version": "4.1.14.rc2", }, { - "rubyPlatform": "ruby", "version": "4.1.14", }, { - "rubyPlatform": "ruby", "version": "4.1.14.1", }, { - "rubyPlatform": "ruby", "version": "4.1.14.2", }, { - "rubyPlatform": "ruby", "version": "4.1.15.rc1", }, { - "rubyPlatform": "ruby", "version": "4.1.15", }, { - "rubyPlatform": "ruby", "version": "4.1.16.rc1", }, { - "rubyPlatform": "ruby", "version": "4.1.16", }, { - "rubyPlatform": "ruby", "version": "4.2.0.beta1", }, { - "rubyPlatform": "ruby", "version": "4.2.0.beta2", }, { - "rubyPlatform": "ruby", "version": "4.2.0.beta3", }, { - "rubyPlatform": "ruby", "version": "4.2.0.beta4", }, { - "rubyPlatform": "ruby", "version": "4.2.0.rc1", }, { - "rubyPlatform": "ruby", "version": "4.2.0.rc2", }, { - "rubyPlatform": "ruby", "version": "4.2.0.rc3", }, { - "rubyPlatform": "ruby", "version": "4.2.0", }, { - "rubyPlatform": "ruby", "version": "4.2.1.rc1", }, { - "rubyPlatform": "ruby", "version": "4.2.1.rc2", }, { - "rubyPlatform": "ruby", "version": "4.2.1.rc3", }, { - "rubyPlatform": "ruby", "version": "4.2.1.rc4", }, { - "rubyPlatform": "ruby", "version": "4.2.1", }, { - "rubyPlatform": "ruby", "version": "4.2.2", }, { - "rubyPlatform": "ruby", "version": "4.2.3.rc1", }, { - "rubyPlatform": "ruby", "version": "4.2.3", }, { - "rubyPlatform": "ruby", "version": "4.2.4.rc1", }, { - "rubyPlatform": "ruby", "version": "4.2.4", }, { - "rubyPlatform": "ruby", "version": "4.2.5.rc1", }, { - "rubyPlatform": "ruby", "version": "4.2.5.rc2", }, { - "rubyPlatform": "ruby", "version": "4.2.5", }, { - "rubyPlatform": "ruby", "version": "4.2.5.1", }, { - "rubyPlatform": "ruby", "version": "4.2.5.2", }, { - "rubyPlatform": "ruby", "version": "4.2.6.rc1", }, { - "rubyPlatform": "ruby", "version": "4.2.6", }, { - "rubyPlatform": "ruby", "version": "4.2.7.rc1", }, { - "rubyPlatform": "ruby", "version": "4.2.7", }, { - "rubyPlatform": "ruby", "version": "4.2.7.1", }, { - "rubyPlatform": "ruby", "version": "4.2.8.rc1", }, { - "rubyPlatform": "ruby", "version": "4.2.8", }, { - "rubyPlatform": "ruby", "version": "4.2.9.rc1", }, { - "rubyPlatform": "ruby", "version": "4.2.9.rc2", }, { - "rubyPlatform": "ruby", "version": "4.2.9", }, { - "rubyPlatform": "ruby", "version": "4.2.10.rc1", }, { - "rubyPlatform": "ruby", "version": "4.2.10", }, { - "rubyPlatform": "ruby", "version": "4.2.11", }, { - "rubyPlatform": "ruby", "version": "5.0.0.beta1", }, { - "rubyPlatform": "ruby", "version": "5.0.0.beta1.1", }, { - "rubyPlatform": "ruby", "version": "5.0.0.beta2", }, { - "rubyPlatform": "ruby", "version": "5.0.0.beta3", }, { - "rubyPlatform": "ruby", "version": "5.0.0.beta4", }, { - "rubyPlatform": "ruby", "version": "5.0.0.racecar1", }, { - "rubyPlatform": "ruby", "version": "5.0.0.rc1", }, { - "rubyPlatform": "ruby", "version": "5.0.0.rc2", }, { - "rubyPlatform": "ruby", "version": "5.0.0", }, { - "rubyPlatform": "ruby", "version": "5.0.0.1", }, { - "rubyPlatform": "ruby", "version": "5.0.1.rc1", }, { - "rubyPlatform": "ruby", "version": "5.0.1.rc2", }, { - "rubyPlatform": "ruby", "version": "5.0.1", }, { - "rubyPlatform": "ruby", "version": "5.0.2.rc1", }, { - "rubyPlatform": "ruby", "version": "5.0.2", }, { - "rubyPlatform": "ruby", "version": "5.0.3", }, { - "rubyPlatform": "ruby", "version": "5.0.4.rc1", }, { - "rubyPlatform": "ruby", "version": "5.0.4", }, { - "rubyPlatform": "ruby", "version": "5.0.5.rc1", }, { - "rubyPlatform": "ruby", "version": "5.0.5.rc2", }, { - "rubyPlatform": "ruby", "version": "5.0.5", }, { - "rubyPlatform": "ruby", "version": "5.0.6.rc1", }, { - "rubyPlatform": "ruby", "version": "5.0.6", }, { - "rubyPlatform": "ruby", "version": "5.0.7", }, { - "rubyPlatform": "ruby", "version": "5.0.7.1", }, { - "rubyPlatform": "ruby", "version": "5.1.0.beta1", }, { - "rubyPlatform": "ruby", "version": "5.1.0.rc1", }, { - "rubyPlatform": "ruby", "version": "5.1.0.rc2", }, { - "rubyPlatform": "ruby", "version": "5.1.0", }, { - "rubyPlatform": "ruby", "version": "5.1.1", }, { - "rubyPlatform": "ruby", "version": "5.1.2.rc1", }, { - "rubyPlatform": "ruby", "version": "5.1.2", }, { - "rubyPlatform": "ruby", "version": "5.1.3.rc1", }, { - "rubyPlatform": "ruby", "version": "5.1.3.rc2", }, { - "rubyPlatform": "ruby", "version": "5.1.3.rc3", }, { - "rubyPlatform": "ruby", "version": "5.1.3", }, { - "rubyPlatform": "ruby", "version": "5.1.4.rc1", }, { - "rubyPlatform": "ruby", "version": "5.1.4", }, { - "rubyPlatform": "ruby", "version": "5.1.5.rc1", }, { - "rubyPlatform": "ruby", "version": "5.1.5", }, { - "rubyPlatform": "ruby", "version": "5.1.6", }, { - "rubyPlatform": "ruby", "version": "5.1.6.1", }, { - "rubyPlatform": "ruby", "version": "5.2.0.beta1", }, { - "rubyPlatform": "ruby", "version": "5.2.0.beta2", }, { - "rubyPlatform": "ruby", "version": "5.2.0.rc1", }, { - "rubyPlatform": "ruby", "version": "5.2.0.rc2", }, { - "rubyPlatform": "ruby", "version": "5.2.0", }, { - "rubyPlatform": "ruby", "version": "5.2.1.rc1", }, { - "rubyPlatform": "ruby", "version": "5.2.1", }, { - "rubyPlatform": "ruby", "version": "5.2.1.1", }, { - "rubyPlatform": "ruby", "version": "5.2.2.rc1", }, { - "rubyPlatform": "ruby", "version": "5.2.2", }, ], @@ -1380,2380 +1041,1364 @@ exports[`modules/datasource/rubygems/index getReleases returns a dep for rubygem exports[`modules/datasource/rubygems/index getReleases uses multiple source urls 1`] = ` { + "changelogUrl": "https://www.railschangelog.com/", "homepage": "http://rubyonrails.org", "registryUrl": "https://firstparty.com/basepath", "releases": [ { "releaseTimestamp": "2009-07-25T18:01:56.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.8.0", }, { "releaseTimestamp": "2009-07-25T18:01:56.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.8.5", }, { "releaseTimestamp": "2009-07-25T18:01:56.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.9.0", }, { "releaseTimestamp": "2009-07-25T18:01:56.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.9.1", }, { "releaseTimestamp": "2009-07-25T18:01:56.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.9.2", }, { "releaseTimestamp": "2009-07-25T18:01:55.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.9.3", }, { "releaseTimestamp": "2009-07-25T18:01:55.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.9.4", }, { "releaseTimestamp": "2009-07-25T18:01:55.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.9.4.1", }, { "releaseTimestamp": "2009-07-25T18:01:55.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.9.5", }, { "releaseTimestamp": "2009-07-25T18:01:58.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.10.0", }, { "releaseTimestamp": "2009-07-25T18:01:58.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.10.1", }, { "releaseTimestamp": "2009-07-25T18:01:58.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.11.0", }, { "releaseTimestamp": "2009-07-25T18:01:58.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.11.1", }, { "releaseTimestamp": "2009-07-25T18:01:58.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.12.0", }, { "releaseTimestamp": "2009-07-25T18:01:57.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.12.1", }, { "releaseTimestamp": "2009-07-25T18:01:57.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.13.0", }, { "releaseTimestamp": "2009-07-25T18:01:57.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.13.1", }, { "releaseTimestamp": "2009-07-25T18:01:57.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.14.1", }, { "releaseTimestamp": "2009-07-25T18:01:57.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.14.2", }, { "releaseTimestamp": "2009-07-25T18:01:56.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.14.3", }, { "releaseTimestamp": "2009-07-25T18:01:56.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.14.4", }, { "releaseTimestamp": "2009-07-25T18:01:55.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.0.0", }, { "releaseTimestamp": "2009-07-25T18:01:55.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.1.0", }, { "releaseTimestamp": "2009-07-25T18:01:55.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.1.1", }, { "releaseTimestamp": "2009-07-25T18:01:54.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.1.2", }, { "releaseTimestamp": "2009-07-25T18:01:54.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.1.3", }, { "releaseTimestamp": "2009-07-25T18:01:54.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.1.4", }, { "releaseTimestamp": "2009-07-25T18:01:54.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.1.5", }, { "releaseTimestamp": "2009-07-25T18:01:54.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.1.6", }, { "releaseTimestamp": "2009-07-25T18:01:53.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.2.0", }, { "releaseTimestamp": "2009-07-25T18:01:52.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.2.1", }, { "releaseTimestamp": "2009-07-25T18:01:52.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.2.2", }, { "releaseTimestamp": "2009-07-25T18:01:52.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.2.3", }, { "releaseTimestamp": "2009-07-25T18:01:52.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.2.4", }, { "releaseTimestamp": "2009-07-25T18:01:52.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.2.5", }, { "releaseTimestamp": "2009-07-25T18:01:51.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.2.6", }, { "releaseTimestamp": "2009-07-25T18:01:51.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.0.0", }, { "releaseTimestamp": "2009-07-25T18:01:51.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.0.1", }, { "releaseTimestamp": "2009-07-25T18:01:51.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.0.2", }, { "releaseTimestamp": "2009-07-25T18:01:51.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.0.4", }, { "releaseTimestamp": "2009-07-25T18:01:50.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.0.5", }, { "releaseTimestamp": "2009-07-25T18:01:50.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.1.0", }, { "releaseTimestamp": "2009-07-25T18:01:50.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.1.1", }, { "releaseTimestamp": "2009-07-25T18:01:50.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.1.2", }, { "releaseTimestamp": "2009-07-25T18:01:49.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.2.2", }, { "releaseTimestamp": "2009-09-28T09:25:13.132Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.2.3", }, { "releaseTimestamp": "2009-07-25T18:01:49.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.2", }, { "releaseTimestamp": "2009-08-05T13:21:07.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.3", }, { "releaseTimestamp": "2009-09-04T17:33:48.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.4", }, { "releaseTimestamp": "2009-11-27T00:12:56.921Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.5", }, { "releaseTimestamp": "2010-05-23T07:49:23.602Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.6", }, { "releaseTimestamp": "2010-05-24T08:23:05.731Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.7", }, { "releaseTimestamp": "2010-05-24T21:17:25.987Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": "> 1.3.1", "version": "2.3.8.pre1", }, { "releaseTimestamp": "2010-05-25T04:53:06.895Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.8", }, { "releaseTimestamp": "2010-08-30T03:32:34.689Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": "> 1.3.1", "version": "2.3.9.pre", }, { "releaseTimestamp": "2010-09-04T21:54:41.257Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.9", }, { "releaseTimestamp": "2010-10-14T20:53:17.413Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.10", }, { "releaseTimestamp": "2011-02-08T21:17:36.254Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.11", }, { "releaseTimestamp": "2011-06-08T00:22:06.357Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.12", }, { "releaseTimestamp": "2011-08-16T22:01:21.962Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.14", }, { "releaseTimestamp": "2013-01-08T20:08:28.812Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.15", }, { "releaseTimestamp": "2013-01-28T21:01:30.451Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.16", }, { "releaseTimestamp": "2013-02-11T18:17:30.726Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.17", }, { "releaseTimestamp": "2013-03-18T17:13:25.422Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.18", }, { "releaseTimestamp": "2010-02-05T03:02:19.496Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": "> 1.3.1", "version": "3.0.0.beta", }, { "releaseTimestamp": "2010-04-01T21:26:26.222Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.0.beta2", }, { "releaseTimestamp": "2010-04-13T19:23:14.932Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.0.beta3", }, { "releaseTimestamp": "2010-06-08T22:33:16.046Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.0.beta4", }, { "releaseTimestamp": "2010-07-26T21:43:12.765Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.0.rc", }, { "releaseTimestamp": "2010-08-24T03:04:45.033Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.0.rc2", }, { "releaseTimestamp": "2010-08-29T23:11:11.490Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.0", }, { "releaseTimestamp": "2010-10-14T20:55:44.846Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.1", }, { "releaseTimestamp": "2010-11-15T19:33:41.460Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.2", }, { "releaseTimestamp": "2010-11-16T16:29:00.892Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.3", }, { "releaseTimestamp": "2011-01-30T23:00:37.572Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.4.rc1", }, { "releaseTimestamp": "2011-02-08T21:17:48.221Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.4", }, { "releaseTimestamp": "2011-02-23T19:08:34.691Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.5.rc1", }, { "releaseTimestamp": "2011-02-27T02:30:55.377Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.5", }, { "releaseTimestamp": "2011-03-29T20:47:15.107Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.6.rc1", }, { "releaseTimestamp": "2011-03-31T05:28:51.216Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.6.rc2", }, { "releaseTimestamp": "2011-04-05T23:05:21.745Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.6", }, { "releaseTimestamp": "2011-04-14T21:57:06.386Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.7.rc1", }, { "releaseTimestamp": "2011-04-15T17:33:53.132Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.7.rc2", }, { "releaseTimestamp": "2011-04-18T21:05:54.308Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.7", }, { "releaseTimestamp": "2011-05-26T00:11:36.891Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.8.rc1", }, { "releaseTimestamp": "2011-05-27T16:32:24.502Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.8.rc2", }, { "releaseTimestamp": "2011-05-31T00:08:18.745Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.8.rc4", }, { "releaseTimestamp": "2011-06-08T00:16:45.270Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.8", }, { "releaseTimestamp": "2011-06-08T21:20:17.404Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.9.rc1", }, { "releaseTimestamp": "2011-06-09T22:51:39.349Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.9.rc3", }, { "releaseTimestamp": "2011-06-12T21:24:34.980Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.9.rc4", }, { "releaseTimestamp": "2011-06-12T21:30:07.555Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.9.rc5", }, { "releaseTimestamp": "2011-06-16T10:05:11.080Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.9", }, { "releaseTimestamp": "2011-08-05T00:12:05.290Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.10.rc1", }, { "releaseTimestamp": "2011-08-16T22:14:17.045Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.10", }, { "releaseTimestamp": "2011-11-18T01:23:23.249Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.11", }, { "releaseTimestamp": "2012-02-22T21:39:19.764Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.12.rc1", }, { "releaseTimestamp": "2012-03-01T17:52:15.609Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.12", }, { "releaseTimestamp": "2012-05-28T19:01:47.715Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.13.rc1", }, { "releaseTimestamp": "2012-05-31T18:24:59.747Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.13", }, { "releaseTimestamp": "2012-06-12T21:26:07.460Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.14", }, { "releaseTimestamp": "2012-06-13T03:07:06.509Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.15", }, { "releaseTimestamp": "2012-07-26T22:08:54.212Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.16", }, { "releaseTimestamp": "2012-08-09T21:16:44.882Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.17", }, { "releaseTimestamp": "2013-01-02T21:19:52.960Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.18", }, { "releaseTimestamp": "2013-01-08T20:08:33.922Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.19", }, { "releaseTimestamp": "2013-01-28T21:01:34.374Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.20", }, { "releaseTimestamp": "2011-05-05T01:23:18.105Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.0.beta1", }, { "releaseTimestamp": "2011-05-22T02:26:25.383Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.0.rc1", }, { "releaseTimestamp": "2011-06-08T00:16:57.976Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.0.rc2", }, { "releaseTimestamp": "2011-06-08T21:27:28.270Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.0.rc3", }, { "releaseTimestamp": "2011-06-09T22:56:24.880Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.0.rc4", }, { "releaseTimestamp": "2011-07-25T23:05:19.817Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.0.rc5", }, { "releaseTimestamp": "2011-08-16T22:33:32.921Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.0.rc6", }, { "releaseTimestamp": "2011-08-29T03:27:19.194Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.0.rc8", }, { "releaseTimestamp": "2011-08-31T02:18:30.035Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.0", }, { "releaseTimestamp": "2011-09-15T00:27:03.617Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.1.rc1", }, { "releaseTimestamp": "2011-09-29T22:17:03.417Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.1.rc2", }, { "releaseTimestamp": "2011-10-06T02:31:00.452Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.1.rc3", }, { "releaseTimestamp": "2011-10-07T15:30:09.628Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.1", }, { "releaseTimestamp": "2011-11-14T14:17:34.523Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.2.rc1", }, { "releaseTimestamp": "2011-11-14T15:49:20.198Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.2.rc2", }, { "releaseTimestamp": "2011-11-18T01:33:32.509Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.2", }, { "releaseTimestamp": "2011-11-20T22:52:57.492Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.3", }, { "releaseTimestamp": "2012-02-22T21:39:29.633Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.4.rc1", }, { "releaseTimestamp": "2012-03-01T17:52:28.342Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.4", }, { "releaseTimestamp": "2012-05-28T19:01:51.050Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.5.rc1", }, { "releaseTimestamp": "2012-05-31T18:25:06.617Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.5", }, { "releaseTimestamp": "2012-06-12T21:26:16.856Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.6", }, { "releaseTimestamp": "2012-07-26T22:09:00.975Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.7", }, { "releaseTimestamp": "2012-08-09T21:20:27.129Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.8", }, { "releaseTimestamp": "2013-01-02T21:19:56.845Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.9", }, { "releaseTimestamp": "2013-01-08T20:08:37.727Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.10", }, { "releaseTimestamp": "2013-02-11T18:17:37.200Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.11", }, { "releaseTimestamp": "2013-03-18T17:13:29.344Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.12", }, { "releaseTimestamp": "2011-12-20T00:41:10.661Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.0.rc1", }, { "releaseTimestamp": "2012-01-04T21:05:27.454Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.0.rc2", }, { "releaseTimestamp": "2012-01-20T16:47:48.848Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.0", }, { "releaseTimestamp": "2012-01-26T23:09:41.494Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.1", }, { "releaseTimestamp": "2012-02-22T21:39:35.308Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.2.rc1", }, { "releaseTimestamp": "2012-03-01T17:52:33.094Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.2", }, { "releaseTimestamp": "2012-03-27T17:11:24.443Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.3.rc1", }, { "releaseTimestamp": "2012-03-29T16:14:14.715Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.3.rc2", }, { "releaseTimestamp": "2012-03-30T22:26:20.685Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.3", }, { "releaseTimestamp": "2012-05-28T19:01:55.834Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.4.rc1", }, { "releaseTimestamp": "2012-05-31T18:25:13.532Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.4", }, { "releaseTimestamp": "2012-06-01T03:39:04.678Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.5", }, { "releaseTimestamp": "2012-06-12T21:26:21.434Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.6", }, { "releaseTimestamp": "2012-07-23T21:45:55.204Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.7.rc1", }, { "releaseTimestamp": "2012-07-26T22:09:06.275Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.7", }, { "releaseTimestamp": "2012-08-01T20:57:56.061Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.8.rc1", }, { "releaseTimestamp": "2012-08-03T14:29:05.254Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.8.rc2", }, { "releaseTimestamp": "2012-08-09T21:23:34.632Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.8", }, { "releaseTimestamp": "2012-10-29T17:07:08.109Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.9.rc1", }, { "releaseTimestamp": "2012-11-01T17:39:37.178Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.9.rc2", }, { "releaseTimestamp": "2012-11-09T18:00:50.077Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.9.rc3", }, { "releaseTimestamp": "2012-11-12T15:21:34.822Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.9", }, { "releaseTimestamp": "2013-01-02T21:20:01.186Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.10", }, { "releaseTimestamp": "2013-01-08T20:08:45.798Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.11", }, { "releaseTimestamp": "2013-02-11T18:17:41.481Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.12", }, { "releaseTimestamp": "2013-02-27T20:25:46.062Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.13.rc1", }, { "releaseTimestamp": "2013-03-06T23:06:19.052Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.13.rc2", }, { "releaseTimestamp": "2013-03-18T17:13:33.058Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.13", }, { "releaseTimestamp": "2013-07-13T00:25:39.110Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.14.rc1", }, { "releaseTimestamp": "2013-07-16T16:13:33.339Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.14.rc2", }, { "releaseTimestamp": "2013-07-22T16:44:50.870Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.14", }, { "releaseTimestamp": "2013-10-03T18:54:09.709Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.15.rc1", }, { "releaseTimestamp": "2013-10-04T20:48:45.484Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.15.rc2", }, { "releaseTimestamp": "2013-10-11T21:17:17.374Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.15.rc3", }, { "releaseTimestamp": "2013-10-16T17:23:10.503Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.15", }, { "releaseTimestamp": "2013-12-03T19:01:19.549Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.16", }, { "releaseTimestamp": "2014-02-18T18:54:56.443Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.17", }, { "releaseTimestamp": "2014-05-06T16:17:02.829Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.18", }, { "releaseTimestamp": "2014-07-02T17:02:48.733Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.19", }, { "releaseTimestamp": "2014-10-30T18:37:26.434Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.20", }, { "releaseTimestamp": "2014-11-17T16:00:44.994Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.21", }, { "releaseTimestamp": "2015-06-16T18:06:38.294Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.22", }, { "releaseTimestamp": "2016-01-25T19:26:12.364Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.22.1", }, { "releaseTimestamp": "2016-02-29T19:24:19.757Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.22.2", }, { "releaseTimestamp": "2016-08-11T17:34:59.710Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.22.3", }, { "releaseTimestamp": "2016-08-11T19:20:46.883Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.22.4", }, { "releaseTimestamp": "2016-09-14T21:19:01.962Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.22.5", }, { "releaseTimestamp": "2013-02-26T00:05:43.566Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.0.beta1", }, { "releaseTimestamp": "2013-04-29T15:39:05.085Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.0.rc1", }, { "releaseTimestamp": "2013-06-11T20:26:00.144Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.0.rc2", }, { "releaseTimestamp": "2013-06-25T14:32:58.526Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.0", }, { "releaseTimestamp": "2013-10-17T16:46:23.993Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.1.rc1", }, { "releaseTimestamp": "2013-10-21T22:01:19.341Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.1.rc2", }, { "releaseTimestamp": "2013-10-23T21:41:08.791Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.1.rc3", }, { "releaseTimestamp": "2013-10-30T20:49:25.297Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.1.rc4", }, { "releaseTimestamp": "2013-11-01T19:08:16.307Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.1", }, { "releaseTimestamp": "2013-12-03T19:01:29.867Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.2", }, { "releaseTimestamp": "2014-02-18T18:49:43.150Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.3", }, { "releaseTimestamp": "2014-03-11T17:31:18.568Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.4.rc1", }, { "releaseTimestamp": "2014-03-14T17:37:07.331Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.4", }, { "releaseTimestamp": "2014-05-06T16:13:27.132Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.5", }, { "releaseTimestamp": "2014-05-27T16:06:55.364Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.6.rc1", }, { "releaseTimestamp": "2014-06-16T16:16:01.642Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.6.rc2", }, { "releaseTimestamp": "2014-06-23T17:24:41.466Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.6.rc3", }, { "releaseTimestamp": "2014-06-26T16:30:13.579Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.6", }, { "releaseTimestamp": "2014-07-02T17:04:32.418Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.7", }, { "releaseTimestamp": "2014-07-02T19:42:37.603Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.8", }, { "releaseTimestamp": "2014-08-18T17:03:01.087Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.9", }, { "releaseTimestamp": "2014-08-19T20:48:29.471Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.10.rc1", }, { "releaseTimestamp": "2014-09-08T17:55:45.314Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.10.rc2", }, { "releaseTimestamp": "2014-09-11T17:33:15.455Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.10", }, { "releaseTimestamp": "2014-10-30T18:37:38.192Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.11", }, { "releaseTimestamp": "2014-11-19T19:09:54.075Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.11.1", }, { "releaseTimestamp": "2014-11-17T16:01:00.306Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.12", }, { "releaseTimestamp": "2015-01-02T00:54:54.587Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.13.rc1", }, { "releaseTimestamp": "2015-01-06T20:08:59.935Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.13", }, { "releaseTimestamp": "2013-12-18T00:15:16.640Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.1.0.beta1", }, { "releaseTimestamp": "2014-02-18T18:52:57.614Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.1.0.beta2", }, { "releaseTimestamp": "2014-02-18T20:59:23.632Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.1.0.rc1", }, { "releaseTimestamp": "2014-03-25T20:12:47.195Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.0.rc2", }, { "releaseTimestamp": "2014-04-08T19:21:51.275Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.0", }, { "releaseTimestamp": "2014-05-06T16:11:31.458Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.1", }, { "releaseTimestamp": "2014-05-27T16:12:48.106Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.2.rc1", }, { "releaseTimestamp": "2014-06-16T16:30:46.332Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.2.rc2", }, { "releaseTimestamp": "2014-06-23T17:28:46.002Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.2.rc3", }, { "releaseTimestamp": "2014-06-26T14:50:09.079Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.2", }, { "releaseTimestamp": "2014-07-02T17:06:42.181Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.3", }, { "releaseTimestamp": "2014-07-02T19:53:35.556Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.4", }, { "releaseTimestamp": "2014-08-18T17:01:03.727Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.5", }, { "releaseTimestamp": "2014-08-19T20:52:47.110Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.6.rc1", }, { "releaseTimestamp": "2014-09-08T18:13:12.723Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.6.rc2", }, { "releaseTimestamp": "2014-09-11T17:26:04.576Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.6", }, { "releaseTimestamp": "2014-10-30T18:37:49.213Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.7", }, { "releaseTimestamp": "2014-11-19T19:12:12.692Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.7.1", }, { "releaseTimestamp": "2014-11-17T16:01:13.385Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.8", }, { "releaseTimestamp": "2015-01-02T01:11:10.973Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.9.rc1", }, { "releaseTimestamp": "2015-01-06T20:04:31.185Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.9", }, { "releaseTimestamp": "2015-02-20T22:25:09.666Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.10.rc1", }, { "releaseTimestamp": "2015-02-25T22:22:40.645Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.10.rc2", }, { "releaseTimestamp": "2015-03-02T21:39:47.964Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.10.rc3", }, { "releaseTimestamp": "2015-03-12T21:32:52.724Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.10.rc4", }, { "releaseTimestamp": "2015-03-19T16:50:27.388Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.10", }, { "releaseTimestamp": "2015-06-16T18:00:13.043Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.11", }, { "releaseTimestamp": "2015-06-22T14:05:08.486Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.12.rc1", }, { "releaseTimestamp": "2015-06-25T21:26:08.544Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.12", }, { "releaseTimestamp": "2015-08-14T15:13:26.943Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.13.rc1", }, { "releaseTimestamp": "2015-08-24T18:02:56.741Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.13", }, { "releaseTimestamp": "2015-10-30T20:45:42.801Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.14.rc1", }, { "releaseTimestamp": "2015-11-05T02:55:44.276Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.14.rc2", }, { "releaseTimestamp": "2015-11-12T18:20:40.613Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.14", }, { "releaseTimestamp": "2016-01-25T19:26:27.339Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.14.1", }, { "releaseTimestamp": "2016-02-29T19:19:55.523Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.14.2", }, { "releaseTimestamp": "2016-03-01T18:43:40.764Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.15.rc1", }, { "releaseTimestamp": "2016-03-07T22:37:14.594Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.15", }, { "releaseTimestamp": "2016-07-02T02:15:20.923Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.16.rc1", }, { "releaseTimestamp": "2016-07-12T22:20:56.527Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.16", }, { "releaseTimestamp": "2014-08-20T02:34:44.046Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.0.beta1", }, { "releaseTimestamp": "2014-09-29T17:16:38.761Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.0.beta2", }, { "releaseTimestamp": "2014-10-30T18:37:59.690Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.0.beta3", }, { "releaseTimestamp": "2014-10-30T22:13:30.689Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.0.beta4", }, { "releaseTimestamp": "2014-11-28T17:53:27.822Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.0.rc1", }, { "releaseTimestamp": "2014-12-05T23:20:12.824Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.0.rc2", }, { "releaseTimestamp": "2014-12-13T02:58:44.762Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.0.rc3", }, { "releaseTimestamp": "2014-12-20T00:15:37.476Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.0", }, { "releaseTimestamp": "2015-02-20T22:21:34.214Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.1.rc1", }, { "releaseTimestamp": "2015-02-25T22:19:50.245Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.1.rc2", }, { "releaseTimestamp": "2015-03-02T21:35:50.169Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.1.rc3", }, { "releaseTimestamp": "2015-03-12T21:25:52.551Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.1.rc4", }, { "releaseTimestamp": "2015-03-19T16:42:01.191Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.1", }, { "releaseTimestamp": "2015-06-16T18:03:17.061Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.2", }, { "releaseTimestamp": "2015-06-22T14:23:17.788Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.3.rc1", }, { "releaseTimestamp": "2015-06-25T21:30:57.890Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.3", }, { "releaseTimestamp": "2015-08-14T15:21:15.566Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.4.rc1", }, { "releaseTimestamp": "2015-08-24T18:27:12.716Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.4", }, { "releaseTimestamp": "2015-10-30T20:47:59.397Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.5.rc1", }, { "releaseTimestamp": "2015-11-05T03:02:33.340Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.5.rc2", }, { "releaseTimestamp": "2015-11-12T17:06:55.226Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.5", }, { "releaseTimestamp": "2016-01-25T19:26:41.410Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.5.1", }, { "releaseTimestamp": "2016-02-29T19:17:10.564Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.5.2", }, { "releaseTimestamp": "2016-03-01T18:37:54.172Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.6.rc1", }, { "releaseTimestamp": "2016-03-07T22:33:22.563Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.6", }, { "releaseTimestamp": "2016-07-01T00:33:36.424Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.7.rc1", }, { "releaseTimestamp": "2016-07-13T02:57:05.601Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.7", }, { "releaseTimestamp": "2016-08-11T17:35:16.160Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.7.1", }, { "releaseTimestamp": "2017-02-10T02:46:51.222Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.8.rc1", }, { "releaseTimestamp": "2017-02-21T16:08:53.220Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.8", }, { "releaseTimestamp": "2017-06-13T18:50:29.897Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.9.rc1", }, { "releaseTimestamp": "2017-06-19T22:28:22.086Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.9.rc2", }, { "releaseTimestamp": "2017-06-26T21:30:56.077Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.9", }, { "releaseTimestamp": "2017-09-20T19:42:33.297Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.10.rc1", }, { "releaseTimestamp": "2017-09-27T14:29:42.567Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.10", }, { "releaseTimestamp": "2018-11-27T20:07:25.845Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.11", }, { "releaseTimestamp": "2015-12-18T21:18:13.306Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0.beta1", }, { "releaseTimestamp": "2016-01-25T19:26:49.903Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0.beta1.1", }, { "releaseTimestamp": "2016-02-01T22:06:25.279Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0.beta2", }, { "releaseTimestamp": "2016-02-24T16:16:22.722Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0.beta3", }, { "releaseTimestamp": "2016-04-27T20:55:26.508Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0.beta4", }, { "releaseTimestamp": "2016-05-06T22:02:43.345Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0.racecar1", }, { "releaseTimestamp": "2016-05-06T21:57:46.793Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0.rc1", }, { "releaseTimestamp": "2016-06-22T20:03:41.237Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0.rc2", }, { "releaseTimestamp": "2016-06-30T21:32:45.255Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0", }, { "releaseTimestamp": "2016-08-11T17:35:27.196Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0.1", }, { "releaseTimestamp": "2016-11-30T20:02:44.553Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.1.rc1", }, { "releaseTimestamp": "2016-12-09T19:13:12.953Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.1.rc2", }, { "releaseTimestamp": "2016-12-21T00:07:46.527Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.1", }, { "releaseTimestamp": "2017-02-25T00:55:48.618Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.2.rc1", }, { "releaseTimestamp": "2017-03-01T23:13:53.219Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.2", }, { "releaseTimestamp": "2017-05-12T20:08:33.226Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.3", }, { "releaseTimestamp": "2017-06-14T20:49:29.610Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.4.rc1", }, { "releaseTimestamp": "2017-06-19T21:58:56.501Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.4", }, { "releaseTimestamp": "2017-07-19T19:43:58.280Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.5.rc1", }, { "releaseTimestamp": "2017-07-25T20:26:10.369Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.5.rc2", }, { "releaseTimestamp": "2017-07-31T19:05:29.060Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.5", }, { "releaseTimestamp": "2017-08-24T19:21:20.599Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.6.rc1", }, { "releaseTimestamp": "2017-09-08T00:47:42.201Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.6", }, { "releaseTimestamp": "2018-03-29T18:18:14.388Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.7", }, { "releaseTimestamp": "2018-11-27T20:09:36.347Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.7.1", }, { "releaseTimestamp": "2017-02-23T20:00:44.720Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.0.beta1", }, { "releaseTimestamp": "2017-03-20T18:57:56.595Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.0.rc1", }, { "releaseTimestamp": "2017-04-21T01:31:13.442Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.0.rc2", }, { "releaseTimestamp": "2017-04-27T21:00:47.670Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.0", }, { "releaseTimestamp": "2017-05-12T20:11:39.743Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.1", }, { "releaseTimestamp": "2017-06-20T17:03:49.322Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.2.rc1", }, { "releaseTimestamp": "2017-06-26T21:51:41.161Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.2", }, { "releaseTimestamp": "2017-07-19T19:38:05.393Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.3.rc1", }, { "releaseTimestamp": "2017-07-25T20:18:18.420Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.3.rc2", }, { "releaseTimestamp": "2017-07-31T19:12:53.241Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.3.rc3", }, { "releaseTimestamp": "2017-08-03T19:15:15.370Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.3", }, { "releaseTimestamp": "2017-08-24T19:37:37.728Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.4.rc1", }, { "releaseTimestamp": "2017-09-08T00:52:07.791Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.4", }, { "releaseTimestamp": "2018-02-01T19:00:37.520Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.5.rc1", }, { "releaseTimestamp": "2018-02-14T20:02:02.541Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.5", }, { "releaseTimestamp": "2018-03-29T18:29:03.149Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.6", }, { "releaseTimestamp": "2018-11-27T20:11:47.585Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.6.1", }, { "releaseTimestamp": "2017-11-27T19:19:13.809Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.0.beta1", }, { "releaseTimestamp": "2017-11-28T05:04:37.765Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.0.beta2", }, { "releaseTimestamp": "2018-01-30T23:38:56.843Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.0.rc1", }, { "releaseTimestamp": "2018-03-20T17:54:58.165Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.0.rc2", }, { "releaseTimestamp": "2018-04-09T20:07:04.834Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.0", }, { "releaseTimestamp": "2018-07-30T20:22:38.749Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.1.rc1", }, { "releaseTimestamp": "2018-08-07T21:44:52.020Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.1", }, { "releaseTimestamp": "2018-11-27T20:14:16.796Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.1.1", }, { "releaseTimestamp": "2018-11-28T22:55:23.827Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.2.rc1", }, { "releaseTimestamp": "2018-12-04T18:15:02.233Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.2", }, ], @@ -3777,2380 +2422,1364 @@ exports[`modules/datasource/rubygems/index getReleases uses rubygems.org if no r exports[`modules/datasource/rubygems/index getReleases works with real data 1`] = ` { + "changelogUrl": "https://www.railschangelog.com/", "homepage": "http://rubyonrails.org", "registryUrl": "https://thirdparty.com", "releases": [ { "releaseTimestamp": "2009-07-25T18:01:56.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.8.0", }, { "releaseTimestamp": "2009-07-25T18:01:56.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.8.5", }, { "releaseTimestamp": "2009-07-25T18:01:56.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.9.0", }, { "releaseTimestamp": "2009-07-25T18:01:56.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.9.1", }, { "releaseTimestamp": "2009-07-25T18:01:56.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.9.2", }, { "releaseTimestamp": "2009-07-25T18:01:55.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.9.3", }, { "releaseTimestamp": "2009-07-25T18:01:55.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.9.4", }, { "releaseTimestamp": "2009-07-25T18:01:55.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.9.4.1", }, { "releaseTimestamp": "2009-07-25T18:01:55.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.9.5", }, { "releaseTimestamp": "2009-07-25T18:01:58.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.10.0", }, { "releaseTimestamp": "2009-07-25T18:01:58.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.10.1", }, { "releaseTimestamp": "2009-07-25T18:01:58.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.11.0", }, { "releaseTimestamp": "2009-07-25T18:01:58.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.11.1", }, { "releaseTimestamp": "2009-07-25T18:01:58.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.12.0", }, { "releaseTimestamp": "2009-07-25T18:01:57.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.12.1", }, { "releaseTimestamp": "2009-07-25T18:01:57.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.13.0", }, { "releaseTimestamp": "2009-07-25T18:01:57.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.13.1", }, { "releaseTimestamp": "2009-07-25T18:01:57.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.14.1", }, { "releaseTimestamp": "2009-07-25T18:01:57.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.14.2", }, { "releaseTimestamp": "2009-07-25T18:01:56.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.14.3", }, { "releaseTimestamp": "2009-07-25T18:01:56.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "0.14.4", }, { "releaseTimestamp": "2009-07-25T18:01:55.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.0.0", }, { "releaseTimestamp": "2009-07-25T18:01:55.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.1.0", }, { "releaseTimestamp": "2009-07-25T18:01:55.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.1.1", }, { "releaseTimestamp": "2009-07-25T18:01:54.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.1.2", }, { "releaseTimestamp": "2009-07-25T18:01:54.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.1.3", }, { "releaseTimestamp": "2009-07-25T18:01:54.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.1.4", }, { "releaseTimestamp": "2009-07-25T18:01:54.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.1.5", }, { "releaseTimestamp": "2009-07-25T18:01:54.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.1.6", }, { "releaseTimestamp": "2009-07-25T18:01:53.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.2.0", }, { "releaseTimestamp": "2009-07-25T18:01:52.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.2.1", }, { "releaseTimestamp": "2009-07-25T18:01:52.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.2.2", }, { "releaseTimestamp": "2009-07-25T18:01:52.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.2.3", }, { "releaseTimestamp": "2009-07-25T18:01:52.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.2.4", }, { "releaseTimestamp": "2009-07-25T18:01:52.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.2.5", }, { "releaseTimestamp": "2009-07-25T18:01:51.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "1.2.6", }, { "releaseTimestamp": "2009-07-25T18:01:51.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.0.0", }, { "releaseTimestamp": "2009-07-25T18:01:51.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.0.1", }, { "releaseTimestamp": "2009-07-25T18:01:51.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.0.2", }, { "releaseTimestamp": "2009-07-25T18:01:51.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.0.4", }, { "releaseTimestamp": "2009-07-25T18:01:50.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.0.5", }, { "releaseTimestamp": "2009-07-25T18:01:50.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.1.0", }, { "releaseTimestamp": "2009-07-25T18:01:50.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.1.1", }, { "releaseTimestamp": "2009-07-25T18:01:50.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.1.2", }, { "releaseTimestamp": "2009-07-25T18:01:49.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.2.2", }, { "releaseTimestamp": "2009-09-28T09:25:13.132Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.2.3", }, { "releaseTimestamp": "2009-07-25T18:01:49.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.2", }, { "releaseTimestamp": "2009-08-05T13:21:07.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.3", }, { "releaseTimestamp": "2009-09-04T17:33:48.000Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.4", }, { "releaseTimestamp": "2009-11-27T00:12:56.921Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.5", }, { "releaseTimestamp": "2010-05-23T07:49:23.602Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.6", }, { "releaseTimestamp": "2010-05-24T08:23:05.731Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.7", }, { "releaseTimestamp": "2010-05-24T21:17:25.987Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": "> 1.3.1", "version": "2.3.8.pre1", }, { "releaseTimestamp": "2010-05-25T04:53:06.895Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.8", }, { "releaseTimestamp": "2010-08-30T03:32:34.689Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": "> 1.3.1", "version": "2.3.9.pre", }, { "releaseTimestamp": "2010-09-04T21:54:41.257Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.9", }, { "releaseTimestamp": "2010-10-14T20:53:17.413Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.10", }, { "releaseTimestamp": "2011-02-08T21:17:36.254Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.11", }, { "releaseTimestamp": "2011-06-08T00:22:06.357Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.12", }, { "releaseTimestamp": "2011-08-16T22:01:21.962Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.14", }, { "releaseTimestamp": "2013-01-08T20:08:28.812Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.15", }, { "releaseTimestamp": "2013-01-28T21:01:30.451Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.16", }, { "releaseTimestamp": "2013-02-11T18:17:30.726Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.17", }, { "releaseTimestamp": "2013-03-18T17:13:25.422Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 0", "version": "2.3.18", }, { "releaseTimestamp": "2010-02-05T03:02:19.496Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": "> 1.3.1", "version": "3.0.0.beta", }, { "releaseTimestamp": "2010-04-01T21:26:26.222Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.0.beta2", }, { "releaseTimestamp": "2010-04-13T19:23:14.932Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.0.beta3", }, { "releaseTimestamp": "2010-06-08T22:33:16.046Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.0.beta4", }, { "releaseTimestamp": "2010-07-26T21:43:12.765Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.0.rc", }, { "releaseTimestamp": "2010-08-24T03:04:45.033Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.0.rc2", }, { "releaseTimestamp": "2010-08-29T23:11:11.490Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.0", }, { "releaseTimestamp": "2010-10-14T20:55:44.846Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.1", }, { "releaseTimestamp": "2010-11-15T19:33:41.460Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.2", }, { "releaseTimestamp": "2010-11-16T16:29:00.892Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.3", }, { "releaseTimestamp": "2011-01-30T23:00:37.572Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.4.rc1", }, { "releaseTimestamp": "2011-02-08T21:17:48.221Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.4", }, { "releaseTimestamp": "2011-02-23T19:08:34.691Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.5.rc1", }, { "releaseTimestamp": "2011-02-27T02:30:55.377Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.5", }, { "releaseTimestamp": "2011-03-29T20:47:15.107Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.6.rc1", }, { "releaseTimestamp": "2011-03-31T05:28:51.216Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.6.rc2", }, { "releaseTimestamp": "2011-04-05T23:05:21.745Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.6", }, { "releaseTimestamp": "2011-04-14T21:57:06.386Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.7.rc1", }, { "releaseTimestamp": "2011-04-15T17:33:53.132Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.7.rc2", }, { "releaseTimestamp": "2011-04-18T21:05:54.308Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.7", }, { "releaseTimestamp": "2011-05-26T00:11:36.891Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.8.rc1", }, { "releaseTimestamp": "2011-05-27T16:32:24.502Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.8.rc2", }, { "releaseTimestamp": "2011-05-31T00:08:18.745Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.8.rc4", }, { "releaseTimestamp": "2011-06-08T00:16:45.270Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.8", }, { "releaseTimestamp": "2011-06-08T21:20:17.404Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.9.rc1", }, { "releaseTimestamp": "2011-06-09T22:51:39.349Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.9.rc3", }, { "releaseTimestamp": "2011-06-12T21:24:34.980Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.9.rc4", }, { "releaseTimestamp": "2011-06-12T21:30:07.555Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.9.rc5", }, { "releaseTimestamp": "2011-06-16T10:05:11.080Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.9", }, { "releaseTimestamp": "2011-08-05T00:12:05.290Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.10.rc1", }, { "releaseTimestamp": "2011-08-16T22:14:17.045Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.10", }, { "releaseTimestamp": "2011-11-18T01:23:23.249Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.11", }, { "releaseTimestamp": "2012-02-22T21:39:19.764Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.12.rc1", }, { "releaseTimestamp": "2012-03-01T17:52:15.609Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.12", }, { "releaseTimestamp": "2012-05-28T19:01:47.715Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.13.rc1", }, { "releaseTimestamp": "2012-05-31T18:24:59.747Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.13", }, { "releaseTimestamp": "2012-06-12T21:26:07.460Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.14", }, { "releaseTimestamp": "2012-06-13T03:07:06.509Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.15", }, { "releaseTimestamp": "2012-07-26T22:08:54.212Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.16", }, { "releaseTimestamp": "2012-08-09T21:16:44.882Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.17", }, { "releaseTimestamp": "2013-01-02T21:19:52.960Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.18", }, { "releaseTimestamp": "2013-01-08T20:08:33.922Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.19", }, { "releaseTimestamp": "2013-01-28T21:01:34.374Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.0.20", }, { "releaseTimestamp": "2011-05-05T01:23:18.105Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.0.beta1", }, { "releaseTimestamp": "2011-05-22T02:26:25.383Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.0.rc1", }, { "releaseTimestamp": "2011-06-08T00:16:57.976Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.0.rc2", }, { "releaseTimestamp": "2011-06-08T21:27:28.270Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.0.rc3", }, { "releaseTimestamp": "2011-06-09T22:56:24.880Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.0.rc4", }, { "releaseTimestamp": "2011-07-25T23:05:19.817Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.0.rc5", }, { "releaseTimestamp": "2011-08-16T22:33:32.921Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.0.rc6", }, { "releaseTimestamp": "2011-08-29T03:27:19.194Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.0.rc8", }, { "releaseTimestamp": "2011-08-31T02:18:30.035Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.0", }, { "releaseTimestamp": "2011-09-15T00:27:03.617Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.1.rc1", }, { "releaseTimestamp": "2011-09-29T22:17:03.417Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.1.rc2", }, { "releaseTimestamp": "2011-10-06T02:31:00.452Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.1.rc3", }, { "releaseTimestamp": "2011-10-07T15:30:09.628Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.1", }, { "releaseTimestamp": "2011-11-14T14:17:34.523Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.2.rc1", }, { "releaseTimestamp": "2011-11-14T15:49:20.198Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.2.rc2", }, { "releaseTimestamp": "2011-11-18T01:33:32.509Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.2", }, { "releaseTimestamp": "2011-11-20T22:52:57.492Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.3", }, { "releaseTimestamp": "2012-02-22T21:39:29.633Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.4.rc1", }, { "releaseTimestamp": "2012-03-01T17:52:28.342Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.4", }, { "releaseTimestamp": "2012-05-28T19:01:51.050Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.5.rc1", }, { "releaseTimestamp": "2012-05-31T18:25:06.617Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.5", }, { "releaseTimestamp": "2012-06-12T21:26:16.856Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.6", }, { "releaseTimestamp": "2012-07-26T22:09:00.975Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.7", }, { "releaseTimestamp": "2012-08-09T21:20:27.129Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.8", }, { "releaseTimestamp": "2013-01-02T21:19:56.845Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.9", }, { "releaseTimestamp": "2013-01-08T20:08:37.727Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.10", }, { "releaseTimestamp": "2013-02-11T18:17:37.200Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.11", }, { "releaseTimestamp": "2013-03-18T17:13:29.344Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.1.12", }, { "releaseTimestamp": "2011-12-20T00:41:10.661Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.0.rc1", }, { "releaseTimestamp": "2012-01-04T21:05:27.454Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.0.rc2", }, { "releaseTimestamp": "2012-01-20T16:47:48.848Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.0", }, { "releaseTimestamp": "2012-01-26T23:09:41.494Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.1", }, { "releaseTimestamp": "2012-02-22T21:39:35.308Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.2.rc1", }, { "releaseTimestamp": "2012-03-01T17:52:33.094Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.2", }, { "releaseTimestamp": "2012-03-27T17:11:24.443Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.3.rc1", }, { "releaseTimestamp": "2012-03-29T16:14:14.715Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.3.rc2", }, { "releaseTimestamp": "2012-03-30T22:26:20.685Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.3", }, { "releaseTimestamp": "2012-05-28T19:01:55.834Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.4.rc1", }, { "releaseTimestamp": "2012-05-31T18:25:13.532Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.4", }, { "releaseTimestamp": "2012-06-01T03:39:04.678Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.5", }, { "releaseTimestamp": "2012-06-12T21:26:21.434Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.6", }, { "releaseTimestamp": "2012-07-23T21:45:55.204Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.7.rc1", }, { "releaseTimestamp": "2012-07-26T22:09:06.275Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.7", }, { "releaseTimestamp": "2012-08-01T20:57:56.061Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.8.rc1", }, { "releaseTimestamp": "2012-08-03T14:29:05.254Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.8.rc2", }, { "releaseTimestamp": "2012-08-09T21:23:34.632Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.8", }, { "releaseTimestamp": "2012-10-29T17:07:08.109Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.9.rc1", }, { "releaseTimestamp": "2012-11-01T17:39:37.178Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.9.rc2", }, { "releaseTimestamp": "2012-11-09T18:00:50.077Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.9.rc3", }, { "releaseTimestamp": "2012-11-12T15:21:34.822Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.9", }, { "releaseTimestamp": "2013-01-02T21:20:01.186Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.10", }, { "releaseTimestamp": "2013-01-08T20:08:45.798Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.11", }, { "releaseTimestamp": "2013-02-11T18:17:41.481Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.12", }, { "releaseTimestamp": "2013-02-27T20:25:46.062Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.13.rc1", }, { "releaseTimestamp": "2013-03-06T23:06:19.052Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.13.rc2", }, { "releaseTimestamp": "2013-03-18T17:13:33.058Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.13", }, { "releaseTimestamp": "2013-07-13T00:25:39.110Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.14.rc1", }, { "releaseTimestamp": "2013-07-16T16:13:33.339Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.14.rc2", }, { "releaseTimestamp": "2013-07-22T16:44:50.870Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.14", }, { "releaseTimestamp": "2013-10-03T18:54:09.709Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.15.rc1", }, { "releaseTimestamp": "2013-10-04T20:48:45.484Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.15.rc2", }, { "releaseTimestamp": "2013-10-11T21:17:17.374Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.15.rc3", }, { "releaseTimestamp": "2013-10-16T17:23:10.503Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.15", }, { "releaseTimestamp": "2013-12-03T19:01:19.549Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.16", }, { "releaseTimestamp": "2014-02-18T18:54:56.443Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.3.6", "version": "3.2.17", }, { "releaseTimestamp": "2014-05-06T16:17:02.829Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.18", }, { "releaseTimestamp": "2014-07-02T17:02:48.733Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.19", }, { "releaseTimestamp": "2014-10-30T18:37:26.434Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.20", }, { "releaseTimestamp": "2014-11-17T16:00:44.994Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.21", }, { "releaseTimestamp": "2015-06-16T18:06:38.294Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.22", }, { "releaseTimestamp": "2016-01-25T19:26:12.364Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.22.1", }, { "releaseTimestamp": "2016-02-29T19:24:19.757Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.22.2", }, { "releaseTimestamp": "2016-08-11T17:34:59.710Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.22.3", }, { "releaseTimestamp": "2016-08-11T19:20:46.883Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.22.4", }, { "releaseTimestamp": "2016-09-14T21:19:01.962Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.8.7", - "rubygemsVersion": ">= 1.3.6", "version": "3.2.22.5", }, { "releaseTimestamp": "2013-02-26T00:05:43.566Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.0.beta1", }, { "releaseTimestamp": "2013-04-29T15:39:05.085Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.0.rc1", }, { "releaseTimestamp": "2013-06-11T20:26:00.144Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.0.rc2", }, { "releaseTimestamp": "2013-06-25T14:32:58.526Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.0", }, { "releaseTimestamp": "2013-10-17T16:46:23.993Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.1.rc1", }, { "releaseTimestamp": "2013-10-21T22:01:19.341Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.1.rc2", }, { "releaseTimestamp": "2013-10-23T21:41:08.791Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.1.rc3", }, { "releaseTimestamp": "2013-10-30T20:49:25.297Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.1.rc4", }, { "releaseTimestamp": "2013-11-01T19:08:16.307Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.1", }, { "releaseTimestamp": "2013-12-03T19:01:29.867Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.2", }, { "releaseTimestamp": "2014-02-18T18:49:43.150Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.3", }, { "releaseTimestamp": "2014-03-11T17:31:18.568Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.4.rc1", }, { "releaseTimestamp": "2014-03-14T17:37:07.331Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.0.4", }, { "releaseTimestamp": "2014-05-06T16:13:27.132Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.5", }, { "releaseTimestamp": "2014-05-27T16:06:55.364Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.6.rc1", }, { "releaseTimestamp": "2014-06-16T16:16:01.642Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.6.rc2", }, { "releaseTimestamp": "2014-06-23T17:24:41.466Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.6.rc3", }, { "releaseTimestamp": "2014-06-26T16:30:13.579Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.6", }, { "releaseTimestamp": "2014-07-02T17:04:32.418Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.7", }, { "releaseTimestamp": "2014-07-02T19:42:37.603Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.8", }, { "releaseTimestamp": "2014-08-18T17:03:01.087Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.9", }, { "releaseTimestamp": "2014-08-19T20:48:29.471Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.10.rc1", }, { "releaseTimestamp": "2014-09-08T17:55:45.314Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.10.rc2", }, { "releaseTimestamp": "2014-09-11T17:33:15.455Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.10", }, { "releaseTimestamp": "2014-10-30T18:37:38.192Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.11", }, { "releaseTimestamp": "2014-11-19T19:09:54.075Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.11.1", }, { "releaseTimestamp": "2014-11-17T16:01:00.306Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.12", }, { "releaseTimestamp": "2015-01-02T00:54:54.587Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.13.rc1", }, { "releaseTimestamp": "2015-01-06T20:08:59.935Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.0.13", }, { "releaseTimestamp": "2013-12-18T00:15:16.640Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.1.0.beta1", }, { "releaseTimestamp": "2014-02-18T18:52:57.614Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.1.0.beta2", }, { "releaseTimestamp": "2014-02-18T20:59:23.632Z", - "rubyPlatform": "ruby", - "rubyVersion": null, - "rubygemsVersion": ">= 1.8.11", "version": "4.1.0.rc1", }, { "releaseTimestamp": "2014-03-25T20:12:47.195Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.0.rc2", }, { "releaseTimestamp": "2014-04-08T19:21:51.275Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.0", }, { "releaseTimestamp": "2014-05-06T16:11:31.458Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.1", }, { "releaseTimestamp": "2014-05-27T16:12:48.106Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.2.rc1", }, { "releaseTimestamp": "2014-06-16T16:30:46.332Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.2.rc2", }, { "releaseTimestamp": "2014-06-23T17:28:46.002Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.2.rc3", }, { "releaseTimestamp": "2014-06-26T14:50:09.079Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.2", }, { "releaseTimestamp": "2014-07-02T17:06:42.181Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.3", }, { "releaseTimestamp": "2014-07-02T19:53:35.556Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.4", }, { "releaseTimestamp": "2014-08-18T17:01:03.727Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.5", }, { "releaseTimestamp": "2014-08-19T20:52:47.110Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.6.rc1", }, { "releaseTimestamp": "2014-09-08T18:13:12.723Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.6.rc2", }, { "releaseTimestamp": "2014-09-11T17:26:04.576Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.6", }, { "releaseTimestamp": "2014-10-30T18:37:49.213Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.7", }, { "releaseTimestamp": "2014-11-19T19:12:12.692Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.7.1", }, { "releaseTimestamp": "2014-11-17T16:01:13.385Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.8", }, { "releaseTimestamp": "2015-01-02T01:11:10.973Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.9.rc1", }, { "releaseTimestamp": "2015-01-06T20:04:31.185Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.9", }, { "releaseTimestamp": "2015-02-20T22:25:09.666Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.10.rc1", }, { "releaseTimestamp": "2015-02-25T22:22:40.645Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.10.rc2", }, { "releaseTimestamp": "2015-03-02T21:39:47.964Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.10.rc3", }, { "releaseTimestamp": "2015-03-12T21:32:52.724Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.10.rc4", }, { "releaseTimestamp": "2015-03-19T16:50:27.388Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.10", }, { "releaseTimestamp": "2015-06-16T18:00:13.043Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.11", }, { "releaseTimestamp": "2015-06-22T14:05:08.486Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.12.rc1", }, { "releaseTimestamp": "2015-06-25T21:26:08.544Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.12", }, { "releaseTimestamp": "2015-08-14T15:13:26.943Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.13.rc1", }, { "releaseTimestamp": "2015-08-24T18:02:56.741Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.13", }, { "releaseTimestamp": "2015-10-30T20:45:42.801Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.14.rc1", }, { "releaseTimestamp": "2015-11-05T02:55:44.276Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.14.rc2", }, { "releaseTimestamp": "2015-11-12T18:20:40.613Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.14", }, { "releaseTimestamp": "2016-01-25T19:26:27.339Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.14.1", }, { "releaseTimestamp": "2016-02-29T19:19:55.523Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.14.2", }, { "releaseTimestamp": "2016-03-01T18:43:40.764Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.15.rc1", }, { "releaseTimestamp": "2016-03-07T22:37:14.594Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.15", }, { "releaseTimestamp": "2016-07-02T02:15:20.923Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.16.rc1", }, { "releaseTimestamp": "2016-07-12T22:20:56.527Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.1.16", }, { "releaseTimestamp": "2014-08-20T02:34:44.046Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.0.beta1", }, { "releaseTimestamp": "2014-09-29T17:16:38.761Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.0.beta2", }, { "releaseTimestamp": "2014-10-30T18:37:59.690Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.0.beta3", }, { "releaseTimestamp": "2014-10-30T22:13:30.689Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.0.beta4", }, { "releaseTimestamp": "2014-11-28T17:53:27.822Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.0.rc1", }, { "releaseTimestamp": "2014-12-05T23:20:12.824Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.0.rc2", }, { "releaseTimestamp": "2014-12-13T02:58:44.762Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.0.rc3", }, { "releaseTimestamp": "2014-12-20T00:15:37.476Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.0", }, { "releaseTimestamp": "2015-02-20T22:21:34.214Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.1.rc1", }, { "releaseTimestamp": "2015-02-25T22:19:50.245Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.1.rc2", }, { "releaseTimestamp": "2015-03-02T21:35:50.169Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.1.rc3", }, { "releaseTimestamp": "2015-03-12T21:25:52.551Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.1.rc4", }, { "releaseTimestamp": "2015-03-19T16:42:01.191Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.1", }, { "releaseTimestamp": "2015-06-16T18:03:17.061Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.2", }, { "releaseTimestamp": "2015-06-22T14:23:17.788Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.3.rc1", }, { "releaseTimestamp": "2015-06-25T21:30:57.890Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.3", }, { "releaseTimestamp": "2015-08-14T15:21:15.566Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.4.rc1", }, { "releaseTimestamp": "2015-08-24T18:27:12.716Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.4", }, { "releaseTimestamp": "2015-10-30T20:47:59.397Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.5.rc1", }, { "releaseTimestamp": "2015-11-05T03:02:33.340Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.5.rc2", }, { "releaseTimestamp": "2015-11-12T17:06:55.226Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.5", }, { "releaseTimestamp": "2016-01-25T19:26:41.410Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.5.1", }, { "releaseTimestamp": "2016-02-29T19:17:10.564Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.5.2", }, { "releaseTimestamp": "2016-03-01T18:37:54.172Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.6.rc1", }, { "releaseTimestamp": "2016-03-07T22:33:22.563Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.6", }, { "releaseTimestamp": "2016-07-01T00:33:36.424Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.7.rc1", }, { "releaseTimestamp": "2016-07-13T02:57:05.601Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.7", }, { "releaseTimestamp": "2016-08-11T17:35:16.160Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.7.1", }, { "releaseTimestamp": "2017-02-10T02:46:51.222Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.8.rc1", }, { "releaseTimestamp": "2017-02-21T16:08:53.220Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.8", }, { "releaseTimestamp": "2017-06-13T18:50:29.897Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.9.rc1", }, { "releaseTimestamp": "2017-06-19T22:28:22.086Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.9.rc2", }, { "releaseTimestamp": "2017-06-26T21:30:56.077Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.9", }, { "releaseTimestamp": "2017-09-20T19:42:33.297Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.10.rc1", }, { "releaseTimestamp": "2017-09-27T14:29:42.567Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.10", }, { "releaseTimestamp": "2018-11-27T20:07:25.845Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 1.9.3", - "rubygemsVersion": ">= 1.8.11", "version": "4.2.11", }, { "releaseTimestamp": "2015-12-18T21:18:13.306Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0.beta1", }, { "releaseTimestamp": "2016-01-25T19:26:49.903Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0.beta1.1", }, { "releaseTimestamp": "2016-02-01T22:06:25.279Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0.beta2", }, { "releaseTimestamp": "2016-02-24T16:16:22.722Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0.beta3", }, { "releaseTimestamp": "2016-04-27T20:55:26.508Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0.beta4", }, { "releaseTimestamp": "2016-05-06T22:02:43.345Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0.racecar1", }, { "releaseTimestamp": "2016-05-06T21:57:46.793Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0.rc1", }, { "releaseTimestamp": "2016-06-22T20:03:41.237Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0.rc2", }, { "releaseTimestamp": "2016-06-30T21:32:45.255Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0", }, { "releaseTimestamp": "2016-08-11T17:35:27.196Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.0.1", }, { "releaseTimestamp": "2016-11-30T20:02:44.553Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.1.rc1", }, { "releaseTimestamp": "2016-12-09T19:13:12.953Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.1.rc2", }, { "releaseTimestamp": "2016-12-21T00:07:46.527Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.1", }, { "releaseTimestamp": "2017-02-25T00:55:48.618Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.2.rc1", }, { "releaseTimestamp": "2017-03-01T23:13:53.219Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.2", }, { "releaseTimestamp": "2017-05-12T20:08:33.226Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.3", }, { "releaseTimestamp": "2017-06-14T20:49:29.610Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.4.rc1", }, { "releaseTimestamp": "2017-06-19T21:58:56.501Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.4", }, { "releaseTimestamp": "2017-07-19T19:43:58.280Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.5.rc1", }, { "releaseTimestamp": "2017-07-25T20:26:10.369Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.5.rc2", }, { "releaseTimestamp": "2017-07-31T19:05:29.060Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.5", }, { "releaseTimestamp": "2017-08-24T19:21:20.599Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.6.rc1", }, { "releaseTimestamp": "2017-09-08T00:47:42.201Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.6", }, { "releaseTimestamp": "2018-03-29T18:18:14.388Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.7", }, { "releaseTimestamp": "2018-11-27T20:09:36.347Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.0.7.1", }, { "releaseTimestamp": "2017-02-23T20:00:44.720Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.0.beta1", }, { "releaseTimestamp": "2017-03-20T18:57:56.595Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.0.rc1", }, { "releaseTimestamp": "2017-04-21T01:31:13.442Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.0.rc2", }, { "releaseTimestamp": "2017-04-27T21:00:47.670Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.0", }, { "releaseTimestamp": "2017-05-12T20:11:39.743Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.1", }, { "releaseTimestamp": "2017-06-20T17:03:49.322Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.2.rc1", }, { "releaseTimestamp": "2017-06-26T21:51:41.161Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.2", }, { "releaseTimestamp": "2017-07-19T19:38:05.393Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.3.rc1", }, { "releaseTimestamp": "2017-07-25T20:18:18.420Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.3.rc2", }, { "releaseTimestamp": "2017-07-31T19:12:53.241Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.3.rc3", }, { "releaseTimestamp": "2017-08-03T19:15:15.370Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.3", }, { "releaseTimestamp": "2017-08-24T19:37:37.728Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.4.rc1", }, { "releaseTimestamp": "2017-09-08T00:52:07.791Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.4", }, { "releaseTimestamp": "2018-02-01T19:00:37.520Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.5.rc1", }, { "releaseTimestamp": "2018-02-14T20:02:02.541Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.5", }, { "releaseTimestamp": "2018-03-29T18:29:03.149Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.6", }, { "releaseTimestamp": "2018-11-27T20:11:47.585Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.1.6.1", }, { "releaseTimestamp": "2017-11-27T19:19:13.809Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.0.beta1", }, { "releaseTimestamp": "2017-11-28T05:04:37.765Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.0.beta2", }, { "releaseTimestamp": "2018-01-30T23:38:56.843Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.0.rc1", }, { "releaseTimestamp": "2018-03-20T17:54:58.165Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.0.rc2", }, { "releaseTimestamp": "2018-04-09T20:07:04.834Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.0", }, { "releaseTimestamp": "2018-07-30T20:22:38.749Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.1.rc1", }, { "releaseTimestamp": "2018-08-07T21:44:52.020Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.1", }, { "releaseTimestamp": "2018-11-27T20:14:16.796Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.1.1", }, { "releaseTimestamp": "2018-11-28T22:55:23.827Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.2.rc1", }, { "releaseTimestamp": "2018-12-04T18:15:02.233Z", - "rubyPlatform": "ruby", - "rubyVersion": ">= 2.2.2", - "rubygemsVersion": ">= 1.8.11", "version": "5.2.2", }, ], diff --git a/lib/modules/datasource/rubygems/get.ts b/lib/modules/datasource/rubygems/get.ts index 064fa275c01477..87e658b86fc3c9 100644 --- a/lib/modules/datasource/rubygems/get.ts +++ b/lib/modules/datasource/rubygems/get.ts @@ -1,185 +1,208 @@ import { Marshal } from '@qnighy/marshal'; +import is from '@sindresorhus/is'; +import { z } from 'zod'; import { logger } from '../../../logger'; import { HttpError } from '../../../util/http'; +import { LooseArray } from '../../../util/schema-utils'; import { getQueryString, joinUrlParts, parseUrl } from '../../../util/url'; import { Datasource } from '../datasource'; import type { GetReleasesConfig, Release, ReleaseResult } from '../types'; -import type { - JsonGemVersions, - JsonGemsInfo, - MarshalledVersionInfo, -} from './types'; -const INFO_PATH = '/api/v1/gems'; -const VERSIONS_PATH = '/api/v1/versions'; -const DEPENDENCIES_PATH = '/api/v1/dependencies'; +const MarshalledVersionInfo = LooseArray( + z + .object({ + number: z.string(), + }) + .transform(({ number: version }) => ({ version })) +) + .transform((releases) => (releases.length === 0 ? null : { releases })) + .nullable() + .catch(null); + +const GemsInfo = z + .object({ + name: z.string().transform((x) => x.toLowerCase()), + version: z.string().nullish().catch(null), + changelog_uri: z.string().nullish().catch(null), + homepage_uri: z.string().nullish().catch(null), + source_code_uri: z.string().nullish().catch(null), + }) + .transform( + ({ + name: packageName, + version, + changelog_uri: changelogUrl, + homepage_uri: homepage, + source_code_uri: sourceUrl, + }) => ({ + packageName, + version, + changelogUrl, + homepage, + sourceUrl, + }) + ); +type GemsInfo = z.infer; + +const GemVersions = LooseArray( + z + .object({ + number: z.string(), + created_at: z.string(), + platform: z.string().nullable().catch(null), + ruby_version: z.string().nullable().catch(null), + rubygems_version: z.string().nullable().catch(null), + }) + .transform( + ({ + number: version, + created_at: releaseTimestamp, + platform, + ruby_version: rubyVersion, + rubygems_version: rubygemsVersion, + }): Release => { + const result: Release = { version, releaseTimestamp }; + const constraints: Record = {}; + + if (platform) { + constraints.platform = [platform]; + } + + if (rubyVersion) { + constraints.ruby = [rubyVersion]; + } + + if (rubygemsVersion) { + constraints.rubygems = [rubygemsVersion]; + } + + if (!is.emptyObject(constraints)) { + result.constraints = constraints; + } + + return result; + } + ) +); +type GemVersions = z.infer; export class InternalRubyGemsDatasource extends Datasource { constructor(override readonly id: string) { super(id); } - private knownFallbackHosts = ['rubygems.pkg.github.com', 'gitlab.com']; - - override getReleases({ - packageName, - registryUrl, - }: GetReleasesConfig): Promise { + async getReleases(config: GetReleasesConfig): Promise { + const registryUrl = config.registryUrl; // istanbul ignore if if (!registryUrl) { - return Promise.resolve(null); + return null; } + + const packageName = config.packageName.toLowerCase(); + const hostname = parseUrl(registryUrl)?.hostname; - if (hostname && this.knownFallbackHosts.includes(hostname)) { - return this.getDependencyFallback(packageName, registryUrl); - } - return this.getDependency(packageName, registryUrl); + return hostname === 'rubygems.pkg.github.com' || hostname === 'gitlab.com' + ? await this.getDependencyFallback(registryUrl, packageName) + : await this.getDependency(registryUrl, packageName); } async getDependencyFallback( - dependency: string, - registry: string + registryUrl: string, + packageName: string ): Promise { - logger.debug( - { dependency, api: DEPENDENCIES_PATH }, - 'RubyGems lookup for dependency' - ); - const info = await this.fetchBuffer( - dependency, - registry, - DEPENDENCIES_PATH - ); - if (!info || info.length === 0) { - return null; - } - const releases = info.map( - ({ number: version, platform: rubyPlatform }) => ({ - version, - rubyPlatform, - }) - ); - return { - releases, - sourceUrl: null, - }; + const path = joinUrlParts(registryUrl, `/api/v1/dependencies`); + const query = getQueryString({ gems: packageName }); + const url = `${path}?${query}`; + const { body: buffer } = await this.http.getBuffer(url); + const data = Marshal.parse(buffer); + return MarshalledVersionInfo.parse(data); } - async getDependency( - dependency: string, - registry: string - ): Promise { - logger.debug( - { dependency, api: INFO_PATH }, - 'RubyGems lookup for dependency' - ); - let info: JsonGemsInfo; - + async fetchGemsInfo( + registryUrl: string, + packageName: string + ): Promise { try { - info = await this.fetchJson(dependency, registry, INFO_PATH); - } catch (error) { + const { body } = await this.http.getJson( + joinUrlParts(registryUrl, '/api/v1/gems', `${packageName}.json`), + GemsInfo + ); + return body; + } catch (err) { // fallback to deps api on 404 - if (error instanceof HttpError && error.response?.statusCode === 404) { - return await this.getDependencyFallback(dependency, registry); + if (err instanceof HttpError && err.response?.statusCode === 404) { + return null; } - throw error; - } - - if (!info) { - logger.debug(`RubyGems package not found packageName: ${dependency} `); - return null; - } - - if (dependency.toLowerCase() !== info.name.toLowerCase()) { - logger.warn( - { lookup: dependency, returned: info.name }, - 'Lookup name does not match with returned.' - ); - return null; + throw err; } + } - let versions: JsonGemVersions[] = []; - let releases: Release[] = []; + async fetchGemVersions( + registryUrl: string, + packageName: string + ): Promise { try { - versions = await this.fetchJson(dependency, registry, VERSIONS_PATH); + const { body } = await this.http.getJson( + joinUrlParts(registryUrl, '/api/v1/versions', `${packageName}.json`), + GemVersions + ); + return body; } catch (err) { if (err.statusCode === 400 || err.statusCode === 404) { logger.debug( - { registry }, + { registry: registryUrl }, 'versions endpoint returns error - falling back to info endpoint' ); + return null; } else { throw err; } } + } - // TODO: invalid properties for `Release` see #11312 - - if (versions.length === 0 && info.version) { - logger.warn('falling back to the version from the info endpoint'); - releases = [ - { - version: info.version, - rubyPlatform: info.platform, - } as Release, - ]; - } else { - releases = versions.map( - ({ - number: version, - platform: rubyPlatform, - created_at: releaseTimestamp, - rubygems_version: rubygemsVersion, - ruby_version: rubyVersion, - }) => ({ - version, - rubyPlatform, - releaseTimestamp, - rubygemsVersion, - rubyVersion, - }) - ); + async getDependency( + registryUrl: string, + packageName: string + ): Promise { + const info = await this.fetchGemsInfo(registryUrl, packageName); + if (!info) { + return await this.getDependencyFallback(registryUrl, packageName); } - return { - releases, - homepage: info.homepage_uri, - sourceUrl: info.source_code_uri, - changelogUrl: info.changelog_uri, - }; - } + if (info.packageName !== packageName) { + logger.warn( + { lookup: packageName, returned: info.packageName }, + 'Lookup name does not match the returned name.' + ); + return null; + } - private async fetchJson( - dependency: string, - registry: string, - path: string - ): Promise { - const url = joinUrlParts(registry, path, `${dependency}.json`); + let releases: Release[] | null = null; + const gemVersions = await this.fetchGemVersions(registryUrl, packageName); + if (gemVersions?.length) { + releases = gemVersions; + } else if (info.version) { + releases = [{ version: info.version }]; + } - logger.trace({ registry, dependency, url }, `RubyGems lookup request`); - const response = (await this.http.getJson(url)) || { - body: undefined, - }; + if (!releases) { + return null; + } - return response.body; - } + const result: ReleaseResult = { releases }; - private async fetchBuffer( - dependency: string, - registry: string, - path: string - ): Promise { - const url = `${joinUrlParts(registry, path)}?${getQueryString({ - gems: dependency, - })}`; + if (info.changelogUrl) { + result.changelogUrl = info.changelogUrl; + } - logger.trace({ registry, dependency, url }, `RubyGems lookup request`); - const response = await this.http.getBuffer(url); + if (info.homepage) { + result.homepage = info.homepage; + } - // istanbul ignore if: needs tests - if (!response) { - return null; + if (info.sourceUrl) { + result.sourceUrl = info.sourceUrl; } - return Marshal.parse(response.body) as T; + return result; } } diff --git a/lib/modules/datasource/rubygems/index.spec.ts b/lib/modules/datasource/rubygems/index.spec.ts index 3f62ca70cb9014..6c7a23804c457e 100644 --- a/lib/modules/datasource/rubygems/index.spec.ts +++ b/lib/modules/datasource/rubygems/index.spec.ts @@ -26,12 +26,16 @@ describe('modules/datasource/rubygems/index', () => { httpMock .scope('https://firstparty.com') .get('/basepath/api/v1/gems/rails.json') - .reply(200); + .reply(200, { name: 'rails' }) + .get('/basepath/api/v1/versions/rails.json') + .reply(200, []); httpMock.scope('https://thirdparty.com').get('/versions').reply(404); httpMock .scope('https://thirdparty.com') .get('/api/v1/gems/rails.json') - .reply(200); + .reply(200, { name: 'rails' }) + .get('/api/v1/versions/rails.json') + .reply(200, []); expect( await getPkgReleases({ versioning: rubyVersioning.id, diff --git a/lib/modules/datasource/rubygems/types.ts b/lib/modules/datasource/rubygems/types.ts deleted file mode 100644 index 907ec3620f361e..00000000000000 --- a/lib/modules/datasource/rubygems/types.ts +++ /dev/null @@ -1,44 +0,0 @@ -/** - * see https://guides.rubygems.org/rubygems-org-api/#get---apiv1dependenciesgemscomma-delimited-gem-names - */ -export interface MarshalledVersionInfo { - name: string; - number: string; - platform: string; - dependencies: MarshalledDependency[]; -} - -export type MarshalledDependency = [name: string, version: string]; - -export interface JsonGemDependency { - name: string; - requirements: string; -} - -/** - * see https://guides.rubygems.org/rubygems-org-api/#get---apiv1gemsgem-namejsonyaml - */ -export interface JsonGemsInfo { - // FIXME: This property doesn't exist in api - changelog_uri: string; - dependencies: { - development: JsonGemDependency; - runtime: JsonGemDependency; - }; - homepage_uri: string; - name: string; - platform?: string; - source_code_uri: string; - version?: string; -} - -/** - * see https://guides.rubygems.org/rubygems-org-api/#get---apiv1versionsgem-namejsonyaml - */ -export interface JsonGemVersions { - created_at: string; - number: string; - platform: string; - rubygems_version: string; - ruby_version: string; -} diff --git a/lib/util/http/index.ts b/lib/util/http/index.ts index 21e13646f43044..e5dd4ac87e98b1 100644 --- a/lib/util/http/index.ts +++ b/lib/util/http/index.ts @@ -221,21 +221,14 @@ export class Http { return this.request(url, { ...options, method: 'head' }); } - protected requestBuffer( - url: string | URL, - httpOptions?: InternalHttpOptions - ): Promise | null> { - return this.request(url, { - ...httpOptions, - responseType: 'buffer', - }); - } - getBuffer( url: string, options: HttpOptions = {} - ): Promise | null> { - return this.requestBuffer(url, options); + ): Promise> { + return this.request(url, { + ...options, + responseType: 'buffer', + }); } private async requestJson( From 3fccfbe9277f59e01e31ea074f6a90772d04d637 Mon Sep 17 00:00:00 2001 From: Sebastian Poxhofer Date: Wed, 17 May 2023 10:15:12 +0200 Subject: [PATCH 58/74] feat(vulnerabilities): add option to add summary to dashboard (#21766) Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> Co-authored-by: Rhys Arkins --- docs/usage/configuration-options.md | 13 ++ lib/config/options/index.ts | 9 + lib/config/types.ts | 1 + .../repository/dependency-dashboard.spec.ts | 185 ++++++++++++++++++ .../repository/dependency-dashboard.ts | 105 ++++++++++ 5 files changed, 313 insertions(+) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 2ba14ca9de3e8e..dce0ff59865d63 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -703,6 +703,19 @@ You can configure this to `true` if you prefer Renovate to close an existing Dep The labels only get updated when the Dependency Dashboard issue updates its content and/or title. It is pointless to edit the labels, as Renovate bot restores the labels on each run. +## dependencyDashboardOSVVulnerabilitySummary + +Use this option to control if the Dependency Dashboard lists the OSV-sourced CVEs for your repository. +You can choose from: + +- `none` (default) do not list any CVEs +- `unresolved` list CVEs that have no fixes +- `all` list all CVEs + +This feature is independent of the `osvVulnerabilityAlerts` option. + +The source of these CVEs is [OSV.dev](https://osv.dev/). + ## dependencyDashboardTitle Configure this option if you prefer a different title for the Dependency Dashboard. diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts index 0e05c187ba51cf..a41fb0fdd7056b 100644 --- a/lib/config/options/index.ts +++ b/lib/config/options/index.ts @@ -520,6 +520,15 @@ const options: RenovateOptions[] = [ subType: 'string', default: null, }, + { + name: 'dependencyDashboardOSVVulnerabilitySummary', + description: + 'Control if the Dependency Dashboard issue lists CVEs supplied by [osv.dev](https://osv.dev).', + type: 'string', + allowedValues: ['none', 'all', 'unresolved'], + default: 'none', + experimental: true, + }, { name: 'configWarningReuseIssue', description: diff --git a/lib/config/types.ts b/lib/config/types.ts index ad5908b00e24b9..5c390b09c825a0 100644 --- a/lib/config/types.ts +++ b/lib/config/types.ts @@ -232,6 +232,7 @@ export interface RenovateConfig dependencyDashboardHeader?: string; dependencyDashboardFooter?: string; dependencyDashboardLabels?: string[]; + dependencyDashboardOSVVulnerabilitySummary?: 'none' | 'all' | 'unresolved'; packageFile?: string; packageRules?: PackageRule[]; postUpdateOptions?: string[]; diff --git a/lib/workers/repository/dependency-dashboard.spec.ts b/lib/workers/repository/dependency-dashboard.spec.ts index a2d9b97782cf83..809669c610824b 100644 --- a/lib/workers/repository/dependency-dashboard.spec.ts +++ b/lib/workers/repository/dependency-dashboard.spec.ts @@ -1,4 +1,5 @@ import { ERROR, WARN } from 'bunyan'; +import { codeBlock } from 'common-tags'; import { mock } from 'jest-mock-extended'; import { Fixtures } from '../../../test/fixtures'; import { @@ -21,8 +22,21 @@ import { import { regEx } from '../../util/regex'; import type { BranchConfig, BranchUpgradeConfig } from '../types'; import * as dependencyDashboard from './dependency-dashboard'; +import { getDashboardMarkdownVulnerabilities } from './dependency-dashboard'; import { PackageFiles } from './package-files'; +const createVulnerabilitiesMock = jest.fn(); +jest.mock('./process/vulnerabilities', () => { + return { + __esModule: true, + Vulnerabilities: class { + static create() { + return createVulnerabilitiesMock(); + } + }, + }; +}); + type PrUpgrade = BranchUpgradeConfig; const massageMdSpy = platform.massageMarkdown; @@ -1019,4 +1033,175 @@ describe('workers/repository/dependency-dashboard', () => { }); }); }); + + describe('getDashboardMarkdownVulnerabilities()', () => { + const packageFiles = Fixtures.getJson>( + './package-files.json' + ); + + it('return empty string if summary is empty', async () => { + const result = await getDashboardMarkdownVulnerabilities( + config, + packageFiles + ); + expect(result).toBeEmpty(); + }); + + it('return empty string if summary is set to none', async () => { + const result = await getDashboardMarkdownVulnerabilities( + { + ...config, + dependencyDashboardOSVVulnerabilitySummary: 'none', + }, + packageFiles + ); + expect(result).toBeEmpty(); + }); + + it('return no data section if summary is set to all and no vulnerabilities', async () => { + const fetchVulnerabilitiesMock = jest.fn(); + createVulnerabilitiesMock.mockResolvedValueOnce({ + fetchVulnerabilities: fetchVulnerabilitiesMock, + }); + + fetchVulnerabilitiesMock.mockResolvedValueOnce([]); + const result = await getDashboardMarkdownVulnerabilities( + { + ...config, + dependencyDashboardOSVVulnerabilitySummary: 'all', + }, + {} + ); + expect(result).toBe( + `## Vulnerabilities\n\nRenovate has not found any CVEs on [osv.dev](https://osv.dev).\n\n` + ); + }); + + it('return all vulnerabilities if set to all and disabled osvVulnerabilities', async () => { + const fetchVulnerabilitiesMock = jest.fn(); + createVulnerabilitiesMock.mockResolvedValueOnce({ + fetchVulnerabilities: fetchVulnerabilitiesMock, + }); + + fetchVulnerabilitiesMock.mockResolvedValueOnce([ + { + packageName: 'express', + depVersion: '4.17.3', + fixedVersion: '4.18.1', + packageFileConfig: { + manager: 'npm', + }, + vulnerability: { + id: 'GHSA-29mw-wpgm-hmr9', + }, + }, + { + packageName: 'cookie-parser', + depVersion: '1.4.6', + packageFileConfig: { + manager: 'npm', + }, + vulnerability: { + id: 'GHSA-35jh-r3h4-6jhm', + }, + }, + ]); + const result = await getDashboardMarkdownVulnerabilities( + { + ...config, + dependencyDashboardOSVVulnerabilitySummary: 'all', + osvVulnerabilityAlerts: true, + }, + packageFiles + ); + expect(result.trimEnd()).toBe(codeBlock`## Vulnerabilities + +\`1\`/\`2\` CVEs have Renovate fixes. +
npm +
+ +
undefined +
+ +
express +
+ +- [GHSA-29mw-wpgm-hmr9](https://osv.dev/vulnerability/GHSA-29mw-wpgm-hmr9) (fixed in 4.18.1) +
+
+ +
cookie-parser +
+ +- [GHSA-35jh-r3h4-6jhm](https://osv.dev/vulnerability/GHSA-35jh-r3h4-6jhm) +
+
+ +
+
+ +
+
`); + }); + + it('return unresolved vulnerabilities if set to "unresolved"', async () => { + const fetchVulnerabilitiesMock = jest.fn(); + createVulnerabilitiesMock.mockResolvedValueOnce({ + fetchVulnerabilities: fetchVulnerabilitiesMock, + }); + + fetchVulnerabilitiesMock.mockResolvedValueOnce([ + { + packageName: 'express', + depVersion: '4.17.3', + fixedVersion: '4.18.1', + packageFileConfig: { + manager: 'npm', + }, + vulnerability: { + id: 'GHSA-29mw-wpgm-hmr9', + }, + }, + { + packageName: 'cookie-parser', + depVersion: '1.4.6', + packageFileConfig: { + manager: 'npm', + }, + vulnerability: { + id: 'GHSA-35jh-r3h4-6jhm', + }, + }, + ]); + const result = await getDashboardMarkdownVulnerabilities( + { + ...config, + dependencyDashboardOSVVulnerabilitySummary: 'unresolved', + }, + packageFiles + ); + expect(result.trimEnd()).toBe(codeBlock`## Vulnerabilities + +\`1\`/\`2\` CVEs have possible Renovate fixes. +See [\`osvVulnerabilityAlerts\`](https://docs.renovatebot.com/configuration-options/#osvvulnerabilityalerts) to allow Renovate to supply fixes. +
npm +
+ +
undefined +
+ +
cookie-parser +
+ +- [GHSA-35jh-r3h4-6jhm](https://osv.dev/vulnerability/GHSA-35jh-r3h4-6jhm) +
+
+ +
+
+ +
+
`); + }); + }); }); diff --git a/lib/workers/repository/dependency-dashboard.ts b/lib/workers/repository/dependency-dashboard.ts index 6054f0e58e9573..15759ff691a181 100644 --- a/lib/workers/repository/dependency-dashboard.ts +++ b/lib/workers/repository/dependency-dashboard.ts @@ -11,6 +11,8 @@ import * as template from '../../util/template'; import type { BranchConfig, SelectAllConfig } from '../types'; import { getDepWarningsDashboard } from './errors-warnings'; import { PackageFiles } from './package-files'; +import type { Vulnerability } from './process/types'; +import { Vulnerabilities } from './process/vulnerabilities'; interface DependencyDashboard { dependencyDashboardChecks: Record; @@ -411,6 +413,9 @@ export async function ensureDependencyDashboard( 'This repository currently has no open or pending branches.\n\n'; } + // add CVE section + issueBody += await getDashboardMarkdownVulnerabilities(config, packageFiles); + // fit the detected dependencies section const footer = getFooter(config); issueBody += PackageFiles.getDashboardMarkdown( @@ -468,3 +473,103 @@ function getFooter(config: RenovateConfig): string { return footer; } + +export async function getDashboardMarkdownVulnerabilities( + config: RenovateConfig, + packageFiles: Record +): Promise { + let result = ''; + + if ( + is.nullOrUndefined(config.dependencyDashboardOSVVulnerabilitySummary) || + config.dependencyDashboardOSVVulnerabilitySummary === 'none' + ) { + return result; + } + + result += '## Vulnerabilities\n\n'; + + const vulnerabilityFetcher = await Vulnerabilities.create(); + const vulnerabilities = await vulnerabilityFetcher.fetchVulnerabilities( + config, + packageFiles + ); + + if (vulnerabilities.length === 0) { + result += + 'Renovate has not found any CVEs on [osv.dev](https://osv.dev).\n\n'; + return result; + } + + const unresolvedVulnerabilities = vulnerabilities.filter((value) => + is.nullOrUndefined(value.fixedVersion) + ); + const resolvedVulnerabilitiesLength = + vulnerabilities.length - unresolvedVulnerabilities.length; + + result += `\`${resolvedVulnerabilitiesLength}\`/\`${vulnerabilities.length}\``; + if (is.truthy(config.osvVulnerabilityAlerts)) { + result += ' CVEs have Renovate fixes.\n'; + } else { + result += + ' CVEs have possible Renovate fixes.\nSee [`osvVulnerabilityAlerts`](https://docs.renovatebot.com/configuration-options/#osvvulnerabilityalerts) to allow Renovate to supply fixes.\n'; + } + + let renderedVulnerabilities: Vulnerability[]; + switch (config.dependencyDashboardOSVVulnerabilitySummary) { + // filter vulnerabilities to display based on configuration + case 'unresolved': + renderedVulnerabilities = unresolvedVulnerabilities; + break; + default: + renderedVulnerabilities = vulnerabilities; + } + + const managerRecords: Record< + string, + Record> + > = {}; + for (const vulnerability of renderedVulnerabilities) { + const { manager, packageFile } = vulnerability.packageFileConfig; + if (is.nullOrUndefined(managerRecords[manager!])) { + managerRecords[manager!] = {}; + } + if (is.nullOrUndefined(managerRecords[manager!][packageFile])) { + managerRecords[manager!][packageFile] = {}; + } + if ( + is.nullOrUndefined( + managerRecords[manager!][packageFile][vulnerability.packageName] + ) + ) { + managerRecords[manager!][packageFile][vulnerability.packageName] = []; + } + managerRecords[manager!][packageFile][vulnerability.packageName].push( + vulnerability + ); + } + + for (const [manager, packageFileRecords] of Object.entries(managerRecords)) { + result += `
${manager}\n
\n\n`; + for (const [packageFile, packageNameRecords] of Object.entries( + packageFileRecords + )) { + result += `
${packageFile}\n
\n\n`; + for (const [packageName, cves] of Object.entries(packageNameRecords)) { + result += `
${packageName}\n
\n\n`; + for (const vul of cves) { + const id = vul.vulnerability.id; + const suffix = is.nonEmptyString(vul.fixedVersion) + ? ` (fixed in ${vul.fixedVersion})` + : ''; + result += `- [${id}](https://osv.dev/vulnerability/${id})${suffix}\n`; + } + result += `
\n
\n\n`; + } + result += `
\n
\n\n`; + } + result += `
\n
\n\n`; + } + + return result; +} From 1c13cf4302f5eba5d863532d611a92511375060e Mon Sep 17 00:00:00 2001 From: Michael Kriese Date: Wed, 17 May 2023 10:27:04 +0200 Subject: [PATCH 59/74] fix: update json-schema (#22262) --- tools/docs/schema.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tools/docs/schema.ts b/tools/docs/schema.ts index abc3c6cbb133db..ed40fbe3c25dcd 100644 --- a/tools/docs/schema.ts +++ b/tools/docs/schema.ts @@ -49,7 +49,12 @@ function createSingleConfig(option: RenovateOptions): Record { if (hasKey('format', option) && option.format) { temp.format = option.format; } - if (option.allowedValues) { + if (option.name === 'versioning') { + temp.oneOf = [ + { enum: option.allowedValues }, + { type: 'string', pattern: '^regex:' }, + ]; + } else if (option.allowedValues) { temp.enum = option.allowedValues; } } @@ -83,7 +88,13 @@ function addChildrenArrayInParents(): void { allOf: [ { type: 'object', - properties: {}, + properties: { + description: { + type: 'string', + description: + 'A custom description for this configuration object', + }, + }, }, ], }; From 9a87c3f7da532bb5ac24d759ae502272aec4fa4e Mon Sep 17 00:00:00 2001 From: Michael Kriese Date: Wed, 17 May 2023 10:27:10 +0200 Subject: [PATCH 60/74] fix(manager/nuget): return null for no deps (#22282) --- lib/modules/manager/nuget/extract.spec.ts | 14 ++++++++++---- lib/modules/manager/nuget/extract.ts | 11 ++++++++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/lib/modules/manager/nuget/extract.spec.ts b/lib/modules/manager/nuget/extract.spec.ts index ba8b9b84e7af84..5156a9fbd406b1 100644 --- a/lib/modules/manager/nuget/extract.spec.ts +++ b/lib/modules/manager/nuget/extract.spec.ts @@ -22,10 +22,10 @@ describe('modules/manager/nuget/extract', () => { GlobalConfig.reset(); }); - it('returns empty for invalid csproj', async () => { - expect(await extractPackageFile('nothing here', 'bogus', config)).toEqual( - { deps: [] } - ); + it('returns null for invalid csproj', async () => { + expect( + await extractPackageFile('nothing here', 'bogus', config) + ).toBeNull(); }); it('extracts package version dependency', async () => { @@ -347,6 +347,12 @@ describe('modules/manager/nuget/extract', () => { ).toBeNull(); }); + it('returns null for no deps', async () => { + expect( + await extractPackageFile('{"version": 1}', packageFile, config) + ).toBeNull(); + }); + it('does not throw', async () => { expect(await extractPackageFile('{{', packageFile, config)).toBeNull(); }); diff --git a/lib/modules/manager/nuget/extract.ts b/lib/modules/manager/nuget/extract.ts index 5fafd4c6598f57..2e329f9f387406 100644 --- a/lib/modules/manager/nuget/extract.ts +++ b/lib/modules/manager/nuget/extract.ts @@ -74,7 +74,7 @@ function extractDepsFromXml(xmlNode: XmlDocument): PackageDependency[] { export async function extractPackageFile( content: string, packageFile: string, - config: ExtractConfig + _config: ExtractConfig ): Promise { logger.trace({ packageFile }, 'nuget.extractPackageFile()'); @@ -99,7 +99,7 @@ export async function extractPackageFile( return null; } - for (const depName of Object.keys(manifest.tools)) { + for (const depName of Object.keys(manifest.tools ?? {})) { const tool = manifest.tools[depName]; const currentValue = tool.version; const dep: PackageDependency = { @@ -115,7 +115,7 @@ export async function extractPackageFile( deps.push(dep); } - return { deps }; + return deps.length ? { deps } : null; } if (packageFile.endsWith('global.json')) { @@ -134,6 +134,11 @@ export async function extractPackageFile( } catch (err) { logger.debug({ err }, `Failed to parse ${packageFile}`); } + + if (!deps.length) { + return null; + } + const res: PackageFileContent = { deps, packageFileVersion }; const lockFileName = getSiblingFileName(packageFile, 'packages.lock.json'); // istanbul ignore if From adacfcf30b67462627457c6bc69d9c74ff72238a Mon Sep 17 00:00:00 2001 From: IKEDA Sho Date: Wed, 17 May 2023 18:58:04 +0900 Subject: [PATCH 61/74] fix(cpanfile): support version ranges which are not v-prefixed (#22259) --- lib/modules/manager/cpanfile/extract.spec.ts | 37 ++++++++++++++++++++ lib/modules/manager/cpanfile/parser.ts | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/lib/modules/manager/cpanfile/extract.spec.ts b/lib/modules/manager/cpanfile/extract.spec.ts index 5235cf3a594f95..29d0042c3bdcd5 100644 --- a/lib/modules/manager/cpanfile/extract.spec.ts +++ b/lib/modules/manager/cpanfile/extract.spec.ts @@ -44,6 +44,13 @@ describe('modules/manager/cpanfile/extract', () => { requires 'URI', '1.59'; requires 'HTTP::Tiny', 0.034; requires "Capture::Tiny" => "0"; + + requires 'A', '== 1.1'; + requires 'AA', '== v1.1'; + requires 'B', '>= 1.2'; + requires 'BB', '>= v1.2'; + requires 'C', '> 1.3'; + requires 'CC', '> v1.3'; `, 'cpanfile' ) @@ -69,6 +76,36 @@ describe('modules/manager/cpanfile/extract', () => { depName: 'Capture::Tiny', currentValue: '0', }, + { + datasource: 'cpan', + depName: 'A', + currentValue: '1.1', + }, + { + datasource: 'cpan', + depName: 'AA', + currentValue: '1.1', + }, + { + datasource: 'cpan', + depName: 'B', + currentValue: '1.2', + }, + { + datasource: 'cpan', + depName: 'BB', + currentValue: '1.2', + }, + { + datasource: 'cpan', + depName: 'C', + currentValue: '1.3', + }, + { + datasource: 'cpan', + depName: 'CC', + currentValue: '1.3', + }, ], }); }); diff --git a/lib/modules/manager/cpanfile/parser.ts b/lib/modules/manager/cpanfile/parser.ts index da9014421700a7..cf2286eaa79b82 100644 --- a/lib/modules/manager/cpanfile/parser.ts +++ b/lib/modules/manager/cpanfile/parser.ts @@ -69,7 +69,7 @@ const moduleMatch = q q.alt(q.op(','), q.op('=>')).alt( q.num((ctx, { value: currentValue }) => ({ ...ctx, currentValue })), q.str((ctx, { value }) => { - const currentValue = value.replace(/^(?:\s*(?:==|>=|>))?\s*v/, ''); + const currentValue = value.replace(/^(?:\s*(?:==|>=|>))?\s*v?/, ''); return { ...ctx, currentValue }; }) ) From 5207da454689778276f3da90e0c102978f2a0327 Mon Sep 17 00:00:00 2001 From: Seiya Kokushi Date: Wed, 17 May 2023 18:59:17 +0900 Subject: [PATCH 62/74] feat(manager/asdf): support channel suffix on asdf-flutter (#22131) Co-authored-by: Michael Kriese --- lib/modules/manager/asdf/extract.spec.ts | 25 ++++++++++++++++++- .../manager/asdf/upgradeable-tooling.ts | 7 ++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/lib/modules/manager/asdf/extract.spec.ts b/lib/modules/manager/asdf/extract.spec.ts index 931981f69c5491..cb4e6b963383d2 100644 --- a/lib/modules/manager/asdf/extract.spec.ts +++ b/lib/modules/manager/asdf/extract.spec.ts @@ -60,7 +60,7 @@ ecspresso 2.1.0 elixir 1.14.1 elm 0.19.1 erlang 25.1.2 -flutter 3.7.6 +flutter 3.7.6-stable flux2 0.41.2 gauche 0.9.12 gohugo extended_0.104.3 @@ -516,6 +516,29 @@ dummy 1.2.3 }); }); + it('can handle flutter version channel', () => { + const withChannel = extractPackageFile('flutter 3.10.0-stable'); + expect(withChannel).toEqual({ + deps: [ + { + currentValue: '3.10.0', + datasource: 'flutter-version', + depName: 'flutter', + }, + ], + }); + const withoutChannel = extractPackageFile('flutter 3.10.0'); + expect(withoutChannel).toEqual({ + deps: [ + { + currentValue: '3.10.0', + datasource: 'flutter-version', + depName: 'flutter', + }, + ], + }); + }); + it('can handle java jre / jdk', () => { const jdkRes = extractPackageFile('java adoptopenjdk-16.0.0+36'); expect(jdkRes).toEqual({ diff --git a/lib/modules/manager/asdf/upgradeable-tooling.ts b/lib/modules/manager/asdf/upgradeable-tooling.ts index 3aefeb62c8dc30..a80a884030295d 100644 --- a/lib/modules/manager/asdf/upgradeable-tooling.ts +++ b/lib/modules/manager/asdf/upgradeable-tooling.ts @@ -1,3 +1,4 @@ +import { regEx } from '../../../util/regex'; import { DartVersionDatasource } from '../../datasource/dart-version'; import { DockerDatasource } from '../../datasource/docker'; import { FlutterVersionDatasource } from '../../datasource/flutter-version'; @@ -158,9 +159,11 @@ export const upgradeableTooling: Record = { }, flutter: { asdfPluginUrl: 'https://github.com/oae/asdf-flutter', - config: { + config: (version) => ({ datasource: FlutterVersionDatasource.id, - }, + // asdf-flutter plugin supports channel on version suffix. + currentValue: version.replace(regEx(/-(stable|beta|dev)$/), ''), + }), }, flux2: { asdfPluginUrl: 'https://github.com/tablexi/asdf-flux2.git', From 42e2b2743dfac2e9b9b02efde5f439b90601c795 Mon Sep 17 00:00:00 2001 From: Sergei Zharinov Date: Wed, 17 May 2023 17:57:36 +0300 Subject: [PATCH 63/74] fix(maven): Implement latest fix of the Maven versions (#22288) --- lib/modules/versioning/maven/compare.spec.ts | 27 +++++++++++++++++++- lib/modules/versioning/maven/compare.ts | 7 ++--- lib/modules/versioning/maven/index.spec.ts | 3 ++- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/lib/modules/versioning/maven/compare.spec.ts b/lib/modules/versioning/maven/compare.spec.ts index 64d545ad87a976..5de6a0185de6ba 100644 --- a/lib/modules/versioning/maven/compare.spec.ts +++ b/lib/modules/versioning/maven/compare.spec.ts @@ -92,6 +92,8 @@ describe('modules/versioning/maven/compare', () => { ${'Hoxton.RELEASE'} | ${'hoxton'} ${'Hoxton.SR1'} | ${'hoxton.sr-1'} ${'1_5ea'} | ${'1.0_5ea'} + ${'1.foo'} | ${'1-foo'} + ${'1.x'} | ${'1-x'} `('$x == $y', ({ x, y }) => { expect(compare(x, y)).toBe(0); expect(compare(y, x)).toBe(0); @@ -164,7 +166,6 @@ describe('modules/versioning/maven/compare', () => { ${'1'} | ${'1-sp'} ${'1-foo2'} | ${'1-foo10'} ${'1-m1'} | ${'1-milestone-2'} - ${'1.foo'} | ${'1-foo'} ${'1-foo'} | ${'1-1'} ${'1-alpha.1'} | ${'1-beta.1'} ${'1-1'} | ${'1.1'} @@ -195,6 +196,30 @@ describe('modules/versioning/maven/compare', () => { }); }); + // @see https://issues.apache.org/jira/browse/MNG-7644 + describe('MNG-7644', () => { + it.each` + qualifier + ${'abc'} + ${'alpha'} + ${'a'} + ${'beta'} + ${'b'} + ${'def'} + ${'milestone'} + ${'m'} + ${'RC'} + `('$qualifier', ({ qualifier }: { qualifier: string }) => { + // 1.0.0.X1 < 1.0.0-X2 for any string x + expect(compare(`1.0.0.${qualifier}1`, `1.0.0-${qualifier}2`)).toBe(-1); + + // 2.0.X == 2-X == 2.0.0.X for any string x + expect(compare(`2-${qualifier}`, `2.0.${qualifier}`)).toBe(0); // previously ordered, now equals + expect(compare(`2-${qualifier}`, `2.0.0.${qualifier}`)).toBe(0); // previously ordered, now equals + expect(compare(`2.0.${qualifier}`, `2.0.0.${qualifier}`)).toBe(0); // previously ordered, now equals + }); + }); + describe('Non-standard behavior', () => { describe('equality', () => { it.each` diff --git a/lib/modules/versioning/maven/compare.ts b/lib/modules/versioning/maven/compare.ts index f186d0fbfac286..f894c8e35c365d 100644 --- a/lib/modules/versioning/maven/compare.ts +++ b/lib/modules/versioning/maven/compare.ts @@ -123,7 +123,7 @@ function tokenize(versionStr: string, preserveMinorZeroes = false): Token[] { let result: Token[] = []; let leadingZero = true; iterateTokens(versionStr.toLowerCase().replace(regEx(/^v/i), ''), (token) => { - if (token.prefix === PREFIX_HYPHEN) { + if (token.prefix === PREFIX_HYPHEN || token.type === TYPE_QUALIFIER) { buf = []; } buf.push(token); @@ -154,10 +154,7 @@ function nullFor(token: Token): Token { } function commonOrder(token: Token): number { - if (token.prefix === PREFIX_DOT && token.type === TYPE_QUALIFIER) { - return 0; - } - if (token.prefix === PREFIX_HYPHEN && token.type === TYPE_QUALIFIER) { + if (token.type === TYPE_QUALIFIER) { return 1; } if (token.prefix === PREFIX_HYPHEN && token.type === TYPE_NUMBER) { diff --git a/lib/modules/versioning/maven/index.spec.ts b/lib/modules/versioning/maven/index.spec.ts index e0e012bbe3ba57..c0b23ac2eceb2d 100644 --- a/lib/modules/versioning/maven/index.spec.ts +++ b/lib/modules/versioning/maven/index.spec.ts @@ -112,12 +112,13 @@ describe('modules/versioning/maven/index', () => { ${'1'} | ${'(,1),(1,)'} | ${false} ${'1'} | ${'(0,1),(1,2)'} | ${false} ${'1.0.0.RC9.2'} | ${'(,1.0.0.RC9.2),(1.0.0.RC9.2,)'} | ${false} - ${'1.0.0-RC14'} | ${'(,1.0.0.RC9.2),(1.0.0.RC9.2,)'} | ${true} + ${'1.0.0.RC14'} | ${'(,1.0.0.RC9.2),(1.0.0.RC9.2,)'} | ${true} ${'0'} | ${''} | ${false} ${'1'} | ${'1'} | ${true} ${'1'} | ${'(1'} | ${false} ${'2.4.2'} | ${'2.4.2'} | ${true} ${'2.4.2'} | ${'= 2.4.2'} | ${false} + ${'1.2.3'} | ${'[1,2],[3,4]'} | ${true} `( 'matches("$version", "$range") === $expected', ({ version, range, expected }) => { From 71d64d23ce74e82b15de1e8067b55ff68e93fab8 Mon Sep 17 00:00:00 2001 From: Ivan Josipovic <9521987+IvanJosipovic@users.noreply.github.com> Date: Wed, 17 May 2023 08:43:10 -0700 Subject: [PATCH 64/74] feat: add sdk to monorepo:dotnet (#22290) --- lib/config/presets/internal/monorepo.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/config/presets/internal/monorepo.ts b/lib/config/presets/internal/monorepo.ts index 40c136d2fd828c..2ffd34584f2e7b 100644 --- a/lib/config/presets/internal/monorepo.ts +++ b/lib/config/presets/internal/monorepo.ts @@ -75,6 +75,7 @@ const repoGroups = { 'https://github.com/dotnet/extensions', 'https://github.com/dotnet/maui', 'https://github.com/dotnet/runtime', + 'https://github.com/dotnet/sdk', ], 'dotnet-azure-ad-identitymodel-extensions': 'https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet', From 98d98515ccae534a5b81534a9d6578e73c6870ba Mon Sep 17 00:00:00 2001 From: Gabriel-Ladzaretti <97394622+Gabriel-Ladzaretti@users.noreply.github.com> Date: Wed, 17 May 2023 20:47:16 +0300 Subject: [PATCH 65/74] refactor(config-error): generalize error issue creation for future reuse (#22289) --- lib/workers/repository/error-config.spec.ts | 49 ++++++++-- lib/workers/repository/error-config.ts | 103 +++++++++++++------- 2 files changed, 110 insertions(+), 42 deletions(-) diff --git a/lib/workers/repository/error-config.spec.ts b/lib/workers/repository/error-config.spec.ts index 5076984e35673d..109bc7aa7d374f 100644 --- a/lib/workers/repository/error-config.spec.ts +++ b/lib/workers/repository/error-config.spec.ts @@ -1,7 +1,13 @@ import { mock } from 'jest-mock-extended'; -import { RenovateConfig, getConfig, platform } from '../../../test/util'; +import { + RenovateConfig, + getConfig, + partial, + platform, +} from '../../../test/util'; import { GlobalConfig } from '../../config/global'; import { CONFIG_VALIDATION } from '../../constants/error-messages'; +import { logger } from '../../logger'; import type { Pr } from '../../modules/platform'; import { raiseConfigWarningIssue } from './error-config'; @@ -24,9 +30,16 @@ describe('workers/repository/error-config', () => { const error = new Error(CONFIG_VALIDATION); error.validationSource = 'package.json'; error.validationMessage = 'some-message'; + error.validationError = 'some-error'; platform.ensureIssue.mockResolvedValueOnce('created'); + const res = await raiseConfigWarningIssue(config, error); + expect(res).toBeUndefined(); + expect(logger.warn).toHaveBeenCalledWith( + { configError: error, res: 'created' }, + 'Configuration Warning' + ); }); it('creates issues (dryRun)', async () => { @@ -35,50 +48,74 @@ describe('workers/repository/error-config', () => { error.validationMessage = 'some-message'; platform.ensureIssue.mockResolvedValueOnce('created'); GlobalConfig.set({ dryRun: 'full' }); + const res = await raiseConfigWarningIssue(config, error); + expect(res).toBeUndefined(); + expect(logger.info).toHaveBeenCalledWith( + { configError: error }, + 'DRY-RUN: Would ensure configuration error issue' + ); }); it('handles onboarding', async () => { const error = new Error(CONFIG_VALIDATION); error.validationSource = 'package.json'; error.validationMessage = 'some-message'; - platform.getBranchPr.mockResolvedValue({ - ...mock(), + const pr = partial({ + title: 'onboarding', number: 1, state: 'open', }); + platform.getBranchPr.mockResolvedValue(pr); + const res = await raiseConfigWarningIssue(config, error); + expect(res).toBeUndefined(); + expect(platform.updatePr).toHaveBeenCalledWith( + expect.objectContaining({ prTitle: pr.title, number: pr.number }) + ); }); it('handles onboarding (dryRun)', async () => { const error = new Error(CONFIG_VALIDATION); error.validationSource = 'package.json'; error.validationMessage = 'some-message'; - platform.getBranchPr.mockResolvedValue({ - ...mock(), + const pr = partial({ number: 1, state: 'open', }); + platform.getBranchPr.mockResolvedValue(pr); GlobalConfig.set({ dryRun: 'full' }); + const res = await raiseConfigWarningIssue(config, error); + expect(res).toBeUndefined(); + expect(logger.info).toHaveBeenCalledWith( + `DRY-RUN: Would update PR #${pr.number}` + ); }); it('disable issue creation on config failure', async () => { + const notificationName = 'configErrorIssue'; const error = new Error(CONFIG_VALIDATION); error.validationSource = 'package.json'; error.validationMessage = 'some-message'; // config.suppressNotifications = ['deprecationWarningIssues'] - config.suppressNotifications = ['configErrorIssue']; + config.suppressNotifications = [notificationName]; platform.getBranchPr.mockResolvedValueOnce({ ...mock(), number: 1, state: '!open', }); + const res = await raiseConfigWarningIssue(config, error); + expect(res).toBeUndefined(); + expect(logger.info).toHaveBeenCalledWith( + { notificationName }, + 'Configuration failure, issues will be suppressed' + ); }); }); }); diff --git a/lib/workers/repository/error-config.ts b/lib/workers/repository/error-config.ts index 0fba9c00eefbbf..54a6d659e00f5c 100644 --- a/lib/workers/repository/error-config.ts +++ b/lib/workers/repository/error-config.ts @@ -2,61 +2,92 @@ import { GlobalConfig } from '../../config/global'; import type { RenovateConfig } from '../../config/types'; import { logger } from '../../logger'; -import { platform } from '../../modules/platform'; +import { Pr, platform } from '../../modules/platform'; import { regEx } from '../../util/regex'; -export async function raiseConfigWarningIssue( +export function raiseConfigWarningIssue( config: RenovateConfig, error: Error ): Promise { logger.debug('raiseConfigWarningIssue()'); - let body = `There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.\n\n`; + const title = `Action Required: Fix Renovate Configuration`; + const body = `There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.\n\n`; + const notificationName = 'configErrorIssue'; + return raiseWarningIssue(config, notificationName, title, body, error); +} + +async function raiseWarningIssue( + config: RenovateConfig, + notificationName: string, + title: string, + initialBody: string, + error: Error +): Promise { + let body = initialBody; if (error.validationSource) { body += `Location: \`${error.validationSource}\`\n`; } - body += `Error type: ${error.validationError!}\n`; + if (error.validationError) { + body += `Error type: ${error.validationError}\n`; + } if (error.validationMessage) { body += `Message: \`${error.validationMessage.replace( regEx(/`/g), "'" )}\`\n`; } + const pr = await platform.getBranchPr(config.onboardingBranch!); if (pr?.state === 'open') { - logger.debug('Updating onboarding PR with config error notice'); - body = `## Action Required: Fix Renovate Configuration\n\n${body}`; - body += `\n\nOnce you have resolved this problem (in this onboarding branch), Renovate will return to providing you with a preview of your repository's configuration.`; - if (GlobalConfig.get('dryRun')) { - logger.info(`DRY-RUN: Would update PR #${pr.number}`); - } else { - try { - await platform.updatePr({ - number: pr.number, - prTitle: config.onboardingPrTitle!, - prBody: body, - }); - } catch (err) /* istanbul ignore next */ { - logger.warn({ err }, 'Error updating onboarding PR'); - } - } - } else if (GlobalConfig.get('dryRun')) { - logger.info('DRY-RUN: Would ensure config error issue'); - } else if (config.suppressNotifications?.includes('configErrorIssue')) { + await handleOnboardingPr(pr, body); + return; + } + + if (GlobalConfig.get('dryRun')) { logger.info( - 'configErrorIssue - configuration failure, issues will be suppressed' + { configError: error }, + 'DRY-RUN: Would ensure configuration error issue' ); - } else { - const once = false; - const shouldReopen = config.configWarningReuseIssue; - const res = await platform.ensureIssue({ - title: `Action Required: Fix Renovate Configuration`, - body, - once, - shouldReOpen: shouldReopen, - confidential: config.confidential, + return; + } + + if (config.suppressNotifications?.includes(notificationName)) { + logger.info( + { notificationName }, + 'Configuration failure, issues will be suppressed' + ); + return; + } + + const res = await platform.ensureIssue({ + title, + body, + once: false, + shouldReOpen: config.configWarningReuseIssue, + confidential: config.confidential, + }); + if (res === 'created') { + logger.warn({ configError: error, res }, 'Configuration Warning'); + } +} + +async function handleOnboardingPr(pr: Pr, issueMessage: string): Promise { + logger.debug('Updating onboarding PR with config error notice'); + if (GlobalConfig.get('dryRun')) { + logger.info(`DRY-RUN: Would update PR #${pr.number}`); + return; + } + + let prBody = `## Action Required: Fix Renovate Configuration\n\n${issueMessage}`; + prBody += `\n\nOnce you have resolved this problem (in this onboarding branch), Renovate will return to providing you with a preview of your repository's configuration.`; + + try { + await platform.updatePr({ + number: pr.number, + prTitle: pr.title, + prBody, }); - if (res === 'created') { - logger.warn({ configError: error, res }, 'Config Warning'); - } + } catch (err) /* istanbul ignore next */ { + logger.warn({ err }, 'Error updating onboarding PR'); } } From b5d74a8ffbe394f6bb3b679c6fcbfc0881baa53f Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Wed, 17 May 2023 23:04:38 +0200 Subject: [PATCH 66/74] feat: allow previously merged PRs, but block automerge (#22279) --- .../repository/update/branch/index.spec.ts | 15 +++++++++++++++ lib/workers/repository/update/branch/index.ts | 15 +++++++++++++-- .../update/pr/body/config-description.spec.ts | 10 ++++++++++ .../update/pr/body/config-description.ts | 2 ++ lib/workers/types.ts | 1 + 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/lib/workers/repository/update/branch/index.spec.ts b/lib/workers/repository/update/branch/index.spec.ts index aaec7534c8499c..5a4ad531e64e75 100644 --- a/lib/workers/repository/update/branch/index.spec.ts +++ b/lib/workers/repository/update/branch/index.spec.ts @@ -289,6 +289,21 @@ describe('workers/repository/update/branch/index', () => { expect(scm.deleteBranch).toHaveBeenCalledTimes(1); }); + it('allows branch but disables automerge if merged PR found', async () => { + schedule.isScheduledNow.mockReturnValueOnce(false); + scm.branchExists.mockResolvedValue(true); + config.automerge = true; + config.updateType = 'digest'; + checkExisting.prAlreadyExisted.mockResolvedValueOnce( + partial({ + number: 13, + state: 'merged', + }) + ); + await branchWorker.processBranch(config); + expect(reuse.shouldReuseExistingBranch).toHaveBeenCalledTimes(0); + }); + it('skips branch if closed minor PR found', async () => { schedule.isScheduledNow.mockReturnValueOnce(false); scm.branchExists.mockResolvedValue(true); diff --git a/lib/workers/repository/update/branch/index.ts b/lib/workers/repository/update/branch/index.ts index 7b61df3f669645..562a08f61539f7 100644 --- a/lib/workers/repository/update/branch/index.ts +++ b/lib/workers/repository/update/branch/index.ts @@ -113,8 +113,19 @@ export async function processBranch( const artifactErrorTopic = emojify(':warning: Artifact update problem'); try { // Check if branch already existed - const existingPr = branchPr ? undefined : await prAlreadyExisted(config); - if (existingPr && !dependencyDashboardCheck) { + const existingPr = + !branchPr || config.automerge + ? await prAlreadyExisted(config) + : undefined; + if (existingPr?.state === 'merged') { + logger.debug(`Matching PR #${existingPr.number} was merged previously`); + if (config.automerge) { + logger.debug('Disabling automerge because PR was merged previously'); + config.automerge = false; + config.automergedPreviously = true; + } + } + if (!branchPr && existingPr && !dependencyDashboardCheck) { logger.debug( { prTitle: config.prTitle }, 'Closed PR already exists. Skipping branch.' diff --git a/lib/workers/repository/update/pr/body/config-description.spec.ts b/lib/workers/repository/update/pr/body/config-description.spec.ts index 9465753fd48e10..435c37258c3940 100644 --- a/lib/workers/repository/update/pr/body/config-description.spec.ts +++ b/lib/workers/repository/update/pr/body/config-description.spec.ts @@ -87,5 +87,15 @@ describe('workers/repository/update/pr/body/config-description', () => { const res = getPrConfigDescription({ ...config, automerge: true }); expect(res).toContain(`**Automerge**: Enabled.`); }); + + it('renders blocked automerge', () => { + const res = getPrConfigDescription({ + ...config, + automergedPreviously: true, + }); + expect(res).toContain( + `**Automerge**: Disabled because a matching PR was automerged previously.` + ); + }); }); }); diff --git a/lib/workers/repository/update/pr/body/config-description.ts b/lib/workers/repository/update/pr/body/config-description.ts index f3d0757c1a1f31..11d1aeed0186f8 100644 --- a/lib/workers/repository/update/pr/body/config-description.ts +++ b/lib/workers/repository/update/pr/body/config-description.ts @@ -15,6 +15,8 @@ export function getPrConfigDescription(config: BranchConfig): string { prBody += emojify(':vertical_traffic_light: **Automerge**: '); if (config.automerge) { prBody += 'Enabled.'; + } else if (config.automergedPreviously) { + prBody += 'Disabled because a matching PR was automerged previously.'; } else { prBody += 'Disabled by config. Please merge this manually once you are satisfied.'; diff --git a/lib/workers/types.ts b/lib/workers/types.ts index 3a14f60295b1ae..b2ba4e1c265a32 100644 --- a/lib/workers/types.ts +++ b/lib/workers/types.ts @@ -111,6 +111,7 @@ export interface BranchConfig PlatformPrOptions { automergeComment?: string; automergeType?: string; + automergedPreviously?: boolean; baseBranch: string; errors?: ValidationMessage[]; hasTypes?: boolean; From ffeb78415a5288264150701f03a0905bf28e2948 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Thu, 18 May 2023 11:26:12 +0530 Subject: [PATCH 67/74] feat(onboarding): merge onboardingBranch into baseBranch (#20893) Co-authored-by: Rhys Arkins Co-authored-by: Michael Kriese --- lib/util/cache/repository/types.ts | 3 +- lib/util/git/index.spec.ts | 6 + lib/util/git/index.ts | 14 +- .../onboarding/branch/check.spec.ts | 6 +- .../repository/onboarding/branch/check.ts | 19 +- .../onboarding/branch/index.spec.ts | 103 +++++-- .../repository/onboarding/branch/index.ts | 69 +++-- .../branch/onboarding-branch-cache.spec.ts | 258 +++++++++++++++--- .../branch/onboarding-branch-cache.ts | 88 +++++- .../onboarding/branch/rebase.spec.ts | 180 ------------ .../repository/onboarding/branch/rebase.ts | 89 ------ .../repository/onboarding/pr/index.spec.ts | 33 +-- lib/workers/repository/onboarding/pr/index.ts | 37 +-- 13 files changed, 489 insertions(+), 416 deletions(-) delete mode 100644 lib/workers/repository/onboarding/branch/rebase.spec.ts delete mode 100644 lib/workers/repository/onboarding/branch/rebase.ts diff --git a/lib/util/cache/repository/types.ts b/lib/util/cache/repository/types.ts index 6f5cbfe32601da..bbcb484864d822 100644 --- a/lib/util/cache/repository/types.ts +++ b/lib/util/cache/repository/types.ts @@ -27,9 +27,10 @@ export interface BranchUpgradeCache { } export interface OnboardingBranchCache { - onboardingBranch: string; defaultBranchSha: string; onboardingBranchSha: string; + isConflicted: boolean; + isModified: boolean; } export interface PrCache { diff --git a/lib/util/git/index.spec.ts b/lib/util/git/index.spec.ts index 1551fdca230c63..297e3691d0232d 100644 --- a/lib/util/git/index.spec.ts +++ b/lib/util/git/index.spec.ts @@ -344,6 +344,12 @@ describe('util/git/index', () => { expect(merged.all).toContain('renovate/future_branch'); }); + it('does not push if localOnly=true', async () => { + const pushSpy = jest.spyOn(SimpleGit.prototype, 'push'); + await git.mergeBranch('renovate/future_branch', true); + expect(pushSpy).toHaveBeenCalledTimes(0); + }); + it('should throw if branch merge throws', async () => { await expect(git.mergeBranch('not_found')).rejects.toThrow(); }); diff --git a/lib/util/git/index.ts b/lib/util/git/index.ts index 5d086bef8612ca..107c67decd1241 100644 --- a/lib/util/git/index.ts +++ b/lib/util/git/index.ts @@ -774,7 +774,10 @@ export async function deleteBranch(branchName: string): Promise { delete config.branchCommits[branchName]; } -export async function mergeBranch(branchName: string): Promise { +export async function mergeBranch( + branchName: string, + localOnly = false +): Promise { let status: StatusResult | undefined; try { await syncGit(); @@ -790,8 +793,13 @@ export async function mergeBranch(branchName: string): Promise { ]) ); status = await git.status(); - await gitRetry(() => git.merge(['--ff-only', branchName])); - await gitRetry(() => git.push('origin', config.currentBranch)); + if (localOnly) { + // merge commit, don't push to origin + await gitRetry(() => git.merge([branchName])); + } else { + await gitRetry(() => git.merge(['--ff-only', branchName])); + await gitRetry(() => git.push('origin', config.currentBranch)); + } incLimitedValue('Commits'); } catch (err) { logger.debug( diff --git a/lib/workers/repository/onboarding/branch/check.spec.ts b/lib/workers/repository/onboarding/branch/check.spec.ts index 74684f8f809352..7fd1d200bee611 100644 --- a/lib/workers/repository/onboarding/branch/check.spec.ts +++ b/lib/workers/repository/onboarding/branch/check.spec.ts @@ -27,9 +27,10 @@ describe('workers/repository/onboarding/branch/check', () => { it('skips normal onboarding check if onboardingCache is valid', async () => { cache.getCache.mockReturnValueOnce({ onboardingBranchCache: { - onboardingBranch: 'configure/renovate', defaultBranchSha: 'default-sha', onboardingBranchSha: 'onboarding-sha', + isConflicted: false, + isModified: false, }, }); git.getBranchCommit @@ -45,9 +46,10 @@ describe('workers/repository/onboarding/branch/check', () => { it('continues with normal logic if onboardingCache is invalid', async () => { cache.getCache.mockReturnValueOnce({ onboardingBranchCache: { - onboardingBranch: 'configure/renovate', defaultBranchSha: 'default-sha', onboardingBranchSha: 'onboarding-sha', + isConflicted: false, + isModified: false, }, }); scm.getFileList.mockResolvedValue([]); diff --git a/lib/workers/repository/onboarding/branch/check.ts b/lib/workers/repository/onboarding/branch/check.ts index bf3abf09f1fe03..0f7fca6870bd7a 100644 --- a/lib/workers/repository/onboarding/branch/check.ts +++ b/lib/workers/repository/onboarding/branch/check.ts @@ -52,8 +52,13 @@ function closedPrExists(config: RenovateConfig): Promise { export async function isOnboarded(config: RenovateConfig): Promise { logger.debug('isOnboarded()'); const title = `Action required: Add a Renovate config`; + // Repo is onboarded if global config is bypassing onboarding and does not require a // configuration file. + // The repo is considered "not onboarded" if: + // - An onboarding cache is present, and + // - The current default branch SHA matches the default SHA found in the cache + // Also if there is a closed pr skip using cache as it is outdated if (config.requireConfig === 'optional' && config.onboarding === false) { // Return early and avoid checking for config files return true; @@ -63,19 +68,17 @@ export async function isOnboarded(config: RenovateConfig): Promise { return true; } - const pr = await closedPrExists(config); + const closedOnboardingPr = await closedPrExists(config); const cache = getCache(); const onboardingBranchCache = cache?.onboardingBranchCache; // if onboarding cache is present and base branch has not been updated branch is not onboarded // if closed pr exists then presence of onboarding cache doesn't matter as we need to skip onboarding if ( config.onboarding && - !pr && + !closedOnboardingPr && onboardingBranchCache && onboardingBranchCache.defaultBranchSha === - getBranchCommit(config.defaultBranch!) && - onboardingBranchCache.onboardingBranchSha === - getBranchCommit(config.onboardingBranch!) + getBranchCommit(config.defaultBranch!) ) { logger.debug('Onboarding cache is valid. Repo is not onboarded'); return false; @@ -123,7 +126,7 @@ export async function isOnboarded(config: RenovateConfig): Promise { throw new Error(REPOSITORY_NO_CONFIG); } - if (!pr) { + if (!closedOnboardingPr) { logger.debug('Found no closed onboarding PR'); return false; } @@ -136,9 +139,9 @@ export async function isOnboarded(config: RenovateConfig): Promise { if (!config.suppressNotifications!.includes('onboardingClose')) { // ensure PR comment await ensureComment({ - number: pr.number, + number: closedOnboardingPr.number, topic: `Renovate is disabled`, - content: `Renovate is disabled due to lack of config. If you wish to reenable it, you can either (a) commit a config file to your base branch, or (b) rename this closed PR to trigger a replacement onboarding PR.`, + content: `Renovate is disabled due to lack of config. If you wish to re-enable it, you can either (a) commit a config file to your base branch, or (b) rename this closed PR to trigger a replacement onboarding PR.`, }); } throw new Error(REPOSITORY_CLOSED_ONBOARDING); diff --git a/lib/workers/repository/onboarding/branch/index.spec.ts b/lib/workers/repository/onboarding/branch/index.spec.ts index d9821294b5880b..ca37252be7d2fe 100644 --- a/lib/workers/repository/onboarding/branch/index.spec.ts +++ b/lib/workers/repository/onboarding/branch/index.spec.ts @@ -3,6 +3,7 @@ import { RenovateConfig, fs, getConfig, + git, mocked, platform, scm, @@ -17,17 +18,15 @@ import { logger } from '../../../../logger'; import type { Pr } from '../../../../modules/platform'; import * as memCache from '../../../../util/cache/memory'; import * as _cache from '../../../../util/cache/repository'; +import type { RepoCacheData } from '../../../../util/cache/repository/types'; import type { FileAddition } from '../../../../util/git/types'; import { OnboardingState } from '../common'; import * as _config from './config'; import * as _onboardingCache from './onboarding-branch-cache'; -import * as _rebase from './rebase'; import { checkOnboardingBranch } from '.'; -const rebase: any = _rebase; const configModule: any = _config; -jest.mock('../../../repository/onboarding/branch/rebase'); jest.mock('../../../../util/cache/repository'); jest.mock('../../../../util/fs'); jest.mock('../../../../util/git'); @@ -40,13 +39,6 @@ const onboardingCache = mocked(_onboardingCache); describe('workers/repository/onboarding/branch/index', () => { describe('checkOnboardingBranch', () => { let config: RenovateConfig; - const dummyCache = { - onboardingBranchCache: { - onboardingBranch: 'configure/renovate', - defaultBranchSha: 'default-sha', - onboardingBranchSha: 'onboarding-sha', - }, - }; beforeEach(() => { memCache.init(); @@ -177,7 +169,6 @@ describe('workers/repository/onboarding/branch/index', () => { }); it('detects repo is onboarded via file', async () => { - cache.getCache.mockReturnValue(dummyCache); scm.getFileList.mockResolvedValueOnce(['renovate.json']); const res = await checkOnboardingBranch(config); expect(res.repoIsOnboarded).toBeTrue(); @@ -261,20 +252,90 @@ describe('workers/repository/onboarding/branch/index', () => { await expect(checkOnboardingBranch(config)).rejects.toThrow(); }); - it('updates onboarding branch', async () => { - cache.getCache.mockReturnValue(dummyCache); + it('processes onboarding branch', async () => { scm.getFileList.mockResolvedValue(['package.json']); platform.findPr.mockResolvedValue(null); platform.getBranchPr.mockResolvedValueOnce(mock()); - rebase.rebaseOnboardingBranch.mockResolvedValueOnce('123test'); const res = await checkOnboardingBranch(config); expect(res.repoIsOnboarded).toBeFalse(); expect(res.branchList).toEqual(['renovate/configure']); - expect(scm.checkoutBranch).toHaveBeenCalledTimes(1); - expect(onboardingCache.setOnboardingCache).toHaveBeenCalledTimes(1); // update onboarding cache + expect(git.mergeBranch).toHaveBeenCalledOnce(); expect(scm.commitAndPush).toHaveBeenCalledTimes(0); }); + it('processes modified onboarding branch and invalidates extract cache', async () => { + const dummyCache = { + scan: { + master: { + sha: 'base_sha', + configHash: 'hash', + packageFiles: {}, + extractionFingerprints: {}, + }, + }, + } satisfies RepoCacheData; + cache.getCache.mockReturnValue(dummyCache); + platform.findPr.mockResolvedValue(null); + platform.getBranchPr.mockResolvedValueOnce(mock()); + git.getBranchCommit + .mockReturnValueOnce('default-sha') + .mockReturnValueOnce('new-onboarding-sha'); + onboardingCache.isOnboardingBranchModified.mockResolvedValueOnce(true); + onboardingCache.hasOnboardingBranchChanged.mockReturnValueOnce(true); + onboardingCache.isOnboardingBranchConflicted.mockResolvedValueOnce(false); + config.baseBranch = 'master'; + await checkOnboardingBranch(config); + expect(git.mergeBranch).toHaveBeenCalledOnce(); + expect(onboardingCache.setOnboardingCache).toHaveBeenCalledWith( + 'default-sha', + 'new-onboarding-sha', + false, + true + ); + expect(dummyCache).toMatchObject({ + scan: {}, + }); + }); + + it('skips processing conflicted onboarding branch', async () => { + scm.getFileList.mockResolvedValue(['package.json']); + platform.findPr.mockResolvedValue(null); + platform.getBranchPr.mockResolvedValueOnce(mock()); + platform.getBranchPr.mockResolvedValueOnce(mock()); + git.getBranchCommit + .mockReturnValueOnce('default-sha') + .mockReturnValueOnce('onboarding-sha'); + onboardingCache.isOnboardingBranchModified.mockResolvedValueOnce(true); + onboardingCache.hasOnboardingBranchChanged.mockReturnValueOnce(true); + onboardingCache.isOnboardingBranchConflicted.mockResolvedValueOnce(true); + await checkOnboardingBranch(config); + expect(git.mergeBranch).not.toHaveBeenCalled(); + expect(onboardingCache.setOnboardingCache).toHaveBeenCalledWith( + 'default-sha', + 'onboarding-sha', + true, + true + ); + }); + + it('sets onboarding cache for existing onboarding branch', async () => { + scm.getFileList.mockResolvedValue(['package.json']); + platform.findPr.mockResolvedValue(null); + platform.getBranchPr.mockResolvedValueOnce(mock()); + git.getBranchCommit + .mockReturnValueOnce('default-sha') + .mockReturnValueOnce('onboarding-sha'); + onboardingCache.isOnboardingBranchModified.mockResolvedValueOnce(false); + await checkOnboardingBranch(config); + expect(git.mergeBranch).toHaveBeenCalled(); + expect(onboardingCache.setOnboardingCache).toHaveBeenCalledWith( + 'default-sha', + 'onboarding-sha', + false, + false + ); + }); + describe('tests onboarding rebase/retry checkbox handling', () => { beforeEach(() => { GlobalConfig.set({ platform: 'github' }); @@ -282,7 +343,6 @@ describe('workers/repository/onboarding/branch/index', () => { OnboardingState.prUpdateRequested = false; scm.getFileList.mockResolvedValueOnce(['package.json']); platform.findPr.mockResolvedValueOnce(null); - rebase.rebaseOnboardingBranch.mockResolvedValueOnce(null); }); it('detects unsupported platfom', async () => { @@ -296,7 +356,7 @@ describe('workers/repository/onboarding/branch/index', () => { `Platform '${pl}' does not support extended markdown` ); expect(OnboardingState.prUpdateRequested).toBeTrue(); - expect(scm.checkoutBranch).toHaveBeenCalledTimes(1); + expect(git.mergeBranch).toHaveBeenCalledOnce(); expect(scm.commitAndPush).toHaveBeenCalledTimes(0); }); @@ -310,7 +370,7 @@ describe('workers/repository/onboarding/branch/index', () => { `No rebase checkbox was found in the onboarding PR` ); expect(OnboardingState.prUpdateRequested).toBeTrue(); - expect(scm.checkoutBranch).toHaveBeenCalledTimes(1); + expect(git.mergeBranch).toHaveBeenCalledOnce(); expect(scm.commitAndPush).toHaveBeenCalledTimes(0); }); @@ -324,8 +384,7 @@ describe('workers/repository/onboarding/branch/index', () => { `Manual onboarding PR update requested` ); expect(OnboardingState.prUpdateRequested).toBeTrue(); - ``; - expect(scm.checkoutBranch).toHaveBeenCalledTimes(1); + expect(git.mergeBranch).toHaveBeenCalledOnce(); expect(scm.commitAndPush).toHaveBeenCalledTimes(0); }); @@ -336,7 +395,7 @@ describe('workers/repository/onboarding/branch/index', () => { await checkOnboardingBranch(config); expect(OnboardingState.prUpdateRequested).toBeFalse(); - expect(scm.checkoutBranch).toHaveBeenCalledTimes(1); + expect(git.mergeBranch).toHaveBeenCalledOnce(); expect(scm.commitAndPush).toHaveBeenCalledTimes(0); }); }); diff --git a/lib/workers/repository/onboarding/branch/index.ts b/lib/workers/repository/onboarding/branch/index.ts index e131f8069a4a66..a4853d1fec8eca 100644 --- a/lib/workers/repository/onboarding/branch/index.ts +++ b/lib/workers/repository/onboarding/branch/index.ts @@ -7,9 +7,13 @@ import { REPOSITORY_NO_PACKAGE_FILES, } from '../../../../constants/error-messages'; import { logger } from '../../../../logger'; -import { Pr, platform } from '../../../../modules/platform'; -import { scm } from '../../../../modules/platform/scm'; -import { getBranchCommit, setGitAuthor } from '../../../../util/git'; +import type { Pr } from '../../../../modules/platform'; +import { getCache } from '../../../../util/cache/repository'; +import { + getBranchCommit, + mergeBranch, + setGitAuthor, +} from '../../../../util/git'; import { extractAllDependencies } from '../../extract'; import { mergeRenovateConfig } from '../../init/merge'; import { OnboardingState } from '../common'; @@ -18,9 +22,11 @@ import { getOnboardingConfig } from './config'; import { createOnboardingBranch } from './create'; import { deleteOnboardingCache, + hasOnboardingBranchChanged, + isOnboardingBranchConflicted, + isOnboardingBranchModified, setOnboardingCache, } from './onboarding-branch-cache'; -import { rebaseOnboardingBranch } from './rebase'; export async function checkOnboardingBranch( config: RenovateConfig @@ -28,6 +34,8 @@ export async function checkOnboardingBranch( logger.debug('checkOnboarding()'); logger.trace({ config }); let onboardingBranch = config.onboardingBranch; + let isConflicted = false; + let isModified = false; const repoIsOnboarded = await isOnboarded(config); if (repoIsOnboarded) { logger.debug('Repo is onboarded'); @@ -48,25 +56,17 @@ export async function checkOnboardingBranch( handleOnboardingManualRebase(onboardingPr); } logger.debug('Onboarding PR already exists'); - const { rawConfigHash } = onboardingPr.bodyStruct ?? {}; - const commit = await rebaseOnboardingBranch(config, rawConfigHash); - if (commit) { - logger.info( - { branch: config.onboardingBranch, commit, onboarding: true }, - 'Branch updated' - ); - // update onboarding cache - setOnboardingCache( - config.onboardingBranch!, - getBranchCommit(config.defaultBranch!)!, - commit + isModified = await isOnboardingBranchModified(config.onboardingBranch!); + if (isModified) { + if (hasOnboardingBranchChanged(config.onboardingBranch!)) { + invalidateExtractCache(config.baseBranch!); + } + isConflicted = await isOnboardingBranchConflicted( + config.baseBranch!, + config.onboardingBranch! ); } - // istanbul ignore if - if (platform.refreshPr) { - await platform.refreshPr(onboardingPr.number); - } } else { logger.debug('Onboarding PR does not exist'); const onboardingConfig = await getOnboardingConfig(config); @@ -93,20 +93,22 @@ export async function checkOnboardingBranch( { branch: onboardingBranch, commit, onboarding: true }, 'Branch created' ); - - // set onboarding branch cache - setOnboardingCache( - config.onboardingBranch!, - getBranchCommit(config.defaultBranch!)!, - commit - ); } } if (!GlobalConfig.get('dryRun')) { - logger.debug('Checkout onboarding branch.'); // TODO #7154 - await scm.checkoutBranch(onboardingBranch!); + if (!isConflicted) { + logger.debug('Merge onboarding branch in default branch'); + await mergeBranch(onboardingBranch!, true); + } } + setOnboardingCache( + getBranchCommit(config.defaultBranch!)!, + getBranchCommit(onboardingBranch!)!, + isConflicted, + isModified + ); + // TODO #7154 const branchList = [onboardingBranch!]; return { ...config, repoIsOnboarded, onboardingBranch, branchList }; @@ -126,3 +128,12 @@ function handleOnboardingManualRebase(onboardingPr: Pr): void { OnboardingState.prUpdateRequested = true; } } + +function invalidateExtractCache(baseBranch: string): void { + const cache = getCache(); + cache.scan ||= {}; + + if (cache.scan?.[baseBranch]) { + delete cache.scan[baseBranch]; + } +} diff --git a/lib/workers/repository/onboarding/branch/onboarding-branch-cache.spec.ts b/lib/workers/repository/onboarding/branch/onboarding-branch-cache.spec.ts index 10307e5a3ec374..40cb3017741454 100644 --- a/lib/workers/repository/onboarding/branch/onboarding-branch-cache.spec.ts +++ b/lib/workers/repository/onboarding/branch/onboarding-branch-cache.spec.ts @@ -1,61 +1,235 @@ -import { mocked } from '../../../../../test/util'; +import { git, mocked, scm } from '../../../../../test/util'; import * as _cache from '../../../../util/cache/repository'; import type { RepoCacheData } from '../../../../util/cache/repository/types'; import { deleteOnboardingCache, + hasOnboardingBranchChanged, + isOnboardingBranchConflicted, + isOnboardingBranchModified, setOnboardingCache, } from './onboarding-branch-cache'; jest.mock('../../../../util/cache/repository'); +jest.mock('../../../../util/git'); const cache = mocked(_cache); describe('workers/repository/onboarding/branch/onboarding-branch-cache', () => { - it('sets new cache', () => { - const dummyCache = {} satisfies RepoCacheData; - cache.getCache.mockReturnValueOnce(dummyCache); - setOnboardingCache('configure/renovate', 'default-sha', 'onboarding-sha'); - expect(dummyCache).toEqual({ - onboardingBranchCache: { - onboardingBranch: 'configure/renovate', - defaultBranchSha: 'default-sha', - onboardingBranchSha: 'onboarding-sha', - }, + describe('setOnboardingCache', () => { + it('does not create new cache', () => { + const dummyCache = {} satisfies RepoCacheData; + cache.getCache.mockReturnValue(dummyCache); + setOnboardingCache('default-sha', null as never, false, false); + expect(dummyCache).toEqual({}); + }); + + it('sets new cache', () => { + const dummyCache = {} satisfies RepoCacheData; + cache.getCache.mockReturnValue(dummyCache); + setOnboardingCache('default-sha', 'onboarding-sha', false, false); + expect(dummyCache).toEqual({ + onboardingBranchCache: { + defaultBranchSha: 'default-sha', + onboardingBranchSha: 'onboarding-sha', + isConflicted: false, + isModified: false, + }, + }); + }); + + it('updates old cache', () => { + const dummyCache = { + onboardingBranchCache: { + defaultBranchSha: 'default-sha', + onboardingBranchSha: 'onboarding-sha', + isConflicted: false, + isModified: false, + }, + } satisfies RepoCacheData; + cache.getCache.mockReturnValue(dummyCache); + setOnboardingCache('default-sha-1', 'onboarding-sha-1', false, true); + expect(dummyCache).toEqual({ + onboardingBranchCache: { + defaultBranchSha: 'default-sha-1', + onboardingBranchSha: 'onboarding-sha-1', + isConflicted: false, + isModified: true, + }, + }); + }); + }); + + describe('deleteOnboardingCache', () => { + it('deletes cache', () => { + const dummyCache = { + onboardingBranchCache: { + defaultBranchSha: 'default-sha', + onboardingBranchSha: 'onboarding-sha', + isConflicted: false, + isModified: false, + }, + } satisfies RepoCacheData; + cache.getCache.mockReturnValue(dummyCache); + deleteOnboardingCache(); + expect(dummyCache.onboardingBranchCache).toBeUndefined(); }); }); - it('updates old cache', () => { - const dummyCache = { - onboardingBranchCache: { - onboardingBranch: 'configure/renovate', - defaultBranchSha: 'default-sha', - onboardingBranchSha: 'onboarding-sha', - }, - } satisfies RepoCacheData; - cache.getCache.mockReturnValueOnce(dummyCache); - setOnboardingCache( - 'configure/renovate', - 'default-sha-1', - 'onboarding-sha-1' - ); - expect(dummyCache).toEqual({ - onboardingBranchCache: { - onboardingBranch: 'configure/renovate', - defaultBranchSha: 'default-sha-1', - onboardingBranchSha: 'onboarding-sha-1', - }, + describe('hasOnboardingBranchChanged()', () => { + it('return true if cache is absent', () => { + cache.getCache.mockReturnValueOnce({}); + git.getBranchCommit.mockReturnValueOnce('onboarding-sha'); + expect(hasOnboardingBranchChanged('configure/renovate')).toBeTrue(); + }); + + it('returns true', () => { + const dummyCache = { + onboardingBranchCache: { + defaultBranchSha: 'default-sha', + onboardingBranchSha: 'old-onboarding-sha', + isConflicted: false, + isModified: false, + }, + } satisfies RepoCacheData; + cache.getCache.mockReturnValueOnce(dummyCache); + git.getBranchCommit.mockReturnValueOnce('new-onboarding-sha'); + expect(hasOnboardingBranchChanged('configure/renovate')).toBeTrue(); + }); + + it('returns false', () => { + const dummyCache = { + onboardingBranchCache: { + defaultBranchSha: 'default-sha', + onboardingBranchSha: 'onboarding-sha', + isConflicted: false, + isModified: false, + }, + } satisfies RepoCacheData; + cache.getCache.mockReturnValueOnce(dummyCache); + git.getBranchCommit.mockReturnValueOnce('onboarding-sha'); + expect(hasOnboardingBranchChanged('configure/renovate')).toBeFalse(); + }); + + it('returns false when branch is modified but has not changed since last run', () => { + const dummyCache = { + onboardingBranchCache: { + defaultBranchSha: 'default-sha', + onboardingBranchSha: 'onboarding-sha', + isConflicted: false, + isModified: true, + }, + } satisfies RepoCacheData; + cache.getCache.mockReturnValueOnce(dummyCache); + git.getBranchCommit.mockReturnValueOnce('onboarding-sha'); + expect(hasOnboardingBranchChanged('configure/renovate')).toBeFalse(); }); }); - it('deletes cache', () => { - const dummyCache = { - onboardingBranchCache: { - onboardingBranch: 'configure/renovate', - defaultBranchSha: 'default-sha', - onboardingBranchSha: 'onboarding-sha', - }, - } satisfies RepoCacheData; - cache.getCache.mockReturnValueOnce(dummyCache); - deleteOnboardingCache(); - expect(dummyCache.onboardingBranchCache).toBeUndefined(); + describe('isOnboardingBranchModified()', () => { + it('falls back to git if cache is absent', async () => { + cache.getCache.mockReturnValueOnce({}); + git.getBranchCommit.mockReturnValueOnce('onboarding-sha'); + scm.isBranchModified.mockResolvedValueOnce(false); + expect( + await isOnboardingBranchModified('configure/renovate') + ).toBeFalse(); + }); + + it('falls back to git if onboarding branch is updated', async () => { + const dummyCache = { + onboardingBranchCache: { + defaultBranchSha: 'default-sha', + onboardingBranchSha: 'old-onboarding-sha', + isConflicted: false, + isModified: false, + }, + } satisfies RepoCacheData; + cache.getCache.mockReturnValueOnce(dummyCache); + git.getBranchCommit.mockReturnValueOnce('new-onboarding-sha'); + scm.isBranchModified.mockResolvedValueOnce(true); + expect(await isOnboardingBranchModified('configure/renovate')).toBeTrue(); + }); + + it('returns cached value', async () => { + const dummyCache = { + onboardingBranchCache: { + defaultBranchSha: 'default-sha', + onboardingBranchSha: 'onboarding-sha', + isConflicted: true, + isModified: true, + }, + } satisfies RepoCacheData; + cache.getCache.mockReturnValueOnce(dummyCache); + git.getBranchCommit.mockReturnValueOnce('onboarding-sha'); + expect(await isOnboardingBranchModified('configure/renovate')).toBeTrue(); + }); + }); + + describe('isOnboardingBranchConflicted()', () => { + it('falls back to git if cache is absent', async () => { + cache.getCache.mockReturnValueOnce({}); + git.getBranchCommit + .mockReturnValueOnce('onboarding-sha') + .mockReturnValueOnce('default-sha'); + scm.isBranchConflicted.mockResolvedValueOnce(false); + expect( + await isOnboardingBranchConflicted('master', 'configure/renovate') + ).toBeFalse(); + }); + + it('falls back to git if default branch is updated', async () => { + const dummyCache = { + onboardingBranchCache: { + defaultBranchSha: 'old-default-sha', + onboardingBranchSha: 'onboarding-sha', + isConflicted: false, + isModified: false, + }, + } satisfies RepoCacheData; + cache.getCache.mockReturnValueOnce(dummyCache); + git.getBranchCommit + .mockReturnValueOnce('onboarding-sha') + .mockReturnValueOnce('new-default-sha'); + scm.isBranchConflicted.mockResolvedValueOnce(false); + expect( + await isOnboardingBranchConflicted('master', 'configure/renovate') + ).toBeFalse(); + }); + + it('falls back to git if onboarding branch is modified', async () => { + const dummyCache = { + onboardingBranchCache: { + defaultBranchSha: 'default-sha', + onboardingBranchSha: 'old-onboarding-sha', + isConflicted: false, + isModified: false, + }, + } satisfies RepoCacheData; + cache.getCache.mockReturnValueOnce(dummyCache); + git.getBranchCommit + .mockReturnValueOnce('new-onboarding-sha') + .mockReturnValueOnce('default-sha'); + scm.isBranchConflicted.mockResolvedValueOnce(false); + expect( + await isOnboardingBranchConflicted('master', 'configure/renovate') + ).toBeFalse(); + }); + + it('returns cached value', async () => { + const dummyCache = { + onboardingBranchCache: { + defaultBranchSha: 'default-sha', + onboardingBranchSha: 'onboarding-sha', + isConflicted: true, + isModified: true, + }, + } satisfies RepoCacheData; + cache.getCache.mockReturnValueOnce(dummyCache); + git.getBranchCommit + .mockReturnValueOnce('onboarding-sha') + .mockReturnValueOnce('default-sha'); + expect( + await isOnboardingBranchConflicted('master', 'configure/renovate') + ).toBeTrue(); + }); }); }); diff --git a/lib/workers/repository/onboarding/branch/onboarding-branch-cache.ts b/lib/workers/repository/onboarding/branch/onboarding-branch-cache.ts index a6ecfcb29677b2..9f7ebd1b47cf1b 100644 --- a/lib/workers/repository/onboarding/branch/onboarding-branch-cache.ts +++ b/lib/workers/repository/onboarding/branch/onboarding-branch-cache.ts @@ -1,21 +1,37 @@ +import is from '@sindresorhus/is'; import { logger } from '../../../../logger'; +import { scm } from '../../../../modules/platform/scm'; import { getCache } from '../../../../util/cache/repository'; +import { getBranchCommit } from '../../../../util/git'; export function setOnboardingCache( - onboardingBranch: string, defaultBranchSha: string, - onboardingBranchSha: string + onboardingBranchSha: string, + isConflicted: boolean, + isModified: boolean ): void { + // do not update cache if commit is null/undefined + if ( + !( + is.nonEmptyString(defaultBranchSha) && + is.nonEmptyString(onboardingBranchSha) + ) + ) { + logger.debug('Onboarding cache not updated'); + return; + } + const cache = getCache(); const onboardingCache = { - onboardingBranch, defaultBranchSha, onboardingBranchSha, + isConflicted, + isModified, }; if (cache.onboardingBranchCache) { - logger.debug('Update Onboarding Cache'); + logger.debug({ onboardingCache }, 'Update Onboarding Cache'); } else { - logger.debug('Create Onboarding Cache'); + logger.debug({ onboardingCache }, 'Create Onboarding Cache'); } cache.onboardingBranchCache = onboardingCache; } @@ -28,3 +44,65 @@ export function deleteOnboardingCache(): void { delete cache.onboardingBranchCache; } } + +// checks if onboarding branch has been modified since last run +// return true if cache isn't present +export function hasOnboardingBranchChanged(onboardingBranch: string): boolean { + const cache = getCache(); + const onboardingSha = getBranchCommit(onboardingBranch); + + if (cache.onboardingBranchCache) { + return onboardingSha !== cache.onboardingBranchCache.onboardingBranchSha; + } + return true; +} + +// checks if onboarding branch has been modified by user +// once set to true it stays true as we do not rebase onboarding branches anymore (this feature will be added in future though) +export async function isOnboardingBranchModified( + onboardingBranch: string +): Promise { + const cache = getCache(); + const onboardingCache = cache.onboardingBranchCache; + const onboardingSha = getBranchCommit(onboardingBranch); + let isModified = false; + + if ( + onboardingCache && + onboardingSha === onboardingCache.onboardingBranchSha && + !is.undefined(onboardingCache.isModified) + ) { + return onboardingCache.isModified; + } else { + isModified = await scm.isBranchModified(onboardingBranch); + } + + return isModified; +} + +export async function isOnboardingBranchConflicted( + defaultBranch: string, + onboardingBranch: string +): Promise { + const cache = getCache(); + const onboardingCache = cache.onboardingBranchCache; + const onboardingSha = getBranchCommit(onboardingBranch); + const defaultBranchSha = getBranchCommit(defaultBranch); + let isConflicted = false; + + if ( + onboardingCache && + defaultBranchSha === onboardingCache.defaultBranchSha && + onboardingSha === onboardingCache.onboardingBranchSha && + !is.undefined(onboardingCache.isConflicted) + ) { + return onboardingCache.isConflicted; + } else { + isConflicted = await scm.isBranchConflicted( + defaultBranch, + onboardingBranch + ); + } + + return isConflicted; +} diff --git a/lib/workers/repository/onboarding/branch/rebase.spec.ts b/lib/workers/repository/onboarding/branch/rebase.spec.ts deleted file mode 100644 index 1bb98d5e05c17d..00000000000000 --- a/lib/workers/repository/onboarding/branch/rebase.spec.ts +++ /dev/null @@ -1,180 +0,0 @@ -import { RenovateConfig, getConfig, git, scm } from '../../../../../test/util'; -import { GlobalConfig } from '../../../../config/global'; -import * as memCache from '../../../../util/cache/memory'; -import { toSha256 } from '../../../../util/hasha'; -import { OnboardingState } from '../common'; -import { rebaseOnboardingBranch } from './rebase'; - -jest.mock('../../../../util/git'); - -describe('workers/repository/onboarding/branch/rebase', () => { - beforeAll(() => { - GlobalConfig.set({ - localDir: '', - }); - }); - - describe('rebaseOnboardingBranch()', () => { - let config: RenovateConfig; - const hash = ''; - - beforeEach(() => { - memCache.init(); - jest.resetAllMocks(); - OnboardingState.prUpdateRequested = false; - config = { - ...getConfig(), - repository: 'some/repo', - }; - }); - - it('does not rebase modified branch', async () => { - scm.isBranchModified.mockResolvedValueOnce(true); - await rebaseOnboardingBranch(config, hash); - expect(scm.commitAndPush).toHaveBeenCalledTimes(0); - }); - - it.each` - checkboxEnabled - ${true} - ${false} - `( - 'does nothing if branch is up to date ' + - '(config.onboardingRebaseCheckbox="$checkboxEnabled")', - async ({ checkboxEnabled }) => { - config.onboardingRebaseCheckbox = checkboxEnabled; - const contents = - JSON.stringify(getConfig().onboardingConfig, null, 2) + '\n'; - git.getFile - .mockResolvedValueOnce(contents) // package.json - .mockResolvedValueOnce(contents); // renovate.json - await rebaseOnboardingBranch(config, toSha256(contents)); - expect(scm.commitAndPush).toHaveBeenCalledTimes(0); - expect(OnboardingState.prUpdateRequested).toBeFalse(); - } - ); - - it.each` - checkboxEnabled | expected - ${true} | ${true} - ${false} | ${false} - `( - 'rebases onboarding branch ' + - '(config.onboardingRebaseCheckbox="$checkboxEnabled")', - async ({ checkboxEnabled, expected }) => { - config.onboardingRebaseCheckbox = checkboxEnabled; - scm.isBranchBehindBase.mockResolvedValueOnce(true); - await rebaseOnboardingBranch(config, hash); - expect(scm.commitAndPush).toHaveBeenCalledTimes(1); - expect(OnboardingState.prUpdateRequested).toBe(expected); - } - ); - - it.each` - checkboxEnabled | expected - ${true} | ${true} - ${false} | ${false} - `( - 'uses the onboardingConfigFileName if set ' + - '(config.onboardingRebaseCheckbox="$checkboxEnabled")', - async ({ checkboxEnabled, expected }) => { - scm.isBranchBehindBase.mockResolvedValueOnce(true); - await rebaseOnboardingBranch({ - ...config, - onboardingConfigFileName: '.github/renovate.json', - onboardingRebaseCheckbox: checkboxEnabled, - }); - expect(scm.commitAndPush).toHaveBeenCalledTimes(1); - expect(scm.commitAndPush.mock.calls[0][0].message).toContain( - '.github/renovate.json' - ); - expect(scm.commitAndPush.mock.calls[0][0].files[0].path).toBe( - '.github/renovate.json' - ); - expect(OnboardingState.prUpdateRequested).toBe(expected); - } - ); - - it.each` - checkboxEnabled | expected - ${true} | ${true} - ${false} | ${false} - `( - 'falls back to "renovate.json" if onboardingConfigFileName is not set ' + - '(config.onboardingRebaseCheckbox="$checkboxEnabled")', - async ({ checkboxEnabled, expected }) => { - scm.isBranchBehindBase.mockResolvedValueOnce(true); - await rebaseOnboardingBranch({ - ...config, - onboardingConfigFileName: undefined, - onboardingRebaseCheckbox: checkboxEnabled, - }); - expect(scm.commitAndPush).toHaveBeenCalledTimes(1); - expect(scm.commitAndPush.mock.calls[0][0].message).toContain( - 'renovate.json' - ); - expect(scm.commitAndPush.mock.calls[0][0].files[0].path).toBe( - 'renovate.json' - ); - expect(OnboardingState.prUpdateRequested).toBe(expected); - } - ); - - describe('handle onboarding config hashes', () => { - const contents = - JSON.stringify(getConfig().onboardingConfig, null, 2) + '\n'; - - beforeEach(() => { - scm.isBranchModified.mockResolvedValueOnce(true); - git.getFile.mockResolvedValueOnce(contents); - }); - - it.each` - checkboxEnabled | expected - ${true} | ${true} - ${false} | ${false} - `( - 'handles a missing previous config hash ' + - '(config.onboardingRebaseCheckbox="$checkboxEnabled")', - async ({ checkboxEnabled, expected }) => { - config.onboardingRebaseCheckbox = checkboxEnabled; - await rebaseOnboardingBranch(config, undefined); - - expect(OnboardingState.prUpdateRequested).toBe(expected); - } - ); - - it.each` - checkboxEnabled - ${true} - ${false} - `( - 'does nothing if config hashes match' + - '(config.onboardingRebaseCheckbox="$checkboxEnabled")', - async ({ checkboxEnabled, expected }) => { - git.getFile.mockResolvedValueOnce(contents); // package.json - config.onboardingRebaseCheckbox = checkboxEnabled; - await rebaseOnboardingBranch(config, toSha256(contents)); - expect(scm.commitAndPush).toHaveBeenCalledTimes(0); - expect(OnboardingState.prUpdateRequested).toBeFalse(); - } - ); - - it.each` - checkboxEnabled | expected - ${true} | ${true} - ${false} | ${false} - `( - 'requests update if config hashes mismatch' + - '(config.onboardingRebaseCheckbox="$checkboxEnabled")', - async ({ checkboxEnabled, expected }) => { - git.getFile.mockResolvedValueOnce(contents); // package.json - config.onboardingRebaseCheckbox = checkboxEnabled; - await rebaseOnboardingBranch(config, hash); - expect(scm.commitAndPush).toHaveBeenCalledTimes(0); - expect(OnboardingState.prUpdateRequested).toBe(expected); - } - ); - }); - }); -}); diff --git a/lib/workers/repository/onboarding/branch/rebase.ts b/lib/workers/repository/onboarding/branch/rebase.ts deleted file mode 100644 index 4cb1d27345db4d..00000000000000 --- a/lib/workers/repository/onboarding/branch/rebase.ts +++ /dev/null @@ -1,89 +0,0 @@ -import is from '@sindresorhus/is'; -import { GlobalConfig } from '../../../../config/global'; -import type { RenovateConfig } from '../../../../config/types'; -import { logger } from '../../../../logger'; -import { scm } from '../../../../modules/platform/scm'; -import { getFile } from '../../../../util/git'; -import { toSha256 } from '../../../../util/hasha'; -import { OnboardingState, defaultConfigFile } from '../common'; -import { OnboardingCommitMessageFactory } from './commit-message'; -import { getOnboardingConfigContents } from './config'; - -export async function rebaseOnboardingBranch( - config: RenovateConfig, - previousConfigHash?: string -): Promise { - logger.debug('Checking if onboarding branch needs rebasing'); - const configFile = defaultConfigFile(config); - const existingContents = - (await getFile(configFile, config.onboardingBranch)) ?? ''; - const currentConfigHash = toSha256(existingContents); - const contents = await getOnboardingConfigContents(config, configFile); - - if (config.onboardingRebaseCheckbox) { - handleOnboardingManualRebase(previousConfigHash, currentConfigHash); - } - - // TODO #7154 - if (await scm.isBranchModified(config.onboardingBranch!)) { - logger.debug('Onboarding branch has been edited and cannot be rebased'); - return null; - } - - // TODO: fix types (#7154) - if ( - contents === existingContents && - !(await scm.isBranchBehindBase( - config.onboardingBranch!, - config.defaultBranch! - )) - ) { - logger.debug('Onboarding branch is up to date'); - return null; - } - - logger.debug('Rebasing onboarding branch'); - if (config.onboardingRebaseCheckbox) { - OnboardingState.prUpdateRequested = true; - } - // istanbul ignore next - const commitMessageFactory = new OnboardingCommitMessageFactory( - config, - configFile - ); - const commitMessage = commitMessageFactory.create(); - - // istanbul ignore if - if (GlobalConfig.get('dryRun')) { - logger.info('DRY-RUN: Would rebase files in onboarding branch'); - return null; - } - - // TODO #7154 - return scm.commitAndPush({ - baseBranch: config.baseBranch, - branchName: config.onboardingBranch!, - files: [ - { - type: 'addition', - path: configFile, - contents, - }, - ], - message: commitMessage.toString(), - platformCommit: !!config.platformCommit, - }); -} - -function handleOnboardingManualRebase( - previousConfigHash: string | undefined, - currentConfigHash: string -): void { - if (is.nullOrUndefined(previousConfigHash)) { - logger.debug('Missing previousConfigHash bodyStruct prop in onboarding PR'); - OnboardingState.prUpdateRequested = true; - } else if (previousConfigHash !== currentConfigHash) { - logger.debug('Onboarding config has been modified by the user'); - OnboardingState.prUpdateRequested = true; - } -} diff --git a/lib/workers/repository/onboarding/pr/index.spec.ts b/lib/workers/repository/onboarding/pr/index.spec.ts index 500a62d1e71ea0..0bc3ad94282deb 100644 --- a/lib/workers/repository/onboarding/pr/index.spec.ts +++ b/lib/workers/repository/onboarding/pr/index.spec.ts @@ -155,6 +155,7 @@ describe('workers/repository/onboarding/pr/index', () => { config.baseBranch = 'some-branch'; config.repository = 'test'; config.onboardingRebaseCheckbox = onboardingRebaseCheckbox; + config.onboardingConfigFileName = undefined; // checks the case when fileName isn't available OnboardingState.prUpdateRequested = true; // case 'false' is tested in "breaks early when onboarding" await ensureOnboardingPr( { @@ -201,7 +202,7 @@ describe('workers/repository/onboarding/pr/index', () => { } ); - it('updates PR when conflicted', async () => { + it('ensures comment, when PR is conflicted', async () => { config.baseBranch = 'some-branch'; platform.getBranchPr.mockResolvedValueOnce( partial({ @@ -210,10 +211,10 @@ describe('workers/repository/onboarding/pr/index', () => { }) ); scm.isBranchConflicted.mockResolvedValueOnce(true); - scm.isBranchModified.mockResolvedValueOnce(true); await ensureOnboardingPr(config, {}, branches); + expect(platform.ensureComment).toHaveBeenCalledTimes(1); expect(platform.createPr).toHaveBeenCalledTimes(0); - expect(platform.updatePr).toHaveBeenCalledTimes(1); + expect(platform.updatePr).toHaveBeenCalledTimes(0); }); it('updates PR when modified', async () => { @@ -224,7 +225,6 @@ describe('workers/repository/onboarding/pr/index', () => { bodyStruct, }) ); - scm.isBranchModified.mockResolvedValueOnce(true); await ensureOnboardingPr(config, {}, branches); expect(platform.createPr).toHaveBeenCalledTimes(0); expect(platform.updatePr).toHaveBeenCalledTimes(1); @@ -242,34 +242,31 @@ describe('workers/repository/onboarding/pr/index', () => { expect(platform.createPr).toHaveBeenCalledTimes(1); }); - it('dryrun of updates PR when modified', async () => { + it('dryrun of creates PR', async () => { GlobalConfig.set({ dryRun: 'full' }); - config.baseBranch = 'some-branch'; - platform.getBranchPr.mockResolvedValueOnce( - partial({ - title: 'Configure Renovate', - bodyStruct, - }) - ); - scm.isBranchConflicted.mockResolvedValueOnce(true); - scm.isBranchModified.mockResolvedValueOnce(true); - await ensureOnboardingPr(config, {}, branches); + await ensureOnboardingPr(config, packageFiles, branches); expect(logger.info).toHaveBeenCalledWith( 'DRY-RUN: Would check branch renovate/configure' ); expect(logger.info).toHaveBeenLastCalledWith( - 'DRY-RUN: Would update onboarding PR' + 'DRY-RUN: Would create onboarding PR' ); }); - it('dryrun of creates PR', async () => { + it('dryrun of updates PR', async () => { GlobalConfig.set({ dryRun: 'full' }); + platform.getBranchPr.mockResolvedValueOnce( + partial({ + title: 'Configure Renovate', + bodyStruct, + }) + ); await ensureOnboardingPr(config, packageFiles, branches); expect(logger.info).toHaveBeenCalledWith( 'DRY-RUN: Would check branch renovate/configure' ); expect(logger.info).toHaveBeenLastCalledWith( - 'DRY-RUN: Would create onboarding PR' + 'DRY-RUN: Would update onboarding PR' ); }); diff --git a/lib/workers/repository/onboarding/pr/index.ts b/lib/workers/repository/onboarding/pr/index.ts index 923dec654e8c2d..2bf76f3ee5526b 100644 --- a/lib/workers/repository/onboarding/pr/index.ts +++ b/lib/workers/repository/onboarding/pr/index.ts @@ -4,6 +4,7 @@ import type { RenovateConfig } from '../../../../config/types'; import { logger } from '../../../../logger'; import type { PackageFile } from '../../../../modules/manager/types'; import { platform } from '../../../../modules/platform'; +import { ensureComment } from '../../../../modules/platform/comment'; import { hashBody } from '../../../../modules/platform/pr-body'; import { scm } from '../../../../modules/platform/scm'; import { emojify } from '../../../../util/emoji'; @@ -19,6 +20,7 @@ import { import { getPlatformPrOptions } from '../../update/pr'; import { prepareLabels } from '../../update/pr/labels'; import { addParticipants } from '../../update/pr/participants'; +import { isOnboardingBranchConflicted } from '../branch/onboarding-branch-cache'; import { OnboardingState, defaultConfigFile } from '../common'; import { getBaseBranchDesc } from './base-branch'; import { getConfigDesc } from './config-description'; @@ -39,6 +41,24 @@ export async function ensureOnboardingPr( logger.trace({ config }); // TODO #7154 const existingPr = await platform.getBranchPr(config.onboardingBranch!); + if (existingPr) { + // skip pr-update if branch is conflicted + if ( + await isOnboardingBranchConflicted( + config.defaultBranch!, + config.onboardingBranch! + ) + ) { + await ensureComment({ + number: existingPr.number, + topic: 'Branch Conflicted', + content: emojify( + `:warning: This PR has a merge conflict which Renovate is unable to automatically resolve, so updates to this PR description are now paused. Please resolve the merge conflict manually.\n\n` + ), + }); + return; + } + } const { rebaseCheckBox, renovateConfigHashComment } = await getRebaseCheckboxComponents(config); logger.debug('Filling in onboarding PR template'); @@ -96,23 +116,6 @@ If you need any further assistance then you can also [request help here](${ if (GlobalConfig.get('dryRun')) { // TODO: types (#7154) logger.info(`DRY-RUN: Would check branch ${config.onboardingBranch!}`); - } else if (await scm.isBranchModified(config.onboardingBranch!)) { - configDesc = emojify( - `### Configuration\n\n:abcd: Renovate has detected a custom config for this PR. Feel free to ask for [help](${ - config.productLinks!.help - }) if you have any doubts and would like it reviewed.\n\n` - ); - const isConflicted = await scm.isBranchConflicted( - config.baseBranch!, - config.onboardingBranch! - ); - if (isConflicted) { - configDesc += emojify( - `:warning: This PR has a merge conflict. However, Renovate is unable to automatically fix that due to edits in this branch. Please resolve the merge conflict manually.\n\n` - ); - } else { - configDesc += `Important: Now that this branch is edited, Renovate can't rebase it from the base branch any more. If you make changes to the base branch that could impact this onboarding PR, please merge them manually.\n\n`; - } } else { configDesc = getConfigDesc(config, packageFiles!); } From 2863361636c2858b30cb00811bbb565313475e29 Mon Sep 17 00:00:00 2001 From: Sebastian Poxhofer Date: Thu, 18 May 2023 07:57:49 +0200 Subject: [PATCH 68/74] feat(manager/pep621): support pdm lock files (#22244) Co-authored-by: Michael Kriese --- lib/modules/manager/pep621/artifacts.spec.ts | 105 +++++++++++ lib/modules/manager/pep621/artifacts.ts | 23 +++ lib/modules/manager/pep621/index.ts | 3 + .../manager/pep621/processors/pdm.spec.ts | 172 ++++++++++++++++++ lib/modules/manager/pep621/processors/pdm.ts | 81 ++++++++- .../manager/pep621/processors/types.ts | 10 +- lib/modules/manager/pep621/readme.md | 2 +- lib/util/exec/containerbase.ts | 5 + 8 files changed, 398 insertions(+), 3 deletions(-) create mode 100644 lib/modules/manager/pep621/artifacts.spec.ts create mode 100644 lib/modules/manager/pep621/artifacts.ts create mode 100644 lib/modules/manager/pep621/processors/pdm.spec.ts diff --git a/lib/modules/manager/pep621/artifacts.spec.ts b/lib/modules/manager/pep621/artifacts.spec.ts new file mode 100644 index 00000000000000..f104c7e51f4327 --- /dev/null +++ b/lib/modules/manager/pep621/artifacts.spec.ts @@ -0,0 +1,105 @@ +import { join } from 'upath'; +import { mockExecAll } from '../../../../test/exec-util'; +import { fs, mockedFunction } from '../../../../test/util'; +import { GlobalConfig } from '../../../config/global'; +import type { RepoGlobalConfig } from '../../../config/types'; +import { getPkgReleases as _getPkgReleases } from '../../datasource'; +import type { UpdateArtifactsConfig } from '../types'; +import { updateArtifacts } from './artifacts'; + +jest.mock('../../../util/fs'); +jest.mock('../../datasource'); + +const getPkgReleases = mockedFunction(_getPkgReleases); + +const config: UpdateArtifactsConfig = {}; +const adminConfig: RepoGlobalConfig = { + localDir: join('/tmp/github/some/repo'), + cacheDir: join('/tmp/cache'), + containerbaseDir: join('/tmp/cache/containerbase'), +}; + +describe('modules/manager/pep621/artifacts', () => { + describe('updateArtifacts()', () => { + it('return null if all processors returns are empty', async () => { + const updatedDeps = [ + { + packageName: 'dep1', + }, + ]; + const result = await updateArtifacts({ + packageFileName: 'pyproject.toml', + newPackageFileContent: '', + config, + updatedDeps, + }); + expect(result).toBeNull(); + }); + + it('return processor result', async () => { + const execSnapshots = mockExecAll(); + GlobalConfig.set({ ...adminConfig, binarySource: 'docker' }); + fs.getSiblingFileName.mockReturnValueOnce('pdm.lock'); + fs.readLocalFile.mockResolvedValueOnce('old test content'); + fs.readLocalFile.mockResolvedValueOnce('new test content'); + // pdm + getPkgReleases.mockResolvedValueOnce({ + releases: [{ version: 'v2.6.1' }, { version: 'v2.5.0' }], + }); + + const updatedDeps = [{ packageName: 'dep1' }]; + const result = await updateArtifacts({ + packageFileName: 'pyproject.toml', + newPackageFileContent: '', + config: {}, + updatedDeps, + }); + expect(result).toEqual([ + { + file: { + contents: 'new test content', + path: 'pdm.lock', + type: 'addition', + }, + }, + ]); + expect(execSnapshots).toMatchObject([ + { + cmd: 'docker pull containerbase/sidecar', + options: { + encoding: 'utf-8', + }, + }, + { + cmd: 'docker ps --filter name=renovate_sidecar -aq', + options: { + encoding: 'utf-8', + }, + }, + { + cmd: + 'docker run --rm --name=renovate_sidecar --label=renovate_child ' + + '-v "/tmp/github/some/repo":"/tmp/github/some/repo" ' + + '-v "/tmp/cache":"/tmp/cache" ' + + '-e BUILDPACK_CACHE_DIR ' + + '-e CONTAINERBASE_CACHE_DIR ' + + '-w "/tmp/github/some/repo" ' + + 'containerbase/sidecar ' + + 'bash -l -c "' + + 'install-tool pdm v2.5.0 ' + + '&& ' + + 'pdm update dep1' + + '"', + options: { + cwd: '/tmp/github/some/repo', + encoding: 'utf-8', + env: { + BUILDPACK_CACHE_DIR: '/tmp/cache/containerbase', + CONTAINERBASE_CACHE_DIR: '/tmp/cache/containerbase', + }, + }, + }, + ]); + }); + }); +}); diff --git a/lib/modules/manager/pep621/artifacts.ts b/lib/modules/manager/pep621/artifacts.ts new file mode 100644 index 00000000000000..21145c463c14e2 --- /dev/null +++ b/lib/modules/manager/pep621/artifacts.ts @@ -0,0 +1,23 @@ +import is from '@sindresorhus/is'; +import { writeLocalFile } from '../../../util/fs'; +import type { UpdateArtifact, UpdateArtifactsResult } from '../types'; +import { processors } from './processors'; + +export async function updateArtifacts( + updateArtifact: UpdateArtifact +): Promise { + const { packageFileName, newPackageFileContent } = updateArtifact; + + await writeLocalFile(packageFileName, newPackageFileContent); + + // process specific tool sets + const result: UpdateArtifactsResult[] = []; + for (const processor of processors) { + const artifactUpdates = await processor.updateArtifacts(updateArtifact); + if (is.array(artifactUpdates)) { + result.push(...artifactUpdates); + } + } + + return result.length > 0 ? result : null; +} diff --git a/lib/modules/manager/pep621/index.ts b/lib/modules/manager/pep621/index.ts index 9b1adb54893e40..62a464046df595 100644 --- a/lib/modules/manager/pep621/index.ts +++ b/lib/modules/manager/pep621/index.ts @@ -1,8 +1,11 @@ import { PypiDatasource } from '../../datasource/pypi'; export { extractPackageFile } from './extract'; +export { updateArtifacts } from './artifacts'; export const supportedDatasources = [PypiDatasource.id]; +export const supportsLockFileMaintenance = true; + export const defaultConfig = { fileMatch: ['(^|/)pyproject\\.toml$'], }; diff --git a/lib/modules/manager/pep621/processors/pdm.spec.ts b/lib/modules/manager/pep621/processors/pdm.spec.ts new file mode 100644 index 00000000000000..d455b0b722b576 --- /dev/null +++ b/lib/modules/manager/pep621/processors/pdm.spec.ts @@ -0,0 +1,172 @@ +import { join } from 'upath'; +import { mockExecAll } from '../../../../../test/exec-util'; +import { fs, mockedFunction } from '../../../../../test/util'; +import { GlobalConfig } from '../../../../config/global'; +import type { RepoGlobalConfig } from '../../../../config/types'; +import { getPkgReleases as _getPkgReleases } from '../../../datasource'; +import type { UpdateArtifactsConfig } from '../../types'; +import { PdmProcessor } from './pdm'; + +jest.mock('../../../../util/fs'); +jest.mock('../../../datasource'); + +const getPkgReleases = mockedFunction(_getPkgReleases); + +const config: UpdateArtifactsConfig = {}; +const adminConfig: RepoGlobalConfig = { + localDir: join('/tmp/github/some/repo'), + cacheDir: join('/tmp/cache'), + containerbaseDir: join('/tmp/cache/containerbase'), +}; + +const processor = new PdmProcessor(); + +describe('modules/manager/pep621/processors/pdm', () => { + describe('updateArtifacts()', () => { + it('return null if there is no lock file', async () => { + fs.getSiblingFileName.mockReturnValueOnce('pdm.lock'); + const updatedDeps = [{ packageName: 'dep1' }]; + const result = await processor.updateArtifacts({ + packageFileName: 'pyproject.toml', + newPackageFileContent: '', + config, + updatedDeps, + }); + expect(result).toBeNull(); + }); + + it('return null if the lock file is unchanged', async () => { + const execSnapshots = mockExecAll(); + GlobalConfig.set({ ...adminConfig, binarySource: 'docker' }); + fs.getSiblingFileName.mockReturnValueOnce('pdm.lock'); + fs.readLocalFile.mockResolvedValueOnce('test content'); + fs.readLocalFile.mockResolvedValueOnce('test content'); + // pdm + getPkgReleases.mockResolvedValueOnce({ + releases: [{ version: 'v2.6.1' }, { version: 'v2.5.0' }], + }); + + const updatedDeps = [{ packageName: 'dep1' }]; + const result = await processor.updateArtifacts({ + packageFileName: 'pyproject.toml', + newPackageFileContent: '', + config: {}, + updatedDeps, + }); + expect(result).toBeNull(); + expect(execSnapshots).toMatchObject([ + { + cmd: 'docker pull containerbase/sidecar', + }, + { + cmd: 'docker ps --filter name=renovate_sidecar -aq', + }, + { + cmd: + 'docker run --rm --name=renovate_sidecar --label=renovate_child ' + + '-v "/tmp/github/some/repo":"/tmp/github/some/repo" ' + + '-v "/tmp/cache":"/tmp/cache" ' + + '-e BUILDPACK_CACHE_DIR ' + + '-e CONTAINERBASE_CACHE_DIR ' + + '-w "/tmp/github/some/repo" ' + + 'containerbase/sidecar ' + + 'bash -l -c "' + + 'install-tool pdm v2.5.0 ' + + '&& ' + + 'pdm update dep1' + + '"', + }, + ]); + }); + + it('returns artifact error', async () => { + const execSnapshots = mockExecAll(); + GlobalConfig.set({ ...adminConfig, binarySource: 'docker' }); + fs.getSiblingFileName.mockReturnValueOnce('pdm.lock'); + fs.readLocalFile.mockImplementationOnce(() => { + throw new Error('test error'); + }); + + const updatedDeps = [{ packageName: 'dep1' }]; + const result = await processor.updateArtifacts({ + packageFileName: 'pyproject.toml', + newPackageFileContent: '', + config: {}, + updatedDeps, + }); + expect(result).toEqual([ + { artifactError: { lockFile: 'pdm.lock', stderr: 'test error' } }, + ]); + expect(execSnapshots).toEqual([]); + }); + + it('return update dep update', async () => { + const execSnapshots = mockExecAll(); + GlobalConfig.set(adminConfig); + fs.getSiblingFileName.mockReturnValueOnce('pdm.lock'); + fs.readLocalFile.mockResolvedValueOnce('test content'); + fs.readLocalFile.mockResolvedValueOnce('changed test content'); + // pdm + getPkgReleases.mockResolvedValueOnce({ + releases: [{ version: 'v2.6.1' }, { version: 'v2.5.0' }], + }); + + const updatedDeps = [{ packageName: 'dep1' }, { packageName: 'dep2' }]; + const result = await processor.updateArtifacts({ + packageFileName: 'pyproject.toml', + newPackageFileContent: '', + config: {}, + updatedDeps, + }); + expect(result).toEqual([ + { + file: { + contents: 'changed test content', + path: 'pdm.lock', + type: 'addition', + }, + }, + ]); + expect(execSnapshots).toMatchObject([ + { + cmd: 'pdm update dep1 dep2', + }, + ]); + }); + + it('return update on lockfileMaintenance', async () => { + const execSnapshots = mockExecAll(); + GlobalConfig.set(adminConfig); + fs.getSiblingFileName.mockReturnValueOnce('pdm.lock'); + fs.readLocalFile.mockResolvedValueOnce('test content'); + fs.readLocalFile.mockResolvedValueOnce('changed test content'); + // pdm + getPkgReleases.mockResolvedValueOnce({ + releases: [{ version: 'v2.6.1' }, { version: 'v2.5.0' }], + }); + + const result = await processor.updateArtifacts({ + packageFileName: 'pyproject.toml', + newPackageFileContent: '', + config: { + updateType: 'lockFileMaintenance', + }, + updatedDeps: [], + }); + expect(result).toEqual([ + { + file: { + contents: 'changed test content', + path: 'pdm.lock', + type: 'addition', + }, + }, + ]); + expect(execSnapshots).toMatchObject([ + { + cmd: 'pdm update', + }, + ]); + }); + }); +}); diff --git a/lib/modules/manager/pep621/processors/pdm.ts b/lib/modules/manager/pep621/processors/pdm.ts index e362694b55a745..cf717b6dbfcfd0 100644 --- a/lib/modules/manager/pep621/processors/pdm.ts +++ b/lib/modules/manager/pep621/processors/pdm.ts @@ -1,6 +1,15 @@ import is from '@sindresorhus/is'; +import { TEMPORARY_ERROR } from '../../../../constants/error-messages'; +import { logger } from '../../../../logger'; +import { exec } from '../../../../util/exec'; +import type { ExecOptions, ToolConstraint } from '../../../../util/exec/types'; +import { getSiblingFileName, readLocalFile } from '../../../../util/fs'; import { PypiDatasource } from '../../../datasource/pypi'; -import type { PackageDependency } from '../../types'; +import type { + PackageDependency, + UpdateArtifact, + UpdateArtifactsResult, +} from '../../types'; import type { PyProject } from '../schema'; import { parseDependencyGroupRecord } from '../utils'; import type { PyProjectProcessor } from './types'; @@ -39,4 +48,74 @@ export class PdmProcessor implements PyProjectProcessor { return deps; } + + async updateArtifacts( + updateArtifact: UpdateArtifact + ): Promise { + const { config, updatedDeps, packageFileName } = updateArtifact; + + const isLockFileMaintenance = config.updateType === 'lockFileMaintenance'; + + // abort if no lockfile is defined + const lockFileName = getSiblingFileName(packageFileName, 'pdm.lock'); + try { + const existingLockFileContent = await readLocalFile(lockFileName, 'utf8'); + if (is.nullOrUndefined(existingLockFileContent)) { + logger.debug('No pdm.lock found'); + return null; + } + + const toolConstraint: ToolConstraint = { + toolName: 'pdm', + constraint: config.constraints?.pdm, + }; + + const execOptions: ExecOptions = { + docker: {}, + toolConstraints: [toolConstraint], + }; + + // on lockFileMaintenance do not specify any packages and update the complete lock file + // else only update specific packages + let packageList = ''; + if (!isLockFileMaintenance) { + packageList = ' '; + packageList += updatedDeps.map((value) => value.packageName).join(' '); + } + const cmd = `pdm update${packageList}`; + await exec(cmd, execOptions); + + // check for changes + const fileChanges: UpdateArtifactsResult[] = []; + const newLockContent = await readLocalFile(lockFileName, 'utf8'); + const isLockFileChanged = existingLockFileContent !== newLockContent; + if (isLockFileChanged) { + fileChanges.push({ + file: { + type: 'addition', + path: lockFileName, + contents: newLockContent, + }, + }); + } else { + logger.debug('pdm.lock is unchanged'); + } + + return fileChanges.length ? fileChanges : null; + } catch (err) { + // istanbul ignore if + if (err.message === TEMPORARY_ERROR) { + throw err; + } + logger.debug({ err }, 'Failed to update PDM lock file'); + return [ + { + artifactError: { + lockFile: lockFileName, + stderr: err.message, + }, + }, + ]; + } + } } diff --git a/lib/modules/manager/pep621/processors/types.ts b/lib/modules/manager/pep621/processors/types.ts index dbe645396e76c2..37798951b7e161 100644 --- a/lib/modules/manager/pep621/processors/types.ts +++ b/lib/modules/manager/pep621/processors/types.ts @@ -1,7 +1,15 @@ -import type { PackageDependency } from '../../types'; +import type { + PackageDependency, + UpdateArtifact, + UpdateArtifactsResult, +} from '../../types'; import type { PyProject } from '../schema'; export interface PyProjectProcessor { + updateArtifacts( + updateArtifact: UpdateArtifact + ): Promise; + /** * Extracts additional dependencies and/or modifies existing ones based on the tool configuration. * If no relevant section for the processor exists, then it should return the received dependencies unmodified. diff --git a/lib/modules/manager/pep621/readme.md b/lib/modules/manager/pep621/readme.md index 96fcde1007a12a..073e1bf787c172 100644 --- a/lib/modules/manager/pep621/readme.md +++ b/lib/modules/manager/pep621/readme.md @@ -2,7 +2,7 @@ This manager supports updating dependencies inside `pyproject.toml` files. In addition to standard dependencies, these toolsets are also supported: -- `pdm` +- `pdm` ( including `pdm.lock` files ) Available `depType`s: diff --git a/lib/util/exec/containerbase.ts b/lib/util/exec/containerbase.ts index bcb21adab9dee1..d9efe6285ac82b 100644 --- a/lib/util/exec/containerbase.ts +++ b/lib/util/exec/containerbase.ts @@ -130,6 +130,11 @@ const allToolConfig: Record = { hash: true, versioning: npmVersioningId, }, + pdm: { + datasource: 'github-releases', + packageName: 'pdm-project/pdm', + versioning: semverVersioningId, + }, php: { datasource: 'github-releases', packageName: 'containerbase/php-prebuild', From 452804834b94bfd90f43107844751639c8d3a1e8 Mon Sep 17 00:00:00 2001 From: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> Date: Thu, 18 May 2023 07:58:46 +0200 Subject: [PATCH 69/74] feat(presets): create `approveMajorUpdates` (#22075) Co-authored-by: Rhys Arkins --- lib/config/presets/internal/default.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/config/presets/internal/default.ts b/lib/config/presets/internal/default.ts index 0c4340b17f996e..4a7ca0f2577a20 100644 --- a/lib/config/presets/internal/default.ts +++ b/lib/config/presets/internal/default.ts @@ -2,6 +2,15 @@ import type { Preset } from '../types'; /* eslint sort-keys: ["error", "asc", {caseSensitive: false, natural: true}] */ export const presets: Record = { + approveMajorUpdates: { + description: 'Require dependency dashboard approval for `major` updates.', + packageRules: [ + { + dependencyDashboardApproval: true, + matchUpdateTypes: ['major'], + }, + ], + }, assignAndReview: { description: 'Set `{{arg0}}` as assignee and reviewer of PRs.', extends: [':assignee({{arg0}})', ':reviewer({{arg0}})'], From c6d7168f44a754147d4ac5aaca50f40f1bb67c97 Mon Sep 17 00:00:00 2001 From: Philip <42116482+PhilipAbed@users.noreply.github.com> Date: Thu, 18 May 2023 08:59:43 +0300 Subject: [PATCH 70/74] feat: log extended branch summary (#22056) --- lib/util/cache/repository/types.ts | 22 +++++-- lib/workers/repository/cache.ts | 21 +++++- .../repository/dependency-dashboard.ts | 1 + .../finalize/repository-statistics.spec.ts | 34 ++++++++++ .../finalize/repository-statistics.ts | 66 ++++++++++++++++++- lib/workers/types.ts | 4 +- 6 files changed, 139 insertions(+), 9 deletions(-) diff --git a/lib/util/cache/repository/types.ts b/lib/util/cache/repository/types.ts index bbcb484864d822..3af4fa03d44c32 100644 --- a/lib/util/cache/repository/types.ts +++ b/lib/util/cache/repository/types.ts @@ -1,9 +1,11 @@ import type { RepositoryCacheConfig, RepositoryCacheType, + UpdateType, } from '../../../config/types'; import type { PackageFile } from '../../../modules/manager/types'; import type { RepoInitConfig } from '../../../workers/repository/init/types'; +import type { PrBlockedBy } from '../../../workers/types'; export interface BaseBranchCache { sha: string; // branch commit sha @@ -17,6 +19,8 @@ export interface BranchUpgradeCache { currentValue?: string; datasource?: string; depName?: string; + depType?: string; + displayPending?: unknown; fixedVersion?: string; currentVersion?: string; packageName?: string; @@ -24,6 +28,9 @@ export interface BranchUpgradeCache { newValue?: string; newVersion?: string; sourceUrl?: string; + packageFile?: string; + remediationNotPossible?: unknown; + updateType?: UpdateType; } export interface OnboardingBranchCache { @@ -45,15 +52,15 @@ export interface BranchCache { /** * Whether this branch has automerge enabled */ - automerge: boolean; + automerge?: boolean; /** * Name of base branch */ - baseBranch: string; + baseBranch?: string; /** * The base branch's most recent commit SHA */ - baseBranchSha: string | null; + baseBranchSha?: string | null; /** * Hash of the manager fingerprints and the filtered update branch config */ @@ -85,7 +92,7 @@ export interface BranchCache { /** * The branch's most recent commit SHA */ - sha: string | null; + sha?: string | null; /** * Details on the dependency upgrades that have been applied in this branch */ @@ -94,6 +101,13 @@ export interface BranchCache { * Object that has PR info */ prCache?: PrCache | null; + + /** + * Dependency dashboard information + */ + prBlockedBy?: PrBlockedBy; + prTitle?: string; + result?: string; } export interface RepoCacheData { diff --git a/lib/workers/repository/cache.ts b/lib/workers/repository/cache.ts index e80979449435d9..684c6220524297 100644 --- a/lib/workers/repository/cache.ts +++ b/lib/workers/repository/cache.ts @@ -22,23 +22,37 @@ function generateBranchUpgradeCache( const { datasource, depName, + depType, + displayPending, packageName, fixedVersion, currentVersion, newVersion, + currentValue, + newValue, currentDigest, newDigest, + packageFile, sourceUrl, + remediationNotPossible, + updateType, } = upgrade; const result: BranchUpgradeCache = { datasource, depName, + depType, + displayPending, fixedVersion, currentVersion, + currentValue, + newValue, newVersion, currentDigest, newDigest, + packageFile, sourceUrl, + remediationNotPossible, + updateType, }; if (packageName) { result.packageName = packageName; @@ -49,7 +63,7 @@ function generateBranchUpgradeCache( async function generateBranchCache( branch: BranchConfig ): Promise { - const { baseBranch, branchName } = branch; + const { baseBranch, branchName, prBlockedBy, prTitle, result } = branch; try { const branchSha = await scm.getBranchCommit(branchName); const baseBranchSha = await scm.getBranchCommit(baseBranch); @@ -79,12 +93,14 @@ async function generateBranchCache( baseBranchSha ) ?? undefined; } + const automerge = !!branch.automerge; const upgrades: BranchUpgradeCache[] = branch.upgrades ? branch.upgrades.map(generateBranchUpgradeCache) : []; const branchFingerprint = branch.branchFingerprint; const prCache = getPrCache(branchName); + return { automerge, baseBranchSha, @@ -94,9 +110,12 @@ async function generateBranchCache( isBehindBase, isConflicted, isModified, + prBlockedBy, pristine, prCache, prNo, + prTitle, + result, sha: branchSha, upgrades, }; diff --git a/lib/workers/repository/dependency-dashboard.ts b/lib/workers/repository/dependency-dashboard.ts index 15759ff691a181..dfd9119169454c 100644 --- a/lib/workers/repository/dependency-dashboard.ts +++ b/lib/workers/repository/dependency-dashboard.ts @@ -168,6 +168,7 @@ function appendRepoProblems(config: RenovateConfig, issueBody: string): string { ) ); if (repoProblems.size) { + logger.debug({ repoProblems }, 'repository problems'); newIssueBody += '## Repository problems\n\n'; newIssueBody += 'These problems occurred while renovating this repository.\n\n'; diff --git a/lib/workers/repository/finalize/repository-statistics.spec.ts b/lib/workers/repository/finalize/repository-statistics.spec.ts index 3f2c323550e1be..68f7ff022e6f5c 100644 --- a/lib/workers/repository/finalize/repository-statistics.spec.ts +++ b/lib/workers/repository/finalize/repository-statistics.spec.ts @@ -11,6 +11,7 @@ import * as cache from '../../../util/cache/repository'; import type { BaseBranchCache, BranchCache, + BranchUpgradeCache, RepoCacheData, } from '../../../util/cache/repository/types'; import { @@ -103,6 +104,7 @@ describe('workers/repository/finalize/repository-statistics', () => { isModified: false, automerge: false, pristine: false, + upgrades: [], }); const expectedMeta = { automerge: branchCache.automerge, @@ -152,5 +154,37 @@ describe('workers/repository/finalize/repository-statistics', () => { `Branch summary` ); }); + + it('logs extended branch info if branchSummaryExtended', () => { + const defaultBranch = 'main'; + const config: RenovateConfig = { + defaultBranch, + branchSummaryExtended: true, + }; + const branchCache = partial({ + result: 'done', + upgrades: partial([ + { + datasource: 'npm', + depName: 'minimist', + currentValue: '1.2.3', + sourceUrl: 'someUrl', + depType: 'dependencies', + }, + ]), + }); + + const branches: BranchCache[] = [{ ...branchCache, branchName: 'b1' }]; + const cache = partial({ + scan: {}, + branches, + }); + getCacheSpy.mockReturnValueOnce(cache); + isCacheModifiedSpy.mockReturnValueOnce(false); + + runBranchSummary(config); + + expect(logger.debug).toHaveBeenCalledTimes(2); + }); }); }); diff --git a/lib/workers/repository/finalize/repository-statistics.ts b/lib/workers/repository/finalize/repository-statistics.ts index 1d3e487d6fd5be..e2b5224a5be35c 100644 --- a/lib/workers/repository/finalize/repository-statistics.ts +++ b/lib/workers/repository/finalize/repository-statistics.ts @@ -2,7 +2,10 @@ import type { RenovateConfig } from '../../../config/types'; import { logger } from '../../../logger'; import type { Pr } from '../../../modules/platform'; import { getCache, isCacheModified } from '../../../util/cache/repository'; -import type { BranchCache } from '../../../util/cache/repository/types'; +import type { + BranchCache, + BranchUpgradeCache, +} from '../../../util/cache/repository/types'; import type { BaseBranchMetadata, BranchMetadata, @@ -60,7 +63,61 @@ function branchCacheToMetadata({ }; } -export function runBranchSummary({ defaultBranch }: RenovateConfig): void { +function filterDependencyDashboardData( + branches: BranchCache[] +): Partial[] { + const branchesFiltered: Partial[] = []; + for (const branch of branches) { + const upgradesFiltered: Partial[] = []; + const { branchName, prNo, prTitle, result, upgrades, prBlockedBy } = branch; + + for (const upgrade of upgrades ?? []) { + const { + datasource, + depName, + displayPending, + fixedVersion, + currentVersion, + currentValue, + newValue, + newVersion, + packageFile, + updateType, + packageName, + } = upgrade; + + const filteredUpgrade: Partial = { + datasource, + depName, + displayPending, + fixedVersion, + currentVersion, + currentValue, + newValue, + newVersion, + packageFile, + updateType, + packageName, + }; + upgradesFiltered.push(filteredUpgrade); + } + + const filteredBranch: Partial = { + branchName, + prNo, + prTitle, + result, + prBlockedBy, + upgrades: upgradesFiltered, + }; + branchesFiltered.push(filteredBranch); + } + + return branchesFiltered; +} + +export function runBranchSummary(config: RenovateConfig): void { + const defaultBranch = config.defaultBranch; const { scan, branches } = getCache(); const baseMetadata: BaseBranchMetadata[] = []; @@ -88,4 +145,9 @@ export function runBranchSummary({ defaultBranch }: RenovateConfig): void { }; logger.debug(res, 'Branch summary'); + + if (branches?.length) { + const branchesInformation = filterDependencyDashboardData(branches); + logger.debug({ branchesInformation }, 'branches info extended'); + } } diff --git a/lib/workers/types.ts b/lib/workers/types.ts index b2ba4e1c265a32..27ac01583ae953 100644 --- a/lib/workers/types.ts +++ b/lib/workers/types.ts @@ -132,10 +132,10 @@ export interface BranchConfig export interface BranchMetadata { branchName: string; - branchSha: string | null; + branchSha?: string | null; baseBranch?: string; baseBranchSha?: string | null; - automerge: boolean; + automerge?: boolean; isModified?: boolean; isPristine?: boolean; } From d4b350400d20fa546a24df2de388d54c75d4bb43 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 18 May 2023 06:43:43 +0000 Subject: [PATCH 71/74] build(deps): update dependency glob to v10.2.5 (#22277) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 70b8e4caed820d..0bca46a1b05dba 100644 --- a/package.json +++ b/package.json @@ -196,7 +196,7 @@ "global-agent": "3.0.0", "good-enough-parser": "1.1.23", "got": "11.8.6", - "glob": "10.2.3", + "glob": "10.2.5", "graph-data-structure": "3.3.0", "handlebars": "4.7.7", "hasha": "5.2.2", diff --git a/yarn.lock b/yarn.lock index 86cdeec2054ffb..79bea66962cd72 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5638,15 +5638,15 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@10.2.3: - version "10.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.2.3.tgz#aa6765963fe6c5936d5c2e00943e7af06302a1a7" - integrity sha512-Kb4rfmBVE3eQTAimgmeqc2LwSnN0wIOkkUL6HmxEFxNJ4fHghYHVbFba/HcGcRjE6s9KoMNK3rSOwkL4PioZjg== +glob@10.2.5: + version "10.2.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.2.5.tgz#73c1850ac8f077810d8370ba414b382ad1a86083" + integrity sha512-Gj+dFYPZ5hc5dazjXzB0iHg2jKWJZYMjITXYPBRQ/xc2Buw7H0BINknRTwURJ6IC6MEFpYbLvtgVb3qD+DwyuA== dependencies: foreground-child "^3.1.0" jackspeak "^2.0.3" minimatch "^9.0.0" - minipass "^5.0.0" + minipass "^5.0.0 || ^6.0.2" path-scurry "^1.7.0" glob@^10.0.0, glob@^10.2.2: @@ -7804,6 +7804,11 @@ minipass@^5.0.0: resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== +"minipass@^5.0.0 || ^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-6.0.2.tgz#542844b6c4ce95b202c0995b0a471f1229de4c81" + integrity sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w== + minizlib@^2.1.1, minizlib@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" From 7cfd7145e7aeff3e579813f705d07575e0d3fad9 Mon Sep 17 00:00:00 2001 From: Sebastian Poxhofer Date: Thu, 18 May 2023 09:39:22 +0200 Subject: [PATCH 72/74] docs(hostRules): document current matchHost behaviour if a port is supplied (#22007) Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> --- docs/usage/configuration-options.md | 17 +++++++++++++++++ lib/util/host-rules.spec.ts | 20 ++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index dce0ff59865d63..223da36102ff8a 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -1208,6 +1208,23 @@ A preset alternative to the above is: } ``` +To match specific ports you have to add a protocol to `matchHost`: + +```json +{ + "hostRules": [ + { + "matchHost": "https://domain.com:9118", + "enabled": false + } + ] +} +``` + + +!!! warning + Using `matchHost` without a protocol behaves the same as if you had set no `matchHost` configuration. + !!! note Disabling a host is only 100% effective if added to self-hosted config. diff --git a/lib/util/host-rules.spec.ts b/lib/util/host-rules.spec.ts index 6513bf9e50ac4c..d8c7dbd78ddf4a 100644 --- a/lib/util/host-rules.spec.ts +++ b/lib/util/host-rules.spec.ts @@ -235,6 +235,26 @@ describe('util/host-rules', () => { expect(find({ url: 'httpsdomain.com' }).token).toBeUndefined(); }); + it('matches on matchHost with port', () => { + add({ + matchHost: 'https://domain.com:9118', + token: 'def', + }); + expect(find({ url: 'https://domain.com:9118' }).token).toBe('def'); + expect(find({ url: 'https://domain.com' }).token).toBeUndefined(); + expect(find({ url: 'httpsdomain.com' }).token).toBeUndefined(); + }); + + it('host with port is interpreted as empty', () => { + add({ + matchHost: 'domain.com:9118', + token: 'def', + }); + expect(find({ url: 'https://domain.com:9118' }).token).toBe('def'); + expect(find({ url: 'https://domain.com' }).token).toBe('def'); + expect(find({ url: 'httpsdomain.com' }).token).toBe('def'); + }); + it('matches on hostType and endpoint', () => { add({ hostType: NugetDatasource.id, From 290463747fd26960a2f9abddd422ee90d411a2a8 Mon Sep 17 00:00:00 2001 From: Spencer Williams Date: Thu, 18 May 2023 00:41:03 -0700 Subject: [PATCH 73/74] feat(manager/terragrunt): support lockFileMaintenance (#20833) Co-authored-by: Rhys Arkins Co-authored-by: Sebastian Poxhofer --- .../manager/terragrunt/artifacts.spec.ts | 71 +++++++++++++++++++ lib/modules/manager/terragrunt/artifacts.ts | 18 +++++ lib/modules/manager/terragrunt/index.ts | 2 + lib/modules/manager/terragrunt/readme.md | 5 ++ 4 files changed, 96 insertions(+) create mode 100644 lib/modules/manager/terragrunt/artifacts.spec.ts create mode 100644 lib/modules/manager/terragrunt/artifacts.ts diff --git a/lib/modules/manager/terragrunt/artifacts.spec.ts b/lib/modules/manager/terragrunt/artifacts.spec.ts new file mode 100644 index 00000000000000..d69cc1ba354d5b --- /dev/null +++ b/lib/modules/manager/terragrunt/artifacts.spec.ts @@ -0,0 +1,71 @@ +import { join } from 'upath'; +import { GlobalConfig } from '../../../config/global'; +import type { UpdateType } from '../../../config/types'; +import * as terraformLockfile from '../terraform/lockfile'; +import type { UpdateArtifactsConfig } from '../types'; +import { updateArtifacts } from './artifacts'; + +jest.mock('../terraform/lockfile'); + +const config = { + constraints: {}, +}; + +const adminConfig = { + // `join` fixes Windows CI + localDir: join('/tmp/github/some/repo'), + cacheDir: join('/tmp/renovate/cache'), + containerbaseDir: join('/tmp/renovate/cache/containerbase'), +}; + +describe('modules/manager/terragrunt/artifacts', () => { + const updateTypes: UpdateType[] = [ + 'digest', + 'pin', + 'rollback', + 'patch', + 'minor', + 'major', + 'replacement', + 'pinDigest', + 'lockfileUpdate', + 'bump', + ]; + + beforeEach(() => { + GlobalConfig.set(adminConfig); + }); + + it('calls terraform updateArtifacts if the update type is lockfileMaintenance', async () => { + const localConfig: UpdateArtifactsConfig = { + updateType: 'lockFileMaintenance', + ...config, + }; + + await updateArtifacts({ + packageFileName: '', + updatedDeps: [], + newPackageFileContent: '', + config: localConfig, + }); + expect(terraformLockfile.updateArtifacts).toHaveBeenCalledOnce(); + }); + + it.each(updateTypes)( + 'does not call terraform updateArtifacts if the update type is %s', + async (updateType) => { + const localConfig: UpdateArtifactsConfig = { + updateType, + ...config, + }; + + await updateArtifacts({ + packageFileName: '', + updatedDeps: [], + newPackageFileContent: '', + config: localConfig, + }); + expect(terraformLockfile.updateArtifacts).not.toHaveBeenCalled(); + } + ); +}); diff --git a/lib/modules/manager/terragrunt/artifacts.ts b/lib/modules/manager/terragrunt/artifacts.ts new file mode 100644 index 00000000000000..865ee1195dba61 --- /dev/null +++ b/lib/modules/manager/terragrunt/artifacts.ts @@ -0,0 +1,18 @@ +import { logger } from '../../../logger'; +import { updateArtifacts as updateTerraformArtifacts } from '../terraform/lockfile/index'; +import type { UpdateArtifact, UpdateArtifactsResult } from '../types'; + +export async function updateArtifacts( + artifact: UpdateArtifact +): Promise { + if (artifact.config.updateType !== 'lockFileMaintenance') { + logger.debug( + `UpdateType ${ + artifact.config.updateType as string + } is not supported for terragrunt` + ); + return null; + } + + return await updateTerraformArtifacts(artifact); +} diff --git a/lib/modules/manager/terragrunt/index.ts b/lib/modules/manager/terragrunt/index.ts index 78eb46b346c2d8..39d6faf56e7fc3 100644 --- a/lib/modules/manager/terragrunt/index.ts +++ b/lib/modules/manager/terragrunt/index.ts @@ -2,6 +2,7 @@ import { GitTagsDatasource } from '../../datasource/git-tags'; import { GithubTagsDatasource } from '../../datasource/github-tags'; import { TerraformModuleDatasource } from '../../datasource/terraform-module'; +export { updateArtifacts } from './artifacts'; export { extractPackageFile } from './extract'; export const supportedDatasources = [ @@ -10,6 +11,7 @@ export const supportedDatasources = [ TerraformModuleDatasource.id, ]; +export const supportsLockFileMaintenance = true; export const defaultConfig = { commitMessageTopic: 'Terragrunt dependency {{depName}}', fileMatch: ['(^|/)terragrunt\\.hcl$'], diff --git a/lib/modules/manager/terragrunt/readme.md b/lib/modules/manager/terragrunt/readme.md index 0e36ffe1550f17..e2484bcfaee478 100644 --- a/lib/modules/manager/terragrunt/readme.md +++ b/lib/modules/manager/terragrunt/readme.md @@ -18,3 +18,8 @@ terraform { source = "github.com/hashicorp/example?ref=v1.0.0" } ``` + +### Terraform lockfiles + +The Terragrunt manager supports [lock file maintenance](https://docs.renovatebot.com/configuration-options/#lockfilemaintenance) for `.terraform.lock.hcl` artifacts. +These artifacts will be updated if and only if the update type is `lockFileMaintenance`. From fc5ddaad89ae2ccc4260f2cfb6096dc516917889 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Thu, 18 May 2023 09:45:45 +0200 Subject: [PATCH 74/74] refactor: drop lint-staged (#22294) --- .husky/pre-commit | 1 - .lintstagedrc.json | 5 -- package.json | 1 - yarn.lock | 207 +++------------------------------------------ 4 files changed, 10 insertions(+), 204 deletions(-) delete mode 100644 .lintstagedrc.json diff --git a/.husky/pre-commit b/.husky/pre-commit index 863d3997b02d17..f642535569f8dc 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,7 +1,6 @@ #!/bin/sh . "$(dirname "$0")/_/husky.sh" -yarn lint-staged yarn ls-lint BRANCH_NAME=$(git branch --show-current) diff --git a/.lintstagedrc.json b/.lintstagedrc.json deleted file mode 100644 index 1d133dcf4f16c4..00000000000000 --- a/.lintstagedrc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "*.md": "markdownlint-cli2-fix", - "**/*.{ts,js,mjs,cjs}": "eslint --cache --fix", - "*": "prettier --cache --ignore-unknown --write" -} diff --git a/package.json b/package.json index 0bca46a1b05dba..729e1bfcfd3518 100644 --- a/package.json +++ b/package.json @@ -314,7 +314,6 @@ "jest-extended": "3.2.4", "jest-junit": "16.0.0", "jest-mock-extended": "3.0.4", - "lint-staged": "13.2.2", "markdownlint-cli2": "0.7.1", "memfs": "3.5.1", "mock-fs": "5.2.0", diff --git a/yarn.lock b/yarn.lock index 79bea66962cd72..11194d887fb50d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3536,7 +3536,7 @@ ajv@^6.10.0, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: +ansi-escapes@^4.2.1: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== @@ -3555,11 +3555,6 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -3579,11 +3574,6 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -ansi-styles@^6.0.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - ansicolors@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" @@ -3719,11 +3709,6 @@ asn1.js@^5.0.0: minimalistic-assert "^1.0.0" safer-buffer "^2.1.0" -astral-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" - integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== - auth-header@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/auth-header/-/auth-header-1.0.0.tgz#ea24fdc5588e1eb8b750df8655a396aa48fc9076" @@ -4099,11 +4084,6 @@ chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@5.2.0, chalk@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.2.0.tgz#249623b7d66869c673699fb66d65723e54dfcfb3" - integrity sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA== - chalk@^2.0.0, chalk@^2.3.2, chalk@^2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -4121,6 +4101,11 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.2.0.tgz#249623b7d66869c673699fb66d65723e54dfcfb3" + integrity sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA== + changelog-filename-regex@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/changelog-filename-regex/-/changelog-filename-regex-2.0.1.tgz#88944bd89a076fc572c0ab6b4a4f2bc2572ac02d" @@ -4202,13 +4187,6 @@ cli-columns@^4.0.0: string-width "^4.2.3" strip-ansi "^6.0.1" -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - cli-table3@^0.6.1, cli-table3@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" @@ -4218,22 +4196,6 @@ cli-table3@^0.6.1, cli-table3@^0.6.3: optionalDependencies: "@colors/colors" "1.5.0" -cli-truncate@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" - integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== - dependencies: - slice-ansi "^3.0.0" - string-width "^4.2.0" - -cli-truncate@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-3.1.0.tgz#3f23ab12535e3d73e839bb43e73c9de487db1389" - integrity sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA== - dependencies: - slice-ansi "^5.0.0" - string-width "^5.0.0" - clipanion@3.2.0-rc.4: version "3.2.0-rc.4" resolved "https://registry.yarnpkg.com/clipanion/-/clipanion-3.2.0-rc.4.tgz#4df6e55e46c1287dd5d6d595eec3c785082e8e32" @@ -4311,11 +4273,6 @@ color-support@^1.1.3: resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== -colorette@^2.0.19: - version "2.0.20" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" - integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== - columnify@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.6.0.tgz#6989531713c9008bb29735e61e37acf5bd553cf3" @@ -4740,11 +4697,6 @@ duplexer2@~0.1.0: dependencies: readable-stream "^2.0.2" -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - editorconfig@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-1.0.2.tgz#0e4ff2ce6bf392f3f9e4d50c1a9819b06d380d15" @@ -4780,11 +4732,6 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - emojibase-data@7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/emojibase-data/-/emojibase-data-7.0.1.tgz#a81d7fcd12247f7d94a96dcbdb143e6b6dd5c328" @@ -6228,11 +6175,6 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-fullwidth-code-point@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" - integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== - is-generator-fn@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" @@ -7170,11 +7112,6 @@ lie@3.1.1: dependencies: immediate "~3.0.5" -lilconfig@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" - integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== - lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -7192,39 +7129,6 @@ linkify-it@^4.0.1: dependencies: uc.micro "^1.0.1" -lint-staged@13.2.2: - version "13.2.2" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.2.2.tgz#5e711d3139c234f73402177be2f8dd312e6508ca" - integrity sha512-71gSwXKy649VrSU09s10uAT0rWCcY3aewhMaHyl2N84oBk4Xs9HgxvUp3AYu+bNsK4NrOYYxvSgg7FyGJ+jGcA== - dependencies: - chalk "5.2.0" - cli-truncate "^3.1.0" - commander "^10.0.0" - debug "^4.3.4" - execa "^7.0.0" - lilconfig "2.1.0" - listr2 "^5.0.7" - micromatch "^4.0.5" - normalize-path "^3.0.0" - object-inspect "^1.12.3" - pidtree "^0.6.0" - string-argv "^0.3.1" - yaml "^2.2.2" - -listr2@^5.0.7: - version "5.0.8" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-5.0.8.tgz#a9379ffeb4bd83a68931a65fb223a11510d6ba23" - integrity sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA== - dependencies: - cli-truncate "^2.1.0" - colorette "^2.0.19" - log-update "^4.0.0" - p-map "^4.0.0" - rfdc "^1.3.0" - rxjs "^7.8.0" - through "^2.3.8" - wrap-ansi "^7.0.0" - load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" @@ -7326,16 +7230,6 @@ lodash@^4.17.15, lodash@^4.17.21, lodash@^4.17.4: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-update@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" - integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== - dependencies: - ansi-escapes "^4.3.0" - cli-cursor "^3.1.0" - slice-ansi "^4.0.0" - wrap-ansi "^6.2.0" - longest-streak@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" @@ -7630,7 +7524,7 @@ micromark@~2.11.0: debug "^4.0.0" parse-entities "^2.0.0" -micromatch@4.0.5, micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: +micromatch@4.0.5, micromatch@^4.0.2, micromatch@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== @@ -8321,7 +8215,7 @@ once@~1.3.0: dependencies: wrappy "1" -onetime@^5.1.0, onetime@^5.1.2: +onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -8697,11 +8591,6 @@ pidtree@^0.3.0: resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a" integrity sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA== -pidtree@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" - integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== - pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" @@ -9202,14 +9091,6 @@ responselike@^2.0.0: dependencies: lowercase-keys "^2.0.0" -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" @@ -9225,11 +9106,6 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rfdc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" - integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== - rimraf@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.0.tgz#5bda14e410d7e4dd522154891395802ce032c2cb" @@ -9270,13 +9146,6 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -rxjs@^7.8.0: - version "7.8.1" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" - integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== - dependencies: - tslib "^2.1.0" - safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -9527,32 +9396,6 @@ slash@^4.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== -slice-ansi@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" - integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - -slice-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" - integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - -slice-ansi@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" - integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ== - dependencies: - ansi-styles "^6.0.0" - is-fullwidth-code-point "^4.0.0" - slugify@1.6.6: version "1.6.6" resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.6.6.tgz#2d4ac0eacb47add6af9e04d3be79319cbcc7924b" @@ -9720,11 +9563,6 @@ stream-to-promise@^2.2.0: end-of-stream "~1.1.0" stream-to-array "~2.3.0" -string-argv@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" - integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== - string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -9742,15 +9580,6 @@ string-length@^4.0.1: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^5.0.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - string.prototype.padend@^3.0.0: version "3.1.4" resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.4.tgz#2c43bb3a89eb54b6750de5942c123d6c98dd65b6" @@ -9808,13 +9637,6 @@ strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" - integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== - dependencies: - ansi-regex "^6.0.1" - strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -9994,7 +9816,7 @@ through2@^4.0.0: dependencies: readable-stream "3" -through@2, "through@>=2.2.7 <3", through@^2.3.8: +through@2, "through@>=2.2.7 <3": version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== @@ -10557,15 +10379,6 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -10646,7 +10459,7 @@ yallist@^3.0.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yaml@2.2.2, yaml@^2.2.2: +yaml@2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.2.2.tgz#ec551ef37326e6d42872dad1970300f8eb83a073" integrity sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==