Skip to content
Open
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
126 changes: 126 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Changelog

All notable changes to ServiceMaker will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

#### Node.js/Foxx Service Support
- **Node.js Base Image**: Added `Dockerfile.node22base` for Node.js 22 base image with pre-installed packages
- Installs Node.js 22 from NodeSource
- Pre-installs ArangoDB packages: `@arangodb/node-foxx`, `@arangodb/node-foxx-launcher`, `@arangodb/arangodb`
- Pre-installs standard packages with version pinning: `lodash`, `dayjs`, `uuid`, `dotenv`, `axios`, `joi`, `winston`, `async`, `jsonwebtoken`, `bcrypt`, `semver`
- Creates base `node_modules` at `/home/user/node_modules` with checksums for dependency tracking
- Base image is immutable and pre-scanned for security vulnerabilities
- Added to `baseimages/imagelist.txt` as `node22base`

- **Node.js Dockerfile Template**: Created `Dockerfile.nodejs.template` for building Node.js/Foxx service images
- Copies service directory directly to `/project/{service-name}/`
- Configures working directory and user permissions
- Sets NODE_PATH environment variable for module resolution
- Executes `prepareproject-nodejs.sh` for dependency management

- **Dependency Management Script**: Added `scripts/prepareproject-nodejs.sh` and `scripts/check-base-dependencies.js`
- Base `node_modules` at `/home/user/node_modules` is immutable and never copied
- Pre-install check: `check-base-dependencies.js` analyzes project dependencies against base packages
- Version compatibility: Uses `semver` to verify if base package versions satisfy project requirements
- Avoids duplication: Only installs packages that are missing or have incompatible versions
- Uses NODE_PATH for module resolution (project first, then base)
- Verifies `node-foxx` binary accessibility from either location
- Keeps base image immutable for security scanning
- Results in smaller project `node_modules` and `project.tar.gz` files

- **Project Type Detection**: Extended `detect_project_type()` to support:
- `python`: Projects with `pyproject.toml`
- `foxx`: Multi-service projects with `package.json` and `services.json` (both required)
- `foxx-service`: Single service directory with `package.json` only (auto-generates `services.json`)
- Execution stops with error if `services.json` is missing for Node.js projects

- **Service Structure Generation**: Simplified structure for single service directories
- Copies service directory directly to `/project/{service-name}/` (no wrapper folder)
- Generates `services.json` automatically with mount path "/" and basePath "." in the service directory
- `package.json` and `services.json` are in the same directory where `node_modules` will be created

- **Services JSON Generation**: Added `generate_services_json()` function
- Automatically generates `services.json` for single service directories (`foxx-service` type)
- Configures mount path as "/" (routing handled by Helm chart at deployment)
- Sets basePath to "." (relative to WORKDIR where `node-foxx` runs)

- **Package.json Support**: Added functions to read Node.js project metadata
- `read_name_from_package_json()`: Extracts project name from `package.json`
- `read_service_info_from_package_json()`: Extracts name and version for Helm charts

- **Entrypoint Enhancement**: Updated `baseimages/scripts/entrypoint.sh` to support Node.js/Foxx services
- Detects Foxx services by checking for both `package.json` and `services.json`
- Automatically runs `node-foxx` for Foxx services (checks project `node_modules` first, then base)
- Only supports Foxx services (requires both `package.json` and `services.json`)
- Maintains backward compatibility with Python services

- **Test Service**: Added `itzpapalotl-node` test service in `testprojects/`
- Example Node.js/Foxx service for testing ServiceMaker functionality
- Demonstrates service structure generation and dependency management

### Changed

- **Main Application Logic**: Extended `src/main.rs` to support Node.js/Foxx projects
- Added project type detection requiring both `package.json` and `services.json` for `foxx` type
- Error handling: execution stops if `services.json` is missing for Node.js projects
- Simplified file copying: projects are copied as-is (no wrapper structure generation)
- Base image default handling: Introduced compile-time constants (`DEFAULT_PYTHON_BASE_IMAGE`, `DEFAULT_NODEJS_BASE_IMAGE`)
- Explicit user intent tracking: Changed `base_image` to `Option<String>` to detect explicit user choices
- Smart defaults: Only sets project-type-specific defaults when user hasn't explicitly set base image
- Modified Dockerfile generation to use Node.js template for Foxx projects
- Updated Helm chart generation to support Node.js/Foxx projects
- Added `prepareproject-nodejs.sh` and `check-base-dependencies.js` to embedded scripts list
- No entrypoint required for Foxx services (uses `node-foxx` from base image)

- **Entrypoint Script**: Enhanced `baseimages/scripts/entrypoint.sh` to support Node.js/Foxx services
- Added service type detection based on project files
- Maintains backward compatibility with Python services

- **Base Image List**: Updated `baseimages/imagelist.txt` to include `node22base`

- **File Copying Logic**: Updated `copy_dir_recursive()` to skip `node_modules` directories
- Prevents copying local `node_modules` which should be installed in Docker build
- Ensures only project source code is copied, dependencies are installed fresh in Docker

### Fixed

