diff --git a/actions/helm-charts-release/README.md b/actions/charts-values-update-action/README.md similarity index 91% rename from actions/helm-charts-release/README.md rename to actions/charts-values-update-action/README.md index 2263fc5e..7182cc31 100644 --- a/actions/helm-charts-release/README.md +++ b/actions/charts-values-update-action/README.md @@ -32,9 +32,9 @@ Can be `replace` or `parse`. Defaults to `parse`. If set to `replace` the action will just replace the versions of docker images with `release-version` value. If set to `parse` the action read provided `config-file` and substitute any environment variables provided in the version part. For example if you have some 3-rd party image in `values.yaml` file and want to manage it's version, you can add repository level variable and use it in the config file: `some-thirg-party-image:${THIRD_PARTY_VERSION}`. -Also if you want the action to find the latest version of some image (supplimentary service for instance), you can set it to something like `#4.*.*` or `#latest`. -In that case the action will find the latest tag of an image which satisfy the regular expression. The regular expression of a tag must start with `#` symbol and follow the `jq` syntax. -**Special word `#latest` will result the latest SemVer tag of the image, not the one which marked with `latest` tag.** +Also if you want the action to find the latest version of some image (supplimentary service for instance), you can set it to something like `#4\.\d+\.\d+` or `#latest`. +In that case the action will find the latest tag of an image which satisfy the regular expression. The regular expression of a tag must start with `#` symbol and follow the Python `re` syntax. +**Special word `#latest` will result the latest SemVer tag of the image ('2.1.0','v4.3.2', etc.), not the one which marked with `latest` tag.** ### `working-directory` @@ -82,7 +82,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Release Helm Charts - uses: netcracker/qubership-workflow-hub/actions/helm-charts-release@main + uses: netcracker/qubership-workflow-hub/actions/charts-values-update-action@main with: release-version: '1.0.0' chart-version: '1.0.0' @@ -113,4 +113,4 @@ jobs: - `version`: Template for the image version (e.g., `my-image:${release}`). - `image`: List of image keys to update in `values.yaml`. -> Example: [helm-charts-release-config.yaml](./helm-charts-release-config.yaml). +> Example: [charts-values-update-config.yaml](./charts-values-update-config.yaml). diff --git a/actions/helm-charts-release/action.yaml b/actions/charts-values-update-action/action.yaml similarity index 100% rename from actions/helm-charts-release/action.yaml rename to actions/charts-values-update-action/action.yaml diff --git a/actions/helm-charts-release/helm-charts-release-config.yaml b/actions/charts-values-update-action/charts-values-update-config.yaml similarity index 86% rename from actions/helm-charts-release/helm-charts-release-config.yaml rename to actions/charts-values-update-action/charts-values-update-config.yaml index 1fd091f5..6146456f 100644 --- a/actions/helm-charts-release/helm-charts-release-config.yaml +++ b/actions/charts-values-update-action/charts-values-update-config.yaml @@ -12,5 +12,5 @@ charts: image: - ghcr.io/netcracker/module1:${release} # This will replace the image version with the release version - ghcr.io/netcracker/module1-service1:${release}-${THIRD_PARTY_VERSION} # This will replace the image version with the release version and append the THIRD_PARTY_VERSION variable - - ghcr.io/netcracker/module1-service2:#5.*.* # This will select the latest tag matching the jq regular expression + - ghcr.io/netcracker/module1-service2:#5\.\d+\.\d+ # This will select the latest tag matching the jq regular expression - ghcr.io/netcracker/module1-service2:#latest # This will select the latest SemVer tag diff --git a/actions/helm-charts-release/image-versions-replace.py b/actions/charts-values-update-action/image-versions-replace.py similarity index 66% rename from actions/helm-charts-release/image-versions-replace.py rename to actions/charts-values-update-action/image-versions-replace.py index 64ea7827..934e35af 100644 --- a/actions/helm-charts-release/image-versions-replace.py +++ b/actions/charts-values-update-action/image-versions-replace.py @@ -3,8 +3,10 @@ import argparse import json import os +from packaging import version import re import subprocess +import sys import yaml def replace_env_variables(input_string): @@ -18,15 +20,64 @@ def replacer(match): return pattern.sub(replacer, input_string) +def get_latest_stable_version(versions): + stable_versions = [] + + for v in versions: + try: + ver = version.parse(v) + # Check that version is stable + if not ver.is_prerelease: + stable_versions.append((v, ver)) + except version.InvalidVersion: + continue + + if not stable_versions: + return None + + latest = sorted(stable_versions, key=lambda x: x[1])[-1][0] + return latest + +def get_latest_version_by_regex(versions, pattern_str): + try: + print(f"Using regex pattern: {pattern_str}") + pattern = r'' + pattern_str + compiled_pattern = re.compile(pattern) + except re.error as e: + print(f"Invalid regular expression '{pattern}': {str(e)}") + sys.exit(1) + #raise ValueError(f"Incorrect regular expression: {str(e)}") from None + + matched_versions = [] + + for v in versions: + try: + if compiled_pattern.fullmatch(v): + ver = version.parse(v) + if not ver.is_prerelease: + matched_versions.append((v, ver)) + except version.InvalidVersion: + continue + + if not matched_versions: + return None + + return sorted(matched_versions, key=lambda x: x[1])[-1][0] + def replace_tag_regexp(image_str, tag_re): # Try to find the requested tag for given image_str if tag_re.startswith("#"): try: os.system(f"skopeo login -u $GITHUB_ACTOR -p $GITHUB_TOKEN ghcr.io") + tags = subprocess.run(f"skopeo list-tags docker://{image_str} | jq -r '.Tags[]'", shell=True, text=True, check=True, capture_output=True).stdout.split() if tag_re[1:] == 'latest': - result_tag = subprocess.run(f"skopeo list-tags docker://{image_str} | jq -r '.Tags[]' | grep -e \"^[0-9]*\.[0-9]*\.[0-9]*\" | sort -V | tail -n 1", shell=True, text=True, check=True, capture_output=True).stdout.rstrip() + result_tag = get_latest_stable_version(tags) else: - result_tag = subprocess.run(f"skopeo list-tags docker://{image_str} | jq -r '.Tags[] | select(test(\"^{tag_re[1:]}\"))' | sort -V | tail -n 1", shell=True, text=True, check=True, capture_output=True).stdout.rstrip() + result_tag = get_latest_version_by_regex(tags, tag_re[1:]) + if not result_tag: + print(f"No matching tag found for {image_str} with pattern {tag_re}") + #raise ValueError(f"No matching tag found for {image_str} with pattern {tag_re}") + sys.exit(1) return(result_tag) except Exception as e: print(f"Error: {e}")