From 26a1317261122509d2328c10f90dde548b563341 Mon Sep 17 00:00:00 2001 From: Charles Vestal Date: Thu, 14 May 2026 17:11:56 +0200 Subject: [PATCH] Sync root module.json + tag-driven version stamping in release workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The release workflow has two coexisting module.json files (root and src/) and previously did two related but incomplete things: 1. "Verify version match" only compared the git tag against `src/module.json`. At the v0.2.3 tag, src/module.json said 0.2.3 so the check passed. 2. The build step then copied the *root* `module.json` into the tarball, which was still at 0.2.2 because nothing bumps it. So the v0.2.3 release shipped a tarball whose bundled module.json reports 0.2.2. Schwung's Module Store fetches `release.json` (0.2.3), downloads the tarball, finds module.json claims 0.2.2, decides the install is still on 0.2.2 → re-offers v0.2.3 on every sync. Endless update loop. Changes: - module.json (root): one-time bump 0.2.2 -> 0.2.3 so master matches src/module.json and the latest tag. - .github/workflows/release.yml: * Replaced "Verify version match" with "Sync module.json version from tag" — derives VERSION from the tag and writes it into both module.json + src/module.json before the Docker build. The tag is now the single source of truth; bumping module.json before tagging is no longer required. * The "Commit release.json" step now also writes the same version into both module.json files on the default branch and commits them alongside release.json, so the tree stays consistent with what was tagged. Note: the v0.2.3 release asset still has module.json=0.2.2 inside (it was built from the pre-bump tree). Users will keep seeing the update loop on v0.2.3 until either a v0.2.4 is cut with this workflow change, or the v0.2.3 asset is re-uploaded from a rebuild. Reported by a user attempting to update Dissolver via Module Store; the same publisher-side bug also surfaced for bbgen, davebox, and euclidrum this week — PRs sent to all four. --- .github/workflows/release.yml | 56 +++++++++++++++++++++++++++-------- module.json | 2 +- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2a2aaa4..dd23fa4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,15 +14,29 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Verify version match + - name: Sync module.json version from tag run: | - TAG_VERSION="${GITHUB_REF_NAME#v}" - MODULE_VERSION=$(grep '"version"' src/module.json | head -1 | sed 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/') - if [ "$TAG_VERSION" != "$MODULE_VERSION" ]; then - echo "ERROR: Tag version ($TAG_VERSION) does not match module.json version ($MODULE_VERSION)" - exit 1 - fi - echo "Version check passed: $TAG_VERSION" + VERSION="${GITHUB_REF_NAME#v}" + # Write the tag version into every module.json the build / Module + # Store might read so the tag is the single source of truth. + # Previously this workflow only *verified* src/module.json matched + # the tag; the build then copied the *root* module.json into the + # tarball, which could (and did) lag behind src/module.json and + # cause the Module Store to advertise the update forever. + python3 - "$VERSION" <<'PYEOF' + import json, sys, pathlib + version = sys.argv[1] + for p in ("module.json", "src/module.json"): + path = pathlib.Path(p) + if not path.exists(): + continue + data = json.loads(path.read_text()) + data["version"] = version + # Preserve the indent style each file already uses. + indent = 4 if p == "module.json" else 4 + path.write_text(json.dumps(data, indent=indent) + "\n") + print(f" {p}: version -> {version}") + PYEOF - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -54,7 +68,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Commit release.json + - name: Commit release.json + module.json sync run: | VERSION="${GITHUB_REF_NAME#v}" BRANCH=$(git remote show origin | sed -n '/HEAD branch/s/.*: //p') @@ -62,12 +76,30 @@ jobs: git checkout -f "$BRANCH" git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" + # Apply the same module.json sync to the default branch so the + # tree stays consistent with what was tagged (and so the next + # author bumping versions starts from the right place). + python3 - "$VERSION" <<'PYEOF' + import json, sys, pathlib + version = sys.argv[1] + for p in ("module.json", "src/module.json"): + path = pathlib.Path(p) + if not path.exists(): + continue + data = json.loads(path.read_text()) + data["version"] = version + path.write_text(json.dumps(data, indent=4) + "\n") + PYEOF cat > release.json << EOF { "version": "${VERSION}", "download_url": "https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/dissolver-module.tar.gz" } EOF - git add release.json - git commit -m "ci: update release.json for ${{ github.ref_name }}" || echo "No changes to commit" - git push origin "$BRANCH" + git add release.json module.json src/module.json + if git diff --cached --quiet; then + echo "No changes to commit" + else + git commit -m "ci: sync release.json + module.json for ${{ github.ref_name }}" + git push origin "$BRANCH" + fi diff --git a/module.json b/module.json index aa15718..f171f4e 100644 --- a/module.json +++ b/module.json @@ -2,7 +2,7 @@ "id": "dissolver", "name": "Dissolver", "abbrev": "DSLVR", - "version": "0.2.2", + "version": "0.2.3", "description": "Spectral smearing pad generator — kills transients, preserves harmonic content, blends temporality into evolving pads.", "author": "fillioning", "dsp": "dissolver.so",