Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • master
1 result

Target

Select target project
  • smartdatalab/public/applications/renovate
1 result
Select Git revision
  • master
1 result
Show changes
Commits on Source (37)
Showing
with 273 additions and 49 deletions
FROM ghcr.io/containerbase/devcontainer:10.11.4 FROM ghcr.io/containerbase/devcontainer:10.11.6
...@@ -12,7 +12,13 @@ ...@@ -12,7 +12,13 @@
Discussions without reproductions are less likely to be converted to Issues. Discussions without reproductions are less likely to be converted to Issues.
To get started, please read our guide on creating a [minimal reproduction](https://github.com/renovatebot/renovate/blob/main/docs/development/minimal-reproductions.md). Please follow these steps:
1. Read our guide on creating a [minimal reproduction](https://github.com/renovatebot/renovate/blob/main/docs/development/minimal-reproductions.md).
2. Go to our [minimal reproduction template repository](https://github.com/renovatebot/minimal-reproduction-template).
3. Select the _Use this template_ button to create a new repository based on the template.
4. Work on the minimal reproduction in your own repository.
5. Fill out the information in your repository's `README.md`.
6. Add the link to your reproduction to the first post of your Discussion. If you are not the original author, you can post a new comment with the link.
Good luck, Good luck,
......
...@@ -406,7 +406,7 @@ jobs: ...@@ -406,7 +406,7 @@ jobs:
merge-multiple: true merge-multiple: true
- name: Codecov - name: Codecov
uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # v4.4.1 uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
with: with:
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}
directory: coverage/lcov directory: coverage/lcov
...@@ -632,7 +632,7 @@ jobs: ...@@ -632,7 +632,7 @@ jobs:
show-progress: false show-progress: false
- name: docker-config - name: docker-config
uses: containerbase/internal-tools@c1f30a1fe20205256d74fe28d8c114e857e30c23 # v3.0.94 uses: containerbase/internal-tools@f07c555495e8db875b0ac2f1ff8beb1f1430267b # v3.0.95
with: with:
command: docker-config command: docker-config
......
...@@ -41,7 +41,7 @@ jobs: ...@@ -41,7 +41,7 @@ jobs:
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@530d4feaa9c62aaab2d250371e2061eb7a172363 # v3.25.9 uses: github/codeql-action/init@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
with: with:
languages: javascript languages: javascript
...@@ -51,7 +51,7 @@ jobs: ...@@ -51,7 +51,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@530d4feaa9c62aaab2d250371e2061eb7a172363 # v3.25.9 uses: github/codeql-action/autobuild@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
# ℹ️ Command-line programs to run using the OS shell. # ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl # 📚 https://git.io/JvXDl
...@@ -65,4 +65,4 @@ jobs: ...@@ -65,4 +65,4 @@ jobs:
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@530d4feaa9c62aaab2d250371e2061eb7a172363 # v3.25.9 uses: github/codeql-action/analyze@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
...@@ -51,6 +51,6 @@ jobs: ...@@ -51,6 +51,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard. # Upload the results to GitHub's code scanning dashboard.
- name: 'Upload to code-scanning' - name: 'Upload to code-scanning'
uses: github/codeql-action/upload-sarif@530d4feaa9c62aaab2d250371e2061eb7a172363 # v3.25.9 uses: github/codeql-action/upload-sarif@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
with: with:
sarif_file: results.sarif sarif_file: results.sarif
...@@ -31,7 +31,7 @@ jobs: ...@@ -31,7 +31,7 @@ jobs:
format: 'sarif' format: 'sarif'
output: 'trivy-results.sarif' output: 'trivy-results.sarif'
- uses: github/codeql-action/upload-sarif@530d4feaa9c62aaab2d250371e2061eb7a172363 # v3.25.9 - uses: github/codeql-action/upload-sarif@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
with: with:
sarif_file: trivy-results.sarif sarif_file: trivy-results.sarif
category: 'docker-image-${{ matrix.tag }}' category: 'docker-image-${{ matrix.tag }}'
...@@ -24,12 +24,12 @@ Please read this section in full _before_ starting on your minimal reproduction. ...@@ -24,12 +24,12 @@ Please read this section in full _before_ starting on your minimal reproduction.
There are two methods to create a reproduction, see the table for a comparison. There are two methods to create a reproduction, see the table for a comparison.
| Start point | Method | Benefits | Drawbacks | | Start point | Method | Benefits | Drawbacks |
| :------------------- | :---------------------- | :-------------------------------- | :----------------------------------------- | | :------------------------------------------------------------------------------------------------ | :---------------------- | :-------------------------------- | :----------------------------------------- |
| Empty repo | Copy files and config | Minimal start point | Crafting the bad config/setup from scratch | | [our minimal reproduction template](https://github.com/renovatebot/minimal-reproduction-template) | Copy files and config | Minimal start point | Crafting the bad config/setup from scratch |
| Fork production repo | Remove files and config | Start with known bad config/setup | May need to edit/delete many files | | Fork production repo | Remove files and config | Start with known bad config/setup | May need to edit/delete many files |
Either method will work. Either method will work.
We recommend you start from an empty repository. We recommend you start from [our minimal reproduction template](https://github.com/renovatebot/minimal-reproduction-template).
### General steps ### General steps
...@@ -39,7 +39,7 @@ _Always_ follow these steps: ...@@ -39,7 +39,7 @@ _Always_ follow these steps:
1. Use the fewest number of repository files and dependencies 1. Use the fewest number of repository files and dependencies
1. Reduce your Renovate config to a minimum 1. Reduce your Renovate config to a minimum
1. Remove private or secret information 1. Remove private or secret information
1. Create a `readme.md` file and: 1. Create a `readme.md` file (or edit the template `readme.md`) and:
- Explain the _Current behavior_ and _Expected behavior_ - Explain the _Current behavior_ and _Expected behavior_
- Link to the Renovate Issue or Discussion - Link to the Renovate Issue or Discussion
- Use headings to organize the information - Use headings to organize the information
......
...@@ -384,7 +384,7 @@ To get access to the token a custom Renovate Docker image is needed that include ...@@ -384,7 +384,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: The Dockerfile to create such an image can look like this:
```Dockerfile ```Dockerfile
FROM renovate/renovate:37.399.10 FROM renovate/renovate:37.409.1
# Include the "Docker tip" which you can find here https://cloud.google.com/sdk/docs/install # Include the "Docker tip" which you can find here https://cloud.google.com/sdk/docs/install
# under "Installation" for "Debian/Ubuntu" # under "Installation" for "Debian/Ubuntu"
RUN ... RUN ...
......
...@@ -49,6 +49,23 @@ To disable the Dependency Dashboard, add the preset `:disableDependencyDashboard ...@@ -49,6 +49,23 @@ To disable the Dependency Dashboard, add the preset `:disableDependencyDashboard
This section explains some common use cases where having the Dependency Dashboard can help. This section explains some common use cases where having the Dependency Dashboard can help.
### Warnings for deprecated dependencies
If Renovate finds:
- packages flagged as deprecated on their registry, or
- packages that have a community-sourced replacement PR available
Then Renovate adds a prominent warning about these packages near the top of the Dependency Dashboard.
Here is an example of how this can look:
> The following dependencies are deprecated:
| Datasource | Name | Replacement? |
| ---------- | ------------------- | --------------------------------------------------------------------------------- |
| npm | `airbnb-prop-types` | ![Available](https://img.shields.io/badge/available-green?style=flat-square) |
| npm | `left-pad` | ![Unavailable](https://img.shields.io/badge/unavailable-orange?style=flat-square) |
### Visibility into rejected/deferred updates ### Visibility into rejected/deferred updates
Renovate's Dependency Dashboard shows an overview of all updates that are still "to do". Renovate's Dependency Dashboard shows an overview of all updates that are still "to do".
......
...@@ -968,11 +968,15 @@ uid Renovate Bot <renovate@whitesourcesoftware.com> ...@@ -968,11 +968,15 @@ uid Renovate Bot <renovate@whitesourcesoftware.com>
sub rsa4096 2021-09-10 [E] sub rsa4096 2021-09-10 [E]
``` ```
</details>
<!-- prettier-ignore --> <!-- prettier-ignore -->
!!! note !!! note
If you use GnuPG `v2.4` (or newer) to generate the key, then you must disable `AEAD` preferences. If you use GnuPG `v2.4` (or newer) to generate the key, then you must disable `AEAD` preferences.
This is needed to allow Renovate to decrypt the encrypted values. This is needed to allow Renovate to decrypt the encrypted values.
<details><summary>key edit log</summary>
```bash ```bash
❯ gpg --edit-key renovate@whitesourcesoftware.com ❯ gpg --edit-key renovate@whitesourcesoftware.com
gpg> showpref gpg> showpref
......
...@@ -6,9 +6,9 @@ description: Configuring Renovate to use Semantic Commits ...@@ -6,9 +6,9 @@ description: Configuring Renovate to use Semantic Commits
# Semantic Commit messages # Semantic Commit messages
Renovate looks at the last 10 commit messages in the base branch to decide if the repository uses semantic commits. Renovate looks at the last 10 commit messages in the base branch to decide if the repository uses semantic commits.
If there are semantic commits, Renovate uses the [conventional-commits-detector](https://github.com/conventional-changelog/conventional-commits-detector) to decide what convention the commit messages follow. If there are Semantic Commits, Renovate uses the [conventional-commits-detector](https://github.com/conventional-changelog/conventional-commits-detector) to decide what convention the commit messages follow.
Renovate only finds Angular-style conventional commits, it ignores other commit conventions. Renovate can only find Angular-style conventional commits, it does not "understand" other commit conventions.
When Renovate finds Angular-style commits, Renovate creates commit messages and PR titles like this: When Renovate finds Angular-style commits, Renovate creates commit messages and PR titles like this:
...@@ -24,15 +24,15 @@ There are some exceptions: ...@@ -24,15 +24,15 @@ There are some exceptions:
## Manually enabling or disabling semantic commits ## Manually enabling or disabling semantic commits
You can override the default settings, and disable or enable semantic commits. You can override the default settings, and disable or enable Semantic Commits.
```json title="If you want Renovate to use semantic commits" ```json title="If you want Renovate to use Semantic Commits"
{ {
"extends": [":semanticCommits"] "extends": [":semanticCommits"]
} }
``` ```
```json title="If you want Renovate to stop using semantic commits" ```json title="If you want Renovate to stop using Semantic Commits"
{ {
"extends": [":semanticCommitsDisabled"] "extends": [":semanticCommitsDisabled"]
} }
...@@ -65,7 +65,7 @@ For example: ...@@ -65,7 +65,7 @@ For example:
## Changing the Semantic Commit scope ## Changing the Semantic Commit scope
You can set your own word for the scope if you don't like the default "deps" scope. You can set your own word for the scope, if you do not like the default "deps" scope.
For example, to set the scope to "package", add the preset `":semanticCommitScope(package)"` to your `extends` array: For example, to set the scope to "package", add the preset `":semanticCommitScope(package)"` to your `extends` array:
```json ```json
...@@ -74,7 +74,7 @@ For example, to set the scope to "package", add the preset `":semanticCommitScop ...@@ -74,7 +74,7 @@ For example, to set the scope to "package", add the preset `":semanticCommitScop
} }
``` ```
To _remove_ the semantic commit scope, so Renovate uses `chore:` instead of `chore(deps):`, add the `":semanticCommitScopeDisabled"` preset to your `extends` array: To _remove_ the Semantic Commit scope, so Renovate uses `chore:` instead of `chore(deps):`, add the `":semanticCommitScopeDisabled"` preset to your `extends` array:
```json ```json
{ {
......
...@@ -514,7 +514,7 @@ const options: RenovateOptions[] = [ ...@@ -514,7 +514,7 @@ const options: RenovateOptions[] = [
description: description:
'Change this value to override the default Renovate sidecar image.', 'Change this value to override the default Renovate sidecar image.',
type: 'string', type: 'string',
default: 'ghcr.io/containerbase/sidecar:10.11.4', default: 'ghcr.io/containerbase/sidecar:10.11.6',
globalOnly: true, globalOnly: true,
}, },
{ {
......
...@@ -29,6 +29,7 @@ export const presets: Record<string, Preset> = { ...@@ -29,6 +29,7 @@ export const presets: Record<string, Preset> = {
'replacements:middie-to-scoped', 'replacements:middie-to-scoped',
'replacements:now-to-vercel', 'replacements:now-to-vercel',
'replacements:npm-run-all-to-maintenance-fork', 'replacements:npm-run-all-to-maintenance-fork',
'replacements:opencost-registry-move',
'replacements:parcel-css-to-lightningcss', 'replacements:parcel-css-to-lightningcss',
'replacements:passport-saml', 'replacements:passport-saml',
'replacements:react-query-devtools-to-scoped', 'replacements:react-query-devtools-to-scoped',
...@@ -743,6 +744,29 @@ export const presets: Record<string, Preset> = { ...@@ -743,6 +744,29 @@ export const presets: Record<string, Preset> = {
}, },
], ],
}, },
'opencost-registry-move': {
description: 'Replace OpenCost registry from quay.io to ghcr.io.',
packageRules: [
{
description:
'Replace `quay.io/kubecost1/kubecost-cost-model` with `ghcr.io/opencost/opencost`.',
matchCurrentVersion: '1.108.0',
matchDatasources: ['docker'],
matchPackageNames: ['quay.io/kubecost1/kubecost-cost-model'],
replacementName: 'ghcr.io/opencost/opencost',
replacementVersion: '1.109.0',
},
{
description:
'Replace `quay.io/kubecost1/opencost-ui` with `ghcr.io/opencost/opencost-ui`.',
matchCurrentVersion: '1.108.0',
matchDatasources: ['docker'],
matchPackageNames: ['quay.io/kubecost1/opencost-ui'],
replacementName: 'ghcr.io/opencost/opencost-ui',
replacementVersion: '1.109.0',
},
],
},
'parcel-css-to-lightningcss': { 'parcel-css-to-lightningcss': {
description: '`@parcel/css` was renamed to `lightningcss`.', description: '`@parcel/css` was renamed to `lightningcss`.',
packageRules: [ packageRules: [
......
import * as npmVersioning from '../../versioning/npm'; import * as npmVersioning from '../../versioning/npm';
import { Datasource } from '../datasource'; import { Datasource } from '../datasource';
import type { GetReleasesConfig, ReleaseResult } from '../types'; import type { GetReleasesConfig, ReleaseResult } from '../types';
import { defaultRegistryUrls as npmDefaultRegistryUrl } from './common';
import { getDependency } from './get'; import { getDependency } from './get';
export { setNpmrc } from './npmrc'; export { setNpmrc } from './npmrc';
...@@ -14,6 +15,8 @@ export class NpmDatasource extends Datasource { ...@@ -14,6 +15,8 @@ export class NpmDatasource extends Datasource {
override readonly defaultVersioning = npmVersioning.id; override readonly defaultVersioning = npmVersioning.id;
override readonly defaultRegistryUrls = npmDefaultRegistryUrl;
override readonly releaseTimestampSupport = true; override readonly releaseTimestampSupport = true;
override readonly releaseTimestampNote = override readonly releaseTimestampNote =
'The release timestamp is determined from the `time` field in the results.'; 'The release timestamp is determined from the `time` field in the results.';
......
import { codeBlock } from 'common-tags';
import { Fixtures } from '../../../../test/fixtures'; import { Fixtures } from '../../../../test/fixtures';
import { ClojureDatasource } from '../../datasource/clojure'; import { ClojureDatasource } from '../../datasource/clojure';
import { extractFromVectors, extractVariables, trimAtKey } from './extract'; import { extractFromVectors, extractVariables, trimAtKey } from './extract';
...@@ -10,6 +11,12 @@ describe('modules/manager/leiningen/extract', () => { ...@@ -10,6 +11,12 @@ describe('modules/manager/leiningen/extract', () => {
expect(trimAtKey('foo', 'bar')).toBeNull(); expect(trimAtKey('foo', 'bar')).toBeNull();
expect(trimAtKey(':dependencies ', 'dependencies')).toBeNull(); expect(trimAtKey(':dependencies ', 'dependencies')).toBeNull();
expect(trimAtKey(':dependencies \nfoobar', 'dependencies')).toBe('foobar'); expect(trimAtKey(':dependencies \nfoobar', 'dependencies')).toBe('foobar');
expect(
trimAtKey(
':parent-project {:coords [my-org/my-parent "4.3.0"]\n:inherit [:profiles]}',
'coords',
),
).toBe('[my-org/my-parent "4.3.0"]\n:inherit [:profiles]}');
}); });
it('extractFromVectors', () => { it('extractFromVectors', () => {
...@@ -48,6 +55,20 @@ describe('modules/manager/leiningen/extract', () => { ...@@ -48,6 +55,20 @@ describe('modules/manager/leiningen/extract', () => {
currentValue: '4.5.6', currentValue: '4.5.6',
}, },
]); ]);
expect(
extractFromVectors(
'[my-org/my-parent "4.3.0"]\n:inherit [:profiles]}',
{},
{},
1,
),
).toEqual([
{
datasource: ClojureDatasource.id,
depName: 'my-org:my-parent',
currentValue: '4.3.0',
},
]);
}); });
it('extractPackageFile', () => { it('extractPackageFile', () => {
...@@ -124,6 +145,95 @@ describe('modules/manager/leiningen/extract', () => { ...@@ -124,6 +145,95 @@ describe('modules/manager/leiningen/extract', () => {
}, },
], ],
}); });
const parentProjectSrc = codeBlock`
(defproject org.example/parent-project "1.0.0-SNAPSHOT"
:plugins [[lein-parent "0.3.9"]
[lein-project-version "0.1.0"]
[lein-shell "0.5.0"]]
:parent-project {:coords [my-org/my-parent "4.3.0"]
:inherit [:profiles :managed-dependencies :local-repo]}
:profiles {:cljfmt {:plugins [[lein-cljfmt "0.9.2"]]}}
:dependencies [[org.clojure/core.async "1.6.681"]
[org.clojure/core.match "1.1.0"]
[org.clojure/data.csv "1.1.0"]
[org.clojure/tools.cli "1.1.230"]
[metosin/malli "0.15.0"]])`;
expect(extractPackageFile(parentProjectSrc)).toMatchObject({
deps: [
{
depName: 'org.clojure:core.async',
datasource: 'clojure',
depType: 'dependencies',
registryUrls: [],
currentValue: '1.6.681',
},
{
depName: 'org.clojure:core.match',
datasource: 'clojure',
depType: 'dependencies',
registryUrls: [],
currentValue: '1.1.0',
},
{
depName: 'org.clojure:data.csv',
datasource: 'clojure',
depType: 'dependencies',
registryUrls: [],
currentValue: '1.1.0',
},
{
depName: 'org.clojure:tools.cli',
datasource: 'clojure',
depType: 'dependencies',
registryUrls: [],
currentValue: '1.1.230',
},
{
depName: 'metosin:malli',
datasource: 'clojure',
depType: 'dependencies',
registryUrls: [],
currentValue: '0.15.0',
},
{
depName: 'lein-parent:lein-parent',
datasource: 'clojure',
depType: 'plugins',
registryUrls: [],
currentValue: '0.3.9',
},
{
depName: 'lein-project-version:lein-project-version',
datasource: 'clojure',
depType: 'plugins',
registryUrls: [],
currentValue: '0.1.0',
},
{
depName: 'lein-shell:lein-shell',
datasource: 'clojure',
depType: 'plugins',
registryUrls: [],
currentValue: '0.5.0',
},
{
depName: 'lein-cljfmt:lein-cljfmt',
datasource: 'clojure',
depType: 'plugins',
registryUrls: [],
currentValue: '0.9.2',
},
{
depName: 'my-org:my-parent',
datasource: 'clojure',
depType: 'parent-project',
registryUrls: [],
currentValue: '4.3.0',
},
],
});
}); });
it('extractVariables', () => { it('extractVariables', () => {
......
...@@ -26,6 +26,7 @@ export function extractFromVectors( ...@@ -26,6 +26,7 @@ export function extractFromVectors(
str: string, str: string,
ctx: ExtractContext = {}, ctx: ExtractContext = {},
vars: ExtractedVariables = {}, vars: ExtractedVariables = {},
dimensions: 1 | 2 = 2,
): PackageDependency[] { ): PackageDependency[] {
if (!str.startsWith('[')) { if (!str.startsWith('[')) {
return []; return [];
...@@ -36,7 +37,8 @@ export function extractFromVectors( ...@@ -36,7 +37,8 @@ export function extractFromVectors(
let vecPos = 0; let vecPos = 0;
let artifactId = ''; let artifactId = '';
let version = ''; let version = '';
let commentLevel = 0; // Are we currently parsing a comment? If so, at what depth?
let commentLevel: number | null = null;
const isSpace = (ch: string | null): boolean => const isSpace = (ch: string | null): boolean =>
!!ch && regEx(/[\s,]/).test(ch); !!ch && regEx(/[\s,]/).test(ch);
...@@ -82,7 +84,7 @@ export function extractFromVectors( ...@@ -82,7 +84,7 @@ export function extractFromVectors(
if (char === '[') { if (char === '[') {
balance += 1; balance += 1;
if (balance === 2) { if (balance === dimensions) {
vecPos = 0; vecPos = 0;
} }
} else if (char === ']') { } else if (char === ']') {
...@@ -91,15 +93,17 @@ export function extractFromVectors( ...@@ -91,15 +93,17 @@ export function extractFromVectors(
if (commentLevel === balance) { if (commentLevel === balance) {
artifactId = ''; artifactId = '';
version = ''; version = '';
commentLevel = 0; commentLevel = null;
} }
if (balance === 1) { if (balance === dimensions - 1) {
yieldDep(); yieldDep();
} else if (balance === 0) { }
if (balance === 0) {
break; break;
} }
} else if (balance === 2) { } else if (balance === dimensions) {
if (isSpace(char)) { if (isSpace(char)) {
if (!isSpace(prevChar)) { if (!isSpace(prevChar)) {
vecPos += 1; vecPos += 1;
...@@ -170,20 +174,34 @@ export function extractVariables(content: string): ExtractedVariables { ...@@ -170,20 +174,34 @@ export function extractVariables(content: string): ExtractedVariables {
return result; return result;
} }
interface CollectDepsOptions {
nested: boolean;
depType?: string;
}
function collectDeps( function collectDeps(
content: string, content: string,
key: string, key: string,
registryUrls: string[], registryUrls: string[],
vars: ExtractedVariables, vars: ExtractedVariables,
options: CollectDepsOptions = {
nested: true,
},
): PackageDependency[] { ): PackageDependency[] {
const ctx = { const ctx = {
depType: key, depType: options.depType ?? key,
registryUrls, registryUrls,
}; };
// A vector like [["dep-1" "1.0.0"] ["dep-2" "0.0.0"]] is nested
// A vector like ["dep-1" "1.0.0"] is not
const dimensions = options.nested ? 2 : 1;
let result: PackageDependency[] = []; let result: PackageDependency[] = [];
let restContent = trimAtKey(content, key); let restContent = trimAtKey(content, key);
while (restContent) { while (restContent) {
result = [...result, ...extractFromVectors(restContent, ctx, vars)]; result = [
...result,
...extractFromVectors(restContent, ctx, vars, dimensions),
];
restContent = trimAtKey(restContent, key); restContent = trimAtKey(restContent, key);
} }
return result; return result;
...@@ -198,6 +216,19 @@ export function extractPackageFile(content: string): PackageFileContent { ...@@ -198,6 +216,19 @@ export function extractPackageFile(content: string): PackageFileContent {
...collectDeps(content, 'managed-dependencies', registryUrls, vars), ...collectDeps(content, 'managed-dependencies', registryUrls, vars),
...collectDeps(content, 'plugins', registryUrls, vars), ...collectDeps(content, 'plugins', registryUrls, vars),
...collectDeps(content, 'pom-plugins', registryUrls, vars), ...collectDeps(content, 'pom-plugins', registryUrls, vars),
// 'coords' is used in lein parent, and specifies zero or one
// dependencies. These are not wrapped in a vector in the way other
// dependencies are. The project.clj fragment looks like
//
// :parent-project {... :coords ["parent" "version"] ...}
//
// - https://github.com/achin/lein-parent
...collectDeps(content, 'coords', registryUrls, vars, {
nested: false,
// The top-level key is 'parent-project', but we skip directly to 'coords'.
// So fix the dep type label
depType: 'parent-project',
}),
]; ];
return { deps }; return { deps };
......
...@@ -201,16 +201,12 @@ function depHandler(ctx: Ctx): Ctx { ...@@ -201,16 +201,12 @@ function depHandler(ctx: Ctx): Ctx {
delete ctx.variableName; delete ctx.variableName;
const depName = `${groupId!}:${artifactId!}`; const depName = `${groupId!}:${artifactId!}`;
const isScala3 = scalaVersion?.[0] === '3';
const scalaVersionForPackageName = isScala3 ? '3' : scalaVersion;
const dep: PackageDependency = { const dep: PackageDependency = {
datasource: SbtPackageDatasource.id, datasource: SbtPackageDatasource.id,
depName, depName,
packageName: packageName:
scalaVersionForPackageName && useScalaVersion scalaVersion && useScalaVersion ? `${depName}_${scalaVersion}` : depName,
? `${depName}_${scalaVersionForPackageName}`
: depName,
currentValue, currentValue,
}; };
......
import { sortPackageFiles } from './util'; import { normalizeScalaVersion, sortPackageFiles } from './util';
describe('modules/manager/sbt/util', () => { describe('modules/manager/sbt/util', () => {
describe('sortPackageFiles()', () => { describe('sortPackageFiles()', () => {
...@@ -15,4 +15,41 @@ describe('modules/manager/sbt/util', () => { ...@@ -15,4 +15,41 @@ describe('modules/manager/sbt/util', () => {
]); ]);
}); });
}); });
describe('normalizeScalaVersion()', () => {
it('does not normalize prior to 2.10', () => {
const version = '2.9.3';
expect(normalizeScalaVersion(version)).toBe('2.9.3');
});
it('normalizes a Scala 2.10 version number', () => {
const version = '2.10.7';
expect(normalizeScalaVersion(version)).toBe('2.10');
});
it('normalizes a Scala 2.11 version number', () => {
const version = '2.11.12';
expect(normalizeScalaVersion(version)).toBe('2.11');
});
it('normalizes a Scala 2.12 version number', () => {
const version = '2.12.19';
expect(normalizeScalaVersion(version)).toBe('2.12');
});
it('normalizes a Scala 2.13 version number', () => {
const version = '2.13.14';
expect(normalizeScalaVersion(version)).toBe('2.13');
});
it('normalizes a Scala 3 LTS version number', () => {
const version = '3.3.3';
expect(normalizeScalaVersion(version)).toBe('3');
});
it('normalizes a Scala 3 current version number', () => {
const version = '3.4.2';
expect(normalizeScalaVersion(version)).toBe('3');
});
});
}); });
...@@ -21,9 +21,14 @@ export function normalizeScalaVersion(str: string): string { ...@@ -21,9 +21,14 @@ export function normalizeScalaVersion(str: string): string {
return str; return str;
} }
} }
const isScala3 = versioning.isGreaterThan(str, '3.0.0');
if (regEx(/^\d+\.\d+\.\d+$/).test(str)) { if (regEx(/^\d+\.\d+\.\d+$/).test(str)) {
if (isScala3) {
return str.replace(regEx(/^(\d+)\.(\d+)\.\d+$/), '$1');
} else {
return str.replace(regEx(/^(\d+)\.(\d+)\.\d+$/), '$1.$2'); return str.replace(regEx(/^(\d+)\.(\d+)\.\d+$/), '$1.$2');
} }
}
// istanbul ignore next // istanbul ignore next
return str; return str;
} }
......
...@@ -51,15 +51,6 @@ describe('util/emoji', () => { ...@@ -51,15 +51,6 @@ describe('util/emoji', () => {
expect(result).toEqual(text); expect(result).toEqual(text);
}); });
describe('unsupported characters', () => {
const unsupported = '🫠';
it('uses replacement character', () => {
setEmojiConfig({ unicodeEmoji: false });
expect(unemojify(unsupported)).toBe('');
});
});
it('converts warning emoji to shortcode', () => { it('converts warning emoji to shortcode', () => {
setEmojiConfig({ unicodeEmoji: false }); setEmojiConfig({ unicodeEmoji: false });
const emoji = '⚠️'; const emoji = '⚠️';
......