- **Windows Compatibility**: Fixed Windows build issues in `src/main.rs`
- Added conditional compilation for Unix-specific file permissions (`#[cfg(unix)]`)
- Windows builds now skip `set_mode()` calls that are Unix-only

### Technical Details
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the technical details a re not needed in the Changelog. They should be somewhere, but here, we would like to at most have a link to that other place.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technical details are moved to docs/ARCHITECTURE.md and link to that file is placed here


For detailed information about base image structure, service architecture, and module resolution, see [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md).

## [0.9.2] - Previous Release

### Existing Features
- Python service support with `pyproject.toml`
- Base image management for Python 3.13
- Docker image building and pushing
- Helm chart generation
- Project tar.gz creation
- Virtual environment management with `uv`

---

## Version History

- **0.9.2**: Initial release with Python support
- **Unreleased**: Added Node.js/Foxx service support

---

## Notes

- All changes maintain backward compatibility with existing Python projects
- Node.js support is additive and does not affect Python service functionality
- Base images must be built separately using `baseimages/build.sh`
- Windows users should use WSL or Linux environment for building base images

24 changes: 24 additions & 0 deletions Dockerfile.nodejs.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
FROM {BASE_IMAGE}

USER root

COPY ./scripts /scripts
COPY {PROJECT_DIR} /project/{PROJECT_DIR}
RUN chown -R user:user /project/{PROJECT_DIR}

USER user
WORKDIR /project/{WORKDIR}

# Set NODE_PATH to resolve from project node_modules first, then base node_modules
# This allows npm to install only missing/incompatible packages in project directory
# while still accessing base packages from /home/user/node_modules
ENV NODE_PATH={NODE_PATH}

RUN /scripts/prepareproject-nodejs.sh

EXPOSE {PORT}

# Run node-foxx from current directory (wrapper or project root)
# Use base node-foxx binary (guaranteed to exist), NODE_PATH handles module resolution
CMD ["/home/user/node_modules/.bin/node-foxx"]

46 changes: 46 additions & 0 deletions baseimages/Dockerfile.node22base
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
FROM debian:trixie-slim

COPY ./scripts /scripts
RUN /scripts/debinstall.sh

# Install Node.js 22
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \
apt-get install -y nodejs && \
apt-get clean

WORKDIR /home/user
USER user

# Create base node_modules with standard packages (immutable, pre-scanned)
# This location is used by all projects and should never be modified
# Standard packages are selected to benefit most projects while keeping image size reasonable
RUN npm init -y && \
npm install \
# ArangoDB/Foxx core
@arangodb/node-foxx@^0.0.1-alpha.0 \
@arangodb/node-foxx-launcher@^0.0.1-alpha.0 \
@arangodb/arangodb@^0.0.1-alpha.0 \
# Dependency checking utility
semver@^7.6.3 \
# Essential utilities
lodash@^4.17.21 \
dayjs@^1.11.10 \
uuid@^9.0.1 \
dotenv@^16.4.5 \
# HTTP clients
axios@^1.7.2 \
# Validation
joi@^17.13.3 \
# Logging
winston@^3.15.0 \
# Async utilities
async@^3.2.5 \
# Security
jsonwebtoken@^9.0.2 \
bcrypt@^5.1.1

# Create checksums for base node_modules (for tracking, base remains immutable)
RUN find node_modules -type f -print0 | \
xargs -0 sha256sum > sums_sha256

CMD [ "/scripts/entrypoint.sh" ]
1 change: 1 addition & 0 deletions baseimages/imagelist.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
py13base
py13cugraph
py13torch
node22base
32 changes: 25 additions & 7 deletions baseimages/scripts/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,34 @@ if test -e project.tar.gz ; then
tar xzvf project.tar.gz > /dev/null
fi

# Run the entrypoint if configured:
# Detect service type and run accordingly
if test -e entrypoint ; then
ENTRYPOINT=$(cat entrypoint)
echo Running project ...
. /home/user/.local/bin/env
. /home/user/the_venv/bin/activate
for p in /project/the_venv/lib/python*/site-packages ; do
export PYTHONPATH=$p
done
exec python $ENTRYPOINT

# Check if it's a Node.js/Foxx service (requires both package.json and services.json)
if [ -f "package.json" ] && [ -f "services.json" ]; then
# Node.js/Foxx service
echo "Detected Node.js/Foxx service"
if [ -f "node_modules/.bin/node-foxx" ]; then
exec node_modules/.bin/node-foxx
elif [ -f "/home/user/node_modules/.bin/node-foxx" ]; then
# Fallback to base node-foxx binary
exec /home/user/node_modules/.bin/node-foxx
else
echo "Error: node-foxx not found. Make sure node_modules are installed."
exit 1
fi
else
# Python service (existing logic)
echo "Detected Python service"
. /home/user/.local/bin/env
. /home/user/the_venv/bin/activate
for p in /project/the_venv/lib/python*/site-packages ; do
export PYTHONPATH=$p
done
exec python $ENTRYPOINT
fi
fi

echo No entrypoint found, running bash instead...
Expand Down
Loading