forked from molecule-ai/molecule-core
The Canvas template palette was empty on a fresh clone because
`workspace-configs-templates/`, `org-templates/`, and `plugins/` are
gitignored and nothing populated them. The registry already exists —
`manifest.json` at repo root lists every curated
`workspace-template-*`, `org-template-*`, and `plugin-*` repo, and
`scripts/clone-manifest.sh` clones them — but the step was absent
from the README and setup.sh, so new users never ran it.
### What this commit does
**1. `setup.sh` runs `clone-manifest.sh` automatically** (once).
After starting the Docker network but before booting infra, iterate
`manifest.json` and clone any workspace_templates / org_templates /
plugins that aren't already populated. Idempotent — subsequent
runs skip dirs that have content. Requires `jq`; when jq is missing
the step prints a clear install hint and skips (doesn't fail).
**2. `clone-manifest.sh` is idempotent.** Before running `git clone`,
check whether the target directory already exists and is non-empty —
skip if so. Lets `setup.sh` rerun safely without forcing the operator
to delete already-cloned template repos.
**3. `ListTemplates` logs the reason it skips a template.** The
handler previously swallowed `resolveYAMLIncludes` errors with
`continue`, so a broken template showed up as an empty palette with
no log trail. Now the include-expansion and yaml.Unmarshal failure
paths both emit a descriptive `log.Printf` — the exact message that
made the stale `org-templates/molecule-dev/` snapshot debuggable:
ListTemplates: skipping molecule-dev — !include expansion failed:
!include "core-platform.yaml" at line 25: open .../teams/
core-platform.yaml: no such file or directory
**4. Remove the in-tree `org-templates/molecule-dev/` snapshot** (170
files). Matches the explicit intent of prior commit
`bfec9e53` — "remove org-templates/molecule-dev/ — standalone repo
is source of truth". A later "full staging snapshot" re-added a
partial copy that had `!include` references to 7 role files that
never existed in the snapshot (`core-platform.yaml`,
`controlplane.yaml`, `app-docs.yaml`, `infra.yaml`, `sdk.yaml`,
`release-manager/workspace.yaml`, `integration-tester/workspace.yaml`).
`clone-manifest.sh` repopulates it fresh from
`Molecule-AI/molecule-ai-org-template-molecule-dev`.
.gitignore exception for `molecule-dev/` is dropped accordingly
— the whole `/org-templates/*` tree is now gitignored, symmetric
with `/plugins/` and `/workspace-configs-templates/`.
**5. Doc updates** (README, README.zh-CN, CONTRIBUTING) mention `jq`
as a prerequisite and describe what setup.sh now does.
### Verification
On a fresh-nuked DB with the updated branch:
1. `bash infra/scripts/setup.sh` — cleanly clones 33/33 manifest
repos (20 plugins, 8 workspace_templates, 5 org_templates), then
boots infra. Second run skips all 33 (idempotent).
2. `go run ./cmd/server` — "Applied 41 migrations", :8080 healthy.
3. `curl http://localhost:8080/org/templates` returns 4 templates
(was `[]`):
- Free Beats All
- MeDo Smoke Test
- Molecule AI Worker Team (Gemini)
- Reno Stars Agent Team
4. `bash tests/e2e/test_api.sh` — 61/61 pass.
5. `npx vitest run` in canvas — 902/902 pass.
6. `shellcheck infra/scripts/setup.sh` — clean.
### SaaS parity
All changes are local-dev surface. `setup.sh`, `clone-manifest.sh`,
and the local `org-templates/` directory aren't part of the CP
provisioner path — SaaS tenant machines get their templates via
Dockerfile layers or CP-side provisioning, not `clone-manifest.sh`.
The `ListTemplates` log addition is harmless either way (replaces a
silent `continue` with a `log.Printf + continue`).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
78 lines
2.6 KiB
Bash
Executable File
78 lines
2.6 KiB
Bash
Executable File
#!/bin/sh
|
|
# clone-manifest.sh — clone all repos listed in manifest.json into their
|
|
# target directories. Replaces hardcoded git-clone lines in Dockerfiles.
|
|
#
|
|
# Usage:
|
|
# ./scripts/clone-manifest.sh <manifest.json> <ws-templates-dir> <org-templates-dir> <plugins-dir>
|
|
#
|
|
# Requires: git, jq (lighter than python3 — ~2MB vs ~50MB in Alpine)
|
|
|
|
set -euo pipefail
|
|
|
|
MANIFEST="${1:?Usage: clone-manifest.sh <manifest.json> <ws-dir> <org-dir> <plugins-dir>}"
|
|
WS_DIR="${2:?Missing workspace-templates dir}"
|
|
ORG_DIR="${3:?Missing org-templates dir}"
|
|
PLUGINS_DIR="${4:?Missing plugins dir}"
|
|
|
|
EXPECTED=0
|
|
CLONED=0
|
|
|
|
clone_category() {
|
|
local category="$1"
|
|
local target_dir="$2"
|
|
|
|
mkdir -p "$target_dir"
|
|
|
|
local count
|
|
count=$(jq -r ".${category} | length" "$MANIFEST")
|
|
EXPECTED=$((EXPECTED + count))
|
|
|
|
local i=0
|
|
while [ "$i" -lt "$count" ]; do
|
|
local name repo ref
|
|
name=$(jq -r ".${category}[$i].name" "$MANIFEST")
|
|
repo=$(jq -r ".${category}[$i].repo" "$MANIFEST")
|
|
ref=$(jq -r ".${category}[$i].ref // \"main\"" "$MANIFEST")
|
|
|
|
# Idempotent: skip if the target already looks populated. Lets the
|
|
# README quickstart rerun setup.sh safely without having to delete
|
|
# already-cloned repos. A directory with any entries counts as
|
|
# populated; empty dirs reclone (may exist from a prior failed run).
|
|
if [ -d "$target_dir/$name" ] && [ -n "$(ls -A "$target_dir/$name" 2>/dev/null || true)" ]; then
|
|
echo " skipping $target_dir/$name (already populated)"
|
|
CLONED=$((CLONED + 1))
|
|
i=$((i + 1))
|
|
continue
|
|
fi
|
|
|
|
echo " cloning $repo -> $target_dir/$name (ref=$ref)"
|
|
if [ "$ref" = "main" ]; then
|
|
git clone --depth=1 -q "https://github.com/${repo}.git" "$target_dir/$name"
|
|
else
|
|
git clone --depth=1 -q --branch "$ref" "https://github.com/${repo}.git" "$target_dir/$name"
|
|
fi
|
|
CLONED=$((CLONED + 1))
|
|
i=$((i + 1))
|
|
done
|
|
|
|
# Strip .git dirs to save space
|
|
find "$target_dir" -name '.git' -type d -exec rm -rf {} + 2>/dev/null || true
|
|
}
|
|
|
|
echo "==> Cloning workspace templates..."
|
|
clone_category "workspace_templates" "$WS_DIR"
|
|
|
|
echo "==> Cloning org templates..."
|
|
clone_category "org_templates" "$ORG_DIR"
|
|
|
|
echo "==> Cloning plugins..."
|
|
clone_category "plugins" "$PLUGINS_DIR"
|
|
|
|
# Verify all repos were cloned
|
|
if [ "$CLONED" -ne "$EXPECTED" ]; then
|
|
echo "::error::Expected $EXPECTED repos but only cloned $CLONED — some clones failed"
|
|
exit 1
|
|
fi
|
|
|
|
echo "==> Done. $CLONED/$EXPECTED repos cloned successfully."
|