openship 0.2.3 → 0.4.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.
Files changed (82) hide show
  1. package/README.md +104 -61
  2. package/dist/bare-ITM45QBX.js +18 -0
  3. package/dist/bowser-MFQA6OS4.js +2821 -0
  4. package/dist/chunk-3U4SPZD5.js +241 -0
  5. package/dist/chunk-46YJFP4S.js +1771 -0
  6. package/dist/chunk-4CQWT2WL.js +116 -0
  7. package/dist/chunk-4FABQGQP.js +23 -0
  8. package/dist/chunk-4LEL3H2Z.js +84 -0
  9. package/dist/chunk-4MG3BVHE.js +326 -0
  10. package/dist/chunk-4VNS5WPM.js +42 -0
  11. package/dist/chunk-5N7VUGL6.js +2094 -0
  12. package/dist/chunk-5ZCKQ2MI.js +1360 -0
  13. package/dist/chunk-6ERIMTBC.js +1412 -0
  14. package/dist/chunk-7UOB5GGQ.js +132 -0
  15. package/dist/chunk-BUBSSKO6.js +1384 -0
  16. package/dist/chunk-E6W2JMMU.js +341 -0
  17. package/dist/chunk-E77LJWJK.js +1535 -0
  18. package/dist/chunk-F4DFVG6Q.js +573 -0
  19. package/dist/chunk-HFYDYK4D.js +1092 -0
  20. package/dist/chunk-JR2OCMJA.js +46 -0
  21. package/dist/chunk-JUJBBF5U.js +746 -0
  22. package/dist/chunk-JZLNHGLW.js +19145 -0
  23. package/dist/chunk-KD7VO4LG.js +2617 -0
  24. package/dist/chunk-LBFH7THC.js +435 -0
  25. package/dist/chunk-NB2VEIWG.js +129 -0
  26. package/dist/chunk-OJE6YWPQ.js +2866 -0
  27. package/dist/chunk-QKFRZNKN.js +4941 -0
  28. package/dist/chunk-RBZPFTHV.js +13354 -0
  29. package/dist/chunk-S6DSRLNE.js +121 -0
  30. package/dist/chunk-TEYJYSMT.js +409 -0
  31. package/dist/chunk-U2DPZSXA.js +112 -0
  32. package/dist/chunk-WJPCBU7Z.js +3147 -0
  33. package/dist/chunk-XIFRMKYT.js +13 -0
  34. package/dist/chunk-XVSAUO2I.js +7946 -0
  35. package/dist/chunk-Y37KHU7L.js +31 -0
  36. package/dist/chunk-YL67EWYZ.js +416 -0
  37. package/dist/chunk-ZKJOFWBJ.js +1879 -0
  38. package/dist/cloud-JMPHO3CW.js +7 -0
  39. package/dist/cloud-W5G6YXAY.js +24 -0
  40. package/dist/dist-L3MPOWCA.js +65 -0
  41. package/dist/dist-es-4C322O5D.js +22 -0
  42. package/dist/dist-es-GTAMF674.js +87 -0
  43. package/dist/dist-es-KE56MWYO.js +169 -0
  44. package/dist/dist-es-NRZIQY5B.js +484 -0
  45. package/dist/dist-es-WZCR7DHQ.js +317 -0
  46. package/dist/dist-es-XQCOTGC7.js +376 -0
  47. package/dist/dist-es-ZW3HFQUM.js +69 -0
  48. package/dist/docker-3FVJMFC3.js +12 -0
  49. package/dist/docker-edge-executor-ZIWAZWPL.js +9 -0
  50. package/dist/edge-import-53M5DGWZ.js +39 -0
  51. package/dist/event-streams-7LGDL56D.js +42 -0
  52. package/dist/executor-J7BHW5HF.js +26 -0
  53. package/dist/index.js +2459 -3461
  54. package/dist/loadSso-N273C5I7.js +577 -0
  55. package/dist/nginx-YZWKYKQU.js +16 -0
  56. package/dist/noop-RRNCIUI5.js +7 -0
  57. package/dist/openresty-lua-HAO4EUDY.js +32 -0
  58. package/dist/server/index.js +217916 -205055
  59. package/dist/server/migrations/0057_complete_prism.sql +18 -0
  60. package/dist/server/migrations/0058_add_server_is_local.sql +1 -0
  61. package/dist/server/migrations/0059_legal_fixer.sql +18 -0
  62. package/dist/server/migrations/0060_add_route_strategy_host_port.sql +3 -0
  63. package/dist/server/migrations/0061_notification_default_multi_kind.sql +3 -0
  64. package/dist/server/migrations/0062_add_incoming_webhook.sql +21 -0
  65. package/dist/server/migrations/0063_add_migration_logs.sql +1 -0
  66. package/dist/server/migrations/0064_add_migration_partial.sql +2 -0
  67. package/dist/server/migrations/0065_custom_app_template.sql +14 -0
  68. package/dist/server/migrations/0066_ensure_migration_partial_columns.sql +2 -0
  69. package/dist/server/migrations/0067_webhook_delivery.sql +28 -0
  70. package/dist/server/migrations/0068_add_migration_target_volumes.sql +1 -0
  71. package/dist/server/migrations/0069_add_project_composite_routes.sql +1 -0
  72. package/dist/server/migrations/0070_forward_git_to_server.sql +1 -0
  73. package/dist/server/migrations/meta/0057_snapshot.json +9326 -0
  74. package/dist/server/migrations/meta/0058_snapshot.json +9333 -0
  75. package/dist/server/migrations/meta/0059_snapshot.json +9495 -0
  76. package/dist/server/migrations/meta/0060_snapshot.json +9515 -0
  77. package/dist/server/migrations/meta/_journal.json +99 -1
  78. package/dist/setup-5X3WEEHA.js +14 -0
  79. package/dist/signin-DR462ERO.js +663 -0
  80. package/dist/sso-oidc-VBZLJUK5.js +830 -0
  81. package/dist/sts-EJLZ4Z77.js +1422 -0
  82. package/package.json +6 -2
