From 8063f0cb038db80a3dd05dd70e5a50acfe9e5296 Mon Sep 17 00:00:00 2001 From: Sangjoon Bob Lee Date: Mon, 9 Sep 2024 08:27:48 -0400 Subject: [PATCH 1/5] Move tests folder to top --- {src/diffpy/snmf/tests => tests}/__init__.py | 0 {src/diffpy/snmf/tests => tests}/conftest.py | 0 {src/diffpy/snmf/tests => tests}/debug.py | 0 {src/diffpy/snmf/tests => tests}/test_containers.py | 0 {src/diffpy/snmf/tests => tests}/test_factorizers.py | 0 {src/diffpy/snmf/tests => tests}/test_optimizers.py | 0 {src/diffpy/snmf/tests => tests}/test_polynomials.py | 0 {src/diffpy/snmf/tests => tests}/test_subroutines.py | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename {src/diffpy/snmf/tests => tests}/__init__.py (100%) rename {src/diffpy/snmf/tests => tests}/conftest.py (100%) rename {src/diffpy/snmf/tests => tests}/debug.py (100%) rename {src/diffpy/snmf/tests => tests}/test_containers.py (100%) rename {src/diffpy/snmf/tests => tests}/test_factorizers.py (100%) rename {src/diffpy/snmf/tests => tests}/test_optimizers.py (100%) rename {src/diffpy/snmf/tests => tests}/test_polynomials.py (100%) rename {src/diffpy/snmf/tests => tests}/test_subroutines.py (100%) diff --git a/src/diffpy/snmf/tests/__init__.py b/tests/__init__.py similarity index 100% rename from src/diffpy/snmf/tests/__init__.py rename to tests/__init__.py diff --git a/src/diffpy/snmf/tests/conftest.py b/tests/conftest.py similarity index 100% rename from src/diffpy/snmf/tests/conftest.py rename to tests/conftest.py diff --git a/src/diffpy/snmf/tests/debug.py b/tests/debug.py similarity index 100% rename from src/diffpy/snmf/tests/debug.py rename to tests/debug.py diff --git a/src/diffpy/snmf/tests/test_containers.py b/tests/test_containers.py similarity index 100% rename from src/diffpy/snmf/tests/test_containers.py rename to tests/test_containers.py diff --git a/src/diffpy/snmf/tests/test_factorizers.py b/tests/test_factorizers.py similarity index 100% rename from src/diffpy/snmf/tests/test_factorizers.py rename to tests/test_factorizers.py diff --git a/src/diffpy/snmf/tests/test_optimizers.py b/tests/test_optimizers.py similarity index 100% rename from src/diffpy/snmf/tests/test_optimizers.py rename to tests/test_optimizers.py diff --git a/src/diffpy/snmf/tests/test_polynomials.py b/tests/test_polynomials.py similarity index 100% rename from src/diffpy/snmf/tests/test_polynomials.py rename to tests/test_polynomials.py diff --git a/src/diffpy/snmf/tests/test_subroutines.py b/tests/test_subroutines.py similarity index 100% rename from src/diffpy/snmf/tests/test_subroutines.py rename to tests/test_subroutines.py From b643887c99a0ef3f79457d6ec3fd0e8cf6b14855 Mon Sep 17 00:00:00 2001 From: Sangjoon Bob Lee Date: Mon, 9 Sep 2024 08:38:20 -0400 Subject: [PATCH 2/5] Revert commit --- {tests => src/diffpy/snmf/tests}/__init__.py | 0 {tests => src/diffpy/snmf/tests}/conftest.py | 0 {tests => src/diffpy/snmf/tests}/debug.py | 0 {tests => src/diffpy/snmf/tests}/test_containers.py | 0 {tests => src/diffpy/snmf/tests}/test_factorizers.py | 0 {tests => src/diffpy/snmf/tests}/test_optimizers.py | 0 {tests => src/diffpy/snmf/tests}/test_polynomials.py | 0 {tests => src/diffpy/snmf/tests}/test_subroutines.py | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename {tests => src/diffpy/snmf/tests}/__init__.py (100%) rename {tests => src/diffpy/snmf/tests}/conftest.py (100%) rename {tests => src/diffpy/snmf/tests}/debug.py (100%) rename {tests => src/diffpy/snmf/tests}/test_containers.py (100%) rename {tests => src/diffpy/snmf/tests}/test_factorizers.py (100%) rename {tests => src/diffpy/snmf/tests}/test_optimizers.py (100%) rename {tests => src/diffpy/snmf/tests}/test_polynomials.py (100%) rename {tests => src/diffpy/snmf/tests}/test_subroutines.py (100%) diff --git a/tests/__init__.py b/src/diffpy/snmf/tests/__init__.py similarity index 100% rename from tests/__init__.py rename to src/diffpy/snmf/tests/__init__.py diff --git a/tests/conftest.py b/src/diffpy/snmf/tests/conftest.py similarity index 100% rename from tests/conftest.py rename to src/diffpy/snmf/tests/conftest.py diff --git a/tests/debug.py b/src/diffpy/snmf/tests/debug.py similarity index 100% rename from tests/debug.py rename to src/diffpy/snmf/tests/debug.py diff --git a/tests/test_containers.py b/src/diffpy/snmf/tests/test_containers.py similarity index 100% rename from tests/test_containers.py rename to src/diffpy/snmf/tests/test_containers.py diff --git a/tests/test_factorizers.py b/src/diffpy/snmf/tests/test_factorizers.py similarity index 100% rename from tests/test_factorizers.py rename to src/diffpy/snmf/tests/test_factorizers.py diff --git a/tests/test_optimizers.py b/src/diffpy/snmf/tests/test_optimizers.py similarity index 100% rename from tests/test_optimizers.py rename to src/diffpy/snmf/tests/test_optimizers.py diff --git a/tests/test_polynomials.py b/src/diffpy/snmf/tests/test_polynomials.py similarity index 100% rename from tests/test_polynomials.py rename to src/diffpy/snmf/tests/test_polynomials.py diff --git a/tests/test_subroutines.py b/src/diffpy/snmf/tests/test_subroutines.py similarity index 100% rename from tests/test_subroutines.py rename to src/diffpy/snmf/tests/test_subroutines.py From b0228b0b764d9b4abf1ec80515a566ce57e6fb30 Mon Sep 17 00:00:00 2001 From: Sangjoon Bob Lee Date: Mon, 7 Oct 2024 18:39:39 -0400 Subject: [PATCH 3/5] Add test pypi/gh release workflows --- .../workflows/build-wheel-release-publish.yml | 84 +++++++++++++++++ .github/workflows/get-latest-changelog.py | 58 ++++++++++++ .github/workflows/update-changelog.py | 92 +++++++++++++++++++ 3 files changed, 234 insertions(+) create mode 100644 .github/workflows/build-wheel-release-publish.yml create mode 100644 .github/workflows/get-latest-changelog.py create mode 100644 .github/workflows/update-changelog.py diff --git a/.github/workflows/build-wheel-release-publish.yml b/.github/workflows/build-wheel-release-publish.yml new file mode 100644 index 00000000..3e47bbff --- /dev/null +++ b/.github/workflows/build-wheel-release-publish.yml @@ -0,0 +1,84 @@ +name: Release +on: + workflow_dispatch: + push: + tags: + - '*' +permissions: + contents: write +jobs: + build-package: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + - uses: hynek/build-and-inspect-python-package@v2 + + update-changelog: + needs: [build-package] + if: "!contains(github.ref, 'rc')" + runs-on: ubuntu-latest + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Update CHANGELOG.rst wit the latest news + run: python .github/workflows/update-changelog.py "${{ github.ref_name }}" + + - name: Commite the changes in CHANGELOG.rst + uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: update changelog + branch: pypi-build # FIXME: change to main + + github-pre-release: + needs: [build-package] + if: contains(github.ref, 'rc') + runs-on: ubuntu-latest + steps: + - name: Generate GH release notes for pre-release + uses: softprops/action-gh-release@v2 + with: + draft: true + prerelease: true + generate_release_notes: true + + github-release: + needs: [build-package, update-changelog] + if: "!contains(github.ref, 'rc')" + runs-on: ubuntu-latest + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + with: + ref: pypi-build # FIXME: change to main + - name: Generate GH release notes for release + run: python .github/workflows/get-latest-changelog.py "${{ github.ref_name }}" + - name: Release + uses: softprops/action-gh-release@v2 + with: + body_path: CHANGELOG.txt + draft: true + + pypi-publish: + needs: [build-package] + environment: + name: testpypi # FIXME: change to pypi + url: https://test/pypi.org/p/diffpy.snmf # FIXME: get the PyPI URL + permissions: + id-token: write + runs-on: ubuntu-latest + steps: + - uses: actions/download-artifact@v4 + with: + name: Packages + path: dist + + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ # FIXME: remove test. + verbose: true \ No newline at end of file diff --git a/.github/workflows/get-latest-changelog.py b/.github/workflows/get-latest-changelog.py new file mode 100644 index 00000000..67d5f4d3 --- /dev/null +++ b/.github/workflows/get-latest-changelog.py @@ -0,0 +1,58 @@ +import re +import sys + + +def get_tag_news_items(tag, filepath): + """Collect news items after the specified tag until the next version is found.""" + collect = False + collected_lines = [] + # Regex to match version numbers + version_pattern = re.compile(r"^\d+\.\d+\.\d+") + + with open(filepath, "r") as file: + for line in file: + if line.strip().startswith(tag): + collect = True + continue + elif collect and version_pattern.match(line.strip()): + break + elif collect: + collected_lines.append(line.rstrip()) + + return collected_lines + + +def remove_two_lines(lines): + """Remove two lines after the tag in CHANGELOG.rst.""" + if lines: + # Remove the first line containing "====" + if "====" in lines[0]: + lines.pop(0) + # Remove the second empty line + if lines[1] == "": + lines.pop(1) + return lines + + +def save_to_txt_file(lines, filename): + """Save collected lines to a .txt file used for GH release notes.""" + output = "\n".join(lines) + with open(filename, "w") as file: + file.write(output) + return output + + +if __name__ == "__main__": + if len(sys.argv) < 2: + assert ( + False + ), "No tag has been provided. Please provide a tag by running python get-latest-changelog.py " + + tag = sys.argv[1] + CHANGELOG_PATH = "CHANGELOG.rst" + LATEST_CHANGELOG_PATH = "CHANGELOG.txt" + + collected_lines = get_tag_news_items(tag, CHANGELOG_PATH) + cleaned_lines = remove_two_lines(collected_lines) + latest_changelog_output = save_to_txt_file(cleaned_lines, LATEST_CHANGELOG_PATH) + print(f"CHANGELOG for {tag}:\n{latest_changelog_output}") diff --git a/.github/workflows/update-changelog.py b/.github/workflows/update-changelog.py new file mode 100644 index 00000000..fe86f74e --- /dev/null +++ b/.github/workflows/update-changelog.py @@ -0,0 +1,92 @@ +import os +from glob import glob +import sys + +# Get the GitHub reference passed as an argument +tag = sys.argv[1] + +# Store category data +news_items = { + "Added": [], + "Changed": [], + "Deprecated": [], + "Removed": [], + "Fixed": [], + "Security": [], +} + + +def extract_news_items(file_path): + """Extract news bullet points under each category for each .rst file.""" + with open(file_path, "r") as file: + for line in file: + line = line.strip() + + # Check if the line is a category header + if line.startswith("**") and line.endswith(":**"): + current_category = line.strip("**:").strip() + + # Only add if the line is not empty and not a category header + elif current_category and line and not line.startswith("* "): + news_items[current_category].append(line) + + +def write_merged_file(): + """Add the news items under the ".. current developments" section.""" + CHANGELOG_PATH = "CHANGELOG.rst" + CHANGELOG_HEADER = ".. current developments" + + # Insert news + new_news_content = f"\n{tag}\n=====\n\n" + for category_name in sorted(news_items.keys()): + items = news_items[category_name] + if items: + # Add category name e.g. Added, Changed, etc. + new_news_content += f"**{category_name}:**\n\n" + for item in items: + # Add each item in the category + new_news_content += f"{item}\n" + new_news_content += "\n" + + # Read CHANGELOG.rst + with open(CHANGELOG_PATH, "r") as file: + current_content = file.read() + + # Find the position to insert news after ".. current developments" + insert_position = current_content.find(CHANGELOG_HEADER) + len(CHANGELOG_HEADER) + 1 + final_content = current_content[:insert_position] + new_news_content + current_content[insert_position:] + + # Write the updated content back to the file + with open(CHANGELOG_PATH, "w") as file: + file.write(final_content) + + return new_news_content + + +def remove_news_rst_files(news_dir_path): + """Remove .rst files in the news directory except TEMPLATE.rst""" + rst_files = os.listdir(news_dir_path) + for file_name in rst_files: + rst_file_path = os.path.join(news_dir_path, file_name) + if file_name.endswith(".rst") and file_name != "TEMPLATE.rst": + os.remove(rst_file_path) + + +if __name__ == "__main__": + NEWS_DIR_PATH = "news" + + # Get all news .rst files + news_rst_files = glob(os.path.join(NEWS_DIR_PATH, "*.rst")) + + # Extract and store news items into a single dictionary + for rst_file in news_rst_files: + extract_news_items(rst_file) + + # Add news under ".. current developments" + new_news_content = write_merged_file() + + # Remove all .rst files in the news directory except TEMPLATE.rst + remove_news_rst_files(NEWS_DIR_PATH) + + # Print for debugging + print(new_news_content) From f7a4242f9fb8d8c04df0b6b32b2ab5d800cb9e3f Mon Sep 17 00:00:00 2001 From: Sangjoon Bob Lee Date: Mon, 7 Oct 2024 18:43:49 -0400 Subject: [PATCH 4/5] Add .rst news file --- news/gh-workflow.rst | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 news/gh-workflow.rst diff --git a/news/gh-workflow.rst b/news/gh-workflow.rst new file mode 100644 index 00000000..801db3b6 --- /dev/null +++ b/news/gh-workflow.rst @@ -0,0 +1,23 @@ +**Added:** + +* GitHub workflow files for PyPI and GH release + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* From 6fe07825f7da032c172d89073e027b0d10544174 Mon Sep 17 00:00:00 2001 From: Sangjoon Bob Lee Date: Mon, 7 Oct 2024 18:46:00 -0400 Subject: [PATCH 5/5] Apply pre-commit --- .github/workflows/build-wheel-release-publish.yml | 6 +++--- .github/workflows/update-changelog.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-wheel-release-publish.yml b/.github/workflows/build-wheel-release-publish.yml index 3e47bbff..7c11c4b9 100644 --- a/.github/workflows/build-wheel-release-publish.yml +++ b/.github/workflows/build-wheel-release-publish.yml @@ -3,7 +3,7 @@ on: workflow_dispatch: push: tags: - - '*' + - '*' permissions: contents: write jobs: @@ -33,7 +33,7 @@ jobs: with: commit_message: update changelog branch: pypi-build # FIXME: change to main - + github-pre-release: needs: [build-package] if: contains(github.ref, 'rc') @@ -81,4 +81,4 @@ jobs: uses: pypa/gh-action-pypi-publish@release/v1 with: repository-url: https://test.pypi.org/legacy/ # FIXME: remove test. - verbose: true \ No newline at end of file + verbose: true diff --git a/.github/workflows/update-changelog.py b/.github/workflows/update-changelog.py index fe86f74e..46094e0b 100644 --- a/.github/workflows/update-changelog.py +++ b/.github/workflows/update-changelog.py @@ -1,6 +1,6 @@ import os -from glob import glob import sys +from glob import glob # Get the GitHub reference passed as an argument tag = sys.argv[1]