hereya-cli 0.104.0 → 0.105.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
@@ -21,7 +21,7 @@ $ npm install -g hereya-cli
21
21
  $ hereya COMMAND
22
22
  running command...
23
23
  $ hereya (--version)
24
- hereya-cli/0.104.0 linux-x64 node-v24.18.0
24
+ hereya-cli/0.105.0 linux-x64 node-v24.18.0
25
25
  $ hereya --help [COMMAND]
26
26
  USAGE
27
27
  $ hereya COMMAND
@@ -131,7 +131,7 @@ EXAMPLES
131
131
  $ hereya add cloudy/docker_postgres
132
132
  ```
133
133
 
134
- _See code: [src/commands/add/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/add/index.ts)_
134
+ _See code: [src/commands/add/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/add/index.ts)_
135
135
 
136
136
  ## `hereya app deploy NAME`
137
137
 
@@ -165,7 +165,7 @@ EXAMPLES
165
165
  $ hereya app deploy my-org/my-app -w prod -p organizationId=org-123
166
166
  ```
167
167
 
168
- _See code: [src/commands/app/deploy/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/app/deploy/index.ts)_
168
+ _See code: [src/commands/app/deploy/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/app/deploy/index.ts)_
169
169
 
170
170
  ## `hereya app deployments NAME`
171
171
 
@@ -185,7 +185,7 @@ EXAMPLES
185
185
  $ hereya app deployments my-org/my-app
186
186
  ```
187
187
 
188
- _See code: [src/commands/app/deployments/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/app/deployments/index.ts)_
188
+ _See code: [src/commands/app/deployments/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/app/deployments/index.ts)_
189
189
 
190
190
  ## `hereya app destroy NAME`
191
191
 
@@ -214,7 +214,7 @@ EXAMPLES
214
214
  $ hereya app destroy my-org/my-app -w my-workspace
215
215
  ```
216
216
 
217
- _See code: [src/commands/app/destroy/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/app/destroy/index.ts)_
217
+ _See code: [src/commands/app/destroy/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/app/destroy/index.ts)_
218
218
 
219
219
  ## `hereya app env NAME [KEY]`
220
220
 
@@ -240,7 +240,7 @@ EXAMPLES
240
240
  $ hereya app env my-org/my-app -w my-workspace DATABASE_URL
241
241
  ```
242
242
 
243
- _See code: [src/commands/app/env/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/app/env/index.ts)_
243
+ _See code: [src/commands/app/env/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/app/env/index.ts)_
244
244
 
245
245
  ## `hereya app list`
246
246
 
@@ -257,7 +257,7 @@ EXAMPLES
257
257
  $ hereya app list
258
258
  ```
259
259
 
260
- _See code: [src/commands/app/list/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/app/list/index.ts)_
260
+ _See code: [src/commands/app/list/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/app/list/index.ts)_
261
261
 
262
262
  ## `hereya app new DIRNAME`
263
263
 
@@ -283,7 +283,7 @@ EXAMPLES
283
283
  $ hereya app new ./my-app -n my-org/my-app --description "An ai-app-builder app"
284
284
  ```
285
285
 
286
- _See code: [src/commands/app/new/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/app/new/index.ts)_
286
+ _See code: [src/commands/app/new/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/app/new/index.ts)_
287
287
 
288
288
  ## `hereya app status NAME`
289
289
 
@@ -306,7 +306,7 @@ EXAMPLES
306
306
  $ hereya app status my-org/my-app -w my-workspace
307
307
  ```
308
308
 
309
- _See code: [src/commands/app/status/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/app/status/index.ts)_
309
+ _See code: [src/commands/app/status/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/app/status/index.ts)_
310
310
 
311
311
  ## `hereya bootstrap INFRASTRUCTURETYPE`
312
312
 
@@ -331,7 +331,7 @@ EXAMPLES
331
331
  $ hereya bootstrap local
332
332
  ```
333
333
 
334
- _See code: [src/commands/bootstrap/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/bootstrap/index.ts)_
334
+ _See code: [src/commands/bootstrap/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/bootstrap/index.ts)_
335
335
 
336
336
  ## `hereya clone PROJECT`
337
337
 
@@ -356,7 +356,7 @@ EXAMPLES
356
356
  $ hereya clone myProject --chdir=./myProject
357
357
  ```
358
358
 
359
- _See code: [src/commands/clone/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/clone/index.ts)_
359
+ _See code: [src/commands/clone/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/clone/index.ts)_
360
360
 
361
361
  ## `hereya config export-backend [FILE]`
362
362
 
@@ -378,7 +378,7 @@ EXAMPLES
378
378
  $ hereya config export-backend ./path/to/export.json
379
379
  ```
380
380
 
381
- _See code: [src/commands/config/export-backend/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/config/export-backend/index.ts)_
381
+ _See code: [src/commands/config/export-backend/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/config/export-backend/index.ts)_
382
382
 
383
383
  ## `hereya config get-backend`
384
384
 
@@ -395,7 +395,7 @@ EXAMPLES
395
395
  $ hereya config get-backend
396
396
  ```
397
397
 
398
- _See code: [src/commands/config/get-backend/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/config/get-backend/index.ts)_
398
+ _See code: [src/commands/config/get-backend/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/config/get-backend/index.ts)_
399
399
 
400
400
  ## `hereya config import-backend FILE`
401
401
 
@@ -415,7 +415,7 @@ EXAMPLES
415
415
  $ hereya config import-backend ./path/to/cloud-backend.json
416
416
  ```
417
417
 
418
- _See code: [src/commands/config/import-backend/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/config/import-backend/index.ts)_
418
+ _See code: [src/commands/config/import-backend/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/config/import-backend/index.ts)_
419
419
 
420
420
  ## `hereya config use-backend TYPE`
421
421
 
@@ -437,7 +437,7 @@ EXAMPLES
437
437
  $ hereya config use-backend local
438
438
  ```
439
439
 
440
- _See code: [src/commands/config/use-backend/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/config/use-backend/index.ts)_
440
+ _See code: [src/commands/config/use-backend/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/config/use-backend/index.ts)_
441
441
 
442
442
  ## `hereya delete-state`
443
443
 
@@ -463,7 +463,7 @@ EXAMPLES
463
463
  $ hereya delete-state --workspace staging
