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
40 changes: 40 additions & 0 deletions .github/ci/bind920_candidate.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@


BIND_SERIES = (9, 20)
BIND_UPSTREAM_REPOSITORY = "https://github.com/isc-projects/bind9.git"
DISTVERSION_PATTERN = re.compile(r"^DISTVERSION[?+]?=\s*([0-9]+\.[0-9]+\.[0-9]+)\s*$", re.MULTILINE)
PORTREVISION_PATTERN = re.compile(r"^PORTREVISION[?+]?=\s*([0-9]+)\s*$", re.MULTILINE)
DISTINFO_SHA256_PATTERN = re.compile(r"^SHA256\s+\(bind-([0-9]+\.[0-9]+\.[0-9]+)\.tar\.[^)]+\)\s+=\s+(\S+)\s*$", re.MULTILINE)
Expand Down Expand Up @@ -275,6 +276,27 @@ def render_assessment_markdown(assessment: Assessment) -> str:
)


def upstream_bind_release_tag(version: str) -> str:
distversion = version.split("_", maxsplit=1)[0]
_version_tuple(distversion)
return f"v{distversion}"


def render_commit_log_markdown(title: str, commit_log_text: str, empty_message: str) -> str:
lines: list[str] = []
for raw_line in commit_log_text.splitlines():
line = raw_line.strip()
if not line:
continue
parts = line.split(maxsplit=1)
commit = parts[0]
subject = parts[1] if len(parts) > 1 else ""
lines.append(f"- `{commit}` {subject}".rstrip())
if not lines:
lines = [f"- {empty_message}"]
return f"### {title}\n\n" + "\n".join(lines) + "\n"


def main() -> None:
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest="command", required=True)
Expand All @@ -295,6 +317,13 @@ def main() -> None:
assess_parser.add_argument("--old-makefile", type=Path)
assess_parser.add_argument("--new-makefile", type=Path)
assess_parser.add_argument("--output", type=Path, required=True)
tag_parser = subparsers.add_parser("upstream-tag")
tag_parser.add_argument("--version", required=True)
render_parser = subparsers.add_parser("render-commit-log")
render_parser.add_argument("--title", required=True)
render_parser.add_argument("--commits", type=Path, required=True)
render_parser.add_argument("--empty-message", required=True)
render_parser.add_argument("--output", type=Path, required=True)
arguments = parser.parse_args()
if arguments.command == "update-profile":
update_profile(
Expand Down Expand Up @@ -326,6 +355,17 @@ def main() -> None:
new_makefile_text,
)
arguments.output.write_text(render_assessment_markdown(assessment), encoding="utf-8")
elif arguments.command == "upstream-tag":
print(upstream_bind_release_tag(arguments.version))
elif arguments.command == "render-commit-log":
arguments.output.write_text(
render_commit_log_markdown(
arguments.title,
arguments.commits.read_text(encoding="utf-8"),
arguments.empty_message,
),
encoding="utf-8",
)


if __name__ == "__main__":
Expand Down
52 changes: 49 additions & 3 deletions .github/ci/ci-tests/test_bind920_candidate.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
candidate_is_newer = bind920_candidate.candidate_is_newer
parse_bind920_makefile = bind920_candidate.parse_bind920_makefile
render_updated_profile = bind920_candidate.render_updated_profile
render_commit_log_markdown = bind920_candidate.render_commit_log_markdown
upstream_bind_release_tag = bind920_candidate.upstream_bind_release_tag


class Bind920CandidateTest(unittest.TestCase):
Expand Down Expand Up @@ -188,6 +190,41 @@ def test_assessment_summary_is_stable(self) -> None:
result.summary,
)

def test_upstream_bind_release_tag_strips_portrevision(self) -> None:
"""Upstream BIND tags must be based on BIND versions, not FreeBSD package revisions."""
self.assertEqual("v9.20.26", upstream_bind_release_tag("9.20.26_2"))
self.assertEqual("v9.20.27", upstream_bind_release_tag("9.20.27"))

def test_render_commit_log_markdown_lists_commit_subjects(self) -> None:
"""Candidate PRs should summarize upstream release commits without full commit bodies."""
rendered = render_commit_log_markdown(
"Upstream BIND Changes",
"abc1234 Fix resolver crash\n"
"def5678 Improve DNSSEC validation\n",
"No upstream commits were found.",
)

self.assertEqual(
"### Upstream BIND Changes\n\n"
"- `abc1234` Fix resolver crash\n"
"- `def5678` Improve DNSSEC validation\n",
rendered,
)

def test_render_commit_log_markdown_uses_fallback_when_empty(self) -> None:
"""PR bodies should explain missing upstream history instead of showing a blank section."""
rendered = render_commit_log_markdown(
"Upstream BIND Changes",
"\n",
"Could not resolve upstream BIND release tags.",
)

self.assertEqual(
"### Upstream BIND Changes\n\n"
"- Could not resolve upstream BIND release tags.\n",
rendered,
)

