device manifests for a-team digital solutions
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Nicholas Andrew 6cebf1a5a6 Jenkinsfile: tolerate unregistered parameters on a job's first run
A new job's first run has no PORTAL_REQUEST_ID/PORTAL_USER/CHANGELOG yet,
which tripped set -u in Preflight. Default them to empty everywhere.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 00:52:02 -04:00
pipeline Add the shared recovery build pipeline 2026-10-11 00:21:42 -04:00
Jenkinsfile Jenkinsfile: tolerate unregistered parameters on a job's first run 2026-10-11 00:52:02 -04:00
LICENSE Initial commit 2026-09-23 17:55:17 -04:00
README.md Add the shared recovery build pipeline 2026-10-11 00:21:42 -04:00

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 revision to 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

  1. 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
    
  2. Copy an existing XML to <codename>.xml and edit the projects and annotations.
  3. Commit and push.
  4. That's it: the branch's Jenkins job (named after the branch, e.g. ofrp-12.1) lists the new XML in its DEVICE dropdown, and the portal picks it up on its next device sync.

Adding a base

  1. 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.
  2. Add a build.toml (see the README on main) describing the base: portal project, release naming, ZFS dataset, lunch target and release files.
  3. Prepare the warm source tree on buildBox and snapshot it as <dataset>@warm.
  4. Create a Jenkins job named exactly like the branch, using Pipeline script from SCM on build_manifests branch main, script path Jenkinsfile.
  5. 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:

  1. checks the device codename, resolves build.toml for that device (pipeline/build_config.py) and checks the warm snapshot and its mountpoint;
  2. rolls the base back to <zfs_dataset>@warm and checks the warm base is clean (no device tree for the device, empty out/target/product, empty .repo/local_manifests);
  3. copies <DEVICE>.xml into .repo/local_manifests/, fixes branch-name case, reads the ateam.* annotations and syncs only the listed projects;
  4. runs lunch, m installclean and mka <make_extra> <partition target>;
  5. picks the release files from out/target/product/<codename>/, verifies their native checksums, renames them to the A-Team scheme with a .sha256 each, uploads them to Garage and registers the build with the portal as testing (including the portal request id when the portal started it);
  6. rolls the base back to @warm again (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.