Skip to content

Route entrypoint commands without running project code - #304

Open
cap10morgan wants to merge 13 commits into
masterfrom
lein-entrypoint-fallback
Open

cap10morgan wants to merge 13 commits into
masterfrom
lein-entrypoint-fallback

Conversation

@cap10morgan

Copy link
Copy Markdown
Collaborator

Fixes #301. Supersedes #302: this builds on @Quantisan's commits from there and adds the fallback discussed in #302 (comment).

The entrypoint no longer runs <build tool> <cmd> --help to decide where a command goes. That check could evaluate code from the mounted project before something like git log ran.

lein images, in order

  1. No arguments or a leading flag → lein
  2. Built-in task or alias (test, cp, repl, …) → lein, even if an executable has the same name
  3. Explicit path or executable on PATH (git, bash, ./run.sh) → runs directly, with no JVM and no project code
  4. Anything else (plugin tasks, project aliases) → lein, with a warning on stderr suggesting lein <task>

Step 4 keeps docker run … clojure:lein cljsbuild once and project aliases working as before. Those names only exist inside lein, so sending them there is what the user asked for.

tools-deps images

A leading flag goes to clj. So does a non-executable file that isn't on PATH, and it now runs once instead of twice. Everything else runs directly. An executable file named without ./ no longer goes to clj.

Known tradeoffs

  • A typo or a missing tool in a lein image goes to lein, which loads project.clj. The old --help probe did that too.
  • An alias or plugin task with the same name as an executable on PATH now runs the executable. Use lein <task> for those. The README covers this.
  • The built-in task list is pinned to Leiningen 2.13.0. The smoke test on CI image builds lists the installed jar's tasks and fails if any of them doesn't route straight to lein. That includes tasks that collide with an executable or that would hit the fallback warning.

Changes since #302

  • The lein fallback (step 4) and its warning
  • Smoke test: the image's real PATH, the exact jar path from $LEIN_VERSION, stdin from /dev/null, tolerance for task namespaces that fail to load, and the script read lazily
  • Unit tests for smoke-test-cmds and the fallback. Entrypoint tests now use the host PATH instead of /usr/bin:/bin
  • README fixes: JDK 16+ instead of 17+, and project mounts in the lein examples

Testing

  • bb run test and bb fmt-check pass.
  • I mounted the new entrypoint into the published clojure:temurin-25-lein image and checked:
    • the routing check passes against the real 2.13.0 jar
    • removing test and deps from the list makes the check fail
    • a project alias runs through the fallback with the warning
    • ls runs directly
    • version runs through lein

🤖 Generated with Claude Code

Quantisan and others added 13 commits November 3, 2026 10:33
Leiningen 2.11.0 added the static-classpath task, which the built-in
task list missed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The entrypoint hardcodes Leiningen's tasks and aliases. Lein images with
the entrypoint now list the tasks shipped in the Leiningen jar, plus its
aliases, and check the installed entrypoint passes each one to lein, so
a Leiningen upgrade that adds a task fails the image build. lein help is
not a usable source: it omits static-classpath.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Plugin tasks and project aliases such as `cljsbuild once` ran through lein
before #301 was fixed, so keep routing them there instead of failing with
"not found". Executables on PATH and explicit paths still run directly, so
commands like `git log` never load project code. The fallback prints a
warning pointing at explicit `lein` invocation.

Tools-deps images no longer pass executable files named without a slash to
clj.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Check routing with the image's PATH and fail on the fallback warning, so a
  stale built-in task list is caught whether the task collides with an
  executable or falls back.
- Use the exact Leiningen jar path and keep the entrypoint off the loop's
  stdin.
- Skip task namespaces that fail to load instead of aborting the listing.
- Read the check script when building smoke test commands, not at namespace
  load.
- Unit test smoke-test-cmds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cap10morgan
cap10morgan requested a review from Quantisan November 3, 2026 17:39
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.

Running git log in the container can execute Clojure project code

2 participants