Merge branch 'main' into feat/flux-chartref

This commit is contained in:
ssams 2025-01-07 07:47:00 +01:00 committed by GitHub
commit a6a22d6716
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
66 changed files with 2488 additions and 1609 deletions

View file

@ -1 +1 @@
FROM ghcr.io/containerbase/devcontainer:13.4.5 FROM ghcr.io/containerbase/devcontainer:13.5.8

View file

@ -684,7 +684,7 @@ jobs:
show-progress: false show-progress: false
- name: docker-config - name: docker-config
uses: containerbase/internal-tools@f022a1677af8af9a36c53589e1b07edb932a3c84 # v3.5.10 uses: containerbase/internal-tools@c8f78cbc830d1883e695d06e3028136656e70f5b # v3.5.17
with: with:
command: docker-config command: docker-config

View file

@ -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@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 uses: github/codeql-action/init@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0
with: with:
languages: javascript languages: javascript
@ -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@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 uses: github/codeql-action/autobuild@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0
# 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:
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 uses: github/codeql-action/analyze@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0

View file

@ -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@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0
with: with:
sarif_file: results.sarif sarif_file: results.sarif

View file

@ -31,7 +31,7 @@ jobs:
format: 'sarif' format: 'sarif'
output: 'trivy-results.sarif' output: 'trivy-results.sarif'
- uses: github/codeql-action/upload-sarif@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 - uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0
with: with:
sarif_file: trivy-results.sarif sarif_file: trivy-results.sarif
category: 'docker-image-${{ matrix.tag }}' category: 'docker-image-${{ matrix.tag }}'

View file

@ -42,7 +42,7 @@ jobs:
run: pnpm prettier-fix run: pnpm prettier-fix
- name: Create pull request - name: Create pull request
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5 uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6
with: with:
author: 'Renovate Bot <renovate@whitesourcesoftware.com>' author: 'Renovate Bot <renovate@whitesourcesoftware.com>'
branch: 'chore/update-static-data' branch: 'chore/update-static-data'

View file

