You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openserverless.apache.org by ms...@apache.org on 2026/09/07 14:38:58 UTC
(openserverless-runtimes) 23/28: reworked runtimes.json generation
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 <mi...@sciabarra.com>
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()