Skip to content

fix: resolve action path at runtime so container jobs work - #107

Merged
hustcer merged 1 commit into
hustcer:mainfrom
dowdiness:fix/container-action-path
May 22, 2026
Merged

fix: resolve action path at runtime so container jobs work#107
hustcer merged 1 commit into
hustcer:mainfrom
dowdiness:fix/container-action-path

Conversation

@dowdiness

Copy link
Copy Markdown
Contributor

Container jobs fail at the Setup MoonBit step with module .../moonbit.nu not found.

${{ github.action_path }} is a workflow expression. GitHub Actions resolves it on the host runner and bakes in a host path like /home/runner/work/_actions/.... Containers mount action files at /__w/_actions/..., so that path is gone inside the container and use can't find moonbit.nu.

The fix drops the use directive and invokes def main from moonbit.nu as an external nu process via $env.GITHUB_ACTION_PATH, which resolves correctly in both runner types.

^nu $"($env.GITHUB_ACTION_PATH)/nu/moonbit.nu" $version $"--setup-core=($setup_core)" $"--core-version=($core_version)"

The $"--setup-core=($setup_core)" wrap is required because nu does not interpolate booleans inside --flag=$var when calling external commands. Without it, the flag arrives unset.

Tested on a downstream repo's CI. Three container jobs (web-e2e, demo-react-e2e, canvas-e2e) pass with this fork. Diff is +3/-2 on action.yaml. Non-container jobs are unaffected.

`use ${{ github.action_path }}/nu/moonbit.nu *` expands at workflow time
to a host-side path (`/home/runner/work/_actions/...`). Container jobs
mount the action files at `/__w/_actions/...`, so the baked-in host path
is invisible there and nu fails with `module ... moonbit.nu not found`.

Drop the `use` directive and invoke moonbit.nu's existing `def main`
via `^nu <path> <args>`. The path is resolved at runtime through
$env.GITHUB_ACTION_PATH, which GHA rewrites correctly for both host
and container contexts.

Boolean switch args need the `$"--flag=($var)"` string-interpolation
form because nu's external-command arg passing doesn't interpolate
bool variables inside `--flag=$var`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hustcer
hustcer merged commit dfde332 into hustcer:main May 22, 2026
1 check failed
@github-actions github-actions Bot added this to the v1.20.0 milestone May 22, 2026
@hustcer

hustcer commented May 22, 2026

Copy link
Copy Markdown
Owner

Looks good to me. Thanks
I will release a new version later

@hustcer hustcer modified the milestones: v1.20.0, v1.22.0 May 22, 2026
hustcer added a commit that referenced this pull request May 22, 2026
Cover the regression fixed in dfde332: ${{ github.action_path }}
points to a host path that does not exist inside container jobs,
so the action must resolve files via $env.GITHUB_ACTION_PATH.
hustcer added a commit that referenced this pull request May 22, 2026
Cover the regression fixed in dfde332: ${{ github.action_path }}
points to a host path that does not exist inside container jobs,
so the action must resolve files via $env.GITHUB_ACTION_PATH.
@hustcer

hustcer commented May 22, 2026

Copy link
Copy Markdown
Owner

dowdiness added a commit to dowdiness/canopy that referenced this pull request May 23, 2026
…tainers)

v1.22 includes hustcer/setup-moonbit#107 — resolves \$env.GITHUB_ACTION_PATH
at runtime instead of baking in a host path via the \${{ github.action_path }}
workflow expression. The previous behavior broke container jobs (Web E2E,
Demo React E2E, Canvas E2E), which mount action files at /__w/_actions/...
instead of the host /home/runner/work/_actions/... path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dowdiness added a commit to dowdiness/canopy that referenced this pull request May 23, 2026
…331)

* chore: bump loom (registry incr switch) + pin canopy to incr@0.5.2

