Skip to content

Complete JetPack 7.2.1 migration and port Orin fast boot #264

Complete JetPack 7.2.1 migration and port Orin fast boot

Complete JetPack 7.2.1 migration and port Orin fast boot #264

Workflow file for this run

name: Build
on:
push:
branches: [main]
tags:
- 'pab-[0-9]*'
- 'jaj-[0-9]*'
- 'pab-v3-[0-9]*'
pull_request:
concurrency:
group: build-${{ github.ref }}
cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/') }}
jobs:
validation:
runs-on: ubuntu-22.04
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- name: Install validation tools
run: sudo apt-get update -qq && sudo apt-get install -y device-tree-compiler gcc patch
- name: Validate build and fast-boot helpers
run: sudo python3 -m unittest discover -s scripts -p 'test_*.py'
ark_os_noble:
# Only release tags provision an application; ordinary PR/main builds keep
# their kernel-only path. Native ARM64 avoids a multi-hour emulated build.
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-24.04-arm
timeout-minutes: 180
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Free application build space
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be
with:
tool-cache: true
android: true
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: false
- name: Build pinned Noble application natively
run: |
test "$(uname -m)" = aarch64
./scripts/build_ark_os_noble.sh "$RUNNER_TEMP/ark-os-noble-build"
- name: Share Noble package and build provenance
uses: actions/upload-artifact@v4
with:
name: ark-os-noble
path: |
downloads/ark-os-jetson-noble_*_arm64.deb
downloads/ark-os-jetson-noble_*_arm64.build.json
if-no-files-found: error
compression-level: 0
overwrite: true
build:
needs: [validation, ark_os_noble]
# Validation gates every build. A skipped release-only application job must
# not skip PR/main compile checks; releases also require that artifact.
if: ${{ !cancelled() && needs.validation.result == 'success' && (!startsWith(github.ref, 'refs/tags/') || needs.ark_os_noble.result == 'success') }}
runs-on: ubuntu-22.04
# Kernel build alone is ~70 min on a cold ccache; leave headroom for packaging
# (tar + parallel compress of the rootfs) and the multi-GB release upload.
timeout-minutes: 180
permissions:
contents: write
env:
# Keep the /mnt staging symlink reachable after R39 container handoff.
ARK_STAGING_MOUNT: /mnt/staging
CCACHE_DIR: ${{ github.workspace }}/.ccache
# Above one build's object set (~1 GB) so ccache doesn't evict its own hits;
# the rotating ccache is the natural LRU victim under the repo's 10 GB budget.
CCACHE_MAXSIZE: "2G"
# Fresh checkouts reset mtimes and a few kernel files embed __DATE__/__TIME__;
# ignore those so they don't force misses.
CCACHE_SLOPPINESS: time_macros,include_file_ctime,include_file_mtime
# The cross toolchain is restored from its own cache each run with fresh
# mtimes; ccache's default compiler check is the compiler's mtime, so that alone
# invalidated the entire cache (observed ~1% hit rate). Hash the compiler's
# contents instead so hits survive a toolchain cache restore.
CCACHE_COMPILERCHECK: content
steps:
- name: Parse tag
if: startsWith(github.ref, 'refs/tags/')
id: tag
run: |
TAG="${GITHUB_REF_NAME}"
case "$TAG" in
pab-v3-*) PRODUCT="pab-v3"; VERSION="${TAG#pab-v3-}"; TARGET="PAB_V3" ;;
pab-*) PRODUCT="pab"; VERSION="${TAG#pab-}"; TARGET="PAB" ;;
jaj-*) PRODUCT="jaj"; VERSION="${TAG#jaj-}"; TARGET="JAJ" ;;
*) echo "::error::Unrecognized tag format: $TAG"; exit 1 ;;
esac
{
echo "product=$PRODUCT"
echo "version=$VERSION"
echo "target=$TARGET"
} >> "$GITHUB_OUTPUT"
echo "Parsed tag: product=$PRODUCT version=$VERSION target=$TARGET"
- uses: actions/checkout@v4
- name: Free disk space
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be
with:
tool-cache: true
android: true
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: false
- name: Stage build tree on /mnt
# staging/ (extracted rootfs + massflash images + the multi-GB mfi tarball)
# overran the ~49 GB free on / and crashed the runner with ENOSPC during
# packaging. The ephemeral /mnt has ~65 GB free and is otherwise unused, so
# build there. The final package + split stay in the workspace on /, where
# the release step globs for them.
run: |
sudo mkdir -p /mnt/staging
sudo chown "$(id -u):$(id -g)" /mnt/staging
ln -s /mnt/staging staging
- name: Install prerequisites
env:
DEBIAN_FRONTEND: noninteractive
run: |
sudo -E apt-get update -qq
sudo -E apt-get install -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" \
abootimg binfmt-support binutils ccache cpio cpp curl \
device-tree-compiler dosfstools \
iproute2 iputils-ping lbzip2 libxml2-utils lz4 \
netcat-openbsd nfs-kernel-server openssl \
pigz python3-yaml qemu-user-static rsync sshpass \
udev usbutils uuid-runtime whois xmlstarlet zstd
- name: Resolve cache keys from versions.env
id: cachekeys
run: |
source versions.env
echo "bsp=${EXPECTED_BSP_RELEASE}.${EXPECTED_BSP_REVISION}" >> "$GITHUB_OUTPUT"
echo "toolchain=$(basename "$TOOLCHAIN_URL")" >> "$GITHUB_OUTPUT"
- name: Cache cross toolchain
uses: actions/cache@v4
with:
path: ~/l4t-gcc
key: l4t-gcc-${{ steps.cachekeys.outputs.toolchain }}
# The L4T BSP/rootfs/sources tarballs (~2.7 GB) are pinned by BSP version, so
# cache them on it — setup.sh skips any tarball already present in downloads/.
- name: Cache L4T BSP tarballs
uses: actions/cache@v4
with:
path: downloads/*.tbz2
key: l4t-bsp-${{ steps.cachekeys.outputs.bsp }}
# ccache across runs (kernel C is mostly hits). Rotating per-run key so each
# run saves an updated cache; restore-keys pulls the most recent prior one.
- name: Cache ccache
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.ccache
key: ccache-${{ steps.cachekeys.outputs.bsp }}-${{ github.run_id }}
restore-keys: |
ccache-${{ steps.cachekeys.outputs.bsp }}-
- name: Download Noble application artifact
if: startsWith(github.ref, 'refs/tags/')
uses: actions/download-artifact@v5
with:
name: ark-os-noble
path: downloads
- name: Verify Noble application provenance
if: startsWith(github.ref, 'refs/tags/')
run: |
source versions.env
python3 - "$ARK_OS_VERSION" "$ARK_OS_SOURCE_COMMIT" <<'PYTHON'
import hashlib, json, pathlib, sys
package = pathlib.Path("downloads") / f"ark-os-jetson-noble_{sys.argv[1]}_arm64.deb"
metadata = json.loads(package.with_suffix(".build.json").read_text())
digest = hashlib.sha256()
with package.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
if metadata["package"] != package.name or metadata["source_commit"] != sys.argv[2]:
raise SystemExit("Noble artifact does not match the pinned source/version")
if metadata["sha256"] != digest.hexdigest():
raise SystemExit("Noble artifact checksum mismatch")
print(f"Verified {package.name}: {digest.hexdigest()}")
PYTHON
- name: Download BSP
run: ./setup.sh --force
- name: Reset ccache stats
run: ccache -z
- name: Build kernel
# Release tags consume the pinned Noble artifact built above, then
# provision ARK-OS and the native R39 camera stack into the image. Missing
# or incompatible artifacts fail; no other release or OS is substituted.
# The draft release ships the resulting provisioned image. PR/main builds
# use --no-provision to retain the existing kernel compile-check path.
run: |
if [ -n "${{ steps.tag.outputs.target }}" ]; then
./build.sh ${{ steps.tag.outputs.target }} --provision
else
./build.sh PAB --no-provision
fi
- name: ccache stats
if: always()
run: ccache -s
- name: Generate flash package
if: startsWith(github.ref, 'refs/tags/')
run: ./packaging/generate_flash_package.sh ${{ steps.tag.outputs.target }}
- name: Create release
if: startsWith(github.ref, 'refs/tags/')
env:
GH_TOKEN: ${{ github.token }}
run: |
TAG="${GITHUB_REF_NAME}"
PRODUCT="${{ steps.tag.outputs.product }}"
VERSION="${{ steps.tag.outputs.version }}"
source versions.env
L4T_VERSION="${EXPECTED_BSP_RELEASE}.${EXPECTED_BSP_REVISION}"
PRODUCT_UPPER=$(echo "$PRODUCT" | tr '[:lower:]' '[:upper:]' | tr '-' '_')
RELEASE_FILES=()
for f in ark-*.tar.gz; do
[ -f "$f" ] && RELEASE_FILES+=("$f")
done
for d in ark-*_split; do
[ -d "$d" ] || continue
for part in "$d"/*.part.*; do
[ -f "$part" ] && RELEASE_FILES+=("$part")
done
done
if [ ${#RELEASE_FILES[@]} -eq 0 ]; then
echo "::error::No flash package artifacts found (ark-*.tar.gz or ark-*_split/)"
exit 1
fi
# The flasher isn't a release asset; it's served from main (linked in the notes below).
echo "Release assets:"
for f in "${RELEASE_FILES[@]}"; do
echo " $(basename "$f") ($(du -h "$f" | cut -f1))"
done
COMMIT_SHORT=$(git rev-parse --short HEAD)
cat > /tmp/release-notes.md <<EOF
## ${PRODUCT_UPPER} v${VERSION}
L4T ${L4T_VERSION} (Jetpack ${JETPACK_VERSION}) | Built from \`${COMMIT_SHORT}\`
### Flash
Fetch the flasher from the main branch (it flashes any release):
\`\`\`
curl -LO https://raw.githubusercontent.com/${GITHUB_REPOSITORY}/main/packaging/flash_from_package.sh
chmod +x flash_from_package.sh
./flash_from_package.sh ${TAG}
\`\`\`
Put the Jetson in recovery mode before running. Requires a Debian/Ubuntu host with USB connection. Supports all Orin Nano/NX module variants.
EOF
# Every release is born a hidden draft; promoting it to published is a
# manual GitHub toggle (same artifact, same tag — no rebuild, no rename).
gh release create "$TAG" --draft \
--title "${PRODUCT_UPPER} v${VERSION}" \
--notes-file /tmp/release-notes.md \
"${RELEASE_FILES[@]}"