* fix: warn user in build plan when no start command is found
previously this would only happen if error-missing-start is enabled, which is not enabled by default.
* test: warning when start is not found
* build: remove Dockerfiles/ folder to keep image management consistent
* docs: document purpose of various docker images
* docs: internal documentation on the how the build system works
* build: merge all of the image building workflows into a single release workflow
* build: use the mise installer for installing the mise binary
* docs: document purposes of the various images
* refactor: move builder to where it's used
* feat: pin mise build and runtime image versions to specific mise versions
* refactor: use mise task for starting buildkit runner
* test: build new builder and runtime mise images if needed for integration tests
* build: add mise.lock file
* refactor: rename integration tests
* test: add MISE_ENV=ci to all workflows
* fix: mise upgrade
* build: move the docs build and install process into mise
* test: use mise CI vars for tagged release process
* fix: cpp-meson installation process
something changed with mise pipx backend that requires us to manually install python and pipx
* fix: revert mise version
to separate out the build improvements from mise upgrades
* test: snapshot update
* docs: update ex to use mise reference example
* build: move ci bun logic into mise
* docs: explain how docker images are used in public docs
* build: don't push stable tags on prod so we can test a dry run release
* test: bump checkout actions
* docs: minor LLM rule tweak
* fix: remove yml frontend image reference
* docs: why mise.ci.toml is used
* Initial plan
* Fix broken pnpm-workspaces-example link in Node.js docs
Replace broken link reference with link to examples folder. Added note about workspace examples for different package managers.
Co-authored-by: iloveitaly <[email protected]>
---------
Co-authored-by: iloveitaly <[email protected]>
Co-authored-by: Hanzo Dev <[email protected]>
* docs: add monorepo support section to Node.js documentation
Addresses user questions about monorepo support by documenting that
Railpack automatically handles npm/pnpm/yarn workspaces and Turborepo
configurations with links to example projects.
* test: improve monorepo example tests to verify workspace functionality
Enhanced integration tests for monorepo examples to properly test that
workspace package linking and dependencies work correctly:
**node-npm-workspaces:**
- Root now imports and uses functions from pkg-a and pkg-b workspace packages
- pkg-a uses its dependency (abbrev) to demonstrate transitive deps work
- pkg-b exports a simple function
- Updated to ES modules for consistency
- Test now verifies all workspace packages load and execute correctly
**node-pnpm-workspaces:**
- Root now imports and uses functions from pkg-a and pkg-b workspace packages
- pkg-a uses its dependency (abbrev) to demonstrate transitive deps work
- pkg-b exports a simple function
- Updated to ES modules for consistency
- Test now verifies all workspace packages load and execute correctly
**node-turborepo:**
- Changed from justBuild to httpCheck since this is a Next.js web server
- Added start script to root package.json to run the web app
- Test now verifies the built app starts and responds to HTTP requests
- This properly tests that the @repo/ui workspace package is built and linked
These changes ensure that monorepo builds are actually testing workspace
functionality, not just that the root package builds in isolation.
Fixes#332
* feat: add yarn workspaces and full-stack monorepo examples
Added two new monorepo examples to complete coverage:
**node-yarn-workspaces:**
- Demonstrates yarn workspaces with workspace package imports
- Uses the packageManager field for corepack
- Similar structure to npm/pnpm workspace examples for consistency
- Tests that workspace packages load and transitive dependencies work
**node-monorepo-fullstack:**
- Real-world example with Express API + frontend + shared package
- Shows how to share code (@monorepo/shared) between API and web packages
- API uses Express and shared utilities/constants
- Frontend demonstrates importing shared code
- Uses HTTP checks to verify API endpoints work correctly
- Demonstrates common full-stack monorepo pattern
Updated documentation to link to the yarn workspaces example and added
a note about the full-stack example for users looking for a more
realistic monorepo setup.
Addresses #332
* fix: format pkg-b package.json properly
Fixed uglified JSON that was created with echo instead of proper editing.
* fix: add yarn.lock and workspace deps to yarn-workspaces example
- Added yarn.lock file required by yarn 4
- Added workspace package dependencies (pkg-a, pkg-b) to root package.json
- Yarn requires lockfile to exist and won't create one in CI mode
* fix: update yarn.lock with correct workspace references
- Added workspace:* aliases to pkg-a and pkg-b entries
- Removed unused transitive dependencies that aren't in package.json
- Yarn requires both the workspace:* and workspace:packages/* forms
* docs: add lockfile guidelines to CLAUDE.md
Never manually update lockfiles - always use the package manager to
generate them properly with correct checksums.
* fix: add workspace deps to pnpm-workspaces package.json
ES module imports require workspace packages to be listed as dependencies
in the root package.json for Node.js to resolve them correctly.
* fix: generate yarn.lock with proper checksums using yarn
Used yarn install via corepack to generate proper yarn.lock with real
checksums instead of manually creating fake ones. Also includes Yarn PnP
files (.pnp.cjs, .pnp.loader.mjs, .yarn/) generated by yarn 4.
* fix: regenerate lockfiles using package managers
Regenerated pnpm-lock.yaml and yarn install-state.gz using the actual
package managers (pnpm and yarn via corepack) instead of manual edits.
- pnpm-lock.yaml: Updated for new workspace dependencies
- .yarn/install-state.gz: Regenerated by yarn install
* fix: remove Yarn PnP files and add .gitignore
Yarn PnP files (.pnp.cjs, .pnp.loader.mjs, .yarn/install-state.gz) should
not be committed as they contain environment-specific paths. They will be
generated during yarn install at build time.
Added .gitignore matching the pattern used in node-yarn-3 example.
* test: update snapshots
* refactor: merge the more realistic monorepo example into existing npm workspaces example
* build: ignore example claude folders
* test: snapshot update
* test: improve unit tests for node workspaces
* docs: deslop AI documentation
* test: improve turborepo example
* test: update snapshots
* test: update unit test for changed monorepo structure
* test: update snapshot
---------
Co-authored-by: Hanzo Dev <[email protected]>
* docs: misc build process documentation
from exploring how we should do secrets + variables
* test: adding explicit int truthy test case
* refactor: centralize all str => list conversion into a single method
it's a one-liner, but self-documents what we are doing better
* refactor: add helper for parsing env as list
* docs: adding todo for ugly direct getenv access
* test: railpack env var configuration options
* test: check version-less RAILPACK_PACKAGES parsing
* test: snapshot update
* feat: support install phase on shell script provider
allows for more advanced install processes
* docs: note that version-less mise packages are allowed in shell config
* docs: more shell provider examples
* docs: maint task list
* refactor: DRY up yarn detection logic
* fix: handle whitespace in packageManager key
this did not originate from a specific issue, but part of overall debugging of bun multi-workspace
* feat: detect psycopg[binary] and skip apt packages
When using psycopg2-binary or psycopg[binary], the PostgreSQL client
libraries (libpq-dev, libpq5) are not needed because these variants
ship with pre-compiled binaries. This change:
- Adds usesBinaryPsycopg() to detect binary variants
- Updates usesPostgres() to return false when binary variants are used
- Skips libpq-dev (build) and libpq5 (runtime) apt package installation
- Adds comprehensive unit tests for binary psycopg detection
This reduces image size and build time for projects using binary variants.
* test: add psycopg[binary] integration test
Adds a dedicated test example for psycopg[binary] to verify that the
bracket syntax for optional dependencies is correctly detected. This
ensures the binary detection works for both psycopg2-binary and
psycopg[binary] variants.
Test coverage now includes:
- psycopg2-binary (existing python-system-deps example)
- psycopg[binary] (new python-psycopg-binary example)
- psycopg non-binary (existing python-latest-psycopg example)
- psycopg2 non-binary (existing python-django example)
* test: snapshot update
* test: add binary pyscogp test
* test: ensure libpq is installed for pyscog operation
* build: add helper for running the current dir tests
* test: check to make sure the libpg library is not installed when a binary postgres connection is requested
* test: update snapshot
---------
Co-authored-by: Hanzo Dev <[email protected]>
* fix: use consistent node version resolution when bun is detected
When Bun is detected as the package manager but Node is still needed
for native module compilation (node-gyp), the Node version was always
set to "latest" instead of following the same version resolution logic
used when Node is the primary runtime.
This change extracts the Node version resolution logic into a reusable
helper function `applyNodeVersionResolution` that checks version sources
in this order:
1. NODE_VERSION environment variable
2. package.json > engines > node
3. .nvmrc file
4. .node-version file
The same logic is now consistently applied whether Node is required in
the final image or just needed during the build process for Bun projects.
Resolves the TODO comment at line 332 in the original code.
* chore: add tmp/ to .gitignore for temporary test files
* docs: document node version resolution consistency
Add comprehensive documentation explaining why consistent Node version
resolution is critical and how it works:
1. Added detailed godoc to applyNodeVersionResolution method explaining:
- Why the method exists (to ensure consistency)
- Why consistency matters (Bun projects, user expectations, dev/prod parity)
- The priority order of version sources
2. Updated Node.js language documentation to:
- Clarify the version resolution priority order
- Add .node-version file to the list (was missing)
- Emphasize that version resolution is consistent across all scenarios
- Improve the Bun section to explain when Node is installed
- Add explicit note about version specifications being respected
This documentation ensures users understand that their version
specifications (.nvmrc, package.json engines, etc.) are always
honored, regardless of whether Node is the primary runtime or just
a build-time dependency.
* Revert "chore: add tmp/ to .gitignore for temporary test files"
This reverts commit 45c5e51f57c070740f1afc0e9f391ddf6c3a6b53.
* docs: remove ai slop
* test: specify and assert against specific node version in bun project
---------
Co-authored-by: Hanzo Dev <[email protected]>
* docs: update provider documentation with missing features
Added missing documentation for Node, Python, and Ruby providers:
Node.js:
- Added .node-version file support for version detection
- Documented Tanstack Start framework detection and caching
- Added Puppeteer system dependencies documentation
- Clarified React Router cache support
Python:
- Added FastHTML framework detection and start command
- Documented Flask with gunicorn start command
- Added FastAPI framework detection
- Documented additional main file names (app.py, bot.py, hello.py, server.py)
- Added pycairo system dependency documentation
Ruby:
- Documented Node.js integration for Ruby projects
- Added Bootsnap precompilation support documentation
- Documented Propshaft asset pipeline support
- Added local path dependencies support documentation
- Documented Bundler version auto-detection
- Added YJIT/rustc requirement for Ruby 3.2+
- Documented jemalloc performance optimization
- Updated Charlock Holmes dependencies to include full list
* docs: complete FastAPI documentation section
Clarify that FastAPI detection is for metadata only and doesn't provide
automatic start command configuration. Users should configure their own
production ASGI server.
* feat: add python-fastapi example project
Add example project demonstrating FastAPI with custom start command
configuration. This example shows how to configure FastAPI applications
that need explicit ASGI server configuration.
Features:
- Simple FastAPI app with root and health endpoints
- Uses uvicorn as the ASGI server
- Custom start command in railpack.json
- HTTP check test to verify the app runs correctly
* feat: add automatic FastAPI start command detection
Add automatic start command detection for FastAPI projects when uvicorn
is available as a dependency, similar to how Flask and FastHTML are
handled.
Changes:
- Add isFastapi() method to Python provider
- Automatically detect FastAPI + uvicorn and set start command
- Update StartCommandHelp to include FastAPI
- Refactor getRuntime() to use isFastapi() method for consistency
Example updates:
- Convert python-fastapi example to use uv package manager
- Remove railpack.json (no longer needed with automatic detection)
- Add pyproject.toml and uv.lock for dependency management
Documentation updates:
- Update FastAPI section to reflect automatic start command detection
- Clarify that uvicorn must be present as a dependency
* refactor: remove unused /health endpoint from FastAPI example
* test: update snapshot
---------
Co-authored-by: Hanzo Dev <[email protected]>
* feat: add python-oldest and python-latest version examples
Add two new Python examples to test version range support:
- python-oldest: tests Python 3.10 (oldest supported LTS version)
- python-latest: tests latest available Python version via mise
Also update Python documentation to indicate supported version range
(3.10+), matching Python's official support policy.
* docs: add endoflife.date link and remove stderrAllowed from tests
- Add link to https://endoflife.date/python in Python docs
- Clarify that we only support actively maintained Python versions (not EOL)
- Remove stderrAllowed from python-oldest and python-latest tests as
these simple version tests should not produce stderr output
* test: snapshot updat
---------
Co-authored-by: Hanzo Dev <[email protected]>
* feat: add node-oldest example to test legacy Node version support
Adds a minimal example using Node v15 via mise.toml to verify railpack
can build projects with older Node versions.
* refactor: add package.json and rename to app.js for consistency
Pattern after node-bun-no-deps example by adding package.json with
empty dependencies and renaming index.js to app.js to match the
main field.
* docs: add Node.js LTS recommendation and update node-oldest example
- Add note about Node.js LTS versions in node.md documentation
- Update node-oldest example to use v20 (oldest supported LTS)
- Update test.json to assert specific Node v20 output
- Change mise.toml and package.json to pin to Node 20
* refactor: simplify node-oldest example and clarify LTS support
- Remove static version message from app.js to avoid hardcoding
- Update docs to clarify we officially support LTS versions but older
versions will likely still work
- Simplify test.json to only check for Node version output
* test: snapshot update
---------
Co-authored-by: Hanzo Dev <[email protected]>
* test: test install in build phase
* fix: detect node_modules removal and avoid caching node_modules/.cache
* test: add new snapshot
* build: adding go debugging tool and helper task
* refactor: node_modules detection is working
* test: test install in build phase
* refactor: pull plan cleansing into a separate file
* refactor: ai cleanup
* refactor: move cleanse to the provider level, stubs for all providers
* refactor: move existing node cleanse logic to a provider-specific implementation
* test: snapshot update
* docs: why we need node cleanse operation
* docs: note on corepack
* docs: on cache handling of node_modules
* docs: remove references to railpack being early/experimental
Remove mentions of the project being "early" and the config file format
being in "beta" to reflect the current maturity of the project.
* docs: remove language suggesting project immaturity
- Remove "Significant" qualifier from PRs welcome message
- Remove "at the moment" phrases that suggest temporary limitations
- Fix typo: "Is is" -> "It is"
- Rephrase backend description to emphasize architectural flexibility
rather than incomplete features
---------
Co-authored-by: Hanzo Dev <[email protected]>
Update the Detection section to accurately reflect the implementation in
ruby.go, which only checks for a Gemfile in the root directory. The
previous wording suggested multiple conditions when only one exists.
Co-authored-by: Hanzo Dev <[email protected]>
* docs: note that ruby version is sourced from mise
* feat: source ruby version from mise configuration
* test: test specific ruby version in integration tests, use mise-specified version
* test: snapshot update
* Allow disabling caches
* docs specificity
* Allow using * to disable all caching
* Reverse condition check
* Make condition less silly
* Document caches
* trigger ci
* fix: respect mise go version in go provider
* test: assert against specific go version
* test: snapshot update
* build: trust all mise.toml files during setup
* ci: trust all mise.toml before running unit tests
* test: require exact version in go project output
* Revert "ci: trust all mise.toml before running unit tests"
This reverts commit e6994b32fb6b168a4170c14ace20ebf07aea8b67.
* test: split test into two cases
* test: specify non-default go version to assert against
* test: snapshot update
* test: fix go version mismatch
* fixup! test: fix go version mismatch
* build: we don't need the trust script to run our tests
* fix: enable mise paranoid mode on host and container
* docs: add a note about paranoid mode
* docs: why pinned GHA
* fix: remove sh -c when running mise install
* test: update snapshot
* chore: update mise
* test: use pinned GHA versions, mise for package installs
* test: drop lint ci version
* ci: use git shas vs tags
more secure
* fix: put the mise trust state in the same folder as the railpack-managed mise binary
* fix: explicitly trust the host app source path
* docs: mise tips and tricks for dev
* fix: MISE_NO_CONFIG=1 on version list
* test: drop golangci action version
* fix: add MISE_CEILING_PATHS to avoid consuming parent mise.toml
* fix: trying .Dir to fix CI, running fine locally
* docs: document exactly why we are using the parent dir for MISE_CEILING_PATHS
the original LLM discovery with gemini was wrong. Man that model is just so bad.
* fix: another mise bump
* feat(gleam): add GLEAM_INCLUDE_SOURCE option
* test: add RAILPACK_GLEAM_INCLUDE_SOURCE=true to the test config
* test: remove railpack.json
* test: snapshot update
* ci: gleam takes forever to run because erlang has to be compiled
---------
Co-authored-by: Michael Bianco <[email protected]>
Add documentation for the `envs` key in test.json files, explaining how to:
- Pass runtime environment variables to test containers
- Use RAILPACK_* configuration variables in tests
- Reference the full environment variables documentation
This addresses common questions about test.json configuration options.
Co-authored-by: Hanzo Dev <[email protected]>
Allow Deno version to be specified via mise-compatible version files
(.deno-version, .tool-versions, mise.toml) in addition to the
DENO_VERSION environment variable.
Version precedence order:
1. Railpack default (DEFAULT_DENO_VERSION = "2")
2. DENO_VERSION environment variable
3. Mise config files
Updated documentation to reflect the new version resolution options.
Co-authored-by: Hanzo Dev <[email protected]>
* test: add specific elixir and erlang versions
* feat: elixir and erlang versions pulled from mise config
* test: snapshot update
* docs: update version detection documentation
* test: add postgres connection to ecto test
* test: fix docker compose cleanup
I was getting a ton of running postgres containers on my local machine
* docs: document output assertions
* test: add docker-compose where postgres is required
* test: http checks where postgres is required
* test: run docker-compose services if they exist in an example project
* test: remove justBuild from django test
* test: snapshot update
* fix: add PORT with default to django gunicorn start command
* test: add bin/rails
* test: update rails with postgres test to have a valid root route
* docs: integration test documentation
* refactor(node): check engines after file-based detection for package manager
Engines are now considered only if file-based detection keeps default npm,
so lockfiles/configs take precedence over engines as a hint.
* feat: extract yarn version from package.json > engines > yarn
* test: add bun version to bun test assertion
* test: update snapshots
* test: add engines version extraction test
* test: assert against two distinct versions
we couldn't do this before the recent testing harness improvement
* test: snapshot update
* fix: properly handle corepack version definitions
* docs: update docs on node provider detection
* docs: add docs command to claude
* fix(rust): pull version from channel, not version field
fixes#296
* test: use correct rust-toolchain.toml channel key
* docs: update rust version specification docs
* refactor: inline ifs
* test: assert against mise-specified rust version
* test: update snapshot