@mnci/cli 4.10.7 → 4.11.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 CHANGED
@@ -1360,7 +1360,7 @@ pipeline installs `golangci-lint` itself (see below).
1360
1360
 
1361
1361
  | Kind | Location | Build / deploy |
1362
1362
  | ----------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1363
- | `go-app` | `apps/<name>` | `go build` binary into `dist/apps/<name>/`, zipped by mnci into `dist/drop/go-app-<name>.zip` |
1363
+ | `go-app` | `apps/<name>` | `go build` binary into `dist/apps/<name>/`, zipped by mnci into `dist/drop/go-app-<name>.zip`; `build-all` / `package-all` cross-compile six platforms into `dist/platforms/<name>/<goos>-<goarch>/` and zip each (`VERSION` env stamps `main.version`) |
1364
1364
  | `go-function-app` | `apps/<name>` | same build; zipped into `dist/drop/go-function-app-<name>.zip`. The handler body is yours to write — AWS Lambda, Google Cloud Functions and Azure each want a different signature, and mnci does not pick one |
1365
1365
  | `go-lib` | `packages/<name>` | publishable **by git tag** — see below; lint + test targets only |
1366
1366
  | `go-internal-lib` | `libs/<name>` | private shared code, lint + test only — a non-`main` package produces no binary |
@@ -1420,9 +1420,12 @@ build` links statically, so the binary in the drop already contains
1420
1420
  - **CI** runs Go through the same `nx run-many -t lint,test,build` as
1421
1421
  everything else. Two guarded steps precede it: `go mod download` (so a
1422
1422
  network failure reads as a dependency failure rather than a confusing
1423
- build error), and a `golangci-lint` install via `go install` — no package
1424
- manager, no sudo, same command on every agent OS — whose `GOPATH/bin` is
1425
- then added to `PATH` for later steps. All three skip cleanly when the
1423
+ build error), and a `golangci-lint` install whose `GOPATH/bin` is then added
1424
+ to `PATH` for later steps. The linter is **pinned** (`GOLANGCI_LINT_VERSION`)
1425
+ and installed from its prebuilt release, verified against the release's
1426
+ SHA-256 checksums, in about a second; compiling it with `go install` took
1427
+ over a minute per run. Any download or verification failure falls back to
1428
+ `go install` at the same pinned version. All three skip cleanly when the
1426
1429
  workspace has no root `go.mod`, and the linter install also skips when the
1427
1430
  agent already provides it.
1428
1431
 
@@ -1486,7 +1489,7 @@ build agents, so the generated pipeline installs it itself (see below).
1486
1489
  under the agent's home directory: the SDK ships dozens of its own
1487
1490
  `pubspec.yaml` files, which inside the tree would pollute pub's resolution and
1488
1491
  give Nx thousands of extra files to glob. The SDK version is **pinned**
1489
- (unlike `golangci-lint`'s `@latest`) because it determines the Dart version,
1492
+ (as is `golangci-lint`'s) because it determines the Dart version,
1490
1493
  and pub workspaces need Dart 3.6+. Three guarded steps precede the build —
1491
1494
  install, add to `PATH`, and one root `flutter pub get` — and all three skip
1492
1495
  cleanly when the workspace has no root `pubspec.yaml`; the install also skips
package/dist/cli.js CHANGED
@@ -1003,7 +1003,8 @@ var PYTHON_INSTALL_GUARD = `node -e "if(!require('node:fs').existsSync('requirem
1003
1003
  var PYTHON_WORKSPACE_INSTALL_GUARD = `node -e "const fs=require('node:fs'),path=require('node:path');const editableDirs=[...fs.globSync('apps/*/pyproject.toml'),...fs.globSync('python-packages/*/pyproject.toml'),...fs.globSync('libs/*/pyproject.toml')].map((p)=>path.dirname(p));const requirementsFiles=fs.globSync('apps/*/requirements.txt');if(editableDirs.length===0&&requirementsFiles.length===0){console.log('No Python projects - skipping.');process.exit(0)}const args=['-m','pip','install','--quiet',...editableDirs.flatMap((d)=>['-e',d]),...requirementsFiles.flatMap((f)=>['-r',f])];const py=process.platform==='win32'?'python':'python3';process.exit(require('node:child_process').spawnSync(py,args,{stdio:'inherit'}).status ?? 1)"`;
1004
1004
  var PIP_AUDIT_GUARD = `node -e "if(!require('node:fs').existsSync('requirements-dev.txt')){console.log('No Python projects - skipping.');process.exit(0)}const py=process.platform==='win32'?'python':'python3';require('node:child_process').spawnSync(py,['-m','pip_audit'],{stdio:'inherit'});process.exit(0)"`;
