diff --git a/.github/workflows/package-test.yml b/.github/workflows/package-test.yml new file mode 100644 index 00000000..e7e42e20 --- /dev/null +++ b/.github/workflows/package-test.yml @@ -0,0 +1,58 @@ +name: Package Test + +on: + workflow_dispatch: + +jobs: + package: + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Check out repository + uses: actions/checkout@v6 + + - name: Build release ZIP (integration root at ZIP root) + shell: bash + run: | + set -euo pipefail + rm -f "${{ github.workspace }}/pollenlevels.zip" + cd "${{ github.workspace }}/custom_components/pollenlevels" + zip "${{ github.workspace }}/pollenlevels.zip" -r ./ + + - name: Validate ZIP structure (zip_release-compatible) + shell: bash + run: | + set -euo pipefail + python - <<'PY' + import zipfile + + zip_path = "pollenlevels.zip" + required = {"manifest.json", "__init__.py"} + + with zipfile.ZipFile(zip_path) as zf: + names = [n for n in zf.namelist() if n and not n.endswith("/")] + + if not names: + raise SystemExit("ZIP is empty") + + bad_prefix = [n for n in names if n.startswith("custom_components/")] + if bad_prefix: + raise SystemExit( + "ZIP contains 'custom_components/' prefix; " + "zip must be integration-root only" + ) + + missing = sorted(required.difference(names)) + if missing: + raise SystemExit("ZIP missing required root files: " + ", ".join(missing)) + + print("ZIP structure validated.") + PY + + - name: Upload ZIP artifact + uses: actions/upload-artifact@v6 + with: + name: pollenlevels-zip + path: pollenlevels.zip diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..93055996 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,61 @@ +name: Release Asset + +on: + release: + types: [published] + +permissions: + contents: write + +jobs: + package-and-upload: + runs-on: ubuntu-latest + + steps: + - name: Check out repository + uses: actions/checkout@v6 + + - name: Build release ZIP (integration root at ZIP root) + shell: bash + run: | + set -euo pipefail + rm -f "${{ github.workspace }}/pollenlevels.zip" + cd "${{ github.workspace }}/custom_components/pollenlevels" + zip "${{ github.workspace }}/pollenlevels.zip" -r ./ + + - name: Validate ZIP structure (zip_release-compatible) + shell: bash + run: | + set -euo pipefail + python - <<'PY' + import zipfile + + zip_path = "pollenlevels.zip" + required = {"manifest.json", "__init__.py"} + + with zipfile.ZipFile(zip_path) as zf: + names = [n for n in zf.namelist() if n and not n.endswith("/")] + + if not names: + raise SystemExit("ZIP is empty") + + bad_prefix = [n for n in names if n.startswith("custom_components/")] + if bad_prefix: + raise SystemExit( + "ZIP contains 'custom_components/' prefix; " + "zip must be integration-root only" + ) + + missing = sorted(required.difference(names)) + if missing: + raise SystemExit("ZIP missing required root files: " + ", ".join(missing)) + + print("ZIP structure validated.") + PY + + - name: Upload ZIP to release + uses: softprops/action-gh-release@v2 + with: + files: pollenlevels.zip + overwrite_files: true + fail_on_unmatched_files: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 8df88078..7d4bd99d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.9.4] - 2026-02-24 +### Changed +- Updated release packaging automation for HACS `zip_release` by validating the + integration-root ZIP layout, enabling strict release upload failure when + `pollenlevels.zip` is missing, and aligning package-test artifact upload to + `actions/upload-artifact@v6`. + ## [1.9.3] - 2026-02-14 ### Fixed - Aligned config-flow API validation with runtime parsing by requiring `dailyInfo` diff --git a/custom_components/pollenlevels/manifest.json b/custom_components/pollenlevels/manifest.json index 8a6d4eb7..42f5c1d5 100644 --- a/custom_components/pollenlevels/manifest.json +++ b/custom_components/pollenlevels/manifest.json @@ -7,5 +7,5 @@ "integration_type": "service", "iot_class": "cloud_polling", "issue_tracker": "https://github.com/eXPerience83/pollenlevels/issues", - "version": "1.9.3" + "version": "1.9.4" } diff --git a/hacs.json b/hacs.json index 99f40769..54ed71a8 100644 --- a/hacs.json +++ b/hacs.json @@ -3,5 +3,7 @@ "homeassistant": "2025.3.0", "content_in_root": false, "render_readme": true, - "hacs": "2.0.0" + "hacs": "2.0.0", + "zip_release": true, + "filename": "pollenlevels.zip" } diff --git a/pyproject.toml b/pyproject.toml index c29fb16d..c3d891f0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ [project] name = "pollenlevels" -version = "1.9.3" +version = "1.9.4" # Enforce the runtime floor aligned with upcoming HA Python 3.14 images. requires-python = ">=3.14"