@ -2426,6 +2426,7 @@ Renovate only queries the OSV database for dependencies that use one of these da
- [`crate`](./modules/datasource/crate/index.md) - [`crate`](./modules/datasource/crate/index.md)
- [`go`](./modules/datasource/go/index.md) - [`go`](./modules/datasource/go/index.md)
- [`hackage`](./modules/datasource/hackage/index.md)
- [`hex`](./modules/datasource/hex/index.md) - [`hex`](./modules/datasource/hex/index.md)
- [`maven`](./modules/datasource/maven/index.md) - [`maven`](./modules/datasource/maven/index.md)
- [`npm`](./modules/datasource/npm/index.md) - [`npm`](./modules/datasource/npm/index.md)
@ -3357,6 +3358,7 @@ Table with options:
| `gomodTidyE` | Run `go mod tidy -e` after Go module updates. | | `gomodTidyE` | Run `go mod tidy -e` after Go module updates. |
| `gomodUpdateImportPaths` | Update source import paths on major module updates, using [mod](https://github.com/marwan-at-work/mod). | | `gomodUpdateImportPaths` | Update source import paths on major module updates, using [mod](https://github.com/marwan-at-work/mod). |
| `gomodSkipVendor` | Never run `go mod vendor` after Go module updates. | | `gomodSkipVendor` | Never run `go mod vendor` after Go module updates. |
| `gomodVendor` | Always run `go mod vendor` after Go module updates even if vendor files aren't detected. |
| `helmUpdateSubChartArchives` | Update subchart archives in the `/charts` folder. | | `helmUpdateSubChartArchives` | Update subchart archives in the `/charts` folder. |
| `npmDedupe` | Run `npm install` with `--prefer-dedupe` for npm >= 7 or `npm dedupe` after `package-lock.json` update for npm <= 6. | | `npmDedupe` | Run `npm install` with `--prefer-dedupe` for npm >= 7 or `npm dedupe` after `package-lock.json` update for npm <= 6. |
| `pnpmDedupe` | Run `pnpm dedupe --config.ignore-scripts=true` after `pnpm-lock.yaml` updates. | | `pnpmDedupe` | Run `pnpm dedupe --config.ignore-scripts=true` after `pnpm-lock.yaml` updates. |
@ -3705,6 +3707,7 @@ This feature works with the following managers:
- [`dockerfile`](modules/manager/dockerfile/index.md) - [`dockerfile`](modules/manager/dockerfile/index.md)
- [`droneci`](modules/manager/droneci/index.md) - [`droneci`](modules/manager/droneci/index.md)
- [`flux`](modules/manager/flux/index.md) - [`flux`](modules/manager/flux/index.md)
- [`github-actions`](modules/manager/github-actions/index.md)
- [`gitlabci`](modules/manager/gitlabci/index.md) - [`gitlabci`](modules/manager/gitlabci/index.md)
- [`helm-requirements`](modules/manager/helm-requirements/index.md) - [`helm-requirements`](modules/manager/helm-requirements/index.md)
- [`helm-values`](modules/manager/helm-values/index.md) - [`helm-values`](modules/manager/helm-values/index.md)

View file

@ -307,7 +307,7 @@ Renovate will get the credentials with the [`google-auth-library`](https://www.n
service_account: ${{ env.SERVICE_ACCOUNT }} service_account: ${{ env.SERVICE_ACCOUNT }}
- name: renovate - name: renovate
uses: renovatebot/github-action@v41.0.6 uses: renovatebot/github-action@v41.0.8
env: env:
RENOVATE_HOST_RULES: | RENOVATE_HOST_RULES: |
[ [
@ -478,7 +478,7 @@ Make sure to install the Google Cloud SDK into the custom image, as you need the
For example: For example:
```Dockerfile ```Dockerfile
FROM renovate/renovate:39.69.2 FROM renovate/renovate:39.91.0
# 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 ...

View file

@ -9,29 +9,42 @@ Requirements:
Create a `docker-compose.yaml` and `otel-collector-config.yml` file as seen below in a folder. Create a `docker-compose.yaml` and `otel-collector-config.yml` file as seen below in a folder.
```yaml title="docker-compose.yaml" ```yaml title="docker-compose.yaml"
version: '3' name: renovate-otel-demo
services: services:
# Jaeger # Jaeger for storing traces
jaeger: jaeger:
image: jaegertracing/all-in-one:1.64.0 image: jaegertracing/jaeger:2.1.0
ports: ports:
- '16686:16686' - '16686:16686' # Web UI
- '4317' - '4317' # OTLP gRPC
- '4318' # OTLP HTTP
# Prometheus for storing metrics
prometheus:
image: prom/prometheus:v3.1.0
ports:
- '9090:9090' # Web UI
- '4318' # OTLP HTTP
command:
- --web.enable-otlp-receiver
# Mirror these flags from the Dockerfile, because `command` overwrites the default flags.
# https://github.com/prometheus/prometheus/blob/5b5fee08af4c73230b2dae35964816f7b3c29351/Dockerfile#L23-L24
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.path=/prometheus
otel-collector: otel-collector:
# Using the Contrib version to access the spanmetrics connector.
# If you don't need the spanmetrics connector, you can use the standard version
image: otel/opentelemetry-collector-contrib:0.116.1 image: otel/opentelemetry-collector-contrib:0.116.1
command: ['--config=/etc/otel-collector-config.yml']
volumes: volumes:
- ./otel-collector-config.yml:/etc/otel-collector-config.yml - ./otel-collector-config.yml:/etc/otelcol-contrib/config.yaml
ports: ports:
- '1888:1888' # pprof extension - '4318:4318' # OTLP HTTP ( exposed to the host )
- '13133:13133' # health_check extension - '4317:4317' # OTLP gRPC ( exposed to the host )
- '55679:55679' # zpages extension
- '4318:4318' # OTLP HTTP
- '4317:4317' # OTLP GRPC
- '9123:9123' # Prometheus exporter
depends_on: depends_on:
- jaeger - jaeger
- prometheus
``` ```
```yaml title="otel-collector-config.yml" ```yaml title="otel-collector-config.yml"
@ -39,28 +52,36 @@ receivers:
otlp: otlp:
protocols: protocols:
grpc: grpc:
endpoint: 0.0.0.0:4317
http: http:
endpoint: 0.0.0.0:4318
exporters: exporters:
otlp/jaeger: otlp/jaeger:
endpoint: jaeger:4317 endpoint: jaeger:4317
tls: tls:
insecure: true insecure: true
logging: otlphttp/prometheus:
prometheus: endpoint: http://prometheus:9090/api/v1/otlp
endpoint: '0.0.0.0:9123' debug:
# verbosity: normal
processors: connectors:
batch:
spanmetrics: spanmetrics:
metrics_exporter: prometheus histogram:
latency_histogram_buckets: [10ms, 100ms, 250ms, 1s, 30s, 1m, 5m] exponential:
dimensions: dimensions:
- name: http.method - name: http.method
default: GET
- name: http.status_code - name: http.status_code
- name: http.host - name: http.host
dimensions_cache_size: 1000 dimensions_cache_size: 1000
aggregation_temporality: 'AGGREGATION_TEMPORALITY_CUMULATIVE' aggregation_temporality: 'AGGREGATION_TEMPORALITY_CUMULATIVE'
exemplars:
enabled: true
processors:
batch:
extensions: extensions:
health_check: health_check:
@ -72,12 +93,23 @@ service:
pipelines: pipelines:
traces: traces:
receivers: [otlp] receivers: [otlp]
exporters: [otlp/jaeger, logging] exporters:
processors: [spanmetrics, batch] - otlp/jaeger
# Send traces to connector for metrics calculation
- spanmetrics
# Enable debug exporter to see traces in the logs
#- debug
processors: [batch]
metrics: metrics:
receivers: [otlp] receivers:
exporters: [prometheus] - otlp # Receive metrics from Renovate.
- spanmetrics # Receive metrics calculated by the spanmetrics connector.
processors: [batch]
exporters:
- otlphttp/prometheus
# Enable debug exporter to see metrics in the logs
# - debug
``` ```
Start setup using this command inside the folder containing the files created in the earlier steps: Start setup using this command inside the folder containing the files created in the earlier steps:
@ -86,7 +118,11 @@ Start setup using this command inside the folder containing the files created in
docker-compose up docker-compose up
``` ```
This command will start an [OpenTelemetry Collector](https://github.com/open-telemetry/opentelemetry-collector-contrib) and an instance of [Jaeger](https://www.jaegertracing.io/). This command will start:
- an [OpenTelemetry Collector](https://github.com/open-telemetry/opentelemetry-collector-contrib)
- an instance of [Jaeger for traces](https://www.jaegertracing.io/)
- and [Prometheus](https://prometheus.io/)
Jaeger will be now reachable under [http://localhost:16686](http://localhost:16686). Jaeger will be now reachable under [http://localhost:16686](http://localhost:16686).
@ -97,7 +133,8 @@ To start Renovate with OpenTelemetry enabled run following command, after pointi
``` ```
docker run \ docker run \
--rm \ --rm \
-e OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 \ --network renovate-otel-demo_default \
-e OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318 \
-v "/path/to/your/config.js:/usr/src/app/config.js" \ -v "/path/to/your/config.js:/usr/src/app/config.js" \
renovate/renovate:latest renovate/renovate:latest
``` ```
@ -130,100 +167,90 @@ You should be able to see now the full trace view which shows each HTTP request
### Metrics ### Metrics
Additional to the received traces some metrics are calculated. Additional to the received traces some metrics are calculated.
This is achieved using the [spanmetricsprocessor](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/spanmetricsprocessor). This is achieved using the [spanmetrics connector](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/connector/spanmetricsconnector).
The previous implemented setup will produce following metrics, which are exposed under [http://localhost:9123/metrics](http://localhost:9123/metrics): The previously implemented setup will produce following metrics, which pushed to [Prometheus](http://localhost:9090):
``` ```
# HELP calls_total
# TYPE calls_total counter
### Example of internal spans ### Example of internal spans
calls_total{operation="renovate repository",service_name="renovate",span_kind="SPAN_KIND_INTERNAL",status_code="STATUS_CODE_UNSET"} 3 traces_span_metrics_calls_total{http_method="GET", job="renovatebot.com/renovate", service_name="renovate", span_kind="SPAN_KIND_INTERNAL", span_name="repository", status_code="STATUS_CODE_UNSET"} 2
calls_total{operation="run",service_name="renovate",span_kind="SPAN_KIND_INTERNAL",status_code="STATUS_CODE_UNSET"} 1 traces_span_metrics_calls_total{http_method="GET", job="renovatebot.com/renovate", service_name="renovate", span_kind="SPAN_KIND_INTERNAL", span_name="run", status_code="STATUS_CODE_UNSET"} 2
### Example of http calls from Renovate to external services
calls_total{http_host="api.github.com:443",http_method="POST",http_status_code="200",operation="HTTPS POST",service_name="renovate",span_kind="SPAN_KIND_CLIENT",status_code="STATUS_CODE_UNSET"} 9
...
# HELP latency
# TYPE latency histogram
### Example of internal spans
latency_bucket{operation="renovate repository",service_name="renovate",span_kind="SPAN_KIND_INTERNAL",status_code="STATUS_CODE_UNSET",le="0.1"} 0
...
latency_bucket{operation="renovate repository",service_name="renovate",span_kind="SPAN_KIND_INTERNAL",status_code="STATUS_CODE_UNSET",le="9.223372036854775e+12"} 3
latency_bucket{operation="renovate repository",service_name="renovate",span_kind="SPAN_KIND_INTERNAL",status_code="STATUS_CODE_UNSET",le="+Inf"} 3
latency_sum{operation="renovate repository",service_name="renovate",span_kind="SPAN_KIND_INTERNAL",status_code="STATUS_CODE_UNSET"} 30947.4689
latency_count{operation="renovate repository",service_name="renovate",span_kind="SPAN_KIND_INTERNAL",status_code="STATUS_CODE_UNSET"} 3
...
### Example of http calls from Renovate to external services ### Example of http calls from Renovate to external services
latency_bucket{http_host="api.github.com:443",http_method="POST",http_status_code="200",operation="HTTPS POST",service_name="renovate",span_kind="SPAN_KIND_CLIENT",status_code="STATUS_CODE_UNSET",le="0.1"} 0 traces_span_metrics_calls_total{http_host="api.github.com:443", http_method="POST", http_status_code="200", job="renovatebot.com/renovate", service_name="renovate", span_kind="SPAN_KIND_CLIENT", span_name="POST", status_code="STATUS_CODE_UNSET"} 4
### Example histogram metrics
traces_span_metrics_duration_milliseconds_bucket{http_method="GET", job="renovatebot.com/renovate", le="8", service_name="renovate", span_kind="SPAN_KIND_INTERNAL", span_name="repository", status_code="STATUS_CODE_UNSET"} 0
... ...
latency_bucket{http_host="api.github.com:443",http_method="POST",http_status_code="200",operation="HTTPS POST",service_name="renovate",span_kind="SPAN_KIND_CLIENT",status_code="STATUS_CODE_UNSET",le="250"} 3 traces_span_metrics_duration_milliseconds_bucket{http_method="GET", job="renovatebot.com/renovate", le="2000", service_name="renovate", span_kind="SPAN_KIND_INTERNAL", span_name="repository", status_code="STATUS_CODE_UNSET"} 0
latency_bucket{http_host="api.github.com:443",http_method="POST",http_status_code="200",operation="HTTPS POST",service_name="renovate",span_kind="SPAN_KIND_CLIENT",status_code="STATUS_CODE_UNSET",le="9.223372036854775e+12"} 9 traces_span_metrics_duration_milliseconds_bucket{http_method="GET", job="renovatebot.com/renovate", le="5000", service_name="renovate", span_kind="SPAN_KIND_INTERNAL", span_name="repository", status_code="STATUS_CODE_UNSET"} 1
latency_bucket{http_host="api.github.com:443",http_method="POST",http_status_code="200",operation="HTTPS POST",service_name="renovate",span_kind="SPAN_KIND_CLIENT",status_code="STATUS_CODE_UNSET",le="+Inf"} 9 traces_span_metrics_duration_milliseconds_bucket{http_method="GET", job="renovatebot.com/renovate", le="15000", service_name="renovate", span_kind="SPAN_KIND_INTERNAL", span_name="repository", status_code="STATUS_CODE_UNSET"} 1
latency_sum{http_host="api.github.com:443",http_method="POST",http_status_code="200",operation="HTTPS POST",service_name="renovate",span_kind="SPAN_KIND_CLIENT",status_code="STATUS_CODE_UNSET"} 2306.1385999999998 traces_span_metrics_duration_milliseconds_bucket{http_method="GET", job="renovatebot.com/renovate", le="10000", service_name="renovate", span_kind="SPAN_KIND_INTERNAL", span_name="repository", status_code="STATUS_CODE_UNSET"} 1
latency_count{http_host="api.github.com:443",http_method="POST",http_status_code="200",operation="HTTPS POST",service_name="renovate",span_kind="SPAN_KIND_CLIENT",status_code="STATUS_CODE_UNSET"} 9 traces_span_metrics_duration_milliseconds_bucket{http_method="GET", job="renovatebot.com/renovate", le="+Inf", service_name="renovate", span_kind="SPAN_KIND_INTERNAL", span_name="repository", status_code="STATUS_CODE_UNSET"} 1
traces_span_metrics_duration_milliseconds_sum{http_method="GET", job="renovatebot.com/renovate", service_name="renovate", span_kind="SPAN_KIND_INTERNAL", span_name="repository", status_code="STATUS_CODE_UNSET"} 4190.694209
traces_span_metrics_duration_milliseconds_count{http_method="GET", job="renovatebot.com/renovate", service_name="renovate", span_kind="SPAN_KIND_INTERNAL", span_name="repository", status_code="STATUS_CODE_UNSET"} 1
``` ```
The [spanmetricsprocessor](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/spanmetricsprocessor) creates two sets of metrics. The [spanmetrics connector](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/connector/spanmetricsconnector) creates two sets of metrics.
#### Calls metric #### Calls metric
At first there are the `calls_total` metrics which display how often specific trace spans have been observed. At first there are the `traces_span_metrics_calls_total` metrics.
These metrics show how often _specific_ trace spans have been observed.
For example: For example:
`calls_total{operation="renovate repository",service_name="renovate",span_kind="SPAN_KIND_INTERNAL",status_code="STATUS_CODE_UNSET"} 3` signals that 3 repositories have been renovated.
`calls_total{operation="run",service_name="renovate",span_kind="SPAN_KIND_INTERNAL",status_code="STATUS_CODE_UNSET"} 1` represents how often Renovate has been run. - `traces_span_metrics_calls_total{http_method="GET", job="renovatebot.com/renovate", service_name="renovate", span_kind="SPAN_KIND_INTERNAL", span_name="repositories", status_code="STATUS_CODE_UNSET"} 2` signals that 2 repositories have been renovated.
- `traces_span_metrics_calls_total{http_method="GET", job="renovatebot.com/renovate", service_name="renovate", span_kind="SPAN_KIND_INTERNAL", span_name="run", status_code="STATUS_CODE_UNSET"} 1` represents how often Renovate has been run.
If we combine this using the PrometheusQueryLanguage ( PromQL ), we can calculate the average count of repositories each Renovate run handles. If we combine this using the PrometheusQueryLanguage ( PromQL ), we can calculate the average count of repositories each Renovate run handles.
``` ```
calls_total{operation="renovate repository",service_name="renovate"} / calls_total{operation="run",service_name="renovate"} traces_span_metrics_calls_total{span_name="repository",service_name="renovate"} / traces_span_metrics_calls_total{span_name="run",service_name="renovate"}
``` ```
This metrics is also for spans generated by http calls: These metrics are generated for HTTP call spans too:
```yaml ```yaml
calls_total{http_host="registry.terraform.io:443",http_method="GET",http_status_code="200",operation="HTTPS GET",service_name="renovate",span_kind="SPAN_KIND_CLIENT",status_code="STATUS_CODE_UNSET"} 5 traces_span_metrics_calls_total{http_host="prometheus-community.github.io:443", http_method="GET", http_status_code="200", job="renovatebot.com/renovate", service_name="renovate", span_kind="SPAN_KIND_CLIENT", span_name="GET", status_code="STATUS_CODE_UNSET"} 5
``` ```
#### Latency buckets #### Latency buckets
The second class of metrics exposed are the latency focused latency buckets which allow to create [heatmaps](https://grafana.com/docs/grafana/latest/basics/intro-histograms/#heatmaps). The second class of metrics exposed are the latency-focused buckets, that allow creating [heatmaps](https://grafana.com/docs/grafana/latest/basics/intro-histograms/#heatmaps).
A request is added to a backed if the latency is bigger than the bucket value (`le`). `request_duration => le` A request is added to a backed if the latency is bigger than the bucket value (`le`). `request_duration => le`
As an example if we receive a request which need `1.533s` to complete get following metrics: As an example if we receive a request which need `1.533s` to complete get following metrics:
``` ```
latency_bucket{http_host="api.github.com:443",le="0.1"} 0 traces_span_metrics_duration_milliseconds_bucket{http_host="api.github.com:443",le="0.1"} 0
latency_bucket{http_host="api.github.com:443",le="1"} 0 traces_span_metrics_duration_milliseconds_bucket{http_host="api.github.com:443",le="1"} 0
latency_bucket{http_host="api.github.com:443",le="2"} 1 traces_span_metrics_duration_milliseconds_bucket{http_host="api.github.com:443",le="2"} 1
latency_bucket{http_host="api.github.com:443",le="6"} 1 traces_span_metrics_duration_milliseconds_bucket{http_host="api.github.com:443",le="6"} 1
latency_bucket{http_host="api.github.com:443",le="10"} 1 traces_span_metrics_duration_milliseconds_bucket{http_host="api.github.com:443",le="10"} 1
latency_bucket{http_host="api.github.com:443",le="100"} 1 traces_span_metrics_duration_milliseconds_bucket{http_host="api.github.com:443",le="100"} 1
latency_bucket{http_host="api.github.com:443",le="250"} 1 traces_span_metrics_duration_milliseconds_bucket{http_host="api.github.com:443",le="250"} 1
latency_bucket{http_host="api.github.com:443",le="9.223372036854775e+12"} 1 traces_span_metrics_duration_milliseconds_bucket{http_host="api.github.com:443",le="9.223372036854775e+12"} 1
latency_bucket{http_host="api.github.com:443",le="+Inf"} 1 traces_span_metrics_duration_milliseconds_bucket{http_host="api.github.com:443",le="+Inf"} 1
latency_sum{http_host="api.github.com:443"} 1.533 traces_span_metrics_duration_milliseconds_sum{http_host="api.github.com:443"} 1.533
latency_count{http_host="api.github.com:443"} 1 traces_span_metrics_duration_milliseconds_count{http_host="api.github.com:443"} 1
``` ```
Now we have another request which this time takes 10s to complete: Now we have another request which this time takes 10s to complete:
``` ```
latency_bucket{http_host="api.github.com:443",le="0.1"} 0 traces_span_metrics_duration_milliseconds_bucket{http_host="api.github.com:443",le="0.1"} 0
latency_bucket{http_host="api.github.com:443",le="1"} 0 traces_span_metrics_duration_milliseconds_bucket{http_host="api.github.com:443",le="1"} 0
latency_bucket{http_host="api.github.com:443",le="2"} 1 traces_span_metrics_duration_milliseconds_bucket{http_host="api.github.com:443",le="2"} 1
latency_bucket{http_host="api.github.com:443",le="6"} 1 traces_span_metrics_duration_milliseconds_bucket{http_host="api.github.com:443",le="6"} 1
latency_bucket{http_host="api.github.com:443",le="10"} 2 traces_span_metrics_duration_milliseconds_bucket{http_host="api.github.com:443",le="10"} 2
latency_bucket{http_host="api.github.com:443",le="100"} 2 traces_span_metrics_duration_milliseconds_bucket{http_host="api.github.com:443",le="100"} 2
latency_bucket{http_host="api.github.com:443",le="250"} 2 traces_span_metrics_duration_milliseconds_bucket{http_host="api.github.com:443",le="250"} 2
latency_bucket{http_host="api.github.com:443",le="9.223372036854775e+12"} 2 traces_span_metrics_duration_milliseconds_bucket{http_host="api.github.com:443",le="9.223372036854775e+12"} 2
latency_bucket{http_host="api.github.com:443",le="+Inf"} 2 traces_span_metrics_duration_milliseconds_bucket{http_host="api.github.com:443",le="+Inf"} 2
latency_sum{http_host="api.github.com:443"} 11.533 traces_span_metrics_duration_milliseconds_sum{http_host="api.github.com:443"} 11.533
latency_count{http_host="api.github.com:443"} 2 traces_span_metrics_duration_milliseconds_count{http_host="api.github.com:443"} 2
``` ```
More about the functionality can be found on the Prometheus page for [metric types](https://prometheus.io/docs/concepts/metric_types/#histogram). More about the functionality can be found on the Prometheus page for [metric types](https://prometheus.io/docs/concepts/metric_types/#histogram).

View file

@ -25,8 +25,8 @@ It builds `latest` based on the `main` branch and all SemVer tags are published
```sh title="Example of valid tags" ```sh title="Example of valid tags"
docker run --rm renovate/renovate docker run --rm renovate/renovate
docker run --rm renovate/renovate:39 docker run --rm renovate/renovate:39
docker run --rm renovate/renovate:39.69 docker run --rm renovate/renovate:39.91
docker run --rm renovate/renovate:39.69.2 docker run --rm renovate/renovate:39.91.0
``` ```
<!-- prettier-ignore --> <!-- prettier-ignore -->
@ -62,7 +62,7 @@ spec:
- name: renovate - name: renovate
# Update this to the latest available and then enable Renovate on # Update this to the latest available and then enable Renovate on
# the manifest # the manifest
image: renovate/renovate:39.69.2 image: renovate/renovate:39.91.0
args: args:
- user/repo - user/repo
# Environment Variables # Environment Variables
@ -121,7 +121,7 @@ spec:
template: template:
spec: spec:
containers: containers:
- image: renovate/renovate:39.69.2 - image: renovate/renovate:39.91.0
name: renovate-bot name: renovate-bot
env: # For illustration purposes, please use secrets. env: # For illustration purposes, please use secrets.
- name: RENOVATE_PLATFORM - name: RENOVATE_PLATFORM
@ -367,7 +367,7 @@ spec:
containers: containers:
- name: renovate - name: renovate
# Update this to the latest available and then enable Renovate on the manifest # Update this to the latest available and then enable Renovate on the manifest
image: renovate/renovate:39.69.2 image: renovate/renovate:39.91.0
volumeMounts: volumeMounts:
- name: ssh-key-volume - name: ssh-key-volume
readOnly: true readOnly: true

View file

@ -12,6 +12,7 @@ describe('config/decrypt', () => {
beforeEach(() => { beforeEach(() => {
config = {}; config = {};
GlobalConfig.reset(); GlobalConfig.reset();
delete process.env.MEND_HOSTED;
delete process.env.RENOVATE_X_ENCRYPTED_STRICT; delete process.env.RENOVATE_X_ENCRYPTED_STRICT;
}); });
@ -34,8 +35,19 @@ describe('config/decrypt', () => {
it('throws exception if encrypted found but no privateKey', async () => { it('throws exception if encrypted found but no privateKey', async () => {
config.encrypted = { a: '1' }; config.encrypted = { a: '1' };
process.env.RENOVATE_X_ENCRYPTED_STRICT = 'true';
process.env.RENOVATE_X_ENCRYPTED_STRICT = 'true';
await expect(decryptConfig(config, repository)).rejects.toThrow(
'config-validation',
);
});
// coverage
it('throws exception if encrypted found but no privateKey- Mend Hosted', async () => {
config.encrypted = { a: '1' };
process.env.MEND_HOSTED = 'true';
process.env.RENOVATE_X_ENCRYPTED_STRICT = 'true';
await expect(decryptConfig(config, repository)).rejects.toThrow( await expect(decryptConfig(config, repository)).rejects.toThrow(
'config-validation', 'config-validation',
); );

View file

@ -179,6 +179,12 @@ export async function decryptConfig(
error.validationSource = 'config'; error.validationSource = 'config';
error.validationError = 'Encrypted config unsupported'; error.validationError = 'Encrypted config unsupported';
error.validationMessage = `This config contains an encrypted object at location \`$.${key}\` but no privateKey is configured. To support encrypted config, the Renovate administrator must configure a \`privateKey\` in Global Configuration.`; error.validationMessage = `This config contains an encrypted object at location \`$.${key}\` but no privateKey is configured. To support encrypted config, the Renovate administrator must configure a \`privateKey\` in Global Configuration.`;
if (process.env.MEND_HOSTED === 'true') {
error.validationMessage = `Mend-hosted Renovate Apps no longer support the use of encrypted secrets in Renovate file config (e.g. renovate.json).
Please migrate all secrets to the Developer Portal using the web UI available at https://developer.mend.io/
Refer to migration documents here: https://docs.renovatebot.com/mend-hosted/migrating-secrets/`;
}
throw error; throw error;
} else { } else {
logger.error('Found encrypted data but no privateKey'); logger.error('Found encrypted data but no privateKey');

View file

@ -516,7 +516,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:13.4.5', default: 'ghcr.io/containerbase/sidecar:13.5.8',
globalOnly: true, globalOnly: true,
}, },
{ {
@ -2390,6 +2390,7 @@ const options: RenovateOptions[] = [
'gomodTidyE', 'gomodTidyE',
'gomodUpdateImportPaths', 'gomodUpdateImportPaths',
'gomodSkipVendor', 'gomodSkipVendor',
'gomodVendor',
'helmUpdateSubChartArchives', 'helmUpdateSubChartArchives',
'npmDedupe', 'npmDedupe',
'pnpmDedupe', 'pnpmDedupe',

View file

@ -74,6 +74,7 @@ const renamedMonorepos: Record<string, string> = {
Steeltoe: 'steeltoe', Steeltoe: 'steeltoe',
stryker: 'stryker-js', stryker: 'stryker-js',
Swashbuckle: 'swashbuckle-aspnetcore', Swashbuckle: 'swashbuckle-aspnetcore',
nrwl: 'nx',
}; };
for (const [from, to] of Object.entries(renamedMonorepos)) { for (const [from, to] of Object.entries(renamedMonorepos)) {

View file

@ -4,7 +4,7 @@ import type { Preset } from '../types';
export const presets: Record<string, Preset> = { export const presets: Record<string, Preset> = {
safeEnv: { safeEnv: {
allowedEnv: ['GO*'], allowedEnv: ['GO*', 'RUSTC_BOOTSTRAP'],
description: description:
'Hopefully safe environment variables to allow users to configure.', 'Hopefully safe environment variables to allow users to configure.',
}, },

View file

@ -316,9 +316,10 @@ const staticGroups = {
'k8s.io/cluster-bootstrap**', 'k8s.io/cluster-bootstrap**',
'k8s.io/code-generator**', 'k8s.io/code-generator**',
'k8s.io/component-base**', 'k8s.io/component-base**',
'k8s.io/component-helpers**',
'k8s.io/controller-manager**', 'k8s.io/controller-manager**',
'k8s.io/cri-api**', 'k8s.io/cri-api**',
// 'k8s.io/csi-api', has not go.mod set up and does not follow the versioning of other repos // 'k8s.io/csi-api', has no go.mod set up and does not follow the versioning of other repos
'k8s.io/csi-translation-lib**', 'k8s.io/csi-translation-lib**',
'k8s.io/kube-aggregator**', 'k8s.io/kube-aggregator**',
'k8s.io/kube-controller-manager**', 'k8s.io/kube-controller-manager**',
@ -450,7 +451,11 @@ const staticGroups = {
packageRules: [ packageRules: [
{ {
groupName: 'react monorepo', groupName: 'react monorepo',
matchPackageNames: ['@types/react', '@types/react-dom'], matchPackageNames: [
'@types/react',
'@types/react-dom',
'@types/react-is',
],
}, },
], ],
}, },

View file

@ -306,6 +306,9 @@ export interface RenovateConfig
statusCheckNames?: Record<StatusCheckKey, string | null>; statusCheckNames?: Record<StatusCheckKey, string | null>;
env?: UserEnv; env?: UserEnv;
logLevelRemap?: LogLevelRemap[]; logLevelRemap?: LogLevelRemap[];
branchTopic?: string;
additionalBranchPrefix?: string;
} }
const CustomDatasourceFormats = ['json', 'plain', 'yaml', 'html'] as const; const CustomDatasourceFormats = ['json', 'plain', 'yaml', 'html'] as const;

View file

@ -55,10 +55,7 @@
"https://github.com/awslabs/aws-sdk-rust" "https://github.com/awslabs/aws-sdk-rust"
], ],
"awsappsync": "https://github.com/awslabs/aws-mobile-appsync-sdk-js", "awsappsync": "https://github.com/awslabs/aws-mobile-appsync-sdk-js",
"axis2": [ "axum": "https://github.com/tokio-rs/axum",
"https://gitbox.apache.org/repos/asf?p=axis-axis2-java-core.git;a=summary",
"https://github.com/apache/axis-axis2-java-core"
],
"azure-functions-dotnet-worker": "https://github.com/Azure/azure-functions-dotnet-worker", "azure-functions-dotnet-worker": "https://github.com/Azure/azure-functions-dotnet-worker",
"azure azure-libraries-for-net": "https://github.com/Azure/azure-libraries-for-net", "azure azure-libraries-for-net": "https://github.com/Azure/azure-libraries-for-net",
"azure azure-sdk-for-net": "https://github.com/Azure/azure-sdk-for-net", "azure azure-sdk-for-net": "https://github.com/Azure/azure-sdk-for-net",
@ -439,6 +436,8 @@
"opentelemetry-java-contrib": "https://github.com/open-telemetry/opentelemetry-java-contrib", "opentelemetry-java-contrib": "https://github.com/open-telemetry/opentelemetry-java-contrib",
"opentelemetry-js": "https://github.com/open-telemetry/opentelemetry-js", "opentelemetry-js": "https://github.com/open-telemetry/opentelemetry-js",
"opentelemetry-js-contrib": "https://github.com/open-telemetry/opentelemetry-js-contrib", "opentelemetry-js-contrib": "https://github.com/open-telemetry/opentelemetry-js-contrib",
"opentelemetry-python": "https://github.com/open-telemetry/opentelemetry-python",
"opentelemetry-python-contrib": "https://github.com/open-telemetry/opentelemetry-python-contrib",
"opentelemetry-rust": "https://github.com/open-telemetry/opentelemetry-rust", "opentelemetry-rust": "https://github.com/open-telemetry/opentelemetry-rust",
"opentelemetry-rust-contrib": "https://github.com/open-telemetry/opentelemetry-rust-contrib", "opentelemetry-rust-contrib": "https://github.com/open-telemetry/opentelemetry-rust-contrib",
"orleans": "https://github.com/dotnet/orleans", "orleans": "https://github.com/dotnet/orleans",
@ -509,6 +508,7 @@
"skiasharp": "https://github.com/mono/SkiaSharp", "skiasharp": "https://github.com/mono/SkiaSharp",
"slack-net": "https://github.com/soxtoby/SlackNet", "slack-net": "https://github.com/soxtoby/SlackNet",
"slf4j": "https://github.com/qos-ch/slf4j", "slf4j": "https://github.com/qos-ch/slf4j",
"slim-message-bus": "https://github.com/zarusz/SlimMessageBus",
"spectre-console": "https://github.com/spectreconsole/spectre.console", "spectre-console": "https://github.com/spectreconsole/spectre.console",
"springfox": "https://github.com/springfox/springfox", "springfox": "https://github.com/springfox/springfox",
"steeltoe": "https://github.com/SteeltoeOSS/steeltoe", "steeltoe": "https://github.com/SteeltoeOSS/steeltoe",
@ -587,7 +587,7 @@
"hapijs": "https://github.com/hapijs/", "hapijs": "https://github.com/hapijs/",
"lodash": "https://github.com/lodash/", "lodash": "https://github.com/lodash/",
"ngrx": "https://github.com/ngrx/", "ngrx": "https://github.com/ngrx/",
"nrwl": "https://github.com/nrwl/", "nx": "https://github.com/nrwl/nx",
"octokit": "https://github.com/octokit/", "octokit": "https://github.com/octokit/",
"semantic-release": "https://github.com/semantic-release/", "semantic-release": "https://github.com/semantic-release/",
"swc": "https://github.com/swc-project/" "swc": "https://github.com/swc-project/"
@ -598,12 +598,17 @@
"apache-poi": "/^org.apache.poi:/", "apache-poi": "/^org.apache.poi:/",
"aws-java-sdk": "/^com.amazonaws:aws-java-sdk-/", "aws-java-sdk": "/^com.amazonaws:aws-java-sdk-/",
"aws-java-sdk-v2": "/^software.amazon.awssdk:/", "aws-java-sdk-v2": "/^software.amazon.awssdk:/",
"axis2": "/^org.apache.axis2:/",
"babel6": "/^babel6$/", "babel6": "/^babel6$/",
"clarity": ["/^@cds//", "/^@clr//"], "clarity": ["/^@cds//", "/^@clr//"],
"embroider": "/^@embroider//", "embroider": "/^@embroider//",
"forge": "/^@forge//", "forge": "/^@forge//",
"fullcalendar": "/^@fullcalendar//", "fullcalendar": "/^@fullcalendar//",
"hotchocolate": "/^HotChocolate\\./", "hotchocolate": "/^HotChocolate\\./",
"oracle-database": [
"/^com.oracle.database.jdbc:/",
"/^com.oracle.database.nls:/"
],
"prometheus-simpleclient": "/^io.prometheus:simpleclient/", "prometheus-simpleclient": "/^io.prometheus:simpleclient/",
"russh": ["/^russh$/", "/^russh-keys$/"], "russh": ["/^russh$/", "/^russh-keys$/"],
"spfx": ["/^@microsoft/sp-/", "/^@microsoft/eslint-.+-spfx$/"], "spfx": ["/^@microsoft/sp-/", "/^@microsoft/eslint-.+-spfx$/"],

View file

@ -59,10 +59,12 @@ describe('instrumentation/index', () => {
_registeredSpanProcessors: [ _registeredSpanProcessors: [
{ {
_exporter: { _exporter: {
_transport: { _delegate: {
_transport: { _transport: {
_parameters: { _transport: {
url: 'https://collector.example.com/v1/traces', _parameters: {
url: 'https://collector.example.com/v1/traces',
},
}, },
}, },
}, },
@ -88,10 +90,12 @@ describe('instrumentation/index', () => {
{ _exporter: {} }, { _exporter: {} },
{ {
_exporter: { _exporter: {
_transport: { _delegate: {
_transport: { _transport: {
_parameters: { _transport: {
url: 'https://collector.example.com/v1/traces', _parameters: {
url: 'https://collector.example.com/v1/traces',
},
}, },
}, },
}, },

View file

@ -58,6 +58,7 @@ describe('modules/datasource/github-runners/index', () => {
{ version: '2016', isDeprecated: true }, { version: '2016', isDeprecated: true },
{ version: '2019' }, { version: '2019' },
{ version: '2022' }, { version: '2022' },
{ version: '2025', isStable: false },
], ],
sourceUrl: 'https://github.com/actions/runner-images', sourceUrl: 'https://github.com/actions/runner-images',
}); });

View file

@ -39,6 +39,7 @@ export class GithubRunnersDatasource extends Datasource {
{ version: '10.15', isDeprecated: true }, { version: '10.15', isDeprecated: true },
], ],
windows: [ windows: [
{ version: '2025', isStable: false },
{ version: '2022' }, { version: '2022' },
{ version: '2019' }, { version: '2019' },
{ version: '2016', isDeprecated: true }, { version: '2016', isDeprecated: true },

View file

@ -494,7 +494,10 @@ describe('modules/datasource/go/releases-goproxy', () => {
.get('.v2/@latest') .get('.v2/@latest')
.reply(200, { Version: 'v2.4.0' }) .reply(200, { Version: 'v2.4.0' })
.get('.v3/@v/list') .get('.v3/@v/list')
.reply(200, ['v3.0.0', 'v3.0.1', ' \n'].join('\n')) .reply(
200,
['v1.0.0', 'v2.0.0', 'v3.0.0', 'v3.0.1', 'v4.0.0', ' \n'].join('\n'),
)
.get('.v3/@v/v3.0.0.info') .get('.v3/@v/v3.0.0.info')
.reply(200, { Version: 'v3.0.0', Time: '2022-05-21T10:33:21Z' }) .reply(200, { Version: 'v3.0.0', Time: '2022-05-21T10:33:21Z' })
.get('.v3/@v/v3.0.1.info') .get('.v3/@v/v3.0.1.info')

View file

@ -217,7 +217,20 @@ export class GoProxyDatasource extends Datasource {
try { try {
const res = await this.listVersions(baseUrl, pkg); const res = await this.listVersions(baseUrl, pkg);
releases = await p.map(res, async (versionInfo) => {
// Artifactory returns all versions in any major (past and future),
// so starting from v2, we filter them in order to avoid the infinite loop
const filteredReleases = res.filter(({ version }) => {
if (major < 2) {
return true;
}
return (
version.split(regEx(/[^\d]+/)).find(is.truthy) === major.toString()
);
});
releases = await p.map(filteredReleases, async (versionInfo) => {
const { version, newDigest, releaseTimestamp } = versionInfo; const { version, newDigest, releaseTimestamp } = versionInfo;
if (releaseTimestamp) { if (releaseTimestamp) {

View file

@ -4,7 +4,7 @@ exports[`modules/datasource/orb/index getReleases processes homeUrl 1`] = `
{ {
"homepage": "https://google.com", "homepage": "https://google.com",
"isPrivate": false, "isPrivate": false,
"registryUrl": "https://circleci.com/", "registryUrl": "https://circleci.com",
"releases": [ "releases": [
{ {
"releaseTimestamp": "2018-12-11T05:28:14.080Z", "releaseTimestamp": "2018-12-11T05:28:14.080Z",
@ -53,7 +53,7 @@ exports[`modules/datasource/orb/index getReleases processes real data 1`] = `
{ {
"homepage": "https://circleci.com/developer/orbs/orb/hyper-expanse/library-release-workflows", "homepage": "https://circleci.com/developer/orbs/orb/hyper-expanse/library-release-workflows",
"isPrivate": false, "isPrivate": false,
"registryUrl": "https://circleci.com/", "registryUrl": "https://circleci.com",
"releases": [ "releases": [
{ {
"releaseTimestamp": "2018-12-11T05:28:14.080Z", "releaseTimestamp": "2018-12-11T05:28:14.080Z",

View file

@ -92,5 +92,18 @@ describe('modules/datasource/orb/index', () => {
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
expect(res?.homepage).toBe('https://google.com'); expect(res?.homepage).toBe('https://google.com');
}); });
it('supports other registries', async () => {
httpMock
.scope('https://cci.internal.dev')
.post('/graphql-unstable')
.reply(200, orbData);
const res = await getPkgReleases({
datasource,
packageName: 'hyper-expanse/library-release-workflows',
registryUrls: ['https://cci.internal.dev'],
});
expect(res?.registryUrl).toBe('https://cci.internal.dev');
});
}); });
}); });

View file

@ -1,5 +1,6 @@
import { logger } from '../../../logger'; import { logger } from '../../../logger';
import { cache } from '../../../util/cache/package/decorator'; import { cache } from '../../../util/cache/package/decorator';
import { joinUrlParts } from '../../../util/url';
import { Datasource } from '../datasource'; import { Datasource } from '../datasource';
import type { GetReleasesConfig, ReleaseResult } from '../types'; import type { GetReleasesConfig, ReleaseResult } from '../types';
import type { OrbResponse } from './types'; import type { OrbResponse } from './types';
@ -27,9 +28,10 @@ export class OrbDatasource extends Datasource {
super(OrbDatasource.id); super(OrbDatasource.id);
} }
override readonly customRegistrySupport = false; override readonly customRegistrySupport = true;
override readonly defaultRegistryUrls = ['https://circleci.com/']; override readonly defaultRegistryUrls = ['https://circleci.com/'];
override readonly registryStrategy = 'hunt';
override readonly releaseTimestampSupport = true; override readonly releaseTimestampSupport = true;
override readonly releaseTimestampNote = override readonly releaseTimestampNote =
@ -47,7 +49,7 @@ export class OrbDatasource extends Datasource {
if (!registryUrl) { if (!registryUrl) {
return null; return null;
} }
const url = `${registryUrl}graphql-unstable`; const url = joinUrlParts(registryUrl, 'graphql-unstable');
const body = { const body = {
query, query,
variables: { packageName, maxVersions: MAX_VERSIONS }, variables: { packageName, maxVersions: MAX_VERSIONS },

View file

@ -44,7 +44,7 @@ resources:
- container: linux - container: linux
image: ubuntu:24.04 image: ubuntu:24.04
- container: python - container: python
image: python:3.13@sha256:9255d1993f6d28b8a1cd611b108adbdfa38cb7ccc46ddde8ea7d734b6c845e32 image: python:3.13@sha256:cea505b81701dd9e46b8dde96eaa8054c4bd2035dbb660edeb7af947ed38a0ad
stages: stages:
- stage: StageOne - stage: StageOne

View file

@ -11,7 +11,7 @@ export const url = 'https://bazel.build/external/module';
export const categories: Category[] = ['bazel']; export const categories: Category[] = ['bazel'];
export const defaultConfig = { export const defaultConfig = {
fileMatch: ['(^|/)MODULE\\.bazel$'], fileMatch: ['(^|/|\\.)MODULE\\.bazel$'],
}; };
export const supportedDatasources = [ export const supportedDatasources = [

View file

@ -10,7 +10,11 @@ import { GithubRunnersDatasource } from '../../datasource/github-runners';
import { GithubTagsDatasource } from '../../datasource/github-tags'; import { GithubTagsDatasource } from '../../datasource/github-tags';
import * as dockerVersioning from '../../versioning/docker'; import * as dockerVersioning from '../../versioning/docker';
import { getDep } from '../dockerfile/extract'; import { getDep } from '../dockerfile/extract';
import type { PackageDependency, PackageFileContent } from '../types'; import type {
ExtractConfig,
PackageDependency,
PackageFileContent,
} from '../types';
import type { Workflow } from './types'; import type { Workflow } from './types';
const dockerActionRe = regEx(/^\s+uses\s*: ['"]?docker:\/\/([^'"]+)\s*$/); const dockerActionRe = regEx(/^\s+uses\s*: ['"]?docker:\/\/([^'"]+)\s*$/);
@ -44,7 +48,10 @@ function detectCustomGitHubRegistryUrlsForActions(): PackageDependency {
return {}; return {};
} }
function extractWithRegex(content: string): PackageDependency[] { function extractWithRegex(
content: string,
config: ExtractConfig,
): PackageDependency[] {
const customRegistryUrlsPackageDependency = const customRegistryUrlsPackageDependency =
detectCustomGitHubRegistryUrlsForActions(); detectCustomGitHubRegistryUrlsForActions();
logger.trace('github-actions.extractWithRegex()'); logger.trace('github-actions.extractWithRegex()');
@ -57,7 +64,7 @@ function extractWithRegex(content: string): PackageDependency[] {
const dockerMatch = dockerActionRe.exec(line); const dockerMatch = dockerActionRe.exec(line);
if (dockerMatch) { if (dockerMatch) {
const [, currentFrom] = dockerMatch; const [, currentFrom] = dockerMatch;
const dep = getDep(currentFrom); const dep = getDep(currentFrom, true, config.registryAliases);
dep.depType = 'docker'; dep.depType = 'docker';
deps.push(dep); deps.push(dep);
continue; continue;
@ -126,11 +133,14 @@ function detectDatasource(registryUrl: string): PackageDependency {
}; };
} }
function extractContainer(container: unknown): PackageDependency | undefined { function extractContainer(
container: unknown,
registryAliases: Record<string, string> | undefined,
): PackageDependency | undefined {
if (is.string(container)) { if (is.string(container)) {
return getDep(container); return getDep(container, true, registryAliases);
} else if (is.plainObject(container) && is.string(container.image)) { } else if (is.plainObject(container) && is.string(container.image)) {
return getDep(container.image); return getDep(container.image, true, registryAliases);
} }
return undefined; return undefined;
} }
@ -181,6 +191,7 @@ function extractRunners(runner: unknown): PackageDependency[] {
function extractWithYAMLParser( function extractWithYAMLParser(
content: string, content: string,
packageFile: string, packageFile: string,
config: ExtractConfig,
): PackageDependency[] { ): PackageDependency[] {
logger.trace('github-actions.extractWithYAMLParser()'); logger.trace('github-actions.extractWithYAMLParser()');
const deps: PackageDependency[] = []; const deps: PackageDependency[] = [];
@ -198,14 +209,14 @@ function extractWithYAMLParser(
} }
for (const job of Object.values(pkg?.jobs ?? {})) { for (const job of Object.values(pkg?.jobs ?? {})) {
const dep = extractContainer(job?.container); const dep = extractContainer(job?.container, config.registryAliases);
if (dep) { if (dep) {
dep.depType = 'container'; dep.depType = 'container';
deps.push(dep); deps.push(dep);
} }
for (const service of Object.values(job?.services ?? {})) { for (const service of Object.values(job?.services ?? {})) {
const dep = extractContainer(service); const dep = extractContainer(service, config.registryAliases);
if (dep) { if (dep) {
dep.depType = 'service'; dep.depType = 'service';
deps.push(dep); deps.push(dep);
@ -221,11 +232,12 @@ function extractWithYAMLParser(
export function extractPackageFile( export function extractPackageFile(
content: string, content: string,
packageFile: string, packageFile: string,
config: ExtractConfig = {}, // TODO: enforce ExtractConfig
): PackageFileContent | null { ): PackageFileContent | null {
logger.trace(`github-actions.extractPackageFile(${packageFile})`); logger.trace(`github-actions.extractPackageFile(${packageFile})`);
const deps = [ const deps = [
...extractWithRegex(content), ...extractWithRegex(content, config),
...extractWithYAMLParser(content, packageFile), ...extractWithYAMLParser(content, packageFile, config),
]; ];
if (!deps.length) { if (!deps.length) {
return null; return null;

View file

@ -189,6 +189,112 @@ describe('modules/manager/gomod/artifacts', () => {
]); ]);
}); });
it('runs go mod vendor with gomodVendor', async () => {
fs.readLocalFile.mockResolvedValueOnce('Current go.sum');
fs.readLocalFile.mockResolvedValueOnce('New go.sum');
fs.readLocalFile.mockResolvedValueOnce('New go.mod');
const execSnapshots = mockExecAll();
git.getRepoStatus.mockResolvedValueOnce(
partial<StatusResult>({
modified: ['go.sum'],
not_added: [],
deleted: [],
}),
);
const res = await gomod.updateArtifacts({
packageFileName: 'go.mod',
updatedDeps: [],
newPackageFileContent: gomod1,
config: {
...config,
postUpdateOptions: ['gomodVendor'],
},
});
expect(res).toEqual([
{
file: {
contents: 'New go.sum',
path: 'go.sum',
type: 'addition',
},
},
{
file: {
contents: 'New go.mod',
path: 'go.mod',
type: 'addition',
},
},
]);
expect(execSnapshots).toMatchObject([
{
cmd: 'go get -d -t ./...',
options: { cwd: '/tmp/github/some/repo' },
},
{
cmd: 'go mod vendor',
options: { cwd: '/tmp/github/some/repo' },
},
]);
});
it('runs go work vendor with gomodVendor and go.work', async () => {
fs.readLocalFile.mockResolvedValueOnce('Current go.sum');
fs.findLocalSiblingOrParent.mockResolvedValueOnce('go.work');
const execSnapshots = mockExecAll();
git.getRepoStatus.mockResolvedValueOnce(
partial<StatusResult>({
modified: ['go.sum'],
not_added: [],
deleted: [],
}),
);
fs.readLocalFile.mockResolvedValueOnce('New go.sum');
fs.readLocalFile.mockResolvedValueOnce('New go.mod');
const res = await gomod.updateArtifacts({
packageFileName: 'go.mod',
updatedDeps: [],
newPackageFileContent: gomod1,
config: {
...config,
postUpdateOptions: ['gomodVendor'],
},
});
expect(res).toEqual([
{
file: {
contents: 'New go.sum',
path: 'go.sum',
type: 'addition',
},
},
{
file: {
contents: 'New go.mod',
path: 'go.mod',
type: 'addition',
},
},
]);
expect(execSnapshots).toMatchObject([
{
cmd: 'go get -d -t ./...',
options: { cwd: '/tmp/github/some/repo' },
},
{
cmd: 'go work vendor',
options: { cwd: '/tmp/github/some/repo' },
},
{
cmd: 'go work sync',
options: { cwd: '/tmp/github/some/repo' },
},
]);
});
it('supports vendor directory update', async () => { it('supports vendor directory update', async () => {
const foo = join('vendor/github.com/foo/foo/go.mod'); const foo = join('vendor/github.com/foo/foo/go.mod');
const bar = join('vendor/github.com/bar/bar/go.mod'); const bar = join('vendor/github.com/bar/bar/go.mod');

View file

@ -134,9 +134,9 @@ export async function updateArtifacts({
const vendorDir = upath.join(goModDir, 'vendor/'); const vendorDir = upath.join(goModDir, 'vendor/');
const vendorModulesFileName = upath.join(vendorDir, 'modules.txt'); const vendorModulesFileName = upath.join(vendorDir, 'modules.txt');
const useVendor = const useVendor =
!config.postUpdateOptions?.includes('gomodSkipVendor') && !!config.postUpdateOptions?.includes('gomodVendor') ||
(await readLocalFile(vendorModulesFileName)) !== null; (!config.postUpdateOptions?.includes('gomodSkipVendor') &&
(await readLocalFile(vendorModulesFileName)) !== null);
let massagedGoMod = newGoModContent; let massagedGoMod = newGoModContent;
if (config.postUpdateOptions?.includes('gomodMassage')) { if (config.postUpdateOptions?.includes('gomodMassage')) {

View file

@ -363,6 +363,32 @@ describe('modules/manager/helmfile/extract', () => {
}); });
}); });
it('allows OCI chart names containing forward slashes', async () => {
const content = `
repositories:
- name: oci-repo
url: ghcr.io/example/oci-repo
oci: true
releases:
- name: nested-example
version: 1.2.3
chart: oci-repo/nested/path/chart
`;
const fileName = 'helmfile.yaml';
const result = await extractPackageFile(content, fileName, {});
expect(result).toMatchObject({
datasource: 'helm',
deps: [
{
currentValue: '1.2.3',
depName: 'nested/path/chart',
datasource: 'docker',
packageName: 'ghcr.io/example/oci-repo/nested/path/chart',
},
],
});
});
it('parses a chart with an oci repository with ---', async () => { it('parses a chart with an oci repository with ---', async () => {
const content = codeBlock` const content = codeBlock`
repositories: repositories:

View file

@ -18,8 +18,13 @@ import {
localChartHasKustomizationsYaml, localChartHasKustomizationsYaml,
} from './utils'; } from './utils';
const isValidChartName = (name: string | undefined): boolean => function isValidChartName(name: string | undefined, oci: boolean): boolean {
!!name && !regEx(/[!@#$%^&*(),.?":{}/|<>A-Z]/).test(name); if (oci) {
return !!name && !regEx(/[!@#$%^&*(),.?":{}|<>A-Z]/).test(name);
} else {
return !!name && !regEx(/[!@#$%^&*(),.?":{}/|<>A-Z]/).test(name);
}
}
function isLocalPath(possiblePath: string): boolean { function isLocalPath(possiblePath: string): boolean {
return ['./', '../', '/'].some((localPrefix) => return ['./', '../', '/'].some((localPrefix) =>
@ -118,7 +123,12 @@ export async function extractPackageFile(
// By definition on helm the chart name should be lowercase letter + number + - // By definition on helm the chart name should be lowercase letter + number + -
// However helmfile support templating of that field // However helmfile support templating of that field
if (!isValidChartName(res.depName)) { if (
!isValidChartName(
res.depName,
isOCIRegistry(dep.chart) || (registryData[repoName]?.oci ?? false),
)
) {
res.skipReason = 'unsupported-chart-type'; res.skipReason = 'unsupported-chart-type';
} }

View file

@ -20,20 +20,20 @@ defmodule MyProject.MixProject do
# {:broadway_dashboard, "~> 0.2.2"}, # {:broadway_dashboard, "~> 0.2.2"},
# {:broadway_dashboard, "~> 0.2.2"}, # {:broadway_dashboard, "~> 0.2.2"},
{:postgrex, "~> 0.8.1"}, # {:broadway_dashboard, "~> 0.2.2"}, {:postgrex, "~> 0.8.1"}, # {:broadway_dashboard, "~> 0.2.2"},
{:foo_bar, ">2.1.0 or <=3.0.0"}, {:ranch, "<1.7.0 or ~>1.7.1"},
{:cowboy, github: "ninenines/cowboy", tag: "v0.4.1"}, {:cowboy, github: "ninenines/cowboy", tag: "0.6.0"},
{:phoenix, git: "https://github.com/phoenixframework/phoenix.git", branch: "main"}, {:phoenix, git: "https://github.com/phoenixframework/phoenix.git", branch: "main"},
{:ecto, github: "elixir-ecto/ecto", ref: "795036d997c7503b21fb64d6bf1a89b83c44f2b5"}, {:ecto, github: "elixir-ecto/ecto", ref: "795036d997c7503b21fb64d6bf1a89b83c44f2b5"},
{:secret, "~> 1.0", organization: "acme"}, {:secret, "~> 1.0", organization: "acme"},
{:also_secret, "~> 1.0", only: [:dev, :test], organization: "acme", runtime: false}, {:also_secret, "~> 1.0", only: [:dev, :test], organization: "acme", runtime: false},
{:ex_doc, ">2.1.0 and <=3.0.0"}, {:metrics, ">0.2.0 and <=1.0.0"},
{:jason, ">= 1.0.0"}, {:jason, ">= 1.0.0"},
{:mason, "~> 1.0", {:hackney, "~> 1.0",
optional: true}, optional: true},
{:hammer_backend_redis, "~> 6.1"}, {:hammer_backend_redis, "~> 6.1"},
{:public, "== 1.6.14"}, {:castore, "== 1.0.10"},
{:gun, "~> 2.0.0", hex: "grpc_gun"}, {:gun, "~> 2.0.0", hex: "grpc_gun"},
{:another_gun, "~> 1.0.0", hex: :gun_atom}, {:another_gun, "~> 0.4.0", hex: :raygun},
] ]
end end
end end

View file

@ -1,18 +1,37 @@
%{ %{
"foo_bar": {:hex, :foo_bar, "2.2.0", "83e8daf59631d632b171faabafb4a9f4242c514b0a06ba3df493951c08f64d07", [:mix], [], "hexpm", "b1f2343568eed6928f3e751cf2dffde95bfaa19dd95d09e8a9ea92ccfd6f7d85"}, "another_gun": {:hex, :raygun, "0.4.0", "7744e99dd695f61e78ad5e047cce0affb3edfc6f93a92278598ab553b9c5091f", [:mix], [{:httpoison, "~> 0.8 or ~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}, {:plug, "~> 1.1", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "eee4b891e6e65c6a4b15386dc7b7a72b717f3c123cc0012cfd19e8f2ab21116d"},
"postgrex": {:hex, :postgrex, "0.8.2", "83e8daf59631d632b171faabafb4a9f4242c514b0a06ba3df493951c08f64d07", [:mix], [], "hexpm", "b1f2343568eed6928f3e751cf2dffde95bfaa19dd95d09e8a9ea92ccfd6f7d85"}, "castore": {:hex, :castore, "1.0.10", "43bbeeac820f16c89f79721af1b3e092399b3a1ecc8df1a472738fd853574911", [:mix], [], "hexpm", "1b0b7ea14d889d9ea21202c43a4fa015eb913021cb535e8ed91946f4b77a8848"},
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"},
"cowboy": {:git, "https://github.com/ninenines/cowboy.git", "81f3a21474155f68fbf494b7026b9678027d303e", [tag: "v0.4.1"]}, "cowboy": {:git, "https://github.com/ninenines/cowboy.git", "0c2e2224e372f01e6cf51a8e12d4856edb4cb8ac", [tag: "0.6.0"]},
"phoenix": {:git, "https://github.com/phoenixframework/phoenix.git", "61f3a21474155f68fbf494b7026b9678027d303e", [branch: "main]}, "cowlib": {:hex, :cowlib, "2.13.0", "db8f7505d8332d98ef50a3ef34b34c1afddec7506e4ee4dd4a3a266285d282ca", [:make, :rebar3], [], "hexpm", "e1e1284dc3fc030a64b1ad0d8382ae7e99da46c3246b815318a4b848873800a4"},
"ecto": {:git, "https://github.com/elixir-ecto/ecto.git", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [ref: "795036d997c7503b21fb64d6bf1a89b83c44f2b5"]}, "decimal": {:hex, :decimal, "1.9.0", "83e8daf59631d632b171faabafb4a9f4242c514b0a06ba3df493951c08f64d07", [:mix], [], "hexpm", "b1f2343568eed6928f3e751cf2dffde95bfaa19dd95d09e8a9ea92ccfd6f7d85"},
"ecto": {:git, "https://github.com/elixir-ecto/ecto.git", "795036d997c7503b21fb64d6bf1a89b83c44f2b5", [ref: "795036d997c7503b21fb64d6bf1a89b83c44f2b5"]},
"secret": {:hex, :secret, "1.5.0", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}, "secret": {:hex, :secret, "1.5.0", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"},
"also_secret": {:hex, :also_secret, "1.3.4", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}, "also_secret": {:hex, :also_secret, "1.3.4", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"},
"ex_doc": {:hex, :ex_doc, "2.2.0", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}, "gun": {:hex, :grpc_gun, "2.0.1", "221b792df3a93e8fead96f697cbaf920120deacced85c6cd3329d2e67f0871f8", [:rebar3], [{:cowlib, "~> 2.11", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "795a65eb9d0ba16697e6b0e1886009ce024799e43bb42753f0c59b029f592831"},
"jason": {:hex, :jason, "1.0.1", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}, "hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"},
"mason": {:hex, :mason, "1.1.0", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}, "hammer": {:hex, :hammer, "6.2.1", "5ae9c33e3dceaeb42de0db46bf505bd9c35f259c8defb03390cd7556fea67ee2", [:mix], [{:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm", "b9476d0c13883d2dc0cc72e786bac6ac28911fba7cc2e04b70ce6a6d9c4b2bdc"},
"hammer_backend_redis": {:hex, :hammer_backend_redis, "6.1.5", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}, "hammer_backend_redis": {:hex, :hammer_backend_redis, "6.2.0", "f39a9c8491387cdf719a38593311537e3e0251ca54725b6ee9145406821f39d2", [:mix], [{:hammer, "~> 6.0", [hex: :hammer, repo: "hexpm", optional: false]}, {:redix, "~> 1.1", [hex: :redix, repo: "hexpm", optional: false]}], "hexpm", "9965d55705d7ca7412bb0685f5cd44fc47d103bf388abc50438e71974c36c9fa"},
"public": {:hex, :public, "1.6.14", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}, "httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"},
"a_transient_dependency": {:hex, :a_transient_dependency, "1.6.14", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"gun": {:hex, :grpc_gun, "2.0.0", "f99678a2ab975e74372a756c86ec30a8384d3ac8a8b86c7ed6243ef4e61d2729", [:rebar3], [{:cowlib, "~> 2.8.0", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "03dbbca1a9c604a0267a40ea1d69986225091acb822de0b2dbea21d5815e410b"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
"another_gun": {:hex, :gun_atom, "1.0.0", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"} "metrics": {:hex, :metrics, "1.0.0", "79fa539adf26405399429ac8061790063b639fc3d29d3001ee164e802effb819", [:rebar3], [], "hexpm", "394140f082d4f8c45466fd6839b563ae8e5334ffe56f736b7ff3cda12642cd76"},
"mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"},
"mimerl": {:hex, :mimerl, "1.3.0", "d0cd9fc04b9061f82490f6581e0128379830e78535e017f7780f37fea7545726", [:rebar3], [], "hexpm", "a1e15a50d1887217de95f0b9b0793e32853f7c258a5cd227650889b38839fe9d"},
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
"parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
"phoenix": {:git, "https://github.com/phoenixframework/phoenix.git", "61cbfebbd2df71e58e9edd2013047f474ab8cbc7", [branch: "main"]},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"},
"phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
"plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"},
"plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"},
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"},
"postgrex": {:hex, :postgrex, "0.8.4", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"},
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"},
"redix": {:hex, :redix, "1.5.2", "ab854435a663f01ce7b7847f42f5da067eea7a3a10c0a9d560fa52038fd7ab48", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:nimble_options, "~> 0.5.0 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "78538d184231a5d6912f20567d76a49d1be7d3fca0e1aaaa20f4df8e1142dcb8"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
"telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
"websock_adapter": {:hex, :websock_adapter, "0.5.8", "3b97dc94e407e2d1fc666b2fb9acf6be81a1798a2602294aac000260a7c4a47d", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "315b9a1865552212b5f35140ad194e67ce31af45bcee443d4ecb96b5fd3f3782"},
} }

View file

@ -23,14 +23,14 @@ describe('modules/manager/mix/extract', () => {
packageName: 'postgrex', packageName: 'postgrex',
}, },
{ {
currentValue: '>2.1.0 or <=3.0.0', currentValue: '<1.7.0 or ~>1.7.1',
datasource: 'hex', datasource: 'hex',
depName: 'foo_bar', depName: 'ranch',
packageName: 'foo_bar', packageName: 'ranch',
}, },
{ {
currentDigest: undefined, currentDigest: undefined,
currentValue: 'v0.4.1', currentValue: '0.6.0',
datasource: 'github-tags', datasource: 'github-tags',
depName: 'cowboy', depName: 'cowboy',
packageName: 'ninenines/cowboy', packageName: 'ninenines/cowboy',
@ -62,10 +62,10 @@ describe('modules/manager/mix/extract', () => {
packageName: 'also_secret:acme', packageName: 'also_secret:acme',
}, },
{ {
currentValue: '>2.1.0 and <=3.0.0', currentValue: '>0.2.0 and <=1.0.0',
datasource: 'hex', datasource: 'hex',
depName: 'ex_doc', depName: 'metrics',
packageName: 'ex_doc', packageName: 'metrics',
}, },
{ {
currentValue: '>= 1.0.0', currentValue: '>= 1.0.0',
@ -76,8 +76,8 @@ describe('modules/manager/mix/extract', () => {
{ {
currentValue: '~> 1.0', currentValue: '~> 1.0',
datasource: 'hex', datasource: 'hex',
depName: 'mason', depName: 'hackney',
packageName: 'mason', packageName: 'hackney',
}, },
{ {
currentValue: '~> 6.1', currentValue: '~> 6.1',
@ -86,11 +86,11 @@ describe('modules/manager/mix/extract', () => {
packageName: 'hammer_backend_redis', packageName: 'hammer_backend_redis',
}, },
{ {
currentValue: '== 1.6.14', currentValue: '== 1.0.10',
currentVersion: '1.6.14', currentVersion: '1.0.10',
datasource: 'hex', datasource: 'hex',
depName: 'public', depName: 'castore',
packageName: 'public', packageName: 'castore',
}, },
{ {
currentValue: '~> 2.0.0', currentValue: '~> 2.0.0',
@ -99,10 +99,10 @@ describe('modules/manager/mix/extract', () => {
packageName: 'grpc_gun', packageName: 'grpc_gun',
}, },
{ {
currentValue: '~> 1.0.0', currentValue: '~> 0.4.0',
datasource: 'hex', datasource: 'hex',
depName: 'another_gun', depName: 'another_gun',
packageName: 'gun_atom', packageName: 'raygun',
}, },
]); ]);
}); });
@ -117,22 +117,22 @@ describe('modules/manager/mix/extract', () => {
datasource: 'hex', datasource: 'hex',
depName: 'postgrex', depName: 'postgrex',
packageName: 'postgrex', packageName: 'postgrex',
lockedVersion: '0.8.2', lockedVersion: '0.8.4',
}, },
{ {
currentValue: '>2.1.0 or <=3.0.0', currentValue: '<1.7.0 or ~>1.7.1',
datasource: 'hex', datasource: 'hex',
depName: 'foo_bar', depName: 'ranch',
packageName: 'foo_bar', packageName: 'ranch',
lockedVersion: '2.2.0', lockedVersion: '1.7.1',
}, },
{ {
currentDigest: undefined, currentDigest: undefined,
currentValue: 'v0.4.1', currentValue: '0.6.0',
datasource: 'github-tags', datasource: 'github-tags',
depName: 'cowboy', depName: 'cowboy',
packageName: 'ninenines/cowboy', packageName: 'ninenines/cowboy',
lockedVersion: undefined, lockedVersion: '0.6.0',
}, },
{ {
currentDigest: undefined, currentDigest: undefined,
@ -165,54 +165,54 @@ describe('modules/manager/mix/extract', () => {
lockedVersion: '1.3.4', lockedVersion: '1.3.4',
}, },
{ {
currentValue: '>2.1.0 and <=3.0.0', currentValue: '>0.2.0 and <=1.0.0',
datasource: 'hex', datasource: 'hex',
depName: 'ex_doc', depName: 'metrics',
packageName: 'ex_doc', packageName: 'metrics',
lockedVersion: '2.2.0', lockedVersion: '1.0.0',
}, },
{ {
currentValue: '>= 1.0.0', currentValue: '>= 1.0.0',
datasource: 'hex', datasource: 'hex',
depName: 'jason', depName: 'jason',
packageName: 'jason', packageName: 'jason',
lockedVersion: '1.0.1', lockedVersion: '1.4.4',
}, },
{ {
currentValue: '~> 1.0', currentValue: '~> 1.0',
datasource: 'hex', datasource: 'hex',
depName: 'mason', depName: 'hackney',
packageName: 'mason', packageName: 'hackney',
lockedVersion: '1.1.0', lockedVersion: '1.20.1',
}, },
{ {
currentValue: '~> 6.1', currentValue: '~> 6.1',
datasource: 'hex', datasource: 'hex',
depName: 'hammer_backend_redis', depName: 'hammer_backend_redis',
packageName: 'hammer_backend_redis', packageName: 'hammer_backend_redis',
lockedVersion: '6.1.5', lockedVersion: '6.2.0',
}, },
{ {
currentValue: '== 1.6.14', currentValue: '== 1.0.10',
currentVersion: '1.6.14', currentVersion: '1.0.10',
datasource: 'hex', datasource: 'hex',
depName: 'public', depName: 'castore',
packageName: 'public', packageName: 'castore',
lockedVersion: '1.6.14', lockedVersion: '1.0.10',
}, },
{ {
currentValue: '~> 2.0.0', currentValue: '~> 2.0.0',
datasource: 'hex', datasource: 'hex',
depName: 'gun', depName: 'gun',
packageName: 'grpc_gun', packageName: 'grpc_gun',
lockedVersion: '2.0.0', lockedVersion: '2.0.1',
}, },
{ {
currentValue: '~> 1.0.0', currentValue: '~> 0.4.0',
datasource: 'hex', datasource: 'hex',
depName: 'another_gun', depName: 'another_gun',
packageName: 'gun_atom', packageName: 'raygun',
lockedVersion: '1.0.0', lockedVersion: '0.4.0',
}, },
]); ]);
}); });

View file

@ -312,7 +312,7 @@ export async function updateYarnBinary(
let yarnrcYml = existingYarnrcYmlContent; let yarnrcYml = existingYarnrcYmlContent;
try { try {
const yarnrcYmlFilename = upath.join(lockFileDir, '.yarnrc.yml'); const yarnrcYmlFilename = upath.join(lockFileDir, '.yarnrc.yml');
yarnrcYml ||= (await getFile(yarnrcYmlFilename)) ?? undefined; yarnrcYml ??= (await getFile(yarnrcYmlFilename)) ?? undefined;
const newYarnrcYml = await readLocalFile(yarnrcYmlFilename, 'utf8'); const newYarnrcYml = await readLocalFile(yarnrcYmlFilename, 'utf8');
if (!is.string(yarnrcYml) || !is.string(newYarnrcYml)) { if (!is.string(yarnrcYml) || !is.string(newYarnrcYml)) {
return existingYarnrcYmlContent; return existingYarnrcYmlContent;

View file

@ -4,17 +4,18 @@ import { parsePEP508 } from './utils';
describe('modules/manager/pep621/utils', () => { describe('modules/manager/pep621/utils', () => {
describe('parsePEP508()', () => { describe('parsePEP508()', () => {
it.each` it.each`
value | success | packageName | currentValue | extras | marker value | success | packageName | currentValue | extras | marker
${''} | ${false} | ${undefined} | ${undefined} | ${undefined} | ${undefined} ${''} | ${false} | ${undefined} | ${undefined} | ${undefined} | ${undefined}
${undefined} | ${false} | ${undefined} | ${undefined} | ${undefined} | ${undefined} ${undefined} | ${false} | ${undefined} | ${undefined} | ${undefined} | ${undefined}
${null} | ${false} | ${undefined} | ${undefined} | ${undefined} | ${undefined} ${null} | ${false} | ${undefined} | ${undefined} | ${undefined} | ${undefined}
${'blinker'} | ${true} | ${'blinker'} | ${undefined} | ${undefined} | ${undefined} ${'blinker'} | ${true} | ${'blinker'} | ${undefined} | ${undefined} | ${undefined}
${'packaging==20.0.0'} | ${true} | ${'packaging'} | ${'==20.0.0'} | ${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} ${'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} ${'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"'} ${'private-depB[extra1, extra2]~=2.4'} | ${true} | ${'private-depB'} | ${'~=2.4'} | ${['extra1', 'extra2']} | ${undefined}
${'typing-extensions; python_version < "3.8"'} | ${true} | ${'typing-extensions'} | ${undefined} | ${undefined} | ${'python_version < "3.8"'} ${'tomli>=1.1.0; python_version < "3.11"'} | ${true} | ${'tomli'} | ${'>=1.1.0'} | ${undefined} | ${'python_version < "3.11"'}
${'typing-extensions[test-feature]; python_version < "3.8"'} | ${true} | ${'typing-extensions'} | ${undefined} | ${['test-feature']} | ${'python_version < "3.8"'} ${'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"', '(parse $value"',
({ value, success, packageName, currentValue, extras, marker }) => { ({ value, success, packageName, currentValue, extras, marker }) => {

View file

@ -10,7 +10,7 @@ import { PyProjectSchema } from './schema';
import type { Pep508ParseResult, Pep621ManagerData } from './types'; import type { Pep508ParseResult, Pep621ManagerData } from './types';
const pep508Regex = regEx( const pep508Regex = regEx(
/^(?<packageName>[A-Z0-9._-]+)\s*(\[(?<extras>[A-Z0-9,._-]+)\])?\s*(?<currentValue>[^;]+)?(;\s*(?<marker>.*))?/i, /^(?<packageName>[A-Z0-9._-]+)\s*(\[(?<extras>[A-Z0-9\s,._-]+)\])?\s*(?<currentValue>[^;]+)?(;\s*(?<marker>.*))?/i,
); );
export const depTypes = { export const depTypes = {
@ -49,7 +49,8 @@ export function parsePEP508(
result.marker = regExpExec.groups.marker; result.marker = regExpExec.groups.marker;
} }
if (is.nonEmptyString(regExpExec.groups.extras)) { if (is.nonEmptyString(regExpExec.groups.extras)) {
result.extras = regExpExec.groups.extras.split(','); // trim to remove allowed whitespace between brackets
result.extras = regExpExec.groups.extras.split(',').map((e) => e.trim());
} }
return result; return result;

View file

@ -166,8 +166,8 @@ describe('modules/platform/bitbucket/pr-cache', () => {
); );
expect(res).toMatchObject([ expect(res).toMatchObject([
{ number: 1, title: 'title' },
{ number: 2, title: 'title' }, { number: 2, title: 'title' },
{ number: 1, title: 'title' },
]); ]);
expect(cache).toEqual({ expect(cache).toEqual({
httpCache: {}, httpCache: {},

View file

@ -11,6 +11,7 @@ import type { BitbucketPrCacheData, PagedResult, PrResponse } from './types';
import { prFieldsFilter, prInfo, prStates } from './utils'; import { prFieldsFilter, prInfo, prStates } from './utils';
export class BitbucketPrCache { export class BitbucketPrCache {
private items: Pr[] = [];
private cache: BitbucketPrCacheData; private cache: BitbucketPrCacheData;
private constructor( private constructor(
@ -41,6 +42,7 @@ export class BitbucketPrCache {
} }
repoCache.platform.bitbucket.pullRequestsCache = pullRequestCache; repoCache.platform.bitbucket.pullRequestsCache = pullRequestCache;
this.cache = pullRequestCache; this.cache = pullRequestCache;
this.updateItems();
} }
private static async init( private static async init(
@ -62,7 +64,7 @@ export class BitbucketPrCache {
} }
private getPrs(): Pr[] { private getPrs(): Pr[] {
return Object.values(this.cache.items); return this.items;
} }
static async getPrs( static async getPrs(
@ -77,6 +79,7 @@ export class BitbucketPrCache {
private setPr(pr: Pr): void { private setPr(pr: Pr): void {
logger.debug(`Adding PR #${pr.number} to the PR cache`); logger.debug(`Adding PR #${pr.number} to the PR cache`);
this.cache.items[pr.number] = pr; this.cache.items[pr.number] = pr;
this.updateItems();
} }
static async setPr( static async setPr(
@ -161,6 +164,16 @@ export class BitbucketPrCache {
}, },
`PR cache sync finished`, `PR cache sync finished`,
); );
this.updateItems();
return this; return this;
} }
/**
* Ensure the pr cache starts with the most recent PRs.
* JavaScript ensures that the cache is sorted by PR number.
*/
private updateItems(): void {
this.items = Object.values(this.cache.items).reverse();
}
} }

View file

@ -1166,10 +1166,10 @@ describe('modules/platform/gitea/index', () => {
const res = await gitea.getPrList(); const res = await gitea.getPrList();
expect(res).toMatchObject([ expect(res).toMatchObject([
{ number: 1, title: 'Some PR' },
{ number: 2, title: 'Other PR' },
{ number: 3, title: 'Draft PR' },
{ number: 4, title: 'Merged PR' }, { number: 4, title: 'Merged PR' },
{ number: 3, title: 'Draft PR' },
{ number: 2, title: 'Other PR' },
{ number: 1, title: 'Some PR' },
]); ]);
}); });
@ -1209,10 +1209,10 @@ describe('modules/platform/gitea/index', () => {
const res = await gitea.getPrList(); const res = await gitea.getPrList();
expect(res).toMatchObject([ expect(res).toMatchObject([
{ number: 1, title: 'Some PR' },
{ number: 2, title: 'Other PR' },
{ number: 3, title: 'Draft PR' },
{ number: 4, title: 'Merged PR' }, { number: 4, title: 'Merged PR' },
{ number: 3, title: 'Draft PR' },
{ number: 2, title: 'Other PR' },
{ number: 1, title: 'Some PR' },
]); ]);
}); });
@ -1244,16 +1244,16 @@ describe('modules/platform/gitea/index', () => {
await initFakeRepo(scope); await initFakeRepo(scope);
const res1 = await gitea.getPrList(); const res1 = await gitea.getPrList();
expect(res1).toMatchObject([{ number: 1 }, { number: 2 }]); expect(res1).toMatchObject([{ number: 2 }, { number: 1 }]);
memCache.set('gitea-pr-cache-synced', false); memCache.set('gitea-pr-cache-synced', false);
const res2 = await gitea.getPrList(); const res2 = await gitea.getPrList();
expect(res2).toMatchObject([ expect(res2).toMatchObject([
{ number: 1 },
{ number: 2 },
{ number: 3 },
{ number: 4 }, { number: 4 },
{ number: 3 },
{ number: 2 },
{ number: 1 },
]); ]);
}); });
}); });

View file

@ -11,6 +11,7 @@ import { API_PATH, toRenovatePR } from './utils';
export class GiteaPrCache { export class GiteaPrCache {
private cache: GiteaPrCacheData; private cache: GiteaPrCacheData;
private items: Pr[] = [];
private constructor( private constructor(
private repo: string, private repo: string,
@ -31,6 +32,7 @@ export class GiteaPrCache {
} }
repoCache.platform.gitea.pullRequestsCache = pullRequestCache; repoCache.platform.gitea.pullRequestsCache = pullRequestCache;
this.cache = pullRequestCache; this.cache = pullRequestCache;
this.updateItems();
} }
static forceSync(): void { static forceSync(): void {
@ -54,7 +56,7 @@ export class GiteaPrCache {
} }
private getPrs(): Pr[] { private getPrs(): Pr[] {
return Object.values(this.cache.items); return this.items;
} }
static async getPrs( static async getPrs(
@ -68,6 +70,7 @@ export class GiteaPrCache {
private setPr(item: Pr): void { private setPr(item: Pr): void {
this.cache.items[item.number] = item; this.cache.items[item.number] = item;
this.updateItems();
} }
static async setPr( static async setPr(
@ -137,6 +140,16 @@ export class GiteaPrCache {
url = parseLinkHeader(res.headers.link)?.next?.url; url = parseLinkHeader(res.headers.link)?.next?.url;
} }
this.updateItems();
return this; return this;
} }
/**
* Ensure the pr cache starts with the most recent PRs.
* JavaScript ensures that the cache is sorted by PR number.
*/
private updateItems(): void {
this.items = Object.values(this.cache.items).reverse();
}
} }

View file

@ -2568,7 +2568,7 @@ describe('modules/platform/github/index', () => {
const scope = httpMock.scope(githubApiHost); const scope = httpMock.scope(githubApiHost);
initRepoMock(scope, 'some/repo'); initRepoMock(scope, 'some/repo');
scope scope
.get('/repos/some/repo/pulls?head=some/repo:branch&state=open') .get('/repos/some/repo/pulls?head=some:branch&state=open')
.reply(200, [ .reply(200, [
{ {
number: 1, number: 1,
@ -2598,7 +2598,7 @@ describe('modules/platform/github/index', () => {
const scope = httpMock.scope(githubApiHost); const scope = httpMock.scope(githubApiHost);
initRepoMock(scope, 'some/repo'); initRepoMock(scope, 'some/repo');
scope scope
.get('/repos/some/repo/pulls?head=some/repo:branch&state=open') .get('/repos/some/repo/pulls?head=some:branch&state=open')
.reply(200, []); .reply(200, []);
await github.initRepo({ repository: 'some/repo' }); await github.initRepo({ repository: 'some/repo' });
const pr = await github.findPr({ const pr = await github.findPr({

View file

@ -855,9 +855,10 @@ export async function findPr({
if (includeOtherAuthors) { if (includeOtherAuthors) {
const repo = config.parentRepo ?? config.repository; const repo = config.parentRepo ?? config.repository;
const org = repo?.split('/')[0];
// PR might have been created by anyone, so don't use the cached Renovate PR list // PR might have been created by anyone, so don't use the cached Renovate PR list
const { body: prList } = await githubApi.getJson<GhRestPr[]>( const { body: prList } = await githubApi.getJson<GhRestPr[]>(
`repos/${repo}/pulls?head=${repo}:${branchName}&state=open`, `repos/${repo}/pulls?head=${org}:${branchName}&state=open`,
{ cacheProvider: repoCacheProvider }, { cacheProvider: repoCacheProvider },
); );

View file

@ -6,6 +6,7 @@ import * as composer from './composer';
import * as conan from './conan'; import * as conan from './conan';
import * as deb from './deb'; import * as deb from './deb';
import * as debian from './debian'; import * as debian from './debian';
import * as devbox from './devbox';
import * as docker from './docker'; import * as docker from './docker';
import * as git from './git'; import * as git from './git';
import * as glasskube from './glasskube'; import * as glasskube from './glasskube';
@ -52,6 +53,7 @@ api.set(composer.id, composer.api);
api.set(conan.id, conan.api); api.set(conan.id, conan.api);
api.set(deb.id, deb.api); api.set(deb.id, deb.api);
api.set(debian.id, debian.api); api.set(debian.id, debian.api);
api.set(devbox.id, devbox.api);
api.set(docker.id, docker.api); api.set(docker.id, docker.api);
api.set(git.id, git.api); api.set(git.id, git.api);
api.set(glasskube.id, glasskube.api); api.set(glasskube.id, glasskube.api);

View file

@ -0,0 +1,103 @@
import devbox from '.';
describe('modules/versioning/devbox/index', () => {
it.each`
version | expected
${'1'} | ${false}
${'01'} | ${false}
${'1.01'} | ${false}
${'1.1'} | ${false}
${'1.3.0'} | ${true}
${'2.1.20'} | ${true}
${'v1.4'} | ${false}
${'V0.5'} | ${false}
${'3.5.0'} | ${true}
${'4.2.21.Final'} | ${false}
${'1234'} | ${false}
${'foo'} | ${false}
${'latest'} | ${false}
${''} | ${false}
${'3.5.0-beta.3'} | ${false}
${'*'} | ${false}
${'x'} | ${false}
${'X'} | ${false}
${'~1.2.3'} | ${false}
${'>1.2.3'} | ${false}
${'^1.2.3'} | ${false}
${'1.2.3-foo'} | ${false}
${'1.2.3foo'} | ${false}
`('isVersion("$version") === $expected', ({ version, expected }) => {
expect(!!devbox.isVersion(version)).toBe(expected);
});
it.each`
version | isValid
${'1'} | ${true}
${'01'} | ${false}
${'1.01'} | ${false}
${'1.1'} | ${true}
${'1.3.0'} | ${true}
${'2.1.20'} | ${true}
${'v1.4'} | ${false}
${'V0.5'} | ${false}
${'3.5.0'} | ${true}
${'4.2.21.Final'} | ${false}
${'1234'} | ${true}
${'foo'} | ${false}
${'latest'} | ${true}
${''} | ${false}
${'3.5.0-beta.3'} | ${false}
${'*'} | ${false}
${'x'} | ${false}
${'X'} | ${false}
${'~1.2.3'} | ${false}
${'>1.2.3'} | ${false}
${'^1.2.3'} | ${false}
${'1.2.3-foo'} | ${false}
${'1.2.3foo'} | ${false}
`('isValid("$version") === $isValid', ({ version, isValid }) => {
expect(!!devbox.isValid(version)).toBe(isValid);
});
it.each`
version | range | expected
${'1'} | ${'1'} | ${false}
${'1'} | ${'0'} | ${false}
${'1.2.3'} | ${'1'} | ${true}
${'1.2'} | ${'1'} | ${false}
${'1.0.0'} | ${'1'} | ${true}
${'1.2.0'} | ${'1.2'} | ${true}
${'1.2.3'} | ${'1.2'} | ${true}
${'0'} | ${'latest'} | ${false}
${'1.2.3'} | ${'latest'} | ${true}
${'1.2.3.5'} | ${'1.2.3.5'} | ${false}
${'1.2'} | ${'1.2.3'} | ${false}
`(
'matches("$version", "$range") === $expected',
({ version, range, expected }) => {
expect(devbox.matches(version, range)).toBe(expected);
},
);
it.each`
version | range | expected
${'1'} | ${'1'} | ${true}
${'1'} | ${'0'} | ${false}
${'1.2.3'} | ${'1'} | ${true}
${'1.2'} | ${'1'} | ${true}
${'1.0.0'} | ${'1'} | ${true}
${'1.2.0'} | ${'1.2'} | ${true}
${'1.2.3'} | ${'1.2'} | ${true}
${'0'} | ${'latest'} | ${true}
${'1.2.3'} | ${'latest'} | ${true}
${'1.2.3.5'} | ${'1.2.3.5'} | ${false}
${'latest'} | ${'latest'} | ${false}
${'latest'} | ${'1.2.3'} | ${false}
${'1.2'} | ${'1.2.3'} | ${true}
`(
'equals("$version", "$range") === $expected',
({ version, range, expected }) => {
expect(devbox.equals(version, range)).toBe(expected);
},
);
});

View file

@ -0,0 +1,74 @@
import { regEx } from '../../../util/regex';
import type { GenericVersion } from '../generic';
import { GenericVersioningApi } from '../generic';
import type { VersioningApi } from '../types';
export const id = 'devbox';
export const displayName = 'devbox';
export const urls = [];
export const supportsRanges = false;
const validPattern = regEx(/^((\d|[1-9]\d*)(\.(\d|[1-9]\d*)){0,2})$/);
const versionPattern = regEx(/^((\d|[1-9]\d*)(\.(\d|[1-9]\d*)){2})$/);
class DevboxVersioningApi extends GenericVersioningApi {
protected _parse(version: string): GenericVersion | null {
const matches = validPattern.exec(version);
if (!matches) {
return null;
}
const release = matches[0].split('.').map(Number);
return { release };
}
override isValid(version: string): boolean {
if (version === 'latest') {
return true;
}
return this._parse(version) !== null;
}
override isVersion(version: string): boolean {
if (version === 'latest') {
return false;
}
const matches = versionPattern.exec(version);
return !!matches;
}
override matches(version: string, range: string): boolean {
return this.isVersion(version) && this.equals(version, range);
}
protected override _compare(version: string, other: string): number {
const parsed1 = this._parse(version);
const parsed2 = this._parse(other);
// Treat "latest" as * and always return equal
if (other === 'latest' && parsed1) {
return 0;
}
// If either version is invalid, return unequal
if (!(parsed1 && parsed2)) {
return 1;
}
// support variable length compare
const length = Math.max(parsed1.release.length, parsed2.release.length);
for (let i = 0; i < length; i += 1) {
// 2.1 and 2.1.0 are equivalent
const part1 = parsed1.release[i];
const part2 = parsed2.release[i];
// if part1 or part2 is undefined, we should treat them as equal
// e.g. 1.0.0 === 1.0
if (part1 !== undefined && part2 !== undefined && part1 !== part2) {
return part1 - part2;
}
}
return 0;
}
}
export const api: VersioningApi = new DevboxVersioningApi();
export default api;

View file

@ -0,0 +1,2 @@
Devbox's Nixhub uses fairly strict versioning, characters such as ~, ^ and >= are not allowed.
The semver values must not include "\*" or "x". "1.2.3" "1.2" and "1" are the only valid formats.

View file

@ -76,6 +76,7 @@ describe('modules/versioning/hex/index', () => {
${'~> 1.2.0'} | ${'replace'} | ${'1.2.3'} | ${'2.0.7'} | ${'~> 2.0.0'} ${'~> 1.2.0'} | ${'replace'} | ${'1.2.3'} | ${'2.0.7'} | ${'~> 2.0.0'}
${'~> 1.2.0'} | ${'pin'} | ${'1.2.3'} | ${'2.0.7'} | ${'== 2.0.7'} ${'~> 1.2.0'} | ${'pin'} | ${'1.2.3'} | ${'2.0.7'} | ${'== 2.0.7'}
${'~> 1.2.0'} | ${'bump'} | ${'1.2.3'} | ${'2.0.7'} | ${'~> 2.0.7'} ${'~> 1.2.0'} | ${'bump'} | ${'1.2.3'} | ${'2.0.7'} | ${'~> 2.0.7'}
${'~> 0.2 and <= 0.2.6'} | ${'widen'} | ${'0.2.6'} | ${'0.2.8'} | ${'~> 0.2 and <= 0.2.8'}
${'>= 1.0.0 and <= 2.0.0'} | ${'widen'} | ${'1.2.3'} | ${'2.0.7'} | ${'>= 1.0.0 and <= 2.0.7'} ${'>= 1.0.0 and <= 2.0.0'} | ${'widen'} | ${'1.2.3'} | ${'2.0.7'} | ${'>= 1.0.0 and <= 2.0.7'}
${'>= 1.0.0 and <= 2.0.0'} | ${'replace'} | ${'1.2.3'} | ${'2.0.7'} | ${'<= 2.0.7'} ${'>= 1.0.0 and <= 2.0.0'} | ${'replace'} | ${'1.2.3'} | ${'2.0.7'} | ${'<= 2.0.7'}
${'>= 1.0.0 and <= 2.0.0'} | ${'pin'} | ${'1.2.3'} | ${'2.0.7'} | ${'== 2.0.7'} ${'>= 1.0.0 and <= 2.0.0'} | ${'pin'} | ${'1.2.3'} | ${'2.0.7'} | ${'== 2.0.7'}

View file

@ -31,7 +31,7 @@ function npm2hex(input: string): string {
.map((str) => str.trim()) .map((str) => str.trim())
.filter((str) => str !== ''); .filter((str) => str !== '');
let output = ''; let output = '';
const operators = ['^', '=', '>', '<', '<=', '>=', '~']; const operators = ['^', '=', '>', '<', '<=', '>=', '~>'];
for (let i = 0; i < res.length; i += 1) { for (let i = 0; i < res.length; i += 1) {
if (i === res.length - 1) { if (i === res.length - 1) {
output += res[i]; output += res[i];

View file

@ -49,13 +49,27 @@ Here is another example, this time for handling Bitnami Docker images, which use
"packageRules": [ "packageRules": [
{ {
"matchDatasources": ["docker"], "matchDatasources": ["docker"],
"matchPackageNamees": ["bitnami/**", "docker.io/bitnami/**"], "matchPackageNames": ["bitnami/**", "docker.io/bitnami/**"],
"versioning": "regex:^(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)(?:-(?<compatibility>.+)(?<build>\\d+)-r(?<revision>\\d+))?$" "versioning": "regex:^(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)(?:-(?<compatibility>.+)(?<build>\\d+)-r(?<revision>\\d+))?$"
} }
] ]
} }
``` ```
Here is another example, this time for handling `ghcr.io/linuxserver/tautulli` Docker images, which use `major` and `build` indicators with string prefixes:
```json
{
"packageRules": [
{
"matchDatasources": ["docker"],
"matchPackageNames": ["ghcr.io/linuxserver/tautulli"],
"versioning": "regex:^v(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)-ls(?<build>.+)$"
}
]
}
```
Here is another example, this time for handling `ghcr.io/linuxserver/openssh-server` Docker images, which use `patch`, `build` and `revision` indicators with string prefixes: Here is another example, this time for handling `ghcr.io/linuxserver/openssh-server` Docker images, which use `patch`, `build` and `revision` indicators with string prefixes:
```json ```json
@ -63,7 +77,7 @@ Here is another example, this time for handling `ghcr.io/linuxserver/openssh-ser
"packageRules": [ "packageRules": [
{ {
"matchDatasources": ["docker"], "matchDatasources": ["docker"],
"matchPackageNamees": ["ghcr.io/linuxserver/openssh-server"], "matchPackageNames": ["ghcr.io/linuxserver/openssh-server"],
"versioning": "regex:^(?<major>\\d+)\\.(?<minor>\\d+)_p(?<patch>\\d+)-r(?<build>\\d)-ls(?<revision>.+)$" "versioning": "regex:^(?<major>\\d+)\\.(?<minor>\\d+)_p(?<patch>\\d+)-r(?<build>\\d)-ls(?<revision>.+)$"
} }
] ]

View file

@ -306,7 +306,11 @@ describe('workers/global/config/parse/env', () => {
it('crashes', async () => { it('crashes', async () => {
const envParam: NodeJS.ProcessEnv = { RENOVATE_CONFIG: '!@#' }; const envParam: NodeJS.ProcessEnv = { RENOVATE_CONFIG: '!@#' };
await env.getConfig(envParam); processExit.mockImplementationOnce(() => {
throw new Error('terminate function to simulate process.exit call');
});
await expect(env.getConfig(envParam)).toReject();
expect(processExit).toHaveBeenCalledWith(1); expect(processExit).toHaveBeenCalledWith(1);
}); });

View file

@ -3,6 +3,7 @@ import JSON5 from 'json5';
import { getOptions } from '../../../../config/options'; import { getOptions } from '../../../../config/options';
import type { AllConfig } from '../../../../config/types'; import type { AllConfig } from '../../../../config/types';
import { logger } from '../../../../logger'; import { logger } from '../../../../logger';
import { parseJson } from '../../../../util/common';
import { coersions } from './coersions'; import { coersions } from './coersions';
import type { ParseConfigOptions } from './types'; import type { ParseConfigOptions } from './types';
import { migrateAndValidateConfig } from './util'; import { migrateAndValidateConfig } from './util';
@ -118,9 +119,9 @@ function massageConvertedExperimentalVars(
export async function getConfig( export async function getConfig(
inputEnv: NodeJS.ProcessEnv, inputEnv: NodeJS.ProcessEnv,
configEnvKey = 'RENOVATE_CONFIG',
): Promise<AllConfig> { ): Promise<AllConfig> {
let env = inputEnv; let env = normalizePrefixes(inputEnv, inputEnv.ENV_PREFIX);
env = normalizePrefixes(inputEnv, inputEnv.ENV_PREFIX);
env = massageConvertedExperimentalVars(env); env = massageConvertedExperimentalVars(env);
env = renameEnvKeys(env); env = renameEnvKeys(env);
// massage the values of migrated configuration keys // massage the values of migrated configuration keys
@ -128,92 +129,82 @@ export async function getConfig(
const options = getOptions(); const options = getOptions();
let config: AllConfig = {}; const config = await parseAndValidateOrExit(env, configEnvKey);
if (env.RENOVATE_CONFIG) { config.hostRules ??= [];
try {
config = JSON5.parse(env.RENOVATE_CONFIG);
logger.debug({ config }, 'Detected config in env RENOVATE_CONFIG');
config = await migrateAndValidateConfig(config, 'RENOVATE_CONFIG'); for (const option of options) {
} catch (err) { if (option.env === false) {
logger.fatal({ err }, 'Could not parse RENOVATE_CONFIG'); continue;
process.exit(1);
} }
}
config.hostRules ||= []; const envName = getEnvName(option);
const envVal = env[envName];
if (!envVal) {
continue;
}
options.forEach((option) => { if (option.type === 'array' && option.subType === 'object') {
if (option.env !== false) { try {
const envName = getEnvName(option); const parsed = JSON5.parse(envVal);
const envVal = env[envName]; if (is.array(parsed)) {
if (envVal) { config[option.name] = parsed;
if (option.type === 'array' && option.subType === 'object') {
try {
const parsed = JSON5.parse(envVal);
if (is.array(parsed)) {
config[option.name] = parsed;
} else {
logger.debug(
{ val: envVal, envName },
'Could not parse object array',
);
}
} catch {
logger.debug(
{ val: envVal, envName },
'Could not parse environment variable',
);
}
} else { } else {
const coerce = coersions[option.type]; logger.debug(
config[option.name] = coerce(envVal); { val: envVal, envName },
if (option.name === 'dryRun') { 'Could not parse object array',
if ((config[option.name] as string) === 'true') { );
logger.warn( }
'env config dryRun property has been changed to full', } catch {
); logger.debug(
config[option.name] = 'full'; { val: envVal, envName },
} else if ((config[option.name] as string) === 'false') { 'Could not parse environment variable',
logger.warn( );
'env config dryRun property has been changed to null', }
); } else {
delete config[option.name]; const coerce = coersions[option.type];
} else if ((config[option.name] as string) === 'null') { config[option.name] = coerce(envVal);
delete config[option.name]; if (option.name === 'dryRun') {
} if ((config[option.name] as string) === 'true') {
} logger.warn('env config dryRun property has been changed to full');
if (option.name === 'requireConfig') { config[option.name] = 'full';
if ((config[option.name] as string) === 'true') { } else if ((config[option.name] as string) === 'false') {
logger.warn( logger.warn('env config dryRun property has been changed to null');
'env config requireConfig property has been changed to required', delete config[option.name];
); } else if ((config[option.name] as string) === 'null') {
config[option.name] = 'required'; delete config[option.name];
} else if ((config[option.name] as string) === 'false') { }
logger.warn( }
'env config requireConfig property has been changed to optional',
); if (option.name === 'requireConfig') {
config[option.name] = 'optional'; if ((config[option.name] as string) === 'true') {
} logger.warn(
} 'env config requireConfig property has been changed to required',
if (option.name === 'platformCommit') { );
if ((config[option.name] as string) === 'true') { config[option.name] = 'required';
logger.warn( } else if ((config[option.name] as string) === 'false') {
'env config platformCommit property has been changed to enabled', logger.warn(
); 'env config requireConfig property has been changed to optional',
config[option.name] = 'enabled'; );
} else if ((config[option.name] as string) === 'false') { config[option.name] = 'optional';
logger.warn( }
'env config platformCommit property has been changed to disabled', }
);
config[option.name] = 'disabled'; if (option.name === 'platformCommit') {
} if ((config[option.name] as string) === 'true') {
} logger.warn(
'env config platformCommit property has been changed to enabled',
);
config[option.name] = 'enabled';
} else if ((config[option.name] as string) === 'false') {
logger.warn(
'env config platformCommit property has been changed to disabled',
);
config[option.name] = 'disabled';
} }
} }
} }
}); }
if (env.GITHUB_COM_TOKEN) { if (env.GITHUB_COM_TOKEN) {
logger.debug(`Converting GITHUB_COM_TOKEN into a global host rule`); logger.debug(`Converting GITHUB_COM_TOKEN into a global host rule`);
@ -237,7 +228,31 @@ export async function getConfig(
'VSTS_TOKEN', 'VSTS_TOKEN',
]; ];
unsupportedEnv.forEach((val) => delete env[val]); for (const val of unsupportedEnv) {
delete env[val];
}
return config; return config;
} }
async function parseAndValidateOrExit(
env: NodeJS.ProcessEnv,
configEnvKey: string,
): Promise<AllConfig> {
if (!env[configEnvKey]) {
return {};
}
try {
const config = parseJson(
env[configEnvKey],
`${configEnvKey}.env.json5`,
) as AllConfig;
logger.debug({ config }, `Detected config in env ${configEnvKey}`);
return await migrateAndValidateConfig(config, `${configEnvKey}`);
} catch (err) {
logger.fatal({ err }, `Could not parse ${configEnvKey}`);
process.exit(1);
}
}

View file

@ -47,7 +47,7 @@ export function getFixedVersionByDatasource(
return `[${fixedVersion},)`; return `[${fixedVersion},)`;
} }
// crates.io, Go, Hex, npm, RubyGems, PyPI // crates.io, Go, Hackage, Hex, npm, RubyGems, PyPI
return `>= ${fixedVersion}`; return `>= ${fixedVersion}`;
} }
@ -113,9 +113,9 @@ export async function detectVulnerabilityAlerts(
alert.security_vulnerability.first_patched_version.identifier; alert.security_vulnerability.first_patched_version.identifier;
const advisory = alert.security_advisory; const advisory = alert.security_advisory;
combinedAlerts[fileName] ||= {}; combinedAlerts[fileName] ??= {};
combinedAlerts[fileName][datasource] ||= {}; combinedAlerts[fileName][datasource] ??= {};
combinedAlerts[fileName][datasource][depName] ||= { combinedAlerts[fileName][datasource][depName] ??= {
advisories: [], advisories: [],
}; };
const alertDetails = combinedAlerts[fileName][datasource][depName]; const alertDetails = combinedAlerts[fileName][datasource][depName];

View file

@ -160,7 +160,7 @@ function handleOnboardingManualRebase(onboardingPr: Pr): void {
function invalidateExtractCache(baseBranch: string): void { function invalidateExtractCache(baseBranch: string): void {
const cache = getCache(); const cache = getCache();
cache.scan ||= {}; cache.scan ??= {};
if (cache.scan?.[baseBranch]) { if (cache.scan?.[baseBranch]) {
delete cache.scan[baseBranch]; delete cache.scan[baseBranch];

View file

@ -136,7 +136,7 @@ export async function extract(
const baseBranchSha = await scm.getBranchCommit(baseBranch!); const baseBranchSha = await scm.getBranchCommit(baseBranch!);
let packageFiles: Record<string, PackageFile[]>; let packageFiles: Record<string, PackageFile[]>;
const cache = getCache(); const cache = getCache();
cache.scan ||= {}; cache.scan ??= {};
const cachedExtract = cache.scan[baseBranch!]; const cachedExtract = cache.scan[baseBranch!];
const configHash = fingerprint(generateFingerprintConfig(config)); const configHash = fingerprint(generateFingerprintConfig(config));
// istanbul ignore if // istanbul ignore if

View file

@ -840,6 +840,63 @@ describe('workers/repository/process/vulnerabilities', () => {
]); ]);
}); });
it('returns packageRules for Hackage', async () => {
const packageFiles: Record<string, PackageFile[]> = {
hackage: [
{
deps: [
{
depName: 'aeson',
currentValue: '0.4.0.0',
datasource: 'hackage',
},
],
packageFile: 'some-file',
},
],
};
getVulnerabilitiesMock.mockResolvedValueOnce([
{
id: 'HSEC-2023-0001',
summary: 'Hash flooding vulnerability in aeson',
details:
'# Hash flooding vulnerability in aeson\n\n*aeson* was vulnerable to hash flooding (a.k.a. hash DoS). The\nissue is a consequence of the HashMap implementation from\n*unordered-containers*. It results in a denial of service through\nCPU consumption. This technique has been used in real-world attacks\nagainst a variety of languages, libraries and frameworks over the\nyears.\n',
aliases: ['CVE-2022-3433'],
modified: '2023-06-13T09:03:52Z',
affected: [
{
package: {
ecosystem: 'Hackage',
name: 'aeson',
},
ranges: [
{
type: 'ECOSYSTEM',
events: [{ introduced: '0.4.0.0' }, { fixed: '2.0.1.0' }],
},
],
},
],
},
]);
await vulnerabilities.appendVulnerabilityPackageRules(
config,
packageFiles,
);
expect(config.packageRules).toHaveLength(1);
expect(config.packageRules).toMatchObject([
{
matchDatasources: ['hackage'],
matchPackageNames: ['aeson'],
matchCurrentVersion: '0.4.0.0',
allowedVersions: '>= 2.0.1.0',
isVulnerabilityAlert: true,
},
]);
});
it('filters not applicable vulnerability based on last_affected version', async () => { it('filters not applicable vulnerability based on last_affected version', async () => {
const packageFiles: Record<string, PackageFile[]> = { const packageFiles: Record<string, PackageFile[]> = {
poetry: [ poetry: [

View file

@ -35,6 +35,7 @@ export class Vulnerabilities {
> = { > = {
crate: 'crates.io', crate: 'crates.io',
go: 'Go', go: 'Go',
hackage: 'Hackage',
hex: 'Hex', hex: 'Hex',
maven: 'Maven', maven: 'Maven',
npm: 'npm', npm: 'npm',

View file

@ -140,37 +140,37 @@
}, },
"volta": { "volta": {
"node": "22.11.0", "node": "22.11.0",
"pnpm": "9.15.0" "pnpm": "9.15.2"
}, },
"dependencies": { "dependencies": {
"@aws-sdk/client-codecommit": "3.699.0", "@aws-sdk/client-codecommit": "3.716.0",
"@aws-sdk/client-ec2": "3.701.0", "@aws-sdk/client-ec2": "3.716.0",
"@aws-sdk/client-ecr": "3.699.0", "@aws-sdk/client-ecr": "3.720.0",
"@aws-sdk/client-rds": "3.699.0", "@aws-sdk/client-rds": "3.719.1",
"@aws-sdk/client-s3": "3.701.0", "@aws-sdk/client-s3": "3.717.0",
"@aws-sdk/credential-providers": "3.699.0", "@aws-sdk/credential-providers": "3.716.0",
"@breejs/later": "4.2.0", "@breejs/later": "4.2.0",
"@cdktf/hcl2json": "0.20.10", "@cdktf/hcl2json": "0.20.10",
"@opentelemetry/api": "1.9.0", "@opentelemetry/api": "1.9.0",
"@opentelemetry/context-async-hooks": "1.28.0", "@opentelemetry/context-async-hooks": "1.30.0",
"@opentelemetry/exporter-trace-otlp-http": "0.55.0", "@opentelemetry/exporter-trace-otlp-http": "0.57.0",
"@opentelemetry/instrumentation": "0.55.0", "@opentelemetry/instrumentation": "0.57.0",
"@opentelemetry/instrumentation-bunyan": "0.44.0", "@opentelemetry/instrumentation-bunyan": "0.45.0",
"@opentelemetry/instrumentation-http": "0.55.0", "@opentelemetry/instrumentation-http": "0.57.0",
"@opentelemetry/resources": "1.28.0", "@opentelemetry/resources": "1.30.0",
"@opentelemetry/sdk-trace-base": "1.28.0", "@opentelemetry/sdk-trace-base": "1.30.0",
"@opentelemetry/sdk-trace-node": "1.28.0", "@opentelemetry/sdk-trace-node": "1.30.0",
"@opentelemetry/semantic-conventions": "1.28.0", "@opentelemetry/semantic-conventions": "1.28.0",
"@qnighy/marshal": "0.1.3", "@qnighy/marshal": "0.1.3",
"@renovatebot/detect-tools": "1.1.0", "@renovatebot/detect-tools": "1.1.0",
"@renovatebot/kbpgp": "4.0.1", "@renovatebot/kbpgp": "4.0.1",
"@renovatebot/osv-offline": "1.5.10", "@renovatebot/osv-offline": "1.5.11",
"@renovatebot/pep440": "4.0.1", "@renovatebot/pep440": "4.0.1",
"@renovatebot/ruby-semver": "4.0.0", "@renovatebot/ruby-semver": "4.0.0",
"@sindresorhus/is": "4.6.0", "@sindresorhus/is": "4.6.0",
"@yarnpkg/core": "4.1.6", "@yarnpkg/core": "4.2.0",
"@yarnpkg/parsers": "3.0.2", "@yarnpkg/parsers": "3.0.2",
"agentkeepalive": "4.5.0", "agentkeepalive": "4.6.0",
"aggregate-error": "3.1.0", "aggregate-error": "3.1.0",
"async-mutex": "0.5.0", "async-mutex": "0.5.0",
"auth-header": "1.0.0", "auth-header": "1.0.0",
@ -250,7 +250,7 @@
"validate-npm-package-name": "6.0.0", "validate-npm-package-name": "6.0.0",
"vuln-vects": "1.1.0", "vuln-vects": "1.1.0",
"xmldoc": "1.3.0", "xmldoc": "1.3.0",
"yaml": "2.6.1", "yaml": "2.7.0",
"zod": "3.24.1" "zod": "3.24.1"
}, },
"optionalDependencies": { "optionalDependencies": {
@ -269,7 +269,7 @@
"@openpgp/web-stream-tools": "0.1.3", "@openpgp/web-stream-tools": "0.1.3",
"@renovate/eslint-plugin": "file:tools/eslint", "@renovate/eslint-plugin": "file:tools/eslint",
"@semantic-release/exec": "6.0.3", "@semantic-release/exec": "6.0.3",
"@swc/core": "1.10.1", "@swc/core": "1.10.4",
"@types/auth-header": "1.0.6", "@types/auth-header": "1.0.6",
"@types/aws4": "1.11.6", "@types/aws4": "1.11.6",
"@types/better-sqlite3": "7.6.12", "@types/better-sqlite3": "7.6.12",
@ -311,34 +311,34 @@
"@types/url-join": "4.0.3", "@types/url-join": "4.0.3",
"@types/validate-npm-package-name": "4.0.2", "@types/validate-npm-package-name": "4.0.2",
"@types/xmldoc": "1.1.9", "@types/xmldoc": "1.1.9",
"@typescript-eslint/eslint-plugin": "8.11.0", "@typescript-eslint/eslint-plugin": "8.19.0",
"@typescript-eslint/parser": "8.11.0", "@typescript-eslint/parser": "8.19.0",
"aws-sdk-client-mock": "4.1.0", "aws-sdk-client-mock": "4.1.0",
"callsite": "1.0.0", "callsite": "1.0.0",
"common-tags": "1.8.2", "common-tags": "1.8.2",
"conventional-changelog-conventionalcommits": "8.0.0", "conventional-changelog-conventionalcommits": "8.0.0",
"emojibase-data": "16.0.2", "emojibase-data": "16.0.2",
"eslint": "8.57.1", "eslint": "8.57.1",
"eslint-formatter-gha": "1.5.1", "eslint-formatter-gha": "1.5.2",
"eslint-import-resolver-typescript": "3.6.3", "eslint-import-resolver-typescript": "3.7.0",
"eslint-plugin-import": "2.31.0", "eslint-plugin-import": "2.31.0",
"eslint-plugin-jest": "28.8.3", "eslint-plugin-jest": "28.10.0",
"eslint-plugin-jest-formatting": "3.1.0", "eslint-plugin-jest-formatting": "3.1.0",
"eslint-plugin-promise": "7.1.0", "eslint-plugin-promise": "7.2.1",
"eslint-plugin-typescript-enum": "2.1.0", "eslint-plugin-typescript-enum": "2.1.0",
"expect": "29.7.0", "expect": "29.7.0",
"expect-more-jest": "5.5.0", "expect-more-jest": "5.5.0",
"graphql": "16.9.0", "graphql": "16.10.0",
"husky": "9.1.7", "husky": "9.1.7",
"jest": "29.7.0", "jest": "29.7.0",
"jest-extended": "4.0.2", "jest-extended": "4.0.2",
"jest-mock": "29.7.0", "jest-mock": "29.7.0",
"jest-mock-extended": "3.0.7", "jest-mock-extended": "3.0.7",
"jest-snapshot": "29.7.0", "jest-snapshot": "29.7.0",
"markdownlint-cli2": "0.16.0", "markdownlint-cli2": "0.17.1",
"memfs": "4.15.0", "memfs": "4.15.2",
"nock": "13.5.6", "nock": "13.5.6",
"npm-run-all2": "7.0.1", "npm-run-all2": "7.0.2",
"nyc": "17.1.0", "nyc": "17.1.0",
"pretty-format": "29.7.0", "pretty-format": "29.7.0",
"rimraf": "6.0.1", "rimraf": "6.0.1",
@ -347,11 +347,11 @@
"tmp-promise": "3.0.3", "tmp-promise": "3.0.3",
"ts-jest": "29.2.5", "ts-jest": "29.2.5",
"ts-node": "10.9.2", "ts-node": "10.9.2",
"type-fest": "4.30.1", "type-fest": "4.31.0",
"typescript": "5.7.2", "typescript": "5.7.2",
"unified": "9.2.2" "unified": "9.2.2"
}, },
"packageManager": "pnpm@9.15.0", "packageManager": "pnpm@9.15.2",
"files": [ "files": [
"dist", "dist",
"renovate-schema.json" "renovate-schema.json"

132
pdm.lock
View file

@ -5,7 +5,7 @@
groups = ["default"] groups = ["default"]
strategy = ["inherit_metadata"] strategy = ["inherit_metadata"]
lock_version = "4.5.0" lock_version = "4.5.0"
content_hash = "sha256:600db411871a7859e3c5506989a7bb6a9101938ebf6797e8d3180309a5a2681f" content_hash = "sha256:389d88fe2eea354363ad2bc3a292f9398c1ab70d41dec7307928a6d5fe1a11c5"
[[metadata.targets]] [[metadata.targets]]
requires_python = ">=3.11" requires_python = ">=3.11"
@ -48,63 +48,57 @@ files = [
[[package]] [[package]]
name = "charset-normalizer" name = "charset-normalizer"
version = "3.4.0" version = "3.4.1"
requires_python = ">=3.7.0" requires_python = ">=3.7"
summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
groups = ["default"] groups = ["default"]
files = [ files = [
{file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"},
{file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"},
{file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"},
{file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"},
{file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"},
{file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"},
{file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"},
{file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"},
{file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"},
{file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"},
{file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"},
{file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"},
{file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"},
{file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"},
{file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"},
{file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"},
{file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"},
{file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"},
{file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"},
{file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"},
{file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"},
{file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"},
{file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"},
{file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"},
{file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"},
{file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"},
{file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"},
{file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"},
{file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"},
{file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"},
{file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"},
{file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"},
{file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"},
{file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"},
{file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"},
{file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"},
{file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"},
{file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"},
{file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"},
{file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"},
{file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"},
{file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"},
{file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"},
{file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"},
{file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"},
{file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"},
{file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"},
] ]
[[package]] [[package]]
name = "click" name = "click"
version = "8.1.7" version = "8.1.8"
requires_python = ">=3.7" requires_python = ">=3.7"
summary = "Composable command line interface toolkit" summary = "Composable command line interface toolkit"
groups = ["default"] groups = ["default"]
@ -113,8 +107,8 @@ dependencies = [
"importlib-metadata; python_version < \"3.8\"", "importlib-metadata; python_version < \"3.8\"",
] ]
files = [ files = [
{file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"},
{file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"},
] ]
[[package]] [[package]]
@ -154,7 +148,7 @@ files = [
[[package]] [[package]]
name = "jinja2" name = "jinja2"
version = "3.1.4" version = "3.1.5"
requires_python = ">=3.7" requires_python = ">=3.7"
summary = "A very fast and expressive template engine." summary = "A very fast and expressive template engine."
groups = ["default"] groups = ["default"]
@ -162,8 +156,8 @@ dependencies = [
"MarkupSafe>=2.0", "MarkupSafe>=2.0",
] ]
files = [ files = [
{file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, {file = "jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"},
{file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, {file = "jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb"},
] ]
[[package]] [[package]]
@ -270,7 +264,7 @@ files = [
[[package]] [[package]]
name = "mkdocs-awesome-pages-plugin" name = "mkdocs-awesome-pages-plugin"
version = "2.9.3" version = "2.10.1"
requires_python = ">=3.8.1" requires_python = ">=3.8.1"
summary = "An MkDocs plugin that simplifies configuring page titles and their order" summary = "An MkDocs plugin that simplifies configuring page titles and their order"
groups = ["default"] groups = ["default"]
@ -280,8 +274,8 @@ dependencies = [
"wcmatch>=7", "wcmatch>=7",
] ]
files = [ files = [
{file = "mkdocs_awesome_pages_plugin-2.9.3-py3-none-any.whl", hash = "sha256:1ba433d4e7edaf8661b15b93267f78f78e2e06ca590fc0e651ea36b191d64ae4"}, {file = "mkdocs_awesome_pages_plugin-2.10.1-py3-none-any.whl", hash = "sha256:c6939dbea37383fc3cf8c0a4e892144ec3d2f8a585e16fdc966b34e7c97042a7"},
{file = "mkdocs_awesome_pages_plugin-2.9.3.tar.gz", hash = "sha256:bdf6369871f41bb17f09c3cfb573367732dfcceb5673d7a2c5c76ac2567b242f"}, {file = "mkdocs_awesome_pages_plugin-2.10.1.tar.gz", hash = "sha256:cda2cb88c937ada81a4785225f20ef77ce532762f4500120b67a1433c1cdbb2f"},
] ]
[[package]] [[package]]
@ -392,18 +386,18 @@ files = [
[[package]] [[package]]
name = "pygments" name = "pygments"
version = "2.18.0" version = "2.19.0"
requires_python = ">=3.8" requires_python = ">=3.8"
summary = "Pygments is a syntax highlighting package written in Python." summary = "Pygments is a syntax highlighting package written in Python."
groups = ["default"] groups = ["default"]
files = [ files = [
{file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, {file = "pygments-2.19.0-py3-none-any.whl", hash = "sha256:4755e6e64d22161d5b61432c0600c923c5927214e7c956e31c23923c89251a9b"},
{file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, {file = "pygments-2.19.0.tar.gz", hash = "sha256:afc4146269910d4bdfabcd27c24923137a74d562a23a320a41a55ad303e19783"},
] ]
[[package]] [[package]]
name = "pymdown-extensions" name = "pymdown-extensions"
version = "10.12" version = "10.13"
requires_python = ">=3.8" requires_python = ">=3.8"
summary = "Extension pack for Python Markdown." summary = "Extension pack for Python Markdown."
groups = ["default"] groups = ["default"]
@ -412,8 +406,8 @@ dependencies = [
"pyyaml", "pyyaml",
] ]
files = [ files = [
{file = "pymdown_extensions-10.12-py3-none-any.whl", hash = "sha256:49f81412242d3527b8b4967b990df395c89563043bc51a3d2d7d500e52123b77"}, {file = "pymdown_extensions-10.13-py3-none-any.whl", hash = "sha256:80bc33d715eec68e683e04298946d47d78c7739e79d808203df278ee8ef89428"},
{file = "pymdown_extensions-10.12.tar.gz", hash = "sha256:b0ee1e0b2bef1071a47891ab17003bfe5bf824a398e13f49f8ed653b699369a7"}, {file = "pymdown_extensions-10.13.tar.gz", hash = "sha256:e0b351494dc0d8d14a1f52b39b1499a00ef1566b4ba23dc74f1eba75c736f5dd"},
] ]
[[package]] [[package]]
@ -566,13 +560,13 @@ files = [
[[package]] [[package]]
name = "urllib3" name = "urllib3"
version = "2.2.3" version = "2.3.0"
requires_python = ">=3.8" requires_python = ">=3.9"
summary = "HTTP library with thread-safe connection pooling, file post, and more." summary = "HTTP library with thread-safe connection pooling, file post, and more."
groups = ["default"] groups = ["default"]
files = [ files = [
{file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"},
{file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"},
] ]
[[package]] [[package]]

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
[project] [project]
dependencies = [ dependencies = [
"mkdocs-material==9.5.49", "mkdocs-material==9.5.49",
"mkdocs-awesome-pages-plugin==2.9.3", "mkdocs-awesome-pages-plugin==2.10.1",
] ]
requires-python = ">=3.11" requires-python = ">=3.11"

View file

@ -5,19 +5,19 @@ ARG BASE_IMAGE_TYPE=slim
# -------------------------------------- # --------------------------------------
# slim image # slim image
# -------------------------------------- # --------------------------------------
FROM ghcr.io/renovatebot/base-image:9.25.1@sha256:886a31c0e6384d8b9673e41051da4421abdc2aa78b5a5fdd831713f0ca51a44b AS slim-base FROM ghcr.io/renovatebot/base-image:9.28.1@sha256:d012a79a5f3dc6e6067c46016405064b30fbaaac954597318a7a2122ef807444 AS slim-base
# -------------------------------------- # --------------------------------------
# full image # full image
# -------------------------------------- # --------------------------------------
FROM ghcr.io/renovatebot/base-image:9.25.1-full@sha256:ce2f4079137e50eb551d4b9cf8b8107c5459ecde3ed8e448e1f42c4810113758 AS full-base FROM ghcr.io/renovatebot/base-image:9.28.1-full@sha256:422a843cbf6c1a3730fab9e89877bf04c49d329501a5b998488078cc6153fc03 AS full-base
ENV RENOVATE_BINARY_SOURCE=global ENV RENOVATE_BINARY_SOURCE=global
# -------------------------------------- # --------------------------------------
# build image # build image
# -------------------------------------- # --------------------------------------
FROM --platform=$BUILDPLATFORM ghcr.io/renovatebot/base-image:9.25.1@sha256:886a31c0e6384d8b9673e41051da4421abdc2aa78b5a5fdd831713f0ca51a44b AS build FROM --platform=$BUILDPLATFORM ghcr.io/renovatebot/base-image:9.28.1@sha256:d012a79a5f3dc6e6067c46016405064b30fbaaac954597318a7a2122ef807444 AS build
# We want a specific node version here # We want a specific node version here
# renovate: datasource=node-version # renovate: datasource=node-version

View file

@ -27,7 +27,7 @@ for FILTER in "$TYPE_LABELS_FILTER" "$PRIORITY_LABELS_FILTER"; do
HAS_ISSUES_MISSING_LABELS=true HAS_ISSUES_MISSING_LABELS=true
# Create a list of issue numbers # Create a list of issue numbers
FORMATTED_OUTPUT=$(echo "$ISSUES_MISSING_LABEL" | jq -r '.[].number' | sed 's/^/- #/') FORMATTED_OUTPUT=$(echo "$ISSUES_MISSING_LABEL" | jq -r '.[].number' | sed 's/^/- https:\/\/redirect.github.com\/renovatebot\/renovate\/issues\//')
# Count the issues and decide if the output should be singular or plural # Count the issues and decide if the output should be singular or plural
ISSUE_COUNT=$(echo "$ISSUES_MISSING_LABEL" | jq '. | length') ISSUE_COUNT=$(echo "$ISSUES_MISSING_LABEL" | jq '. | length')

View file

@ -59,7 +59,7 @@ theme:
# The custom_dir points to the overrides folder, this folder has the code for our announcement bar. # The custom_dir points to the overrides folder, this folder has the code for our announcement bar.
# The easiest way to disable the announcement bar is to comment out the custom_dir: overrides entry in this mkdocs.yml file. # The easiest way to disable the announcement bar is to comment out the custom_dir: overrides entry in this mkdocs.yml file.
# https://squidfunk.github.io/mkdocs-material/customization/#setup-and-theme-structure # https://squidfunk.github.io/mkdocs-material/customization/#setup-and-theme-structure
custom_dir: overrides # custom_dir: overrides
logo: 'assets/images/logo.png' logo: 'assets/images/logo.png'
favicon: 'assets/images/logo.png' favicon: 'assets/images/logo.png'