Openship runBuildPipeline Clone Install Build Steps: Inside the Build Pipeline

Openship's runBuildPipeline() orchestrates a strict three-phase sequence—clone, install, and build—through the BuildEnvironment abstraction, wrapping each phase in logger.runStep() for structured observability and returning a final {status, durationMs} result.

The oblien/openship repository is an open-source deployment platform that powers Docker Compose, bare-host, and cloud runtimes from a single control-plane codebase. Understanding the runBuildPipeline clone install build steps is critical for debugging deployments, extending adapters, or self-hosting the platform.

Build Pipeline Architecture

According to packages/adapters/docs/BUILD-PIPELINE.md lines 5-22, the build service instantiates a BuildLogger and invokes the active runtime's build(config, logger) method. The pipeline remains runtime-agnostic because the BuildEnvironment abstracts all command execution through exec and streamExec. This lets the same clone-install-build logic execute on a local shell, over remote SSH, or inside a Docker container without code changes.

The Three Steps of runBuildPipeline

Clone

The pipeline begins by fetching the application source. It executes git clone … via BuildEnvironment.exec, which automatically resolves the correct transport layer—local shell, remote SSH, or Docker—based on the active runtime configuration. This is the first operation in the build flow described in packages/adapters/docs/BUILD-PIPELINE.md.

Install

Once the repository is available, the pipeline detects the project's package manager. It supports npm, yarn, and pnpm, then runs the appropriate install command through the executor. Dependencies must resolve successfully before the pipeline proceeds to the compilation phase.

Build

If the project configuration defines a buildCommand, the pipeline executes it as the final step. The entire sequence returns {status: "deploying" | "failed", durationMs} and persists all output through BuildLogger. As documented in packages/adapters/docs/BUILD-PIPELINE.md lines 5-22, each step is wrapped in logger.runStep(), providing the single source of truth for real-time dashboard stepper updates and SSE log streaming.

Runtime-Specific Build Transports

Each runtime implements the build(config, logger) interface, but the transport mechanism differs:

  • CloudRuntime — Calls Oblien API: workspace.build() followed by execAndStream(). Remote containers and TLS are handled by the Oblien cloud edge.
  • BareRuntime — Uses executor.streamExec() inside runBuildPipeline(). Commands run directly on the host or over SSH, making this the path for local and self-managed servers.
  • DockerRuntime — Exists as a stub in the current source. It is intended to run Dockerfile builds natively, but the full implementation is not yet complete.

These architectures are detailed in packages/adapters/docs/ARCHITECTURE.md.

Process Management and Logging

Every step emits structured output through the BuildLogger. The logger.runStep() wrapper feeds live logs to the UI and ensures the dashboard stepper stays synchronized with the actual build state.

For bare-mode deployments, the deploy step spawns the application with setsid nohup npm start & to create a new process group. The resulting PID is written to .pids/{deploymentId}.pid, while application logs are written to .logs/{deploymentId}.log. When stopping a deployment, Openship reads the PID file and issues kill -<pgid>—first SIGTERM, then SIGKILL—to terminate the entire process tree cleanly. The full sequence is documented in packages/adapters/docs/BUILD-PIPELINE.md lines 78-106.

Practical Build and Deploy Examples

Run a Local Bare-Mode Deployment


# Install the CLI (bundles API + dashboard)

curl -fsSL https://get.openship.io | sh

# Initialize and deploy the current project

cd my-app
openship init
openship deploy

The openship deploy command triggers runBuildPipeline() using the same code path across Linux, macOS, and Windows.

Start the Full Docker Compose Stack

git clone https://github.com/oblien/openship.git && cd openship
cp .env.example .env
docker compose -f docker/docker-compose.yml up -d

This launches Postgres, Redis, API, Dashboard, and Edge containers. The edge service listens on :80 and :443, writes reverse-proxy vhosts, and obtains Let's Encrypt certificates automatically.

Trigger a Cloud Runtime Build via REST

curl -X POST https://api.openship.io/v1/workspaces/<ws>/build \
     -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"repo":"git@github.com:user/repo.git","branch":"main"}'

This initiates the CloudRuntime build flow, which calls workspace.build() internally and streams logs back to the client via SSE.

Summary

  • Openship's build pipeline executes a fixed three-step flow: clone, install, and build.
  • runBuildPipeline() delegates to BuildEnvironment.exec and executor.streamExec(), making the pipeline portable across bare metal, cloud, and Docker runtimes.
  • Each phase is wrapped in logger.runStep() for live dashboard updates and persistent BuildLogger output.
  • BareRuntime manages application lifecycle through setsid, .pids/{deploymentId}.pid, and .logs/{deploymentId}.log.
  • CloudRuntime delegates container builds to the Oblien API, while DockerRuntime remains a stub for future Dockerfile-native builds.

Frequently Asked Questions

How does Openship detect which package manager to use during the install step?

The pipeline inspects the cloned repository for lockfiles and automatically selects npm, yarn, or pnpm. It then invokes the corresponding install command through the active BuildEnvironment executor before proceeding to the build phase.

What happens if a step fails inside runBuildPipeline()?

If any step fails, the pipeline immediately returns {status: "failed", durationMs} and streams the error details through BuildLogger. Because each step is wrapped in logger.runStep(), the dashboard UI reflects the failure in real time without polling.

Where does BareRuntime store running process IDs?

BareRuntime writes the deployment PID to .pids/{deploymentId}.pid and application logs to .logs/{deploymentId}.log. To stop a deployment, Openship reads the PID file and kills the entire process group using the stored PGID, ensuring no orphan processes remain.

Is the DockerRuntime build pipeline fully implemented?

No. According to packages/adapters/docs/ARCHITECTURE.md, DockerRuntime is currently a stub. The runBuildPipeline architecture is designed to accommodate it, but native Dockerfile-based builds are not yet fully implemented in the source.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →