From f9beef365ff9f8908a67964609567ea648502ade Mon Sep 17 00:00:00 2001 From: Victor Kuznetsov Date: Sat, 8 Aug 2026 21:18:10 -0700 Subject: [PATCH] Remove conda distribution support --- .github/workflows/distribute.yml | 33 ++--------------- docs/release-and-distribution.md | 15 -------- packaging/conda/recipe.yaml | 62 -------------------------------- scripts/sync_conda_recipe.py | 53 --------------------------- tests/test_sync_conda_recipe.py | 49 ------------------------- 5 files changed, 2 insertions(+), 210 deletions(-) delete mode 100644 packaging/conda/recipe.yaml delete mode 100644 scripts/sync_conda_recipe.py delete mode 100644 tests/test_sync_conda_recipe.py diff --git a/.github/workflows/distribute.yml b/.github/workflows/distribute.yml index d907ae4..430def4 100644 --- a/.github/workflows/distribute.yml +++ b/.github/workflows/distribute.yml @@ -1,9 +1,8 @@ name: Distribute on release # Fans a published GitHub Release out to the channels that need a nudge. -# PyPI is handled by publish.yml; the conda-forge channel is handled by its -# autotick bot. This workflow updates the repository recipe and event-drives -# the three channels that would otherwise be manual: +# PyPI is handled by publish.yml. This workflow event-drives the three channels +# that would otherwise be manual: # - Homebrew tap: rewrite the formula's url + sha256 to the new sdist. # - HF Space: factory-rebuild so it reinstalls the latest sdist from PyPI. # - ComfyUI: sync, test, and publish the node against the exact library release. @@ -89,34 +88,6 @@ jobs: git commit -m "remove-ai-watermarks $VERSION" || { echo "Formula already current"; exit 0; } git push - conda-recipe: - needs: resolve - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - name: Checkout main - uses: actions/checkout@v7 - with: - ref: main - - name: Bump the repository conda recipe - env: - SHA: ${{ needs.resolve.outputs.sha }} - VERSION: ${{ needs.resolve.outputs.version }} - run: | - set -euo pipefail - python scripts/sync_conda_recipe.py --version "$VERSION" --sha256 "$SHA" - git diff --check - if git diff --quiet -- packaging/conda/recipe.yaml; then - echo "Conda recipe already current" - exit 0 - fi - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add packaging/conda/recipe.yaml - git commit -m "Sync conda recipe with v$VERSION" - git push - hf-space: needs: resolve runs-on: ubuntu-latest diff --git a/docs/release-and-distribution.md b/docs/release-and-distribution.md index 9e1b17d..44e923e 100644 --- a/docs/release-and-distribution.md +++ b/docs/release-and-distribution.md @@ -43,25 +43,14 @@ PyPI API token from the repository. waits for the matching source distribution to appear on PyPI, then: - updates the Homebrew tap formula URL and SHA-256; -- updates the repository conda recipe version and source-distribution SHA-256; - triggers a factory rebuild of the Hugging Face Space. The workflow can also be started manually with an optional version input. -Conda-forge updates are outside this workflow. If a distribution job fails because a repository or Hugging Face credential is invalid, rotate the corresponding GitHub secret and rerun the failed job. A manual Homebrew formula update is the fallback when its automation is blocked. -The conda job uses the published artifact rather than a locally built archive -as the hash source and commits the resulting recipe change to `main`. Runtime -dependency mapping remains review-controlled: keep it aligned with the default -metadata dependencies in `pyproject.toml`, do not copy optional pixel extras -into the default recipe, and document any conda-forge package that is -unavailable and must be omitted. -The optional `video` extra carries PyAV with Python-version-specific bounds; it -does not belong in the default metadata-focused conda recipe. - ## Source distribution boundary The wheel includes the package under `src/`. @@ -83,8 +72,6 @@ The package uses hatchling through the unpinned `hatchling` build requirement in ## Other channels -The repository includes a conda recipe under `packaging/conda/recipe.yaml`. - The ComfyUI nodes are maintained and versioned in their own repository. After the matching source distribution appears on PyPI, `distribute.yml` dispatches that repository's sync workflow with the exact library version and waits for it @@ -112,7 +99,5 @@ After publication, verify: - the package version matches the tag; - the Homebrew formula points to the new source distribution; - the distribution workflow completed successfully; -- the repository's conda recipe matches the published version and source - distribution; - the ComfyUI Registry node requires the new library version; - a clean install can run `remove-ai-watermarks --version`. diff --git a/packaging/conda/recipe.yaml b/packaging/conda/recipe.yaml deleted file mode 100644 index bf50ea3..0000000 --- a/packaging/conda/recipe.yaml +++ /dev/null @@ -1,62 +0,0 @@ -schema_version: 1 - -context: - version: "0.26.1" - python_min: "3.10" - -package: - name: remove-ai-watermarks - version: ${{ version }} - -source: - url: https://pypi.org/packages/source/r/remove-ai-watermarks/remove_ai_watermarks-${{ version }}.tar.gz - sha256: 4557e10fa2856451df896d87e0158d0232ea5cad90e2c4f2d1359766ac18873b - -build: - noarch: python - number: 0 - script: python -m pip install . -vv --no-deps --no-build-isolation - -requirements: - host: - - python ${{ python_min }}.* - - pip - - hatchling - run: - - python >=${{ python_min }} - - pillow >=10.0.0 - - piexif >=1.1.3 - - click >=8.0.0 - - python-dotenv >=1.0.0 - # c2pa-python is a default PyPI dependency but is not packaged on conda-forge. - # The guarded import falls back to the built-in C2PA byte scanner when it is - # absent. Add it here once a c2pa-python feedstock exists. - -tests: - - python: - imports: - - remove_ai_watermarks - - remove_ai_watermarks.identify - - remove_ai_watermarks.metadata - python_version: ${{ python_min }}.* - # pip_check defaults to true; disable it explicitly. `pip check` fails on - # the conda-forge piexif `py_2` build, whose stale 2019 metadata pip reads - # as "piexif 1.1.3 is not supported on this platform" -- even though the - # package installs, imports, and works. The imports test verifies loading. - pip_check: false - -about: - homepage: https://github.com/wiltodelta/remove-ai-watermarks - summary: Inspect and strip AI provenance metadata from media - description: | - Inspect and strip AI-provenance metadata (C2PA, EXIF, IPTC, and PNG text - chunks) from images and supported video containers. Optional pip extras add - visible watermark removal, video processing, SynthID diffusion removal, and - additional invisible-watermark detectors. - license: Apache-2.0 - license_file: LICENSE - repository: https://github.com/wiltodelta/remove-ai-watermarks - -extra: - recipe-maintainers: - - wiltodelta diff --git a/scripts/sync_conda_recipe.py b/scripts/sync_conda_recipe.py deleted file mode 100644 index f02aaeb..0000000 --- a/scripts/sync_conda_recipe.py +++ /dev/null @@ -1,53 +0,0 @@ -"""Update the conda recipe to a published package version and sdist hash.""" - -from __future__ import annotations - -import argparse -import logging -import re -from pathlib import Path - -log = logging.getLogger(__name__) - -_VERSION_LINE = re.compile(r'^ version: "[^"]+"$', re.MULTILINE) -_SHA256_LINE = re.compile(r"^ sha256: [0-9a-f]{64}$", re.MULTILINE) - - -def update_recipe(text: str, *, version: str, sha256: str) -> str: - """Return recipe text with exactly one context version and source hash updated.""" - if not version or any(char.isspace() for char in version): - raise ValueError("version must be a non-empty value without whitespace") - if re.fullmatch(r"[0-9a-f]{64}", sha256) is None: - raise ValueError("sha256 must be 64 lowercase hexadecimal characters") - - updated, version_count = _VERSION_LINE.subn(f' version: "{version}"', text) - updated, sha_count = _SHA256_LINE.subn(f" sha256: {sha256}", updated) - if version_count != 1 or sha_count != 1: - raise ValueError( - "expected exactly one context version and one source sha256 " - f"(found version={version_count}, sha256={sha_count})" - ) - return updated - - -def main() -> None: - """Update the selected recipe in place.""" - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--version", required=True) - parser.add_argument("--sha256", required=True) - parser.add_argument( - "--recipe", - type=Path, - default=Path("packaging/conda/recipe.yaml"), - ) - args = parser.parse_args() - - original = args.recipe.read_text() - updated = update_recipe(original, version=args.version, sha256=args.sha256) - args.recipe.write_text(updated) - log.info("Updated %s to version %s", args.recipe, args.version) - - -if __name__ == "__main__": - logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") - main() diff --git a/tests/test_sync_conda_recipe.py b/tests/test_sync_conda_recipe.py deleted file mode 100644 index a90335e..0000000 --- a/tests/test_sync_conda_recipe.py +++ /dev/null @@ -1,49 +0,0 @@ -"""Tests for the release-time conda recipe synchronizer.""" - -from __future__ import annotations - -from pathlib import Path - -import pytest - -from scripts.sync_conda_recipe import update_recipe - -_OLD_SHA = "a" * 64 -_NEW_SHA = "b" * 64 -_RECIPE = f"""\ -schema_version: 1 - -context: - version: "1.2.3" - -source: - sha256: {_OLD_SHA} -""" - - -def test_update_recipe_replaces_version_and_hash() -> None: - updated = update_recipe(_RECIPE, version="2.0.0", sha256=_NEW_SHA) - - assert ' version: "2.0.0"' in updated - assert f" sha256: {_NEW_SHA}" in updated - assert "1.2.3" not in updated - assert _OLD_SHA not in updated - - -@pytest.mark.parametrize("sha256", ["", "A" * 64, "f" * 63, "not-a-hash"]) -def test_update_recipe_rejects_invalid_hash(sha256: str) -> None: - with pytest.raises(ValueError, match="sha256"): - update_recipe(_RECIPE, version="2.0.0", sha256=sha256) - - -def test_update_recipe_rejects_ambiguous_recipe() -> None: - duplicate = _RECIPE + f"\nsource_two:\n sha256: {_OLD_SHA}\n" - - with pytest.raises(ValueError, match="exactly one"): - update_recipe(duplicate, version="2.0.0", sha256=_NEW_SHA) - - -def test_repository_recipe_stays_metadata_only() -> None: - recipe = Path("packaging/conda/recipe.yaml").read_text(encoding="utf-8") - - assert " - av >=16\n" not in recipe