[ci]: Add buildenv_setup and cut the Build stage over to it (CI unification, Phase 1)#1222
Open
theasianpianist wants to merge 13 commits into
Open
Conversation
First PR of the dataplane CI-unification effort (HLD: sonic-net/SONiC#2419). Adds the buildenv_setup Python package under ci/ -- the shared tool that sets up the build/test environment for sonic-swss-common, sonic-sairedis, and sonic-swss by reading each repo's declarative build-env/ config, resolving the (cascaded) apt/pip/upstream-DEB dependency set, installing it, and running post_install hooks. Purely additive and dormant: nothing in any existing pipeline references ci/ yet (consumers are cut over stage-by-stage in later PRs), so CI behavior is unchanged. - ci/buildenv_setup/ -- multi-module package (schema/predicates/cascade/azp_client/ installer/post_install/planner/cli/topo/apt_sources/model). - ci/tests/ -- 39 unit tests (fail-loud schema, cascade, predicates, topo, planner). - ci/README.md -- overview + layout. Hosted here because sonic-swss-common is the root of the dependency cascade and is already checked out by every consumer's CI; versioned with its branches. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Lawrence Lee <lawlee@microsoft.com>
Collaborator
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
This PR introduces a new, shared Python tool (ci/buildenv_setup) intended to unify build/test environment setup across SONiC dataplane repositories by resolving and executing install plans from declarative build-env/ YAML configuration. It is currently additive-only and not wired into existing pipelines yet.
Changes:
- Added
ci/buildenv_setup/package implementing schema validation, predicate evaluation, upstream artifact cascade resolution, install planning, and a CLI entrypoint. - Added a pytest suite under
ci/tests/covering schema validation, predicates, topo ordering, cascade resolution, and planner behaviors. - Added
ci/README.mddocumenting purpose, layout, schema evolution policy, and test invocation.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| ci/README.md | Documents the new CI tooling package, its scope, and how to run tests. |
| ci/.gitignore | Ignores Python/pytest cache artifacts under ci/. |
| ci/buildenv_setup/init.py | Declares package metadata and version. |
| ci/buildenv_setup/main.py | Enables python3 -m buildenv_setup execution. |
| ci/buildenv_setup/apt_sources.py | Generates commands to register third-party APT sources. |
| ci/buildenv_setup/azp_client.py | Implements Azure DevOps artifact resolution/download/extraction. |
| ci/buildenv_setup/cascade.py | Resolves upstream-artifacts config and recursively collects bundle artifacts. |
| ci/buildenv_setup/cli.py | Provides CLI surface for configuring and running the tool. |
| ci/buildenv_setup/installer.py | Centralizes apt/pip/dpkg/script execution primitives. |
| ci/buildenv_setup/model.py | Defines dataclasses representing parsed config and runtime context. |
| ci/buildenv_setup/planner.py | Orchestrates plan resolution and execution ordering (apt → deb → pip → post_install). |
| ci/buildenv_setup/post_install.py | Selects/dedups/resolves post_install hooks and their scripts. |
| ci/buildenv_setup/predicates.py | Evaluates when: predicates and performs {var} substitutions. |
| ci/buildenv_setup/schema.py | Loads YAML and enforces additive schema with fail-loud unknown-field rejection. |
| ci/buildenv_setup/topo.py | Provides stable topological sorting for requires: ordering. |
| ci/tests/conftest.py | Ensures buildenv_setup is importable when running pytest. |
| ci/tests/test_cascade.py | Validates upstream resolution, staged bundle collection, and nested cascade behavior. |
| ci/tests/test_planner.py | Validates package selection, batching, and DEB grouping behaviors. |
| ci/tests/test_predicates.py | Validates predicate matching and substitution behavior. |
| ci/tests/test_schema.py | Validates schema parsing and fail-loud behavior for invalid inputs. |
| ci/tests/test_topo.py | Validates stable topo ordering and cycle detection. |
Add a standalone pipeline stage (dependsOn: []) that installs pytest/pyyaml/requests and runs the ci/buildenv_setup unit tests, publishing JUnit results. Gives the tool CI coverage from day one. The stage runs in parallel and does not gate the existing Build/BuildDocker/Test stages (they don't depend on it), while its own pass/fail still contributes to the overall pipeline result. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Lawrence Lee <lawlee@microsoft.com>
Collaborator
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
…les; log fix-broken dpkg Two buildenv_setup refinements needed by the cross-repo build-env cascade: 1. post_install.resolve_script falls back to cascaded upstream build-env/ dirs (by basename) when a source: script is not present locally. This lets a consumer reuse a hook the upstream bundle already provides, so a shared script (e.g. configure-redis-for-tests.sh) lives in exactly one repo -- the cascade root -- instead of being duplicated. planner passes the cascaded build-env dirs. 2. Executor.dpkg_install logs the '+ <cmd>' line on the apt_fix_broken path too (it previously ran subprocess.run directly, hiding the command + any per-upstream install_env such as vpp's VPP_INSTALL_SKIP_SYSCTL=1). Adds tests/test_post_install.py (local-wins / upstream-fallback / not-found / scope-filter dedup) and tests/test_installer.py (env prefix present in dpkg argv on both the plain and apt_fix_broken paths). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Lawrence Lee <lawlee@microsoft.com>
…env_setup First real cutover of the CI-unification effort. Introduces sonic-swss-common's declarative build-env/ configuration and switches the Build stage's amd64/ubuntu-22.04 job to set up its environment via buildenv_setup instead of ~90 lines of inline apt-install + DownloadPipelineArtifact steps. build-env/: - packages/base.yaml -- cascading build+link deps (libhiredis-dev, swig, redis-server, pip libyang) + the canonical, shared configure-redis-for-tests post_install hook. - packages/tooling.yaml -- non-cascading, Build-only tooling (the jammy vmImage toolchain, gtest/gmock, pytest, Pympler) + mkdir-yang-models. - upstream-artifacts.yaml -- common-libs (SONiC-patched libnl + libyang3 DEBs) and sonic-buildimage-vs (sonic-yang wheels), resolved on $(BUILD_BRANCH). - configure-redis-for-tests.sh, build.sh, Dockerfile, compose.yaml, README.md (build.sh/Dockerfile/compose enable local reproduction of the CI build env -- Goal 3). Cutover (.azure-pipelines/build-ubuntu-template.yml, azure-pipelines.yml): - The inline amd64/ubuntu-22.04 job becomes a build-ubuntu-template.yml reference whose setup step runs buildenv_setup --scope build --host-os ubuntu-22.04. Compile / Bazel / archive are unchanged; it still publishes sonic-swss-common.amd64.ubuntu22_04 (same artifact the Test stage consumes), so no downstream contract changes. - Only this job changes. The shared build-template.yml (container amd64 + BuildArm + BuildTrixie) and all downstream stages are untouched. Behavior delta vs the old inline job: libnl now comes from common-libs (SONiC-patched, consistent with the container builds) rather than apt stock; the bogus 'python' (py2) and redundant 'sudo' installs are dropped. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Lawrence Lee <lawlee@microsoft.com>
Collaborator
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
The ubuntu-22.04 Build job now builds libswsscommon against the SONiC-patched libnl from common-libs (3.7.0-0.2+b1sonicN), so its dpkg Depends is >= +b1sonicN. The VS Test stage installs that .deb on the jammy sonictest host, whose apt only has stock libnl (+b1) -- which does NOT satisfy +b1sonicN, so 'dpkg -i libswsscommon || apt-get install -f' removed libswsscommon and python3-swsscommon then failed. Fix (consistent with the repo policy of always using SONiC libnl, never apt stock): download the SONiC libnl runtime debs (libnl-3-200/genl/route/nf) from the common-lib artifact -- already fetched here for libyang -- and apt-install them before the swss-common deb. Mirrors how the build stages obtain libnl. Companion to the ubuntu-22.04 Build cutover; the Test stage is otherwise unchanged (full --scope test cutover to buildenv_setup is a later PR). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Lawrence Lee <lawlee@microsoft.com>
Collaborator
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Resolves the automated review findings on PR sonic-net#1222: - installer: run_script now uses 'bash -e -o pipefail' so a failure anywhere in a pipeline (curl | gpg | tee) fails the command instead of being masked. dpkg_install's apt_fix_broken path routes through a shared _exec() so the command is logged consistently (no direct subprocess.run). - azp_client: extract downloaded artifact zips via _safe_extractall(), rejecting members whose path escapes the target dir (zip-slip / path traversal). - schema: fail loudly when list fields (pip_args/requires/dpkg_args/scopes/result_filter) are not lists and install_env is not a mapping -- previously list('string') silently produced a per-character list. Adds _as_str_list/_as_str_map validators. - planner: _deb_install_groups keeps empty-install_env group first but otherwise preserves artifact insertion order (was sorted by env-var count, which could reorder inter-dependent special-env groups). register_commands is passed use_sudo so --no-sudo is honoured for apt-source registration. - cascade: thread the used-staged accumulator explicitly through the recursion (drop the collect_bundles._used module-attr hack) so a staged upstream referenced only via a nested bundle isn't wrongly reported as unused. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Lawrence Lee <lawlee@microsoft.com>
The diff-coverage gate (threshold 80%) reported 74% because the new buildenv_setup modules were under-tested (azp_client 29%, planner 38%, installer 58%, schema 79%). Add unit tests to bring every module well above threshold (total 60% -> 93%, 109 tests): - test_azp_client.py (new): fake requests.Session -- auth modes, _get retry/backoff, definition/build/artifact resolution + not-found errors, _content_root variants, zip-slip guard (accept nested / reject ../), fetch_artifact end-to-end. - test_planner_run.py (new): planner.run() with a fake Executor + staged upstream -- dry-run rendering, real apt/dpkg/pip/post_install sequence, no-build-env error, apt-source selection. - test_cli.py (new): arg parser defaults/required, main() dry-run success + error exit code. - test_apt_sources.py (new): register_commands with/without sudo. - test_installer.py: rewritten (single import style -- fixes the CodeQL import finding) + full Executor primitive coverage incl. the apt_fix_broken fallback. - test_schema.py / test_cascade.py / test_planner.py: added cases for the new list/map validation, the used-staged recursion fix, and deb-group insertion ordering. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Lawrence Lee <lawlee@microsoft.com>
Collaborator
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Drop the mixed 'import buildenv_setup.azp_client as azp' + 'from ... import' in test_azp_client.py (same CodeQL finding as test_installer.py). Keep only the from-import and use the string-target form for the time.sleep monkeypatch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Lawrence Lee <lawlee@microsoft.com>
Collaborator
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
…ONiC libnl Cut the shared container build job (build-template.yml) over to buildenv_setup, the same mechanism the amd64/ubuntu-22.04 job already uses. This template is instantiated by the Build (amd64), BuildArm (armhf/arm64) and BuildTrixie (amd64/armhf/arm64) stages, so all six container build jobs now set up their environment via the tool. - Replaces the inline 'apt-get install ... libnl-3-dev libnl-genl-3-dev libnl-route-3-dev libnl-nf-3-dev ...' (apt-stock libnl) + the DownloadPipelineArtifact@2 libyang/yang-wheel steps + inline dpkg/pip with a single 'buildenv_setup --scope build' invocation driven by build-env/. libnl now comes from common-lib (SONiC-patched, +b1sonicN) for every arch, matching the ubuntu-22.04 job and the VS test host -- the repo policy of always using SONiC libnl, never apt stock. - Compile is now ./build-env/build.sh (single source of truth). The unit-test step runs the shared configure-redis-for-tests.sh inline after cargo (redis must be down for the Rust logger_init_without_redis test), and yang-models mkdir moves to the tool's post_install. - Keeps the sonic-slave container, $(BUILD_BRANCH) image tag, coverage flags, artifact names and the unit-test/gcov steps unchanged, so stage outputs and downstream contracts are identical. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Lawrence Lee <lawlee@microsoft.com>
Collaborator
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
The container Build cutover makes libswsscommon Depend on the SONiC-patched libnl (>= 3.7.0-0.2+b1sonicN). BuildSairedis installs that libswsscommon .deb but its sonic-slave container had only apt-stock libnl (+b1), so 'dpkg -i libswsscommon' failed with unmet libnl-3-200/libnl-nf-3-200/libnl-route-3-200 (>= +b1sonicN) deps. Fix (consistent with the always-SONiC-libnl policy and build-swss-template.yml): drop the apt-stock libnl-*-dev install and download the full SONiC libnl family (runtime + -dev, used to build sonic-sairedis too) from the common-lib artifact, installed before the swss-common .deb. BuildSwss already downloads+installs SONiC libnl with the swss-common deb (no change). BuildDocker installs into the SONiC docker-sonic-vs base image, which already carries SONiC libnl. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Lawrence Lee <lawlee@microsoft.com>
Collaborator
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
The container/ubuntu Build jobs publish via .artifactignore, which un-ignored only *.deb -- so build-env/ was excluded from the sonic-swss-common artifact. Downstream consumers (sonic-sairedis, sonic-swss) cascade this repo's dependency declarations by downloading the artifact and reading build-env/upstream-artifacts.yaml + build-env/packages/*.yaml from it, so build-env/ (and its configure-redis-for-tests.sh) must be published. Un-ignore build-env/ (dir entry + contents) alongside the debs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Lawrence Lee <lawlee@microsoft.com>
Collaborator
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
…hed)
Revert the SONiC-patched-libnl-everywhere approach to reduce migration churn. Build
sonic-swss-common against the STOCK apt libnl so the libswsscommon .deb's libnl Depends
is on the stock version (satisfied in every build/test/docker environment without a
SONiC-libnl companion step in downstream stages).
- build-env/packages/base.yaml: apt-install libnl-{3,genl-3,route-3,nf-3}-dev (the same
four -dev packages master's build-template.yml installs), instead of relying on the
common-lib download.
- build-env/upstream-artifacts.yaml: drop the libnl-* debs from the common-libs download
(keep only libyang3 + libyang-dev).
- Revert .azure-pipelines/test-docker-sonic-vs-template.yml and build-sairedis-template.yml
to master: their SONiC-libnl download/install steps are no longer needed now that
libswsscommon depends on stock libnl.
The container Build / BuildArm / BuildTrixie / ubuntu jobs already apt-install stock libnl
via buildenv_setup (base.yaml), matching master's behaviour.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Lawrence Lee <lawlee@microsoft.com>
Collaborator
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
theasianpianist
added a commit
to theasianpianist/sonic-sairedis
that referenced
this pull request
Jul 14, 2026
…4 (migration validation) Draft PR to validate that sonic-sairedis builds + tests green against the sonic-swss-common CI-unification migration PR (sonic-net/sonic-swss-common#1222). Pin every 'Download sonic swss common' step (build-template, build-swss-template, build-docker, test-docker) to runVersion: specific / runId: 1164874 (the green sonic-net#1222 build) instead of latestFromBranch on $(BUILD_BRANCH). sonic-net#1222's swss-common builds against STOCK apt libnl, so libswsscommon Depends on the stock libnl already present in every sonic-sairedis build/test/docker environment -- no SONiC-libnl companion changes are needed here (only the pin). NOT for merge -- the runId pin is temporary; revert to latestFromBranch before merge. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Lawrence Lee <lawlee@microsoft.com>
theasianpianist
requested review from
prabhataravind,
prsunny,
qiluo-msft and
saiarcot895
July 14, 2026 22:14
saiarcot895
reviewed
Jul 15, 2026
The sonic-slave build containers already provide Pympler and pytest (python3-pympler / python3-pytest), so installing them via pip in build-env/packages/tooling.yaml is redundant. The Ubuntu 22.04 job runs the Bazel test suite and does not invoke pytest, so it does not need them either. Addresses review feedback from @saiarcot895 on PR sonic-net#1222. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 19e0b615-271d-48f0-98cc-7ad6905c7f9e Signed-off-by: Lawrence Lee <lawlee@microsoft.com>
Collaborator
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
First PR of the dataplane CI-unification effort (HLD: sonic-net/SONiC#2419):
buildenv_setup— a shared, declarative build-environment toolbuild-env/instead of being hand-maintained as inline pipeline steps. As part of the cutover, sonic-swss-common now builds and linksagainst the SONiC-patched libnl everywhere (never apt stock), which is propagated to every stage/host
that installs the resulting
.debs.What's added
ci/buildenv_setup/— a self-contained Python package (schema / predicates / topo / apt_sources /cascade / azp_client / installer / post_install / planner / cli). Given a repo's
build-env/config itresolves the (cascaded) apt/pip/upstream-DEB dependency set, installs it (DEBs before pip), and runs
post_installhooks. Hosted here because sonic-swss-common is the root of the dependency cascade and isalready cloned by every consumer's CI. 109 unit tests run in a standalone
BuildenvSetupUnitTestspipeline stage.
build-env/— sonic-swss-common's declarative config:packages/base.yaml(cascading build+link deps + the canonical sharedconfigure-redis-for-testshook),packages/tooling.yaml(non-cascading Build-only tooling),upstream-artifacts.yaml(common-libSONiC libnl + libyang3, sonic-yang wheels).
build.sh,Dockerfile,compose.yaml,README.md— let a developer reproduce the CI buildenvironment locally (portable-local-dev goal).
What's cut over (Build stage)
Both jobs of the
Buildstage now set up their environment with a singlebuildenv_setup --scope buildcall, replacing ~200 lines of inline
apt-get install+DownloadPipelineArtifact@2+dpkg/pipsteps:amd64/ubuntu-22.04(vmImage) → newbuild-ubuntu-template.yml.build-template.yml— shared byBuild(amd64),BuildArm(armhf/arm64) andBuildTrixie(amd64/armhf/arm64), so all six container build jobs are cut over. Compile is now./build-env/build.sh; the sharedconfigure-redis-for-tests.shruns inline aftercargo(redis mustbe down for the Rust
logger_init_without_redistest). Container image tag ($(BUILD_BRANCH)),coverage flags, artifact names and the unit-test/gcov steps are unchanged, so stage outputs and
downstream contracts are identical.
Scope / safety
ci/tool is dormant except where explicitly invoked; the cutover keeps every stage's artifacts,names and downstream contracts identical, so consumers are unaffected.
@resourcereuse or dependency-cascade cutover yet — those are later migration PRs, andthere are no downstream template changes here (building against stock libnl keeps the
libswsscommondeb's dependencies satisfied everywhere).Validation
buildenv_setupunit tests pass locally and in theBuildenvSetupUnitTestsstage; diff-coverage 96%.amd64/ubuntu-22.04+ containerBuild/BuildArm/BuildTrixiejobs build against stock apt libnl and pass compile + unit tests (nocontinueOnError);BuildSairedis/BuildSwss/BuildDocker/Testall green.the PoC branches across amd64/arm/trixie + VS tests.
Downstream validation (proof)
To prove this migration does not break downstream consumer CI, two draft PRs pin their swss-common
download to this PR's build (
1164874) and build/test against it:Both pin every swss-common download to this PR's fully-green build
1164874and are pins-only (no libnl companion, since swss-common builds against stock libnl). Every build stage and the VS Test stage passed on both drafts (all tasks succeeded); the overallpartiallySucceededis warning-level noise in the ASAN-only stages, unrelated to the swss-common change. DO NOT MERGE — thepins revert before those repos merge anything.
How to review
ci/README.md→ci/buildenv_setup/cli.py(arg surface) →schema.py(config contract) →cascade.py(dependency walk) →
planner.py/installer.py(install plan); thenbuild-env/(the declarative config)and the
.azure-pipelines/*.ymlcutover diffs.