464
464
  ```
465
465
 
466
- _See code: [src/commands/delete-state/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/delete-state/index.ts)_
466
+ _See code: [src/commands/delete-state/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/delete-state/index.ts)_
467
467
 
468
468
  ## `hereya deploy`
469
469
 
@@ -489,7 +489,7 @@ EXAMPLES
489
489
  $ hereya deploy
490
490
  ```
491
491
 
492
- _See code: [src/commands/deploy/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/deploy/index.ts)_
492
+ _See code: [src/commands/deploy/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/deploy/index.ts)_
493
493
 
494
494
  ## `hereya devenv config`
495
495
 
@@ -510,7 +510,7 @@ EXAMPLES
510
510
  $ hereya devenv config -w my-workspace
511
511
  ```
512
512
 
513
- _See code: [src/commands/devenv/config/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/devenv/config/index.ts)_
513
+ _See code: [src/commands/devenv/config/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/devenv/config/index.ts)_
514
514
 
515
515
  ## `hereya devenv install`
516
516
 
@@ -537,7 +537,7 @@ EXAMPLES
537
537
  $ hereya devenv install -w my-workspace -p instanceType=t3.large
538
538
  ```
539
539
 
540
- _See code: [src/commands/devenv/install/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/devenv/install/index.ts)_
540
+ _See code: [src/commands/devenv/install/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/devenv/install/index.ts)_
541
541
 
542
542
  ## `hereya devenv project init PROJECT`
543
543
 
@@ -569,7 +569,7 @@ EXAMPLES
569
569
  $ hereya devenv project init my-app -w my-workspace -t acme/node-starter -p region=us-east-1
570
570
  ```
571
571
 
572
- _See code: [src/commands/devenv/project/init/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/devenv/project/init/index.ts)_
572
+ _See code: [src/commands/devenv/project/init/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/devenv/project/init/index.ts)_
573
573
 
574
574
  ## `hereya devenv project uninit PROJECT`
575
575
 
@@ -595,7 +595,7 @@ EXAMPLES
595
595
  $ hereya devenv project uninit my-app -w my-workspace --force
596
596
  ```
597
597
 
598
- _See code: [src/commands/devenv/project/uninit/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/devenv/project/uninit/index.ts)_
598
+ _See code: [src/commands/devenv/project/uninit/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/devenv/project/uninit/index.ts)_
599
599
 
600
600
  ## `hereya devenv sleep`
601
601
 
@@ -616,7 +616,7 @@ EXAMPLES
616
616
  $ hereya devenv sleep -w my-workspace
617
617
  ```
618
618
 
619
- _See code: [src/commands/devenv/sleep/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/devenv/sleep/index.ts)_
619
+ _See code: [src/commands/devenv/sleep/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/devenv/sleep/index.ts)_
620
620
 
621
621
  ## `hereya devenv ssh`
622
622
 
@@ -636,7 +636,7 @@ EXAMPLES
636
636
  $ hereya devenv ssh -w my-workspace
637
637
  ```
638
638
 
639
- _See code: [src/commands/devenv/ssh/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/devenv/ssh/index.ts)_
639
+ _See code: [src/commands/devenv/ssh/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/devenv/ssh/index.ts)_
640
640
 
641
641
  ## `hereya devenv uninstall`
642
642
 
@@ -657,7 +657,7 @@ EXAMPLES
657
657
  $ hereya devenv uninstall -w my-workspace
658
658
  ```
659
659
 
660
- _See code: [src/commands/devenv/uninstall/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/devenv/uninstall/index.ts)_
660
+ _See code: [src/commands/devenv/uninstall/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/devenv/uninstall/index.ts)_
661
661
 
662
662
  ## `hereya doc PACKAGE`
663
663
 
@@ -690,7 +690,7 @@ EXAMPLES
690
690
  $ hereya doc my-package --no-doc
691
691
  ```
692
692
 
693
- _See code: [src/commands/doc/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/doc/index.ts)_
693
+ _See code: [src/commands/doc/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/doc/index.ts)_
694
694
 
695
695
  ## `hereya docker run IMAGE`
696
696
 
@@ -721,7 +721,7 @@ EXAMPLES
721
721
  $ hereya docker run myapp:latest -- --rm -v ./data:/data
722
722
  ```
723
723
 
724
- _See code: [src/commands/docker/run/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/docker/run/index.ts)_
724
+ _See code: [src/commands/docker/run/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/docker/run/index.ts)_
725
725
 
726
726
  ## `hereya down`
727
727
 
@@ -748,7 +748,7 @@ EXAMPLES
748
748
  $ hereya down
749
749
  ```
750
750
 
751
- _See code: [src/commands/down/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/down/index.ts)_
751
+ _See code: [src/commands/down/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/down/index.ts)_
752
752
 
753
753
  ## `hereya env [NAME]`
754
754
 
@@ -779,7 +779,7 @@ EXAMPLES
779
779
  $ hereya env -w dev -l
780
780
  ```
781
781
 
782
- _See code: [src/commands/env/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/env/index.ts)_
782
+ _See code: [src/commands/env/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/env/index.ts)_
783
783
 
784
784
  ## `hereya env set [NAME]`
785
785
 
@@ -806,7 +806,7 @@ EXAMPLES
806
806
  $ hereya env set FOO -v bar -w dev
807
807
  ```
808
808
 
809
- _See code: [src/commands/env/set/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/env/set/index.ts)_
809
+ _See code: [src/commands/env/set/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/env/set/index.ts)_
810
810
 
811
811
  ## `hereya executor start`
812
812
 
@@ -840,7 +840,7 @@ EXAMPLES
840
840
  HEREYA_TOKEN=<token> HEREYA_CLOUD_URL=https://my-cloud.example.com hereya executor start -w my-workspace
841
841
  ```
842
842
 
843
- _See code: [src/commands/executor/start/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/executor/start/index.ts)_
843
+ _See code: [src/commands/executor/start/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/executor/start/index.ts)_
844
844
 
845
845
  ## `hereya flow add PACKAGE`
846
846
 
@@ -878,7 +878,7 @@ EXAMPLES
878
878
  $ hereya flow add cloudy/docker_postgres -p DB_NAME=mydb -p DB_USER=admin
879
879
  ```
880
880
 
881
- _See code: [src/commands/flow/add/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/flow/add/index.ts)_
881
+ _See code: [src/commands/flow/add/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/flow/add/index.ts)_
882
882
 
883
883
  ## `hereya flow docker run IMAGE`
884
884
 
@@ -908,7 +908,7 @@ EXAMPLES
908
908
  $ hereya flow docker run --pin myapp:latest -- --rm
