Skip to content

Builds with pvr ​

pvr build starts and follows builds from a terminal or any script, and pvr secret manages the secrets they use. Every command prints JSON, so it composes with jq.

pvr build is part of the builds development preview: use a pvr whose pvr --help lists build and secret.

Log in ​

sh
export PVR_BASEURL=https://api.stage.pantahub.com     # stage; or pass -b each time
pvr login https://api.stage.pantahub.com/auth/auth_status

The session is stored in ~/.pvr/auth.json and used by every command below.

Start a build ​

A repository with pvpkg.json (Dockerfile, Yocto or Buildroot) ​

sh
pvr build start \
  --project hello-http \
  --git-url https://github.com/acme/hello-http \
  --git-ref main \
  --platform arm64,amd64 \
  --limit-seconds 7200 \
  --secret gh-acme            # only if a recipe fetches private sources

A Dockerfile ​

sh
pvr build start \
  --project my-app \
  --git-url https://github.com/acme/my-app \
  --git-ref v1.2.0 \
  --dockerfile docker/Dockerfile --context . \
  --platform linux/arm64 \
  --limit-seconds 900

A registry image ​

sh
pvr build start --mode docker --project nginx \
  --image docker.io/library/nginx@sha256:<digest> --platform arm64
OptionDefaultMeaning
--project—Groups related builds.
--git-url—HTTPS GitHub/GitLab repository; sets --mode git.
--git-refmainBranch, tag or full 40-character commit. A branch is resolved to its commit when the build is admitted.
--context.Build context: the directory holding pvpkg.json or the Dockerfile's context.
--dockerfileDockerfileDockerfile path, when there is no pvpkg.json.
--platformlinux/arm64One architecture, or a comma-separated pipeline: amd64, arm64, arm32v6.
--limit-seconds60Runner time per architecture: up to 14400 for git builds, 3600 otherwise. Raise it — 60 s is only enough for a simulation.
--apprepository or image nameThe container's name in the export.
--secretthe account's matching git secretGit secret to fetch with; a named one also reaches recipe fetches.
--signing-secretdeveloper keypvs secret to sign the export with.
--targetrpi4A free-form target label shown with the build.
--idempotency-keygeneratedRe-sending the same key returns the same build instead of starting a new one.
--oem—JSON file of an OEM configuration part to add.

Image builds take these instead of a source (Flashable device images):

OptionMeaning
--image-baseWith --git-url of meta-pantavisor: build its image base with these comma-separated kas files.
--baseImage base build to start from (sets --mode image).
--factoryFactory build to start from instead: nothing is signed but the OEM part, seconds.
--make-factoryMake secret-free factory images of --base, one per --policy.
--identitySigning identity whose trust the images get; needs a platform key.
--app-buildApp build whose export joins the images; repeat for several.
--device<device>@<revision> whose apps join the images.
--policyPV_POLICY of one image; repeat for one image each.
--securebootstrict (default), lenient, audit or disabled.
--pantahub-hostcreds.host the devices join; an OEM config's PH_CREDS_HOST overrides it.

start prints the generated Idempotency-Key and the build as JSON; keep its id:

sh
ID=$(pvr build start --project hello-http --git-url https://github.com/acme/hello-http \
       --platform arm64 --limit-seconds 7200 | jq -r .id)

Follow it ​

sh
pvr build status $ID | jq '{status, phase}'      # queued, running (+ stage), succeeded…
pvr build logs $ID | jq -r '.logs[].message'      # the latest log lines
pvr build list --project hello-http | jq -r '.[] | [.id[0:10], .status] | @tsv'
pvr build usage                                   # runner time used recently

A small wait loop:

sh
while :; do
  s=$(pvr build status $ID | jq -r .status)
  case $s in succeeded|failed|cancelled|timed_out) echo $s; break ;; esac
  sleep 20
done

pvr build cancel $ID stops a queued or running build. The same build is visible on the Builds page, with its live log.

Download the export ​

sh
pvr build download $ID                       # ./<app>.pvrexport.tgz, sha256-checked
pvr build download --platform arm64 $ID      # one architecture of a pipeline
pvr build download -o hello.tgz $ID          # never overwrites an existing file
pvr build download --name acme-green.img.xz $ID   # one artifact of a build that made several

Then put it on a device.

Manage secrets ​

sh
pvr secret ls
pvr secret add --type git --host github.com/acme gh-acme      # value from stdin or prompt
pvr secret set --value gh-acme
pvr secret rm gh-acme

See Secrets, tokens and signing.

Signing identities ​

sh
pvr signing ls
pvr signing create acme-gateway --platform        # keys made by the Hub
pvr signing trust acme-gateway -o trust/          # what the image needs
pvr signing enroll acme-gateway                   # a key on this machine, certified by the Hub
pvr build start ... --signing-secret acme-gateway-oem

See Signing identities.

OEM configuration part ​

sh
pvr secret add --type config --host github.com/acme green-autotok < green.token
pvr build start ... --signing-secret acme-gateway-oem --oem oem.json

oem.json is the oem object described in OEM configuration part.

Flashable device images ​

--image-base builds meta-pantavisor's image base; --base with --make-factory makes factory images of it for a signing identity, one per --policy; --factory assembles images from those in seconds:

sh
pvr build start --project cm5 --target image --base <image base build id> \
  --identity acme --policy green --policy red --make-factory
pvr build start --project cm5 --target image --factory <factory build id> \
  --identity acme --app-build <app build id> --oem oem.json

pvr image factory and pvr image assemble do the same on your machine, with keys you keep. See Flashable device images.

Serial console ​

pvr device tty talks to a device on a USB serial adapter, before it has joined the Hub: pvr device tty probe lists the ports, pvr device tty -d /dev/ttyUSB0 log tails Pantavisor's log, … run CMD runs a command.