From c5774c14a097646f2b81caaf0fc50b048b9080a4 Mon Sep 17 00:00:00 2001 From: ClementMabileau Date: Mon, 18 Mar 2024 09:15:29 +0100 Subject: [PATCH] Improve `scripts/new_article.py`: leaf bundle, tests, comments (#26) * Handle leaf bundle articles in new_article.py script * Check that response code is 200 when sending notification * Minor comment change * Wrap new_article.py's code in a function * Pass new artciles paths in parameters * Make content base location configurable in new_article.py * Add tests for new_article script * Update .gitignore * Add pytest workflow --- .github/workflows/pytest.yml | 33 ++++++++++ .gitignore | 4 ++ scripts/new_article.py | 60 ++++++++++++------ scripts/test_new_article.py | 68 +++++++++++++++++++++ scripts/test_resources/article_1.md | 9 +++ scripts/test_resources/leaf_bundle/index.md | 9 +++ 6 files changed, 163 insertions(+), 20 deletions(-) create mode 100644 .github/workflows/pytest.yml create mode 100644 scripts/test_new_article.py create mode 100644 scripts/test_resources/article_1.md create mode 100644 scripts/test_resources/leaf_bundle/index.md diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml new file mode 100644 index 0000000..43a6132 --- /dev/null +++ b/.github/workflows/pytest.yml @@ -0,0 +1,33 @@ +name: Pytest + +on: + # Runs on pull requests to check that the website is building without errors + pull_request: + + # Only run if the push to main + push: + branches: + - main + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + # Build job + build: + runs-on: ubuntu-latest + steps: + # Checkout repo + - name: 🛒 Checkout + uses: actions/checkout@v3 + + # Install pytest + - name: 🛠️ Install pytest + run: | + python3 -m pip install pytest pytest-mock + + # Run tests + - name: 🚀 Run pytest + run: | + cd ./scripts/ + pytest diff --git a/.gitignore b/.gitignore index d6e0359..2ab7933 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +# env files .env.prod .env.dev @@ -10,3 +11,6 @@ certbot/* # hugo build src/public build/blog/* + +# python +**/__pycache__ diff --git a/scripts/new_article.py b/scripts/new_article.py index 9adda8f..14365af 100644 --- a/scripts/new_article.py +++ b/scripts/new_article.py @@ -1,25 +1,45 @@ +import os import sys import re import requests import yaml -for file_path in sys.argv[1:]: - # Check that this is an article file - if re.match("^src/content/posts/.+\.md$", file_path): - # Read YAML Header - with open(file_path, "r") as f: - raw_txt = f.read() - data = yaml.safe_load(raw_txt.split("---")[1]) - - # Get rid of python objects, only keep basic types - for key in data: - if type(data[key]) not in [int, str, float, bool]: - data[key] = str(data[key]) - - # Add URL info - file_name = file_path.split("/")[-1][:-3] - data["url"] = f"https://iscsc.fr/posts/{file_name}" - - # Finally send Data - requests.post("http://iscsc.fr:8001/new-blog", json=data) - print(file_path, file_name, data) +ARTICLE_FILE_BASE_PATH = "src/content/posts/" + +def main(files_paths): + for file_path in files_paths: + # Check that this is an article file + if re.match(f"^{ARTICLE_FILE_BASE_PATH}.+\.md$", file_path): + ## Read YAML Header + with open(file_path, "r") as f: + raw_txt = f.read() + data = yaml.safe_load(raw_txt.split("---")[1]) + + ## Get rid of python objects, only keep basic types + for key in data: + if type(data[key]) not in [int, str, float, bool]: + data[key] = str(data[key]) + + # we have to deal with both possibilities of new article: + # - an article as a .md file which URL is the name + # - a leaf bundle article (https://gohugo.io/content-management/page-bundles/#leaf-bundles): + # it's an article which name is the folder's name and body is in a index.md in this directory + dirname, basename = os.path.split(file_path) + if basename == "index.md": + # leaf bundle: name is directory name + file_name = os.path.basename(dirname) + else: + # direct article file: name is file name + file_name = basename[:-3] # get rid of the `.md` + + ## Add URL info: + data["url"] = f"https://iscsc.fr/posts/{file_name}" + + ## Finally send Data + req = requests.post("http://iscsc.fr:8001/new-blog", json=data) + print(file_path, file_name, data) + assert(req.status_code == 200) + + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/scripts/test_new_article.py b/scripts/test_new_article.py new file mode 100644 index 0000000..baae7fa --- /dev/null +++ b/scripts/test_new_article.py @@ -0,0 +1,68 @@ +import pytest + +import new_article + +### DISCLAIMER: +# Whereas other extensions are allowed by HUGO: +# "The extension can be .html, .json or any valid MIME type" +# We only accept Markdown articles and so only parse these +### + + +@pytest.fixture +def mock_requests_post(mocker): + mock_post = mocker.MagicMock() + fake_response = mocker.Mock() + + fake_response.status_code = 200 + mock_post.return_value = fake_response + + mocker.patch("requests.post", mock_post) + mocker.patch("new_article.ARTICLE_FILE_BASE_PATH", "test_resources/") + + yield mock_post + + +def test_new_article_file(mock_requests_post): + new_article.main(["test_resources/article_1.md"]) + + mock_requests_post.assert_called_once_with( + 'http://iscsc.fr:8001/new-blog', + json={ + 'title': 'article title', + 'summary': 'article summary', + 'date': '2024-02-19 10:52:09+01:00', + 'lastUpdate': '2024-02-19 10:52:09+01:00', + 'tags': "['some', 'tags']", + 'author': 'ctmbl', + 'draft': False, + 'url': 'https://iscsc.fr/posts/article_1' + } + ) + +def test_new_leaf_bundle_article(mock_requests_post): + new_article.main(["test_resources/leaf_bundle/index.md"]) + + mock_requests_post.assert_called_once_with( + 'http://iscsc.fr:8001/new-blog', + json={ + 'title': 'leaf bundle title', + 'summary': 'leaf bundle summary', + 'date': '2024-02-19 10:52:09+01:00', + 'lastUpdate': '2024-02-19 10:52:09+01:00', + 'tags': "['leaf', 'bundle']", + 'author': 'ctmbl', + 'draft': False, + 'url': 'https://iscsc.fr/posts/leaf_bundle' + } + ) + +def test_new_branch_bundle(): + # not yet implemented + # https://gohugo.io/content-management/page-bundles/#branch-bundles + pass + +def test_headless_bundle(): + # not yet implemented + # https://gohugo.io/content-management/page-bundles/#headless-bundle + pass \ No newline at end of file diff --git a/scripts/test_resources/article_1.md b/scripts/test_resources/article_1.md new file mode 100644 index 0000000..07ed3b8 --- /dev/null +++ b/scripts/test_resources/article_1.md @@ -0,0 +1,9 @@ +--- +title: "article title" +summary: "article summary" +date: 2024-02-19T10:52:09+01:00 +lastUpdate: 2024-02-19T10:52:09+01:00 +tags: ["some","tags"] +author: ctmbl +draft: false +--- \ No newline at end of file diff --git a/scripts/test_resources/leaf_bundle/index.md b/scripts/test_resources/leaf_bundle/index.md new file mode 100644 index 0000000..a71c101 --- /dev/null +++ b/scripts/test_resources/leaf_bundle/index.md @@ -0,0 +1,9 @@ +--- +title: "leaf bundle title" +summary: "leaf bundle summary" +date: 2024-02-19T10:52:09+01:00 +lastUpdate: 2024-02-19T10:52:09+01:00 +tags: ["leaf","bundle"] +author: ctmbl +draft: false +--- \ No newline at end of file