Skip to content

Commit

Permalink
Add Github workflow to check _psl DNS entries on PRs
Browse files Browse the repository at this point in the history
  • Loading branch information
simon-friedberger committed Mar 6, 2024
1 parent 11e07e0 commit 7ce93da
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 0 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/check_pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Check PR

on:
pull_request_target:
paths:
- "public_suffix_list.dat"

permissions:
pull-requests: write

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.base.ref }}
path: local
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
path: other
- uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: "pip"
- run: pip install -r local/tools/pr_checker/requirements.txt
- run: python local/tools/pr_checker/check_dns.py local/public_suffix_list.dat other/public_suffix_list.dat ${{ github.event.pull_request.number }}
- uses: actions/github-script@v7
with:
script: |
github.rest.issues.addLabels({
issue_number: context.payload.pull_request.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['Autocheck Success']
})
94 changes: 94 additions & 0 deletions tools/pr_checker/check_dns.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import click
import dns.message
import dns.name
import dns.query
import dns.resolver
import re


def read_rules(psl_filename):
rules = set()

with open(psl_filename) as f:
for line in f:
line = line.strip()

if line == "":
continue

if line.startswith("//"):
continue

rules.add(line)
return rules


def rule2fqdn(rule):
if rule.startswith("*."):
rule = rule[2:]

if rule.startswith("!"):
rule = rule[1:]

if any(illegal_char in rule for illegal_char in "!*"):
print(rule)
assert False

return rule


def check_dns_pr(rule, pr_id):
print(f" Rule: {rule}")
name = dns.name.from_text(rule)
pslname = dns.name.from_text("_psl." + rule2fqdn(rule))
print(f" Checking TXT entry for {pslname}")
try:
answer = dns.resolver.resolve(pslname, "TXT")
except dns.resolver.NoNameservers as e:
print(f" No nameserver found for {pslname}.")
return False
except dns.resolver.NXDOMAIN:
print(f" No _psl entry for {name}.")
return False
except dns.resolver.NoAnswer:
print(f" No answer from nameserver for {pslname}.")
return False

for rdata in answer:
if match := re.match(r"\"https://github.com/publicsuffix/list/pull/(\d+)\"", str(rdata)):
dns_pr_id = int(match[1])
print(f" DNS answer: {match[0]} -> PR {dns_pr_id}")
if dns_pr_id == pr_id:
return True
else:
print(f" DNS _psl entry incorrect expected PR {pr_id} != {dns_pr_id}.")
return False
print("No DNS entry with pull request URL found.")
return False


@click.command()
@click.argument('current_filename')
@click.argument('pull_request_filename')
@click.argument('pr_id', type=click.INT)
def main(current_filename, pull_request_filename, pr_id):
current_rules = read_rules(current_filename)
pull_request_rules = read_rules(pull_request_filename)

all_good = True
removed = current_rules.difference(pull_request_rules)
print("The following rules have been removed:")
for rule in removed:
if not check_dns_pr(rule, pr_id): all_good = False

added = pull_request_rules.difference(current_rules)

print("The following rules have been added:")
for rule in added:
if not check_dns_pr(rule, pr_id): all_good = False

if not all_good:
exit(1)

if __name__ == "__main__":
main()
2 changes: 2 additions & 0 deletions tools/pr_checker/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
click==8.1.7
dnspython==2.5.0

0 comments on commit 7ce93da

Please sign in to comment.