-
Notifications
You must be signed in to change notification settings - Fork 0
How ncmake understands your app
Nothing is configured twice, everything is read from files your app has anyway.
| Fact | Source |
|---|---|
| App id |
<id> in appinfo/info.xml
|
| Version |
<version> in appinfo/info.xml
|
| PHP build needed? |
composer.json declares runtime requirements (anything besides php and ext-*) |
| Frontend build needed? |
package.json has a build script |
Is js/ (or vendor/) a build artifact? |
.gitignore (evaluated via git check-ignore) |
| PHP container images | build image from the min-version in appinfo/info.xml; analysis on the current composer image |
| Node container image |
engines.node in package.json
|
The .gitignore line deserves a word: when js/ is gitignored, it is a build output and must exist before packaging (make dist refuses otherwise and tells you to run make build). When js/ is committed, as in apps that ship their built frontend in git, a fresh checkout is already complete and packages without building. The same logic applies to vendor/.
The tarball and the deployed directory are always named after the app id, regardless of what your checkout directory is called.
composer and npm never run on your host by default. Each invocation starts a throwaway container (--rm), does its work in your bind-mounted checkout and disappears. Your host needs no PHP, no Node, no version juggling, and you can build against exactly the PHP the app declares as its minimum.
The runtime is auto-detected (podman preferred, then docker) and can be chosen per call, for example make build RUNTIME=docker:
RUNTIME= |
What it is | Notes |
|---|---|---|
podman |
rootless podman (default when podman exists) | daemonless, no idle cost, files owned by you |
docker |
standard rootful docker | ncmake maps your uid/gid into the container, so no root-owned files appear |
docker-rootless |
rootless docker | |
bare |
no container | composer and npm must be on the PATH |
Two PHP images are picked per task, both maintained upstream so ncmake ships no image of its own. The build runs in the Nextcloud CI image for your declared min-version (ghcr.io/nextcloud/continuous-integration-php<min>): fully tooled (composer, git, unzip) and resolving dependencies against the support floor, which is what packaging needs — its frozen patch level is irrelevant for shipping runtime deps. Everything interactive (make composer, make psalm) runs in the official composer image (docker.io/library/composer:2), which always ships the newest PHP patch alongside composer, git and unzip; psalm needs a current runtime, while the analysed PHP level stays pinned through psalm.xml, so the image's fixed PHP version does not affect the result. Node runs in node:<major> from your engines.node. An app that needs a specific PHP version or an extra extension (ext-gd, ext-intl, …) points php_image/analysis_image at another image in ncmake.mk. All images can be overridden (see Per-app tuning).
Caution
On SELinux hosts (Fedora, RHEL) bind mounts may need a :z label. If you hit permission errors there, run with RUNTIME=bare or adjust your container policy.
© 2026 [ernolf] Raphael Gradenwitz · MIT-licensed · Report an issue
For app developers
- Getting started
- How ncmake understands your app
- Building and packaging
- Releasing
- Per-app tuning
- Target reference
CI workflows
App Store
For app users
Background