diff --git a/lib/modules/manager/mix/index.ts b/lib/modules/manager/mix/index.ts index e9722265580591..df1fa52ec6cf6d 100644 --- a/lib/modules/manager/mix/index.ts +++ b/lib/modules/manager/mix/index.ts @@ -5,6 +5,7 @@ import { HexDatasource } from '../../datasource/hex'; export { extractPackageFile } from './extract'; export { updateArtifacts } from './artifacts'; +export { getRangeStrategy } from './range'; export const url = 'https://hexdocs.pm/mix/Mix.html'; export const categories: Category[] = ['elixir']; diff --git a/lib/modules/manager/mix/range.spec.ts b/lib/modules/manager/mix/range.spec.ts new file mode 100644 index 00000000000000..3b0ff9a3468637 --- /dev/null +++ b/lib/modules/manager/mix/range.spec.ts @@ -0,0 +1,48 @@ +import type { RangeConfig } from '../types'; +import { getRangeStrategy } from '.'; + +describe('modules/manager/mix/range', () => { + it('returns same if not auto', () => { + const config: RangeConfig = { rangeStrategy: 'pin' }; + expect(getRangeStrategy(config)).toBe('pin'); + + config.rangeStrategy = 'widen'; + expect(getRangeStrategy(config)).toBe('widen'); + }); + + it('widens complex bump', () => { + const config: RangeConfig = { + rangeStrategy: 'bump', + depType: 'prod', + currentValue: '>= 1.6.0 and < 2.0.0', + }; + expect(getRangeStrategy(config)).toBe('widen'); + }); + + it('bumps non-complex bump', () => { + const config: RangeConfig = { + rangeStrategy: 'bump', + depType: 'prod', + currentValue: '~>1.0.0', + }; + expect(getRangeStrategy(config)).toBe('bump'); + }); + + it('widens complex auto', () => { + const config: RangeConfig = { + rangeStrategy: 'auto', + depType: 'prod', + currentValue: '<1.7.0 or ~>1.7.1', + }; + expect(getRangeStrategy(config)).toBe('widen'); + }); + + it('defaults to update-lockfile', () => { + const config: RangeConfig = { + rangeStrategy: 'auto', + depType: 'prod', + }; + expect(getRangeStrategy(config)).toBe('update-lockfile'); + }); +}); + diff --git a/lib/modules/manager/mix/range.ts b/lib/modules/manager/mix/range.ts new file mode 100644 index 00000000000000..4d6e563eb5123e --- /dev/null +++ b/lib/modules/manager/mix/range.ts @@ -0,0 +1,26 @@ +import { parseRange } from 'semver-utils'; +import { logger } from '../../../logger'; +import type { RangeStrategy } from '../../../types'; +import type { RangeConfig } from '../types'; + +export function getRangeStrategy(config: RangeConfig): RangeStrategy { + const { currentValue, rangeStrategy } = config; + const isComplexRange = currentValue + ? parseRange(currentValue).length > 1 + : false; + + if (rangeStrategy === 'bump' && isComplexRange) { + logger.debug( + { currentValue }, + 'Replacing bump strategy for complex range with widen', + ); + return 'widen'; + } + if (rangeStrategy !== 'auto') { + return rangeStrategy; + } + if (isComplexRange) { + return 'widen'; + } + return 'update-lockfile'; +} diff --git a/lib/modules/manager/mix/readme.md b/lib/modules/manager/mix/readme.md index 175d75a9003123..7924c9704caa2e 100644 --- a/lib/modules/manager/mix/readme.md +++ b/lib/modules/manager/mix/readme.md @@ -6,3 +6,22 @@ The following `depTypes` are currently supported by the `mix` manager : - `prod`: all dependencies by default - `dev`: dependencies with [`:only` option](https://hexdocs.pm/mix/Mix.Tasks.Deps.html#module-dependency-definition-options) not containing `:prod` + +### Default `rangeStrategy=auto` behavior + +Renovate's default [`rangeStrategy`](../../../configuration-options.md#rangestrategy) is `"auto"`. +Here's how `"auto"` works with the `mix` manager: + +| Version type | New version | Old range | New range after update | What Renovate does | +| :----------------------- | :---------- | :-------------------- | :--------------------- | :------------------------------------------------------------------------ | +| Complex range | `1.7.2` | `< 1.7.0 or ~> 1.7.1` | `< 1.7.0 or ~> 1.7.2` | Widen range to include the new version. | +| Simple range | `0.39.0` | `<= 0.38.0` | `<= 0.39.0` | If update outside current range: widens range to include the new version. | +| Exact version constraint | `0.13.0` | `== 0.12.0` | `== 0.13.0` | Replace old version with new version. | + +### Recommended `rangeStrategy` for apps and libraries + +For applications, we recommend using `rangeStrategy=pin`. +This pins your dependencies to exact versions, which is generally considered [best practice for apps](../../../dependency-pinning.md). + +For libraries, use `rangeStrategy=widen` with version ranges in your `mix.exs`. +This allows for greater compatibility with other projects that may use your library as a dependency.