027ad82db2
El SDK CI - dev / build-and-test (pull_request) Successful in 3m35s
el-install.el explicitly imported runtime/*.el modules (string, env, fs, exec, json, http), which elb compiled to .c files in the shared dist/bin out_dir. Linking those alongside el_runtime.c caused multiple definition errors for every runtime function (http_get, http_patch, etc.). The runtime .el files are thin wrappers over seed primitives already compiled into el_runtime.c — no import needed. Fixes: - Remove all explicit runtime imports from el-install.el (root cause) - Add --clean to every elb invocation in sdk-release.yaml so each build starts with a clean out_dir (defense-in-depth against stale .c files) - Add elb build + epm/el-install build steps to ci-dev.yaml and ci-stage.yaml so linker errors are caught on every PR, not just stage->main
406 lines
16 KiB
YAML
406 lines
16 KiB
YAML
name: El SDK Release
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
pull_request:
|
|
branches:
|
|
- main
|
|
|
|
jobs:
|
|
build-and-release:
|
|
runs-on: ubuntu-latest
|
|
defaults:
|
|
run:
|
|
working-directory: lang
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Enforce source branch (main <- stage only)
|
|
if: github.event_name == 'pull_request'
|
|
run: |
|
|
SOURCE="${GITHUB_HEAD_REF}"
|
|
if [ "${SOURCE}" != "stage" ]; then
|
|
echo "ERROR: Main branch only accepts PRs from 'stage'. Source was: '${SOURCE}'"
|
|
exit 1
|
|
fi
|
|
echo "Source branch check passed: ${SOURCE} -> main"
|
|
|
|
- name: Install build dependencies
|
|
run: |
|
|
apt-get update -qq
|
|
apt-get install -y gcc libcurl4-openssl-dev
|
|
|
|
# Seed: use the committed linux-amd64 binary as the bootstrap
|
|
- name: Bootstrap from committed linux binary (seed)
|
|
run: |
|
|
chmod +x dist/platform/elc-linux-amd64
|
|
echo "seed elc (committed linux-amd64 binary)"
|
|
dist/platform/elc-linux-amd64 --version || true
|
|
|
|
# Gen2: use seed to self-host compile the El compiler
|
|
- name: Self-host compile El compiler (gen2)
|
|
run: |
|
|
mkdir -p dist/platform
|
|
dist/platform/elc-linux-amd64 elc-cli.el > dist/elc-gen2.c
|
|
gcc -O2 \
|
|
-I el-compiler/runtime \
|
|
dist/elc-gen2.c \
|
|
el-compiler/runtime/el_runtime.c \
|
|
-lcurl -lssl -lcrypto -lpthread -lm \
|
|
-o dist/platform/elc
|
|
chmod +x dist/platform/elc
|
|
echo "gen2 (self-hosted) elc built"
|
|
dist/platform/elc --version || true
|
|
|
|
# Build elb binary
|
|
- name: Build elb
|
|
run: |
|
|
mkdir -p dist/bin
|
|
dist/platform/elc elb.el > dist/elb.c
|
|
gcc -O2 \
|
|
-I el-compiler/runtime \
|
|
dist/elb.c \
|
|
el-compiler/runtime/el_runtime.c \
|
|
-lcurl -lssl -lcrypto -lpthread -lm \
|
|
-o dist/bin/elb
|
|
chmod +x dist/bin/elb
|
|
echo "elb built"
|
|
|
|
# Build epm binary using elb (epm lives at repo root, not inside lang/)
|
|
- name: Build epm
|
|
run: |
|
|
ABS_ELB="$(pwd)/dist/bin/elb"
|
|
ABS_ELC="$(pwd)/dist/platform/elc"
|
|
ABS_RUNTIME="$(pwd)/el-compiler/runtime"
|
|
ABS_OUT="$(pwd)/dist/bin"
|
|
(cd ../epm && "$ABS_ELB" --clean --elc="$ABS_ELC" --runtime="$ABS_RUNTIME" --out="$ABS_OUT")
|
|
chmod +x dist/bin/epm
|
|
echo "epm built"
|
|
|
|
# Build el-install binary using elb
|
|
- name: Build el-install
|
|
run: |
|
|
ABS_ELB="$(pwd)/dist/bin/elb"
|
|
ABS_ELC="$(pwd)/dist/platform/elc"
|
|
ABS_RUNTIME="$(pwd)/el-compiler/runtime"
|
|
ABS_OUT="$(pwd)/dist/bin"
|
|
(cd tools/install && "$ABS_ELB" --clean --elc="$ABS_ELC" --runtime="$ABS_RUNTIME" --out="$ABS_OUT")
|
|
chmod +x dist/bin/el-install
|
|
echo "el-install built"
|
|
|
|
- name: Run tests - text
|
|
run: |
|
|
ELC="$(pwd)/dist/platform/elc" \
|
|
EL_HOME="$(pwd)" \
|
|
bash tests/text/run.sh
|
|
|
|
- name: Run tests - calendar
|
|
run: |
|
|
ELC="$(pwd)/dist/platform/elc" \
|
|
EL_HOME="$(pwd)" \
|
|
bash tests/calendar/run.sh
|
|
|
|
- name: Run tests - time
|
|
run: |
|
|
ELC="$(pwd)/dist/platform/elc" \
|
|
EL_HOME="$(pwd)" \
|
|
bash tests/time/run.sh
|
|
|
|
- name: Run tests - html_sanitizer
|
|
run: |
|
|
ELC="$(pwd)/dist/platform/elc" \
|
|
EL_HOME="$(pwd)" \
|
|
bash tests/html_sanitizer/run.sh
|
|
|
|
# Native El test suites (elc --test, compile-link-run)
|
|
- name: Run tests - native (core)
|
|
run: |
|
|
set -euo pipefail
|
|
ELC="$(pwd)/dist/platform/elc"
|
|
RUNTIME="$(pwd)/el-compiler/runtime"
|
|
"$ELC" --test tests/native/test_core.el > /tmp/el_native_core.c
|
|
gcc -O2 -I "$RUNTIME" /tmp/el_native_core.c "$RUNTIME/el_runtime.c" \
|
|
-lcurl -lssl -lcrypto -lpthread -lm -o /tmp/el_native_core
|
|
/tmp/el_native_core
|
|
|
|
- name: Run tests - native (text)
|
|
run: |
|
|
set -euo pipefail
|
|
ELC="$(pwd)/dist/platform/elc"
|
|
RUNTIME="$(pwd)/el-compiler/runtime"
|
|
"$ELC" --test tests/native/test_text.el > /tmp/el_native_text.c
|
|
gcc -O2 -I "$RUNTIME" /tmp/el_native_text.c "$RUNTIME/el_runtime.c" \
|
|
-lcurl -lssl -lcrypto -lpthread -lm -o /tmp/el_native_text
|
|
/tmp/el_native_text
|
|
|
|
- name: Run tests - native (string)
|
|
run: |
|
|
set -euo pipefail
|
|
ELC="$(pwd)/dist/platform/elc"
|
|
RUNTIME="$(pwd)/el-compiler/runtime"
|
|
"$ELC" --test tests/native/test_string.el > /tmp/el_native_string.c
|
|
gcc -O2 -I "$RUNTIME" /tmp/el_native_string.c "$RUNTIME/el_runtime.c" \
|
|
-lcurl -lssl -lcrypto -lpthread -lm -o /tmp/el_native_string
|
|
/tmp/el_native_string
|
|
|
|
- name: Run tests - native (math)
|
|
run: |
|
|
set -euo pipefail
|
|
ELC="$(pwd)/dist/platform/elc"
|
|
RUNTIME="$(pwd)/el-compiler/runtime"
|
|
"$ELC" --test tests/native/test_math.el > /tmp/el_native_math.c
|
|
gcc -O2 -I "$RUNTIME" /tmp/el_native_math.c "$RUNTIME/el_runtime.c" \
|
|
-lcurl -lssl -lcrypto -lpthread -lm -o /tmp/el_native_math
|
|
/tmp/el_native_math
|
|
|
|
- name: Run tests - native (state)
|
|
run: |
|
|
set -euo pipefail
|
|
ELC="$(pwd)/dist/platform/elc"
|
|
RUNTIME="$(pwd)/el-compiler/runtime"
|
|
"$ELC" --test tests/native/test_state.el > /tmp/el_native_state.c
|
|
gcc -O2 -I "$RUNTIME" /tmp/el_native_state.c "$RUNTIME/el_runtime.c" \
|
|
-lcurl -lssl -lcrypto -lpthread -lm -o /tmp/el_native_state
|
|
/tmp/el_native_state
|
|
|
|
- name: Run tests - native (time)
|
|
run: |
|
|
set -euo pipefail
|
|
ELC="$(pwd)/dist/platform/elc"
|
|
RUNTIME="$(pwd)/el-compiler/runtime"
|
|
"$ELC" --test tests/native/test_time.el > /tmp/el_native_time.c
|
|
gcc -O2 -I "$RUNTIME" /tmp/el_native_time.c "$RUNTIME/el_runtime.c" \
|
|
-lcurl -lssl -lcrypto -lpthread -lm -o /tmp/el_native_time
|
|
/tmp/el_native_time
|
|
|
|
- name: Run tests - native (json)
|
|
run: |
|
|
set -euo pipefail
|
|
ELC="$(pwd)/dist/platform/elc"
|
|
RUNTIME="$(pwd)/el-compiler/runtime"
|
|
"$ELC" --test tests/native/test_json.el > /tmp/el_native_json.c
|
|
gcc -O2 -I "$RUNTIME" /tmp/el_native_json.c "$RUNTIME/el_runtime.c" \
|
|
-lcurl -lssl -lcrypto -lpthread -lm -o /tmp/el_native_json
|
|
/tmp/el_native_json
|
|
|
|
- name: Run tests - native (env)
|
|
run: |
|
|
set -euo pipefail
|
|
ELC="$(pwd)/dist/platform/elc"
|
|
RUNTIME="$(pwd)/el-compiler/runtime"
|
|
"$ELC" --test tests/native/test_env.el > /tmp/el_native_env.c
|
|
gcc -O2 -I "$RUNTIME" /tmp/el_native_env.c "$RUNTIME/el_runtime.c" \
|
|
-lcurl -lssl -lcrypto -lpthread -lm -o /tmp/el_native_env
|
|
/tmp/el_native_env
|
|
|
|
- name: Run tests - native (fs)
|
|
run: |
|
|
set -euo pipefail
|
|
ELC="$(pwd)/dist/platform/elc"
|
|
RUNTIME="$(pwd)/el-compiler/runtime"
|
|
"$ELC" --test tests/native/test_fs.el > /tmp/el_native_fs.c
|
|
gcc -O2 -I "$RUNTIME" /tmp/el_native_fs.c "$RUNTIME/el_runtime.c" \
|
|
-lcurl -lssl -lcrypto -lpthread -lm -o /tmp/el_native_fs
|
|
/tmp/el_native_fs
|
|
|
|
# Bundle the SDK tarball - runs from the repo root to reference lang/ paths correctly
|
|
- name: Bundle SDK tarball
|
|
if: github.event_name == 'push'
|
|
working-directory: ${{ github.workspace }}
|
|
run: |
|
|
mkdir -p dist/sdk/bin dist/sdk/runtime
|
|
cp lang/dist/platform/elc dist/sdk/bin/elc
|
|
cp lang/dist/bin/elb dist/sdk/bin/elb
|
|
cp lang/dist/bin/epm dist/sdk/bin/epm
|
|
cp lang/el-compiler/runtime/el_runtime.c dist/sdk/runtime/
|
|
cp lang/el-compiler/runtime/el_runtime.h dist/sdk/runtime/
|
|
cp lang/runtime/*.el dist/sdk/runtime/
|
|
tar -czf dist/el-sdk-latest.tar.gz -C dist/sdk .
|
|
echo "SDK tarball bundled: dist/el-sdk-latest.tar.gz"
|
|
ls -lh dist/el-sdk-latest.tar.gz
|
|
|
|
# Publish / update the `latest` release with all SDK assets
|
|
- name: Publish latest release
|
|
if: github.event_name == 'push'
|
|
working-directory: ${{ github.workspace }}
|
|
env:
|
|
GITEA_TOKEN: ${{ secrets.GIT_TOKEN }}
|
|
GITEA_API: https://git.neuralplatform.ai/api/v1
|
|
REPO: neuron-technologies/el
|
|
run: |
|
|
EXISTING_ID=$(curl -sf \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
"${GITEA_API}/repos/${REPO}/releases/tags/latest" \
|
|
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['id'])" 2>/dev/null || true)
|
|
|
|
if [ -n "${EXISTING_ID}" ]; then
|
|
echo "Deleting existing release id=${EXISTING_ID}"
|
|
curl -sf -X DELETE \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
"${GITEA_API}/repos/${REPO}/releases/${EXISTING_ID}"
|
|
fi
|
|
|
|
curl -sf -X DELETE \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
"${GITEA_API}/repos/${REPO}/tags/latest" || true
|
|
|
|
RELEASE_ID=$(curl -sf -X POST \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
"${GITEA_API}/repos/${REPO}/releases" \
|
|
-d "{
|
|
\"tag_name\": \"latest\",
|
|
\"name\": \"El SDK (latest)\",
|
|
\"body\": \"Latest El SDK build from commit ${GITHUB_SHA}.\nBuilt $(date -u +%Y-%m-%dT%H:%M:%SZ).\",
|
|
\"draft\": false,
|
|
\"prerelease\": false
|
|
}" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
|
|
|
|
echo "Created release id=${RELEASE_ID}"
|
|
|
|
upload_asset() {
|
|
local filepath="$1"
|
|
local name="$2"
|
|
echo "Uploading ${name}..."
|
|
curl -sf -X POST \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-F "attachment=@${filepath};filename=${name}" \
|
|
"${GITEA_API}/repos/${REPO}/releases/${RELEASE_ID}/assets"
|
|
}
|
|
|
|
# Per-file assets (downstream CI needs these individually)
|
|
upload_asset lang/dist/platform/elc elc
|
|
upload_asset lang/el-compiler/runtime/el_runtime.c el_runtime.c
|
|
upload_asset lang/el-compiler/runtime/el_runtime.h el_runtime.h
|
|
|
|
# SDK bundle and installer binary
|
|
upload_asset dist/el-sdk-latest.tar.gz el-sdk-latest.tar.gz
|
|
upload_asset lang/dist/bin/el-install el-install
|
|
|
|
echo "Release published successfully"
|
|
|
|
- name: Publish El SDK to Artifact Registry (prod)
|
|
if: github.event_name == 'push'
|
|
env:
|
|
GCP_SA_KEY: ${{ secrets.GCP_SA_KEY }}
|
|
run: |
|
|
echo "${GCP_SA_KEY}" > /tmp/gcp-key.json
|
|
apt-get install -y -qq apt-transport-https ca-certificates curl
|
|
echo "deb [trusted=yes] https://packages.cloud.google.com/apt cloud-sdk main" > /etc/apt/sources.list.d/google-cloud-sdk.list
|
|
apt-get update -qq && apt-get install -y google-cloud-cli
|
|
gcloud auth activate-service-account --key-file=/tmp/gcp-key.json
|
|
gcloud config set project neuron-785695
|
|
|
|
VERSION="${GITHUB_SHA:0:8}"
|
|
|
|
gcloud artifacts generic upload \
|
|
--repository=foundation-prod \
|
|
--location=us-central1 \
|
|
--project=neuron-785695 \
|
|
--package=el-elc \
|
|
--version="${VERSION}" \
|
|
--source=dist/platform/elc
|
|
|
|
gcloud artifacts generic upload \
|
|
--repository=foundation-prod \
|
|
--location=us-central1 \
|
|
--project=neuron-785695 \
|
|
--package=el-elb \
|
|
--version="${VERSION}" \
|
|
--source=dist/bin/elb
|
|
|
|
gcloud artifacts generic upload \
|
|
--repository=foundation-prod \
|
|
--location=us-central1 \
|
|
--project=neuron-785695 \
|
|
--package=el-runtime-c \
|
|
--version="${VERSION}" \
|
|
--source=el-compiler/runtime/el_runtime.c
|
|
|
|
gcloud artifacts generic upload \
|
|
--repository=foundation-prod \
|
|
--location=us-central1 \
|
|
--project=neuron-785695 \
|
|
--package=el-runtime-h \
|
|
--version="${VERSION}" \
|
|
--source=el-compiler/runtime/el_runtime.h
|
|
|
|
gcloud artifacts generic upload \
|
|
--repository=foundation-prod \
|
|
--location=us-central1 \
|
|
--project=neuron-785695 \
|
|
--package=el-runtime-js \
|
|
--version="${VERSION}" \
|
|
--source=el-compiler/runtime/el_runtime.js
|
|
|
|
echo "Published El SDK version=${VERSION} to foundation-prod"
|
|
# Keep key alive for the ci-base rebuild step below
|
|
# (deleted in that step after docker push)
|
|
|
|
- name: Rebuild ci-base with fresh El SDK
|
|
# Patches ci-base:latest in-place: pulls the existing image (which has all
|
|
# system deps — Node, Go, gcloud, Docker CLI, etc.) and overlays the freshly
|
|
# built El SDK on top. Keeps the full ci-base rebuild fast and incremental.
|
|
if: github.event_name == 'push'
|
|
env:
|
|
GCP_SA_KEY: ${{ secrets.GCP_SA_KEY }}
|
|
run: |
|
|
set -euo pipefail
|
|
CI_BASE="us-central1-docker.pkg.dev/neuron-785695/neuron-ci/ci-base"
|
|
SHA="${GITHUB_SHA:0:8}"
|
|
|
|
echo "${GCP_SA_KEY}" > /tmp/gcp-key.json
|
|
gcloud auth activate-service-account --key-file=/tmp/gcp-key.json
|
|
gcloud config set project neuron-785695
|
|
gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
|
|
|
|
# Pull existing ci-base (system deps stay cached in the base layer)
|
|
docker pull "${CI_BASE}:latest"
|
|
|
|
# Inline Dockerfile — only replaces the El SDK layer
|
|
cat > /tmp/Dockerfile.ci-base-patch << 'EOF'
|
|
ARG BASE
|
|
FROM ${BASE}
|
|
COPY dist/platform/elc /opt/el/dist/platform/elc
|
|
COPY dist/bin/elb /opt/el/dist/bin/elb
|
|
COPY el-compiler/runtime/el_runtime.c /opt/el/el-compiler/runtime/el_runtime.c
|
|
COPY el-compiler/runtime/el_runtime.h /opt/el/el-compiler/runtime/el_runtime.h
|
|
COPY el-compiler/runtime/el_runtime.js /opt/el/el-compiler/runtime/el_runtime.js
|
|
RUN chmod +x /opt/el/dist/platform/elc /opt/el/dist/bin/elb
|
|
EOF
|
|
|
|
docker build \
|
|
--build-arg BASE="${CI_BASE}:latest" \
|
|
--build-arg BUILDKIT_INLINE_CACHE=1 \
|
|
-f /tmp/Dockerfile.ci-base-patch \
|
|
-t "${CI_BASE}:latest" \
|
|
-t "${CI_BASE}:${SHA}" \
|
|
.
|
|
|
|
docker push "${CI_BASE}:latest"
|
|
docker push "${CI_BASE}:${SHA}"
|
|
|
|
echo "ci-base rebuilt: ${CI_BASE}:latest (${SHA})"
|
|
rm -f /tmp/gcp-key.json
|
|
|
|
- name: Dispatch el-sdk-updated to downstream repos
|
|
if: github.event_name == 'push'
|
|
env:
|
|
GITEA_TOKEN: ${{ secrets.GIT_TOKEN }}
|
|
GITEA_API: https://git.neuralplatform.ai/api/v1
|
|
run: |
|
|
for repo in neuron-technologies/forge neuron-technologies/neuron-web; do
|
|
curl -sf -X POST \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
"${GITEA_API}/repos/${repo}/dispatches" \
|
|
-d "{
|
|
\"type\": \"el-sdk-updated\",
|
|
\"inputs\": {\"el_version\": \"latest\", \"commit\": \"${GITHUB_SHA}\"}
|
|
}" && echo "Dispatched to ${repo}" || echo "Warning: dispatch to ${repo} failed"
|
|
done
|