Skip to content

Commit 71be74b

Browse files
authored
Merge pull request #2 from 5GRealityLab/feat/starter-kit
feat: initial release of V2X J2735 codec with Python & Node.js bindings
2 parents bd78547 + 5f3275d commit 71be74b

2,320 files changed

Lines changed: 12843 additions & 5 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci-release.yml

Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
name: Core CI & Release
2+
3+
on:
4+
push:
5+
branches: [main]
6+
tags: ['v*']
7+
pull_request:
8+
branches: [main]
9+
10+
jobs:
11+
verify-version:
12+
name: Verify Version Match
13+
if: startsWith(github.ref, 'refs/tags/v')
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v4
17+
- run: |
18+
TAG_VERSION=${GITHUB_REF_NAME#v}
19+
FILE_VERSION=$(cat VERSION)
20+
if [[ "$TAG_VERSION" != "$FILE_VERSION"* ]]; then
21+
echo "::error::Version Mismatch! Tag '$TAG_VERSION' vs VERSION '$FILE_VERSION'"
22+
exit 1
23+
fi
24+
25+
build-core:
26+
name: Build WASM Core
27+
runs-on: ubuntu-latest
28+
steps:
29+
- uses: actions/checkout@v4
30+
- name: Cache Emscripten
31+
id: cache-emsdk
32+
uses: actions/cache@v4
33+
with:
34+
path: emsdk
35+
key: ${{ runner.os }}-emsdk-4.0.10
36+
- name: Install Emscripten
37+
if: steps.cache-emsdk.outputs.cache-hit != 'true'
38+
run: |
39+
git clone https://github.com/emscripten-core/emsdk.git
40+
cd emsdk && ./emsdk install 4.0.10 && ./emsdk activate 4.0.10
41+
- name: Compile
42+
run: |
43+
source emsdk/emsdk_env.sh
44+
cd j2735codec
45+
make wasm
46+
# Create __init__.py files
47+
touch bindings/python/src/j2735codec/generated/__init__.py
48+
touch bindings/python/src/j2735codec/protobuf/__init__.py
49+
50+
- name: Upload Python Artifacts
51+
uses: actions/upload-artifact@v4
52+
with:
53+
name: python-wasm-binaries
54+
# Use the parent directory to ensure the j2735codec folder structure is preserved
55+
path: j2735codec/bindings/python/src/j2735codec/
56+
include-hidden-files: true
57+
58+
- name: Upload Node Artifacts
59+
uses: actions/upload-artifact@v4
60+
with:
61+
name: node-wasm-binaries
62+
path: j2735codec/bindings/node/src/generated/
63+
64+
test-bindings:
65+
name: Test ${{ matrix.binding }}
66+
needs: build-core
67+
runs-on: ubuntu-latest
68+
strategy:
69+
fail-fast: false
70+
matrix:
71+
binding: [python, node]
72+
steps:
73+
- uses: actions/checkout@v4
74+
75+
- name: Download Artifacts
76+
uses: actions/download-artifact@v4
77+
with:
78+
name: ${{ matrix.binding }}-wasm-binaries
79+
path: j2735codec/bindings/${{ matrix.binding }}/${{ matrix.binding == 'python' && 'src/j2735codec/' || 'src/generated/' }}
80+
81+
- name: Repair and Verify Structure
82+
run: |
83+
if [ "${{ matrix.binding }}" == "python" ]; then
84+
cd j2735codec/bindings/python/src/j2735codec
85+
touch __init__.py generated/__init__.py protobuf/__init__.py
86+
echo "🔍 Verifying Python Structure:"
87+
ls -R
88+
fi
89+
90+
- name: Setup & Test
91+
run: |
92+
if [ "${{ matrix.binding }}" == "python" ]; then
93+
pip install uv
94+
cd j2735codec/bindings/python
95+
uv sync --reinstall-package j2735codec
96+
uv run pytest tests -s
97+
else
98+
npm install
99+
npm run build -w j2735codec
100+
npm test -w j2735codec
101+
fi
102+
103+
publish-release:
104+
name: Publish Release
105+
needs: [verify-version, test-bindings]
106+
if: startsWith(github.ref, 'refs/tags/v')
107+
runs-on: ubuntu-latest
108+
permissions:
109+
contents: write
110+
steps:
111+
- uses: actions/checkout@v4
112+
113+
- name: Download Artifacts
114+
uses: actions/download-artifact@v4
115+
with:
116+
path: artifacts
117+
118+
- name: Build & Stage Assets
119+
run: |
120+
STAGING="$GITHUB_WORKSPACE/dist_release"
121+
mkdir -p "$STAGING"
122+
VERSION=$(cat VERSION)
123+
124+
# --- 2. Build Python Bindings ---
125+
PY_DIR="j2735codec/bindings/python"
126+
127+
# Clean and Recreate Structure
128+
mkdir -p "$PY_DIR/src/j2735codec/generated"
129+
mkdir -p "$PY_DIR/src/j2735codec/protobuf"
130+
131+
# Copy artifacts - using '.' to ensure we copy contents into the pre-made folders
132+
cp -a artifacts/python-wasm-binaries/. "$PY_DIR/src/j2735codec/"
133+
134+
# RE-INJECT Package Markers (Vital for Wheel packaging)
135+
touch "$PY_DIR/src/j2735codec/__init__.py"
136+
touch "$PY_DIR/src/j2735codec/generated/__init__.py"
137+
touch "$PY_DIR/src/j2735codec/protobuf/__init__.py"
138+
139+
# Debug: Log the tree to the console so we can see what's happening
140+
echo "📂 Final Python Build Tree:"
141+
ls -R "$PY_DIR/src/j2735codec/"
142+
143+
cp LICENSE "$PY_DIR/"
144+
cp NOTICE "$PY_DIR/"
145+
146+
pip install uv
147+
cd "$PY_DIR"
148+
uv build --wheel --out-dir ./dist_local
149+
150+
# Verify Wheel Contents before moving (Security Check)
151+
WHL_FILE=$(ls ./dist_local/*.whl)
152+
if ! unzip -l "$WHL_FILE" | grep -q "j2735codec/generated/j2735codec.wasm"; then
153+
echo "::error::WASM file missing from generated wheel!"
154+
exit 1
155+
fi
156+
157+
for f in ./dist_local/*; do cp "$f" "$STAGING/$(basename $f)"; done
158+
cd "$GITHUB_WORKSPACE"
159+
160+
# --- 3. Build Node Bindings ---
161+
JS_DIR="j2735codec/bindings/node"
162+
mkdir -p "$JS_DIR/src/generated/"
163+
cp -a artifacts/node-wasm-binaries/. "$JS_DIR/src/generated/"
164+
cp LICENSE "$JS_DIR/"
165+
cp NOTICE "$JS_DIR/"
166+
npm install
167+
npm run build -w j2735codec
168+
cd "$JS_DIR" && npm pack
169+
for f in *.tgz; do cp "$f" "$STAGING/$f"; done
170+
cd "$GITHUB_WORKSPACE"
171+
172+
# --- 4. Package Python Samples ---
173+
SAMPLE_DIR="etx/examples/python"
174+
if [ -d "$SAMPLE_DIR" ]; then
175+
cp LICENSE "$SAMPLE_DIR/"
176+
cp NOTICE "$SAMPLE_DIR/"
177+
178+
# Inject the language wrapper (the wheel)
179+
mkdir -p "$SAMPLE_DIR/j2735codec"
180+
cp "$STAGING"/*.whl "$SAMPLE_DIR/j2735codec/"
181+
182+
cd "$SAMPLE_DIR"
183+
VERSION=$(cat "$GITHUB_WORKSPACE/VERSION")
184+
ZIP_NAME="python-etx-samples-$VERSION.zip"
185+
zip -r "$STAGING/$ZIP_NAME" . \
186+
-x "*config.json" -x "*/.venv/*" -x "*.venv*" -x "*/.env*" -x "*/__pycache__/*"
187+
cd "$GITHUB_WORKSPACE"
188+
fi
189+
190+
# --- 5. Package Node/TS Samples ---
191+
NODE_SAMPLE_DIR="etx/examples/node"
192+
if [ -d "$NODE_SAMPLE_DIR" ]; then
193+
VERSION=$(cat "$GITHUB_WORKSPACE/VERSION")
194+
PKG_STAGING="$GITHUB_WORKSPACE/node_pkg_temp"
195+
mkdir -p "$PKG_STAGING"
196+
197+
# 1. Copy the source (leaves your repo untouched)
198+
cp -r "$NODE_SAMPLE_DIR"/. "$PKG_STAGING/"
199+
200+
# 2. Rewrite the path to the PORTABLE local path
201+
# This changes the monorepo path to the ZIP-friendly path
202+
sed -i "s|\"j2735codec\": \".*\"|\"j2735codec\": \"file:./j2735codec/j2735codec-$VERSION.tgz\"|g" "$PKG_STAGING/package.json"
203+
204+
# 3. Inject the tarball into the staging area
205+
mkdir -p "$PKG_STAGING/j2735codec"
206+
cp "$STAGING"/j2735codec-$VERSION.tgz "$PKG_STAGING/j2735codec/"
207+
208+
# 4. GENERATE THE LOCKFILE HERE
209+
# This lockfile will now contain the correct, portable reference to the codec
210+
cd "$PKG_STAGING"
211+
npm install --package-lock-only --no-workspaces
212+
213+
# 5. ZIP EVERYTHING
214+
# Now the ZIP contains a package.json and a package-lock.json
215+
# that both point to the local ./j2735codec folder.
216+
ZIP_NAME="node-etx-samples-$VERSION.zip"
217+
zip -r "$STAGING/$ZIP_NAME" . -x "node_modules/*" "dist/*"
218+
219+
# We zip EVERYTHING (*) in this folder, excluding ONLY the junk
220+
zip -r "$STAGING/$ZIP_NAME" . \
221+
-x "certs/*" "dist/*" "node_modules/*" "config.json" ".env*" "npm-debug.log*"
222+
223+
cd "$GITHUB_WORKSPACE"
224+
rm -rf "$PKG_STAGING"
225+
fi
226+
227+
# --- 6. Finalize Staging ---
228+
cp "$PY_DIR/src/j2735codec/generated/j2735codec.wasm" "$STAGING/j2735codec-$VERSION.wasm"
229+
cp LICENSE "$STAGING/"
230+
cp NOTICE "$STAGING/"
231+
232+
# --- 7. FIXED Safe Cleanup ---
233+
echo "🧹 Performing final cleanup..."
234+
# Do NOT use -delete on a broad glob. Delete specific files.
235+
rm -f "$STAGING"/.DS_Store
236+
rm -f "$STAGING"/.env
237+
rm -f "$STAGING"/default.gitignore
238+
239+
echo "✅ Contents of $STAGING for release:"
240+
ls -la "$STAGING"
241+
242+
- name: Create GitHub Release
243+
uses: softprops/action-gh-release@v2
244+
with:
245+
name: "Release ${{ github.ref_name }}"
246+
files: dist_release/*
247+
generate_release_notes: true

.gitignore

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# =============================================================================
2+
# Verizon ETX Starter Kit - Master Gitignore
3+
# =============================================================================
4+
5+
# --- System & Editor Files ---
6+
.DS_Store
7+
Thumbs.db
8+
*.swp
9+
*.swo
10+
.vscode/*
11+
!.vscode/extensions.json
12+
.idea/
13+
.vs/
14+
*.sln
15+
*.vcxproj
16+
*.user
17+
18+
# --- General Build Artifacts ---
19+
# Catches all C++, Python, and Node build directories
20+
build/
21+
build_*/
22+
_build/
23+
out/
24+
dist/
25+
bin/
26+
*.tgz
27+
*.tsbuildinfo
28+
29+
# --- C++ / CMake / WASM Tooling ---
30+
CMakeCache.txt
31+
CMakeFiles/
32+
CMakeScripts/
33+
cmake_install.cmake
34+
install_manifest.txt
35+
CMakeUserPresets.json
36+
vcpkg_installed/
37+
.cmake/
38+
cmake-build-*/
39+
40+
# Compiled Binaries
41+
*.o
42+
*.obj
43+
*.so
44+
*.a
45+
*.lib
46+
*.dll
47+
*.exe
48+
*.dylib
49+
*.wasm
50+
*.js.mem
51+
52+
# --- Python (Onboarding & Bindings) ---
53+
.venv/
54+
__pycache__/
55+
*.py[cod]
56+
*$py.class
57+
*.egg-info/
58+
.hatch/
59+
.pytest_cache/
60+
.mypy_cache/
61+
.ruff_cache/
62+
.coverage
63+
htmlcov/
64+
65+
# --- Node.js (Onboarding & Bindings) ---
66+
node_modules/
67+
.npm/
68+
npm-debug.log*
69+
yarn-debug.log*
70+
yarn-error.log*
71+
.eslintcache
72+
73+
# --- Project Specific Patterns ---
74+
# Explicitly ignoring generated WASM and metadata in specific subfolders
75+
**/generated/*
76+
77+
# --- Environment & Secrets ---
78+
# Never commit ETX credentials or local environment configs
79+
.env
80+
.env.local
81+
.env.*.local
82+
logs/
83+
*.log
84+
config.json
85+
certs/
86+
87+
# =============================================================================

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
v22.16.0

.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.9

CONTRIBUTING.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
# Contributing to J2735 Codec
2-
3-
Thank you for helping improve the J2735 Codec. To maintain code quality and history, please follow these guidelines.
4-
51
## 🌿 Branching Strategy
62
We follow a **Feature Branch** workflow. All development must occur on branches and be merged into `main` via Pull Request.
73

Makefile

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
BINDING_PY = j2735codec/bindings/python
2+
BINDING_JS = j2735codec/bindings/node
3+
SAMPLE_PY = etx/examples/python
4+
SAMPLE_JS = etx/examples/node
5+
VERSION ?= $(shell cat VERSION 2>/dev/null || echo "0.1.0")
6+
7+
sync-version:
8+
@echo "🔄 Syncing version $(VERSION) to manifests..."
9+
@# Update Root CMake
10+
@perl -i -pe 's/VERSION\s+"[0-9.]+"/VERSION "$(VERSION)"/gi' j2735codec/CMakeLists.txt
11+
12+
@# Update Node manifests
13+
@npm version $(VERSION) --no-git-tag-version --allow-same-version || true
14+
@cd $(BINDING_JS) && npm version $(VERSION) --no-git-tag-version --allow-same-version || true
15+
@cd $(SAMPLE_JS) && npm version $(VERSION) --no-git-tag-version --allow-same-version || true
16+
17+
@# Update Python manifests (root, binding, sample)
18+
@perl -i -pe 's/^version\s*=\s*"[0-9.]*"/version = "$(VERSION)"/m' pyproject.toml
19+
@perl -i -pe 's/^version\s*=\s*"[0-9.]*"/version = "$(VERSION)"/m' $(BINDING_PY)/pyproject.toml
20+
@perl -i -pe 's/^version\s*=\s*"[0-9.]*"/version = "$(VERSION)"/m' $(SAMPLE_PY)/pyproject.toml
21+
22+
@echo "✅ Version $(VERSION) synced across 6 manifests and CMake."

0 commit comments

Comments
 (0)