909
909
  ```
910
910
 
911
- _See code: [src/commands/flow/docker/run/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/flow/docker/run/index.ts)_
911
+ _See code: [src/commands/flow/docker/run/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/flow/docker/run/index.ts)_
912
912
 
913
913
  ## `hereya flow down`
914
914
 
@@ -942,7 +942,7 @@ EXAMPLES
942
942
  $ hereya flow down --pin
943
943
  ```
944
944
 
945
- _See code: [src/commands/flow/down/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/flow/down/index.ts)_
945
+ _See code: [src/commands/flow/down/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/flow/down/index.ts)_
946
946
 
947
947
  ## `hereya flow env [NAME]`
948
948
 
@@ -976,7 +976,7 @@ EXAMPLES
976
976
  $ hereya flow env -l
977
977
  ```
978
978
 
979
- _See code: [src/commands/flow/env/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/flow/env/index.ts)_
979
+ _See code: [src/commands/flow/env/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/flow/env/index.ts)_
980
980
 
981
981
  ## `hereya flow provid PACKAGE`
982
982
 
@@ -1005,7 +1005,7 @@ EXAMPLES
1005
1005
  $ hereya flow provid hereya/postgres --pin
1006
1006
  ```
1007
1007
 
1008
- _See code: [src/commands/flow/provid/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/flow/provid/index.ts)_
1008
+ _See code: [src/commands/flow/provid/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/flow/provid/index.ts)_
1009
1009
 
1010
1010
  ## `hereya flow remove PACKAGE`
1011
1011
 
@@ -1035,7 +1035,7 @@ EXAMPLES
1035
1035
  $ hereya flow remove cloudy/docker_postgres --profile staging
1036
1036
  ```
1037
1037
 
1038
- _See code: [src/commands/flow/remove/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/flow/remove/index.ts)_
1038
+ _See code: [src/commands/flow/remove/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/flow/remove/index.ts)_
1039
1039
 
1040
1040
  ## `hereya flow run CMD`
1041
1041
 
@@ -1064,7 +1064,7 @@ EXAMPLES
1064
1064
  $ hereya flow run --pin -- npm test
1065
1065
  ```
1066
1066
 
1067
- _See code: [src/commands/flow/run/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/flow/run/index.ts)_
1067
+ _See code: [src/commands/flow/run/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/flow/run/index.ts)_
1068
1068
 
1069
1069
  ## `hereya flow up`
1070
1070
 
@@ -1098,7 +1098,7 @@ EXAMPLES
1098
1098
  $ hereya flow up --pin
1099
1099
  ```
1100
1100
 
1101
- _See code: [src/commands/flow/up/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/flow/up/index.ts)_
1101
+ _See code: [src/commands/flow/up/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/flow/up/index.ts)_
1102
1102
 
1103
1103
  ## `hereya help [COMMAND]`
1104
1104
 
@@ -1155,7 +1155,7 @@ EXAMPLES
1155
1155
  $ hereya import org/my-package -f state.tfstate -w my-workspace
1156
1156
  ```
1157
1157
 
1158
- _See code: [src/commands/import/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/import/index.ts)_
1158
+ _See code: [src/commands/import/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/import/index.ts)_
1159
1159
 
1160
1160
  ## `hereya import-repo PROJECT`
1161
1161
 
@@ -1185,7 +1185,7 @@ EXAMPLES
1185
1185
  $ hereya import-repo myProject -w=dev -r=https://github.com/acme/api --clone --chdir=./api
1186
1186
  ```
1187
1187
 
1188
- _See code: [src/commands/import-repo/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/import-repo/index.ts)_
1188
+ _See code: [src/commands/import-repo/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/import-repo/index.ts)_
1189
1189
 
1190
1190
  ## `hereya init PROJECT`
1191
1191
 
@@ -1219,7 +1219,7 @@ EXAMPLES
1219
1219
  $ hereya init myProject -w=dev -t=acme/node-starter -d=prod -p region=us-east-1
1220
1220
  ```
1221
1221
 
1222
- _See code: [src/commands/init/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/init/index.ts)_
1222
+ _See code: [src/commands/init/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/init/index.ts)_
1223
1223
 
1224
1224
  ## `hereya job cancel JOBID`
1225
1225
 
@@ -1247,7 +1247,7 @@ EXAMPLES
1247
1247
  $ hereya job cancel my-job-id -w my-workspace --force
1248
1248
  ```
1249
1249
 
1250
- _See code: [src/commands/job/cancel/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/job/cancel/index.ts)_
1250
+ _See code: [src/commands/job/cancel/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/job/cancel/index.ts)_
1251
1251
 
1252
1252
  ## `hereya job list`
1253
1253
 
@@ -1273,7 +1273,7 @@ EXAMPLES
1273
1273
  $ hereya job list -w my-workspace --status pending --limit 10
1274
1274
  ```
1275
1275
 
1276
- _See code: [src/commands/job/list/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/job/list/index.ts)_
1276
+ _See code: [src/commands/job/list/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/job/list/index.ts)_
1277
1277
 
1278
1278
  ## `hereya list`
1279
1279
 
@@ -1290,7 +1290,7 @@ EXAMPLES
1290
1290
  $ hereya list
1291
1291
  ```
1292
1292
 
1293
- _See code: [src/commands/list/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/list/index.ts)_
1293
+ _See code: [src/commands/list/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/list/index.ts)_
1294
1294
 
1295
1295
  ## `hereya login [URL]`
1296
1296
 
@@ -1319,7 +1319,7 @@ EXAMPLES
1319
1319
  $ hereya login --token=your-token https://cloud.hereya.dev
1320
1320
  ```
1321
1321
 
1322
- _See code: [src/commands/login/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/login/index.ts)_
1322
+ _See code: [src/commands/login/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/login/index.ts)_
1323
1323
 
1324
1324
  ## `hereya logout`
1325
1325
 
@@ -1336,7 +1336,7 @@ EXAMPLES
1336
1336
  $ hereya logout
1337
1337
  ```
1338
1338
 
1339
- _See code: [src/commands/logout/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/logout/index.ts)_
1339
+ _See code: [src/commands/logout/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/logout/index.ts)_
1340
1340
 
1341
1341
  ## `hereya provid PACKAGE`
1342
1342
 
@@ -1364,7 +1364,7 @@ EXAMPLES
1364
1364
  $ hereya provid hereya/postgres --workspace staging
1365
1365
  ```
1366
1366
 
