This file guides automation agents to run builds / checks the same way CI does:
- use kas-container (isolated from host),
- keep
DL_DIRandSSTATE_DIRoutside the repo so caches are shared, - run
yocto-patchreviewandoe-selftestroutinely, and runyocto-check-layerbefore opening/updating a PR, via the CI helper scripts.
meta-qcom is an OpenEmbedded / Yocto Project hardware enablement layer for Qualcomm based platforms.
Reusable agent skills for the qualcomm-linux projects are maintained in
qcom-linux-skills,
in the SKILL.md format understood by Claude Code, Codex, Cursor and
similar agents. Several of them cover the workflows described in this file,
such as qcom-yocto-build-image (build images with kas-container),
qcom-yocto-pre-pr-checks (the CI-parity checks from section 4),
qcom-yocto-update-base-lock (refresh ci/base.lock.yml), and
qcom-flash-qdl / qcom-boot-validate (flash and boot-test a board).
Install them with the repository's install.sh and prefer an existing
skill over re-deriving the workflow; improvements go back to that catalog.
kas-containeravailable on PATH, or setKAS_CONTAINER=/abs/path/to/kas-container(from kas-container).- Container runtime access (Docker/Podman backend used by
kas-container). - Work directories outside the repository for build outputs and shared caches.
kas-container uses Docker when it is installed and falls back to Podman
otherwise (set KAS_CONTAINER_ENGINE to override), so check the engine it
will pick:
docker run --rm hello-world # or, on a Podman-only host: podman run --rm hello-worldNotes:
- Do not use
sudounless the host setup explicitly requires it. - Do not create or modify user groups as part of this workflow.
If KAS_WORK_DIR, DL_DIR, and SSTATE_DIR are already set in the environment, use them
directly — do not override them. Only set defaults when they are absent:
export REPO_DIR="$(pwd)" # meta-qcom checkout
export KAS_WORK_DIR="${KAS_WORK_DIR:-/path/to/kas-work}" # outside repo to avoid polling the checkout
export DL_DIR="${DL_DIR:-/path/to/shared-cache/downloads}"
export SSTATE_DIR="${SSTATE_DIR:-/path/to/shared-cache/sstate-cache}"
mkdir -p "${DL_DIR}" "${SSTATE_DIR}" "${KAS_WORK_DIR}"CI build composition pattern:
ci/<machine>.yml[:ci/<distro>.yml][:ci/<kernel>.yml]
Example:
export KAS_YAMLS="ci/rb3gen2-core-kit.yml:ci/qcom-distro.yml"
"${KAS_CONTAINER:-kas-container}" build "${KAS_YAMLS}"For routine local validation, run:
ci/kas-container-shell-helper.sh ci/yocto-patchreview.sh
ci/kas-container-shell-helper.sh ci/oe-selftest.shRun yocto-check-layer only before opening/updating a pull request:
ci/kas-container-shell-helper.sh ci/yocto-check-layer.sh- Script:
ci/oe-selftest.sh - Auto-discovers tests in
lib/oeqa/selftest/cases/when no test list is given. - Honors
DL_DIRandSSTATE_DIRfrom environment (recommended for shared cache).
Run a subset:
"${KAS_CONTAINER:-kas-container}" shell ci/base.yml \
--command "/repo/ci/oe-selftest.sh /repo /work qcom_fitimage.QcomFitImageMatrixTests"For one-off commands:
kas-container shell --skip repos_checkout ci/rb3gen2-core-kit.yml -c "bitbake <target>"
kas-container shell --skip repos_checkout ci/rb3gen2-core-kit.yml -c "oe-selftest --run-tests qcom_fitimage"Use the helper scripts for CI parity whenever possible.
Changes reach qualcomm-linux/meta-qcom as GitHub pull requests against
master, from a topic branch in a fork that is rebased on the latest
upstream master; review iterates in the pull request discussion. Commit
requirements are in CONTRIBUTING.md (see section 7).
Open a pull request, backports included, only when the user asks for one. Every pull request lands in the maintainers' review queue, so one the user did not ask for, or does not know about, is review load nobody wanted. Otherwise, stop once the change is committed and tell the user it is ready.
Before opening/updating a PR, run CI-equivalent checks in this order:
ci/kas-container-shell-helper.sh ci/yocto-patchreview.sh
ci/kas-container-shell-helper.sh ci/yocto-check-layer.sh
ci/kas-container-shell-helper.sh ci/oe-selftest.shFollow the commit subject and message requirements documented in
CONTRIBUTING.md: an atomic change per commit, a
recipe-name: summary of the changes subject, a plain-English body that
explains the problem before the imperative actions, and the mandatory
Signed-off-by (and, when applicable, Assisted-by) trailers.
When committing programmatically, take the Signed-off-by identity from the
local git configuration and append the trailer explicitly:
Signed-off-by: $(git config user.name) <$(git config user.email)>
Never fabricate a name or email; always read them from git config.
Trailer order matters: Assisted-by goes before Signed-off-by, so the
sign-off is always the last trailer written by the author. A complete
agent-assisted commit message, at a typical length, looks like this:
ci/performance: enable root-only udev trigger
The initramfs udev framework now supports root-only triggering for all
supported initramfs images and falls back to a full trigger when the
root device cannot be resolved.
Enable the optimization unconditionally in the performance command line
instead of limiting it to initramfs-rootfs-image.
Assisted-by: AGENT_NAME:MODEL_VERSION
Signed-off-by: Author Name <author@example.com>
Do not append Assisted-by after Signed-off-by (for example with
git commit -s followed by git interpret-trailers --trailer Assisted-by=...);
write both trailers in the order above in a single commit message instead.
Fixups within the same patch series are not allowed; changes should be corrected in the patch where they are introduced.
Commit messages, code comments and pull request descriptions are read by maintainers reviewing many changes, so keep them short enough to take in at a glance. A commit body is usually one or two short paragraphs: the problem, the change, and any fact the reviewer cannot get from the diff. Leave out what the diff already shows, the alternatives you considered, and what the change does not affect, unless a reviewer would otherwise ask. Get there by saying less, not by compressing it into fragments.
Comment code the way the surrounding file does, and only where the reason is not obvious; how the code changed belongs in the commit message.
Fixes land on master first and are then backported to the release branch
(currently wrynose). Merged pull requests labelled backport wrynose are
backported automatically by .github/workflows/backport.yml; when a manual
backport is needed (conflicts, or a change that only applies to the release
branch), follow the same conventions the automation uses:
- Create a topic branch from the latest release branch, for example
backport/<pr-number>-to-wrynose. - Cherry-pick the original commits with
git cherry-pick -x <sha>, which appends the(cherry picked from commit <sha>)line for you. Keep the original subject, body, and trailers unchanged, and add your ownSigned-off-byafter the cherry-pick line if it is not already present. - When the user asks for the pull request, open it against the release
branch with the subject prefixed by the target branch, for example
[Backport wrynose] recipe-name: summary of the changes, and link the original pull request in the description.
The [Backport <branch>] prefix belongs to the pull request subject only.
The commits themselves are normal patches whose only backport marker is the
(cherry picked from commit ...) line; never add the prefix to a commit
subject.