@@ -0,0 +1,1092 @@
1
+ import {
2
+ assembleGitClone,
3
+ localGitSshWriter,
4
+ materializeGitSsh,
5
+ sq
6
+ } from "./chunk-YL67EWYZ.js";
7
+ import {
8
+ getTarCreateEnv,
9
+ prepareSourceTarArgs
10
+ } from "./chunk-4MG3BVHE.js";
11
+ import {
12
+ packageManagerEnsureCommand
13
+ } from "./chunk-JZLNHGLW.js";
14
+ import {
15
+ __commonJS,
16
+ __toESM
17
+ } from "./chunk-4VNS5WPM.js";
18
+
19
+ // ../../node_modules/ignore/index.js
20
+ var require_ignore = __commonJS({
21
+ "../../node_modules/ignore/index.js"(exports, module) {
22
+ "use strict";
23
+ function makeArray(subject) {
24
+ return Array.isArray(subject) ? subject : [subject];
25
+ }
26
+ var UNDEFINED = void 0;
27
+ var EMPTY = "";
28
+ var SPACE = " ";
29
+ var ESCAPE = "\\";
30
+ var REGEX_TEST_BLANK_LINE = /^\s+$/;
31
+ var REGEX_INVALID_TRAILING_BACKSLASH = /(?:[^\\]|^)\\$/;
32
+ var REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/;
33
+ var REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/;
34
+ var REGEX_SPLITALL_CRLF = /\r?\n/g;
35
+ var REGEX_TEST_INVALID_PATH = /^\.{0,2}\/|^\.{1,2}$/;
36
+ var REGEX_TEST_TRAILING_SLASH = /\/$/;
37
+ var SLASH = "/";
38
+ var TMP_KEY_IGNORE = "node-ignore";
39
+ if (typeof Symbol !== "undefined") {
40
+ TMP_KEY_IGNORE = /* @__PURE__ */ Symbol.for("node-ignore");
41
+ }
42
+ var KEY_IGNORE = TMP_KEY_IGNORE;
43
+ var define = (object, key, value) => {
44
+ Object.defineProperty(object, key, { value });
45
+ return value;
46
+ };
47
+ var REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g;
48
+ var RETURN_FALSE = () => false;
49
+ var sanitizeRange = (range) => range.replace(
50
+ REGEX_REGEXP_RANGE,
51
+ (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0) ? match : EMPTY
52
+ );
53
+ var cleanRangeBackSlash = (slashes) => {
54
+ const { length } = slashes;
55
+ return slashes.slice(0, length - length % 2);
56
+ };
57
+ var REPLACERS = [
58
+ [
59
+ // Remove BOM
60
+ // TODO:
61
+ // Other similar zero-width characters?
62
+ /^\uFEFF/,
63
+ () => EMPTY
64
+ ],
65
+ // > Trailing spaces are ignored unless they are quoted with backslash ("\")
66
+ [
67
+ // (a\ ) -> (a )
68
+ // (a ) -> (a)
69
+ // (a ) -> (a)
70
+ // (a \ ) -> (a )
71
+ /((?:\\\\)*?)(\\?\s+)$/,
72
+ (_, m1, m2) => m1 + (m2.indexOf("\\") === 0 ? SPACE : EMPTY)
73
+ ],
74
+ // Replace (\ ) with ' '
75
+ // (\ ) -> ' '
76
+ // (\\ ) -> '\\ '
77
+ // (\\\ ) -> '\\ '
78
+ [
79
+ /(\\+?)\s/g,
80
+ (_, m1) => {
81
+ const { length } = m1;
82
+ return m1.slice(0, length - length % 2) + SPACE;
83
+ }
84
+ ],
85
+ // Escape metacharacters
86
+ // which is written down by users but means special for regular expressions.
87
+ // > There are 12 characters with special meanings:
88
+ // > - the backslash \,
89
+ // > - the caret ^,
90
+ // > - the dollar sign $,
91
+ // > - the period or dot .,
92
+ // > - the vertical bar or pipe symbol |,
93
+ // > - the question mark ?,
94
+ // > - the asterisk or star *,
95
+ // > - the plus sign +,
96
+ // > - the opening parenthesis (,
97
+ // > - the closing parenthesis ),
98
+ // > - and the opening square bracket [,
99
+ // > - the opening curly brace {,
100
+ // > These special characters are often called "metacharacters".
101
+ [
102
+ /[\\$.|*+(){^]/g,
103
+ (match) => `\\${match}`
104
+ ],
105
+ [
106
+ // > a question mark (?) matches a single character
107
+ /(?!\\)\?/g,
108
+ () => "[^/]"
109
+ ],
110
+ // leading slash
111
+ [
112
+ // > A leading slash matches the beginning of the pathname.
113
+ // > For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c".
114
+ // A leading slash matches the beginning of the pathname
115
+ /^\//,
116
+ () => "^"
117
+ ],
118
+ // replace special metacharacter slash after the leading slash
119
+ [
120
+ /\//g,
121
+ () => "\\/"
122
+ ],
123
+ [
124
+ // > A leading "**" followed by a slash means match in all directories.
125
+ // > For example, "**/foo" matches file or directory "foo" anywhere,
126
+ // > the same as pattern "foo".
127
+ // > "**/foo/bar" matches file or directory "bar" anywhere that is directly
128
+ // > under directory "foo".
129
+ // Notice that the '*'s have been replaced as '\\*'
130
+ /^\^*\\\*\\\*\\\//,
131
+ // '**/foo' <-> 'foo'
132
+ () => "^(?:.*\\/)?"
133
+ ],
134
+ // starting
135
+ [
136
+ // there will be no leading '/'
137
+ // (which has been replaced by section "leading slash")
138
+ // If starts with '**', adding a '^' to the regular expression also works
139
+ /^(?=[^^])/,
140
+ function startingReplacer() {
141
+ return !/\/(?!$)/.test(this) ? "(?:^|\\/)" : "^";
142
+ }
143
+ ],
144
+ // two globstars
145
+ [
146
+ // Use lookahead assertions so that we could match more than one `'/**'`
147
+ /\\\/\\\*\\\*(?=\\\/|$)/g,
148
+ // Zero, one or several directories
149
+ // should not use '*', or it will be replaced by the next replacer
150
+ // Check if it is not the last `'/**'`
151
+ (_, index, str) => index + 6 < str.length ? "(?:\\/[^\\/]+)*" : "\\/.+"
152
+ ],
153
+ // normal intermediate wildcards
154
+ [
155
+ // Never replace escaped '*'
156
+ // ignore rule '\*' will match the path '*'
157
+ // 'abc.*/' -> go
158
+ // 'abc.*' -> skip this rule,
159
+ // coz trailing single wildcard will be handed by [trailing wildcard]
160
+ /(^|[^\\]+)(\\\*)+(?=.+)/g,
161
+ // '*.js' matches '.js'
162
+ // '*.js' doesn't match 'abc'
163
+ (_, p1, p2) => {
164
+ const unescaped = p2.replace(/\\\*/g, "[^\\/]*");
165
+ return p1 + unescaped;
166
+ }
167
+ ],
168
+ [
169
+ // unescape, revert step 3 except for back slash
170
+ // For example, if a user escape a '\\*',
171
+ // after step 3, the result will be '\\\\\\*'
172
+ /\\\\\\(?=[$.|*+(){^])/g,
173
+ () => ESCAPE
174
+ ],
175
+ [
176
+ // '\\\\' -> '\\'
177
+ /\\\\/g,
178
+ () => ESCAPE
179
+ ],
180
+ [
181
+ // > The range notation, e.g. [a-zA-Z],
182
+ // > can be used to match one of the characters in a range.
183
+ // `\` is escaped by step 3
184
+ /(\\)?\[([^\]/]*?)(\\*)($|\])/g,
185
+ (match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE ? `\\[${range}${cleanRangeBackSlash(endEscape)}${close}` : close === "]" ? endEscape.length % 2 === 0 ? `[${sanitizeRange(range)}${endEscape}]` : "[]" : "[]"
186
+ ],
187
+ // ending
188
+ [
189
+ // 'js' will not match 'js.'
190
+ // 'ab' will not match 'abc'
191
+ /(?:[^*])$/,
192
+ // WTF!
193
+ // https://git-scm.com/docs/gitignore
194
+ // changes in [2.22.1](https://git-scm.com/docs/gitignore/2.22.1)
195
+ // which re-fixes #24, #38
196
+ // > If there is a separator at the end of the pattern then the pattern
197
+ // > will only match directories, otherwise the pattern can match both
198
+ // > files and directories.
199
+ // 'js*' will not match 'a.js'
200
+ // 'js/' will not match 'a.js'
201
+ // 'js' will match 'a.js' and 'a.js/'
202
+ (match) => /\/$/.test(match) ? `${match}$` : `${match}(?=$|\\/$)`
203
+ ]
204
+ ];
205
+ var REGEX_REPLACE_TRAILING_WILDCARD = /(^|\\\/)?\\\*$/;
206
+ var MODE_IGNORE = "regex";
207
+ var MODE_CHECK_IGNORE = "checkRegex";
208
+ var UNDERSCORE = "_";
209
+ var TRAILING_WILD_CARD_REPLACERS = {
210
+ [MODE_IGNORE](_, p1) {
211
+ const prefix = p1 ? `${p1}[^/]+` : "[^/]*";
212
+ return `${prefix}(?=$|\\/$)`;
213
+ },
214
+ [MODE_CHECK_IGNORE](_, p1) {
215
+ const prefix = p1 ? `${p1}[^/]*` : "[^/]*";
216
+ return `${prefix}(?=$|\\/$)`;
217
+ }
218
+ };
219
+ var makeRegexPrefix = (pattern) => REPLACERS.reduce(
220
+ (prev, [matcher, replacer]) => prev.replace(matcher, replacer.bind(pattern)),
221
+ pattern
222
+ );
223
+ var isString = (subject) => typeof subject === "string";
224
+ var checkPattern = (pattern) => pattern && isString(pattern) && !REGEX_TEST_BLANK_LINE.test(pattern) && !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern) && pattern.indexOf("#") !== 0;
225
+ var splitPattern = (pattern) => pattern.split(REGEX_SPLITALL_CRLF).filter(Boolean);
226
+ var IgnoreRule = class {
227
+ constructor(pattern, mark, body, ignoreCase, negative, prefix) {
228
+ this.pattern = pattern;
229
+ this.mark = mark;
230
+ this.negative = negative;
231
+ define(this, "body", body);
232
+ define(this, "ignoreCase", ignoreCase);
233
+ define(this, "regexPrefix", prefix);
234
+ }
235
+ get regex() {
236
+ const key = UNDERSCORE + MODE_IGNORE;
237
+ if (this[key]) {
238
+ return this[key];
239
+ }
240
+ return this._make(MODE_IGNORE, key);
241
+ }
242
+ get checkRegex() {
243
+ const key = UNDERSCORE + MODE_CHECK_IGNORE;
244
+ if (this[key]) {
245
+ return this[key];
246
+ }
247
+ return this._make(MODE_CHECK_IGNORE, key);
248
+ }
249
+ _make(mode, key) {
250
+ const str = this.regexPrefix.replace(
251
+ REGEX_REPLACE_TRAILING_WILDCARD,
252
+ // It does not need to bind pattern
253
+ TRAILING_WILD_CARD_REPLACERS[mode]
254
+ );
255
+ const regex = this.ignoreCase ? new RegExp(str, "i") : new RegExp(str);
256
+ return define(this, key, regex);
257
+ }
258
+ };
259
+ var createRule = ({
260
+ pattern,
261
+ mark
262
+ }, ignoreCase) => {
263
+ let negative = false;
264
+ let body = pattern;
265
+ if (body.indexOf("!") === 0) {
266
+ negative = true;
267
+ body = body.substr(1);
268
+ }
269
+ body = body.replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, "!").replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, "#");
270
+ const regexPrefix = makeRegexPrefix(body);
271
+ return new IgnoreRule(
272
+ pattern,
273
+ mark,
274
+ body,
275
+ ignoreCase,
276
+ negative,
277
+ regexPrefix
278
+ );
279
+ };
280
+ var RuleManager = class {
281
+ constructor(ignoreCase) {
282
+ this._ignoreCase = ignoreCase;
283
+ this._rules = [];
284
+ }
285
+ _add(pattern) {
286
+ if (pattern && pattern[KEY_IGNORE]) {
287
+ this._rules = this._rules.concat(pattern._rules._rules);
288
+ this._added = true;
289
+ return;
290
+ }
291
+ if (isString(pattern)) {
292
+ pattern = {
293
+ pattern
294
+ };
295
+ }
296
+ if (checkPattern(pattern.pattern)) {
297
+ const rule = createRule(pattern, this._ignoreCase);
298
+ this._added = true;
299
+ this._rules.push(rule);
300
+ }
301
+ }
302
+ // @param {Array<string> | string | Ignore} pattern
303
+ add(pattern) {
304
+ this._added = false;
305
+ makeArray(
306
+ isString(pattern) ? splitPattern(pattern) : pattern
307
+ ).forEach(this._add, this);
308
+ return this._added;
309
+ }
310
+ // Test one single path without recursively checking parent directories
311
+ //
312
+ // - checkUnignored `boolean` whether should check if the path is unignored,
313
+ // setting `checkUnignored` to `false` could reduce additional
314
+ // path matching.
315
+ // - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
316
+ // @returns {TestResult} true if a file is ignored
317
+ test(path, checkUnignored, mode) {
318
+ let ignored = false;
319
+ let unignored = false;
320
+ let matchedRule;
321
+ this._rules.forEach((rule) => {
322
+ const { negative } = rule;
323
+ if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
324
+ return;
325
+ }
326
+ const matched = rule[mode].test(path);
327
+ if (!matched) {
328
+ return;
329
+ }
330
+ ignored = !negative;
331
+ unignored = negative;
332
+ matchedRule = negative ? UNDEFINED : rule;
333
+ });
334
+ const ret = {
335
+ ignored,
336
+ unignored
337
+ };
338
+ if (matchedRule) {
339
+ ret.rule = matchedRule;
340
+ }
341
+ return ret;
342
+ }
343
+ };
344
+ var throwError = (message, Ctor) => {
345
+ throw new Ctor(message);
346
+ };
347
+ var checkPath = (path, originalPath, doThrow) => {
348
+ if (!isString(path)) {
349
+ return doThrow(
350
+ `path must be a string, but got \`${originalPath}\``,
351
+ TypeError
352
+ );
353
+ }
354
+ if (!path) {
355
+ return doThrow(`path must not be empty`, TypeError);
356
+ }
357
+ if (checkPath.isNotRelative(path)) {
358
+ const r = "`path.relative()`d";
359
+ return doThrow(
360
+ `path should be a ${r} string, but got "${originalPath}"`,
361
+ RangeError
362
+ );
363
+ }
364
+ return true;
365
+ };
366
+ var isNotRelative = (path) => REGEX_TEST_INVALID_PATH.test(path);
367
+ checkPath.isNotRelative = isNotRelative;
368
+ checkPath.convert = (p) => p;
369
+ var Ignore = class {
370
+ constructor({
371
+ ignorecase = true,
372
+ ignoreCase = ignorecase,
373
+ allowRelativePaths = false
374
+ } = {}) {
375
+ define(this, KEY_IGNORE, true);
376
+ this._rules = new RuleManager(ignoreCase);
377
+ this._strictPathCheck = !allowRelativePaths;
378
+ this._initCache();
379
+ }
380
+ _initCache() {
381
+ this._ignoreCache = /* @__PURE__ */ Object.create(null);
382
+ this._testCache = /* @__PURE__ */ Object.create(null);
383
+ }
384
+ add(pattern) {
385
+ if (this._rules.add(pattern)) {
386
+ this._initCache();
387
+ }
388
+ return this;
389
+ }
390
+ // legacy
391
+ addPattern(pattern) {
392
+ return this.add(pattern);
393
+ }
394
+ // @returns {TestResult}
395
+ _test(originalPath, cache, checkUnignored, slices) {
396
+ const path = originalPath && checkPath.convert(originalPath);
397
+ checkPath(
398
+ path,
399
+ originalPath,
400
+ this._strictPathCheck ? throwError : RETURN_FALSE
401
+ );
402
+ return this._t(path, cache, checkUnignored, slices);
403
+ }
404
+ checkIgnore(path) {
405
+ if (!REGEX_TEST_TRAILING_SLASH.test(path)) {
406
+ return this.test(path);
407
+ }
408
+ const slices = path.split(SLASH).filter(Boolean);
409
+ slices.pop();
410
+ if (slices.length) {
411
+ const parent = this._t(
412
+ slices.join(SLASH) + SLASH,
413
+ this._testCache,
414
+ true,
415
+ slices
416
+ );
417
+ if (parent.ignored) {
418
+ return parent;
419
+ }
420
+ }
421
+ return this._rules.test(path, false, MODE_CHECK_IGNORE);
422
+ }
423
+ _t(path, cache, checkUnignored, slices) {
424
+ if (path in cache) {
425
+ return cache[path];
426
+ }
427
+ if (!slices) {
428
+ slices = path.split(SLASH).filter(Boolean);
429
+ }
430
+ slices.pop();
431
+ if (!slices.length) {
432
+ return cache[path] = this._rules.test(path, checkUnignored, MODE_IGNORE);
433
+ }
434
+ const parent = this._t(
435
+ slices.join(SLASH) + SLASH,
436
+ cache,
437
+ checkUnignored,
438
+ slices
439
+ );
440
+ return cache[path] = parent.ignored ? parent : this._rules.test(path, checkUnignored, MODE_IGNORE);
441
+ }
442
+ ignores(path) {
443
+ return this._test(path, this._ignoreCache, false).ignored;
444
+ }
445
+ createFilter() {
446
+ return (path) => !this.ignores(path);
447
+ }
448
+ filter(paths) {
449
+ return makeArray(paths).filter(this.createFilter());
450
+ }
451
+ // @returns {TestResult}
452
+ test(path) {
453
+ return this._test(path, this._testCache, true);
454
+ }
455
+ };
456
+ var factory = (options) => new Ignore(options);
457
+ var isPathValid = (path) => checkPath(path && checkPath.convert(path), path, RETURN_FALSE);
458
+ var setupWindows = () => {
459
+ const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
460
+ checkPath.convert = makePosix;
461
+ const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
462
+ checkPath.isNotRelative = (path) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path) || isNotRelative(path);
463
+ };
464
+ if (
465
+ // Detect `process` so that it can run in browsers.
466
+ typeof process !== "undefined" && process.platform === "win32"
467
+ ) {
468
+ setupWindows();
469
+ }
470
+ module.exports = factory;
471
+ factory.default = factory;
472
+ module.exports.isPathValid = isPathValid;
473
+ define(module.exports, /* @__PURE__ */ Symbol.for("setupWindows"), setupWindows);
474
+ }
475
+ });
476
+
477
+ // ../../packages/adapters/src/runtime/docker-paths.ts
478
+ import { access, readdir } from "fs/promises";
479
+ import { isAbsolute, join, relative, sep } from "path";
480
+ function toPosixPath(value) {
481
+ return value.split(sep).filter(Boolean).join("/");
482
+ }
483
+ function normalizeDockerRelativePath(value) {
484
+ const normalized = value?.trim().replace(/^\.\//, "").replace(/^\/+|\/+$/g, "");
485
+ if (!normalized || normalized === ".") {
486
+ return "";
487
+ }
488
+ return normalized.split(/[\\/]/).filter(Boolean).join("/");
489
+ }
490
+ function normalizeDockerRootDirectory(rootDirectory, localPath) {
491
+ let normalized = rootDirectory?.trim() ?? "";
492
+ if (!normalized) {
493
+ return "";
494
+ }
495
+ if (localPath && isAbsolute(normalized)) {
496
+ const relativePath = relative(localPath, normalized);
497
+ if (!relativePath || relativePath === ".") {
498
+ return "";
499
+ }
500
+ if (!relativePath.startsWith("..") && !isAbsolute(relativePath)) {
501
+ normalized = relativePath;
502
+ }
503
+ }
504
+ normalized = normalized.replace(/^\.\//, "").replace(/^\/+|\/+$/g, "");
505
+ if (!normalized || normalized === ".") {
506
+ return "";
507
+ }
508
+ return toPosixPath(normalized);
509
+ }
510
+ function resolveExplicitDockerfileCandidate(rootDirectory, dockerfilePath) {
511
+ const normalizedRootDirectory = normalizeDockerRelativePath(rootDirectory);
512
+ const normalizedDockerfilePath = normalizeDockerRelativePath(dockerfilePath);
513
+ if (!normalizedDockerfilePath) {
514
+ return "";
515
+ }
516
+ if (!normalizedRootDirectory) {
517
+ return normalizedDockerfilePath;
518
+ }
519
+ if (normalizedDockerfilePath.startsWith(`${normalizedRootDirectory}/`)) {
520
+ return normalizedDockerfilePath;
521
+ }
522
+ return `${normalizedRootDirectory}/${normalizedDockerfilePath}`;
523
+ }
524
+ function resolveDockerfileCandidates(rootDirectory, explicitDockerfilePath) {
525
+ const normalizedRootDirectory = normalizeDockerRelativePath(rootDirectory);
526
+ return [
527
+ resolveExplicitDockerfileCandidate(rootDirectory, explicitDockerfilePath),
528
+ normalizedRootDirectory ? `${normalizedRootDirectory}/Dockerfile` : "Dockerfile",
529
+ "Dockerfile"
530
+ ].filter(
531
+ (candidate, index, values) => Boolean(candidate) && values.indexOf(candidate) === index
532
+ );
533
+ }
534
+ var ROOT_MANIFESTS = [
535
+ "package.json",
536
+ "pyproject.toml",
537
+ "requirements.txt",
538
+ "Pipfile",
539
+ "go.mod",
540
+ "Cargo.toml",
541
+ "Gemfile",
542
+ "composer.json",
543
+ "pom.xml",
544
+ "build.gradle",
545
+ "build.gradle.kts",
546
+ "mix.exs",
547
+ "Dockerfile"
548
+ ];
549
+ var IGNORED_DIRS = /* @__PURE__ */ new Set([
550
+ "node_modules",
551
+ ".git",
552
+ ".next",
553
+ ".nuxt",
554
+ ".output",
555
+ ".turbo",
556
+ ".venv",
557
+ "__pycache__",
558
+ "build",
559
+ "dist",
560
+ "target",
561
+ "vendor"
562
+ ]);
563
+ async function pathExists(path) {
564
+ return access(path).then(() => true).catch(() => false);
565
+ }
566
+ async function manifestCount(dir) {
567
+ let count = 0;
568
+ for (const file of ROOT_MANIFESTS) {
569
+ if (await pathExists(join(dir, file))) {
570
+ count += 1;
571
+ }
572
+ }
573
+ return count;
574
+ }
575
+ function pathSegments(path) {
576
+ return path.toLowerCase().split("/").filter(Boolean);
577
+ }
578
+ function scorePathHints(relativePath) {
579
+ const segments = pathSegments(relativePath);
580
+ let score = 0;
581
+ for (const segment of segments) {
582
+ if (["app", "apps", "site", "sites", "web", "www", "service", "services"].includes(segment)) {
583
+ score += 12;
584
+ }
585
+ if (["docs", "example", "examples", "test", "tests", "storybook"].includes(segment)) {
586
+ score -= 18;
587
+ }
588
+ }
589
+ return score;
590
+ }
591
+ async function scoreCandidate(dir, relativePath) {
592
+ let score = scorePathHints(relativePath);
593
+ score += await manifestCount(dir) * 20;
594
+ if (relativePath) {
595
+ score += 6;
596
+ }
597
+ return score;
598
+ }
599
+ async function collectCandidates(rootDir, currentDir, depth, candidates) {
600
+ const relativePath = toPosixPath(relative(rootDir, currentDir));
601
+ if (await manifestCount(currentDir) > 0) {
602
+ candidates.push({
603
+ path: relativePath,
604
+ score: await scoreCandidate(currentDir, relativePath)
605
+ });
606
+ }
607
+ if (depth >= 6) {
608
+ return;
609
+ }
610
+ const entries = await readdir(currentDir, { withFileTypes: true }).catch(() => []);
611
+ for (const entry of entries) {
612
+ if (!entry.isDirectory() || IGNORED_DIRS.has(entry.name)) {
613
+ continue;
614
+ }
615
+ await collectCandidates(rootDir, join(currentDir, entry.name), depth + 1, candidates);
616
+ }
617
+ }
618
+ async function resolveDockerRootDirectory(contextDir, rootDirectory, localPath) {
619
+ const hasExplicitRootDirectory = typeof rootDirectory === "string";
620
+ const normalized = normalizeDockerRootDirectory(rootDirectory, localPath);
621
+ if (hasExplicitRootDirectory) {
622
+ return normalized;
623
+ }
624
+ if (normalized) {
625
+ return normalized;
626
+ }
627
+ const candidates = [];
628
+ await collectCandidates(contextDir, contextDir, 0, candidates);
629
+ if (candidates.length === 0) {
630
+ return "";
631
+ }
632
+ candidates.sort((left, right) => right.score - left.score);
633
+ const bestNonRoot = candidates.find((candidate) => candidate.path);
634
+ if (bestNonRoot && bestNonRoot.score > 0) {
635
+ return bestNonRoot.path;
636
+ }
637
+ return candidates[0]?.path ?? "";
638
+ }
639
+
640
+ // ../../packages/adapters/src/runtime/docker-build-plan.ts
641
+ var DOCKER_BUILD_EVENT_PREFIX = "[openship-build]";
642
+ var INLINE_BUILD_ENV_EXCLUDES = /* @__PURE__ */ new Set(["FORCE_COLOR", "TERM"]);
643
+ function formatDockerBuildEvent(step, status) {
644
+ return `${DOCKER_BUILD_EVENT_PREFIX} step=${step} status=${status}`;
645
+ }
646
+ function normalizeRelativePath(value) {
647
+ const normalized = value?.trim().replace(/^\.\//, "").replace(/^\/+|\/+$/g, "");
648
+ if (!normalized || normalized === ".") {
649
+ return "";
650
+ }
651
+ return normalized;
652
+ }
653
+ function builderSourceDir(rootDirectory) {
654
+ const normalized = normalizeDockerRootDirectory(rootDirectory);
655
+ return normalized ? `/workspace/${normalized}` : "/workspace";
656
+ }
657
+ function buildEnvPrefix(envVars) {
658
+ const assignments = Object.entries(envVars).filter(([key]) => !INLINE_BUILD_ENV_EXCLUDES.has(key)).filter(([key]) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(key)).map(([key, value]) => `${key}=${sq(value)}`);
659
+ if (!envVars.NO_COLOR) {
660
+ assignments.push("NO_COLOR='1'");
661
+ }
662
+ if (assignments.length === 0) {
663
+ return "";
664
+ }
665
+ return `export ${assignments.join(" ")} && `;
666
+ }
667
+ function buildRunCommand(command, envPrefix) {
668
+ return `${envPrefix}${command}`;
669
+ }
670
+ function runtimeCopyDirectives(config, sourceDir) {
671
+ if (config.productionPaths && config.productionPaths.length > 0) {
672
+ return config.productionPaths.map((path) => {
673
+ const normalized = normalizeRelativePath(path);
674
+ const source = normalized ? `${sourceDir}/${normalized}` : sourceDir;
675
+ const target = normalized ? `/app/${normalized}` : "/app";
676
+ return `COPY --from=builder ${source} ${target}`;
677
+ });
678
+ }
679
+ return [`COPY --from=builder ${sourceDir} /app`];
680
+ }
681
+ function needsMultiStage(config) {
682
+ return config.buildImage !== config.runtimeImage;
683
+ }
684
+ function workspacePrepareRunLine(config, envPrefix, workspacePrepare) {
685
+ const pmEnsure = packageManagerEnsureCommand(config.packageManager);
686
+ const body = pmEnsure ? `${pmEnsure} && ${workspacePrepare}` : workspacePrepare;
687
+ return `RUN ${envPrefix}${body}`;
688
+ }
689
+ function installBuildRunLine(config, envPrefix) {
690
+ const steps = [];
691
+ const pmEnsure = packageManagerEnsureCommand(config.packageManager);
692
+ if (pmEnsure && (config.installCommand || config.buildCommand)) {
693
+ steps.push(pmEnsure);
694
+ }
695
+ if (config.installCommand) {
696
+ steps.push(`printf '${formatDockerBuildEvent("install", "running")}\\n'`);
697
+ steps.push(buildRunCommand(config.installCommand, envPrefix));
698
+ steps.push(`printf '${formatDockerBuildEvent("install", "completed")}\\n'`);
699
+ }
700
+ if (config.buildCommand) {
701
+ steps.push(`printf '${formatDockerBuildEvent("build", "running")}\\n'`);
702
+ steps.push(buildRunCommand(config.buildCommand, envPrefix));
703
+ steps.push(`printf '${formatDockerBuildEvent("build", "completed")}\\n'`);
704
+ }
705
+ return steps.length > 0 ? `RUN ${steps.join(" && ")}` : null;
706
+ }
707
+ function isPhpRuntime(config) {
708
+ return /^php:/.test(config.runtimeImage);
709
+ }
710
+ var PHP_NGINX_TEMPLATE_LINES = [
711
+ "server {",
712
+ " listen ${PORT} default_server;",
713
+ " root /app/public;",
714
+ " index index.php index.html;",
715
+ " location / { try_files $uri $uri/ /index.php?$query_string; }",
716
+ " location ~ \\.php$ {",
717
+ " fastcgi_pass 127.0.0.1:9000;",
718
+ " fastcgi_index index.php;",
719
+ " include fastcgi_params;",
720
+ " fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;",
721
+ " }",
722
+ "}"
723
+ ];
724
+ function generatePhpDockerfile(config) {
725
+ const sourceDir = builderSourceDir(
726
+ normalizeDockerRootDirectory(config.rootDirectory, config.localPath)
727
+ );
728
+ const envPrefix = buildEnvPrefix(config.envVars);
729
+ const stepsLine = installBuildRunLine(config, envPrefix);
730
+ const nginxTemplate = PHP_NGINX_TEMPLATE_LINES.map((line) => `'${line}'`).join(" ");
731
+ const lines = [
732
+ `FROM ${config.buildImage} AS builder`,
733
+ `WORKDIR /workspace`,
734
+ `COPY . /workspace`,
735
+ // php:*-cli ships no Composer — pull the binary from the official image.
736
+ `COPY --from=composer:2 /usr/bin/composer /usr/bin/composer`,
737
+ // pdo_mysql is the common denominator (Laravel/Symfony + MySQL/MariaDB);
738
+ // app-specific extensions are a per-project follow-on.
739
+ `RUN docker-php-ext-install pdo_mysql > /dev/null`,
740
+ `WORKDIR ${sourceDir}`
741
+ ];
742
+ if (stepsLine) lines.push(stepsLine);
743
+ lines.push(
744
+ `FROM ${config.runtimeImage} AS runtime`,
745
+ `RUN apt-get update && apt-get install -y --no-install-recommends nginx gettext-base && rm -rf /var/lib/apt/lists/* && rm -f /etc/nginx/sites-enabled/default && docker-php-ext-install pdo_mysql > /dev/null`,
746
+ `COPY --from=builder ${sourceDir} /app`,
747
+ `WORKDIR /app`,
748
+ `RUN printf '%s\\n' ${nginxTemplate} > /etc/nginx/app.conf.template`,
749
+ `EXPOSE ${config.port}`
750
+ );
751
+ if (config.startCommand) {
752
+ lines.push(`CMD ["sh", "-c", ${JSON.stringify(config.startCommand)}]`);
753
+ }
754
+ return lines.join("\n");
755
+ }
756
+ function staticNginxTemplateLines(port) {
757
+ return [
758
+ "server {",
759
+ ` listen ${port} default_server;`,
760
+ " root /usr/share/nginx/html;",
761
+ " index index.html;",
762
+ " location / { try_files $uri $uri/ /index.html; }",
763
+ "}"
764
+ ];
765
+ }
766
+ function generateStaticDockerfile(config) {
767
+ const sourceDir = builderSourceDir(
768
+ normalizeDockerRootDirectory(config.rootDirectory, config.localPath)
769
+ );
770
+ const envPrefix = buildEnvPrefix(config.envVars);
771
+ const workspacePrepare = config.workspacePrepareCommand?.trim();
772
+ const output = normalizeRelativePath(config.outputDirectory);
773
+ const outputPath = output ? `${sourceDir}/${output}` : sourceDir;
774
+ const nginxTemplate = staticNginxTemplateLines(config.port).map((line) => `'${line}'`).join(" ");
775
+ const lines = [
776
+ `FROM ${config.buildImage} AS builder`,
777
+ `WORKDIR /workspace`,
778
+ `COPY . /workspace`
779
+ ];
780
+ if (workspacePrepare) {
781
+ lines.push(workspacePrepareRunLine(config, envPrefix, workspacePrepare));
782
+ }
783
+ lines.push(`WORKDIR ${sourceDir}`);
784
+ const stepsLine = installBuildRunLine(config, envPrefix);
785
+ if (stepsLine) lines.push(stepsLine);
786
+ lines.push(
787
+ `FROM nginx:alpine AS runtime`,
788
+ `RUN rm -f /etc/nginx/conf.d/default.conf`,
789
+ `COPY --from=builder ${outputPath} /usr/share/nginx/html`,
790
+ `RUN printf '%s\\n' ${nginxTemplate} > /etc/nginx/conf.d/app.conf`,
791
+ `EXPOSE ${config.port}`,
792
+ `CMD ["nginx", "-g", "daemon off;"]`
793
+ );
794
+ return lines.join("\n");
795
+ }
796
+ function generateDockerfile(config) {
797
+ if (config.isStatic) {
798
+ return generateStaticDockerfile(config);
799
+ }
800
+ if (isPhpRuntime(config) && needsMultiStage(config)) {
801
+ return generatePhpDockerfile(config);
802
+ }
803
+ const sourceDir = builderSourceDir(
804
+ normalizeDockerRootDirectory(config.rootDirectory, config.localPath)
805
+ );
806
+ const multiStage = needsMultiStage(config);
807
+ const envPrefix = buildEnvPrefix(config.envVars);
808
+ const workspacePrepare = config.workspacePrepareCommand?.trim();
809
+ const lines = multiStage ? [
810
+ `FROM ${config.buildImage} AS builder`,
811
+ `WORKDIR /workspace`,
812
+ `COPY . /workspace`
813
+ ] : [
814
+ `FROM ${config.runtimeImage}`,
815
+ `WORKDIR /workspace`,
816
+ `COPY . /workspace`
817
+ ];
818
+ if (workspacePrepare) {
819
+ lines.push(workspacePrepareRunLine(config, envPrefix, workspacePrepare));
820
+ }
821
+ lines.push(`WORKDIR ${sourceDir}`);
822
+ const stepsLine = installBuildRunLine(config, envPrefix);
823
+ if (stepsLine) {
824
+ lines.push(stepsLine);
825
+ }
826
+ if (multiStage) {
827
+ lines.push(`FROM ${config.runtimeImage} AS runtime`);
828
+ lines.push(...runtimeCopyDirectives(config, sourceDir));
829
+ lines.push(`WORKDIR /app`);
830
+ }
831
+ lines.push(`EXPOSE ${config.port}`);
832
+ if (config.startCommand) {
833
+ lines.push(`CMD ["sh", "-c", ${JSON.stringify(config.startCommand)}]`);
834
+ }
835
+ return lines.join("\n");
836
+ }
837
+
838
+ // ../../packages/adapters/src/runtime/docker-build-context.ts
839
+ var import_ignore = __toESM(require_ignore(), 1);
840
+ import { spawn } from "child_process";
841
+ import { access as access2, mkdtemp, readdir as readdir2, readFile, rm, writeFile } from "fs/promises";
842
+ import { tmpdir } from "os";
843
+ import { join as join2, relative as relative2, sep as sep2 } from "path";
844
+ var GIT_CLONE_IDLE_TIMEOUT_MS = 5 * 6e4;
845
+ var GIT_CHECKOUT_IDLE_TIMEOUT_MS = 6e4;
846
+ function spawnGit(args, opts) {
847
+ return new Promise((resolve, reject) => {
848
+ const child = spawn("git", args, {
849
+ stdio: ["ignore", "pipe", "pipe"],
850
+ env: {
851
+ ...process.env,
852
+ GIT_TERMINAL_PROMPT: "0",
853
+ GIT_ASKPASS: "/bin/echo",
854
+ ...opts.env
855
+ }
856
+ });
857
+ let stderr = "";
858
+ const emit = opts.onLog;
859
+ const flushLine = (line) => {
860
+ const trimmed = line.trimEnd();
861
+ if (!trimmed) return;
862
+ if (emit) {
863
+ emit({ timestamp: (/* @__PURE__ */ new Date()).toISOString(), message: trimmed, level: "info" });
864
+ }
865
+ };
866
+ let idleTimer;
867
+ const armIdle = () => {
868
+ clearTimeout(idleTimer);
869
+ idleTimer = setTimeout(() => {
870
+ child.kill("SIGKILL");
871
+ reject(
872
+ new Error(
873
+ `git ${args.find((a) => !a.startsWith("-")) ?? "command"} stalled \u2014 no progress for ${Math.round(
874
+ opts.timeoutMs / 1e3
875
+ )}s`
876
+ )
877
+ );
878
+ }, opts.timeoutMs);
879
+ };
880
+ child.stdout?.on("data", (buf) => {
881
+ armIdle();
882
+ for (const ln of buf.toString().split(/\r?\n/)) flushLine(ln);
883
+ });
884
+ child.stderr?.on("data", (buf) => {
885
+ armIdle();
886
+ const text = buf.toString();
887
+ stderr += text;
888
+ for (const ln of text.split(/\r?\n/)) flushLine(ln);
889
+ });
890
+ armIdle();
891
+ child.on("error", (err) => {
892
+ clearTimeout(idleTimer);
893
+ reject(err);
894
+ });
895
+ child.on("close", (code) => {
896
+ clearTimeout(idleTimer);
897
+ if (code === 0) resolve();
898
+ else reject(new Error(`git exited with code ${code}: ${stderr.trim().slice(-500) || "no stderr"}`));
899
+ });
900
+ });
901
+ }
902
+ var GENERATED_DOCKERFILE_NAME = "Dockerfile.openship";
903
+ function toPosixPath2(value) {
904
+ return value.split(sep2).filter(Boolean).join("/");
905
+ }
906
+ async function loadDockerignoreMatcher(rootPath) {
907
+ try {
908
+ return (0, import_ignore.default)().add(await readFile(join2(rootPath, ".dockerignore"), "utf-8"));
909
+ } catch {
910
+ return void 0;
911
+ }
912
+ }
913
+ async function applyDockerignore(contextDir) {
914
+ const matcher = await loadDockerignoreMatcher(contextDir);
915
+ if (!matcher) return;
916
+ const prune = async (currentPath) => {
917
+ const entries = await readdir2(currentPath, { withFileTypes: true });
918
+ await Promise.all(
919
+ entries.map(async (entry) => {
920
+ const absolutePath = join2(currentPath, entry.name);
921
+ const relativePath = relative2(contextDir, absolutePath);
922
+ if (matcher.ignores(toPosixPath2(relativePath))) {
923
+ await rm(absolutePath, { recursive: true, force: true });
924
+ return;
925
+ }
926
+ if (entry.isDirectory()) await prune(absolutePath);
927
+ })
928
+ );
929
+ };
930
+ await prune(contextDir);
931
+ }
932
+ async function materializeLocalSource(sourcePath, targetPath) {
933
+ const { args, cleanup } = await prepareSourceTarArgs(sourcePath);
934
+ try {
935
+ await new Promise((resolve, reject) => {
936
+ const create = spawn("tar", args, { env: getTarCreateEnv() });
937
+ const extract = spawn("tar", ["-xzf", "-", "-C", targetPath]);
938
+ let err = "";
939
+ create.stderr.on("data", (d) => err += d.toString());
940
+ extract.stderr.on("data", (d) => err += d.toString());
941
+ create.on("error", reject);
942
+ extract.on("error", reject);
943
+ create.stdout.pipe(extract.stdin);
944
+ extract.on(
945
+ "close",
946
+ (code) => code === 0 ? resolve() : reject(new Error(`context materialize failed (tar ${code}): ${err.trim().slice(-500)}`))
947
+ );
948
+ });
949
+ } finally {
950
+ await cleanup();
951
+ }
952
+ }
953
+ async function resolveDockerfileName(contextDir, rootDirectory, explicitDockerfilePath) {
954
+ const candidates = resolveDockerfileCandidates(rootDirectory, explicitDockerfilePath);
955
+ for (const candidate of candidates) {
956
+ const candidatePath = join2(contextDir, ...candidate.split("/"));
957
+ const exists = await access2(candidatePath).then(() => true).catch(() => false);
958
+ if (exists) {
959
+ return candidate;
960
+ }
961
+ }
962
+ return null;
963
+ }
964
+ async function cloneGitSource(config, targetPath, onLog) {
965
+ let sshMaterial;
966
+ if (config.gitSsh) {
967
+ sshMaterial = await materializeGitSsh(
968
+ localGitSshWriter(),
969
+ await mkdtemp(join2(tmpdir(), "opsh-ghkey-")),
970
+ config.gitSsh
971
+ );
972
+ }
973
+ const { cloneUrl, env: gitEnv, credArgs } = assembleGitClone({
974
+ repoUrl: config.repoUrl,
975
+ gitToken: config.gitToken,
976
+ ssh: sshMaterial
977
+ });
978
+ try {
979
+ await spawnGit(
980
+ [
981
+ ...credArgs,
982
+ "clone",
983
+ "--progress",
984
+ "--depth",
985
+ config.commitSha ? "50" : "1",
986
+ "--branch",
987
+ config.branch,
988
+ cloneUrl,
989
+ targetPath
990
+ ],
991
+ { timeoutMs: GIT_CLONE_IDLE_TIMEOUT_MS, onLog, env: gitEnv }
992
+ );
993
+ if (config.commitSha) {
994
+ await spawnGit([...credArgs, "-C", targetPath, "checkout", config.commitSha], {
995
+ timeoutMs: GIT_CHECKOUT_IDLE_TIMEOUT_MS,
996
+ onLog,
997
+ env: gitEnv
998
+ });
999
+ }
1000
+ await rm(join2(targetPath, ".git"), { recursive: true, force: true });
1001
+ } finally {
1002
+ await sshMaterial?.cleanup();
1003
+ }
1004
+ }
1005
+ async function prepareSourceTree(config, opts) {
1006
+ const contextDir = await mkdtemp(join2(tmpdir(), "openship-docker-context-"));
1007
+ try {
1008
+ if (config.localPath) {
1009
+ await materializeLocalSource(config.localPath, contextDir);
1010
+ } else {
1011
+ await cloneGitSource(config, contextDir, opts?.onLog);
1012
+ }
1013
+ await applyDockerignore(contextDir);
1014
+ return {
1015
+ contextDir,
1016
+ cleanup: async () => {
1017
+ await rm(contextDir, { recursive: true, force: true }).catch(() => {
1018
+ });
1019
+ }
1020
+ };
1021
+ } catch (error) {
1022
+ await rm(contextDir, { recursive: true, force: true }).catch(() => {
1023
+ });
1024
+ throw error;
1025
+ }
1026
+ }
1027
+ async function resolveServiceDockerfile(contextDir, config, opts) {
1028
+ const requireRepositoryDockerfile = opts?.requireRepositoryDockerfile ?? false;
1029
+ const generatedName = opts?.generatedName ?? GENERATED_DOCKERFILE_NAME;
1030
+ const resolvedRootDirectory = await resolveDockerRootDirectory(
1031
+ contextDir,
1032
+ config.rootDirectory,
1033
+ config.localPath
1034
+ );
1035
+ const repositoryDockerfileName = await resolveDockerfileName(
1036
+ contextDir,
1037
+ resolvedRootDirectory,
1038
+ config.dockerfilePath
1039
+ );
1040
+ const hasRepositoryDockerfile = repositoryDockerfileName !== null;
1041
+ if (!hasRepositoryDockerfile && requireRepositoryDockerfile) {
1042
+ const expectedDockerfile = config.dockerfilePath?.trim() || "Dockerfile";
1043
+ throw new Error(
1044
+ `No Dockerfile found for this build context. Expected ${expectedDockerfile}${config.rootDirectory ? ` under ${config.rootDirectory}` : ""}.`
1045
+ );
1046
+ }
1047
+ if (!hasRepositoryDockerfile) {
1048
+ await writeFile(
1049
+ join2(contextDir, generatedName),
1050
+ generateDockerfile({
1051
+ ...config,
1052
+ rootDirectory: resolvedRootDirectory
1053
+ }),
1054
+ "utf-8"
1055
+ );
1056
+ }
1057
+ const contextEntries = await readdir2(contextDir);
1058
+ return {
1059
+ contextEntries,
1060
+ dockerfileName: repositoryDockerfileName ?? generatedName,
1061
+ rootDirectory: resolvedRootDirectory,
1062
+ usesRepositoryDockerfile: hasRepositoryDockerfile
1063
+ };
1064
+ }
1065
+ async function createDockerBuildContext(config, opts) {
1066
+ const tree = await prepareSourceTree(config, { onLog: opts?.onLog });
1067
+ try {
1068
+ const resolved = await resolveServiceDockerfile(tree.contextDir, config, {
1069
+ requireRepositoryDockerfile: opts?.requireRepositoryDockerfile
1070
+ });
1071
+ return {
1072
+ contextDir: tree.contextDir,
1073
+ contextEntries: resolved.contextEntries,
1074
+ dockerfileName: resolved.dockerfileName,
1075
+ rootDirectory: resolved.rootDirectory,
1076
+ usesRepositoryDockerfile: resolved.usesRepositoryDockerfile,
1077
+ cleanup: tree.cleanup
1078
+ };
1079
+ } catch (error) {
1080
+ await tree.cleanup();
1081
+ throw error;
1082
+ }
1083
+ }
1084
+
1085
+ export {
1086
+ normalizeDockerRelativePath,
1087
+ resolveDockerfileCandidates,
1088
+ generateDockerfile,
1089
+ prepareSourceTree,
1090
+ resolveServiceDockerfile,
1091
+ createDockerBuildContext
1092
+ };