1367
- _See code: [src/commands/provid/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/provid/index.ts)_
1367
+ _See code: [src/commands/provid/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/provid/index.ts)_
1368
1368
 
1369
1369
  ## `hereya publish`
1370
1370
 
@@ -1387,7 +1387,7 @@ EXAMPLES
1387
1387
  $ hereya publish --chdir=/path/to/package
1388
1388
  ```
1389
1389
 
1390
- _See code: [src/commands/publish/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/publish/index.ts)_
1390
+ _See code: [src/commands/publish/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/publish/index.ts)_
1391
1391
 
1392
1392
  ## `hereya remove PACKAGE`
1393
1393
 
@@ -1415,7 +1415,7 @@ EXAMPLES
1415
1415
  $ hereya remove cloudy/docker_postgres
1416
1416
  ```
1417
1417
 
1418
- _See code: [src/commands/remove/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/remove/index.ts)_
1418
+ _See code: [src/commands/remove/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/remove/index.ts)_
1419
1419
 
1420
1420
  ## `hereya run CMD`
1421
1421
 
@@ -1441,7 +1441,7 @@ EXAMPLES
1441
1441
  $ hereya run -w uat -- node index.js
1442
1442
  ```
1443
1443
 
1444
- _See code: [src/commands/run/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/run/index.ts)_
1444
+ _See code: [src/commands/run/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/run/index.ts)_
1445
1445
 
1446
1446
  ## `hereya search QUERY`
1447
1447
 
@@ -1472,7 +1472,7 @@ EXAMPLES
1472
1472
  $ hereya search database --json
1473
1473
  ```
1474
1474
 
1475
- _See code: [src/commands/search/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/search/index.ts)_
1475
+ _See code: [src/commands/search/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/search/index.ts)_
1476
1476
 
1477
1477
  ## `hereya unbootstrap INFRASTRUCTURETYPE`
1478
1478
 
@@ -1497,7 +1497,7 @@ EXAMPLES
1497
1497
  $ hereya unbootstrap local
1498
1498
  ```
1499
1499
 
1500
- _See code: [src/commands/unbootstrap/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/unbootstrap/index.ts)_
1500
+ _See code: [src/commands/unbootstrap/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/unbootstrap/index.ts)_
1501
1501
 
1502
1502
  ## `hereya undeploy`
1503
1503
 
@@ -1523,7 +1523,7 @@ EXAMPLES
1523
1523
  $ hereya undeploy
1524
1524
  ```
1525
1525
 
1526
- _See code: [src/commands/undeploy/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/undeploy/index.ts)_
1526
+ _See code: [src/commands/undeploy/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/undeploy/index.ts)_
1527
1527
 
1528
1528
  ## `hereya uninit PROJECT`
1529
1529
 
@@ -1551,7 +1551,7 @@ EXAMPLES
1551
1551
  $ hereya uninit myProject -w dev -p prodWorkspace=prod
1552
1552
  ```
1553
1553
 
1554
- _See code: [src/commands/uninit/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/uninit/index.ts)_
1554
+ _See code: [src/commands/uninit/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/uninit/index.ts)_
1555
1555
 
1556
1556
  ## `hereya up`
1557
1557
 
@@ -1578,7 +1578,7 @@ EXAMPLES
1578
1578
  $ hereya up
1579
1579
  ```
1580
1580
 
1581
- _See code: [src/commands/up/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/up/index.ts)_
1581
+ _See code: [src/commands/up/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/up/index.ts)_
1582
1582
 
1583
1583
  ## `hereya update [VERSION]`
1584
1584
 
@@ -1600,7 +1600,7 @@ EXAMPLES
1600
1600
  $ hereya update 0.75.0
1601
1601
  ```
1602
1602
 
1603
- _See code: [src/commands/update/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/update/index.ts)_
1603
+ _See code: [src/commands/update/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/update/index.ts)_
1604
1604
 
1605
1605
  ## `hereya workspace create NAME`
1606
1606
 
@@ -1625,7 +1625,7 @@ EXAMPLES
1625
1625
  $ hereya workspace create dev
1626
1626
  ```
1627
1627
 
1628
- _See code: [src/commands/workspace/create/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/workspace/create/index.ts)_
1628
+ _See code: [src/commands/workspace/create/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/workspace/create/index.ts)_
1629
1629
 
1630
1630
  ## `hereya workspace delete NAME`
1631
1631
 
@@ -1645,7 +1645,7 @@ EXAMPLES
1645
1645
  $ hereya workspace delete dev
1646
1646
  ```
1647
1647
 
1648
- _See code: [src/commands/workspace/delete/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/workspace/delete/index.ts)_
1648
+ _See code: [src/commands/workspace/delete/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/workspace/delete/index.ts)_
1649
1649
 
1650
1650
  ## `hereya workspace env [NAME]`
1651
1651
 
@@ -1671,7 +1671,7 @@ EXAMPLES
1671
1671
  $ hereya workspace env myEnv -w dev
1672
1672
  ```
1673
1673
 
1674
- _See code: [src/commands/workspace/env/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/workspace/env/index.ts)_
1674
+ _See code: [src/commands/workspace/env/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/workspace/env/index.ts)_
1675
1675
 
1676
1676
  ## `hereya workspace env set`
1677
1677
 
@@ -1695,7 +1695,7 @@ EXAMPLES
1695
1695
  $ hereya workspace env set -w my-workspace -n myVar -v my-value -i aws -s
1696
1696
  ```
1697
1697
 
1698
- _See code: [src/commands/workspace/env/set/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/workspace/env/set/index.ts)_
1698
+ _See code: [src/commands/workspace/env/set/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/workspace/env/set/index.ts)_
1699
1699
 
1700
1700
  ## `hereya workspace env unset`
1701
1701
 
@@ -1716,7 +1716,7 @@ EXAMPLES
1716
1716
  $ hereya workspace env unset -w my-workspace -n myVar
1717
1717
  ```
1718
1718
 
1719
- _See code: [src/commands/workspace/env/unset/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/workspace/env/unset/index.ts)_
1719
+ _See code: [src/commands/workspace/env/unset/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/workspace/env/unset/index.ts)_
1720
1720
 
1721
1721
  ## `hereya workspace executor install`
1722
1722
 
@@ -1745,7 +1745,7 @@ DESCRIPTION
1745
1745
  - always-on: a long-lived EC2 polls hereya-cloud 24/7 (legacy).
