1 Commits

Author SHA1 Message Date
Gabriele Bartolini
1af4edac02 docs: add basic security section
closes #209

Signed-off-by: Gabriele Bartolini <gabriele.bartolini@enterprisedb.com>
2025-09-25 18:41:36 +02:00
10 changed files with 90 additions and 255 deletions

View File

@@ -1,120 +0,0 @@
# Copy Images Action
This composite GitHub Action copies a set of container images from a
`testing registry` to a `production registry`, and signs them using `Cosign`.
It requires as input Bake's build result metadata, which is the output provided
by the [bake-action](https://github.com/docker/bake-action?tab=readme-ov-file#outputs).
---
## How it works
The action assumes a consistent naming convention between your testing and production registries.
* A production image is named like `ghcr.io/org/image`
* The corresponding testing image must include a suffix, e.g. `ghcr.io/org/image-testing`
You can customize this suffix with the `inputs.test_registry_suffix` input.
The action proceeds as follows:
1. It retrieves all image references from `inputs.bake_build_metadata`
2. It generates a list of destination images by stripping out the `test_registry_suffix` from each image
3. Each image is copied to the destination registry using `Skopeo copy`. The digest of the image is preserved.
4. Each production image is signed using `Cosign`
---
## Requirements
This composite action requires the calling workflows `GITHUB_TOKEN`
to have the following permissions:
```
permissions:
contents: read
packages: write
id-token: write # needed by Cosign for signing the images with GitHub OIDC Token
```
---
## Inputs
| Name | Description | Required | Default |
| ---------------------- | -------------------------------------------------- | --------- | -------------- |
| `bake_build_metadata` | The JSON build result metadata generated by Bake | ✅ Yes | — |
| `registry_user` | The user used to authenticate to the registry | ✅ Yes | — |
| `registry_token` | The token used to authenticate to the registry | ✅ Yes | — |
| `test_registry_suffix` | The suffix of the testing images | ❌ No | `-testing` |
Note:
The JSON build result metadata is provided by [bake-action](https://github.com/docker/bake-action) as an output, see
[bake-action outputs](https://github.com/docker/bake-action?tab=readme-ov-file#outputs).
Alternatively, if you are using `docker buildx bake` via commandline, you can write your build metadata to a file
by using `--metadata-file`, and then provide the content of that file as `input.bake_build_metadata`.
---
## Usage
Example usage:
```
jobs:
copytoproduction:
runs-on: ubuntu-latest
needs:
- testbuild
permissions:
contents: read
packages: write
id-token: write
steps:
- name: Copy to production
uses: cloudnative-pg/postgres-containers/.github/actions/copy-images@main
with:
bake_build_metadata: "${{ needs.testbuild.outputs.metadata }}"
registry_user: ${{ github.actor }}
registry_token: ${{ secrets.GITHUB_TOKEN }}
```
Example workflow:
```
jobs:
# Building and pushing to a testing registry
testbuild:
runs-on: ubuntu-latest
outputs:
metadata: ${{ steps.build.outputs.metadata }}
steps:
...
- uses: docker/bake-action@v6
id: build
with:
push: true
# Here's when you'd want to have one or
# multiple jobs to scan and test your images
scan-images:
...
# If the tests passed, we promote the images to the production repo
copytoproduction:
runs-on: ubuntu-latest
needs:
- testbuild
- scan-images
permissions:
contents: read
packages: write
id-token: write
steps:
- name: Copy to production
uses: cloudnative-pg/postgres-containers/.github/actions/copy-images@main
with:
bake_build_metadata: "${{ needs.testbuild.outputs.metadata }}"
registry_user: ${{ github.actor }}
registry_token: ${{ secrets.GITHUB_TOKEN }}
```

View File

@@ -1,75 +0,0 @@
name: Copy and sign images
description: Copy and sign images to the production repository
inputs:
bake_build_metadata:
description: "The JSON build metadata of Bake"
required: true
registry_user:
description: "The user used to authenticate to the registry"
required: true
registry_token:
description: "The token used to authenticate to the registry"
required: true
test_registry_suffix:
description: "The testing registry suffix"
required: false
default: '-testing'
runs:
using: composite
steps:
- name: Log in to the GitHub Container registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3
with:
registry: ghcr.io
username: ${{ inputs.registry_user }}
password: ${{ inputs.registry_token }}
- name: Copy images
shell: bash
env:
# renovate: datasource=docker depName=quay.io/skopeo/stable versioning=loose
SKOPEO_VERSION: "v1.20.0-immutable"
SUFFIX: ${{ inputs.test_registry_suffix }}
run: |
images=$(echo '${{ inputs.bake_build_metadata }}' |
jq -r '
.[] as $items |
(
$items."image.name" |
split(",")[] +
"@" +
$items."containerimage.digest"
)
'
)
for image in $images
do
testimageshaonly="${image%:*@*}@${image#*@}"
testimagenosha="${image%@*}"
prodimage="${testimagenosha/$SUFFIX/}"
echo "Copying ${testimageshaonly} to ${prodimage}"
docker run --quiet quay.io/skopeo/stable:$SKOPEO_VERSION copy -q -a \
--dest-creds ${{ inputs.registry_user }}:${{ inputs.registry_token }} \
docker://${testimageshaonly} docker://${prodimage}
done
- name: Install cosign
uses: sigstore/cosign-installer@398d4b0eeef1380460a10c8013a76f728fb906ac # v3
- name: Sign images
shell: bash
env:
SUFFIX: ${{ inputs.test_registry_suffix }}
run: |
images=$(echo '${{ inputs.bake_build_metadata }}' |
jq -r --arg suffix "$SUFFIX" '.[] |
(
."image.name" |
sub(",.*";"") |
sub($suffix + ":[^@]+";"")
) + "@" + ."containerimage.digest"
'
)
echo "Signing ${images}"
cosign sign -t 5m --yes ${images}

View File

@@ -26,7 +26,7 @@ runs:
- name: Set up Python - name: Set up Python
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6 uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6
with: with:
python-version: 3.14 python-version: 3.13
- name: Install Python dependencies - name: Install Python dependencies
shell: bash shell: bash

View File

@@ -51,8 +51,6 @@ jobs:
with: with:
environment: ${{ github.event.inputs.environment }} environment: ${{ github.event.inputs.environment }}
postgresql_version: ${{ matrix.version }} postgresql_version: ${{ matrix.version }}
secrets:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
Catalogs: Catalogs:
name: Update Catalogs name: Update Catalogs
@@ -65,6 +63,6 @@ jobs:
( github.event.inputs.environment == 'production' || github.event_name == 'schedule' ) ( github.event.inputs.environment == 'production' || github.event_name == 'schedule' )
steps: steps:
- name: Repository Dispatch - name: Repository Dispatch
uses: peter-evans/repository-dispatch@5fc4efd1a4797ddb68ffd0714a238564e4cc0e6f # v4 uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # v3
with: with:
event-type: update-catalogs event-type: update-catalogs

View File

@@ -29,9 +29,6 @@ on:
`source` directory. `source` directory.
required: false required: false
type: string type: string
secrets:
SNYK_TOKEN:
required: false
permissions: {} permissions: {}
@@ -77,7 +74,7 @@ jobs:
echo "filtered_targets=$target" >> "$GITHUB_OUTPUT" echo "filtered_targets=$target" >> "$GITHUB_OUTPUT"
- name: Log in to the GitHub Container registry - name: Log in to the GitHub Container registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3 uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
@@ -144,7 +141,7 @@ jobs:
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
- name: Log in to the GitHub Container registry - name: Log in to the GitHub Container registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3 uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
@@ -161,10 +158,6 @@ jobs:
- name: Snyk - name: Snyk
uses: snyk/actions/docker@master uses: snyk/actions/docker@master
id: snyk
if: ${{ env.SNYK_TOKEN != '' }}
# Snyk can be used to break the build when it detects vulnerabilities.
# In this case we want to upload the issues to GitHub Code Scanning.
continue-on-error: true continue-on-error: true
env: env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
@@ -172,18 +165,15 @@ jobs:
image: "${{ matrix.image }}" image: "${{ matrix.image }}"
args: --severity-threshold=high --file=Dockerfile args: --severity-threshold=high --file=Dockerfile
- name: Replace sarif security-severity invalid values
if: ${{ steps.snyk.conclusion == 'success' }}
run: |
sed -i 's/"security-severity": "null"/"security-severity": "0"/g' snyk.sarif
sed -i 's/"security-severity": "undefined"/"security-severity": "0"/g' snyk.sarif
- name: Upload result to GitHub Code Scanning - name: Upload result to GitHub Code Scanning
uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4 uses: github/codeql-action/upload-sarif@192325c86100d080feab897ff886c34abd4c83a3 # v3
if: ${{ steps.snyk.conclusion == 'success' }} continue-on-error: true
with: with:
sarif_file: snyk.sarif sarif_file: snyk.sarif
# Use the metadata generated in the `testbuild` step to find all the images
# that have been built. We copy them one by one to the production registry
# using skopeo. Then we sign the production images too.
copytoproduction: copytoproduction:
name: Copy images to production name: Copy images to production
if: | if: |
@@ -196,15 +186,54 @@ jobs:
permissions: permissions:
contents: read contents: read
packages: write packages: write
security-events: write
# Required by the cosign step # Required by the cosign step
id-token: write id-token: write
steps: steps:
- name: Checkout Code - name: Log in to the GitHub Container registry
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3
- name: Copy to production
uses: ./.github/actions/copy-images
with: with:
bake_build_metadata: "${{ needs.testbuild.outputs.metadata }}" registry: ghcr.io
registry_user: ${{ github.actor }} username: ${{ github.actor }}
registry_token: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Copy images
run: |
images=$(echo '${{ needs.testbuild.outputs.metadata }}' |
jq -r '
.[] as $items |
(
$items."image.name" |
split(",")[] +
"@" +
$items."containerimage.digest"
)
'
)
for image in $images
do
testimageshaonly="${image%:*@*}@${image#*@}"
testimagenosha="${image%@*}"
prodimage="${testimagenosha/-testing/}"
echo "Copying ${testimageshaonly} to ${prodimage}"
docker run --quiet quay.io/skopeo/stable:v1.17.0-immutable copy -q -a \
--dest-creds ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} \
docker://${testimageshaonly} docker://${prodimage}
done
- name: Install cosign
uses: sigstore/cosign-installer@398d4b0eeef1380460a10c8013a76f728fb906ac # v3
- name: Sign images
run: |
images=$(echo '${{ needs.testbuild.outputs.metadata }}' |
jq -r '.[] |
(
."image.name" |
sub(",.*";"") |
sub("-testing:[^@]+";"")
) + "@" + ."containerimage.digest"
'
)
echo "Signing ${images}"
cosign sign -t 5m --yes ${images}

View File

@@ -6,19 +6,17 @@ metadata:
images.cnpg.io/family: postgresql images.cnpg.io/family: postgresql
images.cnpg.io/type: system images.cnpg.io/type: system
images.cnpg.io/os: bookworm images.cnpg.io/os: bookworm
images.cnpg.io/date: '20251013' images.cnpg.io/date: '20250923'
images.cnpg.io/publisher: cnpg.io images.cnpg.io/publisher: cnpg.io
spec: spec:
images: images:
- major: 13 - major: 13
image: ghcr.io/cloudnative-pg/postgresql:13.22-202510130807-system-bookworm@sha256:8960f067c4e5c633e5deff50f781957ca4579d72d275739c586befe9d05d444c image: ghcr.io/cloudnative-pg/postgresql:13.22-202509220807-system-bookworm@sha256:b4a1e2d577546d32e82d44168e6977b3d4b0a4765bb4a7482e353f99ec49216a
- major: 14 - major: 14
image: ghcr.io/cloudnative-pg/postgresql:14.19-202510130807-system-bookworm@sha256:b020285c14e795e262760e5e2c8111769788a7da45e8ee9d1af10ed7a5b66cab image: ghcr.io/cloudnative-pg/postgresql:14.19-202509220807-system-bookworm@sha256:fb3a27a77364017ec604a24f19def5124b945e6e45cb4613455f0aee3e15cc47
- major: 15 - major: 15
image: ghcr.io/cloudnative-pg/postgresql:15.14-202510130807-system-bookworm@sha256:06096a05e7216ada6eafe2e72e7cae1a9d2e57561541caecfcdfcecb4bd03df3 image: ghcr.io/cloudnative-pg/postgresql:15.14-202509220807-system-bookworm@sha256:fbdf4141d38d6c70e6ab10a2d6ab6b7a5853b62fa1bba78b4353032e0b345740
- major: 16 - major: 16
image: ghcr.io/cloudnative-pg/postgresql:16.10-202510130807-system-bookworm@sha256:830b0a2d5b616b06cbb4f594453dc20bafadeb3f1c48441668e9c7e088b0c7d1 image: ghcr.io/cloudnative-pg/postgresql:16.10-202509220807-system-bookworm@sha256:41561360238d5fb7a85e2b1d75f1e5d626be37b94a01306432ad7f94cf542dc4
- major: 17 - major: 17
image: ghcr.io/cloudnative-pg/postgresql:17.6-202510130807-system-bookworm@sha256:71f14116070ce91762198fac8504daee954e75d5d0685363f7844309555130e6 image: ghcr.io/cloudnative-pg/postgresql:17.6-202509220807-system-bookworm@sha256:b931f2c7d6e259c1448a88486912da2a3e4039e13c9099e3c09a54cbb25a36cf
- major: 18
image: ghcr.io/cloudnative-pg/postgresql:18.0-202510130807-system-bookworm@sha256:12707396990ac3ad9767404180f36ea4998761483365938db1f3a8050b50effb

View File

@@ -6,19 +6,17 @@ metadata:
images.cnpg.io/family: postgresql images.cnpg.io/family: postgresql
images.cnpg.io/type: system images.cnpg.io/type: system
images.cnpg.io/os: bullseye images.cnpg.io/os: bullseye
images.cnpg.io/date: '20251013' images.cnpg.io/date: '20250923'
images.cnpg.io/publisher: cnpg.io images.cnpg.io/publisher: cnpg.io
spec: spec:
images: images:
- major: 13 - major: 13
image: ghcr.io/cloudnative-pg/postgresql:13.22-202510130807-system-bullseye@sha256:da485ff71aaa4ff044071af2eb91b18eff65a3befacb988af73b8096ffdc5837 image: ghcr.io/cloudnative-pg/postgresql:13.22-202509220807-system-bullseye@sha256:16323ff5e13f568c943720756ebc59d162adff4a4f9349038ae1796f757448c8
- major: 14 - major: 14
image: ghcr.io/cloudnative-pg/postgresql:14.19-202510130807-system-bullseye@sha256:bdc36b98eb96d0f613fb4570460c57ee27114d2bbfe126d9f29b51766b9ca37e image: ghcr.io/cloudnative-pg/postgresql:14.19-202509220807-system-bullseye@sha256:f74e898ab8ef56d2b9cd259871eef9415b8b3dbdc5c916315073cd2144e89d28
- major: 15 - major: 15
image: ghcr.io/cloudnative-pg/postgresql:15.14-202510130807-system-bullseye@sha256:15661a17359d2ff46961e03a2a6593d58c779624ba5e684780111c09291b49c8 image: ghcr.io/cloudnative-pg/postgresql:15.14-202509220807-system-bullseye@sha256:041340459b4d3ebdaffd55fd2296ca01992fb467301b505bb19b8689434b42a8
- major: 16 - major: 16
image: ghcr.io/cloudnative-pg/postgresql:16.10-202510130807-system-bullseye@sha256:697e6d8e15ace744fe3b0035d4ea633d3a2b2e59138e8a0481014e924dd1b4d4 image: ghcr.io/cloudnative-pg/postgresql:16.10-202509220807-system-bullseye@sha256:9746b62a5f1981533dd475ebc1bd8c7740b8dc8c60fa06db0407c6c6c1254fed
- major: 17 - major: 17
image: ghcr.io/cloudnative-pg/postgresql:17.6-202510130807-system-bullseye@sha256:b7f2855c5a419249e30d64616da38cbb7ed3397a21cb115a581a02da8cb21ee0 image: ghcr.io/cloudnative-pg/postgresql:17.6-202509220807-system-bullseye@sha256:b9763f1137de625622dab2a4b94a456c5a6587d0444885b282d9c222370b3955
- major: 18
image: ghcr.io/cloudnative-pg/postgresql:18.0-202510130807-system-bullseye@sha256:5f67a8c8ae429c8af5692024ad58408a3f70223bf5d1cb9f9dbc36dcead88919

View File

@@ -18,13 +18,14 @@ This repository provides maintenance scripts for generating
| Version | Release Date | EOL | | Version | Release Date | EOL |
|:-------:|:------------:|:----------:| |:-------:|:------------:|:----------:|
| 18 | 2025-09-25 | 2030-11-14 |
| 17 | 2024-09-26 | 2029-11-08 | | 17 | 2024-09-26 | 2029-11-08 |
| 16 | 2023-09-14 | 2028-11-09 | | 16 | 2023-09-14 | 2028-11-09 |
| 15 | 2022-10-13 | 2027-11-11 | | 15 | 2022-10-13 | 2027-11-11 |
| 14 | 2021-09-30 | 2026-11-12 | | 14 | 2021-09-30 | 2026-11-12 |
| 13 | 2020-09-24 | 2025-11-13 | | 13 | 2020-09-24 | 2025-11-13 |
In addition, PostgreSQL 18 RC1 is provided for testing purposes only.
These images are designed to serve as operands of the These images are designed to serve as operands of the
[CloudNativePG (CNPG) operator](https://cloudnative-pg.io) in Kubernetes [CloudNativePG (CNPG) operator](https://cloudnative-pg.io) in Kubernetes
environments, and are not intended for standalone use. environments, and are not intended for standalone use.
@@ -191,7 +192,9 @@ and [`ClusterImageCatalog-bookworm.yaml`](Debian/ClusterImageCatalog-bookworm.ya
manifests, please migrate to the new catalogs as soon as possible. These legacy manifests, please migrate to the new catalogs as soon as possible. These legacy
manifests are deprecated and will be removed along with the `system` image. manifests are deprecated and will be removed along with the `system` image.
## Build Attestations ## Security
### Build Attestations
CNPG PostgreSQL Container Images are built with the following attestations to CNPG PostgreSQL Container Images are built with the following attestations to
ensure transparency and traceability: ensure transparency and traceability:
@@ -215,7 +218,7 @@ docker buildx imagetools inspect <IMAGE> --format "{{ json .SBOM.SPDX }}"
This command outputs the SBOM in JSON format, providing a detailed view of the This command outputs the SBOM in JSON format, providing a detailed view of the
software components and build dependencies. software components and build dependencies.
## Image Signatures ### Image Signatures
The [`minimal`](#minimal-images) and [`standard`](#standard-images) CloudNativePG container images are securely signed using The [`minimal`](#minimal-images) and [`standard`](#standard-images) CloudNativePG container images are securely signed using
[cosign](https://github.com/sigstore/cosign), a tool within the [cosign](https://github.com/sigstore/cosign), a tool within the
@@ -238,6 +241,18 @@ cosign verify IMAGE \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" --certificate-oidc-issuer="https://token.actions.githubusercontent.com"
``` ```
## Image Scanning in CI/CD
To further strengthen the security of our container images, we perform
automated image scanning as part of our CI/CD workflows. These scans help
ensure that our images adhere to best practices and remain free of known
vulnerabilities before they are published or deployed:
- **Dockle**: Verifies configuration best practices for container images. Runs
during the build stage; critical failures can block the build.
- **Snyk**: Detects vulnerabilities in OS packages, libraries, and dependencies
within the container. Runs after image build.
## Building Images ## Building Images
For detailed instructions on building PostgreSQL container images, refer to the For detailed instructions on building PostgreSQL container images, refer to the

View File

@@ -34,6 +34,7 @@ postgreSQLVersions = [
// Preview versions are automatically filtered out if present in the stable list // Preview versions are automatically filtered out if present in the stable list
// MANUALLY EDIT THE CONTENT - AND UPDATE THE README.md FILE TOO // MANUALLY EDIT THE CONTENT - AND UPDATE THE README.md FILE TOO
postgreSQLPreviewVersions = [ postgreSQLPreviewVersions = [
"18~rc1",
] ]
// Barman version to build // Barman version to build
@@ -58,11 +59,11 @@ target "default" {
pgVersion = getPgVersions(postgreSQLVersions, postgreSQLPreviewVersions) pgVersion = getPgVersions(postgreSQLVersions, postgreSQLPreviewVersions)
base = [ base = [
// renovate: datasource=docker versioning=loose // renovate: datasource=docker versioning=loose
"debian:trixie-slim@sha256:1caf1c703c8f7e15dcf2e7769b35000c764e6f50e4d7401c355fb0248f3ddfdb", "debian:trixie-slim@sha256:c2880112cc5c61e1200c26f106e4123627b49726375eb5846313da9cca117337",
// renovate: datasource=docker versioning=loose // renovate: datasource=docker versioning=loose
"debian:bookworm-slim@sha256:7e490910eea2861b9664577a96b54ce68ea3e02ce7f51d89cb0103a6f9c386e0", "debian:bookworm-slim@sha256:df52e55e3361a81ac1bead266f3373ee55d29aa50cf0975d440c2be3483d8ed3",
// renovate: datasource=docker versioning=loose // renovate: datasource=docker versioning=loose
"debian:bullseye-slim@sha256:f807f4b16002c623115b0247dca6a55711c6b1ae821dc64fb8a2339e4ce2115d" "debian:bullseye-slim@sha256:6d3c63184632046054ae709964befc943ecffa140adc697ca955a10002a79c08"
] ]
} }
platforms = [ platforms = [

View File

@@ -19,15 +19,6 @@
"\\/\\/\\s*renovate:\\s*datasource=(?<datasource>.*?)\\s+(versioning=(?<versioning>.*?))?\\s+depName=(?<depName>.*?)\\s*\\n\\s*[A-Za-z0-9_-]+\\s*=\\s*\"(?<currentValue>[^\"]+)\"" "\\/\\/\\s*renovate:\\s*datasource=(?<datasource>.*?)\\s+(versioning=(?<versioning>.*?))?\\s+depName=(?<depName>.*?)\\s*\\n\\s*[A-Za-z0-9_-]+\\s*=\\s*\"(?<currentValue>[^\"]+)\""
], ],
"versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver{{/if}}" "versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver{{/if}}"
},
{
"customType": "regex",
"managerFilePatterns": [
"/\\.ya?ml$/"
],
"matchStrings": [
"# renovate: datasource=(?<datasource>[a-z-.]+?) depName=(?<depName>[^\\s]+?)(?: (?:lookupName|packageName)=(?<packageName>[^\\s]+?))?(?: versioning=(?<versioning>[^\\s]+?))?(?: extractVersion=(?<extractVersion>[^\\s]+?))?\\s+[A-Za-z0-9_]+?_VERSION\\s*:\\s*[\"']?(?<currentValue>.+?)[\"']?\\s"
]
} }
], ],
"packageRules": [ "packageRules": [