This is an automated email from the ASF dual-hosted git repository.
d4rkstar pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/openserverless.git
The following commit(s) were added to refs/heads/main by this push:
new e506d3f Source release first preview (#202)
e506d3f is described below
commit e506d3fc4c5697d59e2aa44eb7daf4d3968d8ae7
Author: Michele Sciabarra <[email protected]>
AuthorDate: Mon Jul 6 14:24:31 2026 +0200
Source release first preview (#202)
* lima config
* taskfile
* java instructions
* Point build submodule to local openwhisk update
* Update build submodule for Nuvolaris openwhisk source
* Update devcontainer with OpenWhisk build tools
* Revert "Update devcontainer with OpenWhisk build tools"
This reverts commit b4f55bc5079a20e65ba2b431e80e8431c2998942.
* Update build submodule devcontainer toolchain
* Update build distdocker local workflow
* Update build distdocker container wrapper
* Update build-all local workflow
* Document and wire local kind build workflow
* Use task build as local workflow entrypoint
* build updated
* Document ops devcontainer build flow
* Vendor OpenWhisk in build workflow
* Track build submodule main branch
* Track build submodule build-local branch
* add openserverless
* Update build submodule for ARM protoc
* Update build submodule for buildx-all
* Update build submodule for buildx setup
* Update build submodule for local buildx registry
* taskfile
* sync refs
* build-and-test
* correct attributes
* remving site
* build-and-test
* avoid issue with snap
* fixes mac
* assume docker
* making executable mount
* mount writable
* sync
* sync
* build-and-test windows
* reorder task
* update
---------
Co-authored-by: Trustable User <[email protected]>
Co-authored-by: Michele Sciabarra <[email protected]>
Co-authored-by: Michele Sciabarra <[email protected]>
---
.gitattributes | 5 +
.gitmodules | 8 +-
README.md | 5 +-
Taskfile.yml | 78 ++++++--
admin-api | 2 +-
build | 1 +
build-and-test-mac.sh | 70 +++++++
build-and-test-ubuntu.sh | 83 ++++++++
build-and-test-windows.ps1 | 136 +++++++++++++
build-step.md | 356 +++++++++++++++++++++++++++++++++
cli | 2 +-
devcontainer | 2 +-
olaris | 2 +-
olaris-op | 2 +-
openserverless-cli.code-workspace | 21 --
openserverless-operator.code-workspace | 17 --
openserverless.code-workspace | 24 ---
runtimes | 2 +-
site | 1 -
streamer | 2 +-
testing | 2 +-
vscode | 2 +-
22 files changed, 727 insertions(+), 96 deletions(-)
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..f7b2686
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,5 @@
+* text=auto eol=lf
+*.sh text eol=lf
+*.ps1 text eol=crlf
+*.png binary
+*.jpg binary
diff --git a/.gitmodules b/.gitmodules
index b608813..956b4a2 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,7 +1,3 @@
-[submodule "site"]
- path = site
- url = https://github.com/apache/openserverless-site
- branch = main
[submodule "cli"]
path = cli
url = https://github.com/apache/openserverless-cli
@@ -38,3 +34,7 @@
path = admin-api
url = https://github.com/apache/openserverless-admin-api
branch = main
+[submodule "build"]
+ path = build
+ url = https://github.com/apache/openserverless-build
+ branch = build-local
diff --git a/README.md b/README.md
index 0a39f51..097e190 100644
--- a/README.md
+++ b/README.md
@@ -38,10 +38,13 @@ Access the distro (`wsl -d Ubuntu-24.04` ), configure a new
user, then execute:
```
sudo apt-get update
-sudo apt-get -y install jq
+sudo apt-get -y install jq unzip zip
sudo snap install go --classic
sudo snap install task --classic
sudo snap install kubectl --classic
+curl -s "https://get.sdkman.io" | bash
+source "/home/msciab/.sdkman/bin/sdkman-init.sh"
+sdk install java 17.0.19-tem
```
## Prepare Ubuntu Linux
diff --git a/Taskfile.yml b/Taskfile.yml
index c0be831..ae0f099 100644
--- a/Taskfile.yml
+++ b/Taskfile.yml
@@ -16,6 +16,11 @@ vars:
RUNTIMES_TAG: "{{.OPERATOR_TAG}}"
+ OPENSERVERLESS_TAG: "{{.OPERATOR_TAG}}"
+ CONTROLLER_SRC:
"docker.io/apache/openserverless-wsk-invoker:{{.OPENSERVERLESS_TAG}}"
+ INVOKER_SRC:
"docker.io/apache/openserverless-wsk-controller:{{.OPENSERVERLESS_TAG}}"
+
+ OPS_BRANCH: "{{.OPERATOR_TAG}}"
tasks:
@@ -50,6 +55,7 @@ tasks:
status:
- ! test -e ../ops
+
operator:
desc: build the operator
deps:
@@ -77,7 +83,6 @@ tasks:
vars:
SRC: "{{.STREAMER_SRC}}"
-
admin-api:
desc: build the admin-api
deps:
@@ -92,18 +97,25 @@ tasks:
vars:
SRC: "{{.ADMIN_API_SRC}}"
- opsroot:
- desc: build current opsroot.json
- dir: olaris
+ openserverless:
+ desc: build openserverless
+ dir: build
+ env:
+ PATH: "{{.TASKFILE_DIR}}:$PATH"
+ OPS_ROOT: "{{.TASKFILE_DIR}}"
cmds:
- - test -e opsroot.orig || jq . <opsroot.json >opsroot.orig
- - >
- jq <opsroot.orig >opsroot.json '
- .config.images.operator = "{{.OPERATOR_SRC}}" |
- .config.images.streamer = "{{.STREAMER_SRC}}" |
- .config.images.systemapi = "{{.ADMIN_API_SRC}}"
- '
- - diff opsroot.orig opsroot.json || true
+ - echo Building OpenServerless
+ - git tag -d $(git tag) && git tag {{.OPENSERVERLESS_TAG}}
+ - |
+ export PATH="{{.TASKFILE_DIR}}:$PATH"
+ export OPS_ROOT="{{.TASKFILE_DIR}}/olaris"
+ task build-all
+ - task: image-save
+ vars:
+ SRC: "{{.CONTROLLER_SRC}}"
+ - task: image-save
+ vars:
+ SRC: "{{.INVOKER_SRC}}"
runtimes:
desc: build current runtimes.json
@@ -121,7 +133,7 @@ tasks:
dir: runtimes
vars:
IMAGES:
- sh: jq -r '.runtimes[][] | select(.default == true) |
"\(.image.prefix)/\(.image.name):\(.image.tag)"' runtimes.json
+ sh: jq -r '.runtimes[][] | select(.default == true) |
"\(.image.prefix)/\(.image.name):\(.image.tag)"' runtimes.json | grep -v php
cmds:
- for: { var: IMAGES, split: "\n", as: IMG }
task: image-save
@@ -130,21 +142,49 @@ tasks:
TGT:
sh: echo ~/.ops/{{OS}}-{{ARCH}}/images/kind/$(echo
docker.io/{{.IMG}} | /usr/bin/base64 -w0)
+ opsroot:
+ desc: build current opsroot.json
+ dir: olaris
+ cmds:
+ - test -e opsroot.orig || jq . <opsroot.json >opsroot.orig
+ - >
+ jq <opsroot.orig >opsroot.json '
+ .config.images.operator = "{{.OPERATOR_SRC}}" |
+ .config.images.streamer = "{{.STREAMER_SRC}}" |
+ .config.images.systemapi = "{{.ADMIN_API_SRC}}" |
+ .config.images.controller = "{{.CONTROLLER_SRC}}" |
+ .config.images.invoker = "{{.INVOKER_SRC}}"
+ '
+ - diff opsroot.orig opsroot.json || true
+
+ opslink:
+ desc: link ops
+ cmds:
+ - task: cli
+ - mkdir -p ~/.local/bin ~/.ops/{{.OPS_BRANCH}}
+ - ln -sf $(pwd)/ops ~/.local/bin/ops
+ - ln -sf $(pwd)/olaris ~/.ops/{{.OPS_BRANCH}}/olaris
+
build:
desc: build all
cmds:
- - task: cli
+ - task: opslink
+ - task: openserverless
- task: operator
- task: runtimes
- task: streamer
- task: admin-api
- task: opsroot
- - task: runtimes
- setup:
- desc: setup
+ test:
+ desc: create
+ dir: testing/tests
cmds:
- |
- export PATH="$PWD:$PATH"
- ops setup mini
+ export PATH="{{.TASKFILE_DIR}}:$PATH"
+ export OPS_ROOT="{{.TASKFILE_DIR}}/olaris"
+ export OPS_BRANCH="{{.OPS_BRANCH}}"
+ which ops
+ ops -info
+ ./all.sh kind
diff --git a/admin-api b/admin-api
index 650c207..395265e 160000
--- a/admin-api
+++ b/admin-api
@@ -1 +1 @@
-Subproject commit 650c2077be04509a208a71fa63b6c22f7b9918e1
+Subproject commit 395265ebff6113f712694ac9bbc7ca725e998ade
diff --git a/build b/build
new file mode 160000
index 0000000..e56fdb1
--- /dev/null
+++ b/build
@@ -0,0 +1 @@
+Subproject commit e56fdb1daed6b4bb8bb8219f2ba85fa8a561c425
diff --git a/build-and-test-mac.sh b/build-and-test-mac.sh
new file mode 100755
index 0000000..dfc6a62
--- /dev/null
+++ b/build-and-test-mac.sh
@@ -0,0 +1,70 @@
+#!/bin/bash
+
+set -euo pipefail
+
+VM_NAME="openserverless"
+# Mount and build in the CURRENT directory (where the script is launched from),
+# not where the script file lives.
+SRC_DIR="$(pwd)"
+LINUX_SCRIPT="build-and-test-ubuntu.sh"
+
+echo "Checking this is a Mac"
+if [[ "$(uname -s)" != "Darwin" ]]; then
+ echo "ERROR: this script must run on macOS (Darwin), found $(uname -s)" >&2
+ exit 1
+fi
+
+echo "Checking lima is installed"
+if ! command -v limactl >/dev/null 2>&1; then
+ echo "ERROR: lima (limactl) is not installed. Install it with 'brew
install lima'" >&2
+ exit 1
+fi
+
+echo "Destroying existing '$VM_NAME' VM if it exists"
+if limactl list --quiet 2>/dev/null | grep -qx "$VM_NAME"; then
+ limactl stop -f "$VM_NAME" 2>/dev/null || true
+ limactl delete -f "$VM_NAME"
+fi
+
+echo "Creating '$VM_NAME' VM with the source dir mounted writable"
+# Mount the source directory writable so `go build` can write the ops binary
+# back into the tree (the default lima mounts are read-only).
+limactl start --name="$VM_NAME" --tty=false \
+ --cpus=4 --memory=8 \
+ --set ".mounts += [{\"location\": \"$SRC_DIR\", \"writable\": true}]"
+
+# Path of the mounted source dir as seen inside the VM (lima mirrors the host
path).
+GUEST_SRC="$SRC_DIR"
+
+echo "Provisioning the build user (docker + passwordless sudo)"
+# The user that owns the mounted source already exists inside the VM (lima maps
+# the host user in), so reuse it rather than creating one with a clashing uid.
+# Give it docker + passwordless sudo so the build script needs no
newgrp/usermod.
+# The resolved username is written to a file we read back on the host.
+BUILD_USER="$(limactl shell "$VM_NAME" sudo env GUEST_SRC="$GUEST_SRC" bash
-euo pipefail <<'PROVISION'
+# uid that owns the source files on the mount -> the user we build as.
+SRC_UID="$(stat -c %u "$GUEST_SRC")"
+BUILD_USER="$(getent passwd "$SRC_UID" | cut -d: -f1)"
+if [ -z "$BUILD_USER" ]; then
+ echo "no user owns $GUEST_SRC (uid $SRC_UID)" >&2
+ exit 1
+fi
+
+# Install docker and add the build user to the docker + sudo groups.
+which docker >/dev/null 2>&1 || curl -sL get.docker.com | sh >&2
+usermod -aG docker,sudo "$BUILD_USER"
+
+# Passwordless sudo.
+echo "$BUILD_USER ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/build-user
+chmod 440 /etc/sudoers.d/build-user
+
+echo "$BUILD_USER"
+PROVISION
+)"
+echo "Build user is '$BUILD_USER'"
+
+echo "Running $LINUX_SCRIPT inside the VM as '$BUILD_USER'"
+# Run as the build user WITHOUT -i: a login shell would reset the working dir
to
+# the user's home. -H sets $HOME; the script cd's into the source dir itself.
+
+limactl shell --workdir "$GUEST_SRC" "$VM_NAME" sudo -H -u "$BUILD_USER" bash
-- "$GUEST_SRC/$LINUX_SCRIPT"
diff --git a/build-and-test-ubuntu.sh b/build-and-test-ubuntu.sh
new file mode 100755
index 0000000..68fdd8c
--- /dev/null
+++ b/build-and-test-ubuntu.sh
@@ -0,0 +1,83 @@
+#!/bin/bash
+set -euo pipefail
+
+# This script builds and tests the sources. It expects to run as a user that
+# already has passwordless sudo and is a member of the docker group (the host
+# driver — build-and-test-mac.sh / build-and-test-windows.ps1 — sets that up).
+# It must run from the source directory, which the user can write to.
+
+echo "Checking this is Linux Ubuntu"
+if [[ "$(uname -s)" != "Linux" ]]; then
+ echo "ERROR: this script must run on Linux, found $(uname -s)" >&2
+ exit 1
+fi
+if ! grep -qi ubuntu /etc/os-release 2>/dev/null; then
+ echo "ERROR: this script must run on Ubuntu" >&2
+ exit 1
+fi
+
+echo "Checking Docker is accessible"
+if ! command -v docker >/dev/null 2>&1; then
+ echo "ERROR: docker is not installed" >&2
+ exit 1
+fi
+if ! docker ps >/dev/null 2>&1; then
+ echo "ERROR: cannot access the Docker daemon (permission denied or daemon
not running)." >&2
+ echo " Ensure the daemon is running and this user is in the 'docker'
group." >&2
+ echo " If you were just added to the group, start a fresh session
(e.g. 'newgrp docker')." >&2
+ exit 1
+fi
+
+echo "Killing k3s processes if present"
+if [[ -x /usr/local/bin/k3s-killall.sh ]]; then
+ sudo /usr/local/bin/k3s-killall.sh
+fi
+
+echo "Uninstalling k3s if present"
+if [[ -x /usr/local/bin/k3s-uninstall.sh ]]; then
+ sudo /usr/local/bin/k3s-uninstall.sh
+fi
+if [[ -x /usr/local/bin/k3s-agent-uninstall.sh ]]; then
+ sudo /usr/local/bin/k3s-agent-uninstall.sh
+fi
+
+sudo apt-get update
+sudo apt-get -y install jq unzip zip
+
+# Install go, task and kubectl WITHOUT snap: snapd mounts each snap via
snapfuse
+# under WSL, which silently presents an empty mountpoint (meta/snap.yaml
missing),
+# so `task`/`go`/`kubectl` fail. Direct binaries avoid the whole snap
machinery.
+
+# Map dpkg arch (amd64/arm64) to the Go/k8s arch naming used by the download
URLs.
+GOARCH="$(dpkg --print-architecture)"
+
+echo "Installing Go"
+GO_VERSION=1.26.4
+curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-${GOARCH}.tar.gz" -o
/tmp/go.tar.gz
+sudo rm -rf /usr/local/go
+sudo tar -C /usr/local -xzf /tmp/go.tar.gz
+rm -f /tmp/go.tar.gz
+# Make go available on PATH for this session and for future login shells.
+export PATH="/usr/local/go/bin:$PATH"
+echo 'export PATH=/usr/local/go/bin:$PATH' | sudo tee /etc/profile.d/go.sh
>/dev/null
+
+echo "Installing Task"
+# Official installer drops the 'task' binary into the given -b directory.
+curl -fsSL https://taskfile.dev/install.sh | sudo sh -s -- -d -b /usr/local/bin
+
+echo "Installing kubectl"
+KUBECTL_VERSION="$(curl -fsSL https://dl.k8s.io/release/stable.txt)"
+curl -fsSL
"https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/${GOARCH}/kubectl" -o
/tmp/kubectl
+sudo install -m 0755 /tmp/kubectl /usr/local/bin/kubectl
+rm -f /tmp/kubectl
+
+export PATH="/usr/local/go/bin:/usr/local/bin:$PATH"
+
+echo "Building and testing"
+# cd into the source dir (where this script lives) so `task` finds the
Taskfile,
+# regardless of the caller's working directory (e.g. a login shell resets it).
+cd "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+git config --global --add safe.directory "$PWD"
+git config --global --add safe.directory "$PWD/olaris-op"
+task build
+task test
diff --git a/build-and-test-windows.ps1 b/build-and-test-windows.ps1
new file mode 100755
index 0000000..04c273a
--- /dev/null
+++ b/build-and-test-windows.ps1
@@ -0,0 +1,136 @@
+#Requires -Version 5.1
+# Build-and-test driver for Windows via WSL.
+# - installs WSL if missing
+# - creates and starts an Ubuntu distribution
+# - initializes it non-interactively: removes k3s, creates a sudo user, sets
it default
+# - Enter in the distro
+
+$ErrorActionPreference = "Stop"
+
+$Distro = "Ubuntu"
+$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
+
+# Default UNIX account created inside the distribution (override with env
vars).
+$WslUser = if ($env:WSL_USER) { $env:WSL_USER } else { "ops" }
+$WslPassword = if ($env:WSL_PASSWORD) { $env:WSL_PASSWORD } else { "ops" }
+
+function Test-WslInstalled {
+ if (-not (Get-Command wsl.exe -ErrorAction SilentlyContinue)) {
+ return $false
+ }
+ # `wsl --status` returns a non-zero exit code when WSL is not usable.
+ wsl.exe --status *> $null
+ return ($LASTEXITCODE -eq 0)
+}
+
+Write-Host "Checking WSL is installed"
+if (-not (Test-WslInstalled)) {
+ Write-Host "WSL not found. Installing WSL with the $Distro distribution..."
+ wsl.exe --install -d $Distro
+ Write-Warning "WSL was just installed. A reboot is usually required to
finish setup."
+ Write-Warning "Please reboot Windows and re-run this script."
+ exit 0
+}
+
+Write-Host "Removing any existing $Distro distribution for a clean build"
+$installed = (wsl.exe --list --quiet) -replace "`0", "" | ForEach-Object {
$_.Trim() } | Where-Object { $_ }
+if ($installed -contains $Distro) {
+ Write-Host "Unregistering existing $Distro distribution..."
+ wsl.exe --unregister $Distro
+ if ($LASTEXITCODE -ne 0) {
+ Write-Error "Failed to unregister $Distro"
+ exit $LASTEXITCODE
+ }
+}
+
+Write-Host "Installing a fresh $Distro distribution"
+wsl.exe --install -d $Distro --no-launch
+if ($LASTEXITCODE -ne 0) {
+ Write-Error "Failed to install $Distro"
+ exit $LASTEXITCODE
+}
+
+Write-Host "Initializing $Distro as root (removing k3s, docker, creating user
'$WslUser')"
+# On WSL there is no host user mapped in, so we create the build user
ourselves.
+# We do it by running provisioning commands directly as root (wsl -u root), no
+# boot command. The script is idempotent: removes k3s, ensures docker, and
+# creates '$WslUser' with docker + passwordless sudo.
+$initScript = @"
+set -e
+
+# Remove k3s if it is installed inside the distribution.
+if [ -x /usr/local/bin/k3s-killall.sh ]; then /usr/local/bin/k3s-killall.sh; fi
+if [ -x /usr/local/bin/k3s-uninstall.sh ]; then
/usr/local/bin/k3s-uninstall.sh; fi
+if [ -x /usr/local/bin/k3s-agent-uninstall.sh ]; then
/usr/local/bin/k3s-agent-uninstall.sh; fi
+
+# Ensure docker is installed.
+command -v docker >/dev/null 2>&1 || curl -sL get.docker.com | sh
+
+# Create the build user if it does not already exist (idempotent).
+if ! id -u '$WslUser' >/dev/null 2>&1; then
+ useradd -m -s /bin/bash '$WslUser'
+ echo '${WslUser}:$WslPassword' | chpasswd
+fi
+
+# Add it to the docker + sudo groups and grant passwordless sudo.
+usermod -aG docker,sudo '$WslUser'
+echo '$WslUser ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/$WslUser
+chmod 440 /etc/sudoers.d/$WslUser
+
+# Make sure the docker daemon is running.
+service docker start >/dev/null 2>&1 || true
+
+# Mount Windows drives with 'metadata' so Unix permissions (including the
+# executable bit) are honored on /mnt/c. Without this, scripts on the mount
+# cannot be run directly (fork/exec fails with "no such file or directory").
+# Requires a `wsl --shutdown` to take effect (done below).
+mkdir -p /etc
+if [ ! -f /etc/wsl.conf ] || ! grep -q '^\[automount\]' /etc/wsl.conf; then
+ printf '[automount]\noptions = "metadata"\n' >> /etc/wsl.conf
+elif ! grep -q 'metadata' /etc/wsl.conf; then
+ sed -i '/^\[automount\]/a options = "metadata"' /etc/wsl.conf
+fi
+"@
+
+# Write the script to a BOM-less, LF-normalized temp file (PS 5.1 stdin pipes
+# prepend a BOM that bash chokes on), then run it as root inside the distro.
+$initFile = Join-Path ([System.IO.Path]::GetTempPath()) "wsl-init-$PID.sh"
+[System.IO.File]::WriteAllText($initFile, ($initScript -replace "`r`n", "`n"),
(New-Object System.Text.UTF8Encoding($false)))
+try {
+ $wslInitPath = (wsl.exe -d $Distro wslpath -a ($initFile -replace '\\',
'/')).Trim()
+ wsl.exe -d $Distro -u root -- bash "$wslInitPath"
+ if ($LASTEXITCODE -ne 0) {
+ Write-Error "Failed to initialize $Distro"
+ exit $LASTEXITCODE
+ }
+} finally {
+ Remove-Item -LiteralPath $initFile -ErrorAction SilentlyContinue
+}
+
+# Restart WSL so the /etc/wsl.conf 'metadata' automount option is applied.
+# Until the distro is remounted, /mnt/c ignores the executable bit and scripts
+# on it cannot be run directly.
+Write-Host "Restarting WSL to apply mount options"
+wsl.exe --shutdown
+
+Write-Host "Setting '$WslUser' as the default user for $Distro"
+# Use wsl.exe --manage: the per-distro launcher (e.g. Ubuntu.exe) is not
always on
+# PATH and its name does not reliably match the distro name.
+wsl.exe --manage $Distro --set-default-user $WslUser
+if ($LASTEXITCODE -ne 0) {
+ Write-Error "Failed to set default user for $Distro"
+ exit $LASTEXITCODE
+}
+
+Write-Host "Running build-and-test-ubuntu.sh in $Distro as '$WslUser'"
+# Run the build/test script as ops from the source directory. ops was created
+# with the mount's owning uid/gid, so it can write the build output in place;
+# it has docker + passwordless sudo, so no newgrp/usermod is needed in-script.
+$wslScriptDir = (wsl.exe -d $Distro wslpath -a ($ScriptDir -replace '\\',
'/')).Trim()
+wsl.exe -d $Distro --cd "$wslScriptDir" -u $WslUser -- bash -lc
"./build-and-test-ubuntu.sh"
+if ($LASTEXITCODE -ne 0) {
+ Write-Error "build-and-test-ubuntu.sh failed with exit code $LASTEXITCODE"
+ exit $LASTEXITCODE
+}
+
+Write-Host "Done."
diff --git a/build-step.md b/build-step.md
new file mode 100644
index 0000000..cfd53aa
--- /dev/null
+++ b/build-step.md
@@ -0,0 +1,356 @@
+# Build Session Notes
+
+Date: 2026-06-27
+
+## Scope
+
+Work was done locally only. No git push and no Docker Hub push were performed.
+
+## Branches And Submodules
+
+- Root repository branch: `build`
+- `build` submodule branch: `build-local`
+- `build/openwhisk` submodule branch: `openwhisk-build-fixes`
+
+## OpenWhisk Source
+
+The nested `build/openwhisk` submodule was moved to the Nuvolaris commit:
+
+```text
+a456219d35bfabe4a3458fcce82cd71497a8524e
+```
+
+`build/.gitmodules` was updated to use:
+
+```text
+https://github.com/nuvolaris/openwhisk.git
+```
+
+## Build Devcontainer
+
+The correct build devcontainer is:
+
+```text
+build/.devcontainer/Dockerfile
+```
+
+The top-level `devcontainer` submodule was touched by mistake, then reverted.
It is not part of the final build path.
+
+The build devcontainer was updated to be multi-arch and OpenWhisk-ready:
+
+- Java 11 via Temurin is the default `JAVA_HOME`
+- GraalVM Java 17 is still available for native-image
+- Docker CLI and buildx are installed
+- Docker repo setup uses the Ubuntu codename instead of a hardcoded `bionic`
+
+Verified inside the container:
+
+```text
+java 11.0.17
+javac 11.0.17
+native-image 17.0.9
+docker CLI available
+task available
+```
+
+## Gradle Fixes
+
+`task distdocker` initially failed with dependency resolution errors in the
old OpenWhisk commit.
+
+Backported minimal Gradle fixes in `build/openwhisk`:
+
+- `build.gradle`: use `gradle.plugin.cz.alenkacz:gradle-scalafmt`
+- `settings.gradle`: `scalafmt` version `1.5.1`
+- `core/standalone/build.gradle`: `gradle-git-properties` version `2.4.2`
+
+These fixes are committed locally in:
+
+```text
+f2cba906 Fix OpenWhisk distDocker dependency resolution
+```
+
+## Java 17 Host Error
+
+Running OpenWhisk Gradle directly on the host failed with:
+
+```text
+Unsupported class file major version 61
+```
+
+Reason: host Java was 17, but this OpenWhisk/Gradle 6.9.1 build must run with
Java 11.
+
+Fix: `build/Taskfile.yml` now wraps `distdocker` and `build-all` with `ops ide
devcontainer`, so the host uses the same devcontainer path expected by OPS
instead of a hand-written `docker run`.
+
+The wrapper also sets a temporary empty `DOCKER_CONFIG` inside the
devcontainer.
+This avoids failures from a devcontainer-generated Docker credential helper,
for
+example:
+
+```text
+error getting credentials - err: exit status 255
+```
+
+## Local Docker Build Tasks
+
+`build/Taskfile.yml` was changed so:
+
+- `task build` is the main local flow: build images, update OPS root, load
kind, roll out controller
+- `task distdocker` runs through `ops ide devcontainer`
+- `task build-all` runs through `ops ide devcontainer`
+- `task build-all:local` checks that `openwhisk/common/scala` exists and
prints a submodule init hint if it does not
+- `distdocker` no longer passes a Docker registry by default
+- `build-all` no longer uses `--push` for `ACT=build`
+- Push remains explicit via `buildx-and-push` / `ACT=buildx-push`
+
+Verified:
+
+```text
+cd /home/msciab/openserverless/build
+task build
+```
+
+This completed successfully locally through `ops ide devcontainer`. It built
the
+OpenWhisk images, loaded controller/invoker/standalone into kind, and rolled
out
+`controller-0`.
+
+Latest verified tag:
+
+```text
+2.0.0-incubating.2606291403
+```
+
+Latest verified pod image:
+
+```text
+controller-0
registry.hub.docker.com/apache/openserverless-wsk-controller:2.0.0-incubating.2606291403
+```
+
+## OpenWhisk Directory
+
+`build/openwhisk` was converted from a nested Git submodule into a regular
+tracked directory inside the `build-local` branch.
+
+Reason: on a fresh server, `task build` failed when Docker tried to build:
+
+```text
+openwhisk/common/scala
+```
+
+The directory was missing because the nested OpenWhisk submodule had not been
+initialized. The `build-local` branch now vendors the OpenWhisk tree from
commit
+`f2cba906`, including the local Gradle fixes, so a checkout of `build-local`
+contains `openwhisk/common/scala` directly.
+
+## Images Built Locally
+
+The OpenWhisk build produced these local Docker images:
+
+```text
+registry.hub.docker.com/apache/openserverless-wsk-scala:2.0.0-incubating.2506080813
+registry.hub.docker.com/apache/openserverless-wsk-controller:2.0.0-incubating.2506080813
+registry.hub.docker.com/apache/openserverless-wsk-invoker:2.0.0-incubating.2506080813
+registry.hub.docker.com/apache/openserverless-wsk-scheduler:2.0.0-incubating.2506080813
+registry.hub.docker.com/apache/openserverless-wsk-standalone:2.0.0-incubating.2506080813
+```
+
+Despite the `registry.hub.docker.com/apache` prefix, these were local tags
only. They were not pushed.
+
+## OPS Root Image Override
+
+The installed OPS root was updated here:
+
+```text
+/home/msciab/.ops/0.1.0/olaris/opsroot.json
+```
+
+Changed keys:
+
+```json
+{
+ "standalone":
"registry.hub.docker.com/apache/openserverless-wsk-standalone:2.0.0-incubating.2506080813",
+ "controller":
"registry.hub.docker.com/apache/openserverless-wsk-controller:2.0.0-incubating.2506080813",
+ "invoker":
"registry.hub.docker.com/apache/openserverless-wsk-invoker:2.0.0-incubating.2506080813"
+}
+```
+
+Important: in the current standalone OpenWhisk deployment path, OPS/operator
uses `controller.image` for the controller pod. The `standalone` key is present
in `opsroot.json`, but the observed `Whisk` resource uses
`spec.controller.image`.
+
+## Kubeconfig Repair
+
+The host kubeconfig was stale:
+
+```text
+https://127.0.0.1:35889
+```
+
+The running kind control plane was exposed on:
+
+```text
+https://127.0.0.1:34101
+```
+
+Backed up kubeconfig:
+
+```text
+/home/msciab/.kube/config.bak.20260627085813
+```
+
+Updated context:
+
+```text
+kind-nuvolaris
+```
+
+Verified:
+
+```text
+kubectl cluster-info
+kubectl get nodes
+```
+
+## Loading Images Into Kind
+
+This is now automated by the build repository task:
+
+```bash
+cd /home/msciab/openserverless/build
+task build
+```
+
+That task runs:
+
+1. `task build-all`
+2. update of `/home/msciab/.ops/0.1.0/olaris/opsroot.json`
+3. import of local OpenWhisk images into the kind node
+4. rollout of the local OpenWhisk controller StatefulSet
+5. final status output
+
+The locally built images were not automatically present in the kind node.
+
+The underlying import command is:
+
+```bash
+for img in \
+
registry.hub.docker.com/apache/openserverless-wsk-controller:2.0.0-incubating.2506080813
\
+
registry.hub.docker.com/apache/openserverless-wsk-invoker:2.0.0-incubating.2506080813
\
+
registry.hub.docker.com/apache/openserverless-wsk-standalone:2.0.0-incubating.2506080813
+do
+ docker save "$img" | docker exec -i nuvolaris-control-plane ctr
--namespace=k8s.io images import -
+done
+```
+
+Verified in kind:
+
+```text
+registry.hub.docker.com/apache/openserverless-wsk-controller
2.0.0-incubating.2506080813
+registry.hub.docker.com/apache/openserverless-wsk-invoker
2.0.0-incubating.2506080813
+registry.hub.docker.com/apache/openserverless-wsk-standalone
2.0.0-incubating.2506080813
+```
+
+## Current Pod Image
+
+The `Whisk` CR had the new image:
+
+```text
+spec.controller.image =
registry.hub.docker.com/apache/openserverless-wsk-controller:2.0.0-incubating.2506080813
+```
+
+But the actual StatefulSet/pod initially still used:
+
+```text
+ghcr.io/nuvolaris/openwhisk-controller:0.3.0-morpheus.22122609
+```
+
+This is now automated by:
+
+```bash
+cd /home/msciab/openserverless/build
+task build
+```
+
+The underlying patch command is:
+
+```bash
+kubectl -n nuvolaris set image statefulset/controller \
+
controller=registry.hub.docker.com/apache/openserverless-wsk-controller:2.0.0-incubating.2506080813
+```
+
+Rollout completed and `controller-0` now uses:
+
+```text
+registry.hub.docker.com/apache/openserverless-wsk-controller:2.0.0-incubating.2506080813
+```
+
+## Why `task build` / `task setup` Did Not Do This Automatically
+
+There are two separate build systems:
+
+1. Root `Taskfile.yml`
+ - Builds CLI, operator, runtimes, streamer, admin-api.
+ - Its `opsroot` task updates only:
+ - `operator`
+ - `streamer`
+ - `systemapi`
+ - It does not build or update OpenWhisk `controller` / `invoker` /
`standalone`.
+ - It saves some images into `~/.ops/<os>-<arch>/images/kind`, but not the
OpenWhisk images produced by `build/Taskfile.yml`.
+
+2. `build/Taskfile.yml`
+ - Builds OpenWhisk images:
+ - controller
+ - invoker
+ - scheduler
+ - standalone
+ - scala base
+ - Before this session, it did not update OPS `opsroot.json`.
+ - Before manual loading, it did not load these images into kind.
+
+Also, the operator/standalone image replacement appears to miss the new image
when rendering the StatefulSet.
+
+Observed behavior:
+
+- The `Whisk` CR contains `spec.controller.image` with the new image.
+- The generated StatefulSet still had the old template image.
+
+Likely technical cause:
+
+- `olaris-op/nuvolaris/openwhisk_standalone.py` calls `kus.image(whisk_image,
newTag=whisk_tag)`.
+- Kustomize image replacement matches the image name already present in the
template.
+- The template contains `ghcr.io/nuvolaris/openwhisk-controller`.
+- The generated kustomization uses the new image as the match name, so it does
not match the old template image.
+
+Proper code-level fix should replace the template image name with `newName`,
for example:
+
+```text
+name: ghcr.io/nuvolaris/openwhisk-controller
+newName: registry.hub.docker.com/apache/openserverless-wsk-controller
+newTag: 2.0.0-incubating.2506080813
+```
+
+## Local Commits Created
+
+Root repo:
+
+```text
+bd8b2b4 Update build-all local workflow
+1796e13 Update build distdocker container wrapper
+35ae719 Update build distdocker local workflow
+d4d269d Update build submodule devcontainer toolchain
+d781ddb Update build submodule for Nuvolaris openwhisk source
+d758eab Point build submodule to local openwhisk update
+```
+
+Build submodule:
+
+```text
+3326ff6 Make build-all local and containerized
+f591434 Run distdocker through build container
+13ef155 Make distdocker local-only by default
+3492964 Make build devcontainer multi-arch OpenWhisk ready
+2c53f0f Use Nuvolaris openwhisk submodule source
+2fd1cf8 Point openwhisk to Nuvolaris action size change
+```
+
+OpenWhisk submodule:
+
+```text
+f2cba906 Fix OpenWhisk distDocker dependency resolution
+```
diff --git a/cli b/cli
index f991fd0..a601c07 160000
--- a/cli
+++ b/cli
@@ -1 +1 @@
-Subproject commit f991fd07e37768e750e2ce8f1971a0073e4ca848
+Subproject commit a601c075303135e65e7ee63e4ab1af2818be2364
diff --git a/devcontainer b/devcontainer
index e704655..f6538f1 160000
--- a/devcontainer
+++ b/devcontainer
@@ -1 +1 @@
-Subproject commit e7046558156861bd62540d88bdaca5aee34842f1
+Subproject commit f6538f12c16913a588ddbd51cb7c6b90e140e5c0
diff --git a/olaris b/olaris
index b5bf768..eb360c0 160000
--- a/olaris
+++ b/olaris
@@ -1 +1 @@
-Subproject commit b5bf7688ad76fa56394b70681d21681a7c93f26b
+Subproject commit eb360c093ec739edcca81cad10b72f4002cfd4e3
diff --git a/olaris-op b/olaris-op
index 84e48da..8e09c2f 160000
--- a/olaris-op
+++ b/olaris-op
@@ -1 +1 @@
-Subproject commit 84e48da96c5253120f19b5d03f7400fdbeca94bf
+Subproject commit 8e09c2f3a85921f1e3f616dbaed51a35336ad8b9
diff --git a/openserverless-cli.code-workspace
b/openserverless-cli.code-workspace
deleted file mode 100644
index 34bbc8a..0000000
--- a/openserverless-cli.code-workspace
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "folders": [
- {
- "name": "cli",
- "path": "cli"
- },
- {
- "name": "task",
- "path": "task"
- }
- ],
- "settings": {
- "workbench.colorCustomizations": {
- "activityBar.background": "#5b09e0",
- "titleBar.activeBackground": "#5b09e0",
- "titleBar.activeForeground": "#5b09e0",
- "statusBar.background": "#5b09e0"
- },
- "go.goroot":
"/nix/store/nnh57s7m672k6snkanhz1kb18skwjpbg-go-1.21.11/share/go"
- }
-}
diff --git a/openserverless-operator.code-workspace
b/openserverless-operator.code-workspace
deleted file mode 100644
index f802d83..0000000
--- a/openserverless-operator.code-workspace
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "folders": [
- {
- "name": "openserverless-operator",
- "path": "operator"
- }
- ],
- "settings": {
- "workbench.colorCustomizations": {
- "activityBar.background": "#32cb0f",
- "titleBar.activeBackground": "#32cb0f",
- "titleBar.activeForeground": "#32cb0f",
- "statusBar.background": "#32cb0f"
-
- }
- }
-}
diff --git a/openserverless.code-workspace b/openserverless.code-workspace
deleted file mode 100644
index 852c8bb..0000000
--- a/openserverless.code-workspace
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "folders": [
- {
- "name": "operator",
- "path": "operator"
- },
- {
- "name": "site",
- "path": "site"
- },
- {
- "name": "root",
- "path": "."
- }
- ],
- "settings": {
- "workbench.colorCustomizations": {
- "activityBar.background": "#d2e313",
- "titleBar.activeBackground": "#d2e313",
- "titleBar.activeForeground": "#d2e313",
- "statusBar.background": "#d2e313"
- }
- }
-}
diff --git a/runtimes b/runtimes
index d1bc9ff..0300f37 160000
--- a/runtimes
+++ b/runtimes
@@ -1 +1 @@
-Subproject commit d1bc9ffee4634899241b60210c0323740deda066
+Subproject commit 0300f377f8ab3704462d9e3c63cef1892441417c
diff --git a/site b/site
deleted file mode 160000
index e45b68f..0000000
--- a/site
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit e45b68f3e8a36705d388ab5608d7cb256f55465c
diff --git a/streamer b/streamer
index 57dd328..99d4f0f 160000
--- a/streamer
+++ b/streamer
@@ -1 +1 @@
-Subproject commit 57dd32888ca610280dfaca1d47cca12a0526cc52
+Subproject commit 99d4f0f75936afda5404c593d91b6e1fa5dfda2e
diff --git a/testing b/testing
index 4784e06..bb6c50c 160000
--- a/testing
+++ b/testing
@@ -1 +1 @@
-Subproject commit 4784e064e0c0b171ceb93b9656d8d1c9f900346f
+Subproject commit bb6c50c892e37947fa801fdf68d2797bd50d8f57
diff --git a/vscode b/vscode
index 2d293c9..abcd703 160000
--- a/vscode
+++ b/vscode
@@ -1 +1 @@
-Subproject commit 2d293c9871a5b8ace39e6b42ab152675bb1967f9
+Subproject commit abcd703fb389c2df2171ce2d32da6068a914f415