1746
1746
  ```
1747
1747
 
1748
- _See code: [src/commands/workspace/executor/install/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/workspace/executor/install/index.ts)_
1748
+ _See code: [src/commands/workspace/executor/install/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/workspace/executor/install/index.ts)_
1749
1749
 
1750
1750
  ## `hereya workspace executor token`
1751
1751
 
@@ -1762,7 +1762,7 @@ DESCRIPTION
1762
1762
  Generate a workspace-scoped executor token for the remote executor
1763
1763
  ```
1764
1764
 
1765
- _See code: [src/commands/workspace/executor/token/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/workspace/executor/token/index.ts)_
1765
+ _See code: [src/commands/workspace/executor/token/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/workspace/executor/token/index.ts)_
1766
1766
 
1767
1767
  ## `hereya workspace executor uninstall`
1768
1768
 
@@ -1786,7 +1786,7 @@ DESCRIPTION
1786
1786
  controls log output.
1787
1787
  ```
1788
1788
 
1789
- _See code: [src/commands/workspace/executor/uninstall/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/workspace/executor/uninstall/index.ts)_
1789
+ _See code: [src/commands/workspace/executor/uninstall/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/workspace/executor/uninstall/index.ts)_
1790
1790
 
1791
1791
  ## `hereya workspace install PACKAGE`
1792
1792
 
@@ -1813,7 +1813,7 @@ EXAMPLES
1813
1813
  $ hereya workspace install hereya/aws-cognito
1814
1814
  ```
1815
1815
 
1816
- _See code: [src/commands/workspace/install/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/workspace/install/index.ts)_
1816
+ _See code: [src/commands/workspace/install/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/workspace/install/index.ts)_
1817
1817
 
1818
1818
  ## `hereya workspace list`
1819
1819
 
@@ -1837,7 +1837,7 @@ EXAMPLES
1837
1837
  $ hereya workspace list --org personal
1838
1838
  ```
1839
1839
 
1840
- _See code: [src/commands/workspace/list/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/workspace/list/index.ts)_
1840
+ _See code: [src/commands/workspace/list/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/workspace/list/index.ts)_
1841
1841
 
1842
1842
  ## `hereya workspace set-profile PROFILE`
1843
1843
 
@@ -1861,7 +1861,7 @@ EXAMPLES
1861
1861
  $ hereya workspace set-profile prod-profile -w production
1862
1862
  ```
1863
1863
 
1864
- _See code: [src/commands/workspace/set-profile/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/workspace/set-profile/index.ts)_
1864
+ _See code: [src/commands/workspace/set-profile/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/workspace/set-profile/index.ts)_
1865
1865
 
1866
1866
  ## `hereya workspace uninstall PACKAGE`
1867
1867
 
@@ -1888,5 +1888,5 @@ EXAMPLES
1888
1888
  $ hereya workspace uninstall hereya/aws-cognito
1889
1889
  ```
1890
1890
 
1891
- _See code: [src/commands/workspace/uninstall/index.ts](https://github.com/hereya/hereya-cli/blob/v0.104.0/src/commands/workspace/uninstall/index.ts)_
1891
+ _See code: [src/commands/workspace/uninstall/index.ts](https://github.com/hereya/hereya-cli/blob/v0.105.0/src/commands/workspace/uninstall/index.ts)_
1892
1892
  <!-- commandsstop -->
@@ -9,6 +9,7 @@ import { executeAppJob } from '../../../lib/executor-start/execute-app-job.js';
9
9
  import { executeInitJob } from '../../../lib/executor-start/execute-init-job.js';
10
10
  import { createExecutorHooks } from '../../../lib/executor-start/hooks.js';
11
11
  import { dispatchJob } from '../../../lib/executor-start/job-dispatch.js';
12
+ import { KeyedMutex } from '../../../lib/executor-start/job-serialization.js';
12
13
  export { redactCredentials } from '../../../lib/executor-start/format.js';
13
14
  export default class ExecutorStart extends Command {
14
15
  static description = `Start the remote executor process (polls for jobs from hereya cloud).
@@ -71,6 +72,9 @@ Set the HEREYA_CLOUD_URL environment variable to target a specific hereya cloud
71
72
  process.on('SIGINT', shutdown);
72
73
  process.on('SIGTERM', shutdown);
73
74
  const activeJobs = new Set();
75
+ // One shared mutex per executor process: jobs targeting the same
76
+ // (target, workspace) run serially, unrelated jobs stay concurrent.
77
+ const serialization = new KeyedMutex();
74
78
  // Ephemeral mode = an idle-timeout is configured (the EC2/ASG executor).
75
79
  // There, a job that hits the execution timeout triggers a delayed
76
80
  // non-zero exit so systemd replaces the wedged instance; in non-ephemeral
@@ -107,6 +111,7 @@ Set the HEREYA_CLOUD_URL environment variable to target a specific hereya cloud
107
111
  lastJobAt,
108
112
  lastSuccessfulPollAt,
109
113
  maxConsecutive401s: MAX_CONSECUTIVE_401S,
114
+ serialization,
110
115
  workspace: flags.workspace,
111
116
  });
112
117
  consecutive401s = step.consecutive401s;
@@ -165,7 +170,7 @@ Set the HEREYA_CLOUD_URL environment variable to target a specific hereya cloud
165
170
  return { exit: false };
166
171
  }
