@quadnix/octo-build 0.0.17 → 0.1.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/LICENSE +661 -0
- package/README.md +25 -3
- package/dist/commands/apply/apply.command.d.ts +25 -0
- package/dist/commands/apply/apply.command.js +136 -0
- package/dist/commands/apply/apply.command.js.map +1 -0
- package/dist/commands/apply/index.d.ts +1 -0
- package/dist/commands/apply/index.js +2 -0
- package/dist/commands/apply/index.js.map +1 -0
- package/dist/commands/build/build.command.d.ts +1 -1
- package/dist/commands/build/build.command.js +4 -4
- package/dist/commands/build/build.command.js.map +1 -1
- package/dist/commands/build/main.d.ts +22 -0
- package/dist/commands/build/main.js +22 -0
- package/dist/commands/build/main.js.map +1 -1
- package/dist/commands/build/parsers/build-file.parser.d.ts +6 -0
- package/dist/commands/build/parsers/build-file.parser.js +6 -0
- package/dist/commands/build/parsers/build-file.parser.js.map +1 -1
- package/dist/commands/build/streams/stream-manager.d.ts +6 -0
- package/dist/commands/build/streams/stream-manager.js +7 -1
- package/dist/commands/build/streams/stream-manager.js.map +1 -1
- package/dist/commands/commit/commit.command.d.ts +22 -0
- package/dist/commands/commit/commit.command.js +94 -0
- package/dist/commands/commit/commit.command.js.map +1 -0
- package/dist/commands/commit/index.d.ts +1 -0
- package/dist/commands/commit/index.js +2 -0
- package/dist/commands/commit/index.js.map +1 -0
- package/dist/commands/create-anchor/create-anchor.command.js +1 -1
- package/dist/commands/create-anchor/create-anchor.command.js.map +1 -1
- package/dist/commands/create-anchor/generator-octo-anchor-template/generators/app/index.d.ts +18 -3
- package/dist/commands/create-anchor/generator-octo-anchor-template/generators/app/index.js +29 -11
- package/dist/commands/create-anchor/generator-octo-anchor-template/generators/app/index.js.map +1 -1
- package/dist/commands/create-anchor/generator-octo-anchor-template/generators/app/templates/anchors/anchor/anchor.schema.ts.ejs +9 -1
- package/dist/commands/create-app/create-app.command.d.ts +1 -1
- package/dist/commands/create-app/create-app.command.js +7 -3
- package/dist/commands/create-app/create-app.command.js.map +1 -1
- package/dist/commands/create-app/generator-octo-app-template/generators/app/index.d.ts +17 -1
- package/dist/commands/create-app/generator-octo-app-template/generators/app/index.js +59 -12
- package/dist/commands/create-app/generator-octo-app-template/generators/app/index.js.map +1 -1
- package/dist/commands/create-app/generator-octo-app-template/generators/app/templates/README.md.ejs +60 -10
- package/dist/commands/create-app/generator-octo-app-template/generators/app/templates/gitignore.ejs +13 -0
- package/dist/commands/create-app/generator-octo-app-template/generators/app/templates/index.ts.ejs +19 -0
- package/dist/commands/create-app/generator-octo-app-template/generators/app/templates/package.json.ejs +9 -1
- package/dist/commands/create-app/generator-octo-app-template/generators/app/templates/src/aws-dynamodb-service/octo.yaml.ejs +111 -0
- package/dist/commands/create-app/generator-octo-app-template/generators/app/templates/src/aws-ecs-server/octo.yaml.ejs +14 -0
- package/dist/commands/create-app/generator-octo-app-template/generators/app/templates/src/aws-s3-website/octo.yaml.ejs +14 -0
- package/dist/commands/create-app/generator-octo-app-template/generators/app/templates/tsconfig.json.ejs +0 -3
- package/dist/commands/{create-resource/create-resource.command.d.ts → create-external-resource/create-external-resource.command.d.ts} +1 -1
- package/dist/commands/create-external-resource/create-external-resource.command.js +64 -0
- package/dist/commands/create-external-resource/create-external-resource.command.js.map +1 -0
- package/dist/commands/{create-resource/generator-octo-resource-template → create-external-resource/generator-octo-external-resource-template}/generators/app/index.d.ts +17 -2
- package/dist/commands/{create-resource/generator-octo-resource-template → create-external-resource/generator-octo-external-resource-template}/generators/app/index.js +36 -35
- package/dist/commands/create-external-resource/generator-octo-external-resource-template/generators/app/index.js.map +1 -0
- package/dist/commands/{create-resource/generator-octo-resource-template → create-external-resource/generator-octo-external-resource-template}/generators/app/templates/resources/resource/actions/add.resource.action.ts.ejs +7 -16
- package/dist/commands/{create-resource/generator-octo-resource-template → create-external-resource/generator-octo-external-resource-template}/generators/app/templates/resources/resource/actions/delete.resource.action.ts.ejs +21 -3
- package/dist/commands/create-external-resource/generator-octo-external-resource-template/generators/app/templates/resources/resource/actions/update.resource.action.ts.ejs +63 -0
- package/dist/commands/{create-resource/generator-octo-resource-template → create-external-resource/generator-octo-external-resource-template}/generators/app/templates/resources/resource/index.ts.ejs +1 -2
- package/dist/commands/create-external-resource/generator-octo-external-resource-template/generators/app/templates/resources/resource/resource.ts.ejs +28 -0
- package/dist/commands/create-external-resource/index.d.ts +1 -0
- package/dist/commands/create-external-resource/index.js +2 -0
- package/dist/commands/create-external-resource/index.js.map +1 -0
- package/dist/commands/create-model/create-model.command.js +1 -1
- package/dist/commands/create-model/create-model.command.js.map +1 -1
- package/dist/commands/create-model/generator-octo-model-template/generators/app/index.d.ts +17 -2
- package/dist/commands/create-model/generator-octo-model-template/generators/app/index.js +26 -9
- package/dist/commands/create-model/generator-octo-model-template/generators/app/index.js.map +1 -1
- package/dist/commands/create-model/generator-octo-model-template/generators/app/templates/models/model/model.ts.ejs +3 -1
- package/dist/commands/create-model/generator-octo-model-template/generators/app/templates/models/model/schema.ts.ejs +6 -1
- package/dist/commands/create-module/create-module.command.js +1 -1
- package/dist/commands/create-module/create-module.command.js.map +1 -1
- package/dist/commands/create-module/generator-octo-module-template/generators/app/index.d.ts +17 -2
- package/dist/commands/create-module/generator-octo-module-template/generators/app/index.js +27 -10
- package/dist/commands/create-module/generator-octo-module-template/generators/app/index.js.map +1 -1
- package/dist/commands/create-overlay/create-overlay.command.js +4 -3
- package/dist/commands/create-overlay/create-overlay.command.js.map +1 -1
- package/dist/commands/create-overlay/generator-octo-overlay-template/generators/app/index.d.ts +17 -2
- package/dist/commands/create-overlay/generator-octo-overlay-template/generators/app/index.js +26 -9
- package/dist/commands/create-overlay/generator-octo-overlay-template/generators/app/index.js.map +1 -1
- package/dist/commands/{create-cdk/create-cdk.command.d.ts → create-terraform-resource/create-terraform-resource.command.d.ts} +3 -3
- package/dist/commands/{create-resource/create-resource.command.js → create-terraform-resource/create-terraform-resource.command.js} +17 -11
- package/dist/commands/create-terraform-resource/create-terraform-resource.command.js.map +1 -0
- package/dist/commands/create-terraform-resource/generator-octo-terraform-resource-template/generators/app/index.d.ts +25 -0
- package/dist/commands/create-terraform-resource/generator-octo-terraform-resource-template/generators/app/index.js +71 -0
- package/dist/commands/create-terraform-resource/generator-octo-terraform-resource-template/generators/app/index.js.map +1 -0
- package/dist/commands/create-terraform-resource/generator-octo-terraform-resource-template/generators/app/templates/resources/resource/index.schema.ts.ejs +43 -0
- package/dist/commands/create-terraform-resource/generator-octo-terraform-resource-template/generators/app/templates/resources/resource/index.ts.ejs +1 -0
- package/dist/commands/create-terraform-resource/generator-octo-terraform-resource-template/generators/app/templates/resources/resource/resource.ts.ejs +83 -0
- package/dist/commands/create-terraform-resource/index.d.ts +1 -0
- package/dist/commands/create-terraform-resource/index.js +2 -0
- package/dist/commands/create-terraform-resource/index.js.map +1 -0
- package/dist/commands/generate/generate.command.d.ts +14 -0
- package/dist/commands/generate/generate.command.js +35 -0
- package/dist/commands/generate/generate.command.js.map +1 -0
- package/dist/commands/generate/index.d.ts +1 -0
- package/dist/commands/generate/index.js +2 -0
- package/dist/commands/generate/index.js.map +1 -0
- package/dist/commands/get-response/get-response.command.d.ts +18 -0
- package/dist/commands/get-response/get-response.command.js +39 -0
- package/dist/commands/get-response/get-response.command.js.map +1 -0
- package/dist/commands/get-response/index.d.ts +1 -0
- package/dist/commands/get-response/index.js +2 -0
- package/dist/commands/get-response/index.js.map +1 -0
- package/dist/commands/lock/index.d.ts +1 -0
- package/dist/commands/lock/index.js +2 -0
- package/dist/commands/lock/index.js.map +1 -0
- package/dist/commands/lock/lock.command.d.ts +13 -0
- package/dist/commands/lock/lock.command.js +28 -0
- package/dist/commands/lock/lock.command.js.map +1 -0
- package/dist/commands/run-action/index.d.ts +1 -0
- package/dist/commands/run-action/index.js +2 -0
- package/dist/commands/run-action/index.js.map +1 -0
- package/dist/commands/run-action/run-action.command.d.ts +12 -0
- package/dist/commands/run-action/run-action.command.js +46 -0
- package/dist/commands/run-action/run-action.command.js.map +1 -0
- package/dist/commands/unlock/index.d.ts +1 -0
- package/dist/commands/unlock/index.js +2 -0
- package/dist/commands/unlock/index.js.map +1 -0
- package/dist/commands/unlock/unlock.command.d.ts +18 -0
- package/dist/commands/unlock/unlock.command.js +51 -0
- package/dist/commands/unlock/unlock.command.js.map +1 -0
- package/dist/commands/validate/index.d.ts +1 -0
- package/dist/commands/validate/index.js +2 -0
- package/dist/commands/validate/index.js.map +1 -0
- package/dist/commands/validate/validate.command.d.ts +17 -0
- package/dist/commands/validate/validate.command.js +68 -0
- package/dist/commands/validate/validate.command.js.map +1 -0
- package/dist/index.js +20 -8
- package/dist/index.js.map +1 -1
- package/dist/resources/octo-v1.schema.json +86 -19
- package/dist/utilities/definition/yaml/yaml-definition.utility.d.ts +98 -10
- package/dist/utilities/definition/yaml/yaml-definition.utility.js +197 -66
- package/dist/utilities/definition/yaml/yaml-definition.utility.js.map +1 -1
- package/dist/utilities/octo/octo.utility.d.ts +48 -0
- package/dist/utilities/octo/octo.utility.js +144 -0
- package/dist/utilities/octo/octo.utility.js.map +1 -0
- package/dist/utilities/process/process.utility.d.ts +8 -0
- package/dist/utilities/process/process.utility.js +8 -0
- package/dist/utilities/process/process.utility.js.map +1 -1
- package/dist/utilities/project-index/project-index.utility.d.ts +27 -0
- package/dist/utilities/project-index/project-index.utility.js +71 -0
- package/dist/utilities/project-index/project-index.utility.js.map +1 -0
- package/dist/utilities/string/string.utility.d.ts +22 -0
- package/dist/utilities/string/string.utility.js +27 -0
- package/dist/utilities/string/string.utility.js.map +1 -1
- package/package.json +9 -8
- package/dist/commands/create-cdk/create-cdk.command.js +0 -70
- package/dist/commands/create-cdk/create-cdk.command.js.map +0 -1
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/index.d.ts +0 -10
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/index.js +0 -107
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/index.js.map +0 -1
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/README.md.ejs +0 -23
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/eslint.config.js.ejs +0 -337
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/gitignore.ejs +0 -82
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/gitkeep.ejs +0 -0
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/package.json.ejs +0 -57
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/prettierrc.ejs +0 -5
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/src/anchors/app/app.anchor.schema.ts.ejs +0 -19
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/src/anchors/app/app.anchor.ts.ejs +0 -17
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/src/factories/dummy-credentials.factory.ts.ejs +0 -28
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/src/modules/app/dummy-app/dummy-app.module.spec.ts.ejs +0 -90
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/src/modules/app/dummy-app/dummy-app.module.ts.ejs +0 -16
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/src/modules/app/dummy-app/index.schema.ts.ejs +0 -10
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/src/modules/app/dummy-app/index.ts.ejs +0 -3
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/src/modules/app/dummy-app/models/app/actions/add-dummy-app.model.action.ts.ejs +0 -59
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/src/modules/app/dummy-app/models/app/index.ts.ejs +0 -1
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/src/resources/http-fetch/actions/add-http-fetch.resource.action.ts.ejs +0 -55
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/src/resources/http-fetch/http-fetch.resource.ts.ejs +0 -12
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/src/resources/http-fetch/index.schema.ts.ejs +0 -35
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/src/resources/http-fetch/index.ts.ejs +0 -3
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/src/utilities/dummy/dummy.utility.ts.ejs +0 -11
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/tsconfig.build.json.ejs +0 -11
- package/dist/commands/create-cdk/generator-octo-cdk-template/generators/app/templates/tsconfig.json.ejs +0 -39
- package/dist/commands/create-cdk/index.d.ts +0 -1
- package/dist/commands/create-cdk/index.js +0 -2
- package/dist/commands/create-cdk/index.js.map +0 -1
- package/dist/commands/create-resource/create-resource.command.js.map +0 -1
- package/dist/commands/create-resource/generator-octo-resource-template/generators/app/index.js.map +0 -1
- package/dist/commands/create-resource/generator-octo-resource-template/generators/app/templates/resources/resource/actions/update-tags.resource.action.ts.ejs +0 -86
- package/dist/commands/create-resource/generator-octo-resource-template/generators/app/templates/resources/resource/actions/validate.resource.action.ts.ejs +0 -40
- package/dist/commands/create-resource/generator-octo-resource-template/generators/app/templates/resources/resource/resource.ts.ejs +0 -12
- package/dist/commands/create-resource/index.d.ts +0 -1
- package/dist/commands/create-resource/index.js +0 -2
- package/dist/commands/create-resource/index.js.map +0 -1
- package/dist/commands/run/index.d.ts +0 -1
- package/dist/commands/run/index.js +0 -2
- package/dist/commands/run/index.js.map +0 -1
- package/dist/commands/run/run.command.d.ts +0 -11
- package/dist/commands/run/run.command.js +0 -96
- package/dist/commands/run/run.command.js.map +0 -1
- package/dist/commands/state/index.d.ts +0 -1
- package/dist/commands/state/index.js +0 -2
- package/dist/commands/state/index.js.map +0 -1
- package/dist/commands/state/state.command.d.ts +0 -14
- package/dist/commands/state/state.command.js +0 -79
- package/dist/commands/state/state.command.js.map +0 -1
- /package/dist/commands/{create-resource/generator-octo-resource-template → create-external-resource/generator-octo-external-resource-template}/generators/app/templates/resources/resource/index.schema.ts.ejs +0 -0
|
@@ -81,6 +81,9 @@
|
|
|
81
81
|
{
|
|
82
82
|
"additionalProperties": false,
|
|
83
83
|
"properties": {
|
|
84
|
+
"reportDir": {
|
|
85
|
+
"type": "string"
|
|
86
|
+
},
|
|
84
87
|
"type": {
|
|
85
88
|
"const": "HtmlReportEventListener",
|
|
86
89
|
"type": "string"
|
|
@@ -92,6 +95,13 @@
|
|
|
92
95
|
{
|
|
93
96
|
"additionalProperties": false,
|
|
94
97
|
"properties": {
|
|
98
|
+
"colorize": {
|
|
99
|
+
"type": "boolean"
|
|
100
|
+
},
|
|
101
|
+
"level": {
|
|
102
|
+
"enum": ["debug", "error", "fatal", "info", "silent", "trace", "warn"],
|
|
103
|
+
"type": "string"
|
|
104
|
+
},
|
|
95
105
|
"type": {
|
|
96
106
|
"const": "LoggingEventListener",
|
|
97
107
|
"type": "string"
|
|
@@ -149,31 +159,88 @@
|
|
|
149
159
|
"type": "object"
|
|
150
160
|
}
|
|
151
161
|
]
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
"required": ["stateProvider"],
|
|
165
|
+
"type": "object"
|
|
166
|
+
},
|
|
167
|
+
"tags": {
|
|
168
|
+
"items": {
|
|
169
|
+
"additionalProperties": false,
|
|
170
|
+
"properties": {
|
|
171
|
+
"scope": {
|
|
172
|
+
"additionalProperties": false,
|
|
173
|
+
"properties": {
|
|
174
|
+
"moduleId": {
|
|
175
|
+
"type": "string"
|
|
176
|
+
}
|
|
159
177
|
},
|
|
160
|
-
"
|
|
161
|
-
|
|
162
|
-
|
|
178
|
+
"type": "object"
|
|
179
|
+
},
|
|
180
|
+
"tags": {
|
|
181
|
+
"additionalProperties": {
|
|
182
|
+
"type": "string"
|
|
183
|
+
},
|
|
184
|
+
"type": "object"
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
"required": ["tags"],
|
|
188
|
+
"type": "object"
|
|
189
|
+
},
|
|
190
|
+
"type": "array"
|
|
191
|
+
},
|
|
192
|
+
"terraform": {
|
|
193
|
+
"additionalProperties": false,
|
|
194
|
+
"properties": {
|
|
195
|
+
"providers": {
|
|
196
|
+
"items": {
|
|
197
|
+
"additionalProperties": false,
|
|
198
|
+
"properties": {
|
|
199
|
+
"accountId": {
|
|
200
|
+
"type": "string"
|
|
201
|
+
},
|
|
202
|
+
"accountName": {
|
|
203
|
+
"type": "string"
|
|
204
|
+
},
|
|
205
|
+
"providerType": {
|
|
206
|
+
"type": "string"
|
|
207
|
+
},
|
|
208
|
+
"regionId": {
|
|
209
|
+
"type": "string"
|
|
210
|
+
},
|
|
211
|
+
"setRegionAttribute": {
|
|
212
|
+
"type": "boolean"
|
|
213
|
+
},
|
|
214
|
+
"spec": {
|
|
215
|
+
"type": "object"
|
|
216
|
+
}
|
|
163
217
|
},
|
|
164
|
-
"
|
|
165
|
-
|
|
166
|
-
|
|
218
|
+
"required": ["accountId", "providerType", "regionId"],
|
|
219
|
+
"type": "object"
|
|
220
|
+
},
|
|
221
|
+
"type": "array"
|
|
222
|
+
},
|
|
223
|
+
"requiredProviders": {
|
|
224
|
+
"additionalProperties": {
|
|
225
|
+
"additionalProperties": false,
|
|
226
|
+
"properties": {
|
|
227
|
+
"minVersion": {
|
|
228
|
+
"type": "string"
|
|
229
|
+
},
|
|
230
|
+
"source": {
|
|
231
|
+
"type": "string"
|
|
232
|
+
}
|
|
167
233
|
},
|
|
168
|
-
"
|
|
169
|
-
|
|
170
|
-
"type": "boolean"
|
|
171
|
-
}
|
|
234
|
+
"required": ["source"],
|
|
235
|
+
"type": "object"
|
|
172
236
|
},
|
|
173
237
|
"type": "object"
|
|
238
|
+
},
|
|
239
|
+
"requiredVersion": {
|
|
240
|
+
"type": "string"
|
|
174
241
|
}
|
|
175
242
|
},
|
|
176
|
-
"required": ["
|
|
243
|
+
"required": ["providers", "requiredProviders", "requiredVersion"],
|
|
177
244
|
"type": "object"
|
|
178
245
|
},
|
|
179
246
|
"version": {
|
|
@@ -181,7 +248,7 @@
|
|
|
181
248
|
"type": "number"
|
|
182
249
|
}
|
|
183
250
|
},
|
|
184
|
-
"required": ["imports", "modules", "settings", "version"],
|
|
251
|
+
"required": ["imports", "modules", "settings", "terraform", "version"],
|
|
185
252
|
"title": "Octo V1 Definition Schema",
|
|
186
253
|
"type": "object"
|
|
187
254
|
}
|
|
@@ -1,10 +1,34 @@
|
|
|
1
|
-
import { type Constructable, LocalEncryptionStateProvider, LocalStateProvider, TestStateProvider } from '@quadnix/octo';
|
|
1
|
+
import { type Constructable, LocalEncryptionStateProvider, LocalStateProvider, type Octo, TestStateProvider } from '@quadnix/octo';
|
|
2
2
|
import type { HtmlReportEventListener } from '@quadnix/octo-event-listeners/html-report';
|
|
3
3
|
import type { LoggingEventListener } from '@quadnix/octo-event-listeners/logging';
|
|
4
|
+
/**
|
|
5
|
+
* Reads `octo.yml` and turns each section into the values {@link Octo} is booted with.
|
|
6
|
+
*/
|
|
4
7
|
export declare class YamlDefinitionUtility {
|
|
5
8
|
private readonly definition;
|
|
9
|
+
/**
|
|
10
|
+
* The directory holding the definition file. Everything the definition names by relative path is
|
|
11
|
+
* resolved against this, not against `process.cwd()`: `octo run-action` is invoked by terraform
|
|
12
|
+
* from inside a terragrunt cache directory, so the cwd there is neither the project nor stable.
|
|
13
|
+
*/
|
|
14
|
+
private readonly definitionDir;
|
|
15
|
+
/**
|
|
16
|
+
* @param definitionFilePath Path to the definition file.
|
|
17
|
+
* @throws If the file is unreadable, or fails schema validation.
|
|
18
|
+
*/
|
|
6
19
|
constructor(definitionFilePath: string);
|
|
20
|
+
/**
|
|
21
|
+
* Substitutes `${env.KEY}` references in a value with what the definition's `env` block declares.
|
|
22
|
+
*
|
|
23
|
+
* Arrays and objects are walked, because a module input is as nested as its schema: a reference
|
|
24
|
+
* can sit inside a list of images, or a key of an object, as readily as at the top level.
|
|
25
|
+
*
|
|
26
|
+
* @throws If a value holds one of its own ancestors, which no substitution over it terminates on.
|
|
27
|
+
*/
|
|
7
28
|
resolveEnvironmentValue<T>(value: unknown): T;
|
|
29
|
+
/**
|
|
30
|
+
* Imports the hook callbacks the definition names, in the shape {@link Octo.registerHooks} takes.
|
|
31
|
+
*/
|
|
8
32
|
resolveHooks(): Promise<{
|
|
9
33
|
postCommitHooks?: {
|
|
10
34
|
handle: any;
|
|
@@ -29,19 +53,35 @@ export declare class YamlDefinitionUtility {
|
|
|
29
53
|
handle: any;
|
|
30
54
|
}[];
|
|
31
55
|
}>;
|
|
56
|
+
/**
|
|
57
|
+
* Imports every module class the definition's `imports` block names.
|
|
58
|
+
*/
|
|
32
59
|
resolveImports(): Promise<{
|
|
33
60
|
className: Constructable<any>;
|
|
34
61
|
}[]>;
|
|
35
|
-
|
|
62
|
+
/**
|
|
63
|
+
* @param logDestination Where the logging listener writes. `run-action` passes `stderr`, because
|
|
64
|
+
* terraform's `data "external"` protocol requires that command's stdout to carry only the response
|
|
65
|
+
* JSON.
|
|
66
|
+
*/
|
|
67
|
+
resolveListeners({ logDestination }?: {
|
|
68
|
+
logDestination?: 'stderr' | 'stdout';
|
|
69
|
+
}): Promise<{
|
|
36
70
|
args?: unknown[];
|
|
37
71
|
metadata?: Record<string, string>;
|
|
38
72
|
type: Constructable<HtmlReportEventListener | LoggingEventListener>;
|
|
39
73
|
}[]>;
|
|
74
|
+
/**
|
|
75
|
+
* Pairs each `modules` entry with its imported class, and resolves its inputs.
|
|
76
|
+
*/
|
|
40
77
|
resolveModules(imports: Awaited<ReturnType<YamlDefinitionUtility['resolveImports']>>): {
|
|
41
78
|
moduleClass: Constructable<any>;
|
|
42
79
|
moduleId: string;
|
|
43
80
|
moduleInputs: Record<string, unknown>;
|
|
44
81
|
}[];
|
|
82
|
+
/**
|
|
83
|
+
* Builds the {@link IStateProvider} the definition asks for.
|
|
84
|
+
*/
|
|
45
85
|
resolveStateProvider(): {
|
|
46
86
|
type: LocalEncryptionStateProvider;
|
|
47
87
|
} | {
|
|
@@ -49,14 +89,62 @@ export declare class YamlDefinitionUtility {
|
|
|
49
89
|
} | {
|
|
50
90
|
type: TestStateProvider;
|
|
51
91
|
};
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
92
|
+
/**
|
|
93
|
+
* The tag registrations the definition declares, in the shape {@link Octo.registerTags} takes.
|
|
94
|
+
*
|
|
95
|
+
* A `scope` naming a `moduleId` reaches that module's resources; an absent or empty one reaches
|
|
96
|
+
* every resource of the run.
|
|
97
|
+
*/
|
|
98
|
+
resolveTags(): Parameters<Octo['registerTags']>[0];
|
|
99
|
+
/**
|
|
100
|
+
* The terraform version, required providers, and provider blocks the definition declares.
|
|
101
|
+
*/
|
|
102
|
+
resolveTerraformOptions(): {
|
|
103
|
+
providers: {
|
|
104
|
+
accountId: string;
|
|
105
|
+
accountName: string | undefined;
|
|
106
|
+
providerType: string;
|
|
107
|
+
regionId: string;
|
|
108
|
+
setRegionAttribute: boolean | undefined;
|
|
109
|
+
spec: Record<string, unknown>;
|
|
110
|
+
}[];
|
|
111
|
+
requiredProviders: Record<string, {
|
|
112
|
+
minVersion?: string;
|
|
113
|
+
source: string;
|
|
114
|
+
}>;
|
|
115
|
+
requiredVersion: string;
|
|
60
116
|
};
|
|
117
|
+
/**
|
|
118
|
+
* Substitutes one `${env.KEY}` reference with what the definition's `env` block declares for that
|
|
119
|
+
* key, read in the kind the block gives it. Anything holding no reference is returned as it came.
|
|
120
|
+
*/
|
|
121
|
+
private resolveEnvironmentReference;
|
|
122
|
+
/**
|
|
123
|
+
* Resolves a definition-file import specifier to something `import()` can load.
|
|
124
|
+
*
|
|
125
|
+
* A relative path resolves against the **definition file's own directory**. It cannot resolve
|
|
126
|
+
* against the current working directory: terraform invokes `octo run-action` from inside a
|
|
127
|
+
* terragrunt cache directory, so a definition saying `./dist/index.js` - which is what every
|
|
128
|
+
* generated app says - would be looked for under the cache and never found.
|
|
129
|
+
*
|
|
130
|
+
* A bare specifier resolves against the **user's project root**, not octo-build's own install
|
|
131
|
+
* directory - node would otherwise resolve it from wherever octo-build happens to live. A flat
|
|
132
|
+
* `node_modules` hides that; a linked store does not, and there the user's own dependencies are
|
|
133
|
+
* invisible.
|
|
134
|
+
*/
|
|
135
|
+
private resolveImportPath;
|
|
136
|
+
/**
|
|
137
|
+
* Walks a value, substituting every `${env.KEY}` reference it holds at any depth.
|
|
138
|
+
*
|
|
139
|
+
* `ancestors` is the chain currently being walked rather than everything already seen. A YAML
|
|
140
|
+
* anchor used in two places points one node at two parents, which resolves twice and is no cycle;
|
|
141
|
+
* a node reappearing beneath itself is one, and walking it never ends.
|
|
142
|
+
*
|
|
143
|
+
* @throws If a value holds one of its own ancestors.
|
|
144
|
+
*/
|
|
145
|
+
private resolveNestedEnvironmentValue;
|
|
146
|
+
/**
|
|
147
|
+
* Checks the definition against `octo-v1.schema.json`.
|
|
148
|
+
*/
|
|
61
149
|
private validateDefinition;
|
|
62
150
|
}
|
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'fs';
|
|
2
|
+
import { createRequire } from 'module';
|
|
2
3
|
import { dirname, join, resolve } from 'path';
|
|
3
|
-
import { fileURLToPath } from 'url';
|
|
4
|
-
import { LocalEncryptionStateProvider, LocalStateProvider, TestStateProvider } from '@quadnix/octo';
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
5
|
+
import { LocalEncryptionStateProvider, LocalStateProvider, TestStateProvider, } from '@quadnix/octo';
|
|
5
6
|
import { Ajv2020 as Ajv } from 'ajv/dist/2020.js';
|
|
6
7
|
import { load } from 'js-yaml';
|
|
7
8
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
/**
|
|
10
|
+
* Reads `octo.yml` and turns each section into the values {@link Octo} is booted with.
|
|
11
|
+
*/
|
|
8
12
|
export class YamlDefinitionUtility {
|
|
13
|
+
/**
|
|
14
|
+
* @param definitionFilePath Path to the definition file.
|
|
15
|
+
* @throws If the file is unreadable, or fails schema validation.
|
|
16
|
+
*/
|
|
9
17
|
constructor(definitionFilePath) {
|
|
10
18
|
definitionFilePath = resolve(process.cwd(), definitionFilePath);
|
|
19
|
+
this.definitionDir = dirname(definitionFilePath);
|
|
11
20
|
if (!existsSync(definitionFilePath)) {
|
|
12
21
|
throw new Error('Cannot find definition file: ' + definitionFilePath);
|
|
13
22
|
}
|
|
@@ -20,32 +29,20 @@ export class YamlDefinitionUtility {
|
|
|
20
29
|
}
|
|
21
30
|
this.validateDefinition();
|
|
22
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Substitutes `${env.KEY}` references in a value with what the definition's `env` block declares.
|
|
34
|
+
*
|
|
35
|
+
* Arrays and objects are walked, because a module input is as nested as its schema: a reference
|
|
36
|
+
* can sit inside a list of images, or a key of an object, as readily as at the top level.
|
|
37
|
+
*
|
|
38
|
+
* @throws If a value holds one of its own ancestors, which no substitution over it terminates on.
|
|
39
|
+
*/
|
|
23
40
|
resolveEnvironmentValue(value) {
|
|
24
|
-
|
|
25
|
-
return value;
|
|
26
|
-
}
|
|
27
|
-
const pattern = value.match(/^\$\{env\.(.+)}$/);
|
|
28
|
-
if (!pattern || pattern.length < 2) {
|
|
29
|
-
return value;
|
|
30
|
-
}
|
|
31
|
-
const environmentKey = this.definition.env.find((e) => e.key === pattern[1]);
|
|
32
|
-
if (!environmentKey) {
|
|
33
|
-
throw new Error(`Key "${pattern[1]}" not found under "env"!`);
|
|
34
|
-
}
|
|
35
|
-
let resolvedValue = process.env[pattern[1]] || environmentKey.value;
|
|
36
|
-
const { kind } = environmentKey;
|
|
37
|
-
switch (kind) {
|
|
38
|
-
case 'boolean': {
|
|
39
|
-
return Boolean(resolvedValue);
|
|
40
|
-
}
|
|
41
|
-
case 'number': {
|
|
42
|
-
return Number(resolvedValue);
|
|
43
|
-
}
|
|
44
|
-
default: {
|
|
45
|
-
return String(resolvedValue);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
41
|
+
return this.resolveNestedEnvironmentValue(value, new Set());
|
|
48
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Imports the hook callbacks the definition names, in the shape {@link Octo.registerHooks} takes.
|
|
45
|
+
*/
|
|
49
46
|
async resolveHooks() {
|
|
50
47
|
const hooks = {
|
|
51
48
|
postCommitHooks: [],
|
|
@@ -60,8 +57,8 @@ export class YamlDefinitionUtility {
|
|
|
60
57
|
}
|
|
61
58
|
for (const hookDef of this.definition.hooks) {
|
|
62
59
|
const { importPath, method } = hookDef;
|
|
63
|
-
const resolvedImport = importPath.startsWith('.') || importPath.startsWith('/') ? resolve(process.cwd(), importPath) : importPath;
|
|
64
60
|
try {
|
|
61
|
+
const resolvedImport = this.resolveImportPath(importPath);
|
|
65
62
|
const imported = await import(resolvedImport);
|
|
66
63
|
if (!imported[method]) {
|
|
67
64
|
throw new Error(`Unable to find export "${method}" in path "${resolvedImport}"!`);
|
|
@@ -77,11 +74,14 @@ export class YamlDefinitionUtility {
|
|
|
77
74
|
}
|
|
78
75
|
}
|
|
79
76
|
catch (error) {
|
|
80
|
-
throw new Error(`Failed to import path "${
|
|
77
|
+
throw new Error(`Failed to import path "${importPath}": ${error?.message || String(error)}`);
|
|
81
78
|
}
|
|
82
79
|
}
|
|
83
80
|
return hooks;
|
|
84
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Imports every module class the definition's `imports` block names.
|
|
84
|
+
*/
|
|
85
85
|
async resolveImports() {
|
|
86
86
|
const imports = [];
|
|
87
87
|
if (!this.definition.imports?.length) {
|
|
@@ -89,8 +89,8 @@ export class YamlDefinitionUtility {
|
|
|
89
89
|
}
|
|
90
90
|
for (const importDef of this.definition.imports) {
|
|
91
91
|
const { className, importPath } = importDef;
|
|
92
|
-
const resolvedImport = importPath.startsWith('.') || importPath.startsWith('/') ? resolve(process.cwd(), importPath) : importPath;
|
|
93
92
|
try {
|
|
93
|
+
const resolvedImport = this.resolveImportPath(importPath);
|
|
94
94
|
const imported = await import(resolvedImport);
|
|
95
95
|
if (!imported[className]) {
|
|
96
96
|
throw new Error(`Unable to find export "${className}" in path "${resolvedImport}"!`);
|
|
@@ -100,32 +100,51 @@ export class YamlDefinitionUtility {
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
catch (error) {
|
|
103
|
-
throw new Error(`Failed to import path "${
|
|
103
|
+
throw new Error(`Failed to import path "${importPath}": ${error?.message || String(error)}`);
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
return imports;
|
|
107
107
|
}
|
|
108
|
-
|
|
108
|
+
/**
|
|
109
|
+
* @param logDestination Where the logging listener writes. `run-action` passes `stderr`, because
|
|
110
|
+
* terraform's `data "external"` protocol requires that command's stdout to carry only the response
|
|
111
|
+
* JSON.
|
|
112
|
+
*/
|
|
113
|
+
async resolveListeners({ logDestination = 'stdout' } = {}) {
|
|
109
114
|
const listeners = [];
|
|
110
115
|
if (!this.definition.settings?.listeners?.length) {
|
|
111
116
|
return listeners;
|
|
112
117
|
}
|
|
113
118
|
for (const listenerDef of this.definition.settings.listeners) {
|
|
114
119
|
if (listenerDef.type === 'HtmlReportEventListener') {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
120
|
+
const imported = await import('@quadnix/octo-event-listeners/html-report');
|
|
121
|
+
listeners.push({
|
|
122
|
+
args: [{ reportDir: listenerDef.reportDir }],
|
|
123
|
+
type: imported.HtmlReportEventListener,
|
|
124
|
+
});
|
|
119
125
|
}
|
|
120
126
|
else if (listenerDef.type === 'LoggingEventListener') {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
127
|
+
const imported = await import('@quadnix/octo-event-listeners/logging');
|
|
128
|
+
// Default to whether the destination is a terminal, so a redirected log carries no escape
|
|
129
|
+
// codes. An explicit `colorize:` in the definition still wins.
|
|
130
|
+
const destinationStream = logDestination === 'stderr' ? process.stderr : process.stdout;
|
|
131
|
+
listeners.push({
|
|
132
|
+
args: [
|
|
133
|
+
{
|
|
134
|
+
colorize: listenerDef.colorize ?? Boolean(destinationStream.isTTY),
|
|
135
|
+
destination: logDestination,
|
|
136
|
+
level: listenerDef.level ?? 'info',
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
type: imported.LoggingEventListener,
|
|
140
|
+
});
|
|
125
141
|
}
|
|
126
142
|
}
|
|
127
143
|
return listeners;
|
|
128
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Pairs each `modules` entry with its imported class, and resolves its inputs.
|
|
147
|
+
*/
|
|
129
148
|
resolveModules(imports) {
|
|
130
149
|
const modules = [];
|
|
131
150
|
if (!this.definition.modules?.length) {
|
|
@@ -145,16 +164,22 @@ export class YamlDefinitionUtility {
|
|
|
145
164
|
}
|
|
146
165
|
return modules;
|
|
147
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Builds the {@link IStateProvider} the definition asks for.
|
|
169
|
+
*/
|
|
148
170
|
resolveStateProvider() {
|
|
149
171
|
const stateProvider = this.definition.settings.stateProvider;
|
|
172
|
+
// Anchored to the definition file for the same reason imports are: `run-action` runs with
|
|
173
|
+
// terragrunt's cache directory as its cwd, and a state path resolved from there would point at
|
|
174
|
+
// an empty directory - the action would read no prior state and write its result nowhere useful.
|
|
150
175
|
if (stateProvider.type === 'LocalEncryptionStateProvider') {
|
|
151
176
|
return {
|
|
152
|
-
type: new LocalEncryptionStateProvider(stateProvider.statePath, stateProvider.encryptionKey),
|
|
177
|
+
type: new LocalEncryptionStateProvider(resolve(this.definitionDir, stateProvider.statePath), stateProvider.encryptionKey),
|
|
153
178
|
};
|
|
154
179
|
}
|
|
155
180
|
else if (stateProvider.type === 'LocalStateProvider') {
|
|
156
181
|
return {
|
|
157
|
-
type: new LocalStateProvider(stateProvider.statePath),
|
|
182
|
+
type: new LocalStateProvider(resolve(this.definitionDir, stateProvider.statePath)),
|
|
158
183
|
};
|
|
159
184
|
}
|
|
160
185
|
else if (stateProvider.type === 'TestStateProvider') {
|
|
@@ -166,40 +191,146 @@ export class YamlDefinitionUtility {
|
|
|
166
191
|
throw new Error(`Invalid state provider!`);
|
|
167
192
|
}
|
|
168
193
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
194
|
+
/**
|
|
195
|
+
* The tag registrations the definition declares, in the shape {@link Octo.registerTags} takes.
|
|
196
|
+
*
|
|
197
|
+
* A `scope` naming a `moduleId` reaches that module's resources; an absent or empty one reaches
|
|
198
|
+
* every resource of the run.
|
|
199
|
+
*/
|
|
200
|
+
resolveTags() {
|
|
201
|
+
const tags = [];
|
|
202
|
+
if (!this.definition.tags?.length) {
|
|
203
|
+
return tags;
|
|
204
|
+
}
|
|
205
|
+
for (const tagDefinition of this.definition.tags) {
|
|
206
|
+
const resolvedTags = {};
|
|
207
|
+
for (const [key, value] of Object.entries(tagDefinition.tags)) {
|
|
208
|
+
// A tag value is always a string, so an `${env.KEY}` declared as a number or a boolean is
|
|
209
|
+
// rendered rather than handed to the resource as the kind it was declared with.
|
|
210
|
+
resolvedTags[key] = String(this.resolveEnvironmentValue(value));
|
|
211
|
+
}
|
|
212
|
+
tags.push({ scope: tagDefinition.scope || {}, tags: resolvedTags });
|
|
213
|
+
}
|
|
214
|
+
return tags;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* The terraform version, required providers, and provider blocks the definition declares.
|
|
218
|
+
*/
|
|
219
|
+
resolveTerraformOptions() {
|
|
220
|
+
const terraform = this.definition.terraform;
|
|
221
|
+
const providers = terraform.providers.map((p) => {
|
|
222
|
+
const spec = {};
|
|
223
|
+
for (const [key, value] of Object.entries(p.spec || {})) {
|
|
224
|
+
spec[key] = this.resolveEnvironmentValue(value);
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
accountId: this.resolveEnvironmentValue(p.accountId),
|
|
228
|
+
accountName: p.accountName ? this.resolveEnvironmentValue(p.accountName) : undefined,
|
|
229
|
+
providerType: p.providerType,
|
|
230
|
+
regionId: this.resolveEnvironmentValue(p.regionId),
|
|
231
|
+
// Passed through as-is: undefined lets octo apply its per-provider-type default.
|
|
232
|
+
setRegionAttribute: p.setRegionAttribute,
|
|
233
|
+
spec,
|
|
234
|
+
};
|
|
235
|
+
});
|
|
236
|
+
return {
|
|
237
|
+
providers,
|
|
238
|
+
requiredProviders: terraform.requiredProviders,
|
|
239
|
+
requiredVersion: this.resolveEnvironmentValue(terraform.requiredVersion),
|
|
179
240
|
};
|
|
180
|
-
|
|
181
|
-
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Substitutes one `${env.KEY}` reference with what the definition's `env` block declares for that
|
|
244
|
+
* key, read in the kind the block gives it. Anything holding no reference is returned as it came.
|
|
245
|
+
*/
|
|
246
|
+
resolveEnvironmentReference(value) {
|
|
247
|
+
if (typeof value !== 'string') {
|
|
248
|
+
return value;
|
|
182
249
|
}
|
|
183
|
-
|
|
184
|
-
|
|
250
|
+
const pattern = value.match(/^\$\{env\.(.+)}$/);
|
|
251
|
+
if (!pattern || pattern.length < 2) {
|
|
252
|
+
return value;
|
|
185
253
|
}
|
|
186
|
-
|
|
187
|
-
|
|
254
|
+
// `env` is optional in the schema, so a definition can reference `${env.X}` without declaring
|
|
255
|
+
// one. Treat that as an empty block and let the "not found" error below report it.
|
|
256
|
+
const environmentKey = (this.definition.env ?? []).find((e) => e.key === pattern[1]);
|
|
257
|
+
if (!environmentKey) {
|
|
258
|
+
throw new Error(`Key "${pattern[1]}" not found under "env"!`);
|
|
188
259
|
}
|
|
189
|
-
|
|
190
|
-
|
|
260
|
+
let resolvedValue = process.env[pattern[1]] || environmentKey.value;
|
|
261
|
+
const { kind } = environmentKey;
|
|
262
|
+
switch (kind) {
|
|
263
|
+
case 'boolean': {
|
|
264
|
+
// A shell always supplies a string, and `Boolean("false")` is `true`. Parse the string form
|
|
265
|
+
// rather than coercing it, and reject anything that is not plainly a boolean.
|
|
266
|
+
if (typeof resolvedValue === 'boolean') {
|
|
267
|
+
return resolvedValue;
|
|
268
|
+
}
|
|
269
|
+
const normalizedValue = String(resolvedValue).trim().toLowerCase();
|
|
270
|
+
if (normalizedValue === 'true') {
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
else if (normalizedValue === 'false') {
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
throw new Error(`Value "${resolvedValue}" for key "${pattern[1]}" is not a boolean!`);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
case 'number': {
|
|
281
|
+
return Number(resolvedValue);
|
|
282
|
+
}
|
|
283
|
+
default: {
|
|
284
|
+
return String(resolvedValue);
|
|
285
|
+
}
|
|
191
286
|
}
|
|
192
|
-
|
|
193
|
-
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Resolves a definition-file import specifier to something `import()` can load.
|
|
290
|
+
*
|
|
291
|
+
* A relative path resolves against the **definition file's own directory**. It cannot resolve
|
|
292
|
+
* against the current working directory: terraform invokes `octo run-action` from inside a
|
|
293
|
+
* terragrunt cache directory, so a definition saying `./dist/index.js` - which is what every
|
|
294
|
+
* generated app says - would be looked for under the cache and never found.
|
|
295
|
+
*
|
|
296
|
+
* A bare specifier resolves against the **user's project root**, not octo-build's own install
|
|
297
|
+
* directory - node would otherwise resolve it from wherever octo-build happens to live. A flat
|
|
298
|
+
* `node_modules` hides that; a linked store does not, and there the user's own dependencies are
|
|
299
|
+
* invisible.
|
|
300
|
+
*/
|
|
301
|
+
resolveImportPath(importPath) {
|
|
302
|
+
if (importPath.startsWith('.') || importPath.startsWith('/')) {
|
|
303
|
+
return resolve(this.definitionDir, importPath);
|
|
194
304
|
}
|
|
195
|
-
|
|
196
|
-
|
|
305
|
+
const requireFromProject = createRequire(join(this.definitionDir, 'package.json'));
|
|
306
|
+
return pathToFileURL(requireFromProject.resolve(importPath)).href;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Walks a value, substituting every `${env.KEY}` reference it holds at any depth.
|
|
310
|
+
*
|
|
311
|
+
* `ancestors` is the chain currently being walked rather than everything already seen. A YAML
|
|
312
|
+
* anchor used in two places points one node at two parents, which resolves twice and is no cycle;
|
|
313
|
+
* a node reappearing beneath itself is one, and walking it never ends.
|
|
314
|
+
*
|
|
315
|
+
* @throws If a value holds one of its own ancestors.
|
|
316
|
+
*/
|
|
317
|
+
resolveNestedEnvironmentValue(value, ancestors) {
|
|
318
|
+
if (value === null || typeof value !== 'object') {
|
|
319
|
+
return this.resolveEnvironmentReference(value);
|
|
197
320
|
}
|
|
198
|
-
if (
|
|
199
|
-
|
|
321
|
+
if (ancestors.has(value)) {
|
|
322
|
+
throw new Error('Definition holds a value that contains itself!');
|
|
200
323
|
}
|
|
201
|
-
|
|
324
|
+
ancestors.add(value);
|
|
325
|
+
const resolvedValue = Array.isArray(value)
|
|
326
|
+
? value.map((v) => this.resolveNestedEnvironmentValue(v, ancestors))
|
|
327
|
+
: Object.fromEntries(Object.entries(value).map(([key, v]) => [key, this.resolveNestedEnvironmentValue(v, ancestors)]));
|
|
328
|
+
ancestors.delete(value);
|
|
329
|
+
return resolvedValue;
|
|
202
330
|
}
|
|
331
|
+
/**
|
|
332
|
+
* Checks the definition against `octo-v1.schema.json`.
|
|
333
|
+
*/
|
|
203
334
|
validateDefinition() {
|
|
204
335
|
if (!this.definition?.version || typeof this.definition?.version !== 'number') {
|
|
205
336
|
throw new Error(`Definition version "${this.definition?.version}" must be a number!`);
|