Jenkinsfile generalizes the OFRP-12.1 job for every base branch: one job per branch named after it (cms-<branch> jobs target the cms test portal), base settings from the branch build.toml (validated by pipeline/build_config.py), the same preflight, warm rollback, manifest sync, build, rename, checksum, Garage upload and portal registration stages, plus portal_request_id for builds started from the portal and a warm-base lock shared by a base's live and test jobs. README documents the device XMLs, the pipeline and build.toml. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6.9 KiB
build_manifests
Device manifests for the A-Team Jenkins build pipelines.
Each base branch has one Jenkins job (named after the branch) running the shared Jenkinsfile from main. It rolls the base's warm source tree back to @warm, drops one device XML into .repo/local_manifests/, syncs only the projects listed in it, reads the device info from its annotations and the base settings from the branch's build.toml.
Layout
One branch per build base, one file per device.
ofrp-12.1/ genevn.xml milanf.xml rtwo.xml ...
twrp-12.1/ genevn.xml ...
aera-16.0/ genevn.xml milanf.xml ...
A job points at a branch + file, e.g. ofrp-12.1 / genevn.xml.
Device XML
A standard repo local manifest, plus ateam.* annotations on the device tree project.
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<remote name="ateam" fetch="ssh://git@ateam.gotadell.com/" />
<project path="device/motorola/genevn"
name="A-Team_Digital_Solutions/recovery_device_motorola_genevn"
remote="ateam" revision="ofrp-12.1">
<annotation name="ateam.model" value="XT2315"/>
<annotation name="ateam.device_name" value="Moto G Stylus 5G 2023"/>
<annotation name="ateam.manufacturer" value="Motorola"/>
<annotation name="ateam.partition" value="recovery"/>
</project>
</manifest>
Annotations
All four are required; the build stops if one is missing.
| Annotation | Used for | Example |
|---|---|---|
ateam.model |
Release file name, portal device name | XT2315 |
ateam.device_name |
Portal device name | Moto G Stylus 5G 2023 |
ateam.manufacturer |
Portal | Motorola |
ateam.partition |
Build target and flash target | recovery |
ateam.partition must be one of:
| Value | Builds |
|---|---|
recovery |
recoveryimage |
boot |
bootimage |
vendor_boot |
vendorbootimage |
The portal shows the device as <device_name> (<model>).
Projects
- List the device tree plus anything else the device needs (kernel, vendor, common trees).
- Every project listed gets synced; nothing else in the base tree is touched.
- Any git source works. Add another
<remote>for GitHub or elsewhere; the device tree doesn't have to live on A-Team Forgejo. - Pin
revisionto the branch for that base (e.g.ofrp-12.1). - Don't add projects that override the base's own repos. Device-specific fixes go in the device trees.
Release naming
Builds come out as:
<RECOVERY>-<ver>_A-Team_<codename>_<model>-<YYMMDD>.<img|zip>
plus a .sha256 for each, e.g. OFRP-12.1_A-Team_genevn_XT2315-261009.zip.
Adding a device
- Clone and switch to the base branch:
git clone ssh://git@ateam.gotadell.com/A-Team_Digital_Solutions/build_manifests.git cd build_manifests git checkout ofrp-12.1 - Copy an existing XML to
<codename>.xmland edit the projects and annotations. - Commit and push.
- That's it: the branch's Jenkins job (named after the branch, e.g.
ofrp-12.1) lists the new XML in itsDEVICEdropdown, and the portal picks it up on its next device sync.
Adding a base
- Create a new branch named
<base>-<version>(e.g.shrp-12.1) and add a device XML for each device built on it. Each base has its own copy of a device's XML, so update model or name changes on every branch that has that device. - Add a
build.toml(see the README onmain) describing the base: portal project, release naming, ZFS dataset, lunch target and release files. - Prepare the warm source tree on buildBox and snapshot it as
<dataset>@warm. - Create a Jenkins job named exactly like the branch, using Pipeline script from SCM on
build_manifestsbranchmain, script pathJenkinsfile. - Map the portal project to the job in the portal admin.
Build pipeline
Jenkinsfile on main is the build pipeline for every base. Each base branch has one Jenkins job named exactly
like the branch (ofrp-12.1, twrp-12.1, ...), set to Pipeline script from SCM on this repo, branch main,
script path Jenkinsfile. A job named cms-<branch> builds the same base for the cms test portal (test bucket,
test credentials, ateam-cms.gotadell.com).
Per run the job:
- checks the device codename, resolves
build.tomlfor that device (pipeline/build_config.py) and checks the warm snapshot and its mountpoint; - rolls the base back to
<zfs_dataset>@warmand checks the warm base is clean (no device tree for the device, emptyout/target/product, empty.repo/local_manifests); - copies
<DEVICE>.xmlinto.repo/local_manifests/, fixes branch-name case, reads theateam.*annotations and syncs only the listed projects; - runs
lunch,m installcleanandmka <make_extra> <partition target>; - picks the release files from
out/target/product/<codename>/, verifies their native checksums, renames them to the A-Team scheme with a.sha256each, uploads them to Garage and registers the build with the portal as testing (including the portal request id when the portal started it); - rolls the base back to
@warmagain (on failure the tree is left for diagnosis; the next run rolls it back).
A base's live and cms- jobs share one ZFS dataset and hold the warm-base:<branch> lock (Lockable Resources
plugin) for the whole run.
Parameters: DEVICE (lists the branch's XMLs), CHANGELOG, PORTAL_REQUEST_ID and PORTAL_USER (set by the
portal's Start build), and MANIFEST_REF (cms- test jobs only, to build from an unmerged branch).
build.toml
Every base branch has a build.toml next to the device XMLs. It is data only: unknown keys, wrong types or
placeholders other than {codename} stop the build.
[base]
project = "orangefox" # portal project slug
project_name = "OrangeFox"
version = "R12.1" # version shown in the portal
release_tag = "OFRP" # <release_tag>-<release_ver>_A-Team_<codename>_<model>-<YYMMDD>
release_ver = "12.1"
source_root = "/build/ofox-12.1" # mountpoint of zfs_dataset; out/ lives inside it
zfs_dataset = "build/ofox-12.1" # rolled back to @warm before and after every build
warm_check = ["vendor/recovery"] # must exist in the warm base
lunch_target = "twrp_{codename}-eng"
make_extra = ["adbd"] # built together with the ateam.partition target
changelog = "Automated OrangeFox testing build."
[base.env] # extra environment for lunch and the build
FOX_BUILD_DEVICE = "{codename}"
[outputs.img] # release files in out/target/product/<codename>/, exactly one match each
glob = "OrangeFox-*.img"
checksum = "md5" # native sidecar to verify: md5 | sha256 | none
[outputs.zip]
glob = "OrangeFox-*.zip"
checksum = "md5"
test_zip = true
[devices.sycamore_row_5G] # optional per-device overrides: lunch_target, make_extra, env, outputs
lunch_target = "twrp_sycamore_row_5G-eng"
Each [outputs.<ext>] becomes <release name>.<ext> plus <release name>.<ext>.sha256.