def test_render_updated_profile_preserves_key_order_and_updates_candidate_values(self) -> None:
"""Profile rewrites must be stable and limited to candidate values."""
current = Bind920Profile("repo", "old", "oldmake", "olddist", "9.20.26", 1)
Expand Down Expand Up @@ -426,11 +463,20 @@ def test_candidate_workflow_never_publishes_packages(self) -> None:
def test_candidate_workflow_includes_ports_commit_subjects_in_pr_body(self) -> None:
"""Review PRs must show the FreeBSD Ports commits behind the candidate."""
workflow = self.workflow_text()
self.assertIn("### FreeBSD Ports Changes", workflow)
self.assertIn("while read -r commit subject; do", workflow)
self.assertIn("printf -- '- `%s` %s\\n' \"$commit\" \"$subject\"", workflow)
self.assertIn("render-commit-log", workflow)
self.assertIn("--title \"FreeBSD Ports Changes\"", workflow)
self.assertIn("No dns/bind920 commits found between the pinned and candidate Ports commits.", workflow)

def test_candidate_workflow_includes_upstream_bind_commit_subjects_in_pr_body(self) -> None:
"""Review PRs must show upstream BIND commits between the old and new release tags."""
workflow = self.workflow_text()
self.assertIn("https://github.com/isc-projects/bind9.git", workflow)
self.assertIn("old_distversion=", workflow)
self.assertIn("--title \"Upstream BIND Changes\"", workflow)
self.assertIn("upstream-tag", workflow)
self.assertIn("git -C \"$RUNNER_TEMP/bind9\" log --format='%h %s' \"$old_tag..$new_tag\"", workflow)
self.assertIn("Could not resolve upstream BIND release tags.", workflow)

def test_candidate_workflow_uses_pinned_actions(self) -> None:
"""Workflow actions must stay pinned to immutable SHAs."""
workflow = self.workflow_text()
Expand Down
40 changes: 30 additions & 10 deletions .github/workflows/bind920-candidate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ jobs:
package_version = f"{candidate.distversion}_{candidate.portrevision}"
print(f"newer={'true' if newer else 'false'}", file=output)
print(f"old_version={old_package_version}", file=output)
print(f"old_distversion={current.distversion}", file=output)
print(f"new_version={package_version}", file=output)
print(f"candidate_distversion={candidate.distversion}", file=output)
print(f"portrevision={candidate.portrevision}", file=output)
Expand All @@ -115,6 +116,7 @@ jobs:
PORTS_DIFF: ${{ steps.ports.outputs.ports_diff }}
PORTS_LOG: ${{ steps.ports.outputs.ports_log }}
CURRENT_MAKEFILE: ${{ steps.ports.outputs.current_makefile }}
BIND_UPSTREAM_REPOSITORY: https://github.com/isc-projects/bind9.git
run: |
set -euo pipefail
printf '%s\n' "$CHANGELOG_TEXT" > "$RUNNER_TEMP/maintainer-notes.txt"
Expand All @@ -139,18 +141,36 @@ jobs:
--old-makefile "$CURRENT_MAKEFILE" \
--new-makefile "$PORTS_DIR/dns/bind920/Makefile" \
--output "$RUNNER_TEMP/assessment.md"
old_tag=$(python3 .github/ci/bind920_candidate.py upstream-tag \
--version '${{ steps.candidate.outputs.old_distversion }}')
new_tag=$(python3 .github/ci/bind920_candidate.py upstream-tag \
--version '${{ steps.candidate.outputs.candidate_distversion }}')
upstream_empty_message="No upstream BIND commits were found between $old_tag and $new_tag."
if git clone --filter=blob:none --no-checkout "$BIND_UPSTREAM_REPOSITORY" "$RUNNER_TEMP/bind9" \
&& git -C "$RUNNER_TEMP/bind9" fetch --no-tags origin \
"refs/tags/$old_tag:refs/tags/$old_tag" \
"refs/tags/$new_tag:refs/tags/$new_tag"; then
git -C "$RUNNER_TEMP/bind9" log --format='%h %s' "$old_tag..$new_tag" > "$RUNNER_TEMP/upstream.log"
else
upstream_empty_message="Could not resolve upstream BIND release tags."
: > "$RUNNER_TEMP/upstream.log"
fi
python3 .github/ci/bind920_candidate.py render-commit-log \
--title "Upstream BIND Changes" \
--commits "$RUNNER_TEMP/upstream.log" \
--empty-message "$upstream_empty_message" \
--output "$RUNNER_TEMP/upstream-changes.md"
python3 .github/ci/bind920_candidate.py render-commit-log \
--title "FreeBSD Ports Changes" \
--commits "$PORTS_LOG" \
--empty-message "No dns/bind920 commits found between the pinned and candidate Ports commits." \
--output "$RUNNER_TEMP/ports-changes.md"
{
cat "$RUNNER_TEMP/assessment.md"
printf '\n### FreeBSD Ports Changes\n\n'
if [ -s "$PORTS_LOG" ]; then
while read -r commit subject; do
if [ -n "$commit" ]; then
printf -- '- `%s` %s\n' "$commit" "$subject"
fi
done < "$PORTS_LOG"
else
printf -- '- No dns/bind920 commits found between the pinned and candidate Ports commits.\n'
fi
printf '\n'
cat "$RUNNER_TEMP/upstream-changes.md"
printf '\n'
cat "$RUNNER_TEMP/ports-changes.md"
printf '\n### Candidate Inputs\n\n'
printf -- '- FreeBSD Ports commit: `%s`\n' "$CANDIDATE_COMMIT"
printf -- '- Previous FreeBSD Ports commit: `%s`\n' '${{ steps.ports.outputs.current_commit }}'
Expand Down
Loading