1005
1005
  var GO_MODULE_DOWNLOAD_GUARD = `node -e "if(!require('node:fs').existsSync('go.mod')){console.log('No Go projects - skipping.');process.exit(0)}process.exit(require('node:child_process').spawnSync('go',['mod','download'],{stdio:'inherit'}).status ?? 1)"`;
1006
- var GOLANGCI_LINT_INSTALL_GUARD = `node -e "const fs=require('node:fs'),cp=require('node:child_process');if(!fs.existsSync('go.mod')){console.log('No Go projects - skipping.');process.exit(0)}if(cp.spawnSync('golangci-lint',['--version'],{stdio:'ignore'}).status===0){console.log('golangci-lint already installed - skipping.');process.exit(0)}process.exit(cp.spawnSync('go',['install','github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest'],{stdio:'inherit'}).status ?? 1)"`;
1006
+ var GOLANGCI_LINT_VERSION = "2.14.0";
1007
+ var GOLANGCI_LINT_INSTALL_GUARD = `node -e "const fs=require('node:fs'),cp=require('node:child_process'),path=require('node:path'),os=require('node:os'),crypto=require('node:crypto');if(!fs.existsSync('go.mod')){console.log('No Go projects - skipping.');process.exit(0)}if(cp.spawnSync('golangci-lint',['--version'],{stdio:'ignore'}).status===0){console.log('golangci-lint already installed - skipping.');process.exit(0)}const v='${GOLANGCI_LINT_VERSION}';const fallback=reason=>{console.log('Prebuilt golangci-lint '+v+' unavailable ('+reason+') - building it with go install instead.');process.exit(cp.spawnSync('go',['install','github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v'+v],{stdio:'inherit'}).status ?? 1)};const plat={linux:'linux',darwin:'darwin',win32:'windows'}[process.platform],arch={x64:'amd64',arm64:'arm64'}[process.arch];if(!plat||!arch)fallback('no prebuilt release for '+process.platform+'/'+process.arch);const gopath=cp.spawnSync('go',['env','GOPATH'],{encoding:'utf8'});if(gopath.status!==0)fallback('go env GOPATH failed');const name='golangci-lint-'+v+'-'+plat+'-'+arch,file=name+(plat==='windows'?'.zip':'.tar.gz'),base='https://github.com/golangci/golangci-lint/releases/download/v'+v+'/';const get=async u=>{const r=await fetch(u,{signal:AbortSignal.timeout(60000)});if(!r.ok)throw new Error('HTTP '+r.status+' for '+u);return Buffer.from(await r.arrayBuffer())};(async()=>{` + String.raw`const sums=(await get(base+'golangci-lint-'+v+'-checksums.txt')).toString('utf8').split('\n').map(l=>l.trim().split(' ').filter(Boolean));` + `const entry=sums.find(p=>p[1]===file);if(!entry)throw new Error(file+' is not in the release checksums');const archive=await get(base+file);if(crypto.createHash('sha256').update(archive).digest('hex')!==entry[0])throw new Error('checksum mismatch for '+file);const tmp=fs.mkdtempSync(path.join(os.tmpdir(),'golangci-lint-')),archivePath=path.join(tmp,file);fs.writeFileSync(archivePath,archive);const tar=plat==='windows'?path.join(process.env.SystemRoot||'','System32','tar.exe'):'tar';const x=cp.spawnSync(tar,['-xf',archivePath,'-C',tmp],{stdio:'inherit'});if(x.status!==0)throw new Error('could not extract '+file);const exe='golangci-lint'+(plat==='windows'?'.exe':''),bin=path.join(gopath.stdout.trim(),'bin');fs.mkdirSync(bin,{recursive:true});fs.copyFileSync(path.join(tmp,name,exe),path.join(bin,exe));fs.chmodSync(path.join(bin,exe),0o755);fs.rmSync(tmp,{recursive:true,force:true});console.log('golangci-lint '+v+' installed from its checksum-verified prebuilt release into '+bin)})().catch(error=>fallback(error.message))"`;
1007
1008
  var GO_TOOL_PATH_PRELUDE = "const fs=require('node:fs'),cp=require('node:child_process');if(!fs.existsSync('go.mod')){console.log('No Go projects - skipping.');process.exit(0)}const r=cp.spawnSync('go',['env','GOPATH'],{encoding:'utf8'});if(r.status!==0){console.log('Could not resolve GOPATH - skipping.');process.exit(0)}const bin=require('node:path').join(r.stdout.trim(),'bin');";
