task-pipeliner 0.3.4 → 0.3.5
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.ko.md +69 -69
- package/README.md +71 -70
- package/dist/index.cjs +17 -18
- package/package.json +1 -1
package/README.ko.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> 조건 기반 실행과 아름다운 CLI 출력을 제공하는 강력한 워크플로우 오케스트레이션 도구
|
|
4
4
|
|
|
5
|
-
**버전:** 0.3.
|
|
5
|
+
**버전:** 0.3.5
|
|
6
6
|
|
|
7
7
|

|
|
8
8
|
|
|
@@ -224,7 +224,7 @@ npx tp run workflow.yaml
|
|
|
224
224
|
name: My Workflow
|
|
225
225
|
|
|
226
226
|
steps:
|
|
227
|
-
- run: echo "Hello, World!"
|
|
227
|
+
- run: 'echo "Hello, World!"'
|
|
228
228
|
|
|
229
229
|
- choose:
|
|
230
230
|
message: "무엇을 하시겠습니까?"
|
|
@@ -238,12 +238,12 @@ steps:
|
|
|
238
238
|
- when:
|
|
239
239
|
var:
|
|
240
240
|
action: build
|
|
241
|
-
run: npm run build
|
|
241
|
+
run: 'npm run build'
|
|
242
242
|
|
|
243
243
|
- when:
|
|
244
244
|
var:
|
|
245
245
|
action: test
|
|
246
|
-
run: npm test
|
|
246
|
+
run: 'npm test'
|
|
247
247
|
```
|
|
248
248
|
|
|
249
249
|
**JSON 형식 (`workflow.json`):**
|
|
@@ -509,12 +509,12 @@ steps: # 필수: 실행할 단계 배열
|
|
|
509
509
|
```yaml
|
|
510
510
|
# 간단한 명령
|
|
511
511
|
steps:
|
|
512
|
-
- run: npm install
|
|
512
|
+
- run: 'npm install'
|
|
513
513
|
|
|
514
514
|
# 조건이 있는 명령
|
|
515
515
|
- when:
|
|
516
516
|
file: ./package.json
|
|
517
|
-
run: npm install
|
|
517
|
+
run: 'npm install'
|
|
518
518
|
|
|
519
519
|
# 변수 입력
|
|
520
520
|
- choose:
|
|
@@ -529,55 +529,55 @@ steps:
|
|
|
529
529
|
as: version
|
|
530
530
|
|
|
531
531
|
# 변수 치환이 있는 명령
|
|
532
|
-
- run: echo "Building {{version}}"
|
|
532
|
+
- run: 'echo "Building {{version}}"'
|
|
533
533
|
|
|
534
534
|
# 타임아웃이 있는 명령 (30초)
|
|
535
|
-
- run: npm install
|
|
535
|
+
- run: 'npm install'
|
|
536
536
|
timeout: 30
|
|
537
537
|
|
|
538
538
|
# 재시도가 있는 명령 (최대 3번 재시도)
|
|
539
|
-
- run: npm install
|
|
539
|
+
- run: 'npm install'
|
|
540
540
|
retry: 3
|
|
541
541
|
|
|
542
542
|
# 무한 재시도 명령 (성공할 때까지 재시도)
|
|
543
|
-
- run: npm install
|
|
543
|
+
- run: 'npm install'
|
|
544
544
|
retry: Infinity
|
|
545
545
|
|
|
546
546
|
# PM2처럼 프로세스 관리: 서버가 죽으면 자동 재시작
|
|
547
|
-
- run: node server.js
|
|
547
|
+
- run: 'node server.js'
|
|
548
548
|
retry: Infinity
|
|
549
549
|
|
|
550
550
|
# 타임아웃과 재시도 모두 사용
|
|
551
|
-
- run: npm install
|
|
551
|
+
- run: 'npm install'
|
|
552
552
|
timeout: 60
|
|
553
553
|
retry: 2
|
|
554
554
|
|
|
555
555
|
# 실패 시 fallback 명령 실행
|
|
556
|
-
- run: pnpm lint
|
|
556
|
+
- run: 'pnpm lint'
|
|
557
557
|
onError:
|
|
558
|
-
run: pnpm lint:fix
|
|
558
|
+
run: 'pnpm lint:fix'
|
|
559
559
|
|
|
560
560
|
# 여러 단계로 이어지는 fallback 체인
|
|
561
|
-
- run: step1
|
|
561
|
+
- run: 'step1'
|
|
562
562
|
onError:
|
|
563
|
-
run: step2
|
|
563
|
+
run: 'step2'
|
|
564
564
|
onError:
|
|
565
|
-
run: step3
|
|
565
|
+
run: 'step3'
|
|
566
566
|
|
|
567
567
|
# 실패를 기록만 하고 워크플로우는 계속 진행
|
|
568
|
-
- run: pnpm typecheck
|
|
568
|
+
- run: 'pnpm typecheck'
|
|
569
569
|
continue: true
|
|
570
570
|
onError:
|
|
571
|
-
run: echo "Type check failed, but continuing..."
|
|
571
|
+
run: 'echo "Type check failed, but continuing..."'
|
|
572
572
|
|
|
573
573
|
# 커스텀 쉘 사용 (스텝별)
|
|
574
|
-
- run: echo $SHELL
|
|
574
|
+
- run: 'echo $SHELL'
|
|
575
575
|
shell:
|
|
576
576
|
- zsh
|
|
577
577
|
- -c
|
|
578
578
|
|
|
579
579
|
# bash 로그인 쉘 사용
|
|
580
|
-
- run: source ~/.bashrc && echo "프로필 로드됨"
|
|
580
|
+
- run: 'source ~/.bashrc && echo "프로필 로드됨"'
|
|
581
581
|
shell:
|
|
582
582
|
- bash
|
|
583
583
|
- -lc
|
|
@@ -679,7 +679,7 @@ steps:
|
|
|
679
679
|
- when:
|
|
680
680
|
var: # 변수를 사용한다는 정의
|
|
681
681
|
env: prod # 'env' 변수가 'prod'와 같은지 확인
|
|
682
|
-
run: echo "프로덕션에 배포 중"
|
|
682
|
+
run: 'echo "프로덕션에 배포 중"'
|
|
683
683
|
```
|
|
684
684
|
|
|
685
685
|
---
|
|
@@ -733,13 +733,13 @@ steps:
|
|
|
733
733
|
**사용:**
|
|
734
734
|
```yaml
|
|
735
735
|
# 명령에서 사용
|
|
736
|
-
- run: echo "Building version {{version}}"
|
|
736
|
+
- run: 'echo "Building version {{version}}"'
|
|
737
737
|
|
|
738
738
|
# 조건에서 확인
|
|
739
739
|
- when:
|
|
740
740
|
var:
|
|
741
741
|
version: "1.0.0"
|
|
742
|
-
run: echo "안정 버전 배포 중"
|
|
742
|
+
run: 'echo "안정 버전 배포 중"'
|
|
743
743
|
```
|
|
744
744
|
|
|
745
745
|
---
|
|
@@ -768,19 +768,19 @@ steps:
|
|
|
768
768
|
# 기본 병렬 실행
|
|
769
769
|
# parallel 내부의 각 step은 `-`로 시작하며, `steps`와 동일한 형식
|
|
770
770
|
- parallel:
|
|
771
|
-
- run: npm run test:unit
|
|
772
|
-
- run: npm run test:integration
|
|
773
|
-
- run: npm run lint
|
|
771
|
+
- run: 'npm run test:unit'
|
|
772
|
+
- run: 'npm run test:integration'
|
|
773
|
+
- run: 'npm run lint'
|
|
774
774
|
|
|
775
775
|
# 조건이 있는 병렬
|
|
776
776
|
# 각 step은 자신만의 `when` 조건을 가질 수 있습니다
|
|
777
777
|
- parallel:
|
|
778
778
|
- when:
|
|
779
779
|
file: ./src
|
|
780
|
-
run: echo "프론트엔드 빌드 중..."
|
|
780
|
+
run: 'echo "프론트엔드 빌드 중..."'
|
|
781
781
|
- when:
|
|
782
782
|
file: ./api
|
|
783
|
-
run: echo "백엔드 빌드 중..."
|
|
783
|
+
run: 'echo "백엔드 빌드 중..."'
|
|
784
784
|
|
|
785
785
|
# 조건부 병렬 블록
|
|
786
786
|
# 전체 parallel 블록에 `when` 조건을 적용할 수 있습니다
|
|
@@ -788,15 +788,15 @@ steps:
|
|
|
788
788
|
var:
|
|
789
789
|
env: staging
|
|
790
790
|
parallel:
|
|
791
|
-
- run: npm run test
|
|
792
|
-
- run: npm run lint
|
|
791
|
+
- run: 'npm run test'
|
|
792
|
+
- run: 'npm run lint'
|
|
793
793
|
|
|
794
794
|
# 중첩 parallel (허용); parallel 내부에는 run / parallel / fail만 사용
|
|
795
795
|
- parallel:
|
|
796
|
-
- run: npm run test
|
|
796
|
+
- run: 'npm run test'
|
|
797
797
|
- parallel:
|
|
798
|
-
- run: npm run lint
|
|
799
|
-
- run: npm run typecheck
|
|
798
|
+
- run: 'npm run lint'
|
|
799
|
+
- run: 'npm run typecheck'
|
|
800
800
|
```
|
|
801
801
|
|
|
802
802
|
**동작:**
|
|
@@ -870,16 +870,16 @@ when:
|
|
|
870
870
|
```yaml
|
|
871
871
|
- when:
|
|
872
872
|
file: ./dist
|
|
873
|
-
run: echo "빌드가 존재합니다"
|
|
873
|
+
run: 'echo "빌드가 존재합니다"'
|
|
874
874
|
|
|
875
875
|
- when:
|
|
876
876
|
file: ./package.json
|
|
877
|
-
run: npm install
|
|
877
|
+
run: 'npm install'
|
|
878
878
|
|
|
879
879
|
- when:
|
|
880
880
|
not:
|
|
881
881
|
file: ./node_modules
|
|
882
|
-
run: npm install
|
|
882
|
+
run: 'npm install'
|
|
883
883
|
```
|
|
884
884
|
|
|
885
885
|
**동작:**
|
|
@@ -910,20 +910,20 @@ when:
|
|
|
910
910
|
- when:
|
|
911
911
|
var:
|
|
912
912
|
env: prod
|
|
913
|
-
run: echo "프로덕션에 배포 중"
|
|
913
|
+
run: 'echo "프로덕션에 배포 중"'
|
|
914
914
|
|
|
915
915
|
# version이 특정 값과 같은지 확인
|
|
916
916
|
- when:
|
|
917
917
|
var:
|
|
918
918
|
version: "1.0.0"
|
|
919
|
-
run: echo "안정 버전 배포 중"
|
|
919
|
+
run: 'echo "안정 버전 배포 중"'
|
|
920
920
|
|
|
921
921
|
# 여러 변수 확인 (모두 일치해야 함)
|
|
922
922
|
- when:
|
|
923
923
|
var:
|
|
924
924
|
env: staging
|
|
925
925
|
version: "2.0.0"
|
|
926
|
-
run: echo "스테이징에 v2.0.0 배포 중"
|
|
926
|
+
run: 'echo "스테이징에 v2.0.0 배포 중"'
|
|
927
927
|
```
|
|
928
928
|
|
|
929
929
|
**동작:**
|
|
@@ -955,12 +955,12 @@ when:
|
|
|
955
955
|
# 변수가 존재하는지 확인
|
|
956
956
|
- when:
|
|
957
957
|
var: version
|
|
958
|
-
run: echo "Version: {{version}}"
|
|
958
|
+
run: 'echo "Version: {{version}}"'
|
|
959
959
|
|
|
960
960
|
# 'has' 별칭 사용
|
|
961
961
|
- when:
|
|
962
962
|
has: projectName
|
|
963
|
-
run: echo "Project: {{projectName}}"
|
|
963
|
+
run: 'echo "Project: {{projectName}}"'
|
|
964
964
|
```
|
|
965
965
|
|
|
966
966
|
**동작:**
|
|
@@ -994,7 +994,7 @@ when:
|
|
|
994
994
|
- file: ./dist
|
|
995
995
|
- var:
|
|
996
996
|
env: production
|
|
997
|
-
run: echo "프로덕션 빌드 준비 완료"
|
|
997
|
+
run: 'echo "프로덕션 빌드 준비 완료"'
|
|
998
998
|
|
|
999
999
|
- when:
|
|
1000
1000
|
all:
|
|
@@ -1003,7 +1003,7 @@ when:
|
|
|
1003
1003
|
- var:
|
|
1004
1004
|
version: "2.0.0"
|
|
1005
1005
|
- file: ./dist
|
|
1006
|
-
run: echo "스테이징에 v2.0.0 배포 중"
|
|
1006
|
+
run: 'echo "스테이징에 v2.0.0 배포 중"'
|
|
1007
1007
|
```
|
|
1008
1008
|
|
|
1009
1009
|
**동작:**
|
|
@@ -1034,13 +1034,13 @@ when:
|
|
|
1034
1034
|
env: staging
|
|
1035
1035
|
- var:
|
|
1036
1036
|
env: production
|
|
1037
|
-
run: echo "서버에 배포 중"
|
|
1037
|
+
run: 'echo "서버에 배포 중"'
|
|
1038
1038
|
|
|
1039
1039
|
- when:
|
|
1040
1040
|
any:
|
|
1041
1041
|
- file: ./dist
|
|
1042
1042
|
- file: ./build
|
|
1043
|
-
run: echo "빌드 출력을 찾았습니다"
|
|
1043
|
+
run: 'echo "빌드 출력을 찾았습니다"'
|
|
1044
1044
|
```
|
|
1045
1045
|
|
|
1046
1046
|
**동작:**
|
|
@@ -1075,7 +1075,7 @@ when:
|
|
|
1075
1075
|
not:
|
|
1076
1076
|
var:
|
|
1077
1077
|
env: prod
|
|
1078
|
-
run: echo "프로덕션 환경이 아닙니다"
|
|
1078
|
+
run: 'echo "프로덕션 환경이 아닙니다"'
|
|
1079
1079
|
|
|
1080
1080
|
# 복잡한 부정
|
|
1081
1081
|
- when:
|
|
@@ -1084,7 +1084,7 @@ when:
|
|
|
1084
1084
|
- file: ./dist
|
|
1085
1085
|
- var:
|
|
1086
1086
|
env: prod
|
|
1087
|
-
run: echo "프로덕션 준비가 되지 않았습니다"
|
|
1087
|
+
run: 'echo "프로덕션 준비가 되지 않았습니다"'
|
|
1088
1088
|
```
|
|
1089
1089
|
|
|
1090
1090
|
**동작:**
|
|
@@ -1112,7 +1112,7 @@ when:
|
|
|
1112
1112
|
- not:
|
|
1113
1113
|
var:
|
|
1114
1114
|
version: "0.0.0"
|
|
1115
|
-
run: echo "배포 준비 완료"
|
|
1115
|
+
run: 'echo "배포 준비 완료"'
|
|
1116
1116
|
|
|
1117
1117
|
# 여러 수준의 중첩
|
|
1118
1118
|
- when:
|
|
@@ -1126,7 +1126,7 @@ when:
|
|
|
1126
1126
|
env: staging
|
|
1127
1127
|
- not:
|
|
1128
1128
|
file: ./test-results
|
|
1129
|
-
run: echo "조건부 배포"
|
|
1129
|
+
run: 'echo "조건부 배포"'
|
|
1130
1130
|
```
|
|
1131
1131
|
|
|
1132
1132
|
---
|
|
@@ -1137,9 +1137,9 @@ when:
|
|
|
1137
1137
|
|
|
1138
1138
|
**문법:**
|
|
1139
1139
|
```yaml
|
|
1140
|
-
run: echo "{{variableName}}"
|
|
1140
|
+
run: 'echo "{{variableName}}"'
|
|
1141
1141
|
# 또는 선택적으로 공백 사용
|
|
1142
|
-
run: echo "{{ variableName }}"
|
|
1142
|
+
run: 'echo "{{ variableName }}"'
|
|
1143
1143
|
```
|
|
1144
1144
|
|
|
1145
1145
|
**⚠️ 중요: YAML 문법 규칙**
|
|
@@ -1148,9 +1148,9 @@ run: echo "{{ variableName }}"
|
|
|
1148
1148
|
|
|
1149
1149
|
✅ **안전한 패턴:**
|
|
1150
1150
|
```yaml
|
|
1151
|
-
#
|
|
1152
|
-
- run: echo "Building {{version}}..."
|
|
1153
|
-
- run: npm run build --version={{version}}
|
|
1151
|
+
# 작은따옴표로 감싸기 (권장)
|
|
1152
|
+
- run: 'echo "Building {{version}}..."'
|
|
1153
|
+
- run: 'npm run build --version={{version}}'
|
|
1154
1154
|
|
|
1155
1155
|
# 전체 명령어를 작은따옴표로 감싸기
|
|
1156
1156
|
- run: 'echo "Selected: {{mode}}"'
|
|
@@ -1171,7 +1171,7 @@ run: echo "{{ variableName }}"
|
|
|
1171
1171
|
- prompt:
|
|
1172
1172
|
message: "프로젝트 이름을 입력하세요:"
|
|
1173
1173
|
as: projectName
|
|
1174
|
-
- run: echo "Building {{projectName}}..."
|
|
1174
|
+
- run: 'echo "Building {{projectName}}..."'
|
|
1175
1175
|
|
|
1176
1176
|
# 선택 변수 사용
|
|
1177
1177
|
- choose:
|
|
@@ -1180,10 +1180,10 @@ run: echo "{{ variableName }}"
|
|
|
1180
1180
|
- id: dev
|
|
1181
1181
|
label: "개발"
|
|
1182
1182
|
as: env
|
|
1183
|
-
- run: echo "Deploying to {{env}}"
|
|
1183
|
+
- run: 'echo "Deploying to {{env}}"'
|
|
1184
1184
|
|
|
1185
1185
|
# 여러 변수
|
|
1186
|
-
- run: echo "Building {{projectName}} version {{version}} for {{env}}"
|
|
1186
|
+
- run: 'echo "Building {{projectName}} version {{version}} for {{env}}"'
|
|
1187
1187
|
```
|
|
1188
1188
|
|
|
1189
1189
|
**동작:**
|
|
@@ -1203,7 +1203,7 @@ baseDir: ./
|
|
|
1203
1203
|
|
|
1204
1204
|
steps:
|
|
1205
1205
|
# 1. 간단한 명령
|
|
1206
|
-
- run: echo "워크플로우 시작 중..."
|
|
1206
|
+
- run: 'echo "워크플로우 시작 중..."'
|
|
1207
1207
|
|
|
1208
1208
|
# 2. 변수 저장이 있는 사용자 선택
|
|
1209
1209
|
- choose:
|
|
@@ -1229,12 +1229,12 @@ steps:
|
|
|
1229
1229
|
- when:
|
|
1230
1230
|
var:
|
|
1231
1231
|
env: dev
|
|
1232
|
-
run: echo "개발 환경에 배포 중..."
|
|
1232
|
+
run: 'echo "개발 환경에 배포 중..."'
|
|
1233
1233
|
|
|
1234
1234
|
- when:
|
|
1235
1235
|
var:
|
|
1236
1236
|
env: staging
|
|
1237
|
-
run: echo "스테이징에 배포 중..."
|
|
1237
|
+
run: 'echo "스테이징에 배포 중..."'
|
|
1238
1238
|
|
|
1239
1239
|
# 5. 복잡한 조건 (all)
|
|
1240
1240
|
- when:
|
|
@@ -1243,22 +1243,22 @@ steps:
|
|
|
1243
1243
|
env: prod
|
|
1244
1244
|
- var: deployReason
|
|
1245
1245
|
- file: ./dist
|
|
1246
|
-
run: echo "프로덕션 배포 승인됨"
|
|
1246
|
+
run: 'echo "프로덕션 배포 승인됨"'
|
|
1247
1247
|
|
|
1248
1248
|
# 6. 병렬 실행
|
|
1249
1249
|
- parallel:
|
|
1250
|
-
- run: npm run test:unit
|
|
1251
|
-
- run: npm run test:integration
|
|
1252
|
-
- run: npm run lint
|
|
1250
|
+
- run: 'npm run test:unit'
|
|
1251
|
+
- run: 'npm run test:integration'
|
|
1252
|
+
- run: 'npm run lint'
|
|
1253
1253
|
|
|
1254
1254
|
# 6.5. 스텝별 쉘 오버라이드
|
|
1255
|
-
- run: echo "zsh로 실행"
|
|
1255
|
+
- run: 'echo "zsh로 실행"'
|
|
1256
1256
|
shell: [zsh, -c] # 이 스텝만 워크플로우 쉘 오버라이드
|
|
1257
1257
|
|
|
1258
1258
|
# 7. 파일 존재 확인
|
|
1259
1259
|
- when:
|
|
1260
1260
|
file: ./test-results
|
|
1261
|
-
run: echo "테스트 완료"
|
|
1261
|
+
run: 'echo "테스트 완료"'
|
|
1262
1262
|
|
|
1263
1263
|
# 8. 결합된 조건 (any)
|
|
1264
1264
|
- when:
|
|
@@ -1267,7 +1267,7 @@ steps:
|
|
|
1267
1267
|
env: staging
|
|
1268
1268
|
- var:
|
|
1269
1269
|
env: prod
|
|
1270
|
-
run: echo "서버에 배포 중..."
|
|
1270
|
+
run: 'echo "서버에 배포 중..."'
|
|
1271
1271
|
|
|
1272
1272
|
# 9. 부정
|
|
1273
1273
|
- when:
|
|
@@ -1277,7 +1277,7 @@ steps:
|
|
|
1277
1277
|
message: "빌드 출력을 찾을 수 없습니다"
|
|
1278
1278
|
|
|
1279
1279
|
# 10. 변수 치환
|
|
1280
|
-
- run: echo "Deploying {{projectName}} version {{version}} to {{env}}"
|
|
1280
|
+
- run: 'echo "Deploying {{projectName}} version {{version}} to {{env}}"'
|
|
1281
1281
|
```
|
|
1282
1282
|
|
|
1283
1283
|
---
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> A powerful workflow orchestration tool with condition-based execution and beautiful CLI output
|
|
4
4
|
|
|
5
|
-
**Version:** 0.3.
|
|
5
|
+
**Version:** 0.3.5
|
|
6
6
|
|
|
7
7
|

|
|
8
8
|
|
|
@@ -224,7 +224,7 @@ Create a `workflow.yaml` or `workflow.json` file:
|
|
|
224
224
|
name: My Workflow
|
|
225
225
|
|
|
226
226
|
steps:
|
|
227
|
-
- run: echo "Hello, World!"
|
|
227
|
+
- run: 'echo "Hello, World!"'
|
|
228
228
|
|
|
229
229
|
- choose:
|
|
230
230
|
message: "What would you like to do?"
|
|
@@ -238,12 +238,12 @@ steps:
|
|
|
238
238
|
- when:
|
|
239
239
|
var:
|
|
240
240
|
action: build
|
|
241
|
-
run: npm run build
|
|
241
|
+
run: 'npm run build'
|
|
242
242
|
|
|
243
243
|
- when:
|
|
244
244
|
var:
|
|
245
245
|
action: test
|
|
246
|
-
run: npm test
|
|
246
|
+
run: 'npm test'
|
|
247
247
|
```
|
|
248
248
|
|
|
249
249
|
**JSON Format (`workflow.json`):**
|
|
@@ -509,12 +509,12 @@ Execute a shell command.
|
|
|
509
509
|
```yaml
|
|
510
510
|
# Simple command
|
|
511
511
|
steps:
|
|
512
|
-
- run: npm install
|
|
512
|
+
- run: 'npm install'
|
|
513
513
|
|
|
514
514
|
# Command with condition
|
|
515
515
|
- when:
|
|
516
516
|
file: ./package.json
|
|
517
|
-
run: npm install
|
|
517
|
+
run: 'npm install'
|
|
518
518
|
|
|
519
519
|
# Variable input
|
|
520
520
|
- choose:
|
|
@@ -529,55 +529,55 @@ steps:
|
|
|
529
529
|
as: version
|
|
530
530
|
|
|
531
531
|
# Command with variable substitution
|
|
532
|
-
- run: echo "Building {{version}}"
|
|
532
|
+
- run: 'echo "Building {{version}}"'
|
|
533
533
|
|
|
534
534
|
# Command with timeout (30 seconds)
|
|
535
|
-
- run: npm install
|
|
535
|
+
- run: 'npm install'
|
|
536
536
|
timeout: 30
|
|
537
537
|
|
|
538
538
|
# Command with retry (retry up to 3 times)
|
|
539
|
-
- run: npm install
|
|
539
|
+
- run: 'npm install'
|
|
540
540
|
retry: 3
|
|
541
541
|
|
|
542
542
|
# Command with infinite retry (retry until success)
|
|
543
|
-
- run: npm install
|
|
543
|
+
- run: 'npm install'
|
|
544
544
|
retry: Infinity
|
|
545
545
|
|
|
546
546
|
# PM2-like process manager: auto-restart crashed server
|
|
547
|
-
- run: node server.js
|
|
547
|
+
- run: 'node server.js'
|
|
548
548
|
retry: Infinity
|
|
549
549
|
|
|
550
550
|
# Using both timeout and retry
|
|
551
|
-
- run: npm install
|
|
551
|
+
- run: 'npm install'
|
|
552
552
|
timeout: 60
|
|
553
553
|
retry: 2
|
|
554
554
|
|
|
555
555
|
# Command with fallback on error
|
|
556
|
-
- run: pnpm lint
|
|
556
|
+
- run: 'pnpm lint'
|
|
557
557
|
onError:
|
|
558
|
-
run: pnpm lint:fix
|
|
558
|
+
run: 'pnpm lint:fix'
|
|
559
559
|
|
|
560
560
|
# Command with multi-level fallback on error
|
|
561
|
-
- run: step1
|
|
561
|
+
- run: 'step1'
|
|
562
562
|
onError:
|
|
563
|
-
run: step2
|
|
563
|
+
run: 'step2'
|
|
564
564
|
onError:
|
|
565
|
-
run: step3
|
|
565
|
+
run: 'step3'
|
|
566
566
|
|
|
567
567
|
# Command that records failure but continues workflow
|
|
568
|
-
- run: pnpm typecheck
|
|
568
|
+
- run: 'pnpm typecheck'
|
|
569
569
|
continue: true
|
|
570
570
|
onError:
|
|
571
|
-
run: echo "Type check failed, but continuing..."
|
|
571
|
+
run: 'echo "Type check failed, but continuing..."'
|
|
572
572
|
|
|
573
573
|
# Command with custom shell (step-level)
|
|
574
|
-
- run: echo $SHELL
|
|
574
|
+
- run: 'echo $SHELL'
|
|
575
575
|
shell:
|
|
576
576
|
- zsh
|
|
577
577
|
- -c
|
|
578
578
|
|
|
579
579
|
# Command with bash login shell
|
|
580
|
-
- run: source ~/.bashrc && echo "Loaded profile"
|
|
580
|
+
- run: 'source ~/.bashrc && echo "Loaded profile"'
|
|
581
581
|
shell:
|
|
582
582
|
- bash
|
|
583
583
|
- -lc
|
|
@@ -679,7 +679,7 @@ steps:
|
|
|
679
679
|
- when:
|
|
680
680
|
var: # Definition that uses a variable
|
|
681
681
|
env: prod # Check if 'env' variable equals 'prod'
|
|
682
|
-
run: echo "Deploying to production"
|
|
682
|
+
run: 'echo "Deploying to production"'
|
|
683
683
|
```
|
|
684
684
|
|
|
685
685
|
---
|
|
@@ -733,13 +733,13 @@ Ask user for text input.
|
|
|
733
733
|
**Usage:**
|
|
734
734
|
```yaml
|
|
735
735
|
# Use in command
|
|
736
|
-
- run: echo "Building version {{version}}"
|
|
736
|
+
- run: 'echo "Building version {{version}}"'
|
|
737
737
|
|
|
738
738
|
# Check in condition
|
|
739
739
|
- when:
|
|
740
740
|
var:
|
|
741
741
|
version: "1.0.0"
|
|
742
|
-
run: echo "Deploying stable version"
|
|
742
|
+
run: 'echo "Deploying stable version"'
|
|
743
743
|
```
|
|
744
744
|
|
|
745
745
|
---
|
|
@@ -768,19 +768,19 @@ Execute multiple steps simultaneously. Like `steps`, `parallel` contains an arra
|
|
|
768
768
|
# Basic parallel execution
|
|
769
769
|
# Each step inside parallel starts with `-`, same format as `steps`
|
|
770
770
|
- parallel:
|
|
771
|
-
- run: npm run test:unit
|
|
772
|
-
- run: npm run test:integration
|
|
773
|
-
- run: npm run lint
|
|
771
|
+
- run: 'npm run test:unit'
|
|
772
|
+
- run: 'npm run test:integration'
|
|
773
|
+
- run: 'npm run lint'
|
|
774
774
|
|
|
775
775
|
# Parallel with conditions
|
|
776
776
|
# Each step can have its own `when` condition
|
|
777
777
|
- parallel:
|
|
778
778
|
- when:
|
|
779
779
|
file: ./src
|
|
780
|
-
run: echo "Building frontend..."
|
|
780
|
+
run: 'echo "Building frontend..."'
|
|
781
781
|
- when:
|
|
782
782
|
file: ./api
|
|
783
|
-
run: echo "Building backend..."
|
|
783
|
+
run: 'echo "Building backend..."'
|
|
784
784
|
|
|
785
785
|
# Conditional parallel block
|
|
786
786
|
# The entire parallel block can have a `when` condition
|
|
@@ -788,15 +788,15 @@ Execute multiple steps simultaneously. Like `steps`, `parallel` contains an arra
|
|
|
788
788
|
var:
|
|
789
789
|
env: staging
|
|
790
790
|
parallel:
|
|
791
|
-
- run: npm run test
|
|
792
|
-
- run: npm run lint
|
|
791
|
+
- run: 'npm run test'
|
|
792
|
+
- run: 'npm run lint'
|
|
793
793
|
|
|
794
794
|
# Nested parallel (allowed); only run / parallel / fail inside parallel
|
|
795
795
|
- parallel:
|
|
796
|
-
- run: npm run test
|
|
796
|
+
- run: 'npm run test'
|
|
797
797
|
- parallel:
|
|
798
|
-
- run: npm run lint
|
|
799
|
-
- run: npm run typecheck
|
|
798
|
+
- run: 'npm run lint'
|
|
799
|
+
- run: 'npm run typecheck'
|
|
800
800
|
```
|
|
801
801
|
|
|
802
802
|
**Behavior:**
|
|
@@ -870,16 +870,16 @@ when:
|
|
|
870
870
|
```yaml
|
|
871
871
|
- when:
|
|
872
872
|
file: ./dist
|
|
873
|
-
run: echo "Build exists"
|
|
873
|
+
run: 'echo "Build exists"'
|
|
874
874
|
|
|
875
875
|
- when:
|
|
876
876
|
file: ./package.json
|
|
877
|
-
run: npm install
|
|
877
|
+
run: 'npm install'
|
|
878
878
|
|
|
879
879
|
- when:
|
|
880
880
|
not:
|
|
881
881
|
file: ./node_modules
|
|
882
|
-
run: npm install
|
|
882
|
+
run: 'npm install'
|
|
883
883
|
```
|
|
884
884
|
|
|
885
885
|
**Behavior:**
|
|
@@ -910,20 +910,20 @@ when:
|
|
|
910
910
|
- when:
|
|
911
911
|
var:
|
|
912
912
|
env: prod
|
|
913
|
-
run: echo "Deploying to production"
|
|
913
|
+
run: 'echo "Deploying to production"'
|
|
914
914
|
|
|
915
915
|
# Check if version equals specific value
|
|
916
916
|
- when:
|
|
917
917
|
var:
|
|
918
918
|
version: "1.0.0"
|
|
919
|
-
run: echo "Deploying stable version"
|
|
919
|
+
run: 'echo "Deploying stable version"'
|
|
920
920
|
|
|
921
921
|
# Multiple variable checks (all must match)
|
|
922
922
|
- when:
|
|
923
923
|
var:
|
|
924
924
|
env: staging
|
|
925
925
|
version: "2.0.0"
|
|
926
|
-
run: echo "Deploying v2.0.0 to staging"
|
|
926
|
+
run: 'echo "Deploying v2.0.0 to staging"'
|
|
927
927
|
```
|
|
928
928
|
|
|
929
929
|
**Behavior:**
|
|
@@ -955,12 +955,12 @@ when:
|
|
|
955
955
|
# Check if variable exists
|
|
956
956
|
- when:
|
|
957
957
|
var: version
|
|
958
|
-
run: echo "Version: {{version}}"
|
|
958
|
+
run: 'echo "Version: {{version}}"'
|
|
959
959
|
|
|
960
960
|
# Use 'has' alias
|
|
961
961
|
- when:
|
|
962
962
|
has: projectName
|
|
963
|
-
run: echo "Project: {{projectName}}"
|
|
963
|
+
run: 'echo "Project: {{projectName}}"'
|
|
964
964
|
```
|
|
965
965
|
|
|
966
966
|
**Behavior:**
|
|
@@ -994,7 +994,7 @@ when:
|
|
|
994
994
|
- file: ./dist
|
|
995
995
|
- var:
|
|
996
996
|
env: production
|
|
997
|
-
run: echo "Production build ready"
|
|
997
|
+
run: 'echo "Production build ready"'
|
|
998
998
|
|
|
999
999
|
- when:
|
|
1000
1000
|
all:
|
|
@@ -1003,7 +1003,7 @@ when:
|
|
|
1003
1003
|
- var:
|
|
1004
1004
|
version: "2.0.0"
|
|
1005
1005
|
- file: ./dist
|
|
1006
|
-
run: echo "Deploying v2.0.0 to staging"
|
|
1006
|
+
run: 'echo "Deploying v2.0.0 to staging"'
|
|
1007
1007
|
```
|
|
1008
1008
|
|
|
1009
1009
|
**Behavior:**
|
|
@@ -1034,13 +1034,13 @@ when:
|
|
|
1034
1034
|
env: staging
|
|
1035
1035
|
- var:
|
|
1036
1036
|
env: production
|
|
1037
|
-
run: echo "Deploying to server"
|
|
1037
|
+
run: 'echo "Deploying to server"'
|
|
1038
1038
|
|
|
1039
1039
|
- when:
|
|
1040
1040
|
any:
|
|
1041
1041
|
- file: ./dist
|
|
1042
1042
|
- file: ./build
|
|
1043
|
-
run: echo "Build output found"
|
|
1043
|
+
run: 'echo "Build output found"'
|
|
1044
1044
|
```
|
|
1045
1045
|
|
|
1046
1046
|
**Behavior:**
|
|
@@ -1075,7 +1075,7 @@ when:
|
|
|
1075
1075
|
not:
|
|
1076
1076
|
var:
|
|
1077
1077
|
env: prod
|
|
1078
|
-
run: echo "Not production environment"
|
|
1078
|
+
run: 'echo "Not production environment"'
|
|
1079
1079
|
|
|
1080
1080
|
# Complex negation
|
|
1081
1081
|
- when:
|
|
@@ -1084,7 +1084,7 @@ when:
|
|
|
1084
1084
|
- file: ./dist
|
|
1085
1085
|
- var:
|
|
1086
1086
|
env: prod
|
|
1087
|
-
run: echo "Production not ready"
|
|
1087
|
+
run: 'echo "Production not ready"'
|
|
1088
1088
|
```
|
|
1089
1089
|
|
|
1090
1090
|
**Behavior:**
|
|
@@ -1112,7 +1112,7 @@ Nest conditions to create complex logic.
|
|
|
1112
1112
|
- not:
|
|
1113
1113
|
var:
|
|
1114
1114
|
version: "0.0.0"
|
|
1115
|
-
run: echo "Ready to deploy"
|
|
1115
|
+
run: 'echo "Ready to deploy"'
|
|
1116
1116
|
|
|
1117
1117
|
# Multiple levels of nesting
|
|
1118
1118
|
- when:
|
|
@@ -1126,7 +1126,7 @@ Nest conditions to create complex logic.
|
|
|
1126
1126
|
env: staging
|
|
1127
1127
|
- not:
|
|
1128
1128
|
file: ./test-results
|
|
1129
|
-
run: echo "Conditional deployment"
|
|
1129
|
+
run: 'echo "Conditional deployment"'
|
|
1130
1130
|
```
|
|
1131
1131
|
|
|
1132
1132
|
---
|
|
@@ -1137,9 +1137,9 @@ Variables can be used in commands using the `{{variable}}` syntax. Optional whit
|
|
|
1137
1137
|
|
|
1138
1138
|
**Syntax:**
|
|
1139
1139
|
```yaml
|
|
1140
|
-
run: echo "{{variableName}}"
|
|
1140
|
+
run: 'echo "{{variableName}}"'
|
|
1141
1141
|
# or with optional spaces
|
|
1142
|
-
run: echo "{{ variableName }}"
|
|
1142
|
+
run: 'echo "{{ variableName }}"'
|
|
1143
1143
|
```
|
|
1144
1144
|
|
|
1145
1145
|
**⚠️ Important YAML Syntax Rules:**
|
|
@@ -1148,9 +1148,9 @@ When using `{{variable}}` in commands, follow these rules to avoid parsing error
|
|
|
1148
1148
|
|
|
1149
1149
|
✅ **Safe patterns:**
|
|
1150
1150
|
```yaml
|
|
1151
|
-
#
|
|
1152
|
-
- run: echo "Building {{version}}..."
|
|
1153
|
-
- run: npm run build --version={{version}}
|
|
1151
|
+
# Wrap in single quotes (recommended)
|
|
1152
|
+
- run: 'echo "Building {{version}}..."'
|
|
1153
|
+
- run: 'npm run build --version={{version}}'
|
|
1154
1154
|
|
|
1155
1155
|
# Wrap entire command in single quotes
|
|
1156
1156
|
- run: 'echo "Selected: {{mode}}"'
|
|
@@ -1158,7 +1158,7 @@ When using `{{variable}}` in commands, follow these rules to avoid parsing error
|
|
|
1158
1158
|
|
|
1159
1159
|
❌ **Problematic patterns:**
|
|
1160
1160
|
```yaml
|
|
1161
|
-
# DO NOT:
|
|
1161
|
+
# DO NOT: unquoted value with colons before variables
|
|
1162
1162
|
- run: echo "mode: {{mode}}" # ❌ YAML parsing error!
|
|
1163
1163
|
|
|
1164
1164
|
# FIX: Wrap entire command in single quotes
|
|
@@ -1171,7 +1171,7 @@ When using `{{variable}}` in commands, follow these rules to avoid parsing error
|
|
|
1171
1171
|
- prompt:
|
|
1172
1172
|
message: "Enter project name:"
|
|
1173
1173
|
as: projectName
|
|
1174
|
-
- run: echo "Building {{projectName}}..."
|
|
1174
|
+
- run: 'echo "Building {{projectName}}..."'
|
|
1175
1175
|
|
|
1176
1176
|
# Use choice variable
|
|
1177
1177
|
- choose:
|
|
@@ -1180,10 +1180,11 @@ When using `{{variable}}` in commands, follow these rules to avoid parsing error
|
|
|
1180
1180
|
- id: dev
|
|
1181
1181
|
label: "Development"
|
|
1182
1182
|
as: env
|
|
1183
|
-
- run: echo "Deploying to {{env}}"
|
|
1183
|
+
- run: 'echo "Deploying to {{env}}"'
|
|
1184
|
+
|
|
1184
1185
|
|
|
1185
1186
|
# Multiple variables
|
|
1186
|
-
- run: echo "Building {{projectName}} version {{version}} for {{env}}"
|
|
1187
|
+
- run: 'echo "Building {{projectName}} version {{version}} for {{env}}"'
|
|
1187
1188
|
```
|
|
1188
1189
|
|
|
1189
1190
|
**Behavior:**
|
|
@@ -1204,7 +1205,7 @@ shell: [bash, -c] # Optional: Use bash for all steps (default: user's current s
|
|
|
1204
1205
|
|
|
1205
1206
|
steps:
|
|
1206
1207
|
# 1. Simple command
|
|
1207
|
-
- run: echo "Starting workflow..."
|
|
1208
|
+
- run: 'echo "Starting workflow..."'
|
|
1208
1209
|
|
|
1209
1210
|
# 2. User choice with variable storage
|
|
1210
1211
|
- choose:
|
|
@@ -1230,12 +1231,12 @@ steps:
|
|
|
1230
1231
|
- when:
|
|
1231
1232
|
var:
|
|
1232
1233
|
env: dev
|
|
1233
|
-
run: echo "Deploying to development..."
|
|
1234
|
+
run: 'echo "Deploying to development..."'
|
|
1234
1235
|
|
|
1235
1236
|
- when:
|
|
1236
1237
|
var:
|
|
1237
1238
|
env: staging
|
|
1238
|
-
run: echo "Deploying to staging..."
|
|
1239
|
+
run: 'echo "Deploying to staging..."'
|
|
1239
1240
|
|
|
1240
1241
|
# 5. Complex condition (all)
|
|
1241
1242
|
- when:
|
|
@@ -1244,22 +1245,22 @@ steps:
|
|
|
1244
1245
|
env: prod
|
|
1245
1246
|
- var: deployReason
|
|
1246
1247
|
- file: ./dist
|
|
1247
|
-
run: echo "Production deployment approved"
|
|
1248
|
+
run: 'echo "Production deployment approved"'
|
|
1248
1249
|
|
|
1249
1250
|
# 6. Parallel execution
|
|
1250
1251
|
- parallel:
|
|
1251
|
-
- run: npm run test:unit
|
|
1252
|
-
- run: npm run test:integration
|
|
1253
|
-
- run: npm run lint
|
|
1252
|
+
- run: 'npm run test:unit'
|
|
1253
|
+
- run: 'npm run test:integration'
|
|
1254
|
+
- run: 'npm run lint'
|
|
1254
1255
|
|
|
1255
1256
|
# 6.5. Step-level shell override
|
|
1256
|
-
- run: echo "Running with zsh"
|
|
1257
|
+
- run: 'echo "Running with zsh"'
|
|
1257
1258
|
shell: [zsh, -c] # Override workflow shell for this step only
|
|
1258
1259
|
|
|
1259
1260
|
# 7. File existence check
|
|
1260
1261
|
- when:
|
|
1261
1262
|
file: ./test-results
|
|
1262
|
-
run: echo "Tests completed"
|
|
1263
|
+
run: 'echo "Tests completed"'
|
|
1263
1264
|
|
|
1264
1265
|
# 8. Combined condition (any)
|
|
1265
1266
|
- when:
|
|
@@ -1268,7 +1269,7 @@ steps:
|
|
|
1268
1269
|
env: staging
|
|
1269
1270
|
- var:
|
|
1270
1271
|
env: prod
|
|
1271
|
-
run: echo "Deploying to server..."
|
|
1272
|
+
run: 'echo "Deploying to server..."'
|
|
1272
1273
|
|
|
1273
1274
|
# 9. Negation
|
|
1274
1275
|
- when:
|
|
@@ -1278,7 +1279,7 @@ steps:
|
|
|
1278
1279
|
message: "Build output not found"
|
|
1279
1280
|
|
|
1280
1281
|
# 10. Variable substitution
|
|
1281
|
-
- run: echo "Deploying {{projectName}} version {{version}} to {{env}}"
|
|
1282
|
+
- run: 'echo "Deploying {{projectName}} version {{version}} to {{env}}"'
|
|
1282
1283
|
```
|
|
1283
1284
|
|
|
1284
1285
|
---
|
package/dist/index.cjs
CHANGED
|
@@ -12,7 +12,7 @@ ${r.stack??""}
|
|
|
12
12
|
`).forEach(o=>{o.trim()&&console.log(`| ${o}`)}):console.log(e)}displayBufferedOutput(e,t,o=!1,n,s){let i=Le(t,n,s,{borderColor:"cyan",isNested:o});this.formatNestedOutput(i,o),e.stdout.forEach(l=>{let c=Oe(l,o);process.stdout.write(`${c}
|
|
13
13
|
`)}),e.stderr.forEach(l=>{let c=Oe(l,o);process.stderr.write(`${c}
|
|
14
14
|
`)});let a=K(e.success,o);console.log(a)}};function no(r,e,t){if(e.hasVariable(r))return e.getVariable(r)??t;if(e.hasFact(r)){let o=e.getFact(r);return typeof o=="string"?o:String(o)}return e.hasChoice(r)?e.getChoice(r)??t:t}function ye(r,e){let t=/\{\{\s*(\w+)\s*\}\}/g;return r.replace(t,(o,n)=>no(n,e,o))}var be=class r{state;constructor(){this.state={facts:new Map,choices:new Map,variables:new Map,stepResults:new Map,lastStepIndex:-1}}hasFact(e){return this.state.facts.has(e)}getFact(e){return this.state.facts.get(e)}setFact(e,t){this.state.facts.set(e,t)}getFactStatus(e){if(!this.hasFact(e))return"pending";let t=this.getFact(e);return t===!1||t==="failed"?"failed":"ready"}getAllFacts(){return new Map(this.state.facts)}hasChoice(e){return this.state.choices.has(e)}getChoice(e){return this.state.choices.get(e)}setChoice(e,t){this.state.choices.set(e,t)}hasVariable(e){return this.state.variables.has(e)}getVariable(e){return this.state.variables.get(e)}setVariable(e,t){this.state.variables.set(e,t)}getAllVariables(){return new Map(this.state.variables)}setStepResult(e,t,o){this.state.stepResults.set(e,{success:t,exitCode:o}),this.state.lastStepIndex=e}getStepResult(e){return this.state.stepResults.get(e)}getLastStepResult(){if(this.state.lastStepIndex!==-1)return this.state.stepResults.get(this.state.lastStepIndex)}clone(){let e=new r;return e.state.facts=new Map(this.state.facts),e.state.choices=new Map(this.state.choices),e.state.variables=new Map(this.state.variables),e.state.stepResults=new Map(this.state.stepResults),e.state.lastStepIndex=this.state.lastStepIndex,e}};var re=class r{static PARALLEL_STEP_INDEX_MULTIPLIER=1e3;workspace;taskRunner;choicePrompt;textPrompt;baseDir;globalShell;constructor(){this.workspace=new be,this.taskRunner=new we,this.choicePrompt=new I,this.textPrompt=new me}resolveBaseDir(e){if(e.baseDir)if((0,q.isAbsolute)(e.baseDir))this.baseDir=e.baseDir;else if(e._filePath){let t=(0,q.dirname)(e._filePath);this.baseDir=(0,q.resolve)(t,e.baseDir)}else this.baseDir=(0,q.resolve)(process.cwd(),e.baseDir)}createStepContext(e,t){let o={workspace:this.workspace,stepIndex:e};return t._lineNumbers&&(o.lineNumber=t._lineNumbers.get(e)),t._fileName&&(o.fileName=t._fileName),o}evaluateStepCondition(e){return e.when?new ee(this.workspace).evaluate(e.when):!0}calculateBaseStepIndex(e){return e.branchIndex===void 0?e.stepIndex:Math.floor(e.stepIndex/r.PARALLEL_STEP_INDEX_MULTIPLIER)}isRunStep(e){return"run"in e}async execute(e,t){if(t?.profileVars&&Object.keys(t.profileVars).length>0)for(let[a,l]of Object.entries(t.profileVars))this.workspace.setVariable(a,l);this.resolveBaseDir(e),this.globalShell=e.shell;let o=new ge,n=Date.now();for(let a=0;a<e.steps.length;a++){let l=e.steps[a],c=this.createStepContext(a,e),f=!!l.when;if(this.evaluateStepCondition(l)){o.recordStart();try{let g=await this.executeStep(l,c,!1,f);this.handleStepResult(l,c,a,g,o)}catch(g){throw this.handleStepError(l,c,a,g,o),g}}}let s=Date.now()-n,i=Q(s);console.log(ut.default.cyan(`
|
|
15
|
-
Total execution time: ${i}`)),await o.save(),o.reset()}isStepSuccessful(e,t){return"run"in t?typeof e=="boolean"?e:e&&typeof e=="object"&&"success"in e?e.success:!1:!0}handleStepResult(e,t,o,n,s){let i=this.isRunStep(e)?(()=>{let c=this.workspace.getStepResult(o);return c?c.success:!0})():this.isStepSuccessful(n,e),a=i?"success":"failure",l=s.recordEnd(e,t,n,a);if(!this.isRunStep(e)){let c=K(i,!1,l);console.log(c)}if(this.isRunStep(e)){if(e.continue===!1){let c=t.lineNumber?` (line ${t.lineNumber})`:"",f=i?`Step ${o}${c} completed, but workflow stopped due to continue: false`:`Step ${o}${c} failed`;throw new Error(f)}if(!i&&e.continue!==!0){let c=t.lineNumber?` (line ${t.lineNumber})`:"";throw new Error(`Step ${o}${c} failed`)}}}handleStepError(e,t,o,n,s){this.workspace.setStepResult(o,!1);let i=n instanceof Error?n.message:String(n),a={success:!1,stdout:[],stderr:[i]};s.recordEnd(e,t,a,"failure")}fixMalformedStep(e){let o=e;return"choose"in e&&o.choose===null&&"message"in e&&"options"in e?{choose:{message:o.message,options:o.options,as:o.as},when:o.when}:"prompt"in e&&o.prompt===null&&"message"in e&&"as"in e?{prompt:{message:o.message,as:o.as,default:o.default},when:o.when}:e}async executeStep(e,t,o=!1,n=!1){if(e=this.fixMalformedStep(e),"run"in e){let s=await this.executeRunStep(e,t,o,n);return o&&typeof s=="object"&&"stdout"in s,s}if("choose"in e){await this.executeChooseStep(e,t);return}if("prompt"in e){await this.executePromptStep(e,t);return}if("parallel"in e){await this.executeParallelStep(e,t);return}if("fail"in e){await this.executeFailStep(e,t);return}}async executeSingleRun(e,t,o=!1,n=!1){let s=this.calculateBaseStepIndex(t),i=ye(e.run,this.workspace),a=e.shell??this.globalShell,l=e.retry??0,c=l==="Infinity"||l===1/0,f=typeof l=="number"?l:0,g=e.timeout,h=!1,d=0;for(;c||d<=f;){let w=await this.taskRunner.run(i,s,i,t.branchIndex,o,n,t.lineNumber,t.fileName,this.baseDir,g,a),b=typeof w=="boolean"?w:w.success;if(h=w,b||!c&&d>=f)break;if(d++,c||d<=f){let v=Math.min(1e3*Math.pow(2,d-1),1e4);await new Promise(E=>setTimeout(E,v))}}return h}async executeRunStep(e,t,o=!1,n=!1){let s=await this.executeSingleRun({run:e.run,timeout:e.timeout,retry:e.retry,shell:e.shell},t,o,n),i=typeof s=="boolean"?s:s.success;if(this.workspace.setStepResult(t.stepIndex,i),i||!e.onError)return s;let a={run:e.onError.run,timeout:e.onError.timeout,retry:e.onError.retry,onError:e.onError.onError??void 0};return await this.executeRunChain(a,t,o,n)}async executeRunChain(e,t,o,n){let s=await this.executeSingleRun({run:e.run,timeout:e.timeout,retry:e.retry,shell:void 0},t,o,n);return(typeof s=="boolean"?s:s.success)||!e.onError?s:this.executeRunChain(e.onError,t,o,n)}async executeChooseStep(e,t){let o=e.choose.as,n=e.choose.options.map(a=>a.id);if(o&&this.workspace.hasVariable(o)){let a=this.workspace.getVariable(o)??"";if(n.includes(a)){this.workspace.setChoice(a,a),this.workspace.setStepResult(t.stepIndex,!0);return}}let s=await this.choicePrompt.prompt(e.choose.message,e.choose.options);if(!s?.id)throw new Error(`Invalid choice result: ${JSON.stringify(s)}`);let i=o??s.id;this.workspace.setChoice(s.id,s.id),this.workspace.setVariable(i,s.id),this.workspace.setStepResult(t.stepIndex,!0)}async executePromptStep(e,t){let o=e.prompt.as;if(this.workspace.hasVariable(o)){let a=this.workspace.getVariable(o)??"";this.workspace.setFact(o,a),this.workspace.setStepResult(t.stepIndex,!0);return}let n=ye(e.prompt.message,this.workspace),s=e.prompt.default?ye(e.prompt.default,this.workspace):void 0,i=await this.textPrompt.prompt(n,s);this.workspace.setVariable(o,i),this.workspace.setFact(o,i),this.workspace.setStepResult(t.stepIndex,!0)}createParallelContexts(e,t){return e.parallel.map((o,n)=>({workspace:this.workspace.clone(),stepIndex:t.stepIndex*r.PARALLEL_STEP_INDEX_MULTIPLIER+n,branchIndex:n,lineNumber:t.lineNumber,fileName:t.fileName}))}getBranchDisplayName(e,t){return"run"in e?e.run:"choose"in e?`Choose: ${e.choose.message}`:"prompt"in e?`Prompt: ${e.prompt.message}`:"fail"in e?`Fail: ${e.fail.message}`:`Branch ${t+1}`}async executeParallelBranches(e,t){let o=[],n=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],s=0;for(let c=0;c<e.length;c++){let f=e[c],g=t[c];if(f.when&&!new ee(g.workspace).evaluate(f.when))continue;let h=this.getBranchDisplayName(f,c);o.push({index:c,name:h,status:"pending"})}let i=setInterval(()=>{s=(s+1)%n.length,this.updateParallelBranchesDisplay(o,n[s])},100),a=o.map(async c=>{let{index:f}=c,g=e[f],h=t[f];c.status="running";try{let d=await this.executeStep(g,h,!0);return c.status="success",this.updateParallelBranchesDisplay(o,n[s]),{index:f,result:d,context:h}}catch(d){h.workspace.setStepResult(h.stepIndex,!1);let w=d instanceof Error?d.message:String(d);return c.status="failed",c.error=w,this.updateParallelBranchesDisplay(o,n[s]),{index:f,error:d,context:h}}}),l=await Promise.all(a);return clearInterval(i),this.updateParallelBranchesDisplay(o,"",!0),Se.default.done(),l}updateParallelBranchesDisplay(e,t,o=!1){let n=e.map(s=>{let i=s.index+1,a="",l="";switch(s.status){case"pending":a="\u25CB",l=`Branch ${i}: ${s.name} - Pending`;break;case"running":a=t,l=`Branch ${i}: ${s.name} - Running...`;break;case"success":a="\u2713",l=`Branch ${i}: ${s.name} - Completed`;break;case"failed":a="\u2717",l=`Branch ${i}: ${s.name} - Failed${s.error?`: ${s.error}`:""}`;break}return`${a} ${l}`});o?(0,Se.default)(n.join(`
|
|
15
|
+
Total execution time: ${i}`)),await o.save(),o.reset()}isStepSuccessful(e,t){return"run"in t?typeof e=="boolean"?e:e&&typeof e=="object"&&"success"in e?e.success:!1:!0}handleStepResult(e,t,o,n,s){let i=this.isRunStep(e)?(()=>{let c=this.workspace.getStepResult(o);return c?c.success:!0})():this.isStepSuccessful(n,e),a=i?"success":"failure",l=s.recordEnd(e,t,n,a);if(!this.isRunStep(e)){let c=K(i,!1,l);console.log(c)}if(this.isRunStep(e)){if(e.continue===!1){let c=t.lineNumber?` (line ${t.lineNumber})`:"",f=i?`Step ${o}${c} completed, but workflow stopped due to continue: false`:`Step ${o}${c} failed`;throw new Error(f)}if(!i&&e.continue!==!0){let c=t.lineNumber?` (line ${t.lineNumber})`:"";throw new Error(`Step ${o}${c} failed`)}}}handleStepError(e,t,o,n,s){this.workspace.setStepResult(o,!1);let i=n instanceof Error?n.message:String(n),a={success:!1,stdout:[],stderr:[i]};s.recordEnd(e,t,a,"failure")}fixMalformedStep(e){let o=e;return"choose"in e&&o.choose===null&&"message"in e&&"options"in e?{choose:{message:o.message,options:o.options,as:o.as},when:o.when}:"prompt"in e&&o.prompt===null&&"message"in e&&"as"in e?{prompt:{message:o.message,as:o.as,default:o.default},when:o.when}:e}async executeStep(e,t,o=!1,n=!1){if(e=this.fixMalformedStep(e),"run"in e){let s=await this.executeRunStep(e,t,o,n);return o&&typeof s=="object"&&"stdout"in s,s}if("choose"in e){await this.executeChooseStep(e,t);return}if("prompt"in e){await this.executePromptStep(e,t);return}if("parallel"in e){await this.executeParallelStep(e,t);return}if("fail"in e){await this.executeFailStep(e,t);return}}async executeSingleRun(e,t,o=!1,n=!1){let s=this.calculateBaseStepIndex(t),i=ye(e.run.trim(),this.workspace),a=e.shell??this.globalShell,l=e.retry??0,c=l==="Infinity"||l===1/0,f=typeof l=="number"?l:0,g=e.timeout,h=!1,d=0;for(;c||d<=f;){let w=await this.taskRunner.run(i,s,i,t.branchIndex,o,n,t.lineNumber,t.fileName,this.baseDir,g,a),b=typeof w=="boolean"?w:w.success;if(h=w,b||!c&&d>=f)break;if(d++,c||d<=f){let v=Math.min(1e3*Math.pow(2,d-1),1e4);await new Promise(E=>setTimeout(E,v))}}return h}async executeRunStep(e,t,o=!1,n=!1){let s=await this.executeSingleRun({run:e.run,timeout:e.timeout,retry:e.retry,shell:e.shell},t,o,n),i=typeof s=="boolean"?s:s.success;if(this.workspace.setStepResult(t.stepIndex,i),i||!e.onError)return s;let a={run:e.onError.run,timeout:e.onError.timeout,retry:e.onError.retry,onError:e.onError.onError??void 0};return await this.executeRunChain(a,t,o,n)}async executeRunChain(e,t,o,n){let s=await this.executeSingleRun({run:e.run,timeout:e.timeout,retry:e.retry,shell:void 0},t,o,n);return(typeof s=="boolean"?s:s.success)||!e.onError?s:this.executeRunChain(e.onError,t,o,n)}async executeChooseStep(e,t){let o=e.choose.as,n=e.choose.options.map(a=>a.id);if(o&&this.workspace.hasVariable(o)){let a=this.workspace.getVariable(o)??"";if(n.includes(a)){this.workspace.setChoice(a,a),this.workspace.setStepResult(t.stepIndex,!0);return}}let s=await this.choicePrompt.prompt(e.choose.message,e.choose.options);if(!s?.id)throw new Error(`Invalid choice result: ${JSON.stringify(s)}`);let i=o??s.id;this.workspace.setChoice(s.id,s.id),this.workspace.setVariable(i,s.id),this.workspace.setStepResult(t.stepIndex,!0)}async executePromptStep(e,t){let o=e.prompt.as;if(this.workspace.hasVariable(o)){let a=this.workspace.getVariable(o)??"";this.workspace.setFact(o,a),this.workspace.setStepResult(t.stepIndex,!0);return}let n=ye(e.prompt.message,this.workspace),s=e.prompt.default?ye(e.prompt.default,this.workspace):void 0,i=await this.textPrompt.prompt(n,s);this.workspace.setVariable(o,i),this.workspace.setFact(o,i),this.workspace.setStepResult(t.stepIndex,!0)}createParallelContexts(e,t){return e.parallel.map((o,n)=>({workspace:this.workspace.clone(),stepIndex:t.stepIndex*r.PARALLEL_STEP_INDEX_MULTIPLIER+n,branchIndex:n,lineNumber:t.lineNumber,fileName:t.fileName}))}getBranchDisplayName(e,t){return"run"in e?e.run:"choose"in e?`Choose: ${e.choose.message}`:"prompt"in e?`Prompt: ${e.prompt.message}`:"fail"in e?`Fail: ${e.fail.message}`:`Branch ${t+1}`}async executeParallelBranches(e,t){let o=[],n=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],s=0;for(let c=0;c<e.length;c++){let f=e[c],g=t[c];if(f.when&&!new ee(g.workspace).evaluate(f.when))continue;let h=this.getBranchDisplayName(f,c);o.push({index:c,name:h,status:"pending"})}let i=setInterval(()=>{s=(s+1)%n.length,this.updateParallelBranchesDisplay(o,n[s])},100),a=o.map(async c=>{let{index:f}=c,g=e[f],h=t[f];c.status="running";try{let d=await this.executeStep(g,h,!0);return c.status="success",this.updateParallelBranchesDisplay(o,n[s]),{index:f,result:d,context:h}}catch(d){h.workspace.setStepResult(h.stepIndex,!1);let w=d instanceof Error?d.message:String(d);return c.status="failed",c.error=w,this.updateParallelBranchesDisplay(o,n[s]),{index:f,error:d,context:h}}}),l=await Promise.all(a);return clearInterval(i),this.updateParallelBranchesDisplay(o,"",!0),Se.default.done(),l}updateParallelBranchesDisplay(e,t,o=!1){let n=e.map(s=>{let i=s.index+1,a="",l="";switch(s.status){case"pending":a="\u25CB",l=`Branch ${i}: ${s.name} - Pending`;break;case"running":a=t,l=`Branch ${i}: ${s.name} - Running...`;break;case"success":a="\u2713",l=`Branch ${i}: ${s.name} - Completed`;break;case"failed":a="\u2717",l=`Branch ${i}: ${s.name} - Failed${s.error?`: ${s.error}`:""}`;break}return`${a} ${l}`});o?(0,Se.default)(n.join(`
|
|
16
16
|
`)):(0,Se.default)(n.join(`
|
|
17
17
|
`))}displayParallelResults(e,t,o){let n=!0,s=!1;console.log("");for(let a of e){if(!a)continue;s=!0;let{index:l,result:c,error:f,context:g}=a;if(f){n=!1;let h=`Branch ${l+1} failed: ${f instanceof Error?f.message:String(f)}`,d=ce(h);console.error(d)}else if(c&&typeof c=="object"&&"stdout"in c){let h=c;if(n=n&&h.success,h.stdout.length>0||h.stderr.length>0||!h.success){let d=t[l],w=this.getBranchDisplayName(d,l);this.taskRunner.displayBufferedOutput(h,w,!1,g.lineNumber,g.fileName)}}}s||console.log("\u26A0\uFE0F All parallel branches were skipped (conditions not met)");let i=st(n);return console.log(i),n}mergeParallelResults(e){for(let t of e){let o=t.workspace.getAllFacts(),n=t.workspace.getAllVariables();for(let[s,i]of o)this.workspace.setFact(s,i);for(let[s,i]of n)this.workspace.setVariable(s,i)}}countExecutableBranches(e,t){let o=0;for(let n=0;n<e.length;n++){let s=e[n],i=t[n];s.when&&!new ee(i.workspace).evaluate(s.when)||o++}return o}async executeParallelStep(e,t){let o=this.createParallelContexts(e,t),n=this.countExecutableBranches(e.parallel,o),s=nt(n);console.log(s);let i=await this.executeParallelBranches(e.parallel,o),a=this.displayParallelResults(i,e.parallel,t);if(this.workspace.setStepResult(t.stepIndex,a),!a){let l=t.lineNumber?` (line ${t.lineNumber})`:"";throw new Error(`Parallel step ${t.stepIndex}${l} failed: one or more branches failed`)}this.mergeParallelResults(o)}async executeFailStep(e,t){let o=new Error(e.fail.message);throw o.stack=void 0,o}};var ht=require("yaml"),He=require("zod");var u=require("zod"),so=u.z.object({file:u.z.string()}),io=u.z.object({var:u.z.union([u.z.string(),u.z.record(u.z.string(),u.z.string())]).optional(),has:u.z.string().optional()}),ao=u.z.object({status:u.z.object({fact:u.z.string(),is:u.z.enum(["ready","failed","pending"])})}),lo=u.z.object({step:u.z.object({success:u.z.boolean()}).optional(),last_step:u.z.enum(["success","failure"]).optional()}),co=u.z.object({choice:u.z.string()}),uo=u.z.union([so,co,io,ao,lo]),A=u.z.lazy(()=>u.z.union([uo,u.z.object({all:u.z.array(A)}),u.z.object({any:u.z.array(A)}),u.z.object({not:A})])),pt=u.z.lazy(()=>u.z.object({run:u.z.string(),timeout:u.z.number().optional(),retry:u.z.union([u.z.number(),u.z.literal("Infinity")]).optional(),onError:pt.optional()})),dt=u.z.object({run:u.z.string(),when:A.optional(),timeout:u.z.number().optional(),retry:u.z.union([u.z.number(),u.z.literal("Infinity")]).optional(),shell:u.z.array(u.z.string()).min(1,"shell must have at least one element").optional(),continue:u.z.boolean().optional(),onError:pt.optional()}),po=u.z.object({choose:u.z.object({message:u.z.string(),options:u.z.array(u.z.object({id:u.z.string(),label:u.z.string()})),as:u.z.string().optional()}),when:A.optional()}),fo=u.z.object({prompt:u.z.object({message:u.z.string(),as:u.z.string(),default:u.z.string().optional(),validate:u.z.string().optional()}),when:A.optional()});function ft(r){if(!r||typeof r!="object")return{found:!1};let e=r;if("choose"in e)return{found:!0,type:"choose"};if("prompt"in e)return{found:!0,type:"prompt"};if("parallel"in e&&Array.isArray(e.parallel))for(let t of e.parallel){let o=ft(t);if(o.found)return o}return{found:!1}}var mt=u.z.lazy(()=>u.z.union([dt,u.z.object({parallel:u.z.array(u.z.lazy(()=>mt)),when:A.optional()}),u.z.object({fail:u.z.object({message:u.z.string()}),when:A.optional()})]).superRefine((r,e)=>{let t=ft(r);t.found&&e.addIssue({code:u.z.ZodIssueCode.custom,message:`'${t.type}' step is not allowed inside 'parallel' block (user input cannot run in parallel)`})})),mo=u.z.lazy(()=>u.z.union([dt,po,fo,u.z.object({parallel:u.z.array(mt),when:A.optional()}),u.z.object({fail:u.z.object({message:u.z.string()}),when:A.optional()})])),ho=u.z.object({name:u.z.string().min(1,"Profile name must be non-empty"),var:u.z.record(u.z.string(),u.z.union([u.z.string(),u.z.number(),u.z.boolean()]).transform(String))}),go=u.z.object({name:u.z.string().optional(),baseDir:u.z.string().optional(),shell:u.z.array(u.z.string()).min(1,"shell must have at least one element").optional(),profiles:u.z.array(ho).optional(),steps:u.z.array(mo).min(1,"Workflow must have at least one step")});function Be(r){return go.parse(r)}function gt(r,e){let t=r.path;if(r.code==="custom"){let n=We(t);return` - ${r.message}${n}`}if(r.message==="Invalid input"){let n=We(t),s=wo(t,e);return s?` - ${s}${n}`:` - Invalid step type${n}`}let o=We(t);return` - ${r.message}${o}`}function We(r){if(r.length===0)return"";let e=[];for(let t=0;t<r.length;t++){let o=r[t],n=r[t+1];o==="steps"&&typeof n=="number"?(e.push(`step ${n+1}`),t++):o==="parallel"&&typeof n=="number"?(e.push(`parallel branch ${n+1}`),t++):typeof o=="string"&&o!=="steps"&&o!=="parallel"&&e.push(o)}return e.length>0?` (${e.join(" \u2192 ")})`:""}function k(r,e,t){let o=t?`
|
|
18
18
|
Reason: ${t}`:"";throw new Error(`Invalid workflow structure:
|
|
@@ -48,7 +48,7 @@ ${n}`)}throw o}}extractStepLineNumbers(e){let t=new Map,o=e.split(`
|
|
|
48
48
|
`))}}stop(){for(let e of this.tasks.values())e.stop();this.tasks.clear()}async stopDaemon(){let e=await $();if(!e.running||!e.pid)return!1;let t=e.pid;try{if(process.kill(t,"SIGTERM"),await new Promise(o=>setTimeout(o,1e3)),await H()){try{process.kill(t,"SIGKILL")}catch{}await new Promise(o=>setTimeout(o,500))}return await ae(),!0}catch{return await ae(),!1}}};var Ot=require("child_process"),Ee=require("fs"),Ft=require("fs/promises"),R=require("path"),Re=y(require("boxen"),1),m=y(require("chalk"),1),Bt=require("commander"),Pe=y(require("dayjs"),1),Ce=y(require("inquirer"),1),pe=y(require("log-update"),1),Wt=y(require("node-cron"),1);le();var Et=require("fs/promises"),Rt=require("path"),Pt=require("yaml"),Ct=require("zod");var C=require("zod"),vo=C.z.object({name:C.z.string().min(1,"Schedule name must be non-empty"),cron:C.z.string().min(1,"Cron expression is required"),workflow:C.z.string().min(1,"Workflow path is required"),baseDir:C.z.string().optional(),timezone:C.z.union([C.z.string(),C.z.number()]).transform(String).optional(),silent:C.z.boolean().optional(),profile:C.z.string().optional()}),ko=C.z.object({schedules:C.z.array(vo).min(1,"Schedule file must have at least one schedule")});function $t(r){return ko.parse(r)}async function Dt(r){let e=await(0,Et.readFile)(r,"utf-8"),t=(0,Rt.extname)(r).toLowerCase(),o;try{if(t===".yaml"||t===".yml")o=(0,Pt.parse)(e);else if(t===".json")o=JSON.parse(e);else throw new Error(`Unsupported file format: ${t}. Use .yaml, .yml, or .json`)}catch(n){if(n instanceof Error&&n.message.startsWith("Unsupported"))throw n;let s=t===".json"?"JSON":"YAML";throw new Error(`Invalid ${s} format: ${n instanceof Error?n.message:String(n)}`)}try{return $t(o)}catch(n){if(n instanceof Ct.ZodError){let s=n.issues.map(i=>` - ${i.message} (${i.path.join(".")})`).join(`
|
|
49
49
|
`);throw new Error(`Invalid schedule file structure:
|
|
50
50
|
${s}`)}throw n}}var Tt=y(require("boxen"),1),S=y(require("chalk"),1),It=y(require("cronstrue"),1),Ye=y(require("dayjs"),1),Je=y(require("node-cron"),1);function qe(r){try{return It.default.toString(r)}catch{return null}}function xo(r){if(!Je.default.validate(r.cron))return null;try{let e={},t=ke(r.timezone);t&&(e.timezone=t);let o=Je.default.createTask(r.cron,()=>{},e),n=o.getNextRun();return o.destroy(),n}catch{return null}}function G(r,e){let t=r,{daemonRunning:o,emphasizeState:n}=e,s=t.enabled?n?S.default.bold.green("ENABLED"):S.default.green("enabled"):n?S.default.bold.gray("DISABLED"):S.default.gray("disabled"),i=o&&t.enabled,a=i?S.default.green("\u25CF active"):S.default.gray("\u25CB inactive"),l=n?t.enabled?S.default.bold.green(" [ENABLED]"):S.default.bold.gray(" [DISABLED]"):"",c=S.default.bold(t.name??t.workflowPath),f=xo(t),g=f?(0,Ye.default)(f).format("YYYY-MM-DD HH:mm:ss"):S.default.dim("\u2014"),h=t.lastRun?(0,Ye.default)(t.lastRun).format("YYYY-MM-DD HH:mm:ss"):S.default.dim("never"),d=qe(t.cron),w=t.timezone?t.timezone.startsWith("+")||t.timezone.startsWith("-")?`UTC${t.timezone}`:`UTC+${t.timezone}`:null,b=d?`${t.cron} ${S.default.dim(`\u2192 ${d}`)}`:t.cron,v=[[S.default.gray("Enabled"),s],[S.default.gray("Cron"),b],...w?[[S.default.gray("Timezone"),w]]:[],[S.default.gray("Workflow"),t.workflowPath],...t.profile?[[S.default.gray("Profile"),S.default.cyan(t.profile)]]:[],...t.silent?[[S.default.gray("Silent"),S.default.yellow("yes")]]:[],[S.default.gray("Last run"),h],[S.default.gray("Next run"),g]],E=[`${c} ${a}${l}`,...v.map(([B,W])=>` ${B.padEnd(10)} ${W}`)].join(`
|
|
51
|
-
`);return(0,Tt.default)(E,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:i?"green":"gray"})}var V=require("fs"),P=require("path"),Ge=require("url"),Mt={};function Nt(){console.log=()=>{},console.error=()=>{},console.warn=()=>{},console.info=()=>{},process.stdout.write=()=>!0,process.stderr.write=()=>!0}function jt(){return"0.3.
|
|
51
|
+
`);return(0,Tt.default)(E,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:i?"green":"gray"})}var V=require("fs"),P=require("path"),Ge=require("url"),Mt={};function Nt(){console.log=()=>{},console.error=()=>{},console.warn=()=>{},console.info=()=>{},process.stdout.write=()=>!0,process.stderr.write=()=>!0}function jt(){return"0.3.5"}function $e(r){let e=r?(0,P.resolve)(r):process.cwd(),t=50,o=0;for(;o<t;){let n=(0,P.resolve)(e,"tp");try{if((0,V.existsSync)(n)&&(0,V.statSync)(n).isDirectory())return n}catch{}let s=(0,P.dirname)(e);if(s===e)break;e=s,o++}return null}function _t(){let r=new Bt.Command("schedule").description("Manage workflow schedules").action(async()=>{await At()});return r.command("add [scheduleFile]").description("Add schedules from a schedule file (YAML or JSON). If no file given, select from nearest tp/schedules directory.").action(async e=>{await $o(e)}),r.command("remove").alias("rm").description("Remove a workflow schedule").action(async()=>{await Eo()}),r.command("remove-all").description("Remove all workflow schedules").action(async()=>{await Mo()}),r.command("list").alias("ls").description("List all workflow schedules").action(async()=>{await At()}),r.command("start").description("Start the scheduler daemon").option("-d, --daemon","Run in background daemon mode").action(async e=>{await Ro(e.daemon??!1)}),r.command("stop").description("Stop the scheduler daemon").action(async()=>{await Po()}),r.command("status").description('View daemon and schedule status (does not start the daemon). In live mode, Ctrl+C only exits the status view; the daemon keeps running if it was started with "tp schedule start -d".').option("-n, --no-follow","Show status once and exit (no live refresh)").action(async e=>{let t=e.follow!==!1;await To(t)}),r.command("toggle").description("Enable or disable a schedule").action(async()=>{await Io()}),r}function Ze(r,e){let t=e.workflow;if((0,R.isAbsolute)(t))return t;let o=e.baseDir?(0,R.resolve)(e.baseDir):(0,R.dirname)(r);return(0,R.resolve)(o,t)}async function $o(r){let e=new j;if(!r){let l=$e();l||(console.error(m.default.red(`
|
|
52
52
|
\u2717 No tp directory found`)),process.exit(1));let c=(0,R.join)(l,"schedules");(0,Ee.existsSync)(c)||(console.error(m.default.red(`
|
|
53
53
|
\u2717 No schedules directory found at ${c}`)),process.exit(1));let g=(await(0,Ft.readdir)(c)).filter(b=>{let v=(0,R.extname)(b).toLowerCase();return[".yaml",".yml",".json"].includes(v)});g.length===0&&(console.error(m.default.red(`
|
|
54
54
|
\u2717 No schedule files found in ${c}`)),process.exit(1));let h=g.map(b=>({id:(0,R.join)(c,b),label:b}));r=(await new I(!0).prompt("Select a schedule file to add",h)).id}let t=(0,R.resolve)(r);(0,Ee.existsSync)(t)||(console.error(`\u2717 File not found: ${t}`),process.exit(1));let o;try{o=await Dt(t)}catch(l){console.error(`\u2717 Failed to parse schedule file: ${l instanceof Error?l.message:String(l)}`),process.exit(1)}let n=o.schedules.filter(l=>!Wt.default.validate(l.cron));if(n.length>0){console.error("\u2717 Invalid cron expression(s):");for(let l of n)console.error(` - ${l.name}: "${l.cron}"`);process.exit(1)}let s=o.schedules.filter(l=>{let c=Ze(t,l);return!(0,Ee.existsSync)(c)});if(s.length>0){console.error("\u2717 Workflow file(s) not found:");for(let l of s){let c=Ze(t,l);console.error(` - ${l.name}: ${l.workflow} (resolved: ${c})`)}process.exit(1)}console.log(`
|
|
@@ -93,7 +93,7 @@ Quick Start:
|
|
|
93
93
|
|
|
94
94
|
1. Create a workflow.yaml or workflow.json file:
|
|
95
95
|
steps:
|
|
96
|
-
- run: echo "Hello, World!"
|
|
96
|
+
- run: 'echo "Hello, World!"'
|
|
97
97
|
- choose:
|
|
98
98
|
message: "Select action:"
|
|
99
99
|
options:
|
|
@@ -103,7 +103,7 @@ Quick Start:
|
|
|
103
103
|
- when:
|
|
104
104
|
var:
|
|
105
105
|
action: build
|
|
106
|
-
run: npm run build
|
|
106
|
+
run: 'npm run build'
|
|
107
107
|
|
|
108
108
|
2. Run it:
|
|
109
109
|
tp run workflow.yaml
|
|
@@ -195,7 +195,7 @@ Please visit manually: ${t}`)),process.exit(1)}});U.addCommand(_t());var jo=[{fi
|
|
|
195
195
|
|
|
196
196
|
# Interactive choice: stored as variable and used in later steps
|
|
197
197
|
steps:
|
|
198
|
-
- run: echo "Hello from task-pipeliner"
|
|
198
|
+
- run: 'echo "Hello from task-pipeliner"'
|
|
199
199
|
- choose:
|
|
200
200
|
message: "Select action:"
|
|
201
201
|
options:
|
|
@@ -204,15 +204,15 @@ steps:
|
|
|
204
204
|
- id: info
|
|
205
205
|
label: "Show info"
|
|
206
206
|
as: action
|
|
207
|
-
- run: echo "You chose: {{ action }}"
|
|
207
|
+
- run: 'echo "You chose: {{ action }}"'
|
|
208
208
|
- when:
|
|
209
209
|
var:
|
|
210
210
|
action: greet
|
|
211
|
-
run: echo "Hi there! Edit tp/workflows
|
|
211
|
+
run: 'echo "Hi there! Edit tp/workflows and run: tp run tp/workflows/example-hello.yaml"'
|
|
212
212
|
- when:
|
|
213
213
|
var:
|
|
214
214
|
action: info
|
|
215
|
-
run: echo "Tip: Use --profile
|
|
215
|
+
run: 'echo "Tip: Use --profile. See example-build.yaml for profiles."'
|
|
216
216
|
`},{filename:"example-build.yaml",content:`name: Example Build (with profiles and choose)
|
|
217
217
|
|
|
218
218
|
# Profiles: run without prompts via "tp run tp/workflows/example-build.yaml --profile Dev"
|
|
@@ -228,7 +228,7 @@ profiles:
|
|
|
228
228
|
label: "prod-build"
|
|
229
229
|
|
|
230
230
|
steps:
|
|
231
|
-
- run: echo "Build workflow started..."
|
|
231
|
+
- run: 'echo "Build workflow started..."'
|
|
232
232
|
- choose:
|
|
233
233
|
message: "Select mode (or run with --profile Dev/Prod to skip):"
|
|
234
234
|
options:
|
|
@@ -237,21 +237,21 @@ steps:
|
|
|
237
237
|
- id: prod
|
|
238
238
|
label: "Production"
|
|
239
239
|
as: mode
|
|
240
|
-
- run: echo "Mode: {{ mode }}"
|
|
240
|
+
- run: 'echo "Mode: {{ mode }}"'
|
|
241
241
|
- prompt:
|
|
242
242
|
message: "Enter build label"
|
|
243
243
|
as: label
|
|
244
244
|
default: "default"
|
|
245
|
-
- run: echo "Label: {{ label }}"
|
|
245
|
+
- run: 'echo "Label: {{ label }}"'
|
|
246
246
|
- when:
|
|
247
247
|
var:
|
|
248
248
|
mode: dev
|
|
249
|
-
run: echo "Dev-only step (e.g. npm run build:dev)"
|
|
249
|
+
run: 'echo "Dev-only step (e.g. npm run build:dev)"'
|
|
250
250
|
- when:
|
|
251
251
|
var:
|
|
252
252
|
mode: prod
|
|
253
|
-
run: echo "Prod-only step (e.g. npm run build)"
|
|
254
|
-
- run: echo "Done. Replace run steps with real commands."
|
|
253
|
+
run: 'echo "Prod-only step (e.g. npm run build)"'
|
|
254
|
+
- run: 'echo "Done. Replace run steps with real commands."'
|
|
255
255
|
`}],Ao=[{filename:"example-daily.yaml",content:`schedules:
|
|
256
256
|
# Runs at 09:00 daily; interactive choose is skipped in scheduled runs (no TTY)
|
|
257
257
|
- name: Daily Hello
|
|
@@ -287,10 +287,9 @@ steps:
|
|
|
287
287
|
\u2717 No tp directory found`)),null;let e=(0,D.join)(r,"workflows");if(!(0,O.existsSync)(e))return console.error(p.default.red(`
|
|
288
288
|
\u2717 No workflows directory found at ${e}`)),null;try{let o=(await(0,F.readdir)(e)).filter(a=>{let l=(0,D.extname)(a).toLowerCase();return[".yaml",".yml",".json"].includes(l)});if(o.length===0)return console.error(p.default.red(`
|
|
289
289
|
\u2717 No workflow files found in ${e}`)),null;let n=await Promise.all(o.map(async a=>{let l=(0,D.join)(e,a);try{let c=ue(l),f=(0,O.readFileSync)(l,"utf-8"),h=c.parse(f).name??"Untitled";return{id:l,label:`${a} - ${h}`}}catch{return{id:l,label:a}}}));return(await new I(!0).prompt("Select a workflow to run",n)).id}catch(t){let o=t instanceof Error?t.message:String(t);return console.error(p.default.red(`
|
|
290
|
-
\u2717 Failed to read tp directory: ${o}`)),null}}function Fo(r){return r.split("/").pop()??r}function Bo(r,e){console.log(`
|
|
291
|
-
`);
|
|
292
|
-
`);console.log((0,Ke.default)(l,{borderStyle:"round",padding:{top:
|
|
293
|
-
`);console.log((0,Ke.default)(l,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:1,left:0,right:0},borderColor:r.status==="success"?"green":"red"})),Vo(r.output)&&zo(r.output)}function _o(r){return"run"in r?"Run":"choose"in r?"Choose":"prompt"in r?"Prompt":"parallel"in r?"Parallel":"fail"in r?"Fail":"Unknown"}function Ho(r){return"run"in r?`Command: ${p.default.yellow(r.run)}`:"choose"in r?`Message: ${p.default.yellow(r.choose.message)}`:"prompt"in r?`Message: ${p.default.yellow(r.prompt.message)} | Variable: ${p.default.cyan(r.prompt.as)}`:"parallel"in r?`Parallel execution with ${r.parallel.length} branches`:"fail"in r?`Error: ${p.default.red(r.fail.message)}`:"Unknown step type"}function Vo(r){return typeof r=="object"&&r!==null&&"success"in r&&"stdout"in r&&"stderr"in r}function zo(r){if(r.stdout.length>0){let e=r.stdout.map(t=>p.default.gray(` ${t}`)).join(`
|
|
290
|
+
\u2717 Failed to read tp directory: ${o}`)),null}}function Fo(r){return r.split("/").pop()??r}function Bo(r,e){console.log();let t=r.records.reduce((c,f)=>c+f.duration,0),o=r.records.filter(c=>c.status==="success").length,n=r.records.filter(c=>c.status==="failure").length,s=(0,Jt.default)(r.initialTimestamp).format("YYYY-MM-DD HH:mm:ss"),a=Q(t),l=[p.default.bold("Workflow Execution History"),"",`${p.default.cyan("File:")} ${e}`,`${p.default.cyan("Started:")} ${s}`,`${p.default.cyan("Total Duration:")} ${a}`,`${p.default.cyan("Total Steps:")} ${r.records.length}`,`${p.default.green("\u2713 Successful:")} ${o}`,n>0?`${p.default.red("\u2717 Failed:")} ${n}`:""].filter(Boolean).join(`
|
|
291
|
+
`);console.log((0,Ke.default)(l,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"cyan"})),r.records.forEach((c,f)=>{Wo(c,f+1,r.records.length)}),console.log()}function Wo(r,e,t){let o=_o(r.step),n=Ho(r.step),s=r.status==="success"?p.default.green("\u2713"):p.default.red("\u2717"),i=r.status==="success"?p.default.green("Success"):p.default.red("Failed"),a=Q(r.duration),l=[`${s} ${p.default.bold(`Step ${e}/${t}`)} - ${p.default.cyan(o)}`,`${p.default.gray("Duration:")} ${a} | ${p.default.gray("Status:")} ${i}`,"",p.default.white(n)].join(`
|
|
292
|
+
`);console.log((0,Ke.default)(l,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:r.status==="success"?"green":"red"})),Vo(r.output)&&zo(r.output)}function _o(r){return"run"in r?"Run":"choose"in r?"Choose":"prompt"in r?"Prompt":"parallel"in r?"Parallel":"fail"in r?"Fail":"Unknown"}function Ho(r){return"run"in r?`Command: ${p.default.yellow(r.run)}`:"choose"in r?`Message: ${p.default.yellow(r.choose.message)}`:"prompt"in r?`Message: ${p.default.yellow(r.prompt.message)} | Variable: ${p.default.cyan(r.prompt.as)}`:"parallel"in r?`Parallel execution with ${r.parallel.length} branches`:"fail"in r?`Error: ${p.default.red(r.fail.message)}`:"Unknown step type"}function Vo(r){return typeof r=="object"&&r!==null&&"success"in r&&"stdout"in r&&"stderr"in r}function zo(r){if(r.stdout.length>0){let e=r.stdout.map(t=>p.default.gray(` ${t}`)).join(`
|
|
294
293
|
`);console.log(p.default.green(" Output:")),console.log(e)}if(r.stderr.length>0){let e=r.stderr.map(t=>p.default.gray(` ${t}`)).join(`
|
|
295
294
|
`);console.log(p.default.red(" Errors:")),console.log(e)}}U.command("clean").description("Remove all data in ~/.pipeliner (schedules, daemon state, workflow history). Use after upgrades if data is incompatible.").action(async()=>{if((await new I().prompt(`This will remove all data in ${p.default.yellow(de)} (schedules, daemon PID, workflow history). Continue?`,[{id:"yes",label:"Yes, remove all"},{id:"no",label:"No, cancel"}]))?.id!=="yes"){console.log(p.default.yellow(`
|
|
296
295
|
\u2717 Cancelled`));return}try{if(await H()){let t=await $();console.log(p.default.gray(`Stopping scheduler daemon (PID: ${t.pid})...`)),await new z().stopDaemon(),console.log(p.default.gray(" Daemon stopped"))}(0,O.existsSync)(de)?(await(0,F.rm)(de,{recursive:!0}),console.log(p.default.green(`
|