This is an automated email from the ASF dual-hosted git repository. sciabarracom pushed a commit to branch 0.9.0 in repository https://gitbox.apache.org/repos/asf/openserverless-runtimes.git
commit 0b3227e1bb66b5b8e51d26562beccbfdad8d0386 Author: Michele Sciabarra <[email protected]> AuthorDate: Sun Sep 6 23:17:33 2026 +0200 reworked runtimes.json generation --- .env.dist | 6 +- Taskfile.yml | 71 +----- {runtime/common => common}/common1.17.1/DISCLAIMER | 0 {runtime/common => common}/common1.17.1/Dockerfile | 0 {runtime/common => common}/common1.17.1/LICENSE | 0 {runtime/common => common}/common1.17.1/NOTICE | 0 {runtime/common => common}/common1.17.1/WARN | 0 {runtime/common => common}/common1.18.4/DISCLAIMER | 0 {runtime/common => common}/common1.18.4/Dockerfile | 0 {runtime/common => common}/common1.18.4/LICENSE | 0 {runtime/common => common}/common1.18.4/NOTICE | 0 {runtime/common => common}/common1.18.4/WARN | 0 {runtime => experimental}/php/v8.2/CHANGELOG.md | 0 {runtime => experimental}/php/v8.2/DISCLAIMER | 0 {runtime => experimental}/php/v8.2/Dockerfile | 0 {runtime => experimental}/php/v8.2/LICENSE | 0 {runtime => experimental}/php/v8.2/NOTICE | 0 {runtime => experimental}/php/v8.2/WARN | 0 {runtime => experimental}/php/v8.2/build.gradle | 0 {runtime => experimental}/php/v8.2/compile.php | 0 {runtime => experimental}/php/v8.2/composer.json | 0 {runtime => experimental}/php/v8.2/php.ini | 0 {runtime => experimental}/php/v8.2/runner.php | 0 {runtime => experimental}/php/v8.3/CHANGELOG.md | 0 {runtime => experimental}/php/v8.3/DISCLAIMER | 0 {runtime => experimental}/php/v8.3/Dockerfile | 0 {runtime => experimental}/php/v8.3/LICENSE | 0 {runtime => experimental}/php/v8.3/NOTICE | 0 {runtime => experimental}/php/v8.3/WARN | 0 {runtime => experimental}/php/v8.3/compile.php | 0 {runtime => experimental}/php/v8.3/composer.json | 0 {runtime => experimental}/php/v8.3/php.ini | 0 {runtime => experimental}/php/v8.3/runner.php | 0 .../python/v3.11cuda/Dockerfile | 0 .../python/v3.11cuda/bin/compile | 0 .../python/v3.11cuda/debug.sh | 0 .../python/v3.11cuda/lib/launcher.py | 0 .../python/v3.11cuda/platforms.txt | 0 .../python/v3.11cuda/requirements.txt | 0 runtime/go/v1.26/merge.json | 3 + runtime/java/v8/merge.json | 3 + runtime/nodejs/v22/merge.json | 16 ++ runtime/python/v3.12/merge.json | 16 ++ runtimes.json.tpl | 252 --------------------- runtimes.py | 175 ++++++++++++++ 45 files changed, 218 insertions(+), 324 deletions(-) diff --git a/.env.dist b/.env.dist index 85bf60e..26f0f89 100644 --- a/.env.dist +++ b/.env.dist @@ -1,3 +1,3 @@ -DOCKER_HUB_USER=docker hub user -DOCKER_HUB_TOKEN=docker hub token -DOCKER_HUB_REGISTRY=docker hub registry +DOCKERHUB_USER=docker hub user +DOCKERHUB_TOKEN=docker hub token +DOCKERHUB_REGISTRY=docker hub registry diff --git a/Taskfile.yml b/Taskfile.yml index 3d2f171..e65a57a 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -233,76 +233,9 @@ tasks: cmds: - python3 packages/invoke.py run '{{.J}}' - render-runtime: - requires: { vars: [RT, VER] } - dir: "runtime/{{.RT}}/{{.VER}}" - cmds: - - | - RUNTIME="{{.BASEIMG}}/openserverless-runtime-{{.RT}}:{{.VER}}-{{.TAG}}" - ENVVER=$(echo "{{.VER}}" | tr '.' '_' | tr '[:upper:][:lower:]' '[:lower:][:upper:]') - ENVRT=$(echo "{{.RT}}" | tr '[a-zA-Z]' '[A-Za-z]') - if test -n "{{.PUSH}}" - then - {{.DRY}} echo "OPS_RUNTIME_TAG_${ENVRT}_${ENVVER}={{.VER}}-{{.TAG}}" >> {{.BASE_DIR}}/runtimes.env - else {{.DRY}} echo "OPS_RUNTIME_TAG_${ENVRT}_${ENVVER}={{.VER}}-{{.TAG}}" - fi - echo "Rendered $RUNTIME" - - render-lang: - desc: render images for one runtime - requires: { vars: [RT, BASE_DIR] } - vars: - DIRS: - sh: ls -d runtime/{{.RT}}/v* || echo "" - cmds: - - for: { var: DIRS } - task: render-runtime - vars: - VER: "{{base .ITEM}}" - BASE_DIR: "{{.BASE_DIR}}" - - render: - silent: true - requires: { vars: [TAG, RUNTIMES] } - vars: - RT_REGEX: - sh: echo "{{.RUNTIMES}}" | tr ',' '|' - SPECIFIC_RT: - sh: echo "{{.TAG}}" | grep -E -o '({{.RT_REGEX}})' || echo '' - BASE_DIR: - sh: pwd - cmds: - - | - rm -f runtimes.env - T="{{.TAG}}" - TS="${T#*_}" - RT="${T%%_*}" - echo "OPS_RUNTIME_PREFIX={{.REPO_PATH}}" >> runtimes.env - echo "==> RENDERING RUNTIMES {{.RUNTIMES}}" - for ITEM in `echo {{.RUNTIMES}} | tr ',' ' '`; do - echo "==> RENDERING $ITEM:$TS" - task render-lang TAG=$TS RT=$ITEM DRY={{.DRY}} BASE_DIR="{{.BASE_DIR}}" - done - - generate-runtimes: - silent: true - dotenv: - - runtimes.env - cmds: - - cat runtimes.json.tpl | envsubst > runtimes.json - # envsubst silently expands unset vars to "", so catch template/runtime drift here - - | - if grep -q '"tag": ""' runtimes.json - then - echo "ERROR: unresolved image tags in runtimes.json (runtimes.json.tpl is out of sync with runtimes.env):" >&2 - grep -n -B12 -A2 '"tag": ""' runtimes.json | grep -E '"(kind|name)"' >&2 - exit 1 - fi - render-runtimes: silent: true desc: generate a runtimes.json file with all the runtime corresponding to the current TAG cmds: - - | - task render PUSH=y - task generate-runtimes + - echo "creating runtimes.json" + - uv run runtimes.py {{.TAG}} >runtimes.json diff --git a/runtime/common/common1.17.1/DISCLAIMER b/common/common1.17.1/DISCLAIMER similarity index 100% rename from runtime/common/common1.17.1/DISCLAIMER rename to common/common1.17.1/DISCLAIMER diff --git a/runtime/common/common1.17.1/Dockerfile b/common/common1.17.1/Dockerfile similarity index 100% rename from runtime/common/common1.17.1/Dockerfile rename to common/common1.17.1/Dockerfile diff --git a/runtime/common/common1.17.1/LICENSE b/common/common1.17.1/LICENSE similarity index 100% rename from runtime/common/common1.17.1/LICENSE rename to common/common1.17.1/LICENSE diff --git a/runtime/common/common1.17.1/NOTICE b/common/common1.17.1/NOTICE similarity index 100% rename from runtime/common/common1.17.1/NOTICE rename to common/common1.17.1/NOTICE diff --git a/runtime/common/common1.17.1/WARN b/common/common1.17.1/WARN similarity index 100% rename from runtime/common/common1.17.1/WARN rename to common/common1.17.1/WARN diff --git a/runtime/common/common1.18.4/DISCLAIMER b/common/common1.18.4/DISCLAIMER similarity index 100% rename from runtime/common/common1.18.4/DISCLAIMER rename to common/common1.18.4/DISCLAIMER diff --git a/runtime/common/common1.18.4/Dockerfile b/common/common1.18.4/Dockerfile similarity index 100% rename from runtime/common/common1.18.4/Dockerfile rename to common/common1.18.4/Dockerfile diff --git a/runtime/common/common1.18.4/LICENSE b/common/common1.18.4/LICENSE similarity index 100% rename from runtime/common/common1.18.4/LICENSE rename to common/common1.18.4/LICENSE diff --git a/runtime/common/common1.18.4/NOTICE b/common/common1.18.4/NOTICE similarity index 100% rename from runtime/common/common1.18.4/NOTICE rename to common/common1.18.4/NOTICE diff --git a/runtime/common/common1.18.4/WARN b/common/common1.18.4/WARN similarity index 100% rename from runtime/common/common1.18.4/WARN rename to common/common1.18.4/WARN diff --git a/runtime/php/v8.2/CHANGELOG.md b/experimental/php/v8.2/CHANGELOG.md similarity index 100% rename from runtime/php/v8.2/CHANGELOG.md rename to experimental/php/v8.2/CHANGELOG.md diff --git a/runtime/php/v8.2/DISCLAIMER b/experimental/php/v8.2/DISCLAIMER similarity index 100% rename from runtime/php/v8.2/DISCLAIMER rename to experimental/php/v8.2/DISCLAIMER diff --git a/runtime/php/v8.2/Dockerfile b/experimental/php/v8.2/Dockerfile similarity index 100% rename from runtime/php/v8.2/Dockerfile rename to experimental/php/v8.2/Dockerfile diff --git a/runtime/php/v8.2/LICENSE b/experimental/php/v8.2/LICENSE similarity index 100% rename from runtime/php/v8.2/LICENSE rename to experimental/php/v8.2/LICENSE diff --git a/runtime/php/v8.2/NOTICE b/experimental/php/v8.2/NOTICE similarity index 100% rename from runtime/php/v8.2/NOTICE rename to experimental/php/v8.2/NOTICE diff --git a/runtime/php/v8.2/WARN b/experimental/php/v8.2/WARN similarity index 100% rename from runtime/php/v8.2/WARN rename to experimental/php/v8.2/WARN diff --git a/runtime/php/v8.2/build.gradle b/experimental/php/v8.2/build.gradle similarity index 100% rename from runtime/php/v8.2/build.gradle rename to experimental/php/v8.2/build.gradle diff --git a/runtime/php/v8.2/compile.php b/experimental/php/v8.2/compile.php similarity index 100% rename from runtime/php/v8.2/compile.php rename to experimental/php/v8.2/compile.php diff --git a/runtime/php/v8.2/composer.json b/experimental/php/v8.2/composer.json similarity index 100% rename from runtime/php/v8.2/composer.json rename to experimental/php/v8.2/composer.json diff --git a/runtime/php/v8.2/php.ini b/experimental/php/v8.2/php.ini similarity index 100% rename from runtime/php/v8.2/php.ini rename to experimental/php/v8.2/php.ini diff --git a/runtime/php/v8.2/runner.php b/experimental/php/v8.2/runner.php similarity index 100% rename from runtime/php/v8.2/runner.php rename to experimental/php/v8.2/runner.php diff --git a/runtime/php/v8.3/CHANGELOG.md b/experimental/php/v8.3/CHANGELOG.md similarity index 100% rename from runtime/php/v8.3/CHANGELOG.md rename to experimental/php/v8.3/CHANGELOG.md diff --git a/runtime/php/v8.3/DISCLAIMER b/experimental/php/v8.3/DISCLAIMER similarity index 100% rename from runtime/php/v8.3/DISCLAIMER rename to experimental/php/v8.3/DISCLAIMER diff --git a/runtime/php/v8.3/Dockerfile b/experimental/php/v8.3/Dockerfile similarity index 100% rename from runtime/php/v8.3/Dockerfile rename to experimental/php/v8.3/Dockerfile diff --git a/runtime/php/v8.3/LICENSE b/experimental/php/v8.3/LICENSE similarity index 100% rename from runtime/php/v8.3/LICENSE rename to experimental/php/v8.3/LICENSE diff --git a/runtime/php/v8.3/NOTICE b/experimental/php/v8.3/NOTICE similarity index 100% rename from runtime/php/v8.3/NOTICE rename to experimental/php/v8.3/NOTICE diff --git a/runtime/php/v8.3/WARN b/experimental/php/v8.3/WARN similarity index 100% rename from runtime/php/v8.3/WARN rename to experimental/php/v8.3/WARN diff --git a/runtime/php/v8.3/compile.php b/experimental/php/v8.3/compile.php similarity index 100% rename from runtime/php/v8.3/compile.php rename to experimental/php/v8.3/compile.php diff --git a/runtime/php/v8.3/composer.json b/experimental/php/v8.3/composer.json similarity index 100% rename from runtime/php/v8.3/composer.json rename to experimental/php/v8.3/composer.json diff --git a/runtime/php/v8.3/php.ini b/experimental/php/v8.3/php.ini similarity index 100% rename from runtime/php/v8.3/php.ini rename to experimental/php/v8.3/php.ini diff --git a/runtime/php/v8.3/runner.php b/experimental/php/v8.3/runner.php similarity index 100% rename from runtime/php/v8.3/runner.php rename to experimental/php/v8.3/runner.php diff --git a/runtime/experimental/python/v3.11cuda/Dockerfile b/experimental/python/v3.11cuda/Dockerfile similarity index 100% rename from runtime/experimental/python/v3.11cuda/Dockerfile rename to experimental/python/v3.11cuda/Dockerfile diff --git a/runtime/experimental/python/v3.11cuda/bin/compile b/experimental/python/v3.11cuda/bin/compile similarity index 100% rename from runtime/experimental/python/v3.11cuda/bin/compile rename to experimental/python/v3.11cuda/bin/compile diff --git a/runtime/experimental/python/v3.11cuda/debug.sh b/experimental/python/v3.11cuda/debug.sh similarity index 100% rename from runtime/experimental/python/v3.11cuda/debug.sh rename to experimental/python/v3.11cuda/debug.sh diff --git a/runtime/experimental/python/v3.11cuda/lib/launcher.py b/experimental/python/v3.11cuda/lib/launcher.py similarity index 100% rename from runtime/experimental/python/v3.11cuda/lib/launcher.py rename to experimental/python/v3.11cuda/lib/launcher.py diff --git a/runtime/experimental/python/v3.11cuda/platforms.txt b/experimental/python/v3.11cuda/platforms.txt similarity index 100% rename from runtime/experimental/python/v3.11cuda/platforms.txt rename to experimental/python/v3.11cuda/platforms.txt diff --git a/runtime/experimental/python/v3.11cuda/requirements.txt b/experimental/python/v3.11cuda/requirements.txt similarity index 100% rename from runtime/experimental/python/v3.11cuda/requirements.txt rename to experimental/python/v3.11cuda/requirements.txt diff --git a/runtime/go/v1.26/merge.json b/runtime/go/v1.26/merge.json new file mode 100644 index 0000000..077a621 --- /dev/null +++ b/runtime/go/v1.26/merge.json @@ -0,0 +1,3 @@ +{ + "default": true +} \ No newline at end of file diff --git a/runtime/java/v8/merge.json b/runtime/java/v8/merge.json new file mode 100644 index 0000000..077a621 --- /dev/null +++ b/runtime/java/v8/merge.json @@ -0,0 +1,3 @@ +{ + "default": true +} \ No newline at end of file diff --git a/runtime/nodejs/v22/merge.json b/runtime/nodejs/v22/merge.json new file mode 100644 index 0000000..e2d5da4 --- /dev/null +++ b/runtime/nodejs/v22/merge.json @@ -0,0 +1,16 @@ +{ +"default": true, +"stemCells": [ + { + "initialCount": 1, + "memory": "256 MB", + "reactive": { + "minCount": 1, + "maxCount": 4, + "ttl": "2 minutes", + "threshold": 1, + "increment": 1 + } + } +] +} \ No newline at end of file diff --git a/runtime/python/v3.12/merge.json b/runtime/python/v3.12/merge.json new file mode 100644 index 0000000..e2d5da4 --- /dev/null +++ b/runtime/python/v3.12/merge.json @@ -0,0 +1,16 @@ +{ +"default": true, +"stemCells": [ + { + "initialCount": 1, + "memory": "256 MB", + "reactive": { + "minCount": 1, + "maxCount": 4, + "ttl": "2 minutes", + "threshold": 1, + "increment": 1 + } + } +] +} \ No newline at end of file diff --git a/runtimes.json.tpl b/runtimes.json.tpl deleted file mode 100644 index f05e22d..0000000 --- a/runtimes.json.tpl +++ /dev/null @@ -1,252 +0,0 @@ -{ - "description": [ - "This file describes the different languages (aka. managed action runtimes) supported by the system", - "as well as blackbox images that support the runtime specification.", - "Only actions with runtime families / kinds defined here can be created / read / updated / deleted / invoked.", - "Define a list of runtime families (example: 'nodejs') with at least one kind per family (example: 'nodejs:14').", - "Each runtime family needs a default kind (default: true).", - "When removing or renaming runtime families or runtime kinds from this file, preexisting actions", - "with the affected kinds can no longer be read / updated / deleted / invoked. In order to remove or rename", - "runtime families or runtime kinds, mark all affected runtime kinds as deprecated (deprecated: true) and", - "perform a manual migration of all affected actions.", - "", - "This file is meant to list all stable runtimes supported by the Apache Openwhisk community." - ], - "runtimes": { - "nodejs": [ - { - "kind": "nodejs:24", - "default": true, - "image": { - "prefix": "$OPS_RUNTIME_PREFIX", - "name": "openserverless-runtime-nodejs", - "tag": "$OPS_RUNTIME_TAG_NODEJS_V24" - }, - "deprecated": false, - "attached": { - "attachmentName": "codefile", - "attachmentType": "text/plain" - }, - "stemCells": [ - { - "initialCount": 1, - "memory": "256 MB", - "reactive": { - "minCount": 1, - "maxCount": 4, - "ttl": "2 minutes", - "threshold": 1, - "increment": 1 - } - } - ] - }, - { - "kind": "nodejs:22", - "default": false, - "image": { - "prefix": "$OPS_RUNTIME_PREFIX", - "name": "openserverless-runtime-nodejs", - "tag": "$OPS_RUNTIME_TAG_NODEJS_V22" - }, - "deprecated": false, - "attached": { - "attachmentName": "codefile", - "attachmentType": "text/plain" - } - }, - { - "kind": "nodejs:20", - "default": false, - "image": { - "prefix": "$OPS_RUNTIME_PREFIX", - "name": "openserverless-runtime-nodejs", - "tag": "$OPS_RUNTIME_TAG_NODEJS_V20" - }, - "deprecated": false, - "attached": { - "attachmentName": "codefile", - "attachmentType": "text/plain" - } - } - ], - "python": [ - { - "kind": "python:3", - "default": true, - "image": { - "prefix": "$OPS_RUNTIME_PREFIX", - "name": "openserverless-runtime-python", - "tag": "$OPS_RUNTIME_TAG_PYTHON_V3_12" - }, - "deprecated": false, - "attached": { - "attachmentName": "codefile", - "attachmentType": "text/plain" - }, - "stemCells": [ - { - "initialCount": 1, - "memory": "256 MB", - "reactive": { - "minCount": 1, - "maxCount": 4, - "ttl": "2 minutes", - "threshold": 1, - "increment": 1 - } - } - ] - }, - { - "kind": "python:3.11", - "default": false, - "image": { - "prefix": "$OPS_RUNTIME_PREFIX", - "name": "openserverless-runtime-python", - "tag": "$OPS_RUNTIME_TAG_PYTHON_V3_11" - }, - "deprecated": false, - "attached": { - "attachmentName": "codefile", - "attachmentType": "text/plain" - } - }, - { - "kind": "python:3.12", - "default": false, - "image": { - "prefix": "$OPS_RUNTIME_PREFIX", - "name": "openserverless-runtime-python", - "tag": "$OPS_RUNTIME_TAG_PYTHON_V3_12" - }, - "deprecated": false, - "attached": { - "attachmentName": "codefile", - "attachmentType": "text/plain" - } - }, - { - "kind": "python:3.13", - "default": false, - "image": { - "prefix": "$OPS_RUNTIME_PREFIX", - "name": "openserverless-runtime-python", - "tag": "$OPS_RUNTIME_TAG_PYTHON_V3_13" - }, - "deprecated": false, - "attached": { - "attachmentName": "codefile", - "attachmentType": "text/plain" - } - } - ], - "go": [ - { - "kind": "go:1.27", - "default": true, - "deprecated": false, - "attached": { - "attachmentName": "codefile", - "attachmentType": "text/plain" - }, - "image": { - "prefix": "$OPS_RUNTIME_PREFIX", - "name": "openserverless-runtime-go", - "tag": "$OPS_RUNTIME_TAG_GO_V1_27" - } - }, - { - "kind": "go:1.26", - "default": false, - "deprecated": false, - "attached": { - "attachmentName": "codefile", - "attachmentType": "text/plain" - }, - "image": { - "prefix": "$OPS_RUNTIME_PREFIX", - "name": "openserverless-runtime-go", - "tag": "$OPS_RUNTIME_TAG_GO_V1_26" - } - }, - { - "kind": "go:1.25", - "default": false, - "deprecated": false, - "attached": { - "attachmentName": "codefile", - "attachmentType": "text/plain" - }, - "image": { - "prefix": "$OPS_RUNTIME_PREFIX", - "name": "openserverless-runtime-go", - "tag": "$OPS_RUNTIME_TAG_GO_V1_25" - } - } - ], - "java": [ - { - "kind": "java:8", - "default": true, - "image": { - "prefix": "$OPS_RUNTIME_PREFIX", - "name": "openserverless-runtime-java", - "tag": "$OPS_RUNTIME_TAG_JAVA_V8" - }, - "deprecated": false, - "attached": { - "attachmentName": "codefile", - "attachmentType": "text/plain" - }, - "requireMain": true - }, - { - "kind": "java:11", - "default": false, - "image": { - "prefix": "$OPS_RUNTIME_PREFIX", - "name": "openserverless-runtime-java", - "tag": "$OPS_RUNTIME_TAG_JAVA_V11" - }, - "deprecated": false, - "attached": { - "attachmentName": "codefile", - "attachmentType": "text/plain" - }, - "requireMain": true - }, - { - "kind": "java:17", - "default": false, - "image": { - "prefix": "$OPS_RUNTIME_PREFIX", - "name": "openserverless-runtime-java", - "tag": "$OPS_RUNTIME_TAG_JAVA_V17" - }, - "deprecated": false, - "attached": { - "attachmentName": "codefile", - "attachmentType": "text/plain" - }, - "requireMain": true - }, - { - "kind": "java:21", - "default": false, - "image": { - "prefix": "$OPS_RUNTIME_PREFIX", - "name": "openserverless-runtime-java", - "tag": "$OPS_RUNTIME_TAG_JAVA_V21" - }, - "deprecated": false, - "attached": { - "attachmentName": "codefile", - "attachmentType": "text/plain" - }, - "requireMain": true - } - ] - }, - "blackboxes": [ ] -} \ No newline at end of file diff --git a/runtimes.py b/runtimes.py new file mode 100755 index 0000000..00a1eec --- /dev/null +++ b/runtimes.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python3 +"""Generate runtimes.json by walking the runtime/ subtree. +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + Each runtime/<language>/<version> directory becomes one kind: the language + directory gives the kind family, the version subdir gives both the kind + version and the image tag, with -<tag> appended. A merge.json in a version + directory is merged into that entry, which is how defaults, stemCells and + requireMain are declared. + + Example: + ./runtime.py all_26i06r36-snapshot + ./runtime.py all_26i06r36-snapshot -o runtimes.json +""" + +import argparse +import json +import os +import sys + +DESCRIPTION = [ + "This file describes the different languages (aka. managed action runtimes) supported by the system", + "as well as blackbox images that support the runtime specification.", + "Only actions with runtime families / kinds defined here can be created / read / updated / deleted / invoked.", + "Define a list of runtime families (example: 'nodejs') with at least one kind per family (example: 'nodejs:14').", + "Each runtime family needs a default kind (default: true).", + "When removing or renaming runtime families or runtime kinds from this file, preexisting actions", + "with the affected kinds can no longer be read / updated / deleted / invoked. In order to remove or rename", + "runtime families or runtime kinds, mark all affected runtime kinds as deprecated (deprecated: true) and", + "perform a manual migration of all affected actions.", + "", + "This file is meant to list all stable runtimes supported by the Apache Openwhisk community.", +] + +ATTACHED = {"attachmentName": "codefile", "attachmentType": "text/plain"} + + +def read_env(path): + """Parse a dotenv file into a dict; missing file yields an empty environment.""" + env = {} + if not os.path.isfile(path): + return env + with open(path) as f: + for line in f: + line = line.strip() + if not line or line.startswith("#") or "=" not in line: + continue + key, value = line.split("=", 1) + env[key.strip()] = value.strip().strip('"').strip("'") + return env + + +def strip_prefix(tag): + """Drop the leading `xxx_` build selector, e.g. all_26i06r36-snapshot -> 26i06r36-snapshot.""" + return tag.split("_", 1)[1] if "_" in tag else tag + + +def version_key(version): + """Sort v3.11/v1.27/v8 numerically, newest first, so ordering is stable.""" + return [int(p) if p.isdigit() else p for p in version.lstrip("v").split(".")] + + +def kind_entry(language, version, tag, prefix): + """Build one kind from a runtime/<language>/<version> directory.""" + entry = { + "kind": "%s:%s" % (language, version.lstrip("v")), + "default": False, + "image": { + "prefix": prefix, + "name": "openserverless-runtime-%s" % language, + "tag": "%s-%s" % (version, tag), + }, + "deprecated": False, + "attached": dict(ATTACHED), + } + return entry + + +def walk(runtime_dir, tag, prefix): + """Walk runtime/<language>/<version>, yielding (language, [kinds]).""" + for language in sorted(os.listdir(runtime_dir)): + lang_dir = os.path.join(runtime_dir, language) + if not os.path.isdir(lang_dir): + continue + + versions = sorted( + ( + d + for d in os.listdir(lang_dir) + if d.startswith("v") and os.path.isdir(os.path.join(lang_dir, d)) + ), + key=version_key, + reverse=True, + ) + if not versions: + continue + + kinds = [] + for version in versions: + entry = kind_entry(language, version, tag, prefix) + merge_file = os.path.join(lang_dir, version, "merge.json") + if os.path.isfile(merge_file): + with open(merge_file) as f: + try: + entry.update(json.load(f)) + except ValueError as err: + sys.exit("ERROR: cannot parse %s: %s" % (merge_file, err)) + kinds.append(entry) + yield language, kinds + + +def build(runtime_dir, tag, prefix): + runtimes = {} + for language, kinds in walk(runtime_dir, tag, prefix): + runtimes[language] = kinds + return {"description": DESCRIPTION, "runtimes": runtimes, "blackboxes": []} + + +def main(): + here = os.path.dirname(os.path.abspath(__file__)) + parser = argparse.ArgumentParser( + description="generate runtimes.json by walking the runtime/ subtree" + ) + parser.add_argument( + "tag", help="build tag, e.g. all_26i06r36-snapshot (the xxx_ prefix is removed)" + ) + parser.add_argument( + "--env", + default=os.path.join(here, ".env"), + help="dotenv file providing DOCKER_HUB_REGISTRY and DOCKERHUB_USER", + ) + parser.add_argument( + "--runtime-dir", + default=os.path.join(here, "runtime"), + help="path to the runtime/ tree (default: alongside this script)", + ) + parser.add_argument("-o", "--output", help="write to this file instead of stdout") + args = parser.parse_args() + + # .env provides the defaults; a real environment variable still wins. + env = read_env(args.env) + registry = os.environ.get( + "DOCKER_HUB_REGISTRY", env.get("DOCKER_HUB_REGISTRY", "docker.io") + ) + user = os.environ.get("DOCKERHUB_USER", env.get("DOCKERHUB_USER", "apache")) + prefix = "%s/%s" % (registry, user) + + result = build(args.runtime_dir, strip_prefix(args.tag), prefix) + text = json.dumps(result, indent=4) + "\n" + + if args.output: + with open(args.output, "w") as f: + f.write(text) + print("Generated %s" % args.output, file=sys.stderr) + else: + sys.stdout.write(text) + + +if __name__ == "__main__": + main()