1008
1009
  var GO_TOOL_PATH_AZURE = `node -e "${GO_TOOL_PATH_PRELUDE}console.log('##vso[task.prependpath]'+bin)"`;
1009
1010
  var GO_TOOL_PATH_GITHUB = `node -e "${GO_TOOL_PATH_PRELUDE}if(!process.env.GITHUB_PATH){console.log('Not running in GitHub Actions - skipping.');process.exit(0)}fs.appendFileSync(process.env.GITHUB_PATH,bin+${String.raw`'\n'`})"`;
@@ -1238,8 +1239,9 @@ ${npmAuthenticateStep} - script: npm ci
1238
1239
  displayName: Download Go module dependencies
1239
1240
 
1240
1241
  # golangci-lint is what the generated Go lint target actually runs (the
1241
- # plugin's own default is 'go fmt', which only reformats). 'go install'
1242
- # drops it in GOPATH/bin, which is not on PATH by default on a hosted
1242
+ # plugin's own default is 'go fmt', which only reformats). The pinned,
1243
+ # checksum-verified prebuilt release lands in GOPATH/bin (go install at the
1244
+ # same version is the fallback), which is not on PATH by default on a hosted
1243
1245
  # agent \u2014 so prepend it for every later step in the job.
1244
1246
  - script: ${GOLANGCI_LINT_INSTALL_GUARD}
1245
1247
  displayName: Install golangci-lint
@@ -1493,9 +1495,10 @@ jobs:
1493
1495
  name: Download Go module dependencies
1494
1496
 
1495
1497
  # golangci-lint is what the generated Go lint target actually runs (the
1496
- # plugin's own default is 'go fmt', which only reformats). 'go install'
1497
- # drops it in GOPATH/bin, which is not on PATH by default on a hosted
1498
- # runner \u2014 so publish it for every later step in the job.
1498
+ # plugin's own default is 'go fmt', which only reformats). The pinned,
1499
+ # checksum-verified prebuilt release lands in GOPATH/bin (go install at the
1500
+ # same version is the fallback), which is not on PATH by default on a
1501
+ # hosted runner \u2014 so publish it for every later step in the job.
1499
1502
  - run: ${GOLANGCI_LINT_INSTALL_GUARD}
1500
1503
  name: Install golangci-lint
1501
1504
 
@@ -2633,6 +2636,63 @@ function goPackageTarget(tag, name) {
2633
2636
  options: { command }
2634
2637
  };
2635
2638
  }
