@postman-cs/onboarding-repo-sync 2.11.2 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/action.cjs +372 -75
- package/dist/cli.cjs +372 -75
- package/dist/index.cjs +372 -75
- package/package.json +2 -1
package/dist/cli.cjs
CHANGED
|
@@ -116146,6 +116146,102 @@ function resolvePostmanEndpointProfile(stack, region = "us", env = process.env)
|
|
|
116146
116146
|
};
|
|
116147
116147
|
}
|
|
116148
116148
|
|
|
116149
|
+
// src/lib/postman/environment-yaml.ts
|
|
116150
|
+
var import_fs_utils = __toESM(require_dist5(), 1);
|
|
116151
|
+
var EXTENSION = ".environment.yaml";
|
|
116152
|
+
var SEPARATOR = " - ";
|
|
116153
|
+
var MAX_BASENAME_BYTES = 64;
|
|
116154
|
+
var SANITIZE_OPTIONS = {
|
|
116155
|
+
replacement: "-",
|
|
116156
|
+
combineConsecutiveReplacements: true
|
|
116157
|
+
};
|
|
116158
|
+
function assertWellFormed(value, label) {
|
|
116159
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
116160
|
+
const current2 = value.charCodeAt(index);
|
|
116161
|
+
if (current2 >= 55296 && current2 <= 56319) {
|
|
116162
|
+
const next = value.charCodeAt(index + 1);
|
|
116163
|
+
if (next < 56320 || next > 57343) throw new Error(`${label} must contain well-formed Unicode`);
|
|
116164
|
+
index += 1;
|
|
116165
|
+
} else if (current2 >= 56320 && current2 <= 57343) {
|
|
116166
|
+
throw new Error(`${label} must contain well-formed Unicode`);
|
|
116167
|
+
}
|
|
116168
|
+
}
|
|
116169
|
+
}
|
|
116170
|
+
function safeEnvironmentName(value) {
|
|
116171
|
+
assertWellFormed(value, "environment name");
|
|
116172
|
+
const hasInvalidCharacter = [...value].some((char) => {
|
|
116173
|
+
const code = char.charCodeAt(0);
|
|
116174
|
+
return char === "/" || char === "\\" || code <= 31 || code >= 127 && code <= 159;
|
|
116175
|
+
});
|
|
116176
|
+
if (!value || hasInvalidCharacter) {
|
|
116177
|
+
throw new Error("environment name must be non-empty and contain no path separators or control characters");
|
|
116178
|
+
}
|
|
116179
|
+
return (0, import_fs_utils.sanitizeFilename)(value, {
|
|
116180
|
+
...SANITIZE_OPTIONS,
|
|
116181
|
+
maxLength: MAX_BASENAME_BYTES - Buffer.byteLength(SEPARATOR)
|
|
116182
|
+
});
|
|
116183
|
+
}
|
|
116184
|
+
function environmentFileName(projectName, environmentName) {
|
|
116185
|
+
assertWellFormed(projectName, "project name");
|
|
116186
|
+
const suffix = safeEnvironmentName(environmentName);
|
|
116187
|
+
const projectBudget = Math.max(
|
|
116188
|
+
0,
|
|
116189
|
+
MAX_BASENAME_BYTES - Buffer.byteLength(SEPARATOR) - Buffer.byteLength(suffix)
|
|
116190
|
+
);
|
|
116191
|
+
const prefix = (0, import_fs_utils.sanitizeFilename)(projectName, { ...SANITIZE_OPTIONS, maxLength: projectBudget });
|
|
116192
|
+
return `${prefix ? `${prefix}${SEPARATOR}` : ""}${suffix}${EXTENSION}`;
|
|
116193
|
+
}
|
|
116194
|
+
function assertUniqueEnvironmentFileNames(projectName, environmentNames) {
|
|
116195
|
+
const owners = /* @__PURE__ */ new Map();
|
|
116196
|
+
for (const environmentName of environmentNames) {
|
|
116197
|
+
const fileName = environmentFileName(projectName, environmentName);
|
|
116198
|
+
const key = fileName.normalize("NFD").toUpperCase().toLowerCase();
|
|
116199
|
+
const owner = owners.get(key);
|
|
116200
|
+
if (owner) {
|
|
116201
|
+
throw new Error(
|
|
116202
|
+
`Environment identities "${owner}" and "${environmentName}" resolve to the same artifact filename ${fileName}`
|
|
116203
|
+
);
|
|
116204
|
+
}
|
|
116205
|
+
owners.set(key, environmentName);
|
|
116206
|
+
}
|
|
116207
|
+
}
|
|
116208
|
+
function environmentManifestRef(artifactDir, projectName, environmentName) {
|
|
116209
|
+
return `../${artifactDir}/environments/${environmentFileName(projectName, environmentName)}`;
|
|
116210
|
+
}
|
|
116211
|
+
function legacyEnvironmentManifestRef(artifactDir, environmentName) {
|
|
116212
|
+
return `../${artifactDir}/environments/${environmentName}.postman_environment.json`;
|
|
116213
|
+
}
|
|
116214
|
+
function serializeEnvironmentYaml(payload, displayName) {
|
|
116215
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
116216
|
+
throw new Error("sync-service environment must contain an object body");
|
|
116217
|
+
}
|
|
116218
|
+
const body = payload;
|
|
116219
|
+
if (!Array.isArray(body.values)) {
|
|
116220
|
+
throw new Error("sync-service environment must contain a values array");
|
|
116221
|
+
}
|
|
116222
|
+
const values = body.values.map((entry) => {
|
|
116223
|
+
const input = entry && typeof entry === "object" && !Array.isArray(entry) ? entry : {};
|
|
116224
|
+
const secret = input.secret === true || input.type === "secret";
|
|
116225
|
+
const output = {
|
|
116226
|
+
key: input.key == null ? "" : String(input.key)
|
|
116227
|
+
};
|
|
116228
|
+
if (secret) {
|
|
116229
|
+
output.secret = true;
|
|
116230
|
+
if (input.source != null) output.source = input.source;
|
|
116231
|
+
} else {
|
|
116232
|
+
output.value = input.value == null ? "" : String(input.value);
|
|
116233
|
+
}
|
|
116234
|
+
if (input.enabled === false) output.disabled = true;
|
|
116235
|
+
if (input.description != null) output.description = String(input.description);
|
|
116236
|
+
return output;
|
|
116237
|
+
});
|
|
116238
|
+
const environment = { name: displayName, values };
|
|
116239
|
+
if (Number.isInteger(body.color) && Number(body.color) >= 0 && Number(body.color) < 360) {
|
|
116240
|
+
environment.color = Number(body.color);
|
|
116241
|
+
}
|
|
116242
|
+
return dump(environment, { indent: 2, lineWidth: -1, noRefs: true, sortKeys: false });
|
|
116243
|
+
}
|
|
116244
|
+
|
|
116149
116245
|
// src/lib/ci-workflow-template.ts
|
|
116150
116246
|
var DEFAULT_POSTMAN_CLI_INSTALL_URL = POSTMAN_ENDPOINT_PROFILES.prod.cliInstallUrl;
|
|
116151
116247
|
var DEFAULT_POSTMAN_CLI_WINDOWS_INSTALL_URL = POSTMAN_ENDPOINT_PROFILES.prod.cliWindowsInstallUrl;
|
|
@@ -116173,6 +116269,16 @@ function resolveCiRunnerOs(runnerOsOption) {
|
|
|
116173
116269
|
}
|
|
116174
116270
|
throw new Error("ci-runner-os must be one of: linux, windows; got: " + runnerOs);
|
|
116175
116271
|
}
|
|
116272
|
+
function expectedEnvironmentFileName(projectName) {
|
|
116273
|
+
const name = String(projectName || "").trim();
|
|
116274
|
+
return name ? environmentFileName(name, "prod") : "";
|
|
116275
|
+
}
|
|
116276
|
+
function rubyStringLiteral(value) {
|
|
116277
|
+
return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
116278
|
+
}
|
|
116279
|
+
function powershellStringLiteral(value) {
|
|
116280
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
116281
|
+
}
|
|
116176
116282
|
function renderCiWorkflowTemplate(options = {}) {
|
|
116177
116283
|
const runnerOs = resolveCiRunnerOs(options.runnerOs);
|
|
116178
116284
|
if (runnerOs === "windows") {
|
|
@@ -116181,9 +116287,15 @@ function renderCiWorkflowTemplate(options = {}) {
|
|
|
116181
116287
|
const rawUrl = String(options.postmanCliInstallUrl || "").trim() || DEFAULT_POSTMAN_CLI_INSTALL_URL;
|
|
116182
116288
|
const installUrl = validateHttpsInstallUrl(rawUrl);
|
|
116183
116289
|
const postmanRegion = resolvePostmanRegion(options.postmanRegion);
|
|
116184
|
-
return buildCiWorkflowLines(
|
|
116290
|
+
return buildCiWorkflowLines(
|
|
116291
|
+
installUrl,
|
|
116292
|
+
postmanRegion,
|
|
116293
|
+
options.privateMockAuth === true,
|
|
116294
|
+
options.projectName
|
|
116295
|
+
).join("\n");
|
|
116185
116296
|
}
|
|
116186
|
-
function buildCiWorkflowLines(installUrl, postmanRegion, privateMockAuth) {
|
|
116297
|
+
function buildCiWorkflowLines(installUrl, postmanRegion, privateMockAuth, projectName) {
|
|
116298
|
+
const expectedEnvironment = expectedEnvironmentFileName(projectName);
|
|
116187
116299
|
return [
|
|
116188
116300
|
"name: CI/CD Pipeline",
|
|
116189
116301
|
"on:",
|
|
@@ -116221,11 +116333,18 @@ function buildCiWorkflowLines(installUrl, postmanRegion, privateMockAuth) {
|
|
|
116221
116333
|
" environments = cloud.fetch('environments', {})",
|
|
116222
116334
|
" smoke = collections.find { |path, _| path.include?('[Smoke]') }&.last",
|
|
116223
116335
|
" contract = collections.find { |path, _| path.include?('[Contract]') }&.last",
|
|
116224
|
-
|
|
116336
|
+
` expected_environment = ${rubyStringLiteral(expectedEnvironment)}`,
|
|
116337
|
+
" environment = environments.find { |path, _| File.basename(path) == expected_environment }&.last unless expected_environment.empty?",
|
|
116338
|
+
" environment ||= environments.find { |path, _| File.basename(path) == 'prod.postman_environment.json' }&.last",
|
|
116339
|
+
// A repo whose environments are named only `stage` or `dev` has no prod file to
|
|
116340
|
+
// match, and aborting there would break generated CI that worked before the YAML
|
|
116341
|
+
// migration. One environment is unambiguous, so use it; two or more without a
|
|
116342
|
+
// prod match is a real ambiguity and still aborts.
|
|
116343
|
+
" environment ||= environments.values.first if environments.size == 1",
|
|
116225
116344
|
" missing = []",
|
|
116226
|
-
" missing << '
|
|
116227
|
-
" missing << '
|
|
116228
|
-
" missing << 'environment' unless environment",
|
|
116345
|
+
" missing << '[Smoke] collection' unless smoke",
|
|
116346
|
+
" missing << '[Contract] collection' unless contract",
|
|
116347
|
+
" missing << (expected_environment.empty? ? 'environment' : expected_environment) unless environment",
|
|
116229
116348
|
` abort("Missing Postman resource IDs in .postman/resources.yaml: #{missing.join(', ')}") unless missing.empty?`,
|
|
116230
116349
|
" File.open(ENV.fetch('GITHUB_ENV'), 'a') do |file|",
|
|
116231
116350
|
' file.puts("POSTMAN_SMOKE_COLLECTION_UID=#{smoke}")',
|
|
@@ -116335,7 +116454,8 @@ function buildAdoWindowsCollectionRunLines(displayName, collectionEnvironmentNam
|
|
|
116335
116454
|
...privateMockAuth ? [" POSTMAN_API_KEY: $(POSTMAN_API_KEY)"] : []
|
|
116336
116455
|
];
|
|
116337
116456
|
}
|
|
116338
|
-
function buildAdoWindowsCiWorkflowLines(installUrl, postmanRegion, privateMockAuth) {
|
|
116457
|
+
function buildAdoWindowsCiWorkflowLines(installUrl, postmanRegion, privateMockAuth, projectName) {
|
|
116458
|
+
const expectedEnvironment = expectedEnvironmentFileName(projectName);
|
|
116339
116459
|
return [
|
|
116340
116460
|
"trigger:",
|
|
116341
116461
|
" branches:",
|
|
@@ -116380,22 +116500,38 @@ function buildAdoWindowsCiWorkflowLines(installUrl, postmanRegion, privateMockAu
|
|
|
116380
116500
|
" $contract = ''",
|
|
116381
116501
|
" $environment = ''",
|
|
116382
116502
|
" $fallbackEnvironment = ''",
|
|
116503
|
+
" $environmentCount = 0",
|
|
116504
|
+
` $expectedEnvironment = ${powershellStringLiteral(expectedEnvironment)}`,
|
|
116383
116505
|
" foreach ($line in Get-Content -LiteralPath '.postman/resources.yaml') {",
|
|
116384
|
-
" if ($line -match '^ (collections|environments):\\s*$') { $section = $Matches[1]; continue }",
|
|
116506
|
+
" if ($line -match '^ (collections|environments|specs):\\s*$') { $section = $Matches[1]; continue }",
|
|
116385
116507
|
" if ($line -notmatch '^ (.+?):\\s+(.+?)\\s*$') { continue }",
|
|
116386
|
-
|
|
116508
|
+
" $rawKey = $Matches[1].Trim()",
|
|
116509
|
+
` if ($rawKey.StartsWith("'") -and $rawKey.EndsWith("'")) {`,
|
|
116510
|
+
` $key = $rawKey.Substring(1, $rawKey.Length - 2) -replace "''", "'"`,
|
|
116511
|
+
` } elseif ($rawKey.StartsWith('"') -and $rawKey.EndsWith('"')) {`,
|
|
116512
|
+
" $key = $rawKey.Substring(1, $rawKey.Length - 2)",
|
|
116513
|
+
" } else {",
|
|
116514
|
+
" $key = $rawKey",
|
|
116515
|
+
" }",
|
|
116387
116516
|
` $value = $Matches[2].Trim().Trim("'").Trim('"')`,
|
|
116388
116517
|
" if ($section -eq 'collections' -and $key -match '\\[Smoke\\]') { $smoke = $value }",
|
|
116389
116518
|
" if ($section -eq 'collections' -and $key -match '\\[Contract\\]') { $contract = $value }",
|
|
116390
116519
|
" if ($section -eq 'environments') {",
|
|
116520
|
+
" $environmentCount += 1",
|
|
116391
116521
|
" if ([string]::IsNullOrWhiteSpace($fallbackEnvironment)) { $fallbackEnvironment = $value }",
|
|
116392
|
-
"
|
|
116522
|
+
" $fileName = [IO.Path]::GetFileName($key)",
|
|
116523
|
+
" if ($fileName -eq $expectedEnvironment) { $environment = $value }",
|
|
116524
|
+
" if ([string]::IsNullOrWhiteSpace($environment) -and $fileName -eq 'prod.postman_environment.json') { $environment = $value }",
|
|
116393
116525
|
" }",
|
|
116394
116526
|
" }",
|
|
116395
|
-
|
|
116396
|
-
|
|
116397
|
-
" if ([string]::IsNullOrWhiteSpace($
|
|
116398
|
-
"
|
|
116527
|
+
// Matches the Ruby resolvers: a single environment is unambiguous, so use it
|
|
116528
|
+
// rather than aborting a pipeline that worked before the YAML migration.
|
|
116529
|
+
" if ([string]::IsNullOrWhiteSpace($environment) -and $environmentCount -eq 1) { $environment = $fallbackEnvironment }",
|
|
116530
|
+
" $missing = @()",
|
|
116531
|
+
" if ([string]::IsNullOrWhiteSpace($smoke)) { $missing += '[Smoke] collection' }",
|
|
116532
|
+
" if ([string]::IsNullOrWhiteSpace($contract)) { $missing += '[Contract] collection' }",
|
|
116533
|
+
" if ([string]::IsNullOrWhiteSpace($environment)) { $missing += $(if ($expectedEnvironment) { $expectedEnvironment } else { 'environment' }) }",
|
|
116534
|
+
" if ($missing.Count) { throw ('Missing Postman resource IDs in .postman/resources.yaml: ' + ($missing -join ', ')) }",
|
|
116399
116535
|
' Write-Host "##vso[task.setvariable variable=POSTMAN_SMOKE_COLLECTION_UID]$smoke"',
|
|
116400
116536
|
' Write-Host "##vso[task.setvariable variable=POSTMAN_CONTRACT_COLLECTION_UID]$contract"',
|
|
116401
116537
|
' Write-Host "##vso[task.setvariable variable=POSTMAN_ENVIRONMENT_UID]$environment"',
|
|
@@ -116425,7 +116561,8 @@ function buildAdoWindowsCiWorkflowLines(installUrl, postmanRegion, privateMockAu
|
|
|
116425
116561
|
""
|
|
116426
116562
|
];
|
|
116427
116563
|
}
|
|
116428
|
-
function buildAdoCiWorkflowLines(installUrl, postmanRegion, privateMockAuth) {
|
|
116564
|
+
function buildAdoCiWorkflowLines(installUrl, postmanRegion, privateMockAuth, projectName) {
|
|
116565
|
+
const expectedEnvironment = expectedEnvironmentFileName(projectName);
|
|
116429
116566
|
return [
|
|
116430
116567
|
"trigger:",
|
|
116431
116568
|
" branches:",
|
|
@@ -116452,16 +116589,29 @@ function buildAdoCiWorkflowLines(installUrl, postmanRegion, privateMockAuth) {
|
|
|
116452
116589
|
" env:",
|
|
116453
116590
|
" POSTMAN_API_KEY: $(POSTMAN_API_KEY)",
|
|
116454
116591
|
" - script: |",
|
|
116455
|
-
"
|
|
116456
|
-
"
|
|
116457
|
-
"
|
|
116458
|
-
"
|
|
116459
|
-
|
|
116460
|
-
|
|
116461
|
-
|
|
116462
|
-
|
|
116463
|
-
|
|
116464
|
-
|
|
116592
|
+
" ruby <<'RUBY'",
|
|
116593
|
+
" require 'yaml'",
|
|
116594
|
+
" config = YAML.load_file('.postman/resources.yaml') || {}",
|
|
116595
|
+
" cloud = config.fetch('canonical', config.fetch('cloudResources', {}))",
|
|
116596
|
+
" collections = cloud.fetch('collections', {})",
|
|
116597
|
+
" environments = cloud.fetch('environments', {})",
|
|
116598
|
+
" smoke = collections.find { |path, _| path.include?('[Smoke]') }&.last",
|
|
116599
|
+
" contract = collections.find { |path, _| path.include?('[Contract]') }&.last",
|
|
116600
|
+
` expected_environment = ${rubyStringLiteral(expectedEnvironment)}`,
|
|
116601
|
+
" environment = environments.find { |path, _| File.basename(path) == expected_environment }&.last unless expected_environment.empty?",
|
|
116602
|
+
" environment ||= environments.find { |path, _| File.basename(path) == 'prod.postman_environment.json' }&.last",
|
|
116603
|
+
// See the GitHub resolver: one environment is unambiguous, two or more without a
|
|
116604
|
+
// prod match still aborts.
|
|
116605
|
+
" environment ||= environments.values.first if environments.size == 1",
|
|
116606
|
+
" missing = []",
|
|
116607
|
+
" missing << '[Smoke] collection' unless smoke",
|
|
116608
|
+
" missing << '[Contract] collection' unless contract",
|
|
116609
|
+
" missing << (expected_environment.empty? ? 'environment' : expected_environment) unless environment",
|
|
116610
|
+
` abort("Missing Postman resource IDs in .postman/resources.yaml: #{missing.join(', ')}") unless missing.empty?`,
|
|
116611
|
+
' puts "##vso[task.setvariable variable=POSTMAN_SMOKE_COLLECTION_UID]#{smoke}"',
|
|
116612
|
+
' puts "##vso[task.setvariable variable=POSTMAN_CONTRACT_COLLECTION_UID]#{contract}"',
|
|
116613
|
+
' puts "##vso[task.setvariable variable=POSTMAN_ENVIRONMENT_UID]#{environment}"',
|
|
116614
|
+
" RUBY",
|
|
116465
116615
|
" displayName: Resolve Postman Resource IDs",
|
|
116466
116616
|
" - script: |",
|
|
116467
116617
|
' mkdir -p "$(Agent.TempDirectory)/postman-ssl"',
|
|
@@ -116617,7 +116767,7 @@ function getCiWorkflowTemplate(provider, options = {}) {
|
|
|
116617
116767
|
const postmanRegion = resolvePostmanRegion(options.postmanRegion);
|
|
116618
116768
|
const installUrl = validateHttpsInstallUrl(rawUrl);
|
|
116619
116769
|
const privateMockAuth = options.privateMockAuth === true;
|
|
116620
|
-
return (runnerOs === "windows" ? buildAdoWindowsCiWorkflowLines(installUrl, postmanRegion, privateMockAuth) : buildAdoCiWorkflowLines(installUrl, postmanRegion, privateMockAuth)).join("\n");
|
|
116770
|
+
return (runnerOs === "windows" ? buildAdoWindowsCiWorkflowLines(installUrl, postmanRegion, privateMockAuth, options.projectName) : buildAdoCiWorkflowLines(installUrl, postmanRegion, privateMockAuth, options.projectName)).join("\n");
|
|
116621
116771
|
}
|
|
116622
116772
|
return renderCiWorkflowTemplate(options);
|
|
116623
116773
|
}
|
|
@@ -128075,16 +128225,71 @@ function matchesCollectionDirectory(filePath, directoryName) {
|
|
|
128075
128225
|
function matchesBaselineCollectionResource(filePath, assetProjectName) {
|
|
128076
128226
|
return matchesCollectionDirectory(filePath, assetProjectName) || matchesCollectionDirectory(filePath, `${LEGACY_BASELINE_COLLECTION_PREFIX} ${assetProjectName}`);
|
|
128077
128227
|
}
|
|
128078
|
-
function
|
|
128228
|
+
function getEnvironmentOwnershipFromResources(resourcesState, artifactDir, projectName, environmentNames) {
|
|
128229
|
+
const result = {};
|
|
128230
|
+
for (const environmentName of environmentNames) {
|
|
128231
|
+
result[environmentName] = {
|
|
128232
|
+
currentRef: canonicalizeRelativePath(environmentManifestRef(artifactDir, projectName, environmentName)),
|
|
128233
|
+
legacyRef: canonicalizeRelativePath(legacyEnvironmentManifestRef(artifactDir, environmentName))
|
|
128234
|
+
};
|
|
128235
|
+
}
|
|
128079
128236
|
const cloudEnvironments = resourcesState?.cloudResources?.environments;
|
|
128080
128237
|
if (!cloudEnvironments) {
|
|
128081
|
-
return
|
|
128238
|
+
return result;
|
|
128082
128239
|
}
|
|
128083
|
-
|
|
128084
|
-
|
|
128085
|
-
|
|
128086
|
-
|
|
128087
|
-
|
|
128240
|
+
const normalizedEntries = Object.entries(cloudEnvironments).map(([filePath, uid]) => [
|
|
128241
|
+
canonicalizeRelativePath(filePath),
|
|
128242
|
+
uid
|
|
128243
|
+
]);
|
|
128244
|
+
for (const environmentName of environmentNames) {
|
|
128245
|
+
const ownership = result[environmentName];
|
|
128246
|
+
const currentUids = new Set(
|
|
128247
|
+
normalizedEntries.filter(([filePath]) => filePath === ownership.currentRef).map(([, uid]) => uid)
|
|
128248
|
+
);
|
|
128249
|
+
const legacyUids = new Set(
|
|
128250
|
+
normalizedEntries.filter(([filePath]) => filePath === ownership.legacyRef).map(([, uid]) => uid)
|
|
128251
|
+
);
|
|
128252
|
+
if (currentUids.size > 1 || legacyUids.size > 1) {
|
|
128253
|
+
throw new StateUnreadableError(
|
|
128254
|
+
`.postman/resources.yaml maps environment "${environmentName}" artifact to multiple UIDs. Reconcile the entries before rerunning.`
|
|
128255
|
+
);
|
|
128256
|
+
}
|
|
128257
|
+
ownership.currentUid = [...currentUids][0];
|
|
128258
|
+
ownership.legacyUid = [...legacyUids][0];
|
|
128259
|
+
const uids = new Set([ownership.currentUid, ownership.legacyUid].filter(Boolean));
|
|
128260
|
+
if (uids.size > 1) {
|
|
128261
|
+
throw new StateUnreadableError(
|
|
128262
|
+
`.postman/resources.yaml maps canonical and legacy artifacts for environment "${environmentName}" to different UIDs. Reconcile the entries before rerunning.`
|
|
128263
|
+
);
|
|
128264
|
+
}
|
|
128265
|
+
}
|
|
128266
|
+
return result;
|
|
128267
|
+
}
|
|
128268
|
+
function getEnvironmentUidsFromOwnership(ownership) {
|
|
128269
|
+
const result = {};
|
|
128270
|
+
for (const [environmentName, entry] of Object.entries(ownership)) {
|
|
128271
|
+
const uid = entry.currentUid || entry.legacyUid;
|
|
128272
|
+
if (uid) result[environmentName] = uid;
|
|
128273
|
+
}
|
|
128274
|
+
return result;
|
|
128275
|
+
}
|
|
128276
|
+
function assertEnvironmentTargetAvailable(options) {
|
|
128277
|
+
assertPathWithinCwd(options.filePath, "environment target");
|
|
128278
|
+
let stats;
|
|
128279
|
+
try {
|
|
128280
|
+
stats = (0, import_node_fs6.lstatSync)(options.filePath);
|
|
128281
|
+
} catch (error) {
|
|
128282
|
+
if (error.code === "ENOENT") return;
|
|
128283
|
+
throw error;
|
|
128284
|
+
}
|
|
128285
|
+
if (stats.isSymbolicLink() || !stats.isFile()) {
|
|
128286
|
+
throw new StateUnreadableError(
|
|
128287
|
+
`${options.filePath} exists but is not a regular owned environment file. Remove it before rerunning; no cloud environment was changed.`
|
|
128288
|
+
);
|
|
128289
|
+
}
|
|
128290
|
+
if (options.currentUid) return;
|
|
128291
|
+
throw new StateUnreadableError(
|
|
128292
|
+
`${options.filePath} exists but is not owned by .postman/resources.yaml. Adopt its UID into the manifest or remove the file before rerunning; no cloud environment was changed.`
|
|
128088
128293
|
);
|
|
128089
128294
|
}
|
|
128090
128295
|
function normalizeToPosix(filePath) {
|
|
@@ -128368,12 +128573,34 @@ async function writeGitHubRepositorySecrets(repository, token, secrets, env = pr
|
|
|
128368
128573
|
}
|
|
128369
128574
|
}
|
|
128370
128575
|
async function upsertEnvironments(inputs, dependencies, resourcesState, assetMarker) {
|
|
128576
|
+
const environmentNames = /* @__PURE__ */ new Set([
|
|
128577
|
+
...inputs.environments,
|
|
128578
|
+
...Object.keys(inputs.environmentUids)
|
|
128579
|
+
]);
|
|
128580
|
+
assertUniqueEnvironmentFileNames(inputs.projectName, environmentNames);
|
|
128581
|
+
const trackedOwnership = getEnvironmentOwnershipFromResources(
|
|
128582
|
+
resourcesState,
|
|
128583
|
+
inputs.artifactDir,
|
|
128584
|
+
inputs.projectName,
|
|
128585
|
+
environmentNames
|
|
128586
|
+
);
|
|
128587
|
+
const trackedUids = getEnvironmentUidsFromOwnership(trackedOwnership);
|
|
128588
|
+
for (const environmentName of environmentNames) {
|
|
128589
|
+
assertEnvironmentTargetAvailable({
|
|
128590
|
+
filePath: path4.join(
|
|
128591
|
+
inputs.artifactDir,
|
|
128592
|
+
"environments",
|
|
128593
|
+
environmentFileName(inputs.projectName, environmentName)
|
|
128594
|
+
),
|
|
128595
|
+
currentUid: trackedOwnership[environmentName].currentUid
|
|
128596
|
+
});
|
|
128597
|
+
}
|
|
128371
128598
|
const envUids = {
|
|
128372
|
-
...
|
|
128599
|
+
...trackedUids,
|
|
128373
128600
|
...inputs.environmentUids
|
|
128374
128601
|
};
|
|
128375
128602
|
if (!inputs.workspaceId) {
|
|
128376
|
-
return envUids;
|
|
128603
|
+
return { envUids, ownership: trackedOwnership };
|
|
128377
128604
|
}
|
|
128378
128605
|
const mask = resolveRepoSyncMasker(dependencies);
|
|
128379
128606
|
const envRemediation = "verify access-token/team/workspace permissions then rerun";
|
|
@@ -128475,7 +128702,7 @@ async function upsertEnvironments(inputs, dependencies, resourcesState, assetMar
|
|
|
128475
128702
|
);
|
|
128476
128703
|
}
|
|
128477
128704
|
}
|
|
128478
|
-
return envUids;
|
|
128705
|
+
return { envUids, ownership: trackedOwnership };
|
|
128479
128706
|
}
|
|
128480
128707
|
async function upsertMockEnvironment(inputs, dependencies, assetProjectName, mockUrl, privateMockAuth) {
|
|
128481
128708
|
if (!inputs.mockEnvironmentEnabled || !inputs.workspaceId || !mockUrl) {
|
|
@@ -128558,7 +128785,8 @@ function getCollectionDirectoryName(kind, projectName) {
|
|
|
128558
128785
|
var VOLATILE_KEYS = /* @__PURE__ */ new Set([
|
|
128559
128786
|
"createdAt",
|
|
128560
128787
|
"updatedAt",
|
|
128561
|
-
"lastUpdatedBy"
|
|
128788
|
+
"lastUpdatedBy",
|
|
128789
|
+
"lastRevision"
|
|
128562
128790
|
]);
|
|
128563
128791
|
function stripVolatileFields(obj) {
|
|
128564
128792
|
if (Array.isArray(obj)) {
|
|
@@ -128635,7 +128863,21 @@ function resolveDurableWorkspaceId(options) {
|
|
|
128635
128863
|
}
|
|
128636
128864
|
return prior === candidate ? prior : void 0;
|
|
128637
128865
|
}
|
|
128638
|
-
function buildResourcesManifest(
|
|
128866
|
+
function buildResourcesManifest(options) {
|
|
128867
|
+
const {
|
|
128868
|
+
workspaceId,
|
|
128869
|
+
collectionMap,
|
|
128870
|
+
envMap,
|
|
128871
|
+
artifactDir,
|
|
128872
|
+
projectName,
|
|
128873
|
+
localSpecRefs,
|
|
128874
|
+
mappedSpecRef,
|
|
128875
|
+
specId,
|
|
128876
|
+
existingSpecs,
|
|
128877
|
+
priorState,
|
|
128878
|
+
preserveGeneratedAssets = false,
|
|
128879
|
+
preservePriorEnvironmentAssets = preserveGeneratedAssets
|
|
128880
|
+
} = options;
|
|
128639
128881
|
const manifest = { ...priorState ?? {} };
|
|
128640
128882
|
delete manifest.version;
|
|
128641
128883
|
delete manifest.workspace;
|
|
@@ -128652,15 +128894,26 @@ function buildResourcesManifest(workspaceId, collectionMap, envMap, artifactDir,
|
|
|
128652
128894
|
if (collectionKeys.length > 0) {
|
|
128653
128895
|
cloudResources.collections = effectiveCollectionMap;
|
|
128654
128896
|
}
|
|
128655
|
-
const priorEnvironmentMap =
|
|
128897
|
+
const priorEnvironmentMap = preservePriorEnvironmentAssets ? { ...priorState?.cloudResources?.environments ?? {} } : {};
|
|
128656
128898
|
const envEntries = Object.entries(envMap);
|
|
128899
|
+
for (const [envName] of envEntries) {
|
|
128900
|
+
const replacedRefs = /* @__PURE__ */ new Set([
|
|
128901
|
+
canonicalizeRelativePath(environmentManifestRef(artifactDir, projectName, envName)),
|
|
128902
|
+
canonicalizeRelativePath(legacyEnvironmentManifestRef(artifactDir, envName))
|
|
128903
|
+
]);
|
|
128904
|
+
for (const filePath of Object.keys(priorEnvironmentMap)) {
|
|
128905
|
+
if (replacedRefs.has(canonicalizeRelativePath(filePath))) {
|
|
128906
|
+
delete priorEnvironmentMap[filePath];
|
|
128907
|
+
}
|
|
128908
|
+
}
|
|
128909
|
+
}
|
|
128657
128910
|
if (Object.keys(priorEnvironmentMap).length > 0 || envEntries.length > 0) {
|
|
128658
128911
|
cloudResources.environments = priorEnvironmentMap;
|
|
128659
128912
|
}
|
|
128660
128913
|
if (envEntries.length > 0) {
|
|
128661
128914
|
cloudResources.environments ??= {};
|
|
128662
128915
|
for (const [envName, envUid] of envEntries) {
|
|
128663
|
-
cloudResources.environments[
|
|
128916
|
+
cloudResources.environments[environmentManifestRef(artifactDir, projectName, envName)] = envUid;
|
|
128664
128917
|
}
|
|
128665
128918
|
}
|
|
128666
128919
|
void localSpecRefs;
|
|
@@ -129396,18 +129649,19 @@ async function exportArtifacts(inputs, dependencies, envUids, assetProjectName,
|
|
|
129396
129649
|
}
|
|
129397
129650
|
ensureDir(".postman");
|
|
129398
129651
|
assertPathWithinCwd(".postman/resources.yaml", "resources state target");
|
|
129399
|
-
(0, import_node_fs6.writeFileSync)(".postman/resources.yaml", buildResourcesManifest(
|
|
129400
|
-
durableWorkspaceId,
|
|
129401
|
-
{},
|
|
129402
|
-
{},
|
|
129403
|
-
inputs.artifactDir,
|
|
129404
|
-
|
|
129405
|
-
|
|
129406
|
-
|
|
129407
|
-
|
|
129408
|
-
options.
|
|
129409
|
-
|
|
129410
|
-
|
|
129652
|
+
(0, import_node_fs6.writeFileSync)(".postman/resources.yaml", buildResourcesManifest({
|
|
129653
|
+
workspaceId: durableWorkspaceId,
|
|
129654
|
+
collectionMap: {},
|
|
129655
|
+
envMap: {},
|
|
129656
|
+
artifactDir: inputs.artifactDir,
|
|
129657
|
+
projectName: inputs.projectName,
|
|
129658
|
+
localSpecRefs: discoveredSpecs.map((spec) => spec.configRelativePath),
|
|
129659
|
+
mappedSpecRef: mappedSpecCloudKey,
|
|
129660
|
+
specId: inputs.specId || void 0,
|
|
129661
|
+
existingSpecs: preservePriorWorkspaceResources ? options.existingSpecs : void 0,
|
|
129662
|
+
priorState: options.priorState,
|
|
129663
|
+
preserveGeneratedAssets: preservePriorWorkspaceResources
|
|
129664
|
+
}));
|
|
129411
129665
|
dependencies.core.info(
|
|
129412
129666
|
"onboarding-scope=spec-only; updated only workspace/spec state in .postman/resources.yaml."
|
|
129413
129667
|
);
|
|
@@ -129473,15 +129727,31 @@ async function exportArtifacts(inputs, dependencies, envUids, assetProjectName,
|
|
|
129473
129727
|
}
|
|
129474
129728
|
}
|
|
129475
129729
|
const environmentSpecs = [
|
|
129476
|
-
...Object.entries(envUids).map(([envName, envUid]) =>
|
|
129477
|
-
envName
|
|
129478
|
-
|
|
129479
|
-
|
|
129480
|
-
|
|
129730
|
+
...Object.entries(envUids).map(([envName, envUid]) => {
|
|
129731
|
+
const ownership = options.environmentOwnership[envName];
|
|
129732
|
+
if (!ownership) {
|
|
129733
|
+
throw new Error(
|
|
129734
|
+
`environment "${envName}" has a UID but no manifest ownership entry; environment sync and artifact export disagree`
|
|
129735
|
+
);
|
|
129736
|
+
}
|
|
129737
|
+
return {
|
|
129738
|
+
kind: "environment",
|
|
129739
|
+
envName,
|
|
129740
|
+
envUid,
|
|
129741
|
+
filePath: `${environmentsDir}/${environmentFileName(inputs.projectName, envName)}`,
|
|
129742
|
+
currentUid: ownership.currentUid,
|
|
129743
|
+
legacyUid: ownership.legacyUid,
|
|
129744
|
+
legacyFilePath: ownership.legacyUid === envUid ? `${environmentsDir}/${envName}.postman_environment.json` : void 0
|
|
129745
|
+
};
|
|
129746
|
+
}),
|
|
129481
129747
|
...options.mockEnvironmentUid ? [{
|
|
129748
|
+
kind: "mock",
|
|
129482
129749
|
envName: "manual-validation",
|
|
129483
129750
|
envUid: options.mockEnvironmentUid,
|
|
129484
|
-
filePath: `${mocksDir}/manual-validation.postman_environment.json
|
|
129751
|
+
filePath: `${mocksDir}/manual-validation.postman_environment.json`,
|
|
129752
|
+
currentUid: void 0,
|
|
129753
|
+
legacyUid: void 0,
|
|
129754
|
+
legacyFilePath: void 0
|
|
129485
129755
|
}] : []
|
|
129486
129756
|
];
|
|
129487
129757
|
const environmentStartedAt = Date.now();
|
|
@@ -129501,26 +129771,50 @@ async function exportArtifacts(inputs, dependencies, envUids, assetProjectName,
|
|
|
129501
129771
|
`environment-artifact-acquisition count=${environmentSpecs.length} width=${ARTIFACT_ACQUISITION_WIDTH} ms=${Date.now() - environmentStartedAt} status=${environmentStatus}`
|
|
129502
129772
|
);
|
|
129503
129773
|
}
|
|
129774
|
+
const legacyEnvironmentCleanupPaths = [];
|
|
129504
129775
|
for (const [index, spec] of environmentSpecs.entries()) {
|
|
129505
|
-
|
|
129506
|
-
|
|
129776
|
+
if (spec.kind === "mock") {
|
|
129777
|
+
assertPathWithinCwd(spec.filePath, "environment target");
|
|
129778
|
+
writeJsonFile(spec.filePath, sanitizeMockEnvironmentArtifact(environmentPayloads[index]), true);
|
|
129779
|
+
continue;
|
|
129780
|
+
}
|
|
129781
|
+
assertEnvironmentTargetAvailable({
|
|
129782
|
+
filePath: spec.filePath,
|
|
129783
|
+
currentUid: spec.currentUid
|
|
129784
|
+
});
|
|
129785
|
+
(0, import_node_fs6.writeFileSync)(
|
|
129507
129786
|
spec.filePath,
|
|
129508
|
-
|
|
129509
|
-
true
|
|
129787
|
+
serializeEnvironmentYaml(environmentPayloads[index], `${inputs.projectName} - ${spec.envName}`)
|
|
129510
129788
|
);
|
|
129789
|
+
if (spec.legacyFilePath) {
|
|
129790
|
+
legacyEnvironmentCleanupPaths.push(spec.legacyFilePath);
|
|
129791
|
+
}
|
|
129511
129792
|
}
|
|
129512
129793
|
assertPathWithinCwd(".postman/resources.yaml", "resources state target");
|
|
129513
|
-
(0, import_node_fs6.writeFileSync)(".postman/resources.yaml", buildResourcesManifest(
|
|
129514
|
-
durableWorkspaceId,
|
|
129515
|
-
manifestCollections,
|
|
129516
|
-
envUids,
|
|
129517
|
-
inputs.artifactDir,
|
|
129518
|
-
|
|
129519
|
-
|
|
129520
|
-
|
|
129521
|
-
|
|
129522
|
-
options.
|
|
129523
|
-
|
|
129794
|
+
(0, import_node_fs6.writeFileSync)(".postman/resources.yaml", buildResourcesManifest({
|
|
129795
|
+
workspaceId: durableWorkspaceId,
|
|
129796
|
+
collectionMap: manifestCollections,
|
|
129797
|
+
envMap: envUids,
|
|
129798
|
+
artifactDir: inputs.artifactDir,
|
|
129799
|
+
projectName: inputs.projectName,
|
|
129800
|
+
localSpecRefs: discoveredSpecs.map((spec) => spec.configRelativePath),
|
|
129801
|
+
mappedSpecRef: mappedSpecCloudKey,
|
|
129802
|
+
specId: inputs.specId || void 0,
|
|
129803
|
+
existingSpecs: options.existingSpecs,
|
|
129804
|
+
priorState: options.priorState,
|
|
129805
|
+
// The export path always rewrites collections from this run, but keeps prior
|
|
129806
|
+
// environments so an environment tracked by an earlier run is not dropped.
|
|
129807
|
+
preserveGeneratedAssets: false,
|
|
129808
|
+
preservePriorEnvironmentAssets: preservePriorWorkspaceResources
|
|
129809
|
+
}));
|
|
129810
|
+
for (const legacyFilePath of legacyEnvironmentCleanupPaths) {
|
|
129811
|
+
assertPathWithinCwd(legacyFilePath, "legacy environment target");
|
|
129812
|
+
try {
|
|
129813
|
+
(0, import_node_fs6.unlinkSync)(legacyFilePath);
|
|
129814
|
+
} catch (error) {
|
|
129815
|
+
if (error.code !== "ENOENT") throw error;
|
|
129816
|
+
}
|
|
129817
|
+
}
|
|
129524
129818
|
if (mappedSpec && Object.keys(manifestCollections).length > 0) {
|
|
129525
129819
|
let existingWorkflows;
|
|
129526
129820
|
try {
|
|
@@ -129545,6 +129839,7 @@ function renderCiWorkflow(inputs, privateMockAuth) {
|
|
|
129545
129839
|
}
|
|
129546
129840
|
if (inputs.provider === "azure-devops") {
|
|
129547
129841
|
return getCiWorkflowTemplate(inputs.provider, {
|
|
129842
|
+
projectName: inputs.projectName,
|
|
129548
129843
|
postmanCliInstallUrl: inputs.postmanCliInstallUrl,
|
|
129549
129844
|
postmanCliWindowsInstallUrl: inputs.postmanCliWindowsInstallUrl,
|
|
129550
129845
|
runnerOs: inputs.ciRunnerOs,
|
|
@@ -129553,6 +129848,7 @@ function renderCiWorkflow(inputs, privateMockAuth) {
|
|
|
129553
129848
|
});
|
|
129554
129849
|
}
|
|
129555
129850
|
return renderCiWorkflowTemplate({
|
|
129851
|
+
projectName: inputs.projectName,
|
|
129556
129852
|
postmanCliInstallUrl: inputs.postmanCliInstallUrl,
|
|
129557
129853
|
postmanCliWindowsInstallUrl: inputs.postmanCliWindowsInstallUrl,
|
|
129558
129854
|
runnerOs: inputs.ciRunnerOs,
|
|
@@ -129801,10 +130097,10 @@ async function runRepoSyncInner(inputs, dependencies, executionContext) {
|
|
|
129801
130097
|
}
|
|
129802
130098
|
}
|
|
129803
130099
|
const branchAssetMarker = buildBranchAssetMarker(branchDecision, inputs);
|
|
129804
|
-
const envUids = onboardingScope === "full" ? await logger.phase(
|
|
130100
|
+
const { envUids, ownership: environmentOwnership } = onboardingScope === "full" ? await logger.phase(
|
|
129805
130101
|
"sync-environments",
|
|
129806
130102
|
async () => upsertEnvironments(inputs, dependencies, resourcesState, branchAssetMarker)
|
|
129807
|
-
) : {};
|
|
130103
|
+
) : { envUids: {}, ownership: {} };
|
|
129808
130104
|
outputs["environment-uids-json"] = JSON.stringify(envUids);
|
|
129809
130105
|
dependencies.core.setOutput("environment-uids-json", outputs["environment-uids-json"]);
|
|
129810
130106
|
if (inputs.environmentSyncEnabled && inputs.workspaceId && dependencies.internalIntegration) {
|
|
@@ -130204,6 +130500,7 @@ async function runRepoSyncInner(inputs, dependencies, executionContext) {
|
|
|
130204
130500
|
mockEnvironmentUid: outputs["mock-environment-uid"] || void 0,
|
|
130205
130501
|
releaseLabel,
|
|
130206
130502
|
priorState: resourcesState,
|
|
130503
|
+
environmentOwnership,
|
|
130207
130504
|
preparedPrebuiltCollections,
|
|
130208
130505
|
privateMockAuth: outputs["mock-auth-required"] === "true"
|
|
130209
130506
|
})
|