mirror of
https://github.com/dgtlmoon/changedetection.io.git
synced 2025-11-23 18:06:09 +00:00
Compare commits
8 Commits
browserste
...
0.45.11
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93e1dc0e14 | ||
|
|
3ac0c9346c | ||
|
|
b6d8db4c67 | ||
|
|
436a66d465 | ||
|
|
764514e5eb | ||
|
|
ad3ffb6ccb | ||
|
|
e051b29bf2 | ||
|
|
126852b778 |
72
.github/workflows/pypi-release.yml
vendored
Normal file
72
.github/workflows/pypi-release.yml
vendored
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
name: Publish Python 🐍distribution 📦 to PyPI and TestPyPI
|
||||||
|
|
||||||
|
on: push
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build distribution 📦
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: "3.x"
|
||||||
|
- name: Install pypa/build
|
||||||
|
run: >-
|
||||||
|
python3 -m
|
||||||
|
pip install
|
||||||
|
build
|
||||||
|
--user
|
||||||
|
- name: Build a binary wheel and a source tarball
|
||||||
|
run: python3 -m build
|
||||||
|
- name: Store the distribution packages
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: python-package-distributions
|
||||||
|
path: dist/
|
||||||
|
|
||||||
|
|
||||||
|
test-pypi-package:
|
||||||
|
name: Test the built 📦 package works basically.
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
steps:
|
||||||
|
- name: Download all the dists
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: python-package-distributions
|
||||||
|
path: dist/
|
||||||
|
- name: Test that the basic pip built package runs without error
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
pip3 install dist/changedetection.io*.whl
|
||||||
|
changedetection.io -d /tmp -p 10000 &
|
||||||
|
sleep 3
|
||||||
|
curl http://127.0.0.1:10000/static/styles/pure-min.css >/dev/null
|
||||||
|
curl http://127.0.0.1:10000/ >/dev/null
|
||||||
|
killall changedetection.io
|
||||||
|
|
||||||
|
|
||||||
|
publish-to-pypi:
|
||||||
|
name: >-
|
||||||
|
Publish Python 🐍 distribution 📦 to PyPI
|
||||||
|
if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
|
||||||
|
needs:
|
||||||
|
- test-pypi-package
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment:
|
||||||
|
name: release
|
||||||
|
url: https://pypi.org/p/changedetection.io
|
||||||
|
permissions:
|
||||||
|
id-token: write # IMPORTANT: mandatory for trusted publishing
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Download all the dists
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: python-package-distributions
|
||||||
|
path: dist/
|
||||||
|
- name: Publish distribution 📦 to PyPI
|
||||||
|
uses: pypa/gh-action-pypi-publish@release/v1
|
||||||
36
.github/workflows/test-pip-build.yml
vendored
36
.github/workflows/test-pip-build.yml
vendored
@@ -1,36 +0,0 @@
|
|||||||
name: ChangeDetection.io PIP package test
|
|
||||||
|
|
||||||
# Triggers the workflow on push or pull request events
|
|
||||||
|
|
||||||
# This line doesnt work, even tho it is the documented one
|
|
||||||
on: [push, pull_request]
|
|
||||||
|
|
||||||
# Changes to requirements.txt packages and Dockerfile may or may not always be compatible with arm etc, so worth testing
|
|
||||||
# @todo: some kind of path filter for requirements.txt and Dockerfile
|
|
||||||
jobs:
|
|
||||||
test-pip-build-basics:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Python 3.11
|
|
||||||
uses: actions/setup-python@v4
|
|
||||||
with:
|
|
||||||
python-version: 3.11
|
|
||||||
|
|
||||||
|
|
||||||
- name: Test that the basic pip built package runs without error
|
|
||||||
run: |
|
|
||||||
set -e
|
|
||||||
mkdir dist
|
|
||||||
pip3 install wheel
|
|
||||||
python3 setup.py bdist_wheel
|
|
||||||
pip3 install -r requirements.txt
|
|
||||||
rm ./changedetection.py
|
|
||||||
rm -rf changedetectio
|
|
||||||
|
|
||||||
pip3 install dist/changedetection.io*.whl
|
|
||||||
changedetection.io -d /tmp -p 10000 &
|
|
||||||
sleep 3
|
|
||||||
curl http://127.0.0.1:10000/static/styles/pure-min.css >/dev/null
|
|
||||||
killall -9 changedetection.io
|
|
||||||
@@ -10,6 +10,8 @@ prune changedetectionio/static/package-lock.json
|
|||||||
prune changedetectionio/static/styles/node_modules
|
prune changedetectionio/static/styles/node_modules
|
||||||
prune changedetectionio/static/styles/package-lock.json
|
prune changedetectionio/static/styles/package-lock.json
|
||||||
include changedetection.py
|
include changedetection.py
|
||||||
|
include requirements.txt
|
||||||
|
include README-pip.md
|
||||||
global-exclude *.pyc
|
global-exclude *.pyc
|
||||||
global-exclude node_modules
|
global-exclude node_modules
|
||||||
global-exclude venv
|
global-exclude venv
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ Please :star: star :star: this project and help it grow! https://github.com/dgtl
|
|||||||
With Docker composer, just clone this repository and..
|
With Docker composer, just clone this repository and..
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ docker-compose up -d
|
$ docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
Docker standalone
|
Docker standalone
|
||||||
@@ -137,10 +137,10 @@ docker rm $(docker ps -a -f name=changedetection.io -q)
|
|||||||
docker run -d --restart always -p "127.0.0.1:5000:5000" -v datastore-volume:/datastore --name changedetection.io dgtlmoon/changedetection.io
|
docker run -d --restart always -p "127.0.0.1:5000:5000" -v datastore-volume:/datastore --name changedetection.io dgtlmoon/changedetection.io
|
||||||
```
|
```
|
||||||
|
|
||||||
### docker-compose
|
### docker compose
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose pull && docker-compose up -d
|
docker compose pull && docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
See the wiki for more information https://github.com/dgtlmoon/changedetection.io/wiki
|
See the wiki for more information https://github.com/dgtlmoon/changedetection.io/wiki
|
||||||
|
|||||||
21
app.json
21
app.json
@@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "ChangeDetection.io",
|
|
||||||
"description": "The best and simplest self-hosted open source website change detection monitoring and notification service.",
|
|
||||||
"keywords": [
|
|
||||||
"changedetection",
|
|
||||||
"website monitoring"
|
|
||||||
],
|
|
||||||
"repository": "https://github.com/dgtlmoon/changedetection.io",
|
|
||||||
"success_url": "/",
|
|
||||||
"scripts": {
|
|
||||||
},
|
|
||||||
"env": {
|
|
||||||
},
|
|
||||||
"formation": {
|
|
||||||
"web": {
|
|
||||||
"quantity": 1,
|
|
||||||
"size": "free"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"image": "heroku/python"
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Read more https://github.com/dgtlmoon/changedetection.io/wiki
|
# Read more https://github.com/dgtlmoon/changedetection.io/wiki
|
||||||
|
|
||||||
__version__ = '0.45.9'
|
__version__ = '0.45.11'
|
||||||
|
|
||||||
from distutils.util import strtobool
|
from distutils.util import strtobool
|
||||||
from json.decoder import JSONDecodeError
|
from json.decoder import JSONDecodeError
|
||||||
|
|||||||
@@ -43,9 +43,11 @@ class JSActionExceptions(Exception):
|
|||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
class BrowserStepsStepTimout(Exception):
|
class BrowserStepsStepException(Exception):
|
||||||
def __init__(self, step_n):
|
def __init__(self, step_n, original_e):
|
||||||
self.step_n = step_n
|
self.step_n = step_n
|
||||||
|
self.original_e = original_e
|
||||||
|
print(f"Browser Steps exception at step {self.step_n}", str(original_e))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
@@ -173,7 +175,7 @@ class Fetcher():
|
|||||||
|
|
||||||
def iterate_browser_steps(self):
|
def iterate_browser_steps(self):
|
||||||
from changedetectionio.blueprint.browser_steps.browser_steps import steppable_browser_interface
|
from changedetectionio.blueprint.browser_steps.browser_steps import steppable_browser_interface
|
||||||
from playwright._impl._errors import TimeoutError
|
from playwright._impl._errors import TimeoutError, Error
|
||||||
from jinja2 import Environment
|
from jinja2 import Environment
|
||||||
jinja2_env = Environment(extensions=['jinja2_time.TimeExtension'])
|
jinja2_env = Environment(extensions=['jinja2_time.TimeExtension'])
|
||||||
|
|
||||||
@@ -203,10 +205,10 @@ class Fetcher():
|
|||||||
optional_value=optional_value)
|
optional_value=optional_value)
|
||||||
self.screenshot_step(step_n)
|
self.screenshot_step(step_n)
|
||||||
self.save_step_html(step_n)
|
self.save_step_html(step_n)
|
||||||
except TimeoutError as e:
|
|
||||||
print(str(e))
|
except (Error, TimeoutError) as e:
|
||||||
# Stop processing here
|
# Stop processing here
|
||||||
raise BrowserStepsStepTimout(step_n=step_n)
|
raise BrowserStepsStepException(step_n=step_n, original_e=e)
|
||||||
|
|
||||||
# It's always good to reset these
|
# It's always good to reset these
|
||||||
def delete_browser_steps_screenshots(self):
|
def delete_browser_steps_screenshots(self):
|
||||||
|
|||||||
@@ -188,9 +188,9 @@ class update_worker(threading.Thread):
|
|||||||
return
|
return
|
||||||
threshold = self.datastore.data['settings']['application'].get('filter_failure_notification_threshold_attempts')
|
threshold = self.datastore.data['settings']['application'].get('filter_failure_notification_threshold_attempts')
|
||||||
n_object = {'notification_title': "Changedetection.io - Alert - Browser step at position {} could not be run".format(step_n+1),
|
n_object = {'notification_title': "Changedetection.io - Alert - Browser step at position {} could not be run".format(step_n+1),
|
||||||
'notification_body': "Your configured browser step at position {} for {{watch['url']}} "
|
'notification_body': "Your configured browser step at position {} for {{{{watch_url}}}} "
|
||||||
"did not appear on the page after {} attempts, did the page change layout? "
|
"did not appear on the page after {} attempts, did the page change layout? "
|
||||||
"Does it need a delay added?\n\nLink: {{base_url}}/edit/{{watch_uuid}}\n\n"
|
"Does it need a delay added?\n\nLink: {{{{base_url}}}}/edit/{{{{watch_uuid}}}}\n\n"
|
||||||
"Thanks - Your omniscient changedetection.io installation :)\n".format(step_n+1, threshold),
|
"Thanks - Your omniscient changedetection.io installation :)\n".format(step_n+1, threshold),
|
||||||
'notification_format': 'text'}
|
'notification_format': 'text'}
|
||||||
|
|
||||||
@@ -354,20 +354,32 @@ class update_worker(threading.Thread):
|
|||||||
changed_detected = False
|
changed_detected = False
|
||||||
self.datastore.update_watch(uuid=uuid, update_obj={'last_error': False})
|
self.datastore.update_watch(uuid=uuid, update_obj={'last_error': False})
|
||||||
|
|
||||||
except content_fetcher.BrowserStepsStepTimout as e:
|
except content_fetcher.BrowserStepsStepException as e:
|
||||||
|
|
||||||
if not self.datastore.data['watching'].get(uuid):
|
if not self.datastore.data['watching'].get(uuid):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
error_step = e.step_n + 1
|
error_step = e.step_n + 1
|
||||||
err_text = f"Warning, browser step at position {error_step} could not run, target not found, check the watch, add a delay if necessary, view Browser Steps to see screenshot at that step"
|
from playwright._impl._errors import TimeoutError, Error
|
||||||
|
|
||||||
|
# Generally enough info for TimeoutError (couldnt locate the element after default seconds)
|
||||||
|
err_text = f"Browser step at position {error_step} could not run, check the watch, add a delay if necessary, view Browser Steps to see screenshot at that step."
|
||||||
|
|
||||||
|
if e.original_e.name == "TimeoutError":
|
||||||
|
# Just the first line is enough, the rest is the stack trace
|
||||||
|
err_text += " Could not find the target."
|
||||||
|
else:
|
||||||
|
# Other Error, more info is good.
|
||||||
|
err_text += " " + str(e.original_e).splitlines()[0]
|
||||||
|
|
||||||
|
print(f"BrowserSteps exception at step {error_step}", str(e.original_e))
|
||||||
|
|
||||||
self.datastore.update_watch(uuid=uuid,
|
self.datastore.update_watch(uuid=uuid,
|
||||||
update_obj={'last_error': err_text,
|
update_obj={'last_error': err_text,
|
||||||
'browser_steps_last_error_step': error_step
|
'browser_steps_last_error_step': error_step
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if self.datastore.data['watching'][uuid].get('filter_failure_notification_send', False):
|
if self.datastore.data['watching'][uuid].get('filter_failure_notification_send', False):
|
||||||
c = self.datastore.data['watching'][uuid].get('consecutive_filter_failures', 5)
|
c = self.datastore.data['watching'][uuid].get('consecutive_filter_failures', 5)
|
||||||
c += 1
|
c += 1
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
run:
|
|
||||||
changedetection: python3 ./changedetection.py -C -d ./datastore -p $PORT
|
|
||||||
4
setup.py
4
setup.py
@@ -27,7 +27,7 @@ install_requires = open('requirements.txt').readlines()
|
|||||||
setup(
|
setup(
|
||||||
name='changedetection.io',
|
name='changedetection.io',
|
||||||
version=find_version("changedetectionio", "__init__.py"),
|
version=find_version("changedetectionio", "__init__.py"),
|
||||||
description='Website change detection and monitoring service',
|
description='Website change detection and monitoring service, detect changes to web pages and send alerts/notifications.',
|
||||||
long_description=open('README-pip.md').read(),
|
long_description=open('README-pip.md').read(),
|
||||||
long_description_content_type='text/markdown',
|
long_description_content_type='text/markdown',
|
||||||
keywords='website change monitor for changes notification change detection '
|
keywords='website change monitor for changes notification change detection '
|
||||||
@@ -41,7 +41,7 @@ setup(
|
|||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
install_requires=install_requires,
|
install_requires=install_requires,
|
||||||
license="Apache License 2.0",
|
license="Apache License 2.0",
|
||||||
python_requires=">= 3.7",
|
python_requires=">= 3.10",
|
||||||
classifiers=['Intended Audience :: Customer Service',
|
classifiers=['Intended Audience :: Customer Service',
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
'Intended Audience :: Education',
|
'Intended Audience :: Education',
|
||||||
|
|||||||
Reference in New Issue
Block a user