Monitor, build, and compare the health of all MoonBit packages published on mooncakes (MoonBit's package registry) plus a curated set of Git repositories. The dashboard tracks buildability across OS (Linux / macOS / Windows), backend targets (wasm / wasm-gc / js / native), and channels (stable / nightly / pre-release) to surface regressions and inconsistencies quickly.
See docs/repo-architecture.md for architecture, data flow, command behavior, and common change points.
- Enumerates every MoonBit package from the local mooncakes index (
~/.moon/registry/index/user). - Applies per-package overrides from
resources/repos.ymland exclusion rules fromresources/exclude.yml. - Clones configured GitHub repos and downloads mooncakes package archives.
- Runs a matrix of
moon check,moon build,moon test(test currently build-only) across selected backends & OS. - Captures stdout/stderr, timing, success/failure per command/backend.
- Writes structured line-delimited JSON (
.jsonl) for later rendering in the web UI. - Compares nightly vs stable channel results and labels:
regression– nightly failed but stable succeeded (potential toolchain regression)inconsistent– results differ across platformsok– consistent success or uniformly skipped
| Layer | File(s) | Responsibility |
|---|---|---|
| CLI parsing | lib/cli.ts |
Parse args (--channel, --repos, --exclude, --only). |
| Source discovery | lib/source.ts#getMooncakeSources |
Merge mooncakes index + repos config + exclusions. |
| Mooncakes index access | lib/mooncakesio.ts |
Read local index, filter out test-only packages, discover versions. |
| Download / clone | lib/mooncakesio.ts#downloadTo, lib/git.ts |
Fetch package zip or clone git repo at rev. |
| Execution wrapper | lib/moon.ts#runMoon |
Run moon commands with timeout & capture output. |
| Build + log orchestration | lib/build.ts, lib/log.ts |
Build matrix execution + per-command log file creation. |
| Result aggregation | lib/core.ts#stat |
Collect metadata (run id, toolchain version, timestamps). |
| Type system / schemas | lib/types.ts, schema.ts |
Zod schemas, JSON schema emission. |
| Web UI | web.ts + index.html |
Render table, fetch published .jsonl artifacts, classify results. |
Each output file: data/{os}-{channel}.jsonl
First line: Metadata object:
{
"runId": "<CI_RUN_ID>",
"runNumber": "<CI_RUN_NUMBER>",
"startTime": "2025-10-20T00:00:00.000Z",
"toolchainVersion": ["moon <version lines>"]
}Subsequent lines: BuildResult objects:
{
"source": {"type": "mooncakes", "name": "foo", "version": "1.2.3"},
"cbt": {
"check": {"wasm": {"status": "Success", "elapsed": 123, ...}, ...},
"build": { ... },
"test": { ... }
}
// or "error": "Unable to download"
}Skipped backends/commands use {"status": "Skipped"}. Nightly/pre-release check failures caused by configured warning
checks are marked as {"status": "WarningFailure"}.
Previously each Result embedded full stdout and stderr strings directly in the JSONL, producing very large files
and slow initial page loads.
Now logs are written to separate files under data/logs/ and the JSONL stores lightweight path references:
The file name uses a SHA-256 hash (first 16 hex chars) of the tuple (type, sourceId, command, backend) to keep names
short yet unique:
<hash>.out.log
<hash>.err.log
Frontend behavior: when you click a cell the UI fetches these two log files on demand instead of constructing a Blob from embedded strings. This reduces bandwidth and speeds up initial render.
Benefits:
- Much smaller
data/*.jsonlartifacts. - Browser/CDN can cache individual log files.
- Faster initial dashboard load with lazy log fetching.
Future migration script (planned): deno run -A scripts/migrate-logs.ts <old.jsonl> <new.jsonl> will extract embedded
logs from older artifacts into data/logs/ and rewrite each line with path references.
If a log file is missing or fetch fails, the UI displays a clear error message in the opened tab.
resources/sources.yml– configuration of package sources (Git repos and mooncakes packages).resources/build-config.yml– per-package build configuration (OS/backends/version constraints).schema.ts– emits JSON Schemas:resources/sources.schema.json,resources/build-config.schema.json.
Run schema generation:
deno run -A main.ts schemagit-repos:
- name: corelib
link: https://github.com/moonbitlang/corelib
branch: main
mooncakes:
- name: foo
version: '1.2.3'
exclude:
- deprecated-package
include_all_mooncakes: trueconfigs:
- package: foo
version: '>=1.0.0'
running_os: [linux, macos]
running_backend: [wasm, native]The tool now provides a unified CLI with three subcommands: stat, analyze, and schema.
Requires the MoonBit toolchain (moon executable) in PATH and populated ~/.moon/registry/index/user.
deno run -A main.ts <SUBCOMMAND> [OPTIONS]Collects build statistics across all configured packages and generates JSONL data files.
deno run -A main.ts stat --channel nightly --sources resources/sources.yml --build-config resources/build-config.ymlOptions:
--sources PATH- Path to sources config file (default:resources/sources.yml)--build-config PATH- Path to build config file (default:resources/build-config.yml)--channel stable|nightly- Channel to use (default:stable)--max-concurrent-builds NUMBER- Maximum number of concurrent builds (default: 3)
Generates: data/<os>/<channel>/data.jsonl for the current OS only. (CI runs across all OS variants.)
Search build logs for specific patterns like old operator overloads, library usage, etc.
Simple Analysis Mode (quick failures/slow builds):
deno run -A main.ts analyze --file data/mac/nightly/data.jsonlPattern Search Mode (comprehensive log analysis):
# Use predefined patterns
deno run -A main.ts analyze --predefined old_operators
# Custom patterns
deno run -A main.ts analyze --patterns op_add op_mul @immut/list
# With regex
deno run -A main.ts analyze --patterns "op_\w+" --regex
# Export to CSV
deno run -A main.ts analyze --predefined old_operators --csv results.csv
# Simple output (package names only)
deno run -A main.ts analyze --predefined old_operators --simple
# Filter to specific GitHub organizations
deno run -A main.ts analyze --predefined old_operators --github-orgs moonbitlang moonbit-communityOptions:
-f, --file PATH- Analyze a single data.jsonl file (simple mode: shows failures and slow builds)-p, --patterns PATTERN...- Patterns to search for (can be specified multiple times)-d, --predefined SET- Use predefined pattern set:old_operators,immut_list,moonbitlang_core,json_usage-r, --regex- Treat patterns as regular expressions-s, --simple- Simple output mode (package names only)-c, --csv FILENAME- Export results to CSV file-D, --data-dir PATH- Data directory path (default:data)-g, --github-orgs ORG...- Filter results to specific GitHub organizations (e.g., moonbitlang, moonbit-community)
Predefined Pattern Sets:
old_operators- Old operator overload syntax (op_add, op_mul, etc.)immut_list- Usage of @immut/list packagemoonbitlang_core- Usage of @moonbitlang/core packagejson_usage- JSON-related functionality usage
GitHub Organization Filtering:
When you specify --github-orgs, the tool will output an additional list of GitHub repositories from the specified organizations that need to be fixed. This is useful for focusing on packages maintained by specific organizations like moonbitlang or moonbit-community.
Example output:
================================================================================
需要修复的GitHub仓库 (组织: moonbitlang, moonbit-community)
================================================================================
总数: 5
1. https://github.com/moonbitlang/core
2. https://github.com/moonbitlang/x
3. https://github.com/moonbit-community/async
4. https://github.com/moonbit-community/http
5. https://github.com/moonbit-community/json
Generates JSON schema files for configuration validation.
deno run -A main.ts schemaGenerates:
resources/sources.schema.jsonresources/build-config.schema.json
To prevent timeouts caused by excessive parallelism, the dashboard implements concurrency control at the package level
using a simple Promise.race based approach.
Package-level concurrency (--max-concurrent-builds): Limits how many packages are built at the same time (default:
3).
You can configure this limit via:
- CLI argument:
--max-concurrent-builds - Environment variable:
MAX_CONCURRENT_BUILDS
Example:
# Limit to 2 concurrent packages
deno run -A main.ts stat --max-concurrent-builds 2
# Or via environment variable
MAX_CONCURRENT_BUILDS=2 deno run -A main.ts statImplementation details: The executeWithConcurrency function uses standard Web APIs (Promise-based) without any
external dependencies:
- Maintains a Set of executing promises (避免数组 splice 导致的索引问题)
- When the concurrency limit is reached, waits for any task to complete using
Promise.race - Tasks automatically remove themselves from the Set when completed
- Ensures results maintain the same order as input tasks
- Compatible with both Deno and Node.js
Within each package, different backend targets (wasm, js, native, etc.) are built sequentially to avoid resource contention.
The frontend (web.ts) bundles to web.js and fetches published artifacts (e.g. from GitHub Pages). It:
- Merges per-source results across all (OS, channel) combinations.
- Computes a per-source label (
regression,inconsistent,ok). - Provides per-cell click to open raw logs (stdout/stderr + timing) for a specific command/backend.
Dev bundle (watch):
deno task devEach moon command is wrapped with a 60s timeout to avoid hanging builds/tests. Test runs use --build-only to prevent
potentially long-running suites.
For each platform: if nightly fails while stable succeeds → mark regression. If mixed success/failure exists across platforms within a channel → inconsistent.
- Line-delimited JSON allows streaming parse in web UI and incremental processing.
- Separation of source discovery and build execution keeps logic modular.
- Zod schemas ensure config validation early and enable automatic JSON Schema generation.
- Stateless execution: each source builds in a fresh temp dir, avoiding cross-contamination.
- 2025-10 refactor:
core.ts精简为仅聚合与调度;新增source.ts/build.ts/log.ts分离职责,提升可维护性与测试粒度。
- Missing
moonbinary → install MoonBit toolchain first. - Empty index → ensure you have fetched packages (
moon updateto sync registry). - Lots of
Skippedstatuses → current OS not in packagerunning_os; check overrides inrepos.yml. - Timeout failures → inspect logs; consider increasing timeout logic if legitimately long builds.