# <no value>
`versionFilter` allows to specify the kind of version retrieved from a resource and its version pattern.
Default value is "latest" as we want to retrieve the newest version from a resource.

A version filter accepts the following keys:

[cols="1,1,3",options=header]
|===
| Name | Default | Description

| `kind`
| `latest`
| One of `latest`, `lex`, `regex`, `semver`, `regex/semver`, `time`, `regex/time`, `pep440`. An unsupported value stops the run with an error.

| `pattern`
| depends on `kind`
| The constraint applied to the versions, interpreted according to `kind`. Defaults to `.*` for `regex`, `*` for `semver` and `pep440`, and `2006-01-02` for `time` and `regex/time`.

| `regex`
| -
| Used by `regex/semver` and `regex/time` only, to extract the version from a longer string. The **first capture group** is the value being filtered.

| `replaceall`
| -
| An optional find-and-replace applied to each version *before* the filter, with the sub-keys `pattern` (a regular expression) and `replacement` (which may reference capture groups with `$1`, `$2`, …).

| `strict`
| `false`
| Used by `semver` and `regex/semver` only. When `true`, only strictly formatted `MAJOR.MINOR.PATCH` versions are considered, so a lenient version such as `1.2` is dropped instead of being read as `1.2.0`.
|===

NOTE: Versions that cannot be parsed for the selected kind are silently skipped, not treated as errors. When nothing is left after filtering, the resource fails with "no version found".

==== latest

If kind is set to `latest` then there is no need to specify a pattern, as Updatecli returns the last
version provided by the resource, in the order the resource returned them.

IMPORTANT: `latest` does not compare versions, it trusts the ordering of the resource. For a Docker registry, that is the most recently pushed tag, which is not necessarily the highest version number. Use `semver` when you need the highest version.

===== Example

```
sources:
  kubectl:
    kind: githubRelease
    spec:
      owner: "kubernetes"
      repository: "kubectl"
      token: "{{ requiredEnv .github.token }}"
      username: "john"
      versionFilter:
        kind: latest
    transformers:
      - trimPrefix: "kubernetes-"
```
Return the latest Github release and remove "kubernetes-" from it.

==== Lex

If the kind is set to `lex` then Updatecli returns the latest version sorted lexicographically.

Sorting versions lexicographically means arranging them based on their lexicographic order, which is essentially alphabetical order as used in dictionaries, but applied to version strings.

For example, in lexicographic order:

    "1.10" comes before "1.2", because it compares character by character:
        Compare "1" vs. "1" → equal.
        Compare "." vs "." → equal.
        Compare "1" vs. "2" → "1" is smaller, so "1.10" < "1.2".

This ordering does not account for numerical values of version components. For meaningful version comparisons, semantic versioning is typically preferred, where "1.2" < "1.10" because "2" is numerically smaller than "10".

===== Example

```yaml
sources:
  ubuntu-focal:
    name: Get latest ubuntu focal docker image tag using regex/time versionfilter
    kind: dockerimage
    spec:
      image: ubuntu
      versionfilter:
        kind: lex
```

==== regex

If `versionFilter.kind` is set to `regex` then we can use `versionFilter.pattern` to specify a regular expression to
return the newest version returned from a resource matching the regex
If no versionFilter.pattern is provided then it uses '.*' which return the newest version

NOTE: Like `latest`, `regex` walks the versions in the order the resource returned them and stops on the first match, starting from the end. It filters, it does not sort. To compare version numbers, use `regex/semver`.

`versionFilter.replaceall` can optionally be used to transform version strings before the regex is applied.
It accepts a `pattern` (regex) and a `replacement` string, similar to a find-and-replace operation.

```
sources:
  kubectl:
    kind: githubRelease
    spec:
      owner: "kubernetes"
      repository: "kubectl"
      token: "{{ requiredEnv .github.token }}"
      username: "john"
      versionFilter:
        kind: regex
        pattern: "kubernetes-1.(\\d*).(\\d*)$"
    transformers:
      - trimPrefix: "kubernetes-"
```
=> Return the newest kubectl version matching pattern "kubernetes-1.(\\d*).(\\d*)$" and remove "kubernetes-" from it

===== Example with replaceall

