mirror-cockpit-project-cockpit/tools/urls-check

142 lines
4.5 KiB
Text
Raw Permalink Normal View History

all: replace `import parent` with an interpreter line hack We'd like to run our executable python scripts using our new `pywrap` feature as a better way to get their PYTHONPATH setup properly. This script lives in our source tree, at a fixed relative location to each script that we're interested in, but has no absolute system path. The #!interpreter syntax does supports relative paths, but they are resolved relative to the current working directory, not relative to the file in which they appear, which makes this feature pretty useless. There are some tricks we can do to get our designed 'relative' behaviour, though. Something like this works: #!/usr/bin/env -S sh -c '"${0%/*}/pywrap" "$0"' but it causes various file auto-detection schemes (including our own test/static-code) to improperly conclude that this is a shell script, rather than a Python script. (n)vim also gets it wrong for highlighting and linting purposes. Fortunately there's a somewhat longer, but still acceptable version of this we can do in Python: #!/usr/bin/python3 -cimport os, sys; os.execv(os.path.dirname(sys.argv[1]) + "/pywrap", sys.argv) This fits well under our 118 column limit. Note that unlike `sh`, the `-c` option in Python doesn't require the script to be passed as a separate argument, which means we don't need to use the non-POSIX splitting tricks of `/usr/bin/env -S`. Note also: it appears as though our hardcoding of /usr/bin/python3 here might be venv-unfriendly, but it's not: /usr/bin/python3 (which surely exists) is used only for running this one tiny fragment of code. Our pywrap script itself finds python3 in the path. Let's move all of our previous users of `import parent` over to the new approach. We can remove a couple of `parent.py` symlinks we had lying around, as well. We also remove `parent.py` itself, since otherwise vulture complains about it being unused. Subprojects will be forced to adjust on upgrade. Remove a CodeQL exemption that was necessitated by our `import parent` shenanigans.
2023-05-26 00:57:53 -08:00
#!/usr/bin/python3 -cimport os, sys; os.execv(os.path.dirname(sys.argv[1]) + "/../test/common/pywrap", sys.argv)
#
# Copyright (C) 2020 Red Hat, Inc.
# SPDX-License-Identifier: LGPL-2.1-or-later
import argparse
import fnmatch
all: replace `import parent` with an interpreter line hack We'd like to run our executable python scripts using our new `pywrap` feature as a better way to get their PYTHONPATH setup properly. This script lives in our source tree, at a fixed relative location to each script that we're interested in, but has no absolute system path. The #!interpreter syntax does supports relative paths, but they are resolved relative to the current working directory, not relative to the file in which they appear, which makes this feature pretty useless. There are some tricks we can do to get our designed 'relative' behaviour, though. Something like this works: #!/usr/bin/env -S sh -c '"${0%/*}/pywrap" "$0"' but it causes various file auto-detection schemes (including our own test/static-code) to improperly conclude that this is a shell script, rather than a Python script. (n)vim also gets it wrong for highlighting and linting purposes. Fortunately there's a somewhat longer, but still acceptable version of this we can do in Python: #!/usr/bin/python3 -cimport os, sys; os.execv(os.path.dirname(sys.argv[1]) + "/pywrap", sys.argv) This fits well under our 118 column limit. Note that unlike `sh`, the `-c` option in Python doesn't require the script to be passed as a separate argument, which means we don't need to use the non-POSIX splitting tricks of `/usr/bin/env -S`. Note also: it appears as though our hardcoding of /usr/bin/python3 here might be venv-unfriendly, but it's not: /usr/bin/python3 (which surely exists) is used only for running this one tiny fragment of code. Our pywrap script itself finds python3 in the path. Let's move all of our previous users of `import parent` over to the new approach. We can remove a couple of `parent.py` symlinks we had lying around, as well. We also remove `parent.py` itself, since otherwise vulture complains about it being unused. Subprojects will be forced to adjust on upgrade. Remove a CodeQL exemption that was necessitated by our `import parent` shenanigans.
2023-05-26 00:57:53 -08:00
import os
import subprocess
import sys
import time
import urllib
from urllib.request import Request, urlopen
from lib.github import GitHub
all: replace `import parent` with an interpreter line hack We'd like to run our executable python scripts using our new `pywrap` feature as a better way to get their PYTHONPATH setup properly. This script lives in our source tree, at a fixed relative location to each script that we're interested in, but has no absolute system path. The #!interpreter syntax does supports relative paths, but they are resolved relative to the current working directory, not relative to the file in which they appear, which makes this feature pretty useless. There are some tricks we can do to get our designed 'relative' behaviour, though. Something like this works: #!/usr/bin/env -S sh -c '"${0%/*}/pywrap" "$0"' but it causes various file auto-detection schemes (including our own test/static-code) to improperly conclude that this is a shell script, rather than a Python script. (n)vim also gets it wrong for highlighting and linting purposes. Fortunately there's a somewhat longer, but still acceptable version of this we can do in Python: #!/usr/bin/python3 -cimport os, sys; os.execv(os.path.dirname(sys.argv[1]) + "/pywrap", sys.argv) This fits well under our 118 column limit. Note that unlike `sh`, the `-c` option in Python doesn't require the script to be passed as a separate argument, which means we don't need to use the non-POSIX splitting tricks of `/usr/bin/env -S`. Note also: it appears as though our hardcoding of /usr/bin/python3 here might be venv-unfriendly, but it's not: /usr/bin/python3 (which surely exists) is used only for running this one tiny fragment of code. Our pywrap script itself finds python3 in the path. Let's move all of our previous users of `import parent` over to the new approach. We can remove a couple of `parent.py` symlinks we had lying around, as well. We also remove `parent.py` itself, since otherwise vulture complains about it being unused. Subprojects will be forced to adjust on upgrade. Remove a CodeQL exemption that was necessitated by our `import parent` shenanigans.
2023-05-26 00:57:53 -08:00
BASE_DIR = os.path.realpath(f'{__file__}/../..')
DAYS = 7
TASK_NAME = "Validate all URLs"
github = GitHub()
USER_AGENT = "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:90.0) Gecko/20100101 Firefox/90.0"
IGNORE = [
"https://www.gnome.org", # keeps causing 403 from GitHub; DNS or user-agent ban?
"*example.com*", # some tests use demo urls
]
KNOWN_REDIRECTS = [
# fnmatch-like
"https://access.redhat.com/security/updates/classification/#",
"https://firefox.com/",
"https://www.microsoft.com/",
"https://github.com/patternfly/*",
# SVG/XML processing in *.jsx
"http://www.w3.org/2000/svg",
"http://www.w3.org/XML/1998/namespace",
]
tools: Link checker warns about redirections Currently it would succeed, but would print this output: ``` Checked 133 URLs and all are valid. Following URLs are redirected: http://cloud.redhat.com/insights http://cloud.redhat.com/insights/inventory/ https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/managing-networking-in-the-web-console_system-management-using-the-rhel-8-web-console https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/managing-networking-in-the-web-console_system-management-using-the-rhel-8-web-console#configuring-network-bonds-using-the-web-console_managing-networking-in-the-web-console https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/managing-storage-devices-in-the-web-console_system-management-using-the-rhel-8-web-console https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/performing-basic-system-administration-tasks-in-the-web-console_system-management-using-the-rhel-8-web-console https://access.redhat.com/security/updates/classification/# https://apple.com/safari/ https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload https://firefox.com/ https://github.com/patternfly/patternfly/issues/3053 https://github.com/patternfly/patternfly-react/issues/4777 https://github.com/storaged-project/storaged/issues/26 https://github.com/storaged-project/storaged/pull/68 https://github.com/systemd/systemd/blob/master/src/systemctl/systemctl.c https://google.com/chrome https://microsoftedge.com/ https://patternfly-next-pr-2757.surge.sh/documentation/core/components/tabs https://udisks.freedesktop.org/docs/latest/gdbus-org.freedesktop.UDisks2.Block.html#gdbus-method-org-freedesktop-UDisks2-Block.GetSecretConfiguration https://www.patternfly.org/v4/components/table https://www.redhat.com/archives/libvir-list/2019-January/msg01104.html ```
2021-02-15 05:40:57 -09:00
def main():
parser = argparse.ArgumentParser(description=TASK_NAME)
parser.add_argument("-v", "--verbose", action="store_true", help="Verbose output")
parser.add_argument('-n', '--dry-run', action="store_true",
help="Only show urls")
opts = parser.parse_args()
if opts.dry_run:
(success, err) = check_urls(opts.verbose)
print(err)
print(success)
sys.exit(1 if err else 0)
since = time.time() - (DAYS * 86400)
# When there is an open issue, don't do anything
issues = github.issues(state="open")
issues = [i for i in issues if i["title"] == TASK_NAME]
if issues:
return
issues = github.issues(state="closed", since=since)
issues = [i for i in issues if i["title"] == TASK_NAME]
# If related issue was not modified in last n-DAYS, then do your thing
if not issues:
(success, err) = check_urls(opts.verbose)
if err:
# Create a new issue
data = {
"title": TASK_NAME,
"body": err,
"labels": ["bot"]
}
github.post("issues", data)
else:
# Try to comment on the last issue (look in the last 4*DAYS)
# If there is not issue to be found, then just open a new one and close it
success = success or "Task hasn't produced any output"
since = time.time() - (DAYS * 4 * 86400)
issues = github.issues(state="closed", since=since)
issues = [i for i in issues if i["title"] == TASK_NAME]
if issues:
github.comment(issues[0]["number"], success)
else:
data = {
"title": TASK_NAME,
"body": success,
"labels": ["bot"]
}
new_issue = github.post("issues", data)
github.patch(f"issues/{new_issue['number']}", {"state": "closed"})
def check_urls(verbose):
command = r'git grep -IEho "(https?)://[-a-zA-Z0-9@:%_\+.~#?&=/]+" -- pkg ":!*.svg" | sort -u'
urls = subprocess.check_output(command, shell=True, universal_newlines=True, cwd=BASE_DIR).split("\n")
tools: Link checker warns about redirections Currently it would succeed, but would print this output: ``` Checked 133 URLs and all are valid. Following URLs are redirected: http://cloud.redhat.com/insights http://cloud.redhat.com/insights/inventory/ https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/managing-networking-in-the-web-console_system-management-using-the-rhel-8-web-console https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/managing-networking-in-the-web-console_system-management-using-the-rhel-8-web-console#configuring-network-bonds-using-the-web-console_managing-networking-in-the-web-console https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/managing-storage-devices-in-the-web-console_system-management-using-the-rhel-8-web-console https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/performing-basic-system-administration-tasks-in-the-web-console_system-management-using-the-rhel-8-web-console https://access.redhat.com/security/updates/classification/# https://apple.com/safari/ https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload https://firefox.com/ https://github.com/patternfly/patternfly/issues/3053 https://github.com/patternfly/patternfly-react/issues/4777 https://github.com/storaged-project/storaged/issues/26 https://github.com/storaged-project/storaged/pull/68 https://github.com/systemd/systemd/blob/master/src/systemctl/systemctl.c https://google.com/chrome https://microsoftedge.com/ https://patternfly-next-pr-2757.surge.sh/documentation/core/components/tabs https://udisks.freedesktop.org/docs/latest/gdbus-org.freedesktop.UDisks2.Block.html#gdbus-method-org-freedesktop-UDisks2-Block.GetSecretConfiguration https://www.patternfly.org/v4/components/table https://www.redhat.com/archives/libvir-list/2019-January/msg01104.html ```
2021-02-15 05:40:57 -09:00
redirects = []
failed = []
for url in urls:
if not url:
continue
if any(fnmatch.fnmatch(url, pattern) for pattern in IGNORE):
if verbose:
print(f"Ignoring: {url}")
continue
if verbose:
print(f"Checking: {url}")
try:
# Specify agent as some websites otherwise block requests
req = Request(url=url, headers={"User-Agent": USER_AGENT})
resp = urlopen(req)
if resp.geturl() != url and not any(fnmatch.fnmatch(url, pattern) for pattern in KNOWN_REDIRECTS):
tools: Link checker warns about redirections Currently it would succeed, but would print this output: ``` Checked 133 URLs and all are valid. Following URLs are redirected: http://cloud.redhat.com/insights http://cloud.redhat.com/insights/inventory/ https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/managing-networking-in-the-web-console_system-management-using-the-rhel-8-web-console https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/managing-networking-in-the-web-console_system-management-using-the-rhel-8-web-console#configuring-network-bonds-using-the-web-console_managing-networking-in-the-web-console https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/managing-storage-devices-in-the-web-console_system-management-using-the-rhel-8-web-console https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/performing-basic-system-administration-tasks-in-the-web-console_system-management-using-the-rhel-8-web-console https://access.redhat.com/security/updates/classification/# https://apple.com/safari/ https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload https://firefox.com/ https://github.com/patternfly/patternfly/issues/3053 https://github.com/patternfly/patternfly-react/issues/4777 https://github.com/storaged-project/storaged/issues/26 https://github.com/storaged-project/storaged/pull/68 https://github.com/systemd/systemd/blob/master/src/systemctl/systemctl.c https://google.com/chrome https://microsoftedge.com/ https://patternfly-next-pr-2757.surge.sh/documentation/core/components/tabs https://udisks.freedesktop.org/docs/latest/gdbus-org.freedesktop.UDisks2.Block.html#gdbus-method-org-freedesktop-UDisks2-Block.GetSecretConfiguration https://www.patternfly.org/v4/components/table https://www.redhat.com/archives/libvir-list/2019-January/msg01104.html ```
2021-02-15 05:40:57 -09:00
redirects.append(url)
if resp.getcode() >= 400:
failed.append(f"{url} : {resp.getcode()} {resp.reason}")
except urllib.error.URLError as e:
2024-06-19 04:05:42 -08:00
failed.append(f"{url} : {e.reason}")
err = ""
success = ""
if failed:
err = f"Checked {len(urls)} URLs out of which {len(failed)} is/are invalid:\n"
err += ''.join(f' {url}\n' for url in failed)
else:
success = f"Checked {len(urls)} URLs and all are valid."
if redirects:
success += "\nFollowing URLs are redirected:\n"
success += ''.join(f' {url}\n' for url in redirects)
return success, err
if __name__ == '__main__':
sys.exit(main())