Build a release branch in the FreeBSD release declared by that branch's
.resolver-plugins/upstream.json. The profile contains exactly these immutable
inputs:
seriesandupstream_branch: the OPNsense stable series being built.upstream_commit: the OPNsense plugins source commit.tools_tag: the matching numericopnsense/toolsrelease tag.freebsd_release: the value ofOS?=inconfig/<series>/build.confat thattools_tag.core_commit: the exact OPNsense core Git commit used to configure the package repository. The build checks out and verifies this commit directly; it does not trust the bytes of a GitHub-generated archive.core_archive_urlandcore_archive_sha256: legacy provenance fields kept in existing release profiles. They are not the build-time trust anchor.
Do not substitute a moving branch, a current tools checkout, or an unverified
core commit for these values. .github/ci/metadata_profile.py rejects profiles
that do not meet the required schema and provenance checks.
The BIND runtime package recipe is pinned separately in
.resolver-plugins/bind920.json. That profile records the FreeBSD Ports
repository, exact Ports commit, dns/bind920 Makefile and distinfo
SHA-256 values, BIND DISTVERSION, and PORTREVISION. Resolver Plugins owns
this pin for os-bind-rp; OPNsense's bundled BIND package remains the
compatibility baseline, but this repository may carry a newer reviewed BIND
9.20 package when a security fix, critical bugfix, or maintainer-approved
routine update warrants it.
The GitHub Actions workflow is the canonical build path. It keeps the CI
scripts checked out from master, fetches the selected immutable release
commit, then materializes only that commit's dns/bind source and
.resolver-plugins/upstream.json and Mk build framework. This matters for
legacy release branches, which intentionally do not carry the control-plane
scripts. In particular, the release Mk files prevent a development-branch
marker from adding an unintended -devel package suffix.
Package-affecting pushes to master automatically run production for the
newest numeric release/bind-rp/<series> branch. Merging a package-affecting
pull request into a release-source branch automatically runs production for
that series, pinned to the merge commit. The workflow and publication helpers
still come from the trusted master control plane. Closing a pull request
without merging does not build a release. Manual dispatch remains available
for an explicit series or development build.
Reproduce that split in a disposable worktree when building locally. Start
from master, fetch the selected release branch, and overlay only its release
inputs before entering the matching FreeBSD environment:
series=26.7
release_ref="refs/heads/release/bind-rp/$series"
git fetch --no-tags origin "$release_ref:refs/remotes/origin/build-source"
source_commit=$(git rev-parse refs/remotes/origin/build-source)
git checkout "$source_commit" -- .resolver-plugins/upstream.json Mk dns/bind
git cat-file -e "$source_commit:Mk/devel.mk" 2>/dev/null || rm -f Mk/devel.mkThe runner checks out the pinned OPNsense core commit and configures its
package repository and fingerprints. Before compiling, it checks the
self-contained pkg-<series> channel in resolver-plugins/repository for
bind920-provenance.json. If the complete BIND profile, series, FreeBSD
release, architecture, and target package-creator identity match, it downloads
the two BIND packages through the signed package channel and installs them in
the build VM. A first build or changed compatibility identity is a normal cache
miss and uses the exact FreeBSD Ports recipe pinned in
.resolver-plugins/bind920.json, verifies its hashes, and builds bind-tools
followed by bind920 at the pinned BIND package version. Documentation is
excluded because it is not needed at runtime; this keeps the source build from
pulling in the large Sphinx documentation toolchain. The plugin build then
installs that exact pair before packaging os-bind-rp, so the current channel
and its rollback snapshot contain the BIND packages actually used by the build.
The plugin manifest records dep_formula: "bind920 >= 9.20.26", not a locally
built BIND revision, and the builder verifies the OPNsense version floor.
It clears only dns/bind/work before packaging; do not invoke the inherited
make clean target after materializing a release source, because that target
resets dns/bind/src to the control-plane checkout.
The disposable FreeBSD 14.3 GitHub Actions image may need
IGNORE_OSVERSION=yes to install current builder tools after the public
FreeBSD catalogue advances. Current FreeBSD Ports also requires
ALLOW_UNSUPPORTED_SYSTEM=yes for its end-of-life release; the BIND wrapper
scopes that flag, along with BATCH=yes, to the two Ports package builds. None
of these builder-only compatibility overrides alter the target ABI or the
OPNsense packages used by os-bind-rp.
The wrapper explicitly installs the pinned recipe's ordinary build and linked
library dependencies from the configured OPNsense repository, then invokes the
two BIND builds with NO_DEPENDS=yes. It therefore compiles only the pinned
BIND source instead of recursively rebuilding ordinary Ports dependencies,
while retaining OPNsense-compatible linked libraries.
The runner installs python3 first when the clean FreeBSD environment does
not provide it; Python is required to validate the immutable metadata before
any OPNsense package repository configuration is used.
.resolver-plugins/target-pkg.json pins the exact pkg archive and
pkg-static executable hash for each OPNsense series. Build wrappers install
and lock that target package manager before creating either BIND or plugin
archives. This forced selection is builder-only; it is not an instruction to
upgrade an OPNsense host package manager.
.resolver-plugins/target-pkg-content.json separately pins a canonical digest
of the archive's extracted paths, types, modes, ownership, file flags,
hardlink relationships, file bytes, and symlink targets. Each digest records
the exact signed archive from which its reviewed baseline was calculated. If a
production build fails because OPNsense repacked an otherwise identical
archive, the workflow opens a review PR containing only the new outer archive
hash. It never merges that PR automatically. Merging the PR rebuilds the
affected release series.
An identity or extracted-content change remains a hard failure and requires an
intentional package-creator update.
The initial 26.7 content pin is an intentional baseline of the currently signed archive. The previously pinned archive was no longer available when this guard was introduced, so that baseline must be reviewed as a full package content trust decision; it is not cryptographic proof that the unavailable archive had identical contents. Subsequent automatic proposals compare against this fixed baseline and cannot update it.
BIND provenance records the immutable creator as package_creator; plugin
build-metadata.txt records the flat pkg_creator and
pkg_creator_sha256 fields. Reuse is a cache miss unless those values match
the selected target exactly.
Before copying an artifact, each wrapper verifies that the target parser can read a non-null checksum for every packaged file. The equivalent manual gate is:
python3 .github/ci/package_checksums.py \
--pkg-command /usr/local/sbin/pkg-static path/to/package.pkgTreat a missing, (null), or malformed file checksum as an incompatible
artifact even when the archive and repository signatures are valid.
For example, after preparing the selected release source:
RP_UPSTREAM_METADATA=.resolver-plugins/upstream.json \
SOURCE_COMMIT="$source_commit" \
.github/ci/build-os-bind-rp.sh "$series" "artifacts/$series"If that command exits with status 3, build or reuse the Resolver fallback
and invoke the plugin wrapper with RP_BIND920_FALLBACK=yes:
RP_UPSTREAM_METADATA=.resolver-plugins/upstream.json \
SOURCE_COMMIT="$source_commit" \
.github/ci/build-bind920.sh "$series" "artifacts/$series"
RP_BIND920_FALLBACK=yes RP_UPSTREAM_METADATA=.resolver-plugins/upstream.json \
SOURCE_COMMIT="$source_commit" \
.github/ci/build-os-bind-rp.sh "$series" "artifacts/$series"The package and build-metadata.txt are written below the output directory.
The metadata records the source commit, BIND package version, OPNsense package
version, ABI, provenance values, and FreeBSD environment used for the build.
.github/ci/setup-opnsense-repository.sh <series> is normally called by the
build runner. Use it directly only when diagnosing repository setup; it changes
the FreeBSD VM's package repository configuration.
The Test BIND plugin pull-request workflow discovers every active
release/bind-rp/<series> branch, materializes its dns/bind/src tree, and
runs the canonical dns/bind/tests suite from the pull request. It also runs
the CI helper tests for BIND profile changes, including generated
.resolver-plugins/bind920.json candidate PRs. Do not add a static release
matrix: a newly created release branch is included automatically.
The workflow also requires dns/bind/pkg-descr to change with publishable
BIND runtime, package-hook, or package-metadata changes. Test-only changes and
PLUGIN_REVISION-only rebuilds do not require a changelog entry.
The Propose bind920 candidate workflow is manual-only. It inspects a
FreeBSD Ports ref, defaults to main, and compares dns/bind920 with the
current .resolver-plugins/bind920.json pin. If it finds a newer BIND 9.20
candidate, it updates the pin on a sync/bind920/<version>-<portrevision>
branch and opens or updates a PR against master.
The workflow's assessment is deterministic. It classifies a candidate as:
securitywhen maintainer-supplied notes or security text contain CVE, vulnerability, advisory, or related security signals.riskywhen the Ports diff changes dependency or configuration inputs such asLIB_DEPENDS,RUN_DEPENDS,USES,OPTIONS_DEFAULT, orCONFIGURE_ARGS.critical-bugfixwhen notes mention resolver-impacting issues such as crash, assertion, SERVFAIL, DNSSEC validation, DoT, TLS, cache corruption, or data loss.routinewhen none of those signals are present.
The workflow may receive maintainer-supplied changelog/security notes through
its changelog_text input. It does not fetch ISC or VuXML pages directly,
because adding non-GitHub egress destinations requires explicit approval under
the workspace security policy. The generated PR is evidence for review only;
it does not publish packages.
Check that the metadata is valid before running a full VM build:
python3 .github/ci/metadata_profile.py \
.resolver-plugins/upstream.json "$series" freebsd_release
sh -n .github/ci/build-bind920.sh .github/ci/build-os-bind-rp.sh \
.github/ci/setup-opnsense-repository.sh
python3 -m py_compile .github/ci/*.py
pytest -q .github/ci/ci-tests
git diff --checkInspect the resulting package and build-metadata.txt before treating a build
artifact as suitable for later package-repository publication.