Some projects use version tags that are not directly compatible with the regex pattern. For example, curl uses tags like
`curl-8_11_1` where underscores separate version components.
The `replaceall` option can be used to normalize these tags before applying the regex.

```yaml
sources:
  curl:
    kind: githubRelease
    spec:
      owner: "curl"
      repository: "curl"
      versionFilter:
        kind: regex
        pattern: 'curl-\d+\.\d+\.\d+'
        replaceall:
          pattern: "_"
          replacement: "."
```
=> The `replaceall` converts `curl-8_11_1` to `curl-8.11.1`, and the newest tag matching `pattern` is returned as `curl-8.11.1`

IMPORTANT: With `kind: regex`, the returned value is the whole transformed version, not a capture group - the `regex` key is ignored, only `pattern` is read. Use `kind: regex/semver` when you need to extract `8.11.1` out of `curl-8.11.1`, and add a `trimprefix` transformer otherwise.

==== semver

If `versionFilter.kind` is set to `semver` then we can use `versionFilter.pattern` to specify version pattern as explained link:https://github.com/Masterminds/semver#checking-version-constraints[here]. In the process we also sort.
If no `versionFilter.pattern` is provided then it falls back to '*' which returns the newest version.
Versions that do not respect semantic versioning are ignored.

Setting `versionFilter.strict` to `true` additionally rejects versions that are only loosely
semantic, such as `1.2` or `v1`, instead of completing them with zeros.

**Remark**

In the process we drop any characters not respecting semantic version like in this version "v1.0.0", we drop the "v" but we can add it back using `transformers`.

===== Autodiscovery patterns

On top of the standard constraints, `semver` accepts the following keywords, which are resolved
against the version currently in use. They are what the link:/docs/core/autodiscovery/[autodiscovery]
crawlers use to restrict the scope of an update.

[cols="1,3",options=header]
|===
| Pattern | Meaning

| `patch`
| Only patch updates, keeping the same major and minor.

| `minor`
| Minor and patch updates, keeping the same major.

| `minoronly`
| Minor updates only, excluding patch updates within the current minor.

| `major`
| Any update from the current major upwards.

| `majoronly`
| Major updates only.

| `prerelease`
| Pre-releases of the current version.
|===

===== Example

```
  jenkins-wiki-exporter:
    kind: githubRelease
    spec:
      owner: "jenkins-infra"
      repository: "jenkins-wiki-exporter"
      token: "{{ requiredEnv .github.token }}"
      username: "john"
      versionFilter:
        kind: semver
        pattern: "~1.10"
```
=> Return the version "v1.10.3"

==== regex/semver

If `versionFilter.kind` is set to `regex/semver` then we can use `versionFilter.regex` to specify a regular expression to extract version numbers.
The regular expression should return the semantic version in the first capturing group.
We can then use `versionFilter.pattern` to specify version pattern as explained link:https://github.com/Masterminds/semver#checking-version-constraints[here]. In the process we also sort.
If no `versionFilter.pattern` is provided then it falls back to '*' which returns the newest version.
Extracted values that do not respect semantic versioning are ignored.

`versionFilter.replaceall` can optionally be used to transform version strings before the regex is applied.
It accepts a `pattern` (regex) and a `replacement` string, similar to a find-and-replace operation.
See the link:#_regex[regex section] for an example.

IMPORTANT: The regular expression must define at least one capture group; a version without one is skipped. `pattern` filters the extracted value, `regex` extracts it (the two are not interchangeable).

===== Example

```
sources:
  default:
    name: Get latest version
    kind: githubrelease
    spec:
      owner: yarnpkg
      repository: berry
      token: '{{ requiredEnv "GITHUB_TOKEN" }}'
      versionfilter:
        kind: regex/semver
        regex: "@yarnpkg/cli/(\\d*\\.\\d*\\.\\d*)"
```
=> Return the version "4.5.3"

==== regex/time

If `versionFilter.kind` is set to `regex/time` then we can use `versionFilter.regex` to specify a regular expression to extract dates.
The regular expression should return the date in the first capturing group.
We can then use `versionFilter.pattern` to specify date pattern as explained link:https://golang.org/pkg/time/#Time.Format[here]. In the process we also sort.
If no `versionFilter.pattern` is provided then it falls back to '2006-01-02' which returns the newest version using date format YYYY-MM-DD.
Extracted values that do not match the date pattern are ignored.

