Skip to content

fix: republish release metadata on every deploy#11

Open
kattapug wants to merge 1 commit into
sdevil7th:mainfrom
kattapug:fix/republish-release-metadata-on-every-deploy
Open

fix: republish release metadata on every deploy#11
kattapug wants to merge 1 commit into
sdevil7th:mainfrom
kattapug:fix/republish-release-metadata-on-every-deploy

Conversation

@kattapug

Copy link
Copy Markdown

Problem

Every release-metadata URL on openstudio.org.in currently returns the SPA HTML shell:

GET /releases/ai-runtime/stable/latest.json  -> 200  text/html  31735 bytes
GET /appcast/windows-stable.xml              -> 200  text/html  31735 bytes
GET /nonexistent-probe-xyz.json              -> 200  text/html  31735 bytes   <- identical

(Server: Netlify, Cache-Status: "Netlify Edge"; hit. The _headers no-store rule for those paths is applied, so the deploy simply has no file there and /* -> /index.html 200 answers instead.)

Shipped desktop builds break on this. OpenStudio's AI Tools Setup fetches https://openstudio.org.in/releases/ai-runtime/stable/latest.json, receives HTML, juce::JSON::parse fails, and the user gets:

AI runtime download info is unavailable — Error reported: The AI runtime manifest was not valid JSON. — Terminal reason: runtime_manifest_invalid

The AI runtime is fully published (v0.0.40 carries OpenStudio-ai-runtime-stable-latest.json, runtime 0.0.11); only the website copy is gone.

Root cause

stageReleasePublishInputs() stages /releases and /appcast only from release-input/, and calls ensureCleanGeneratedReleaseTargets() when it finds nothing. release-input/ is gitignored and is populated only by .github/workflows/publish-release-surfaces.yml (repository_dispatch: openstudio_release_published).

So the metadata exists only in deploys produced by that workflow. Any ordinary Netlify build from a git push produces a dist with those files deliberately removed, silently overwriting them in production.

Timeline matches: last publish run 2026-05-19 (v0.0.40) → last website commit 2026-06-11 → metadata gone.

Change

Make an ordinary deploy self-sufficient. When release-input/ has no metadata, hydrate it from the desktop repo's release assets, then stage and validate exactly as before:

  • hydrateReleaseMetadataInputs() — downloads the 6 required assets (+ optional Linux appcast) into release-input/.
  • Tries https://github.com/<repo>/releases/latest/download/<asset> first; on failure falls back to scanning /releases for the newest non-draft, non-prerelease release carrying all required assets. GitHub's "latest" can be an ai-runtime-v* release, which does not publish them.
  • Failure only console.warns — offline/local builds behave exactly as today.
  • The publish workflow is unaffected: its release-input/ is already populated, so hydration never runs there.
  • Opt out with OPENSTUDIO_FETCH_RELEASE_METADATA=0; repo override reuses the existing OPENSTUDIO_DESKTOP_REPO.
  • .gitignore: added public/releases/stable/*, generated by staging but not covered by the existing patterns.

Verification

  • npm run stage-release-publish-inputs on a clean checkout (no release-input/) hydrates all seven files from v0.0.40; npm run validate-release-publish-inputs passes; staged latest.json reports appVersion 0.0.40, runtimeVersion 0.0.11, new platforms.windows.base shape intact.
  • New test/release-metadata-hydration.test.mjs (3 tests, injected fetch): happy path, fallback-to-release-scan, and no-release-found returning a reason instead of throwing. npm run test:release-metadata — 3/3 pass; test:ai-runtime still 6/6.
  • npx eslint clean on changed files.

Note

This fixes future deploys. To restore production now, re-run the publish workflow for the current release:

gh api repos/sdevil7th/OpenStudioWebsite/dispatches \
  -f event_type=openstudio_release_published \
  -F 'client_payload[tag]=v0.0.40' \
  -F 'client_payload[channel]=stable' \
  -F 'client_payload[desktopRepo]=sdevil7th/OpenStudio'

🤖 Generated with Claude Code

/releases/*.json and /appcast/*.xml are only staged into the deploy when
release-input/ is populated, which happens exclusively in the "Publish Release
Surfaces" workflow. release-input/ is gitignored, and stageReleasePublishInputs()
calls ensureCleanGeneratedReleaseTargets() when it finds nothing, so any other
deploy (a content push that triggers a Netlify build) ships a dist with those
files removed. The SPA catch-all then answers those URLs with index.html.

That is what production is serving today: every metadata URL, and any nonexistent
path, returns the same 31735-byte HTML shell with HTTP 200. Shipped desktop apps
hit it - OpenStudio's AI Tools setup fetches
https://openstudio.org.in/releases/ai-runtime/stable/latest.json, gets HTML,
fails juce::JSON::parse and reports "The AI runtime manifest was not valid JSON"
(terminal reason runtime_manifest_invalid). The last publish workflow run was
2026-05-19; the last website commit is 2026-06-11, which is when the metadata
was overwritten.

Make the website self-sufficient: when release-input/ has no metadata, hydrate it
from the desktop repo's GitHub release assets before staging. Tries
/releases/latest/download/ first, then falls back to scanning releases for the
newest one that carries all required assets (GitHub's "latest" can be an
ai-runtime-v* release, which does not publish them). Failure only warns, so
offline and local builds behave as before, and the publish workflow is untouched
because its release-input/ is already populated.

Opt out with OPENSTUDIO_FETCH_RELEASE_METADATA=0. Repo override via the existing
OPENSTUDIO_DESKTOP_REPO.

Also ignore public/releases/stable/*, which the staging step generates but the
existing patterns did not cover.

Verified: npm run stage-release-publish-inputs on a clean checkout hydrates all
seven files from v0.0.40 and npm run validate-release-publish-inputs passes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@netlify

netlify Bot commented Jul 24, 2026

Copy link
Copy Markdown

👷 Deploy request for openstudiowebsite pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit a58f97b

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant