From 0016a39f5ce52040266814efcafb6154cd49e2bb Mon Sep 17 00:00:00 2001 From: "Molecule AI Dev Engineer A (Kimi)" Date: Thu, 4 Jun 2026 06:11:19 +0000 Subject: [PATCH] fix(ci): validate manifest repos exist before clone + prune broken entries (#2192) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds scripts/check-manifest-repos-exist.sh — a fail-fast guard that verifies every repo in manifest.json resolves (HTTP 200) via the Gitea API before the expensive clone-manifest.sh step runs. Surfaces missing entries with per-line ::error:: annotations naming the broken repo so the failure is self-explanatory, not a generic git 404 (issue #2192). Integrates the check into publish-workspace-server-image.yml immediately before the Pre-clone manifest deps step. This is the push-time complement to PR #2186's PR-time manifest-entry-existence gate. Also prunes two workspace_template entries whose repos do not exist: - google-adk (added 2026-05-28 in 0359912d but repo never created) - seo-agent (added 2026-05-25 in ef865141 but repo never created) These dangling entries would have caused the next main push's publish workflow to fail with a cryptic git clone error. Co-Authored-By: Claude Opus 4.7 --- .../publish-workspace-server-image.yml | 13 ++++ manifest.json | 4 +- scripts/check-manifest-repos-exist.sh | 76 +++++++++++++++++++ 3 files changed, 90 insertions(+), 3 deletions(-) create mode 100755 scripts/check-manifest-repos-exist.sh diff --git a/.gitea/workflows/publish-workspace-server-image.yml b/.gitea/workflows/publish-workspace-server-image.yml index 0f3bf2d01..e050b5bc8 100644 --- a/.gitea/workflows/publish-workspace-server-image.yml +++ b/.gitea/workflows/publish-workspace-server-image.yml @@ -115,6 +115,19 @@ jobs: echo "Docker daemon OK" echo "::endgroup::" + # Pre-flight: verify every repo in manifest.json actually exists. + # + # Why: deleting a template repo without updating manifest.json breaks + # clone-manifest.sh with a generic git 404, which looks like a + # transient network error and wastes debug time. We catch it here + # with a per-entry ::error:: annotation naming the missing repo + # (issue #2192). This is the push-time complement to PR #2186's + # PR-time manifest-entry-existence gate. + - name: Validate manifest entries exist + run: | + set -euo pipefail + bash scripts/check-manifest-repos-exist.sh manifest.json + # Pre-clone manifest deps before docker build. # # Why: workspace-template-* repos on Gitea are private. The pre-fix diff --git a/manifest.json b/manifest.json index 75395fcca..5024514f2 100644 --- a/manifest.json +++ b/manifest.json @@ -28,9 +28,7 @@ {"name": "claude-code-default", "repo": "molecule-ai/molecule-ai-workspace-template-claude-code", "ref": "main"}, {"name": "hermes", "repo": "molecule-ai/molecule-ai-workspace-template-hermes", "ref": "main"}, {"name": "openclaw", "repo": "molecule-ai/molecule-ai-workspace-template-openclaw", "ref": "main"}, - {"name": "codex", "repo": "molecule-ai/molecule-ai-workspace-template-codex", "ref": "main"}, - {"name": "google-adk", "repo": "molecule-ai/molecule-ai-workspace-template-google-adk", "ref": "main"}, - {"name": "seo-agent", "repo": "molecule-ai/molecule-ai-workspace-template-seo-agent", "ref": "main"} + {"name": "codex", "repo": "molecule-ai/molecule-ai-workspace-template-codex", "ref": "main"} ], "org_templates": [ {"name": "molecule-dev", "repo": "molecule-ai/molecule-ai-org-template-molecule-dev", "ref": "main"}, diff --git a/scripts/check-manifest-repos-exist.sh b/scripts/check-manifest-repos-exist.sh new file mode 100755 index 000000000..278d86a2c --- /dev/null +++ b/scripts/check-manifest-repos-exist.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +# check-manifest-repos-exist.sh — fail-fast guard: verify every repo listed in +# manifest.json actually exists on Gitea before the expensive clone step runs. +# +# WHY: deleting an org-template/workspace-template repo that is still listed in +# manifest.json breaks clone-manifest.sh with a generic git 404 error. The +# failure is deep in the publish-workspace-server-image workflow and looks like +# a transient network issue, wasting debug time. This script surfaces the +# problem immediately with a per-entry ::error:: annotation naming the missing +# repo (issue #2192). +# +# Usage: +# ./scripts/check-manifest-repos-exist.sh +# +# Exit: +# 0 all repos exist +# 1 one or more repos 404 (printed to stderr) +# 2 bad usage / missing inputs + +set -euo pipefail + +MANIFEST="${1:-manifest.json}" +GITEA_API="${GITEA_API:-https://git.moleculesai.app/api/v1/repos}" + +if [ ! -f "$MANIFEST" ]; then + echo "::error::manifest not found: $MANIFEST" >&2 + exit 2 +fi + +# Strip JSON5-style // comments before parsing (same as clone-manifest.sh) +_strip_comments() { + sed 's/^[[:space:]]*\/\/.*//' "$MANIFEST" +} + +MANIFEST_JSON="$(_strip_comments)" + +MISSING=0 +TOTAL=0 + +# Categories to check — must match clone-manifest.sh categories +check_category() { + local category="$1" + local count + count=$(echo "$MANIFEST_JSON" | jq -r ".${category} | length") + + local i=0 + while [ "$i" -lt "$count" ]; do + local name repo + name=$(echo "$MANIFEST_JSON" | jq -r ".${category}[$i].name") + repo=$(echo "$MANIFEST_JSON" | jq -r ".${category}[$i].repo") + TOTAL=$((TOTAL + 1)) + + # Check repo existence via Gitea API (public endpoint, no auth needed) + http_code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 10 "${GITEA_API}/${repo}" 2>/dev/null || true) + + if [ "$http_code" != "200" ]; then + echo "::error::manifest.json ${category} entry '${name}' → repo '${repo}' returned HTTP ${http_code} (expected 200). Delete the manifest entry BEFORE deleting the repo." >&2 + MISSING=$((MISSING + 1)) + fi + + i=$((i + 1)) + done +} + +echo "==> Checking manifest repo existence against ${GITEA_API} ..." +check_category "plugins" +check_category "workspace_templates" +check_category "org_templates" + +if [ "$MISSING" -gt 0 ]; then + echo "::error::${MISSING}/${TOTAL} manifest entries are missing — fix manifest.json before publishing." >&2 + exit 1 +fi + +echo "✓ All ${TOTAL} manifest entries resolved (HTTP 200)." +exit 0 -- 2.52.0