From 59ca3c87373fafa1e596b63604b1801a17e4ab38 Mon Sep 17 00:00:00 2001 From: "v.oleynikov" Date: Wed, 13 May 2026 11:30:53 +0300 Subject: [PATCH 1/2] feat: add check_previous_channel_release composite action Promotes the per-repository check_previous_channel_release.sh script into a reusable composite action so module repositories don't have to ship and maintain their own copy. The version parser now handles both single-line (`{"version":"v0.1.14"}`) and pretty-printed multi-line `version.json` produced by yq (newlines and indentation around the keys), using a multiline-aware PCRE grep. --- README.md | 1 + check_previous_channel_release/action.yml | 93 +++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 check_previous_channel_release/action.yml diff --git a/README.md b/README.md index a2469df..8546092 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ This repository contains GitHub Actions workflows for building and deploying mod | [**setup**](./setup/action.yml) | Sets up the environment for building and deploying modules. This workflow **must** be run before any other workflows. | | [**build**](./build/action.yml) | Builds the Deckhouse modules using the [werf](https://werf.io/) tool. | | [**deploy**](./deploy/action.yml) | Deploys the Deckhouse modules to the one of selected release channels. | +| [**check_previous_channel_release**](./check_previous_channel_release/action.yml) | Checks that the previous release channel exposes the same module version before deploying to the next channel. | | [**cve_scan**](./cve_scan/action.yml) | Trivy CVE Scan of module images. Documentation can be found [here](./.docs/cve_scan.md) | | [**svace_analyze**](./svace_analyze/action.yml) | Include svace analyze action to analyze and import builds made with svace tool | | [**translate-changelog**](./translate-changelog/action.yml) | Translates Russian changelog files to English and creates a PR | diff --git a/check_previous_channel_release/action.yml b/check_previous_channel_release/action.yml new file mode 100644 index 0000000..df2577d --- /dev/null +++ b/check_previous_channel_release/action.yml @@ -0,0 +1,93 @@ +name: 'Check previous channel release' +description: 'Check that the previous release channel exposes the same module version as the one being deployed' +inputs: + module_source: + description: 'Registry repository address for the module, e.g., registry.example.com/deckhouse/ce/modules' + required: true + module_name: + description: 'Name of the module, e.g., my-module' + required: true + module_tag: + description: 'The version of the module to deploy to release channel, e.g., v1.21.1' + required: true + release_channel: + description: 'Name of the release channel. Must be one of alpha, beta, early-access, stable, rock-solid' + required: true + registry: + description: 'Registry URL used to read the previous release channel image' + required: true + registry_login: + description: 'Registry login used to read the previous release channel image (read-only is enough)' + required: true + registry_password: + description: 'Registry password used to read the previous release channel image (read-only is enough)' + required: true + +runs: + using: "composite" + steps: + - name: Check previous channel release for ${{ inputs.module_name }} + shell: bash + env: + MODULE_SOURCE: ${{ inputs.module_source }} + MODULE_NAME: ${{ inputs.module_name }} + MODULE_TAG: ${{ inputs.module_tag }} + RELEASE_CHANNEL: ${{ inputs.release_channel }} + REGISTRY: ${{ inputs.registry }} + REGISTRY_LOGIN: ${{ inputs.registry_login }} + REGISTRY_PASSWORD: ${{ inputs.registry_password }} + run: | + set -euo pipefail + + echo "Module ${MODULE_NAME}, source ${MODULE_SOURCE}, channel ${RELEASE_CHANNEL}, version ${MODULE_TAG}" + + case "${RELEASE_CHANNEL}" in + alpha) + echo "Deploying ${MODULE_TAG} to alpha channel, skipping previous channel check" + exit 0 + ;; + beta) + previous_channel="alpha" + ;; + early-access) + previous_channel="beta" + ;; + stable) + previous_channel="early-access" + ;; + rock-solid) + previous_channel="stable" + ;; + *) + echo "Unknown channel: ${RELEASE_CHANNEL}" + exit 1 + ;; + esac + + echo "Checking previous channel ${previous_channel}" + crane auth login -u "${REGISTRY_LOGIN}" -p "${REGISTRY_PASSWORD}" "${REGISTRY}" + + # version.json inside the release image can be either single-line + # ({"version":"v0.1.14"}) or pretty-printed across multiple lines + # ({\n "version": "v0.1.0"\n}). Use a multiline-aware PCRE grep + # (-P -z) so both layouts are matched. + previous_channel_version=$( + crane export "${MODULE_SOURCE}/${MODULE_NAME}/release:${previous_channel}" - \ + | grep -aoPz '\{\s*"version"\s*:\s*"[^"]+"\s*\}' \ + | head -z -n 1 \ + | tr -d '\0' \ + | jq -r .version + ) + + if [[ -z "${previous_channel_version}" || "${previous_channel_version}" == "null" ]]; then + echo "Failed to read version from previous channel ${previous_channel}" + exit 1 + fi + + if [[ "${MODULE_TAG}" == "${previous_channel_version}" ]]; then + echo "Previous channel ${previous_channel} version ${previous_channel_version} is equal to desired version ${MODULE_TAG}, processing" + exit 0 + else + echo "Previous channel ${previous_channel} version ${previous_channel_version} is not equal to desired version ${MODULE_TAG}, rejecting" + exit 1 + fi From 494d115a118f9c1b8ffffcd5e0ef26e645b0ca7a Mon Sep 17 00:00:00 2001 From: "v.oleynikov" Date: Wed, 13 May 2026 13:17:14 +0300 Subject: [PATCH 2/2] feat(check_previous_channel_release): swap module_source domain with registry input The previous-channel image often lives on a read-only mirror that has a different domain than the registry used to push releases. Swap the domain portion of `module_source` with the `registry` input before calling `crane export`, so callers can pass `vars.PROD_REGISTRY_READ` while keeping `module_source` built from `vars.PROD_REGISTRY`. --- check_previous_channel_release/action.yml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/check_previous_channel_release/action.yml b/check_previous_channel_release/action.yml index df2577d..9a2a5b8 100644 --- a/check_previous_channel_release/action.yml +++ b/check_previous_channel_release/action.yml @@ -14,7 +14,12 @@ inputs: description: 'Name of the release channel. Must be one of alpha, beta, early-access, stable, rock-solid' required: true registry: - description: 'Registry URL used to read the previous release channel image' + description: | + Registry URL used to read the previous release channel image. The domain + portion of `module_source` is replaced with this value before pulling, so + reads can go through a different registry than the one used for pushing + (e.g. pass `vars.PROD_REGISTRY_READ` while `module_source` is built from + `vars.PROD_REGISTRY`). required: true registry_login: description: 'Registry login used to read the previous release channel image (read-only is enough)' @@ -67,12 +72,18 @@ runs: echo "Checking previous channel ${previous_channel}" crane auth login -u "${REGISTRY_LOGIN}" -p "${REGISTRY_PASSWORD}" "${REGISTRY}" + # Swap the domain portion of module_source with the read registry, so + # the previous-channel image is pulled from `${REGISTRY}` rather than + # the (possibly write-only) registry baked into `module_source`. + read_module_source="${REGISTRY}/${MODULE_SOURCE#*/}" + echo "Reading previous channel image from ${read_module_source}/${MODULE_NAME}/release:${previous_channel}" + # version.json inside the release image can be either single-line # ({"version":"v0.1.14"}) or pretty-printed across multiple lines # ({\n "version": "v0.1.0"\n}). Use a multiline-aware PCRE grep # (-P -z) so both layouts are matched. previous_channel_version=$( - crane export "${MODULE_SOURCE}/${MODULE_NAME}/release:${previous_channel}" - \ + crane export "${read_module_source}/${MODULE_NAME}/release:${previous_channel}" - \ | grep -aoPz '\{\s*"version"\s*:\s*"[^"]+"\s*\}' \ | head -z -n 1 \ | tr -d '\0' \