@mnci/cli 1.9.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +165 -24
- package/dist/cli.js +338 -83
- package/dist/cli.js.map +1 -1
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -52,6 +52,11 @@ mnci add go-function-app fn # serverless handler -> apps/
|
|
|
52
52
|
mnci add go-lib core # publishable (by git tag) -> packages/
|
|
53
53
|
mnci add go-internal-lib util # private shared package -> libs/
|
|
54
54
|
|
|
55
|
+
# Flutter (@mnci/nx-flutter — one root pubspec.yaml pub workspace, analyze + test)
|
|
56
|
+
mnci add flutter-app hello # Flutter web app -> apps/ (bundle, zipped into the drop)
|
|
57
|
+
mnci add flutter-lib shared # publishable (by git tag) -> packages/
|
|
58
|
+
mnci add flutter-internal-lib core # private shared package -> libs/
|
|
59
|
+
|
|
55
60
|
mnci upgrade # re-apply the latest overlay (see below)
|
|
56
61
|
mnci upgrade --agent windows-latest # ...with an explicit override
|
|
57
62
|
```
|
|
@@ -70,6 +75,43 @@ each a single cross-platform command:
|
|
|
70
75
|
| `npm run python:install` | fixed Python toolchain (ruff/pytest/build/twine) + editable-install every Python project — the same two guards CI runs, for local dev |
|
|
71
76
|
| `prepare` | `husky` (commit-msg lint hook) |
|
|
72
77
|
|
|
78
|
+
## Every `add` also wires local-dev commands
|
|
79
|
+
|
|
80
|
+
Every `mnci add` (and the inline `internal-lib` case) finishes by calling
|
|
81
|
+
`registerProjectCommands` (`commands/add/shared.ts`), which writes up to three
|
|
82
|
+
root `package.json` scripts for the project just added:
|
|
83
|
+
|
|
84
|
+
| Script | Runs | When it's added |
|
|
85
|
+
| -------------- | ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
86
|
+
| `<name>:build` | `nx run <name>:build` | the kind has a `build` target (not every kind does — a private lib with nothing to publish, or a Python function app deployed as source, has none) |
|
|
87
|
+
| `<name>:qa` | `nx run <name>:lint && nx run <name>:test` | always — every kind has both |
|
|
88
|
+
| `<name>:start` | the kind's real local-dev command | only kinds with a genuine dev-server story — never a library |
|
|
89
|
+
|
|
90
|
+
The same three (when present) are appended as VS Code Tasks into the
|
|
91
|
+
workspace's `<workspace-name>.code-workspace` file, so they also show up
|
|
92
|
+
under **Terminal → Run Task** / the Command Palette — `build`/`qa` grouped
|
|
93
|
+
accordingly, `start` marked `isBackground` since it runs a process that
|
|
94
|
+
doesn't exit on its own. Re-running `add` for the same project name
|
|
95
|
+
overwrites its own scripts/tasks rather than duplicating them.
|
|
96
|
+
|
|
97
|
+
`:start` resolves differently per kind — an existing generator target where
|
|
98
|
+
one already exists, a small `nx:run-commands` target mnci writes where none
|
|
99
|
+
did:
|
|
100
|
+
|
|
101
|
+
| Kind(s) | `:start` runs |
|
|
102
|
+
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
|
|
103
|
+
| `react-app`, `node-app` | `nx run <name>:serve` — the generator's own inferred dev-server target |
|
|
104
|
+
| `node-function-app`, `python-function-app` | `nx run <name>:start` → `func start` (Azure Functions Core Tools, install separately — never a prerequisite for `add` itself) |
|
|
105
|
+
| `python-app` | `nx run <name>:start` → `python3 main.py` — mnci writes a runnable `main.py`, since the plugin's own sample module has no entry point |
|
|
106
|
+
| `go-app` | `nx run <name>:start` → `go run .` |
|
|
107
|
+
| `flutter-app` | `nx run <name>:start` → `flutter run -d chrome` (web is the only platform this plugin builds for) |
|
|
108
|
+
| every library, `go-function-app` | no `:start` at all — see below |
|
|
109
|
+
|
|
110
|
+
**`go-function-app` is a known gap, not an oversight**: unlike the Node and
|
|
111
|
+
Python function-app kinds, it writes no `host.json`/custom-handler config, so
|
|
112
|
+
there is nothing for `func start` to attach to. Shipping a `:start` script
|
|
113
|
+
that would just fail felt worse than being upfront that it doesn't exist yet.
|
|
114
|
+
|
|
73
115
|
## What `new` actually does
|
|
74
116
|
|
|
75
117
|
1. `npx create-nx-workspace@latest <name> --preset=ts` — npm workspaces +
|
|
@@ -85,9 +127,10 @@ each a single cross-platform command:
|
|
|
85
127
|
(`azure-pipelines.yml` and/or `.github/workflows/ci.yml`, `--ci`, default
|
|
86
128
|
`azure`; `github`/`both` also gets `.github/dependabot.yml` — weekly
|
|
87
129
|
dependency-update PRs), a `<workspace-name>.code-workspace` file (VS Code
|
|
88
|
-
workspace configuration with folder structure, ESLint/Prettier settings,
|
|
89
|
-
recommended extensions
|
|
90
|
-
|
|
130
|
+
workspace configuration with folder structure, ESLint/Prettier settings,
|
|
131
|
+
recommended extensions, and an empty `tasks` array that `mnci add` fills in
|
|
132
|
+
per project — see below — open it in VS Code via `File > Open Workspace
|
|
133
|
+
from File`), and the curated root scripts.
|
|
91
134
|
4. Installs the chosen **stack** (see below), `husky` + `@commitlint/*` for
|
|
92
135
|
real, so versions resolve at generation time.
|
|
93
136
|
|
|
@@ -162,15 +205,24 @@ no programmatic API yet; the two aliases are what make it work.)
|
|
|
162
205
|
|
|
163
206
|
## Layout convention = release scoping
|
|
164
207
|
|
|
165
|
-
| Directory | Contents
|
|
166
|
-
| ------------------ |
|
|
167
|
-
| `apps/` | React / Node / Python apps (plain or
|
|
168
|
-
| `packages/` | Publishable npm libraries
|
|
169
|
-
| `python-packages/` | Publishable Python packages (hatchling wheels)
|
|
170
|
-
| `libs/` | Internal libraries (TS or
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
208
|
+
| Directory | Contents | Released? |
|
|
209
|
+
| ------------------ | -------------------------------------------------------------- | -------------------------------------- |
|
|
210
|
+
| `apps/` | React / Node / Python / Go / Flutter apps (plain or Functions) | Never (packed into the drop) |
|
|
211
|
+
| `packages/` | Publishable npm libraries, plus Go and Dart packages | Yes — `nx release`, per-package tags |
|
|
212
|
+
| `python-packages/` | Publishable Python packages (hatchling wheels) | Yes — `twine upload` (Azure Artifacts) |
|
|
213
|
+
| `libs/` | Internal libraries (TS, Python, Go or Dart), never published | Never |
|
|
214
|
+
|
|
215
|
+
The directory is very nearly the whole model — one exception, and it is a bug
|
|
216
|
+
fix rather than a nicety. `go-lib` also lives in `packages/`, but a Go package
|
|
217
|
+
has **no per-project manifest** (mnci puts every Go project in one root
|
|
218
|
+
`go.mod`), so Nx's default `versionActions` looks for a `package.json` that is
|
|
219
|
+
not there and aborts _while building the release graph_ — killing `nx release`
|
|
220
|
+
for the whole workspace, not just the Go project. It is therefore excluded with
|
|
221
|
+
`!tag:type:go-lib`, which is also the semantically correct call: one module
|
|
222
|
+
means its packages have no independent versions to bump. A publishable **Dart**
|
|
223
|
+
package in `packages/` needs no such exclusion — `pubspec.yaml` has a real
|
|
224
|
+
`version:` field, and `@mnci/nx-flutter` stamps a `versionActions` override that
|
|
225
|
+
reads it. Publishable Python packages get their own
|
|
174
226
|
`python-packages/` dir so the npm `nx release` (`packages/*`) is never entangled
|
|
175
227
|
with Python publishing.
|
|
176
228
|
|
|
@@ -299,7 +351,7 @@ lint,test,build`. Pushes to `main` then:
|
|
|
299
351
|
separate explicit `git push origin --tags` step on this provider. `--ci=azure`
|
|
300
352
|
and `--ci=both` keep today's behaviour (no GitHub Release, explicit tag
|
|
301
353
|
push) — GitHub Release creation only turns on when GitHub Actions is the
|
|
302
|
-
|
|
354
|
+
_only_ configured provider, since that's the one case a `GITHUB_TOKEN` is
|
|
303
355
|
guaranteed to exist.
|
|
304
356
|
|
|
305
357
|
**npm auth** is the base64 `PAT`, read the same way on both providers but from
|
|
@@ -379,17 +431,31 @@ fix-ci`) — `mnci` does not automate that step.
|
|
|
379
431
|
Being upfront about what mnci leans on, so it's a conscious trade-off rather
|
|
380
432
|
than a surprise:
|
|
381
433
|
|
|
382
|
-
- **
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
434
|
+
- **Two Nx plugins this project builds and maintains** carry the most weight,
|
|
435
|
+
both for the same reason — the ecosystem has no maintained, Nx-23-compatible
|
|
436
|
+
option:
|
|
437
|
+
- **`@mnci/nx-python-pip`** (`packages/nx-python-pip`): no maintained plugin
|
|
438
|
+
supports pip. The obvious candidate, `@nxlv/python`, requires `uv`, which
|
|
439
|
+
the company standardizing on this tool does not use.
|
|
440
|
+
- **`@mnci/nx-flutter`** (`packages/nx-flutter`): `@nxrocks/nx-flutter`
|
|
441
|
+
cannot even load on Nx 23 — it imports
|
|
442
|
+
`@nx/workspace/src/utilities/fileutils`, removed in 23 — and there is no
|
|
443
|
+
alternative. Its exposure is smaller than the Python plugin's, because
|
|
444
|
+
scaffolding is delegated to the official `flutter create` rather than
|
|
445
|
+
hand-maintained templates; what this project owns is the pub-workspace
|
|
446
|
+
wiring, the targets and the release integration.
|
|
447
|
+
|
|
448
|
+
Both trade third-party risk for a different, real one: **this project owns
|
|
449
|
+
two extra packages' maintenance surface** (generators, executors, their own
|
|
450
|
+
release cycles). Unlike official `@nx/*` plugins, if either needs fixes, this
|
|
451
|
+
project owns them directly. That is the cost of the gaps in the ecosystem.
|
|
452
|
+
|
|
453
|
+
- **`@nx-go/nx-go` is a third-party plugin on a declared-incompatible range.**
|
|
454
|
+
It declares `@nx/devkit ">= 20 < 23"` while this workspace runs Nx 23. That
|
|
455
|
+
range is a plain dependency rather than a peer, so npm nests its own devkit
|
|
456
|
+
copy and everything works — validated empirically against a real Nx 23.1.0
|
|
457
|
+
workspace (generators, build, test, lint). It is still a version trap worth
|
|
458
|
+
re-checking on Nx upgrades.
|
|
393
459
|
- **The TS7 dual-compiler aliases pin a very new, fast-moving dependency.**
|
|
394
460
|
TypeScript 7's native compiler is recent; `TS_COMPILER_DEPENDENCIES` pins
|
|
395
461
|
`npm:typescript@^7.0.2` / `npm:@typescript/typescript6@^6.0.2` specifically
|
|
@@ -401,6 +467,15 @@ than a surprise:
|
|
|
401
467
|
## Known gaps (accepted for the experiment)
|
|
402
468
|
|
|
403
469
|
- No `doctor`/`resurrect`/`spell` — out of scope until the model is proven.
|
|
470
|
+
- **Flutter apps build for web only.** Android would require the Android SDK and
|
|
471
|
+
NDK on every build agent; iOS is impossible on a Linux agent regardless. Add
|
|
472
|
+
other platforms per-app with `flutter create --platforms=...` — the generated
|
|
473
|
+
`build` target only knows about web.
|
|
474
|
+
- **Go has no e2e coverage.** The `go-*` kinds have real unit tests and real CI
|
|
475
|
+
wiring, but the e2e suite never drives them, because it needs Go on the
|
|
476
|
+
machine. Flutter took the opposite approach — its e2e section runs when the
|
|
477
|
+
SDK is present and reports **SKIPPED** (loudly) when it is not — so the same
|
|
478
|
+
pattern could be applied to Go, but has not been.
|
|
404
479
|
- Azure Functions Core Tools is only needed for **local** `func start` — never
|
|
405
480
|
for `mnci add node-function-app`/`python-function-app` generation, since
|
|
406
481
|
neither shells out to the `func` CLI.
|
|
@@ -681,3 +756,69 @@ build` links statically, so the binary in the drop already contains
|
|
|
681
756
|
then added to `PATH` for later steps. All three skip cleanly when the
|
|
682
757
|
workspace has no root `go.mod`, and the linter install also skips when the
|
|
683
758
|
agent already provides it.
|
|
759
|
+
|
|
760
|
+
## Flutter (`@mnci/nx-flutter` — one root `pubspec.yaml` pub workspace)
|
|
761
|
+
|
|
762
|
+
Requires the **Flutter SDK** (3.27+, for Dart 3.6+ pub workspaces) on the
|
|
763
|
+
machine; `mnci add flutter-*` fails fast with an install link when `flutter` is
|
|
764
|
+
not on the `PATH`. Unlike Python and Go, the SDK is **not** present on hosted
|
|
765
|
+
build agents, so the generated pipeline installs it itself (see below).
|
|
766
|
+
|
|
767
|
+
| Kind | Location | Build / deploy |
|
|
768
|
+
| ---------------------- | ----------------- | ----------------------------------------------------------------------------------------------------- |
|
|
769
|
+
| `flutter-app` | `apps/<name>` | `flutter build web` bundle into `dist/apps/<name>/`, zipped into `dist/drop/flutter-app-<name>.zip` |
|
|
770
|
+
| `flutter-lib` | `packages/<name>` | publishable **by git tag** — see below; analyze + test targets only |
|
|
771
|
+
| `flutter-internal-lib` | `libs/<name>` | private shared code, analyze + test only — a Dart package is compiled into whatever app depends on it |
|
|
772
|
+
|
|
773
|
+
- **Dependencies are central, via a Dart pub workspace.** One root
|
|
774
|
+
`pubspec.yaml` lists every project under `workspace:`, and each project
|
|
775
|
+
carries `resolution: workspace`. A single `flutter pub get` at the root then
|
|
776
|
+
resolves the whole graph into **one** `pubspec.lock` and **one**
|
|
777
|
+
`.dart_tool/package_config.json` — pub actively deletes any per-package
|
|
778
|
+
copies. This is the Flutter half of the same root-manifest model as the root
|
|
779
|
+
`package.json` for TS, `requirements-dev.txt` for Python and `go.mod` for Go.
|
|
780
|
+
- **An internal library is consumed with a plain version constraint — no
|
|
781
|
+
`path:`.** `dependencies: { core: ^0.0.1 }` resolves to the local package
|
|
782
|
+
because it is a workspace member. That is also why Flutter needs **no
|
|
783
|
+
vendoring step**: contrast `mnci add python-vendor`, which exists only
|
|
784
|
+
because pip cannot bundle an unpublished sibling into a wheel. Flutter is in
|
|
785
|
+
the Go camp here — nothing to weave in at build time.
|
|
786
|
+
- **Lint configuration is central too.** The workspace root owns one
|
|
787
|
+
`analysis_options.yaml` (including `package:flutter_lints/flutter.yaml`), and
|
|
788
|
+
each project's own file is a one-line relative `include:` of it, so a rule
|
|
789
|
+
change lands in one place.
|
|
790
|
+
- **`flutter analyze --fatal-infos`, pinned explicitly.** `flutter analyze`
|
|
791
|
+
already defaults `--fatal-infos` on — verified against 3.44.8, where
|
|
792
|
+
`--no-fatal-infos` turns a failing lint run green. It is passed anyway
|
|
793
|
+
because that default is the only thing making this a real gate: nearly every
|
|
794
|
+
`flutter_lints` rule reports at _info_ severity. Worth knowing that plain
|
|
795
|
+
`dart analyze` defaults the opposite way (it fails on errors and warnings but
|
|
796
|
+
not infos), so swapping the command without carrying the flag across would
|
|
797
|
+
silently stop enforcing anything.
|
|
798
|
+
- **Publishing a `flutter-lib` is a git tag, not a registry upload.** Azure
|
|
799
|
+
Artifacts has no pub/Dart feed type, so a private pub registry is not
|
|
800
|
+
available on this stack, and these packages are deliberately not pushed to
|
|
801
|
+
pub.dev. `nx release` versions and tags them; no `nx-release-publish` target
|
|
802
|
+
is written.
|
|
803
|
+
- **The publishable lib carries a `versionActions` override, and it is
|
|
804
|
+
load-bearing.** Nx's default reads a `package.json`, which a Dart package
|
|
805
|
+
does not have. Without the override `nx release` aborts while building the
|
|
806
|
+
release graph — taking down the release of **every** project in the
|
|
807
|
+
workspace, not just the Dart one. The plugin's `library` generator stamps
|
|
808
|
+
`@mnci/nx-flutter/release/version-actions` on, which reads and writes
|
|
809
|
+
`pubspec.yaml`'s `version:`.
|
|
810
|
+
- **Apps build for web only.** Web needs nothing beyond the Flutter SDK,
|
|
811
|
+
whereas an Android build would drag the whole Android SDK and NDK onto every
|
|
812
|
+
build agent. Other platforms can be added per-app later with
|
|
813
|
+
`flutter create --platforms=...`.
|
|
814
|
+
- **CI** installs the SDK by shallow `git clone` at a pinned tag — Flutter's own
|
|
815
|
+
documented install method, and the only one uniform across agents (the
|
|
816
|
+
release archives differ by platform). It is cloned **outside** the workspace,
|
|
817
|
+
under the agent's home directory: the SDK ships dozens of its own
|
|
818
|
+
`pubspec.yaml` files, which inside the tree would pollute pub's resolution and
|
|
819
|
+
give Nx thousands of extra files to glob. The SDK version is **pinned**
|
|
820
|
+
(unlike `golangci-lint`'s `@latest`) because it determines the Dart version,
|
|
821
|
+
and pub workspaces need Dart 3.6+. Three guarded steps precede the build —
|
|
822
|
+
install, add to `PATH`, and one root `flutter pub get` — and all three skip
|
|
823
|
+
cleanly when the workspace has no root `pubspec.yaml`; the install also skips
|
|
824
|
+
when an SDK is already available.
|