Bumps the loom submodule to 9cc25c7 (loom#138), which:
- pins loom's own incr deps to registry "0.5.2"
- resets the incr submodule to v0.5.2 release tag (c885d19)
- exports the whitebox helper `explain_reuse_rejection` so canopy's
  `moon check --deny-warn` no longer trips

Also flips canopy's own incr declaration from
  { "path": "./loom/incr", "version": "0.5.1" }
to a plain registry string "0.5.2".

Net effect: canopy and the loom monorepo agree on registry 0.5.2 for
incr, and the loom/incr submodule directory is now byte-equivalent to
that mooncake — preserving the build behavior canopy/main had before
PR #137 of loom landed the breaking ideal-API rename slice.

The Phase 3a caller migration (60-80 Runtime::read sites in canopy)
remains the unblocking work for picking up incr ≥ #61; that lands in
a separate session.

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

* ci: bump hustcer/setup-moonbit v1.21 → v1.22 (action path fix for containers)

v1.22 includes hustcer/setup-moonbit#107 — resolves \$env.GITHUB_ACTION_PATH
at runtime instead of baking in a host path via the \${{ github.action_path }}
workflow expression. The previous behavior broke container jobs (Web E2E,
Demo React E2E, Canvas E2E), which mount action files at /__w/_actions/...
instead of the host /home/runner/work/_actions/... path.

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dowdiness added a commit to dowdiness/canopy that referenced this pull request May 24, 2026
…=0 (#333)

* chore(workspace): add 5 in-repo modules to moon.work

Adds lib/semantic + examples/{ideal,block-editor,canvas,codemirror_demo}
as workspace members so root-level `moon check` and `moon test` cover
them without the per-example `cd` fanout. `moon work sync` stamped the
`version:` field onto path-deps in the newly-added members (matches the
existing convention from prior workspace members).

Submodules (event-graph-walker, loom/*, rabbita/*, etc.) intentionally
stay on cd-fanout — they have independent CI and publish cadence.
The CI `test-examples` matrix is left alone for parallel feedback.

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

* ci: revert container-job carve-outs after setup-moonbit v1.22

hustcer/setup-moonbit#107 (merged upstream 2026-05-22, released as
v1.22) fixes the action-path resolution bug that broke container jobs.
The composite action at .github/actions/setup-moonbit/action.yml is
already pinned to v1.22, so the 3 container jobs (web-e2e,
demo-react-e2e, canvas-e2e) can now use it like every other job
instead of an inline `curl unix.sh | bash` carve-out.

The original carve-out comment claimed nushell wasn't visible inside
the container, but the action actually installs nushell itself via
hustcer/setup-nu@v3.22 — the real failure was action-path resolution,
which #107 fixes.

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

* ci: add toolchain setup experiment workflow

Compares three MoonBit setups in parallel on this branch's CI runs to
gather data for the long-term choice between staying on the v0.9.2 pin
or dropping it once moon#1716 has known workarounds:

  A. latest compiler + NEW_MOON_MOD=0
  B. latest compiler, no env opt-out
  C. v0.9.2 pin + NEW_MOON_MOD=0

Bobzhang flagged NEW_MOON_MOD=0 as an unstable-feature opt-out on
moonbitlang/moon#1716, and hustcer confirmed it works elsewhere. Setup
A tests whether that env var alone is enough with the workspace
expansion already on this branch; B is the no-opt-out control; C
combines the pin with the env var to confirm they don't interact badly.

Non-blocking: continue-on-error on both the job and every step so the
full failure surface is visible per setup instead of stopping at the
first red command.

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

* ci: add moon update step to toolchain experiment

The first experiment run (26330420535) failed every setup at `moon
check` with "module was not found in the registry" because the
registry cache wasn't populated. The existing CI does `moon update`
before `moon check` (scripts/run-moon-module.sh `ci` action). Reusing
scripts/update-moon-deps.sh so the experiment mirrors prod setup.

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

* fix(semantic): replace Result-snapshot inspect with pattern-match tests

derive(Show) on container types (Result, Option, etc.) is deprecated
in MoonBit 0.9.2; using `inspect(r, content=...)` on a `Result[T, E]`
triggers warning [0020]. Under `moon check --deny-warn` (the CI ci
action) this turns into a hard error.

Rewrite the 4 affected tests to pattern-match the raised error and
assert on the inner float value with assert_eq / assert_true(is_nan()).
Same coverage, no Show snapshot.

Surfaced now because lib/semantic became a workspace member in the
prior commit — Test Main Module's `moon check --deny-warn` now scans
it as well.

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

* style(block-editor): apply moon fmt to main/*.mbt

Multi-line function-call formatting (one arg per line) that moon fmt
wants to collapse to single-line. Format drift that was undetected
before because examples/block-editor wasn't a workspace member;
adding it to moon.work made workspace-root `moon fmt --check`
discover it.

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

* ci: drop v0.9.2 pin in favour of latest + NEW_MOON_MOD=0

Switch the composite action from `version: 0.9.2+bbe2b338f` (pinned
2026-05-23 as PR #325) to the latest MoonBit toolchain, with
NEW_MOON_MOD=0 exported into $GITHUB_ENV so every downstream step
inherits the opt-out.

Validated by toolchain-experiment workflow (run 26330483536):

  - latest + NEW_MOON_MOD=0   moon check ✓, test ✓ 1350, 0 migration warnings
  - latest, no env opt-out    moon check ✓, test ✓ 1350, 13 migration warnings
  - v0.9.2 pin + env (status quo)   moon check ✓, test ✓ 1350

bobzhang flagged NEW_MOON_MOD=0 as the unstable-feature opt-out for
rr_moon_mod on moonbitlang/moon#1716; hustcer confirmed it works. The
opt-out unblocks compiler updates without re-triggering the migration
cascade that broke CI on 2026-05-22.

Tradeoff: NEW_MOON_MOD is an unstable-feature toggle; a future moon
release could remove it. If/when that happens, either upstream
moon#1716 has shipped path-dep TOML syntax (no action needed) or we
re-pin to the last working version (one-line revert of this commit).

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

* style(canvas): apply moon fmt to canvas_update.mbt

Same root cause as the block-editor format commit — adding
examples/canvas to moon.work made workspace-root `moon fmt --check`
scan it, surfacing pre-existing multi-line-collapse drift.

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

* ci: suppress warning [20] (Show-on-container deprecation) under --deny-warn

The latest MoonBit compiler (validated in PR #325 follow-up branch as
Setup A on 2026-05-23) reports ~150 [0020] deprecation sites across
canopy core that the v0.9.2 pin didn't enforce. Each site uses
inspect() on a Result/Option/tuple/array, which now requires Debug
instead of Show.

Cleaning all 150 sites is a separate workstream. To unblock the
toolchain upgrade without losing warning-as-error discipline for
everything else, the ci/check actions now pass `--warn-list "-20"`
alongside `--deny-warn`: warning 20 becomes a soft warning, other
warnings stay hard errors.

`moon check` (no --deny-warn) still surfaces the warnings, so the
deprecation debt remains visible locally — just not blocking in CI.

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

* style: apply moon fmt under MoonBit 0.1.20260522 across 62 files

The latest MoonBit toolchain (selected by the prior Setup A commit)
formats some constructs differently than the v0.9.2 pin:

  - `pub impl X with method(self, ...)` now requires `fn`:
    `pub impl X with fn method(self, ...)`
  - moon.pkg imports drop the `@alias` suffix when it matches the
    module name (e.g. `"dowdiness/seam" @seam` → `"dowdiness/seam"`)

Auto-applied via `moon fmt` workspace-wide. No behavior change — every
diff is either the `fn` insertion or a redundant-alias removal.

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

* fix(ci): set MOON_WORK=off for canvas E2E build

Adding examples/canvas to moon.work (prior commit) broke the canvas
JS build pipeline. In workspace mode, `moon build --target js` only
emits wasm-gc artifacts — canvas's `preferred-target: js` declaration
is ignored. vite-plugin-moonbit then can't find
_build/js/release/build/main/main.js and the Playwright run fails
loading '@moonbit/canopy-canvas'.

Setting MOON_WORK=off in test-canvas-e2e.sh scopes moon to the canvas
package only when vite kicks off the build. The workspace stays
intact for everything else (moon check/test at root, the per-example
matrix in test-examples, etc.).

The underlying moon behavior (workspace target overriding member
preferred-target) is worth raising upstream — the v0.9.2 release
notes specifically claimed per-member preferred-target is honored.

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

* fix(ci): wire benchmark editor-response job through composite action + MOON_WORK=off

Two stacked issues caused the Editor Response Benchmark to fail on
this PR:

1. The job used inline `curl unix.sh | bash` instead of the composite
   action, so it didn't inherit `NEW_MOON_MOD=0`. With the latest moon
   and no opt-out, vite-time builds trigger the rr_moon_mod migration
   cascade.

2. examples/ideal is now a moon.work member, and vite-plugin-moonbit
   kicks off `moon build` inside it. In workspace mode `moon build
   --target js` only emits wasm-gc artifacts (canvas hit the exact
   same workspace-vs-preferred-target bug — see prior commit). The
   `_build/js/release/build/main/main.js` bundle vite expects is
   never produced and the Ideal editor never finishes loading, so the
   `Text` mode button never appears and the perf spec times out.

Switching the moon setup to the composite action gives us
NEW_MOON_MOD=0 transitively, and exporting MOON_WORK=off for the
npm-run step bypasses workspace mode for the JS build.

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

* chore(ci): remove toolchain-experiment workflow

Served its purpose — validated three MoonBit setup variants against
CI on this branch (run 26334290884 was the final clean comparison),
which selected Setup A (latest compiler + NEW_MOON_MOD=0) as the
long-term choice. Findings are captured in commit messages
('ci: drop v0.9.2 pin in favour of latest + NEW_MOON_MOD=0') and PR
#333's description.

Trivial to recreate from git history if a future comparison is
needed.

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

* chore(ci): wire benchmark-comparison through composite action; link tracking issues

Two follow-ups from the PR #333 review:

1. The `benchmark-comparison` job in benchmark.yml still used inline
   `curl unix.sh | bash` for moon install — symmetrical with the
   `editor-response-benchmark` fix in a18a84d. Without the composite
   action it would run latest moon without NEW_MOON_MOD=0, hitting
   the rr_moon_mod migration cascade on `moon bench`. The base-ref
   step has continue-on-error so it wouldn't fail the job, but every
   future PR's comparison report would say "base branch benchmark
   failed — may not compile" until somebody noticed.

2. Reference issue #334 (deprecation-cleanup workstream) from the
   `--warn-list -20` comment in scripts/run-moon-module.sh, and
   issue #335 (workspace ignores per-member preferred-target) from
   both MOON_WORK=off sites (canvas E2E + benchmark). Stops the
   workarounds from rotting silently.

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

* chore(ci): route remaining 3 workflows through composite setup-moonbit

After the prior commits, ci.yml + benchmark.yml fully wired through
.github/actions/setup-moonbit (NEW_MOON_MOD=0 + hustcer@v1.22 pin) but
three workflows still installed via inline `curl unix.sh | bash`:

  - deploy-cloudflare.yml — Cloudflare Workers build (high risk:
    runs on push to main, would hit the rr_moon_mod migration cascade
    after this PR merges)
  - release.yml — release packaging on tag push (same risk)
  - copilot-setup-steps.yml — Copilot agent environment setup

All three swapped to `uses: ./.github/actions/setup-moonbit`. Net:
every moon install in this repo now goes through one composite with
one pin and one env var. Audit:

  $ grep -rn 'setup-moonbit\|cli.moonbitlang' .github/
  # 1 hustcer pin (the composite itself) + 17 composite invocations
  # 0 inline curl install commands

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

* ci: gate deploy + npm prebuild moon-build steps behind MOON_WORK=off

After examples/ideal, examples/canvas, and examples/block-editor became
moon.work members, `moon build --target js` inside those directories runs
in workspace mode and emits wasm-gc only — the JS bundle vite expects at
_build/js/release/build/main/main.js is never produced.

Phase 1 of this PR applied the workaround to test/bench paths
(scripts/test-canvas-e2e.sh, benchmark.yml's editor-response job). The
deploy and prebuild paths were missed, so Cloudflare deploys for those
three apps would fail on main with missing JS outputs and the local
`npm run build` workflow has the same regression.

Apply MOON_WORK=off to:
- deploy-cloudflare.yml matrix entries for ideal, block-editor, canvas
  (moon-update + moon-build commands)
- prebuild:moonbit npm scripts in each web/ subdir

Verified locally: without the gate, `moon build --target js --release`
in examples/canvas produces zero outputs; with the gate, main.js is at
the expected path. Tracked as #335 — remove once moon honors per-member
preferred-target.

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

* ci: gate ideal build-deploy.sh moon steps behind MOON_WORK=off

Follow-up to 106855e: that commit gated the deploy-cloudflare.yml matrix
entries and the prebuild:moonbit npm scripts, but missed the standalone
examples/ideal/scripts/build-deploy.sh which is the canonical local
deploy path. Once examples/ideal joined moon.work, `moon build --target js
--release` inside that directory runs in workspace mode and emits
wasm-gc only — the JS bundle vite expects is never produced, so this
script would silently produce a broken bundle for anyone running it
directly.

Apply MOON_WORK=off to both `moon update` and `moon build` invocations,
matching the pattern used in deploy-cloudflare.yml. Tracked as #335 —
remove once moon honors per-member preferred-target.

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

2 participants