To define your own format/pattern, write down what the reference time would look like formatted your way; The model is to demonstrate what the reference time looks like so that the Format and Parse methods can apply the same transformation to a general time value.

Here is a summary of the components of a layout string. Each element shows by example the formatting of an element of the reference time. Only these values are recognized. Text in the layout string that is not recognized as part of the reference time is echoed verbatim during Format and expected to appear verbatim in the input to Parse. 

```
Year: "2006" "06"
Month: "Jan" "January" "01" "1"
Day of the week: "Mon" "Monday"
Day of the month: "2" "_2" "02"
Day of the year: "__2" "002"
Hour: "15" "3" "03" (PM or AM)
Minute: "4" "04"
Second: "5" "05"
AM/PM mark: "PM"
```

You can get inspiration from the following examples

|===
| Pattern | Example
| 2006-01-02 | 2021-01-02 (YYYY-MM-DD)
| 20060102 | 20210102 (YYYYMMDD)
| 20060201 | 20260201 (YYYYDDMM)
|===

===== Example

```yaml
sources:
  ubuntu-focal:
    name: Get latest ubuntu focal docker image tag using regex/time versionfilter
    kind: dockerimage
    spec:
      image: ubuntu
      versionfilter:
        kind: 'regex/time'
        regex: '^focal-(\d*)$'
        pattern: "20060102"
```

==== time

If `versionFilter.kind` is set to `time` then we can use `versionFilter.pattern` to specify date pattern as explained link:https://golang.org/pkg/time/#Time.Format[here]. In the process we also sort.
If no `versionFilter.pattern` is provided then it fallback to '2006-01-02' which return the newest version using date format YYYY-MM-DD.
Please note date time not matching the pattern will be ignored.

To define your own format/pattern, write down what the reference time would look like formatted your way; The model is to demonstrate what the reference time looks like so that the Format and Parse methods can apply the same transformation to a general time value.

Here is a summary of the components of a layout string. Each element shows by example the formatting of an element of the reference time. Only these values are recognized. Text in the layout string that is not recognized as part of the reference time is echoed verbatim during Format and expected to appear verbatim in the input to Parse. 

```
Year: "2006" "06"
Month: "Jan" "January" "01" "1"
Day of the week: "Mon" "Monday"
Day of the month: "2" "_2" "02"
Day of the year: "__2" "002"
Hour: "15" "3" "03" (PM or AM)
Minute: "4" "04"
Second: "5" "05"
AM/PM mark: "PM"
```

You can get inspiration from the following examples

|===
| Pattern | Example
| 2006-01-02 | 2021-01-02 (YYYY-MM-DD)
| 20060102 | 20210102 (YYYYMMDD)
| 20060201 | 20260201 (YYYYDDMM)
|===


===== Example

```yaml
sources:
  ubuntu:
    name: Get latest ubuntu docker image tag using time versionfilter
    kind: dockerimage
    spec:
      image: ubuntu
      versionfilter:
        kind: 'time'
        pattern: "06.01"
```

==== pep440

If `versionFilter.kind` is set to `pep440` then versions are parsed and sorted according to the
Python https://peps.python.org/pep-0440/[PEP 440] specification, and `versionFilter.pattern` is a
PEP 440 specifier such as `>=1.0,<2.0`.
Versions that are not valid PEP 440 versions are ignored.

This is the right choice for Python packages, whose versions are not semantic versions: PEP 440
understands epochs (`1!2.0`), post-releases (`1.0.post1`), development releases (`1.0.dev1`), and
pre-release spellings such as `1.0rc1` or `1.0a1`, which `semver` rejects or misorders.

If no `versionFilter.pattern` is provided then it falls back to `*`.

IMPORTANT: With `*`, or with no pattern at all, Updatecli returns the newest **stable** version and only falls back to a pre-release when no stable version exists. An explicit specifier does not apply that preference: it returns the newest version satisfying it, pre-release or not.

===== Example

```yaml
sources:
  ansible:
    name: Get the latest stable Ansible release
    kind: pypi
    spec:
      name: ansible
      versionfilter:
        kind: pep440
```