Zero-config application builder that automatically analyzes your code and turns it into a container image. It's built on BuildKit with support for Node, Python, Go, PHP, and more.
- Core: Analyzes apps and generates JSON build plans using language providers
- BuildKit: Converts build plans to BuildKit LLB (Low-Level Builder) format for efficient image construction
- CLI: Main entry point that coordinates core analysis and BuildKit execution
- Providers: Language-specific modules that detect project types (e.g. Node detects package.json) and generate appropriate build steps
- Runtime: The built images are based on @images/debian/runtime/Dockerfile
- When writing a comment describing a function, do not start the comment with the name of the function
- Assume the person reading this code is an expert software engineer, but is not familiar with the internals of every system. Include concise one-line comments explaining key hooks, API usage, blocks of logic, etc., to help the reader quickly understand the code you've written.
- Follow Go conventions and existing patterns in the codebase
- Prefer early returns or early continues to
ifnesting - Use appropriate error handling with proper error wrapping
- Do not write comments that are obvious from the code itself; focus on explaining why something is done, not what it does
- Seriously, do not write comments that are obvious from the code itself.
- Do not write one-line functions
- Always use the App abstraction for file system operations.
- When configuring Mise settings, prefer TOML settings in the generated
mise.toml(viaAddMiseSetting) over environment variables, so users can override defaults with their ownmise.toml. - Never manually update lockfiles (yarn.lock, package-lock.json, pnpm-lock.yaml, etc.). Always use the respective package manager to generate or update lockfiles. Manual edits can result in invalid checksums and broken builds.
- If mise is not available in your environment, install it using the instructions at https://mise.jdx.dev/installing-mise.html.
- Take a careful look at @mise.toml to understand what commands should be run at different points in the project lifecycle
- Do not worry about docker cache, etc. Never run
docker system pruneor any other similar commands. - Do not run
godirectly. Instead, inspect @mise.toml and usemise run <task>to run various dev lifecycle commands. For instance, you should not rungo vet,go fmt,go test, etc directly. - After making code changes, first run
mise run check - Then, run unit tests and a couple of relevant integration tests to verify your changes
- Don't run tests manually using
go testunless instructed to do so - If tests are failing that are unrelated to your changes, let me know and stop working.
- Don't run tests manually using
- Use the
climise task to test your changes on a specific example project, i.e.mise run cli -- --verbose build --show-plan examples/node-vite-react-router-spa/ - Do not run any write operations with
git - Do not use
bin/railpackinstead usemise run cli(which is the development build ofrailpack)- Therefore do not run
mise build, we don't need arailpackbinary for local testing
- Therefore do not run
- Use a local
tmp/directory for temporary files instead of the global/tmp/directory. Don't worry about cleaning up tmp directories. - You can clone the mise repo (https://github.com/jdx/mise) into
tmp/to inspect it when needed.
There are normal unit tests, snapshot tests, and integration tests. The integration tests are most unique to this project:
- They represent example projects that would be built using the
railpackCLI - On CI, they are built and run to make sure
railpackproperly builds and runs the project test.jsonanddocker-compose.ymlare used to help determine what assertions should be made and what services should be run for the test
- Run
mise run test-integration-cwdfrom within anexamples/directory to run the integration test for that example. test.jsonfiles are JSONC format and support comments. Use comments to explain temporary workarounds or special test conditions.- In
test.jsonwe should avoid usingjustBuildfor all but the most simple projects.justBuilddoes not testexpectedOutputor any other assertions. - If the project has a server component, we should use a
httpChecktest. Read the @docs/src/content/docs/guides/developing-locally.md guide, specifically the### HTTP Checkssection for more information. httpCheckassertions assume that$PORTis respected.- You can use
"env": { "SECRET": "123"}to add a required environment variable to a test case.
- Markdown files in @docs/src/content/docs/ should be limited to 80 columns
- Do not fix indentation or formatting manually. This is corrected automatically using
mise run check - NEVER commit language-specific cache or build artifacts (e.g. Python
__pycache__/,*.pyc,*.pyofiles). If you encounter build artifacts that are not excluded by .gitignore, add appropriate patterns to .gitignore to exclude them