2639
+ var GO_PLATFORMS = [
2640
+ "windows/amd64",
2641
+ "windows/arm64",
2642
+ "linux/amd64",
2643
+ "linux/arm64",
2644
+ "darwin/amd64",
2645
+ "darwin/arm64"
2646
+ ];
2647
+ function goBuildAllTarget(name) {
2648
+ const platforms = JSON.stringify(GO_PLATFORMS).replaceAll('"', "'");
2649
+ const command = `node -e "const{spawnSync}=require('node:child_process');const v=process.env.VERSION||'dev';for(const p of ${platforms}){const[os,arch]=p.split('/');const out='../../dist/platforms/${name}/'+os+'-'+arch+'/${name}'+(os==='windows'?'.exe':'');const r=spawnSync('go',['build','-trimpath','-ldflags','-s -w -X main.version='+v,'-o',out,'.'],{cwd:'apps/${name}',stdio:'inherit',env:{...process.env,CGO_ENABLED:'0',GOOS:os,GOARCH:arch}});if(r.status!==0)process.exit(r.status??1)}"`;
2650
+ return {
2651
+ executor: "nx:run-commands",
2652
+ inputs: ["default", "^default", "{workspaceRoot}/go.mod", "{workspaceRoot}/go.sum", { env: "VERSION" }],
2653
+ outputs: [`{workspaceRoot}/dist/platforms/${name}`],
2654
+ options: { command }
2655
+ };
2656
+ }
2657
+ function goPackageAllTarget(tag, name) {
2658
+ const command = `node -e "const fs=require('node:fs');const A=require('adm-zip');fs.mkdirSync('dist/drop',{recursive:true});for(const d of fs.readdirSync('dist/platforms/${name}')){const z=new A();z.addLocalFolder('dist/platforms/${name}/'+d);z.writeZip('dist/drop/${tag}-${name}-'+d+'.zip')}"`;
2659
+ return {
2660
+ executor: "nx:run-commands",
2661
+ dependsOn: ["build-all"],
2662
+ outputs: [`{workspaceRoot}/dist/drop/${tag}-${name}-*.zip`],
2663
+ options: { command }
2664
+ };
2665
+ }
2666
+ function addGoPlatformTargets(workspaceRoot) {
2667
+ const changed = [];
2668
+ const apps = (0, import_node_path6.join)(workspaceRoot, "apps");
2669
+ if (!fileExists(apps)) {
2670
+ return changed;
2671
+ }
2672
+ for (const name of (0, import_node_fs5.readdirSync)(apps)) {
2673
+ const projectJsonPath = (0, import_node_path6.join)(apps, name, "project.json");
2674
+ if (!fileExists(projectJsonPath)) {
2675
+ continue;
2676
+ }
2677
+ const project = JSON.parse((0, import_node_fs5.readFileSync)(projectJsonPath, "utf8"));
2678
+ const tag = (project.tags ?? []).find((each) => each === "type:go-app" || each === "type:go-function-app")?.slice("type:".length);
2679
+ if (tag === void 0) {
2680
+ continue;
2681
+ }
2682
+ const missing = {};
2683
+ if (project.targets?.["build-all"] === void 0) {
2684
+ missing["build-all"] = goBuildAllTarget(name);
2685
+ }
2686
+ if (project.targets?.["package-all"] === void 0) {
2687
+ missing["package-all"] = goPackageAllTarget(tag, name);
2688
+ }
2689
+ if (Object.keys(missing).length > 0) {
2690
+ addProjectJsonTargets(projectJsonPath, missing);
2691
+ changed.push(`apps/${name}/project.json`);
2692
+ }
2693
+ }
2694
+ return changed;
2695
+ }
2636
2696
  function goStartTarget(name) {
2637
2697
  return {
2638
2698
  executor: "nx:run-commands",
@@ -2720,11 +2780,13 @@ function addGoApp(workspaceRoot, name) {
2720
2780
  workspaceRoot
2721
2781
  );
2722
2782
  addProjectJsonTargets((0, import_node_path6.join)(workspaceRoot, "apps", name, "project.json"), {
2723
- build: goBuildTarget(name),
2724
- test: goTestTarget(),
2725
- lint: goLintTarget(),
2726
- package: goPackageTarget("go-app", name),
2727
- start: goStartTarget(name)
2783
+ "build": goBuildTarget(name),
2784
+ "test": goTestTarget(),
2785
+ "lint": goLintTarget(),
2786
+ "package": goPackageTarget("go-app", name),
2787
+ "build-all": goBuildAllTarget(name),
2788
+ "package-all": goPackageAllTarget("go-app", name),
2789
+ "start": goStartTarget(name)
2728
2790
  });
2729
2791
  registerProjectCommands(workspaceRoot, name, { build: true, start: `nx run ${name}:start` });
2730
2792
  }
@@ -2743,10 +2805,12 @@ function addGoFunctionApp(workspaceRoot, name) {
2743
2805
  workspaceRoot
2744
2806
  );
2745
2807
  addProjectJsonTargets((0, import_node_path6.join)(workspaceRoot, "apps", name, "project.json"), {
2746
- build: goBuildTarget(name),
2747
- test: goTestTarget(),
2748
- lint: goLintTarget(),
2749
- package: goPackageTarget("go-function-app", name)
2808
+ "build": goBuildTarget(name),
2809
+ "test": goTestTarget(),
2810
+ "lint": goLintTarget(),
2811
+ "package": goPackageTarget("go-function-app", name),
2812
+ "build-all": goBuildAllTarget(name),
2813
+ "package-all": goPackageAllTarget("go-function-app", name)
2750
2814
  });
2751
2815
  registerProjectCommands(workspaceRoot, name, { build: true });
2752
2816
  }
@@ -5659,6 +5723,13 @@ function runUpgrade(workspaceRoot, options) {
5659
5723
  logger.detail(`updated ${path}`);
5660
5724
  }
5661
5725
  }
5726
+ const goApps = addGoPlatformTargets(workspaceRoot);
5727
+ if (goApps.length > 0) {
5728
+ logger.step("Adding the six-platform build to Go apps (build-all, package-all)");
5729
+ for (const path of goApps) {
5730
+ logger.detail(`updated ${path}`);
5731
+ }
5732
+ }
5662
5733
  const upgradedDtsPlugins = upgradeDeclarationSpecifierPlugins(workspaceRoot);
5663
5734
  if (upgradedDtsPlugins.length > 0) {
5664
5735
  logger.step("Upgrading declaration specifiers to resolve under nodenext");