diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..e088570 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 + +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: monthly + open-pull-requests-limit: 5 + commit-message: + prefix: deps diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8c0af8d..b32302f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,18 +13,45 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Install validators + run: sudo apt-get update && sudo apt-get install --yes lua5.1 libxml2-utils + + - name: Validate Lua and XML syntax + shell: bash + run: | + set -euo pipefail + + find OpenHeal -type f -name '*.lua' -print0 | + while IFS= read -r -d '' file; do + luac5.1 -p "$file" + done + + find OpenHeal -type f -name '*.xml' -print0 | + while IFS= read -r -d '' file; do + xmllint --noout "$file" + done - name: Validate tag and package addon shell: bash run: | set -euo pipefail + VERSION="${GITHUB_REF_NAME#v}" - test -f OpenHeal/OpenHeal.toc - test -f OpenHeal/LICENSE - grep -q "GNU GENERAL PUBLIC LICENSE" OpenHeal/LICENSE - zip -r "OpenHeal-${VERSION}.zip" OpenHeal \ + TOC_VERSION="$(sed -n 's/^## Version:[[:space:]]*//p' OpenHeal/OpenHeal.toc)" + + test -n "$VERSION" + test "$VERSION" = "$TOC_VERSION" + grep -Fxq '## X-License: GPL-3.0-only' OpenHeal/OpenHeal.toc + grep -q 'GNU GENERAL PUBLIC LICENSE' LICENSE + grep -q 'Version 3, 29 June 2007' LICENSE + cmp --silent LICENSE OpenHeal/LICENSE + + ARCHIVE="OpenHeal-${VERSION}.zip" + zip -r "$ARCHIVE" OpenHeal \ -x '*/.DS_Store' '*/Thumbs.db' '*.log' '*.tmp' + sha256sum "$ARCHIVE" > "${ARCHIVE}.sha256" - name: Create GitHub release env: @@ -32,9 +59,13 @@ jobs: shell: bash run: | set -euo pipefail + VERSION="${GITHUB_REF_NAME#v}" + ARCHIVE="OpenHeal-${VERSION}.zip" + gh release create "$GITHUB_REF_NAME" \ - "OpenHeal-${VERSION}.zip" \ + "$ARCHIVE" \ + "${ARCHIVE}.sha256" \ --repo "$GITHUB_REPOSITORY" \ --generate-notes \ --verify-tag \ diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 64b877d..31fc00a 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install validators run: sudo apt-get update && sudo apt-get install --yes lua5.1 libxml2-utils @@ -39,35 +39,80 @@ jobs: xmllint --noout "$file" done - - name: Validate repository and TOC references + - name: Validate repository, licensing, and TOC references shell: python run: | from pathlib import Path + import re import sys root = Path("OpenHeal") toc = root / "OpenHeal.toc" - required = [Path("LICENSE"), root / "LICENSE", toc] + root_license = Path("LICENSE") + addon_license = root / "LICENSE" + required = [root_license, addon_license, toc] errors = [] for path in required: if not path.is_file(): errors.append(f"Missing required file: {path}") + lua_files = list(root.rglob("*.lua")) + if not lua_files: + errors.append("No Lua files found in OpenHeal") + for path in Path(".").rglob("*"): if not path.is_file() or ".git" in path.parts: continue try: - text = path.read_text(encoding="utf-8") + lines = path.read_text(encoding="utf-8").splitlines() except UnicodeDecodeError: continue - if "<<<<<<< " in text or "=======\n" in text or ">>>>>>> " in text: - errors.append(f"Possible merge marker in {path}") + + for line_number, line in enumerate(lines, start=1): + if ( + line.startswith("<<<<<<< ") + or line == "=======" + or line.startswith(">>>>>>> ") + ): + errors.append( + f"Merge conflict marker in {path}:{line_number}" + ) + + if root_license.is_file() and addon_license.is_file(): + if root_license.read_bytes() != addon_license.read_bytes(): + errors.append("Root and packaged LICENSE files differ") + + license_text = root_license.read_text(encoding="utf-8") + if "GNU GENERAL PUBLIC LICENSE" not in license_text: + errors.append("LICENSE is not the expected GNU GPL text") + if "Version 3, 29 June 2007" not in license_text: + errors.append("LICENSE is not GPL version 3") if toc.is_file(): - for raw_line in toc.read_text(encoding="utf-8-sig").splitlines(): + toc_text = toc.read_text(encoding="utf-8-sig") + toc_lines = toc_text.splitlines() + + if "## X-License: GPL-3.0-only" not in toc_lines: + errors.append( + "OpenHeal.toc must declare X-License: GPL-3.0-only" + ) + + version_lines = [ + line.removeprefix("## Version:").strip() + for line in toc_lines + if line.startswith("## Version:") + ] + if len(version_lines) != 1: + errors.append("OpenHeal.toc must contain exactly one Version field") + elif not re.fullmatch(r"\d+\.\d+\.\d+", version_lines[0]): + errors.append( + "OpenHeal.toc Version must use numeric major.minor.patch" + ) + + for raw_line in toc_lines: line = raw_line.strip() - if not line or line.startswith("##") or line.startswith("#"): + if not line or line.startswith("#"): continue referenced = root / Path(line.replace("\\", "/")) if not referenced.is_file(): @@ -77,4 +122,4 @@ jobs: print("\n".join(errors), file=sys.stderr) raise SystemExit(1) - print("Repository structure and TOC references are valid.") + print("OpenHeal repository validation passed.") diff --git a/OpenHeal/CHANGELOG.md b/OpenHeal/CHANGELOG.md index fc4aab5..2a12daf 100644 --- a/OpenHeal/CHANGELOG.md +++ b/OpenHeal/CHANGELOG.md @@ -6,7 +6,8 @@ exports, media paths, and SavedVariables to OpenHeal. - Added a one-time import for settings from the previous addon when it is enabled during the first OpenHeal login. -- Added the MIT open-source license. +- Published OpenHeal under the GNU General Public License version 3 only + (`GPL-3.0-only`). ## Version 0.5 @@ -93,10 +94,10 @@ of dead code and dead configuration. - **Export strings are uncompressed** (~600 bytes for a full profile) because LibDeflate is not embedded. They paste fine. -### Note on licensing +### Licensing -`LICENSE` is GPLv3 and `LICENSE.txt` is "All Rights Reserved". These contradict -each other. Both were left untouched — pick one. +The earlier conflicting license files were resolved before the public release. +The repository and packaged addon are licensed as `GPL-3.0-only`. --- diff --git a/OpenHeal/OpenHeal.toc b/OpenHeal/OpenHeal.toc index 4813105..e398834 100644 --- a/OpenHeal/OpenHeal.toc +++ b/OpenHeal/OpenHeal.toc @@ -4,7 +4,7 @@ ## Author: Roburmaster ## Version: 1.0.0 ## IconTexture: Interface\AddOns\OpenHeal\media\openheal.png -## X-License: MIT +## X-License: GPL-3.0-only ## OptionalDeps: LibSharedMedia-3.0 # Account-wide: