Buildpacks and builders for Node.js applications that use Yarn workspaces and Python applications that use uv.
The images are published in GitHub Container Registry. They are public and can be used with pack, CI jobs, or any tool that accepts Cloud Native Buildpacks builder and buildpack images.
These examples assume a Yarn project with a checked runtime selected by
yarnPath and a production start script in package.json.
Use Node 26 for new applications:
pack build my-app \
--builder ghcr.io/atls/builder-base:26 \
--buildpack ghcr.io/atls/buildpack-yarn-workspace:26Use Node 24 when the application must stay on Node 24:
pack build my-app \
--builder ghcr.io/atls/builder-base:24 \
--buildpack ghcr.io/atls/buildpack-yarn-workspace:24The builder provides the Node stack and CNB lifecycle. The buildpack prepares a Yarn workspace application for build and launch.
Use the Python builder for a project with pyproject.toml, uv.lock, and .python-version. Set the launch command in a Procfile:
web: python app.py
Build the application with Pack, trusting the builder to use its embedded lifecycle:
pack build my-app --builder ghcr.io/atls/builder-python:latest --trust-builderThe builder uses the Heroku Python buildpack and Heroku's supported Ubuntu stack.
Pass the project root and the exact workspace name when building an application inside a monorepo:
pack build my-app \
--path . \
--builder ghcr.io/atls/builder-base:24 \
--buildpack ghcr.io/atls/buildpack-yarn-workspace:24 \
--env WORKSPACE=@example/appWORKSPACE selects an application in this buildpack; it is not a Yarn or CNB
standard variable. The selected workspace supplies a production start script.
Yarn runs its build script when present, focuses production dependencies, and
launches start. The root package does not need either script. Yarn retains ownership of workspace
dependencies, patches and Plug'n'Play state; the buildpack does not create a
standalone package or rewrite dependency resolutions.
The buildpack installs dependencies even when the source project
uses a global cache outside its directory. A CNB cache layer supplies the Yarn
global-folder location for build and launch without rewriting .yarnrc.yml.
An environment override of YARN_GLOBAL_FOLDER pointing elsewhere is rejected
before installation. With global caching disabled, Yarn's effective cacheFolder
must stay inside the application or that layer; external paths are rejected
before installation as well.
The project remains the application context. Production focus does not remove
unrelated source files or guarantee a minimal image. Without WORKSPACE, the
same build, production focus and launch sequence applies to the root workspace.
The buildpacks/image-targets GitHub action selects image workspaces before a
workflow invokes Pack. Pin it to a published buildpack-root-<version> tag.
The action needs Node 24 and the repository-managed Yarn executable. For the
default changed-workspace selection, check out the caller with full Git history
and pass an exact, nonzero comparison commit as base. With include or
exclude, base may be omitted; Yarn selects matching workspaces from all
workspaces without running a workspace command or installing dependencies. The action returns a matrix
output containing { workspace, imageName } pairs, without building or
publishing an image. A missing eligible image fails selection.
With no explicit filter, Yarn selects changed workspaces and the action includes
their dependents. A root workspace change selects all image workspaces. The
production start script is the shared eligibility condition for the action
and the Yarn workspace buildpack. Image names use the existing scoped package
normalization (@scope/name becomes scope-name).
The buildpacks/publish-image action runs Pack for one selected workspace.
Use docker/metadata-action to produce the versioned and latest image
references, docker/login-action to authenticate, and
buildpacks/github-actions/setup-pack to install Pack before calling it.
The action accepts those two image references, the workspace name, builder,
and buildpack. It publishes both tags using the same Pack build.
Optional buildEnv contains newline-separated KEY=value entries. The
action writes it to a private temporary file, passes that file to Pack with
--env-file, and removes it after Pack exits. These values are build-time
inputs, not image runtime environment variables. Pass SKILLS_NPM_TOKEN
through the action step environment when private Yarn dependencies require it.
| Image | Use it for |
|---|---|
| ghcr.io/atls/builder-base | Building application images with the ATLS Node stack. |
| ghcr.io/atls/builder-python | Building Python application images with uv. |
| ghcr.io/atls/buildpack-yarn-workspace | Building Yarn workspace applications. |
| ghcr.io/atls/stack-node | Stack base, build and run images used by the builder. |
All release images are published for linux/amd64 and linux/arm64.
Use Node-line tags for normal application builds:
- ghcr.io/atls/builder-base:26
- ghcr.io/atls/buildpack-yarn-workspace:26
Available Node lines:
- Node 24
- Node 26
Node-line tags move to the latest published image for that Node line. Use them when an application should receive the current validated builder and buildpack for its Node version.
Use semantic version tags when a rollout needs a fixed buildpack version:
- ghcr.io/atls/buildpack-yarn-workspace:0.2.2
Stack images use role-specific tags:
- ghcr.io/atls/stack-node:base-26
- ghcr.io/atls/stack-node:build-26
- ghcr.io/atls/stack-node:run-26
The same tags exist for Node 24. Tags without a Node suffix currently point to the default Node line, which is Node 26:
- ghcr.io/atls/stack-node:base
- ghcr.io/atls/stack-node:build
- ghcr.io/atls/stack-node:run
For application configuration, prefer explicit Node-line tags such as builder-base:26 and buildpack-yarn-workspace:26.
The repository uses one semantic-release version for buildpack components,
extensions and their composite. Conventional Commits select the next version;
release PRs and committed version-bump records are not used. Existing
buildpack-root-<version> tags provide the release history, including releases
created before this transition. Existing component tags remain historical.
The GHCR workflow first asks semantic-release for a dry-run version. It uses that
version for component tags and <node-major>-<version> builder/stack
tags, builds both supported architectures, and runs the existing manifest,
security and runtime checks. Only then does semantic-release create the GitHub
release. The Node 24/26 channels are promoted after that release succeeds.
CNB TOML files are packaging templates. The existing packaging step substitutes
the supplied RELEASE_VERSION with envsubst; it does not calculate a version,
rewrite dependency resolutions or commit generated metadata. For a local package,
provide an explicit test version to scripts/prepare-buildpack-package.sh and
pass the generated package config to pack buildpack package. Builder templates
also require IMAGE_PREFIX and RELEASE_TAG when rendered.
A failed publication may leave immutable artifacts behind. There is no custom retry engine or promise of an atomic cross-provider release. A green version preview alone is not a completed release.
buildpack-yarn-workspace is the application buildpack for Yarn Plug'n'Play workspace projects, with either provided local caches or a global cache.
The application supplies its production launch command as scripts.start in
package.json.
Yarn configures Plug'n'Play for the application process. The buildpack registers a direct CNB process running the checked Yarn runtime through Node, without a generated shell launcher, and enables Node source maps. The application launch script can stay simple:
{
"scripts": {
"start": "node server.js"
}
}The image start buildpack runs yarn run start. That script should start the application entrypoint. Do not duplicate Yarn's Plug'n'Play loader flags in it. The runtime is executed directly, so an ESM Yarn bundle with top-level await does not need a CommonJS compatibility wrapper or a globally installed Yarn.
builder-base is a base builder. It does not make every application buildable by itself.
For Yarn workspace applications, pass both images:
pack build my-app \
--builder ghcr.io/atls/builder-base:26 \
--buildpack ghcr.io/atls/buildpack-yarn-workspace:26Tools that wrap CNB builds should use the same pair: one builder image and one application buildpack image for the selected Node line.
Component buildpacks and extensions are also published in GHCR:
- buildpack-yarn-cache
- buildpack-yarn-workspace-start
- buildpack-require-extension
- buildpack-extension-curl
- buildpack-extension-htop
- buildpack-extension-graphql-hive