From 770ae1104f2e6cda8e1ac71660cd5f6d4cea8ba0 Mon Sep 17 00:00:00 2001 From: Chaim Date: Sun, 21 Jun 2026 18:22:34 +0000 Subject: [PATCH] fix(publish): ship only the installable payload in release assets build_and_publish copied the entire tag archive (minus top dir + .git) into the release zip, leaking dev/docs files to clients: ARCHITECTURE.md, README.md, CHANGELOG.md, build.sh, .env.example, .taskmaster/, .claude/, the repo's own composer.json. This raced n8n IcF30's clean upload under the same asset name, producing two same-named assets per release (one clean, one junk). Filter the copy loop to manifest.json + files/ + scripts/ only (composer.json is generated), matching n8n IcF30 and build.sh. The /publish output is now the clean installable package. Co-Authored-By: Claude Opus 4.6 (1M context) --- app_server.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app_server.py b/app_server.py index e9cc0e7..302a31d 100644 --- a/app_server.py +++ b/app_server.py @@ -347,14 +347,23 @@ def build_and_publish(module, version): with zipfile.ZipFile(ext_zip_path, 'w', zipfile.ZIP_DEFLATED) as ext_zip: ext_zip.writestr('composer.json', json.dumps(composer, indent=2)) - # Re-read archive and copy contents without the top-level dir + # Re-read archive and copy ONLY the installable payload, without the + # top-level dir. Mirror n8n IcF30 / build.sh: ship manifest.json + + # files/ + scripts/ only. Everything else (ARCHITECTURE.md, README.md, + # CHANGELOG.md, build.sh, .env.example, .taskmaster/, .claude/, .git, + # the repo's own composer.json) is dev/docs noise that must NOT reach a + # client install. composer.json is generated above. + INCLUDE_EXACT = {'manifest.json'} + INCLUDE_PREFIXES = ('files/', 'scripts/') with zipfile.ZipFile(archive_path) as src_zip: for item in src_zip.namelist(): if item.endswith('/'): continue # Strip top-level directory rel_path = item[len(prefix):] if prefix and item.startswith(prefix) else item - if not rel_path or rel_path.startswith('.git'): + if not rel_path: + continue + if rel_path not in INCLUDE_EXACT and not rel_path.startswith(INCLUDE_PREFIXES): continue ext_zip.writestr(rel_path, src_zip.read(item))