Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## [v0.5.4] - 2026-09-25

### Changed

- **The web app template runs on `@pipelex/sdk` 0.25.1**: the SDK no longer offers the Pipelex Gateway key calls (`createGatewayApiKey`, `getGatewayApiKey`), which neither the template nor any action the scaffold writes ever made, so nothing changes for a project. The app keeps calling the hosted API with a Pipelex API key, which this release leaves untouched.

### Fixed

- **`create-method-app` at a path another repository ignores**: a destination inside another repository's work tree that the repository ignores, such as a `tmp/` its `.gitignore` lists or anywhere under a home directory kept as a repository that ignores `*`, now gets a repository of its own on `main` with the pristine commit, and the `git:` line names the repository that ignores it. The initializer used to report such a project as new files in the enclosing repository and make no repository, which left it under no version control at all; a project made that way earlier can be given one with `git init` and a first commit. A directory the repository does not ignore still gets no repository even when every file in it is ignored, as under `*` followed by `!*/`, and the `git:` line now says the project is under no version control instead of calling it new files of that repository. A destination that is a symlink is judged by the repository its target is in, not the one the link sits in.

## [v0.5.3] - 2026-09-24

### Changed
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.5.3
0.5.4
2 changes: 1 addition & 1 deletion docs/family.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ make -C my-app serve

**Each initializer's table of templates is `templates.json` at its root**, which says which templates it serves, the extras each one's `make create` takes, and the command of the other ecosystem's initializer, named when a person asks one for the other's template (`refused: other-ecosystem`). JSON, so the root reads every initializer's table whatever its language: `scripts/initializers.test.mjs` fails when a template of `TEMPLATES` is served by no initializer or by more than one, and when a table's variables are not the `make create` contract's.

**`initializers/cases.json` is the table of cases every initializer executes**: destinations (missing, empty, a lone `.git` with and without history, a lone `.git` with a staged file and no commit, a `.DS_Store`, a file of the user's, spelled `.`, a name with a space), git states (none, inside another work tree, inside a template's checkout, `--no-git`), flags, and the verdict each must print. The npm initializer's suite runs it now, and the Python one will, so the two print the same verdicts for the same situations.
**`initializers/cases.json` is the table of cases every initializer executes**: destinations (missing, empty, a lone `.git` with and without history, a lone `.git` with a staged file and no commit, a `.DS_Store`, a file of the user's, spelled `.`, a name with a space), git states (none, inside another work tree, under a path that work tree ignores or re-includes, in one that ignores every file but no directory, inside a template's checkout, an identity only the enclosing repository holds, `--no-git`), flags, and the verdict each must print. The npm initializer's suite runs it now, and the Python one will, so the two print the same verdicts for the same situations.

## The version and the release