167
172
  async runPollIteration(args) {
168
- const { activeJobs, cloudBackend, cloudUrl, concurrency, executor, executorId, hereyaToken, hooks, idleTimeout, maxConsecutive401s, workspace, } = args;
173
+ const { activeJobs, cloudBackend, cloudUrl, concurrency, executor, executorId, hereyaToken, hooks, idleTimeout, maxConsecutive401s, serialization, workspace, } = args;
169
174
  let { consecutive401s, lastJobAt, lastSuccessfulPollAt } = args;
170
175
  if (activeJobs.size > 0) {
171
176
  lastJobAt = Date.now();
@@ -201,7 +206,7 @@ Set the HEREYA_CLOUD_URL environment variable to target a specific hereya cloud
201
206
  const { job } = pollResult;
202
207
  this.log(`Received job ${job.id} (${job.type}) [${activeJobs.size + 1}/${concurrency} slots used]`);
203
208
  lastJobAt = Date.now();
204
- const jobPromise = dispatchJob(job, executor, cloudBackend, hooks).finally(() => {
209
+ const jobPromise = dispatchJob(job, executor, cloudBackend, hooks, serialization).finally(() => {
205
210
  activeJobs.delete(jobPromise);
206
211
  });
207
212
  activeJobs.add(jobPromise);
@@ -4,6 +4,15 @@
4
4
  * the same sanitization.
5
5
  */
6
6
  export declare function sanitizeWorkspaceForFilename(workspace: string): string;
7
+ /**
8
+ * Builds a verbose error description for server-side job logs. If the thrown
9
+ * error is a `ShellCommandError` (or anything carrying `.stderr`/`.stdout`),
10
+ * include the full buffers so operators can see the complete failure context.
11
+ */
12
+ export declare function formatJobError(error: unknown): {
13
+ fullErr: string;
14
+ reason: string;
15
+ };
7
16
  /**
8
17
  * Strip credentials from log strings before flushing them to the cloud.
9
18
  * Removes:
@@ -6,6 +6,30 @@
6
6
  export function sanitizeWorkspaceForFilename(workspace) {
7
7
  return workspace.replaceAll('/', '-');
8
8
  }
9
+ /**
10
+ * Builds a verbose error description for server-side job logs. If the thrown
11
+ * error is a `ShellCommandError` (or anything carrying `.stderr`/`.stdout`),
12
+ * include the full buffers so operators can see the complete failure context.
13
+ */
14
+ export function formatJobError(error) {
15
+ const reason = error && typeof error === 'object' && 'message' in error && typeof error.message === 'string'
16
+ ? error.message
17
+ : String(error);
18
+ const stderrBuffer = error && typeof error === 'object' && typeof error.stderr === 'string'
19
+ ? error.stderr
20
+ : '';
21
+ const stdoutBuffer = error && typeof error === 'object' && typeof error.stdout === 'string'
22
+ ? error.stdout
23
+ : '';
24
+ let extra = '';
25
+ if (stderrBuffer.trim()) {
26
+ extra = `\n--- stderr ---\n${stderrBuffer}`;
27
+ }
28
+ else if (stdoutBuffer.trim()) {
29
+ extra = `\n--- stdout ---\n${stdoutBuffer}`;
30
+ }
31
+ return { fullErr: reason + extra, reason };
32
+ }
9
33
  /**
10
34
  * Strip credentials from log strings before flushing them to the cloud.
11
35
  * Removes:
@@ -1,5 +1,6 @@
1
1
  import { CloudBackend } from '../../backend/cloud/cloud-backend.js';
2
2
  import { LocalExecutor } from '../../executor/local.js';
3
+ import { KeyedMutex } from './job-serialization.js';
3
4
  export interface JobDispatchHooks {
4
5
  log(msg: string): void;
5
6
  /**
@@ -15,9 +16,13 @@ export interface JobDispatchHooks {
15
16
  * and heartbeating to the cloud. Errors are caught and reported as failed
16
17
  * jobs. Execution is raced against a per-job timeout so a hung child can
17
18
  * never hold its slot indefinitely.
19
+ *
20
+ * `serialization` must be the executor-process-wide KeyedMutex: jobs that
21
+ * mutate the same logical (target, workspace) run serially on it, everything
22
+ * else stays concurrent. See job-serialization.ts.
18
23
  */
19
24
  export declare function dispatchJob(job: {
20
25
  id: string;
21
26
  payload: any;
22
27
  type: string;
23
- }, executor: LocalExecutor, cloudBackend: CloudBackend, hooks: JobDispatchHooks): Promise<void>;
28
+ }, executor: LocalExecutor, cloudBackend: CloudBackend, hooks: JobDispatchHooks, serialization: KeyedMutex): Promise<void>;
@@ -1,54 +1,21 @@
1
1
  import { executeAppJob } from './execute-app-job.js';
2
2
  import { executeDeployJob } from './execute-deploy-job.js';
3
3
  import { executeInitJob } from './execute-init-job.js';
4
- const DEFAULT_EXECUTOR_JOB_TIMEOUT_MIN = 60;
5
- /**
6
- * Per-job execution timeout in minutes. Overridable via
7
- * HEREYA_EXECUTOR_JOB_TIMEOUT_MIN (positive number, in minutes).
8
- * A wedged child process (e.g. a tool blocking on a prompt) must not hold
9
- * its executor slot forever while the heartbeat keeps the job "alive".
10
- */
11
- function executorJobTimeoutMin() {
12
- const fromEnv = process.env.HEREYA_EXECUTOR_JOB_TIMEOUT_MIN;
13
- if (fromEnv !== undefined) {
14
- const parsed = Number(fromEnv);
15
- if (Number.isFinite(parsed) && parsed > 0) {
16
- return parsed;
17
- }
18
- }
19
- return DEFAULT_EXECUTOR_JOB_TIMEOUT_MIN;
20
- }
21
- /**
22
- * Builds a verbose error description for server-side job logs. If the thrown
23
- * error is a `ShellCommandError` (or anything carrying `.stderr`/`.stdout`),
24
- * include the full buffers so operators can see the complete failure context.
25
- */
26
- function formatJobError(error) {
27
- const reason = error && typeof error === 'object' && 'message' in error && typeof error.message === 'string'
28
- ? error.message
29
- : String(error);
30
- const stderrBuffer = error && typeof error === 'object' && typeof error.stderr === 'string'
31
- ? error.stderr
32
- : '';
33
- const stdoutBuffer = error && typeof error === 'object' && typeof error.stdout === 'string'
34
- ? error.stdout
35
- : '';
36
- let extra = '';
37
- if (stderrBuffer.trim()) {
38
- extra = `\n--- stderr ---\n${stderrBuffer}`;
39
- }
40
- else if (stdoutBuffer.trim()) {
41
- extra = `\n--- stdout ---\n${stdoutBuffer}`;
42
- }
43
- return { fullErr: reason + extra, reason };
44
- }
4
+ import { formatJobError } from './format.js';
5
+ import { deriveJobSerializationKey } from './job-serialization.js';
6
+ import { executorJobTimeoutMin } from './job-timeout.js';
45
7
  /**
46
8
  * Dispatches a single job to the right handler, with periodic log flushing
47
9
  * and heartbeating to the cloud. Errors are caught and reported as failed
48
10
  * jobs. Execution is raced against a per-job timeout so a hung child can
49
11
  * never hold its slot indefinitely.
12
+ *
13
+ * `serialization` must be the executor-process-wide KeyedMutex: jobs that
14
+ * mutate the same logical (target, workspace) run serially on it, everything
15
+ * else stays concurrent. See job-serialization.ts.
50
16
  */
51
- export async function dispatchJob(job, executor, cloudBackend, hooks) {
17
+ // eslint-disable-next-line max-params -- explicit DI of the process-wide mutex beats hidden module state
18
+ export async function dispatchJob(job, executor, cloudBackend, hooks, serialization) {
52
19
  let logBuffer = '';
53
20
  const logInterval = setInterval(async () => {
54
21
  if (logBuffer) {
@@ -125,13 +92,35 @@ export async function dispatchJob(job, executor, cloudBackend, hooks) {
125
92
  : await executor.destroy({ ...job.payload, logger });
126
93
  await finalize(result, '');
127
94
  };
95
+ // Jobs mutating the same logical (target, workspace) — e.g. a resubmitted
96
+ // duplicate of a deploy that looked stuck — must run serially: concurrent
97
+ // runs race over the same cloned repo dirs, local hereya state and tofu/CDK
98
+ // state. The wait happens INSIDE the job lifecycle, AFTER the log/heartbeat
99
+ // intervals started above, so a queued job keeps heartbeating — otherwise
100
+ // the server-side stale reaper would reset it and this same executor would
101
+ // claim it again. The per-job execution timeout below INTENTIONALLY covers
102
+ // queue-wait + execution: a job stuck behind a wedged predecessor is failed
103
+ // and retried rather than waiting forever.
104
+ const serializationKey = deriveJobSerializationKey(job);
105
+ const executeSerialized = async () => {
106
+ if (serialization.isBusy(serializationKey)) {
107
+ logger.info(`Waiting for an in-flight job on the same target (${serializationKey}) to finish before starting...`);
108
+ }
109
+ await serialization.run(serializationKey, async () => {
110
+ // A job that timed out while queued must not ghost-execute after its
111
+ // predecessor finally drains — its row is already failed.
112
+ if (timedOut)
113
+ return;
114
+ await execute();
115
+ });
116
+ };
128
117
  try {
129
118
  const timeoutPromise = new Promise((resolve) => {
130
119
  timeoutTimer = setTimeout(() => resolve('timeout'), timeoutMin * 60 * 1000);
131
120
  // Belt-and-braces: a pending job timer must never keep the process alive.
132
121
  timeoutTimer.unref?.();
133
122
  });
134
- const executePromise = execute().then(() => 'done');
123
+ const executePromise = executeSerialized().then(() => 'done');
135
124
  // Keep the chain explicitly handled even after the timeout wins the race:
136
125
  // a late rejection from the wedged handler (hung tool killed by OOM,
137
126
  // network drop, ...) must never surface as an unhandledRejection and
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Per-(target, workspace) job serialization for the remote executor.
3
+ *
4
+ * Production incident: a user resubmitted a deploy that looked stuck, and the
5
+ * executor ran BOTH identical deploys of the same project+workspace
6
+ * concurrently. They raced each other over the same cloned repo dirs, local
7
+ * hereya state and tofu/CDK state, and both wedged. Jobs that mutate the same
8
+ * logical target in the same workspace must run serially on one executor;
9
+ * unrelated jobs (e.g. the normal boot burst of provisions for different
10
+ * packages) must keep running concurrently.
11
+ */
12
+ /**
13
+ * Derives a stable key identifying "same logical target in the same
14
+ * workspace", or null when the job must NOT be serialized (read-only jobs,
15
+ * unknown job types, malformed payloads — those run immediately, no lock).
16
+ * Never throws.
17
+ *
18
+ * Key derivation per job type (the kind prefix prevents cross-kind
19
+ * collisions, e.g. a project named like an app):
20
+ * - deploy / undeploy: `project:<payload.project>:<payload.workspace>`
21
+ * - init: `project:<payload.projectName>:<payload.workspace>`
22
+ * - app-deploy / app-destroy: `app:<payload.appName>:<payload.workspace>`
23
+ * - provision / destroy: `pkg:<payload.package>:<payload.workspace>`
24
+ * - resolve-env: null (read-only, never serialized)
25
+ */
26
+ export declare function deriveJobSerializationKey(job: {
27
+ id: string;
28
+ payload: any;
29
+ type: string;
30
+ }): null | string;
31
+ /**
32
+ * Minimal keyed mutex: chains async functions per key so runs with the same
33
+ * key execute strictly serially (FIFO), while runs with different keys — or a
34
+ * null key — start immediately and proceed concurrently.
35
+ *
36
+ * - A rejecting fn never blocks its successors: each fn is chained via
37
+ * `.then(fn, fn)` onto a rejection-swallowed tail.
38
+ * - The map entry for a key is removed once its chain drains, so the map
39
+ * cannot grow unboundedly over executor uptime.
40
+ */
41
+ export declare class KeyedMutex {
42
+ private readonly chains;
43
+ /** Number of keys with in-flight or queued runs (introspection/test aid). */
44
+ get size(): number;
45
+ /**
46
+ * True when at least one run for this key is in flight or queued — i.e. a
47
+ * new run() with this key would have to wait. A null key is never busy.
48
+ */
49
+ isBusy(key: null | string): boolean;
50
+ run<T>(key: null | string, fn: () => Promise<T>): Promise<T>;
51
+ }
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Per-(target, workspace) job serialization for the remote executor.
3
+ *
4
+ * Production incident: a user resubmitted a deploy that looked stuck, and the
5
+ * executor ran BOTH identical deploys of the same project+workspace
6
+ * concurrently. They raced each other over the same cloned repo dirs, local
7
+ * hereya state and tofu/CDK state, and both wedged. Jobs that mutate the same
8
+ * logical target in the same workspace must run serially on one executor;
9
+ * unrelated jobs (e.g. the normal boot burst of provisions for different
10
+ * packages) must keep running concurrently.
11
+ */
12
+ /**
13
+ * Escape '%' (the escape character) and ':' (the key segment separator) so
14
+ * two different (target, workspace) pairs can never collide on the same key
15
+ * (e.g. project `a:b` in workspace `c` vs project `a` in workspace `b:c`).
16
+ */
17
+ function escapeSegment(value) {
18
+ return value.replaceAll('%', '%25').replaceAll(':', '%3A');
19
+ }
20
+ function buildKey(kind, target, workspace) {
21
+ return `${kind}:${escapeSegment(target)}:${escapeSegment(workspace)}`;
22
+ }
23
+ function nonEmptyString(value) {
24
+ if (typeof value !== 'string')
25
+ return undefined;
26
+ const trimmed = value.trim();
27
+ return trimmed === '' ? undefined : trimmed;
28
+ }
29
+ /**
30
+ * Derives a stable key identifying "same logical target in the same
31
+ * workspace", or null when the job must NOT be serialized (read-only jobs,
32
+ * unknown job types, malformed payloads — those run immediately, no lock).
33
+ * Never throws.
34
+ *
35
+ * Key derivation per job type (the kind prefix prevents cross-kind
36
+ * collisions, e.g. a project named like an app):
37
+ * - deploy / undeploy: `project:<payload.project>:<payload.workspace>`
38
+ * - init: `project:<payload.projectName>:<payload.workspace>`
39
+ * - app-deploy / app-destroy: `app:<payload.appName>:<payload.workspace>`
40
+ * - provision / destroy: `pkg:<payload.package>:<payload.workspace>`
41
+ * - resolve-env: null (read-only, never serialized)
42
+ */
43
+ export function deriveJobSerializationKey(job) {
44
+ try {
45
+ const { payload } = job;
46
+ if (!payload || typeof payload !== 'object')
47
+ return null;
48
+ const workspace = nonEmptyString(payload.workspace);
49
+ if (!workspace)
50
+ return null;
51
+ switch (job.type) {
52
+ case 'app-deploy':
53
+ case 'app-destroy': {
54
+ const appName = nonEmptyString(payload.appName);
55
+ return appName ? buildKey('app', appName, workspace) : null;
56
+ }
57
+ case 'deploy':
58
+ case 'undeploy': {
59
+ // The deploy payload carries the project NAME (the repo URL lives in
60
+ // the project metadata fetched later), so the name is the identity.
61
+ const project = nonEmptyString(payload.project);
62
+ return project ? buildKey('project', project, workspace) : null;
63
+ }
64
+ case 'destroy':
65
+ case 'provision': {
66
+ const pkg = nonEmptyString(payload.package);
67
+ return pkg ? buildKey('pkg', pkg, workspace) : null;
68
+ }
69
+ case 'init': {
70
+ // Shares the `project:` key space with deploy/undeploy on purpose:
71
+ // an init and a deploy of the same project must not interleave.
72
+ const projectName = nonEmptyString(payload.projectName);
73
+ return projectName ? buildKey('project', projectName, workspace) : null;
74
+ }
75
+ default: {
76
+ // resolve-env (read-only) and any unknown/future job type.
77
+ return null;
78
+ }
79
+ }
80
+ }
81
+ catch {
82
+ // Serialization is best-effort protection; a weird payload must never
83
+ // prevent the job from running at all.
84
+ return null;
85
+ }
86
+ }
87
+ /**
88
+ * Minimal keyed mutex: chains async functions per key so runs with the same
89
+ * key execute strictly serially (FIFO), while runs with different keys — or a
90
+ * null key — start immediately and proceed concurrently.
91
+ *
92
+ * - A rejecting fn never blocks its successors: each fn is chained via
93
+ * `.then(fn, fn)` onto a rejection-swallowed tail.
94
+ * - The map entry for a key is removed once its chain drains, so the map
95
+ * cannot grow unboundedly over executor uptime.
96
+ */
97
+ export class KeyedMutex {
98
+ chains = new Map();
99
+ /** Number of keys with in-flight or queued runs (introspection/test aid). */
100
+ get size() {
101
+ return this.chains.size;
102
+ }
103
+ /**
104
+ * True when at least one run for this key is in flight or queued — i.e. a
105
+ * new run() with this key would have to wait. A null key is never busy.
106
+ */
107
+ isBusy(key) {
108
+ return key !== null && this.chains.has(key);
109
+ }
110
+ async run(key, fn) {
111
+ if (key === null) {
112
+ return fn();
113
+ }
114
+ const existing = this.chains.get(key);
115
+ const entry = existing ?? { pending: 0, tail: Promise.resolve() };
116
+ if (!existing) {
117
+ this.chains.set(key, entry);
118
+ }
119
+ entry.pending += 1;
120
+ const chained = entry.tail.then(fn, fn);
121
+ // The stored tail must never reject (a failed predecessor must not block
122
+ // or poison successors); once this run settles, drop the map entry if no
123
+ // other run is in flight or queued for the key.
124
+ entry.tail = chained
125
+ .then(() => { }, () => { })
126
+ .finally(() => {
127
+ entry.pending -= 1;
128
+ if (entry.pending === 0 && this.chains.get(key) === entry) {
129
+ this.chains.delete(key);
130
+ }
131
+ });
132
+ return chained;
133
+ }
134
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Per-job execution timeout in minutes. Overridable via
3
+ * HEREYA_EXECUTOR_JOB_TIMEOUT_MIN (positive number, in minutes).
4
+ * A wedged child process (e.g. a tool blocking on a prompt) must not hold
5
+ * its executor slot forever while the heartbeat keeps the job "alive".
6
+ */
7
+ export declare function executorJobTimeoutMin(): number;
@@ -0,0 +1,17 @@
1
+ const DEFAULT_EXECUTOR_JOB_TIMEOUT_MIN = 60;
2
+ /**
3
+ * Per-job execution timeout in minutes. Overridable via
4
+ * HEREYA_EXECUTOR_JOB_TIMEOUT_MIN (positive number, in minutes).
5
+ * A wedged child process (e.g. a tool blocking on a prompt) must not hold
6
+ * its executor slot forever while the heartbeat keeps the job "alive".
7
+ */
8
+ export function executorJobTimeoutMin() {
9
+ const fromEnv = process.env.HEREYA_EXECUTOR_JOB_TIMEOUT_MIN;
10
+ if (fromEnv !== undefined) {
11
+ const parsed = Number(fromEnv);
12
+ if (Number.isFinite(parsed) && parsed > 0) {
13
+ return parsed;
14
+ }
15
+ }
16
+ return DEFAULT_EXECUTOR_JOB_TIMEOUT_MIN;
17
+ }
@@ -3517,5 +3517,5 @@
3517
3517
  ]
3518
3518
  }
3519
3519
  },
3520
- "version": "0.104.0"
3520
+ "version": "0.105.0"
3521
3521
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "hereya-cli",
3
3
  "description": "Infrastructure as Package",
4
- "version": "0.104.0",
4
+ "version": "0.105.0",
5
5
  "author": "Hereya Developers",
6
6
  "bin": {
7
7
  "hereya": "./bin/run.cjs"