Compare commits

...

21 Commits

Author SHA1 Message Date
Florian du Garage Num
ab18396e89 remove hard-coded uid 1000
Some checks failed
Sync with private repo / sync (push) Has been cancelled
Run tests / tests (3.12) (push) Has been cancelled
Run tests / tests (3.9) (push) Has been cancelled
2025-09-30 21:47:30 +02:00
Syed Muhammad Dawoud Sheraz Ali
ae4e3f20ac
feat: migrate to ruff for linting and formatting checks (#50) 2025-09-24 10:30:18 +05:00
Ahmed Khalid
4fde7e355b
Merge pull request #49 from overhangio/teak 2025-06-27 17:04:20 +05:00
Syed Muhammad Dawoud Sheraz Ali
1ff9c0bd77 chore: generate changelog for v20 2025-06-05 17:50:09 +05:00
jfavellar90
3fe46bc278 feat: upgrade to teak 2025-04-04 12:44:52 -05:00
Syed Muhammad Dawoud Sheraz Ali
cde10c2f97
v19.0.2 (#48) 2025-03-12 15:17:38 +05:00
Syed Muhammad Dawoud Sheraz Ali
97aed60b38
build: Add hatch_build in sdist to fix installation issues (#47)
* build: Add hatch_build in sdist to fix installation issues
2025-03-12 15:13:12 +05:00
jfavellar90
1465402bfa v19.0.1 2025-03-11 13:14:03 -05:00
Jhony Avella
8540aef9b8
feat: migrate from setup.py to pyproject.toml (#46)
* feat: migrate from setup.py to pyproject.toml

* chore: fixes

* chore: addressing PR comments

* chore: addressing more comments
2025-03-11 13:09:00 -05:00
Régis Behmo
9d91f7499d
fix: broken feature in dev mode (#43)
Student notes were simply not working in dev mode because the dev server
hostname was not whitelisted in ALLOWED_HOSTS.
2025-02-13 20:34:56 -05:00
Syed Muhammad Dawoud Sheraz Ali
3f0ff01105
build: re-add auto-add for PRs with a different target (#45) 2025-01-17 11:31:04 +05:00
Régis Behmo
e61f3cea5f
feat: Upgrade to Sumac 2024-12-16 21:58:16 +01:00
Syed Muhammad Dawoud Sheraz Ali
0267ffde12 chore: update changelog 2024-12-09 18:52:20 +05:00
Régis Behmo
6e8bc34475 feat: migrate to Meilisearch
We make use of a new search engine to search annotations. The index will
automatically be created and filled during init. This is considered a
breaking change if you have customised your notes index.
2024-11-29 22:28:03 +05:00
Régis Behmo
a61e09c11e fix: actually mount notes directory
Notes directory could be added via `tutor mounts add ./edx-notes-api`,
but it was not actually being mounted.
2024-11-29 22:28:03 +05:00
jfavellar90
e5fedc2d83 feat: upgrade to sumac 2024-11-29 22:28:01 +05:00
Régis Behmo
e52064fe64 Merge branch 'release' 2024-11-27 18:35:01 +01:00
Syed Muhammad Dawoud Sheraz Ali
75e64f5065 feat!: Rename branches master->release, nightly->main 2024-11-27 22:34:13 +05:00
Overhang.IO
7d16414908 Merge remote-tracking branch 'origin/master' into nightly 2024-11-14 16:25:16 +00:00
Jhony Avella
fdf73b62e3
Ubuntu 24.04 Upgrade (#39)
* chore: notes service now uses ubuntu 24.04 as base image

* chore: using 1000 UID. Updating setuptools

* chore: adding changelog entry
2024-10-22 16:07:32 -05:00
Régis Behmo
f9fcbf26f4 docs: *.local.edly.io -> *.local.openedx.io
The default URL to run a local platform switched from local.edly.io to
local.openedx.io. This changes makes it clearer for everyone that Tutor
is to run Open edX.

See: https://github.com/overhangio/tutor/issues/1120
2024-10-17 08:36:40 +02:00
22 changed files with 223 additions and 101 deletions

View File

@ -1,9 +1,12 @@
name: Auto Add Issues to Project
name: Auto Add Issues and Pull Requests to Project
on:
issues:
types:
- opened
pull_request_target:
types:
- opened
jobs:
# https://github.com/actions/add-to-project

View File

@ -2,7 +2,7 @@ name: Sync with private repo
on:
push:
branches: [ master, main, nightly ]
branches: [ release, main ]
jobs:
sync:

View File

@ -2,7 +2,9 @@ name: Run tests
on:
pull_request:
branches: [master]
branches: [ release, main ]
push:
branches: [ release, main ]
jobs:
tests:
@ -16,8 +18,6 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Upgrade pip
run: python -m pip install --upgrade pip setuptools
- name: Install dependencies
run: |
pip install .[dev]

21
.hatch_build.py Normal file
View File

@ -0,0 +1,21 @@
# https://hatch.pypa.io/latest/how-to/config/dynamic-metadata/
import os
import typing as t
from hatchling.metadata.plugin.interface import MetadataHookInterface
HERE = os.path.dirname(__file__)
class MetaDataHook(MetadataHookInterface):
def update(self, metadata: dict[str, t.Any]) -> None:
about = load_about()
metadata["version"] = about["__version__"]
def load_about() -> dict[str, str]:
about: dict[str, str] = {}
with open(os.path.join(HERE, "tutornotes", "__about__.py"), "rt", encoding="utf-8") as f:
exec(f.read(), about)
return about

View File

@ -19,6 +19,41 @@ instructions, because git commits are used to generate release notes:
<!-- scriv-insert-here -->
<a id='changelog-20.0.0'></a>
## v20.0.0 (2025-06-05)
- 💥[Feature] Upgrade to Teak. (by @jfavellar90)
<a id='changelog-19.0.2'></a>
## v19.0.2 (2025-03-12)
- [Improvement] Add hatch_build.py in sdist target to fix the installation issues (by @dawoudsheraz)
<a id='changelog-19.0.1'></a>
## v19.0.1 (2025-03-11)
- [Bugfix] Fix broken feature in `dev` mode, where the frontend is reporting a CORS error on loading the notes. (by @regisb)
- [Improvement] Migrate from `setup.py` (setuptools) to `pyproject.toml` (hatch). (by @jfavellar90)
<a id='changelog-19.0.0'></a>
## v19.0.0 (2024-10-24)
- [Bugfix] Fix legacy warnings during Docker build. (by @regisb)
- 💥[Feature] Update Notes Image to use Ubuntu 24.04 as base OS. (by @jfavellar90)
- [Bugfix] Actually mount edx-notes-api repositories from host on `tutor mounts add /path/to/edx-notes-api`. (by @regisb)
- 💥[Feature] Replace Elasticsearch by Meilisearch. The implementation is much more compact and readable. All content will be automatically re-indexed during init. (by @regisb)
- 💥 [Deprecation] Drop support for python 3.8 and set Python 3.9 as the minimum supported python version. (by @DawoudSheraz)
- 💥[Improvement] Rename Tutor's two branches (by @DawoudSheraz):
* Rename **master** to **release**, as this branch runs the latest official Open edX release tag.
* Rename **nightly** to **main**, as this branch runs the Open edX master branches, which are the basis for the next Open edX release.
- 💥[Feature] Upgrade to Sumac. (by @jfavellar90)
<a id='changelog-18.0.0'></a>
## v18.0.0 (2024-05-09)

View File

@ -1,2 +0,0 @@
recursive-include tutornotes/patches *
recursive-include tutornotes/templates *

View File

@ -1,22 +1,31 @@
.DEFAULT_GOAL := help
.PHONY: docs
SRC_DIRS = ./tutornotes
BLACK_OPTS = --exclude templates ${SRC_DIRS}
RUFF_OPTS = --exclude templates ${SRC_DIRS}
# Warning: These checks are run on every PR.
test: test-lint test-types test-format # Run some static checks.
test: test-lint test-types test-format test-pythonpackage
test-format: ## Run code formatting tests.
black --check --diff $(BLACK_OPTS)
ruff format --check --diff $(RUFF_OPTS)
test-lint: ## Run code linting tests
pylint --errors-only --enable=unused-import,unused-argument --ignore=templates --ignore=docs/_ext ${SRC_DIRS}
test-lint:
ruff check ${SRC_DIRS}
test-types: ## Run type checks.
mypy --exclude=templates --ignore-missing-imports --implicit-reexport --strict ${SRC_DIRS}
build-pythonpackage:
python -m build --sdist
test-pythonpackage: build-pythonpackage
twine check dist/tutor_notes-$(shell make version).tar.gz
format: ## Format code automatically.
black $(BLACK_OPTS)
ruff format $(RUFF_OPTS)
fix-lint: ## Fix linting issues automatically.
ruff check --fix $(RUFF_OPTS)
isort: ## Sort imports. This target is not mandatory because the output may be incompatible with black formatting. Provided for convenience purposes.
isort --skip=templates ${SRC_DIRS}
@ -27,6 +36,9 @@ changelog-entry: ## Create a new changelog entry.
changelog: ## Collect changelog entries in the CHANGELOG.md file.
scriv collect
version: ## Print the current tutor-notes version
@python -c 'import io, os; about = {}; exec(io.open(os.path.join("tutornotes", "__about__.py"), "rt", encoding="utf-8").read(), about); print(about["__version__"])'
ESCAPE = 
help: ## Print this help.
@grep -E '^([a-zA-Z_-]+:.*?## .*|######* .+)$$' Makefile \

View File

@ -1,9 +1,9 @@
Students notes plugin for `Tutor <https://docs.tutor.edly.io>`_
===================================================================
This is a plugin for `Tutor <https://docs.tutor.edly.io>`_ to easily add the `Open edX note-taking app <https://github.com/openedx/edx-notes-api>`_ to an Open edX platform. This app allows students to annotate portions of the courseware (see `the official documentation <https://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-redwood.master/exercises_tools/notes.html>`_).
This is a plugin for `Tutor <https://docs.tutor.edly.io>`_ to easily add the `Open edX note-taking app <https://github.com/openedx/edx-notes-api>`_ to an Open edX platform. This app allows students to annotate portions of the courseware (see `the official documentation <https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/enable_notes.html>`_).
.. image:: https://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-redwood.master/_images/SFD_SN_bodyexample.png
.. image:: https://docs.openedx.org/en/latest/_images/SFD_SN_bodyexample.png
:alt: Notes in action
Installation
@ -23,7 +23,7 @@ Then, to make migrations & tasks::
You should beware that the ``notes.<LMS_HOST>`` domain name should exist and point to your server. For instance, if your LMS is hosted at http://myopenedx.com, the notes service should be found at http://notes.myopenedx.com.
If you would like to host the notes service at a different domain name, you can set the ``NOTES_HOST`` configuration variable (see below). When testing Tutor on a local computer, this will be automatically set to notes.local.edly.io.
If you would like to host the notes service at a different domain name, you can set the ``NOTES_HOST`` configuration variable (see below). When testing Tutor on a local computer, this will be automatically set to notes.local.openedx.io.
To enable student notes for a specific course, you should go to the course advanced settings in the studio, and set "Enable Student Notes" to "true". Then, hit "save changes".
@ -59,4 +59,4 @@ This Tutor plugin is maintained by Jhony Avella from `eduNEXT <https://www.edune
License
-------
This software is licensed under the terms of the `GNU Affero General Public License (AGPL) <https://github.com/overhangio/tutor-notes/blob/master/LICENSE.txt>`_.
This software is licensed under the terms of the `GNU Affero General Public License (AGPL) <https://github.com/overhangio/tutor-notes/blob/release/LICENSE.txt>`_.

View File

@ -1 +0,0 @@
- [Bugfix] Fix legacy warnings during Docker build. (by @regisb)

View File

@ -1 +0,0 @@
- 💥 [Deprecation] Drop support for python 3.8 and set Python 3.9 as the minimum supported python version. (by @DawoudSheraz)

View File

@ -0,0 +1,2 @@
- [Improvement] Migrate from pylint and black to ruff. (by @dawoudsheraz)
- [Improvement] Test python package distribution build when running make-test. (by @dawoudsheraz)

View File

@ -1,2 +1,87 @@
# https://packaging.python.org/en/latest/tutorials/packaging-projects/
# https://hatch.pypa.io/latest/config/build/
[project]
name = "tutor-notes"
description = "A Tutor plugin for student notes"
authors = [
{ name = "Edly" },
{ email = "hello@edly.io"},
]
maintainers = [
{ name = "Jhony Avella" },
{ email = "jhony.avella@edunext.co" },
]
license = {text = "AGPL-3.0-only"}
readme = {file = "README.rst", content-type = "text/x-rst"}
requires-python = ">=3.9"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Affero General Public License v3",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dependencies = [
"tutor>=20.0.0,<21.0.0",
]
# These fields will be set by hatch_build.py
dynamic = ["version"]
[project.optional-dependencies]
dev = [
"tutor[dev]>=20.0.0,<21.0.0",
"ruff"
]
# https://packaging.python.org/en/latest/specifications/well-known-project-urls/#well-known-labels
[project.urls]
Homepage = "https://docs.tutor.edly.io/"
Documentation = "https://github.com/overhangio/tutor-notes#readme"
Issues = "https://github.com/overhangio/tutor-notes/issues"
Source = "https://github.com/overhangio/tutor-notes"
Changelog = "https://github.com/overhangio/tutor-notes/blob/release/CHANGELOG.md"
Community = "https://discuss.openedx.org/tag/tutor"
[build-system]
requires = ["setuptools", "wheel"]
requires = ["hatchling"]
build-backend = "hatchling.build"
# hatch-specific configuration
[tool.hatch.metadata.hooks.custom]
path = ".hatch_build.py"
[tool.hatch.build.targets.wheel]
packages = ["tutornotes"]
[tool.hatch.build.targets.sdist]
# Disable strict naming, otherwise twine is not able to detect name/version
strict-naming = false
include = [ "/tutornotes", ".hatch_build.py"]
exclude = ["tests*"]
[project.entry-points."tutor.plugin.v1"]
notes = "tutornotes.plugin"
[tool.ruff]
exclude = ["templates", "docs/_ext"]
[tool.ruff.lint]
# E: pycodestyle errors
# I: isort
# N: pep8-naming
select = ["E", "I", "N"]
# F401: unused-import
# F841: unused-variable
# W292: missing-newline-at-end-of-file
extend-select = ["F401", "F841", "W292"]
[tool.ruff.format]
# Default config is automatically taken from https://docs.astral.sh/ruff/configuration/

View File

@ -1,50 +0,0 @@
import io
import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
with io.open(os.path.join(here, "README.rst"), "rt", encoding="utf8") as f:
readme = f.read()
about = {}
with io.open(
os.path.join(here, "tutornotes", "__about__.py"), "rt", encoding="utf-8"
) as f:
exec(f.read(), about)
setup(
name="tutor-notes",
version=about["__version__"],
url="https://docs.tutor.edly.io/",
project_urls={
"Documentation": "https://docs.tutor.edly.io/",
"Code": "https://github.com/overhangio/tutor-notes",
"Issue tracker": "https://github.com/overhangio/tutor-notes/issues",
"Community": "https://discuss.openedx.org",
},
license="AGPLv3",
author="Edly",
author_email="hello@edly.io",
maintainer="eduNEXT",
description="A Tutor plugin for student notes",
long_description=readme,
long_description_content_type="text/x-rst",
packages=find_packages(exclude=["tests*"]),
include_package_data=True,
python_requires=">=3.9",
install_requires=["tutor>=18.0.0,<19.0.0"],
extras_require={"dev": ["tutor[dev]>=18.0.0,<19.0.0"]},
entry_points={"tutor.plugin.v1": ["notes = tutornotes.plugin"]},
classifiers=[
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Affero General Public License v3",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
],
)

View File

@ -1 +1 @@
__version__ = "18.0.0"
__version__ = "20.0.0"

View File

@ -15,8 +15,8 @@ spec:
app.kubernetes.io/name: notes
spec:
securityContext:
runAsUser: 1000
runAsGroup: 1000
runAsUser: {{ APP_USER_ID }}
runAsGroup: {{ APP_USER_ID }}
containers:
- name: notes
image: {{ NOTES_DOCKER_IMAGE }}

View File

@ -4,4 +4,7 @@ notes-job:
DJANGO_SETTINGS_MODULE: notesserver.settings.tutor
volumes:
- ../plugins/notes/apps/settings/tutor.py:/app/edx-notes-api/notesserver/settings/tutor.py:ro
{%- for mount in iter_mounts(MOUNTS, "notes") %}
- {{ mount }}
{%- endfor %}
depends_on: {{ [("mysql", RUN_MYSQL)]|list_if }}

View File

@ -1 +1 @@
setowner 1000 /mounts/notes
setowner {{ APP_USER_ID }} /mounts/notes

View File

@ -6,5 +6,8 @@ notes:
volumes:
- ../plugins/notes/apps/settings/tutor.py:/app/edx-notes-api/notesserver/settings/tutor.py:ro
- ../../data/notes:/app/data
{%- for mount in iter_mounts(MOUNTS, "notes") %}
- {{ mount }}
{%- endfor %}
restart: unless-stopped
depends_on: {{ [("mysql", RUN_MYSQL)]|list_if }}

View File

@ -10,14 +10,14 @@ from tutor.__about__ import __version_suffix__
from .__about__ import __version__
# Handle version suffix in nightly mode, just like tutor core
# Handle version suffix in main mode, just like tutor core
if __version_suffix__:
__version__ += "-" + __version_suffix__
config = {
"defaults": {
"VERSION": __version__,
"DOCKER_IMAGE": "{{ DOCKER_REGISTRY }}overhangio/openedx-notes:{{ NOTES_VERSION }}",
"DOCKER_IMAGE": "{{ DOCKER_REGISTRY }}overhangio/openedx-notes:{{ NOTES_VERSION }}", # noqa: E501
"HOST": "notes.{{ LMS_HOST }}",
"MYSQL_DATABASE": "notes",
"MYSQL_USERNAME": "notes",

View File

@ -4,13 +4,14 @@ SECRET_KEY = "{{ NOTES_SECRET_KEY }}"
ALLOWED_HOSTS = [
"notes",
"{{ NOTES_HOST }}",
"{{ NOTES_HOST }}:8120",
]
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"HOST": "{{ MYSQL_HOST }}",
"PORT": {{MYSQL_PORT}},
"PORT": {{ MYSQL_PORT }},
"NAME": "{{ NOTES_MYSQL_DATABASE }}",
"USER": "{{ NOTES_MYSQL_USERNAME }}",
"PASSWORD": "{{ NOTES_MYSQL_PASSWORD }}",
@ -23,11 +24,12 @@ DATABASES = {
CLIENT_ID = "notes"
CLIENT_SECRET = "{{ NOTES_OAUTH2_SECRET }}"
ELASTICSEARCH_DSL = {
'default': {
'hosts': '{{ ELASTICSEARCH_SCHEME }}://{{ ELASTICSEARCH_HOST }}:{{ ELASTICSEARCH_PORT }}'
}
}
# Meilisearch credentials
ES_DISABLED = True
MEILISEARCH_ENABLED = True
MEILISEARCH_URL = "{{ MEILISEARCH_URL }}"
MEILISEARCH_API_KEY = "{{ MEILISEARCH_API_KEY }}"
MEILISEARCH_INDEX = "{{ MEILISEARCH_INDEX_PREFIX }}student_notes"
LOGGING = {
"version": 1,

View File

@ -1,24 +1,27 @@
# syntax=docker/dockerfile:1.4
FROM docker.io/python:3.12-slim-bookworm
# syntax=docker/dockerfile:1
FROM docker.io/ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive
# Delete default UID=1000 `ubuntu` user to ensure we can use id 1000 for app user
RUN userdel -r ubuntu
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt update && \
apt upgrade -y && \
apt install -y \
locales \
git \
python3-dev \
build-essential \
default-libmysqlclient-dev \
pkg-config && \
sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \
locale-gen
ENV LC_ALL=en_US.UTF-8
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt update && \
apt upgrade -y && \
apt install -y \
language-pack-en \
git \
python3 \
python3-pip \
python3-venv \
libmysqlclient-dev \
pkg-config
RUN ln -s /usr/bin/python3 /usr/bin/python
###### Git-clone Notes repo ######
ARG APP_USER_ID=1000
ARG APP_USER_ID={{ HOST_USER_ID }}
RUN useradd --home-dir /app --create-home --shell /bin/bash --uid ${APP_USER_ID} app
USER ${APP_USER_ID}
@ -31,8 +34,13 @@ ENV PATH=/app/venv/bin:${PATH}
# https://pypi.org/project/setuptools/
# https://pypi.org/project/pip/
# https://pypi.org/project/wheel/
RUN --mount=type=cache,target=/app/.cache/pip,sharing=shared pip install setuptools==69.2.0 pip==24.0 wheel==0.43.0
RUN --mount=type=cache,target=/app/.cache/pip,sharing=shared pip install setuptools==78.1.0 pip==25.0.1 wheel==0.46.0
RUN --mount=type=cache,target=/app/.cache/pip,sharing=shared pip install -r requirements/base.txt
EXPOSE 8000
CMD gunicorn --workers=2 --name notes --bind=0.0.0.0:8000 --max-requests=1000 notesserver.wsgi:application
CMD ["gunicorn", \
"--workers=2", \
"--name", "notes", \
"--bind=0.0.0.0:8000", \
"--max-requests=1000", \
"notesserver.wsgi:application"]

View File

@ -1,2 +1,4 @@
./manage.py migrate
./manage.py search_index --rebuild -f
# Re-index with meilisearch
./manage.py shell -c "from notesapi.v1.views.meilisearch import reindex; reindex()"