Expand Down
79 changes: 76 additions & 3 deletions initializers/cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
"legend": {
"destination": "What stands at the destination before the run. missing: nothing; empty: an empty directory; git-without-commit: a directory holding only the .git of git init; git-with-history: a directory holding only the .git of a repository with a commit, its files deleted; git-with-staged-file: a directory holding only the .git of git init whose index holds notes.txt, added and then deleted from the directory; ds-store: a directory holding .DS_Store; user-file: a directory holding notes.txt; beneath-a-file: the destination is typed as notes.txt/my-app, notes.txt being a file, so nothing can stand there.",
"spelled": "How the destination is typed. name: my-app, from its parent; space: my app, from its parent; dot: ., from inside it (the destination must exist); absent: no directory at all.",
"within": "Where the destination's parent is. nothing: a directory no repository tracks; work-tree: inside the work tree of a repository with a commit and an origin of its own; template-checkout: inside the work tree of a repository whose origin is https://github.com/Pipelex/pipelex-method-apps.git.",
"within": "Where the destination's parent is. nothing: a directory no repository tracks; work-tree: inside the work tree of a repository with a commit and an origin of its own; template-checkout: inside the work tree of a repository whose origin is https://github.com/Pipelex/pipelex-method-apps.git; ignored-parent: under the tmp/ directory of a repository as in work-tree, whose committed .gitignore holds tmp/; ignored-by-name: at the root of a repository as in work-tree, whose committed .gitignore holds the directory-only pattern my-app/, which matches the destination only when it is read as a directory; re-included: under the apps/ directory of a repository as in work-tree, whose committed .gitignore holds apps/* and then !apps/my-app/, so that the destination itself is not ignored when it is read as a directory; ignores-everything: at the root of a repository as in work-tree, whose committed .gitignore holds *, as a home directory kept as a repository often does; ignores-files-only: at the root of a repository as in work-tree, whose committed .gitignore holds * and then !*/, which ignores every file but no directory; contents-ignored: at the root of a repository as in work-tree, whose committed .gitignore holds my-app/* and then !my-app/package.json, which ignores what the destination holds but not the destination itself.",
"args": "The arguments after the destination. {other-ecosystem} stands for a template the other ecosystem's initializer serves.",
"method": "Whether --method mt_case is passed. Defaults to true.",
"key": "Whether PIPELEX_API_KEY is set. Defaults to true.",
"tools": "Which of make and git are on the PATH. Defaults to both.",
"git_identity": "Whether git has an identity to commit with. true: in its global configuration; false: none, and git refuses to guess one; under-parent: only through an includeIf \"gitdir:<the destination's parent>/\" section, git refusing to guess one elsewhere. Defaults to true.",
"git_identity": "Whether git has an identity to commit with. true: in its global configuration; false: none, and git refuses to guess one; under-parent: only through an includeIf \"gitdir:<the destination's parent>/\" section, git refusing to guess one elsewhere; enclosing-only: only in the enclosing repository's own .git/config, git refusing to guess one elsewhere. Defaults to true.",
"make_exit": "The stub make's exit status. Defaults to 0.",
"expect.verdict": "The verdict: the last line's first word, or its first two for refused: and failed:.",
"expect.written": "Whether the template was written. When false, the destination holds exactly what it held before the run.",
"expect.git": "initialized: the destination is a repository on main with one commit, the pristine one; first-commit: the repository that was there has one commit, the pristine one; none: the destination holds no .git, and the enclosing repository's HEAD did not move; untouched: the repository that was there did not change.",
"expect.git": "initialized: the destination is a repository on main with one commit, the pristine one, and an enclosing repository's HEAD did not move and its git status --porcelain --untracked-files=all prints nothing; first-commit: the repository that was there has one commit, the pristine one; none: the destination holds no .git, and the enclosing repository's HEAD did not move; untouched: the repository that was there did not change.",
"expect.make": "Whether make ran.",
"expect.forwarded": "Arguments make's argument vector must contain."
},
Expand Down Expand Up @@ -104,6 +104,79 @@
"git_identity": false,
"expect": { "verdict": "created", "written": true, "git": "none", "make": true }
},
{
"name": "under a path the enclosing repository ignores, the project gets a repository of its own",
"destination": "missing",
"within": "ignored-parent",
"expect": { "verdict": "created", "written": true, "git": "initialized", "make": true }
},
{
"name": "an empty directory under an ignored path",
"destination": "empty",
"within": "ignored-parent",
"expect": { "verdict": "created", "written": true, "git": "initialized", "make": true }
},
{
"name": "a destination a directory-only pattern ignores is read as a directory before it exists",
"destination": "missing",
"within": "ignored-by-name",
"expect": { "verdict": "created", "written": true, "git": "initialized", "make": true }
},
{
"name": "an ignored destination spelled .",
"destination": "empty",
"within": "ignored-by-name",
"spelled": "dot",
"expect": { "verdict": "created", "written": true, "git": "initialized", "make": true }
},
{
"name": "a destination the enclosing repository re-includes is new files in that repository",
"destination": "missing",
"within": "re-included",
"expect": { "verdict": "created", "written": true, "git": "none", "make": true }
},
{
"name": "a repository that ignores everything gives the project a repository of its own",
"destination": "missing",
"within": "ignores-everything",
"expect": { "verdict": "created", "written": true, "git": "initialized", "make": true }
},
{
"name": "a directory whose files alone are ignored gets no repository before it exists",
"destination": "missing",
"within": "ignores-files-only",
"expect": { "verdict": "created", "written": true, "git": "none", "make": true }
},
{
"name": "an empty directory whose files alone are ignored gets no repository",
"destination": "empty",
"within": "ignores-files-only",
"expect": { "verdict": "created", "written": true, "git": "none", "make": true }
},
{
"name": "a destination whose contents alone are ignored gets no repository before it exists",
"destination": "missing",
"within": "contents-ignored",
"expect": { "verdict": "created", "written": true, "git": "none", "make": true }
},
{
"name": "an empty destination whose contents alone are ignored gets no repository",
"destination": "empty",
"within": "contents-ignored",
"expect": { "verdict": "created", "written": true, "git": "none", "make": true }
},
{
"name": "under an ignored path, an identity only the enclosing repository holds is not the new repository's",
"destination": "missing",
"within": "ignored-parent",
"git_identity": "enclosing-only",
"expect": {
"verdict": "refused: no-git-identity",
"written": false,
"git": "none",
"make": false
}
},
{
"name": "a template's own checkout is refused",
"destination": "missing",
Expand Down
5 changes: 4 additions & 1 deletion initializers/js/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,13 @@ The initializer reads git before it writes anything:
| A repository with no commit yet (a `git init` by hand, or a clone of an empty GitHub repository) | The pristine commit, as its first |
| A repository with no commit whose index already holds a file, added and then deleted | Refused: the commit would record that file beside the template |
| A repository with commits, holding only `.git` | Refused: every tracked file would show as deleted, and the commit would record that |
| Inside another repository's work tree, at a path it ignores | A new repository on `main`, then the pristine commit: that repository does not see the project |
| Inside another repository's work tree | No repository and no commit: the project is new files in that repository. `--no-create` lets you commit the template there first |
| Inside a checkout of `pipelex-method-apps` or of a starter | Refused, `--no-git` included whenever git is on the PATH |

A commit needs a git identity, and a missing one is refused before anything is written. When git shows none outside a repository, the initializer asks again inside a throwaway repository at the destination, which it removes before going on, so an identity given only by an `includeIf "gitdir:…"` section is found.
A path the enclosing repository ignores, such as a `tmp/` its `.gitignore` lists or anywhere under a home directory kept as a repository that ignores `*`, is one it does not version, so a project there gets a repository of its own rather than no version control at all. Every source git reads counts: the enclosing repository's `.gitignore` files, its `.git/info/exclude`, and your `core.excludesFile`. What counts is the directory itself, which a missing destination is made for a moment to let git read: a directory the enclosing repository does not ignore gets no repository even when every file in it is ignored, as under `*` followed by `!*/`, since a repository there would still show in the enclosing one's `git status`, and the `git:` line then says the project is under no version control. A destination that is a symlink is read where it points: the repository whose work tree holds its target is the one whose ignores count.

A commit needs a git identity, and a missing one is refused before anything is written. When git shows none outside a repository, the initializer asks again inside a throwaway repository at the destination, which it removes before going on, so an identity given only by an `includeIf "gitdir:…"` section is found. At a path another repository ignores, it always asks inside that throwaway repository, since an identity set in the enclosing repository's own configuration does not reach the new one.

The pristine commit reads `Start from Pipelex/pipelex-method-apps/webapp-js <version> (<sha>)`, so `make create`'s changes are a diff you can read before committing them. `make create` itself commits nothing.

Expand Down
Loading
Loading