Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/ci/check-bind-pkg-descr.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/bin/sh

set -eu

if [ "$#" -ne 2 ]; then
echo "usage: $0 <base> <head>" >&2
exit 2
fi

base=$1
head=$2
base=$(git merge-base "$base" "$head")
description_changed=false
runtime_changed=false
changed_paths=$(git diff --no-renames --name-only "$base" "$head" -- dns/bind)

while IFS= read -r path; do
case "$path" in
dns/bind/pkg-descr)
description_changed=true
;;
dns/bind/src/*|dns/bind/+*)
runtime_changed=true
;;
dns/bind/Makefile)
if git diff --unified=0 "$base" "$head" -- "$path" |
awk '
/^[+-]PLUGIN_[A-Z0-9_]+[[:space:]]*[?+:!]?=/ &&
$0 !~ /^[+-]PLUGIN_REVISION[[:space:]]*=/ { changed = 1 }
END { exit !changed }
'; then
runtime_changed=true
fi
;;
esac
done <<EOF
$changed_paths
EOF

if [ "$runtime_changed" = true ] && [ "$description_changed" = false ]; then
echo "dns/bind/pkg-descr must change with publishable BIND changes" >&2
exit 1
fi
128 changes: 128 additions & 0 deletions .github/ci/ci-tests/test_bind_pkg_descr_guard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import pathlib
import subprocess

import pytest


REPOSITORY_ROOT = pathlib.Path(__file__).resolve().parents[3]
GUARD = REPOSITORY_ROOT / ".github/ci/check-bind-pkg-descr.sh"


def git(repository: pathlib.Path, *arguments: str) -> str:
return subprocess.run(
["git", "-C", repository, *arguments],
check=True,
capture_output=True,
text=True,
).stdout.strip()


def initialize_repository(repository: pathlib.Path) -> str:
repository.mkdir()
git(repository, "init")
git(repository, "config", "user.email", "tests@example.invalid")
git(repository, "config", "user.name", "Description guard tests")
initial = {
"dns/bind/Makefile": "PLUGIN_VERSION= 1.0\nPLUGIN_REVISION= 1\nPLUGIN_DEPENDS= bind920\n",
"dns/bind/pkg-descr": "Initial description\n",
"dns/bind/src/service": "initial\n",
"dns/bind/tests/test_service.py": "initial\n",
}
for name, contents in initial.items():
destination = repository / name
destination.parent.mkdir(parents=True, exist_ok=True)
destination.write_text(contents, encoding="utf-8")
git(repository, "add", ".")
git(repository, "commit", "-m", "initial")
return git(repository, "rev-parse", "HEAD")


def run_guard(repository: pathlib.Path, base: str, head: str) -> int:
return subprocess.run(
[str(GUARD), base, head],
cwd=repository,
capture_output=True,
text=True,
).returncode


def check_case(repository: pathlib.Path, changes: dict[str, str]) -> int:
base = initialize_repository(repository)
for name, contents in changes.items():
destination = repository / name
destination.parent.mkdir(parents=True, exist_ok=True)
destination.write_text(contents, encoding="utf-8")
git(repository, "add", ".")
git(repository, "commit", "-m", "change")
return run_guard(repository, base, "HEAD")


@pytest.mark.parametrize(
("case", "changes", "expected"),
[
("runtime", {"dns/bind/src/service": "changed\n"}, 1),
("hook", {"dns/bind/+POST_INSTALL.post": "changed\n"}, 1),
(
"documented",
{
"dns/bind/src/service": "changed\n",
"dns/bind/pkg-descr": "Updated description\n",
},
0,
),
(
"dependency-formula",
{
"dns/bind/Makefile": (
"PLUGIN_VERSION= 1.0\nPLUGIN_REVISION= 1\nPLUGIN_DEPENDS= bind920\n"
"PLUGIN_DEPEND_FORMULA_DEPENDS= bind920\n"
)
},
1,
),
(
"manifest-dependency",
{
"dns/bind/Makefile": (
"PLUGIN_VERSION= 1.0\nPLUGIN_REVISION= 1\nPLUGIN_DEPENDS= bind920\n"
"PLUGIN_MANIFEST_DEPENDS= bind920\n"
)
},
1,
),
(
"revision",
{"dns/bind/Makefile": "PLUGIN_VERSION= 1.0\nPLUGIN_REVISION= 2\nPLUGIN_DEPENDS= bind920\n"},
0,
),
("tests", {"dns/bind/tests/test_service.py": "changed\n"}, 0),
],
)
def test_guard_requires_pkg_descr_only_for_publishable_changes(tmp_path, case, changes, expected):
assert check_case(tmp_path / case, changes) == expected


def test_guard_uses_merge_base_when_the_release_branch_advances(tmp_path):
repository = tmp_path / "advanced-base"
original_base = initialize_repository(repository)
git(repository, "checkout", "-b", "feature")
(repository / "dns/bind/src/service").write_text("changed\n", encoding="utf-8")
git(repository, "commit", "-am", "runtime change")
head = git(repository, "rev-parse", "HEAD")

git(repository, "checkout", original_base)
(repository / "dns/bind/pkg-descr").write_text("Base advanced\n", encoding="utf-8")
git(repository, "commit", "-am", "advance base")
advanced_base = git(repository, "rev-parse", "HEAD")

assert original_base == git(repository, "merge-base", advanced_base, head)
assert run_guard(repository, advanced_base, head) == 1


def test_guard_detects_runtime_files_moved_out_of_the_package(tmp_path):
repository = tmp_path / "runtime-rename"
base = initialize_repository(repository)
git(repository, "mv", "dns/bind/src/service", "dns/bind/tests/moved_service")
git(repository, "commit", "-m", "move runtime file")

assert run_guard(repository, base, "HEAD") == 1
12 changes: 12 additions & 0 deletions .github/ci/ci-tests/test_bind_pull_request_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,18 @@ def test_release_source_pull_requests_materialize_master_ci_helpers():
assert '.resolver-plugins/bind920.json' in helper_job


def test_workflow_requires_pkg_descr_for_publishable_bind_changes():
workflow = workflow_text()
changes_job = workflow.split(' changes:', 1)[1].split(' ci-helpers:', 1)[0]

assert 'Check BIND package description freshness' in changes_job
assert 'CALLER_SHA: ${{ inputs.pull_request_sha }}' in changes_job
assert 'if [ -n "$CALLER_SHA" ]; then' in changes_job
assert 'refs/heads/$PR_BASE:refs/remotes/origin/pr-base' in changes_job
assert 'refs/heads/master:refs/remotes/origin/control-plane' in changes_job
assert 'check-bind-pkg-descr.sh' in changes_job


def test_reusable_workflow_accepts_the_callers_pull_request_context():
workflow = workflow_text()

Expand Down
20 changes: 20 additions & 0 deletions .github/workflows/bind-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,26 @@ jobs:
esac
done < "$RUNNER_TEMP/changed-paths"
printf 'bind_source=%s\nci_helpers=%s\n' "$bind_source" "$ci_helpers" >> "$GITHUB_OUTPUT"
- name: Check BIND package description freshness
shell: bash
env:
CALLER_SHA: ${{ inputs.pull_request_sha }}
PR_BASE: ${{ inputs.pull_request_base || github.event.pull_request.base.ref }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ inputs.pull_request_sha || github.event.pull_request.head.sha }}
run: |
set -euo pipefail
guard=.github/ci/check-bind-pkg-descr.sh
if [ -n "$CALLER_SHA" ]; then
git fetch --no-tags origin \
"refs/heads/$PR_BASE:refs/remotes/origin/pr-base" \
'refs/heads/master:refs/remotes/origin/control-plane'
BASE_SHA=$(git rev-parse refs/remotes/origin/pr-base)
guard="$RUNNER_TEMP/check-bind-pkg-descr.sh"
git show refs/remotes/origin/control-plane:.github/ci/check-bind-pkg-descr.sh > "$guard"
chmod +x "$guard"
fi
"$guard" "$BASE_SHA" "$HEAD_SHA"

ci-helpers:
needs: changes
Expand Down
16 changes: 16 additions & 0 deletions dns/bind/pkg-descr
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ necessary for asking and answering name service questions.
Plugin Changelog
================

1.36

* Bound BIND shutdown and log forced recovery steps in the General Log
* Preserve dynamic BIND records while package upgrades regenerate zone files
* Reconcile the supported BIND package pair after plugin and system upgrades
* Add DHCP lease watcher and scoped dynamic DNS mappings
* Add reverse DNS zone management
* Source DNSBL lists from the Unbound definitions
* Add Forward First / Forward Only mode

1.35

* Add per-forwarder destination port for plain DNS forwarders
* Add DNS-over-TLS (DoT) forwarders with TLS hostname verification
* Migrate legacy DNS Forwarders list to the new DNS Forwarders tab

1.34

* Add custom configuration include directory /usr/local/etc/namedb/named.conf.d (contributed by Nicholas Card)
Expand Down
4 changes: 4 additions & 0 deletions docs/building.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ 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.

## BIND candidate updates

The `Propose bind920 candidate` workflow is manual-only. It inspects a
Expand Down
Loading