Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 70 additions & 95 deletions .github/workflows/cpp-compilation-test.yml
Original file line number Diff line number Diff line change
@@ -1,109 +1,84 @@
# DISABLED: C++ Compilation Service Tests
# To enable: remove the comment above and uncomment the 'on:' section below

name: C++ Compilation Service Tests

# on:
# push:
# branches: [ main, cpp-compilation-feature ]
# pull_request:
# branches: [ main ]
on:
push:
branches: [ tree-structure-clean ]

jobs:
test-cpp-compilation:
build-and-test:
runs-on: ubuntu-latest

services:
docker:
image: docker:dind
options: --privileged
timeout-minutes: 20
permissions:
contents: read
packages: write
id-token: write

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '18'

- name: Install dependencies
run: |
npm install
npm install socket.io-client

- name: Build SDV Runtime container
run: |
docker build \
--tag sdv-runtime-production:latest \
--progress=plain .

- name: Start SDV Runtime container
run: |
mkdir -p docker-output
docker run -d \
--name sdv-runtime-container \
--publish 3090:3090 \
--volume "$(pwd)/docker-output:/home/dev/data/output" \
sdv-runtime-production:latest

- name: Wait for container to be ready
run: |
echo "Waiting for SDV Runtime to start..."
for i in {1..30}; do
if curl -f http://localhost:3090 >/dev/null 2>&1; then
echo "SDV Runtime is ready!"
break
fi
echo "Attempt $i/30: Still waiting..."
sleep 2
done

# Verify container is running
docker ps | grep sdv-runtime-container
docker logs sdv-runtime-container

- name: Run automated test suite
run: |
chmod +x test/ci/automated-test-suite.js
node test/ci/automated-test-suite.js
env:
SDV_SERVER_URL: http://localhost:3090
TEST_TIMEOUT: 60000

- name: Run individual tests
run: |
echo "Running connection test..."
timeout 15 node test/scripts/connection-test.js

echo "Running basic compilation test..."
timeout 30 node test/scripts/basic-test.js

echo "Running multi-file test..."
timeout 45 node test/02-multi-file/test-multifile.js

- name: Check generated executables
submodules: recursive

- name: Verify submodules
run: |
echo "Checking generated executables..."
ls -la docker-output/
if [ -n "$(ls -A docker-output/)" ]; then
echo "✅ Executables generated successfully"
file docker-output/app_* | head -3
else
echo "❌ No executables found"
exit 1
echo "Checking submodules..."
git submodule status
if [ ! -d "vehicle_signal_specification" ] || [ ! -d "vehicle-model-generator" ]; then
echo "Submodules not found, initializing..."
git submodule update --init --recursive
fi
ls -la vehicle_signal_specification/ || echo "VSS submodule missing"
ls -la vehicle-model-generator/ || echo "Vehicle model generator submodule missing"

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=ref,event=branch,prefix=cpp-test-
type=raw,value=cpp-test-latest,enable=${{ github.ref == 'refs/heads/tree-structure-clean' }}

- name: Container logs (on failure)
if: failure()
run: |
echo "=== Container Logs ==="
docker logs sdv-runtime-container
echo "=== Container Status ==="
docker ps -a | grep sdv-runtime

- name: Cleanup
if: always()
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
BUILD_DATE=${{ github.event.head_commit.timestamp }}
VCS_REF=${{ github.sha }}
VERSION=cpp-test-${{ github.sha }}

- name: Generate build summary
run: |
docker stop sdv-runtime-container || true
docker rm sdv-runtime-container || true
echo "## 🐳 C++ Test Package Built Successfully" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Docker Images:" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "${{ steps.meta.outputs.tags }}" | tr ',' '\n' >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Build Info:" >> $GITHUB_STEP_SUMMARY
echo "- **Branch**: ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
echo "- **Commit**: ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
echo "- **Author**: ${{ github.actor }}" >> $GITHUB_STEP_SUMMARY
echo "- **Message**: ${{ github.event.head_commit.message }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Pull Image:" >> $GITHUB_STEP_SUMMARY
echo '```bash' >> $GITHUB_STEP_SUMMARY
echo "docker pull ghcr.io/${{ github.repository }}:cpp-test-${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ data/custom-models/

# C++ Compilation Output
docker-output/
output/
node_modules/
69 changes: 51 additions & 18 deletions Kit-Manager/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,12 +301,58 @@ io.on('connection', (socket) => {
io.to(payload.request_from).emit('messageToKit-kitReply', payload)
})

// Native tree structure file writer
async function writeTreeStructure(items, baseDir, socket) {
for (const item of items) {
if (item.type === 'file' && item.content !== undefined) {
const filePath = path.join(baseDir, item.name);
const fileDir = path.dirname(filePath);
await fs.promises.mkdir(fileDir, { recursive: true });
await fs.promises.writeFile(filePath, item.content, 'utf8');

await socket.emit("compile_cpp_reply", {
"status": "file-written",
"result": `Written file: ${item.name}\r\n`,
"cmd": "compile_cpp",
"data": "",
"isDone": false,
"code": 0
});
} else if (item.type === 'folder' && item.items) {
const folderPath = path.join(baseDir, item.name);
await fs.promises.mkdir(folderPath, { recursive: true });
await writeTreeStructure(item.items, folderPath, socket);
}
}
}

// ============ C++ COMPILATION SERVICE ============
socket.on('compile_cpp', async (data) => {
if(!data["files"] || !data["app_name"]) {
// Only support tree structure format
if(!data.files || !Array.isArray(data.files) || !data["app_name"]) {
socket.emit('compile_cpp_reply', {
"status": "err: invalid",
"result": "Invalid request, missing files or app_name\r\n",
"result": "Invalid request. Only tree structure format supported. Expected files as array with type/name/content objects.\r\n",
"cmd": "compile_cpp",
"data": "",
"isDone": true,
"code": 1
})
return
}

// Validate tree structure has files
function hasFiles(items) {
return items.some(item =>
item.type === 'file' ||
(item.type === 'folder' && item.items && hasFiles(item.items))
);
}

if(!hasFiles(data.files)) {
socket.emit('compile_cpp_reply', {
"status": "err: invalid",
"result": "No valid files found in tree structure\r\n",
"cmd": "compile_cpp",
"data": "",
"isDone": true,
Expand Down Expand Up @@ -341,7 +387,7 @@ io.on('connection', (socket) => {
return
}

// Write C++ files
// Write C++ files using native tree structure
try {
try {
if (fs.promises.rm) {
Expand All @@ -358,21 +404,8 @@ io.on('connection', (socket) => {
}
await fs.promises.mkdir(`${app_dir}/app/src`, { recursive: true });

for (const [filename, content] of Object.entries(data.files)) {
const filePath = path.join(`${app_dir}/app/src`, filename);
const fileDir = path.dirname(filePath);
await fs.promises.mkdir(fileDir, { recursive: true });
await fs.promises.writeFile(filePath, content, 'utf8');

socket.emit("compile_cpp_reply", {
"status": "file-written",
"result": `Written file: ${filename}\r\n`,
"cmd": "compile_cpp",
"data": "",
"isDone": false,
"code": 0
})
}
// Write files directly from tree structure
await writeTreeStructure(data.files, `${app_dir}/app/src`, socket);

const cmakeContent = `set(TARGET_NAME "app")

Expand Down
Loading