@postman-cse/onboarding-repo-sync 2.1.7 → 2.1.9
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 +1 -0
- package/action.yml +4 -0
- package/dist/action.cjs +644 -82
- package/dist/cli.cjs +644 -82
- package/dist/index.cjs +644 -82
- package/package.json +2 -2
package/dist/cli.cjs
CHANGED
|
@@ -123219,6 +123219,7 @@ var POSTMAN_ENDPOINT_PROFILES = {
|
|
|
123219
123219
|
bifrostBaseUrl: "https://bifrost-premium-https-v4.gw.postman.com",
|
|
123220
123220
|
fallbackBaseUrl: "https://go.postman.co/_api",
|
|
123221
123221
|
cliInstallUrl: "https://dl-cli.pstmn.io/install/unix.sh",
|
|
123222
|
+
cliWindowsInstallUrl: "https://dl-cli.pstmn.io/install/win64.ps1",
|
|
123222
123223
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
123223
123224
|
},
|
|
123224
123225
|
beta: {
|
|
@@ -123226,6 +123227,7 @@ var POSTMAN_ENDPOINT_PROFILES = {
|
|
|
123226
123227
|
bifrostBaseUrl: "https://bifrost-https-v4.gw.postman-beta.com",
|
|
123227
123228
|
fallbackBaseUrl: "https://go.postman-beta.co/_api",
|
|
123228
123229
|
cliInstallUrl: "https://dl-cli.pstmn-beta.io/install/unix.sh",
|
|
123230
|
+
cliWindowsInstallUrl: "https://dl-cli.pstmn-beta.io/install/win64.ps1",
|
|
123229
123231
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
123230
123232
|
}
|
|
123231
123233
|
};
|
|
@@ -123259,6 +123261,7 @@ function resolvePostmanEndpointProfile(stack, region = "us") {
|
|
|
123259
123261
|
|
|
123260
123262
|
// src/lib/ci-workflow-template.ts
|
|
123261
123263
|
var DEFAULT_POSTMAN_CLI_INSTALL_URL = POSTMAN_ENDPOINT_PROFILES.prod.cliInstallUrl;
|
|
123264
|
+
var DEFAULT_POSTMAN_CLI_WINDOWS_INSTALL_URL = POSTMAN_ENDPOINT_PROFILES.prod.cliWindowsInstallUrl;
|
|
123262
123265
|
function validateHttpsInstallUrl(url) {
|
|
123263
123266
|
const safeUrlPattern = /^https:\/\/[A-Za-z0-9.-]+\/[A-Za-z0-9._~/?=&%-]+$/;
|
|
123264
123267
|
if (!safeUrlPattern.test(url)) {
|
|
@@ -123275,7 +123278,18 @@ function resolvePostmanRegion(postmanRegionOption) {
|
|
|
123275
123278
|
}
|
|
123276
123279
|
return postmanRegion;
|
|
123277
123280
|
}
|
|
123281
|
+
function resolveCiRunnerOs(runnerOsOption) {
|
|
123282
|
+
const runnerOs = String(runnerOsOption || "").trim() || "linux";
|
|
123283
|
+
if (runnerOs === "linux" || runnerOs === "windows") {
|
|
123284
|
+
return runnerOs;
|
|
123285
|
+
}
|
|
123286
|
+
throw new Error("ci-runner-os must be one of: linux, windows; got: " + runnerOs);
|
|
123287
|
+
}
|
|
123278
123288
|
function renderCiWorkflowTemplate(options = {}) {
|
|
123289
|
+
const runnerOs = resolveCiRunnerOs(options.runnerOs);
|
|
123290
|
+
if (runnerOs === "windows") {
|
|
123291
|
+
throw new Error("ci-runner-os=windows is currently supported for azure-devops workflows only");
|
|
123292
|
+
}
|
|
123279
123293
|
const rawUrl = String(options.postmanCliInstallUrl || "").trim() || DEFAULT_POSTMAN_CLI_INSTALL_URL;
|
|
123280
123294
|
const installUrl = validateHttpsInstallUrl(rawUrl);
|
|
123281
123295
|
const postmanRegion = resolvePostmanRegion(options.postmanRegion);
|
|
@@ -123382,6 +123396,132 @@ function buildCiWorkflowLines(installUrl, postmanRegion) {
|
|
|
123382
123396
|
];
|
|
123383
123397
|
}
|
|
123384
123398
|
var CI_WORKFLOW_TEMPLATE = renderCiWorkflowTemplate();
|
|
123399
|
+
function buildAdoWindowsCollectionRunLines(displayName, collectionEnvironmentName) {
|
|
123400
|
+
return [
|
|
123401
|
+
" - pwsh: |",
|
|
123402
|
+
" $ErrorActionPreference = 'Stop'",
|
|
123403
|
+
" function Resolve-AdoOptional([string]$Value) {",
|
|
123404
|
+
" if ($Value -match '^\\$\\([^)]+\\)$') { return '' }",
|
|
123405
|
+
" return $Value",
|
|
123406
|
+
" }",
|
|
123407
|
+
` $collectionUid = $env:${collectionEnvironmentName}`,
|
|
123408
|
+
" $ciEnvironment = Resolve-AdoOptional $env:CI_ENVIRONMENT",
|
|
123409
|
+
" if ([string]::IsNullOrWhiteSpace($ciEnvironment)) { $ciEnvironment = 'Production' }",
|
|
123410
|
+
` $arguments = @('collection', 'run', $collectionUid, '-e', $env:POSTMAN_ENVIRONMENT_UID, '--report-events', '--env-var', "CI_ENVIRONMENT=$ciEnvironment")`,
|
|
123411
|
+
" $sslRoot = Join-Path $env:AGENT_TEMPDIRECTORY 'postman-ssl'",
|
|
123412
|
+
" $clientCert = Join-Path $sslRoot 'client.crt'",
|
|
123413
|
+
" $clientKey = Join-Path $sslRoot 'client.key'",
|
|
123414
|
+
" $caCert = Join-Path $sslRoot 'ca.crt'",
|
|
123415
|
+
" if (Test-Path -LiteralPath $clientCert) {",
|
|
123416
|
+
" $arguments += @('--ssl-client-cert', $clientCert, '--ssl-client-key', $clientKey)",
|
|
123417
|
+
" $passphrase = Resolve-AdoOptional $env:POSTMAN_SSL_CLIENT_PASSPHRASE",
|
|
123418
|
+
" if (-not [string]::IsNullOrWhiteSpace($passphrase)) {",
|
|
123419
|
+
" $arguments += @('--ssl-client-passphrase', $passphrase)",
|
|
123420
|
+
" }",
|
|
123421
|
+
" if (Test-Path -LiteralPath $caCert) {",
|
|
123422
|
+
" $arguments += @('--ssl-extra-ca-certs', $caCert)",
|
|
123423
|
+
" }",
|
|
123424
|
+
" }",
|
|
123425
|
+
" & postman @arguments",
|
|
123426
|
+
` if ($LASTEXITCODE -ne 0) { throw '${displayName} failed with exit code ' + $LASTEXITCODE }`,
|
|
123427
|
+
` displayName: ${displayName}`,
|
|
123428
|
+
" env:",
|
|
123429
|
+
` ${collectionEnvironmentName}: $(${collectionEnvironmentName})`,
|
|
123430
|
+
" POSTMAN_ENVIRONMENT_UID: $(POSTMAN_ENVIRONMENT_UID)",
|
|
123431
|
+
" CI_ENVIRONMENT: $(CI_ENVIRONMENT)",
|
|
123432
|
+
" POSTMAN_SSL_CLIENT_PASSPHRASE: $(POSTMAN_SSL_CLIENT_PASSPHRASE)"
|
|
123433
|
+
];
|
|
123434
|
+
}
|
|
123435
|
+
function buildAdoWindowsCiWorkflowLines(installUrl, postmanRegion) {
|
|
123436
|
+
return [
|
|
123437
|
+
"trigger:",
|
|
123438
|
+
" branches:",
|
|
123439
|
+
" include:",
|
|
123440
|
+
" - main",
|
|
123441
|
+
"schedules:",
|
|
123442
|
+
' - cron: "0 */6 * * *"',
|
|
123443
|
+
" displayName: Scheduled run",
|
|
123444
|
+
" branches:",
|
|
123445
|
+
" include:",
|
|
123446
|
+
" - main",
|
|
123447
|
+
" always: true",
|
|
123448
|
+
"pool:",
|
|
123449
|
+
" vmImage: windows-latest",
|
|
123450
|
+
"steps:",
|
|
123451
|
+
" - checkout: self",
|
|
123452
|
+
" persistCredentials: true",
|
|
123453
|
+
" - pwsh: |",
|
|
123454
|
+
" $ErrorActionPreference = 'Stop'",
|
|
123455
|
+
" if (-not (Get-Command postman -ErrorAction SilentlyContinue)) {",
|
|
123456
|
+
" [System.Net.ServicePointManager]::SecurityProtocol = 3072",
|
|
123457
|
+
" Invoke-Expression ((New-Object System.Net.WebClient).DownloadString($env:POSTMAN_CLI_INSTALL_URL))",
|
|
123458
|
+
" }",
|
|
123459
|
+
" & postman --version",
|
|
123460
|
+
" if ($LASTEXITCODE -ne 0) { throw 'Postman CLI installation failed' }",
|
|
123461
|
+
" displayName: Install Postman CLI",
|
|
123462
|
+
" env:",
|
|
123463
|
+
` POSTMAN_CLI_INSTALL_URL: ${installUrl}`,
|
|
123464
|
+
" - pwsh: |",
|
|
123465
|
+
" $ErrorActionPreference = 'Stop'",
|
|
123466
|
+
" $arguments = @('login', '--with-api-key', $env:POSTMAN_API_KEY)",
|
|
123467
|
+
...postmanRegion === "eu" ? [" $arguments += @('--region', 'eu')"] : [],
|
|
123468
|
+
" & postman @arguments",
|
|
123469
|
+
" if ($LASTEXITCODE -ne 0) { throw 'Postman CLI login failed' }",
|
|
123470
|
+
" displayName: Login to Postman CLI",
|
|
123471
|
+
" env:",
|
|
123472
|
+
" POSTMAN_API_KEY: $(POSTMAN_API_KEY)",
|
|
123473
|
+
" - pwsh: |",
|
|
123474
|
+
" $ErrorActionPreference = 'Stop'",
|
|
123475
|
+
" $section = ''",
|
|
123476
|
+
" $smoke = ''",
|
|
123477
|
+
" $contract = ''",
|
|
123478
|
+
" $environment = ''",
|
|
123479
|
+
" $fallbackEnvironment = ''",
|
|
123480
|
+
" foreach ($line in Get-Content -LiteralPath '.postman/resources.yaml') {",
|
|
123481
|
+
" if ($line -match '^ (collections|environments):\\s*$') { $section = $Matches[1]; continue }",
|
|
123482
|
+
" if ($line -notmatch '^ (.+?):\\s+(.+?)\\s*$') { continue }",
|
|
123483
|
+
` $key = $Matches[1].Trim().Trim("'").Trim('"')`,
|
|
123484
|
+
` $value = $Matches[2].Trim().Trim("'").Trim('"')`,
|
|
123485
|
+
" if ($section -eq 'collections' -and $key -match '\\[Smoke\\]') { $smoke = $value }",
|
|
123486
|
+
" if ($section -eq 'collections' -and $key -match '\\[Contract\\]') { $contract = $value }",
|
|
123487
|
+
" if ($section -eq 'environments') {",
|
|
123488
|
+
" if ([string]::IsNullOrWhiteSpace($fallbackEnvironment)) { $fallbackEnvironment = $value }",
|
|
123489
|
+
" if ($key -match 'prod\\.postman_environment\\.json$') { $environment = $value }",
|
|
123490
|
+
" }",
|
|
123491
|
+
" }",
|
|
123492
|
+
" if ([string]::IsNullOrWhiteSpace($environment)) { $environment = $fallbackEnvironment }",
|
|
123493
|
+
" if ([string]::IsNullOrWhiteSpace($smoke)) { throw 'Missing smoke collection UID in .postman/resources.yaml' }",
|
|
123494
|
+
" if ([string]::IsNullOrWhiteSpace($contract)) { throw 'Missing contract collection UID in .postman/resources.yaml' }",
|
|
123495
|
+
" if ([string]::IsNullOrWhiteSpace($environment)) { throw 'Missing environment UID in .postman/resources.yaml' }",
|
|
123496
|
+
' Write-Host "##vso[task.setvariable variable=POSTMAN_SMOKE_COLLECTION_UID]$smoke"',
|
|
123497
|
+
' Write-Host "##vso[task.setvariable variable=POSTMAN_CONTRACT_COLLECTION_UID]$contract"',
|
|
123498
|
+
' Write-Host "##vso[task.setvariable variable=POSTMAN_ENVIRONMENT_UID]$environment"',
|
|
123499
|
+
" displayName: Resolve Postman Resource IDs",
|
|
123500
|
+
" - pwsh: |",
|
|
123501
|
+
" $ErrorActionPreference = 'Stop'",
|
|
123502
|
+
" function Resolve-AdoOptional([string]$Value) {",
|
|
123503
|
+
" if ($Value -match '^\\$\\([^)]+\\)$') { return '' }",
|
|
123504
|
+
" return $Value",
|
|
123505
|
+
" }",
|
|
123506
|
+
" $sslRoot = Join-Path $env:AGENT_TEMPDIRECTORY 'postman-ssl'",
|
|
123507
|
+
" New-Item -ItemType Directory -Path $sslRoot -Force | Out-Null",
|
|
123508
|
+
" [IO.File]::WriteAllBytes((Join-Path $sslRoot 'client.crt'), [Convert]::FromBase64String($env:POSTMAN_SSL_CLIENT_CERT_B64))",
|
|
123509
|
+
" [IO.File]::WriteAllBytes((Join-Path $sslRoot 'client.key'), [Convert]::FromBase64String($env:POSTMAN_SSL_CLIENT_KEY_B64))",
|
|
123510
|
+
" $extraCa = Resolve-AdoOptional $env:POSTMAN_SSL_EXTRA_CA_CERTS_B64",
|
|
123511
|
+
" if (-not [string]::IsNullOrWhiteSpace($extraCa)) {",
|
|
123512
|
+
" [IO.File]::WriteAllBytes((Join-Path $sslRoot 'ca.crt'), [Convert]::FromBase64String($extraCa))",
|
|
123513
|
+
" }",
|
|
123514
|
+
" condition: ne(variables['POSTMAN_SSL_CLIENT_CERT_B64'], '')",
|
|
123515
|
+
" displayName: Decode SSL certificates",
|
|
123516
|
+
" env:",
|
|
123517
|
+
" POSTMAN_SSL_CLIENT_CERT_B64: $(POSTMAN_SSL_CLIENT_CERT_B64)",
|
|
123518
|
+
" POSTMAN_SSL_CLIENT_KEY_B64: $(POSTMAN_SSL_CLIENT_KEY_B64)",
|
|
123519
|
+
" POSTMAN_SSL_EXTRA_CA_CERTS_B64: $(POSTMAN_SSL_EXTRA_CA_CERTS_B64)",
|
|
123520
|
+
...buildAdoWindowsCollectionRunLines("Run Smoke Tests", "POSTMAN_SMOKE_COLLECTION_UID"),
|
|
123521
|
+
...buildAdoWindowsCollectionRunLines("Run Contract Tests", "POSTMAN_CONTRACT_COLLECTION_UID"),
|
|
123522
|
+
""
|
|
123523
|
+
];
|
|
123524
|
+
}
|
|
123385
123525
|
function buildAdoCiWorkflowLines(installUrl, postmanRegion) {
|
|
123386
123526
|
return [
|
|
123387
123527
|
"trigger:",
|
|
@@ -123561,10 +123701,12 @@ function renderGcWorkflowTemplate() {
|
|
|
123561
123701
|
}
|
|
123562
123702
|
var GC_WORKFLOW_TEMPLATE = renderGcWorkflowTemplate();
|
|
123563
123703
|
function getCiWorkflowTemplate(provider, options = {}) {
|
|
123704
|
+
const runnerOs = resolveCiRunnerOs(options.runnerOs);
|
|
123564
123705
|
if (provider === "azure-devops") {
|
|
123565
|
-
const rawUrl = String(options.postmanCliInstallUrl || "").trim() || DEFAULT_POSTMAN_CLI_INSTALL_URL;
|
|
123706
|
+
const rawUrl = runnerOs === "windows" ? String(options.postmanCliWindowsInstallUrl || "").trim() || DEFAULT_POSTMAN_CLI_WINDOWS_INSTALL_URL : String(options.postmanCliInstallUrl || "").trim() || DEFAULT_POSTMAN_CLI_INSTALL_URL;
|
|
123566
123707
|
const postmanRegion = resolvePostmanRegion(options.postmanRegion);
|
|
123567
|
-
|
|
123708
|
+
const installUrl = validateHttpsInstallUrl(rawUrl);
|
|
123709
|
+
return (runnerOs === "windows" ? buildAdoWindowsCiWorkflowLines(installUrl, postmanRegion) : buildAdoCiWorkflowLines(installUrl, postmanRegion)).join("\n");
|
|
123568
123710
|
}
|
|
123569
123711
|
return renderCiWorkflowTemplate(options);
|
|
123570
123712
|
}
|
|
@@ -124959,6 +125101,17 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
124959
125101
|
mask: this.secretMasker
|
|
124960
125102
|
};
|
|
124961
125103
|
}
|
|
125104
|
+
/**
|
|
125105
|
+
* One-line non-fatal preflight reason: operation + entity (repo/path) + cause +
|
|
125106
|
+
* operator action. Secrets are redacted via secretMasker, then CR/LF and other
|
|
125107
|
+
* line-breaking whitespace are collapsed to spaces so CI logs stay one line.
|
|
125108
|
+
* Display-only: does not alter request repoUrl/path or probe classification.
|
|
125109
|
+
*/
|
|
125110
|
+
unknownFilesystemLookupReason(repoUrl, fsPath, cause) {
|
|
125111
|
+
return this.secretMasker(
|
|
125112
|
+
`filesystem lookup for repository ${repoUrl} path ${fsPath} ${cause}; verify Bifrost connectivity/credentials then rerun`
|
|
125113
|
+
).replace(/[\r\n\v\f\u2028\u2029]+/g, " ");
|
|
125114
|
+
}
|
|
124962
125115
|
async associateSystemEnvironments(workspaceId, associations) {
|
|
124963
125116
|
if (associations.length === 0) {
|
|
124964
125117
|
return;
|
|
@@ -124998,7 +125151,106 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
124998
125151
|
throw advised ?? httpErr;
|
|
124999
125152
|
}
|
|
125000
125153
|
}
|
|
125001
|
-
|
|
125154
|
+
/**
|
|
125155
|
+
* Probe who (if anyone) already owns the global `(repo, path)` filesystem
|
|
125156
|
+
* link. Non-fatal: unexpected statuses / network errors yield `unknown` so
|
|
125157
|
+
* callers can proceed and rely on reactive POST conflict handling.
|
|
125158
|
+
*
|
|
125159
|
+
* Bifrost states (FileSystemController.fetchWorkspaceForFileSystem):
|
|
125160
|
+
* - 200 + data null -> free
|
|
125161
|
+
* - 200 + data -> linked-visible (workspace payload)
|
|
125162
|
+
* - 403 + error.meta.workspaceId -> linked-invisible
|
|
125163
|
+
* - 200 + error.meta.workspaceId -> linked-invisible (proxy envelope)
|
|
125164
|
+
*/
|
|
125165
|
+
async findWorkspaceForRepo(repoUrl, path5 = "/") {
|
|
125166
|
+
const fsPath = path5 && path5.trim() ? path5.trim() : "/";
|
|
125167
|
+
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
125168
|
+
const payload = {
|
|
125169
|
+
service: "workspaces",
|
|
125170
|
+
method: "GET",
|
|
125171
|
+
path: `/workspaces/filesystem?repo=${encodeURIComponent(repoUrl)}&path=${encodeURIComponent(fsPath)}`
|
|
125172
|
+
};
|
|
125173
|
+
try {
|
|
125174
|
+
const response = await this.fetchImpl(url, {
|
|
125175
|
+
method: "POST",
|
|
125176
|
+
headers: this.bifrostHeaders(),
|
|
125177
|
+
body: JSON.stringify(payload)
|
|
125178
|
+
});
|
|
125179
|
+
let parsed = {};
|
|
125180
|
+
try {
|
|
125181
|
+
parsed = await response.json();
|
|
125182
|
+
} catch {
|
|
125183
|
+
return {
|
|
125184
|
+
state: "unknown",
|
|
125185
|
+
reason: this.unknownFilesystemLookupReason(
|
|
125186
|
+
repoUrl,
|
|
125187
|
+
fsPath,
|
|
125188
|
+
`returned non-JSON body (HTTP ${response.status})`
|
|
125189
|
+
)
|
|
125190
|
+
};
|
|
125191
|
+
}
|
|
125192
|
+
const errorMetaWorkspaceId = typeof parsed?.error?.meta?.workspaceId === "string" && parsed.error.meta.workspaceId.trim() ? parsed.error.meta.workspaceId.trim() : void 0;
|
|
125193
|
+
if (errorMetaWorkspaceId) {
|
|
125194
|
+
return { state: "linked-invisible", workspaceId: errorMetaWorkspaceId };
|
|
125195
|
+
}
|
|
125196
|
+
if (response.ok) {
|
|
125197
|
+
if (parsed?.data == null) {
|
|
125198
|
+
return { state: "free" };
|
|
125199
|
+
}
|
|
125200
|
+
const id = typeof parsed.data.id === "string" ? parsed.data.id.trim() : "";
|
|
125201
|
+
if (!id) {
|
|
125202
|
+
return {
|
|
125203
|
+
state: "unknown",
|
|
125204
|
+
reason: this.unknownFilesystemLookupReason(
|
|
125205
|
+
repoUrl,
|
|
125206
|
+
fsPath,
|
|
125207
|
+
"returned 200 without a workspace id"
|
|
125208
|
+
)
|
|
125209
|
+
};
|
|
125210
|
+
}
|
|
125211
|
+
const name = typeof parsed.data.name === "string" && parsed.data.name.trim() ? parsed.data.name.trim() : void 0;
|
|
125212
|
+
return {
|
|
125213
|
+
state: "linked-visible",
|
|
125214
|
+
workspace: name ? { id, name } : { id }
|
|
125215
|
+
};
|
|
125216
|
+
}
|
|
125217
|
+
if (response.status === 403) {
|
|
125218
|
+
const workspaceId = extractDuplicateWorkspaceId(
|
|
125219
|
+
JSON.stringify(parsed)
|
|
125220
|
+
);
|
|
125221
|
+
if (workspaceId) {
|
|
125222
|
+
return { state: "linked-invisible", workspaceId };
|
|
125223
|
+
}
|
|
125224
|
+
return {
|
|
125225
|
+
state: "unknown",
|
|
125226
|
+
reason: this.unknownFilesystemLookupReason(
|
|
125227
|
+
repoUrl,
|
|
125228
|
+
fsPath,
|
|
125229
|
+
"returned 403 without error.meta.workspaceId"
|
|
125230
|
+
)
|
|
125231
|
+
};
|
|
125232
|
+
}
|
|
125233
|
+
return {
|
|
125234
|
+
state: "unknown",
|
|
125235
|
+
reason: this.unknownFilesystemLookupReason(
|
|
125236
|
+
repoUrl,
|
|
125237
|
+
fsPath,
|
|
125238
|
+
`returned HTTP ${response.status}`
|
|
125239
|
+
)
|
|
125240
|
+
};
|
|
125241
|
+
} catch (error) {
|
|
125242
|
+
const cause = error instanceof Error ? error.message : String(error);
|
|
125243
|
+
return {
|
|
125244
|
+
state: "unknown",
|
|
125245
|
+
reason: this.unknownFilesystemLookupReason(
|
|
125246
|
+
repoUrl,
|
|
125247
|
+
fsPath,
|
|
125248
|
+
`failed: ${cause}`
|
|
125249
|
+
)
|
|
125250
|
+
};
|
|
125251
|
+
}
|
|
125252
|
+
}
|
|
125253
|
+
async connectWorkspaceToRepository(workspaceId, repoUrl, options) {
|
|
125002
125254
|
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
125003
125255
|
const payload = {
|
|
125004
125256
|
service: "workspaces",
|
|
@@ -125025,6 +125277,11 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
125025
125277
|
if (isDuplicate) {
|
|
125026
125278
|
const existingWorkspaceId = extractDuplicateWorkspaceId(body);
|
|
125027
125279
|
if (existingWorkspaceId && existingWorkspaceId !== workspaceId) {
|
|
125280
|
+
if (options?.preflightWasFree) {
|
|
125281
|
+
throw new Error(
|
|
125282
|
+
`REPOSITORY_LINK_CONFLICT_UNRESOLVED: Preflight found no active owner, but link creation reported workspace ${existingWorkspaceId}. Stop and contact Postman support; do not alter the repository URL.`
|
|
125283
|
+
);
|
|
125284
|
+
}
|
|
125028
125285
|
throw new Error(
|
|
125029
125286
|
await this.describeWorkspaceLinkConflict(existingWorkspaceId, workspaceId, repoUrl)
|
|
125030
125287
|
);
|
|
@@ -125203,6 +125460,12 @@ var postmanRepoSyncActionContract = {
|
|
|
125203
125460
|
required: false,
|
|
125204
125461
|
default: ".github/workflows/ci.yml"
|
|
125205
125462
|
},
|
|
125463
|
+
"ci-runner-os": {
|
|
125464
|
+
description: "Runner operating system for the generated CI workflow.",
|
|
125465
|
+
required: false,
|
|
125466
|
+
default: "linux",
|
|
125467
|
+
allowedValues: ["linux", "windows"]
|
|
125468
|
+
},
|
|
125206
125469
|
"project-name": {
|
|
125207
125470
|
description: "Service project name used for environment, mock, and monitor naming.",
|
|
125208
125471
|
required: true
|
|
@@ -126862,6 +127125,25 @@ function parseAssetMarker(description) {
|
|
|
126862
127125
|
}
|
|
126863
127126
|
|
|
126864
127127
|
// src/index.ts
|
|
127128
|
+
var identitySecretMasker = (input) => input;
|
|
127129
|
+
function resolveRepoSyncMasker(dependencies) {
|
|
127130
|
+
return dependencies.secretMasker ?? identitySecretMasker;
|
|
127131
|
+
}
|
|
127132
|
+
function causeText(cause) {
|
|
127133
|
+
return cause instanceof Error ? cause.message : String(cause);
|
|
127134
|
+
}
|
|
127135
|
+
function toOneLineDisplay(value) {
|
|
127136
|
+
return String(value ?? "").replace(/[\r\n\u0085\u2028\u2029\v\f]+/g, " ").replace(/[ \t]{2,}/g, " ").trim();
|
|
127137
|
+
}
|
|
127138
|
+
function formatOrchestrationIssue(params) {
|
|
127139
|
+
const operation = toOneLineDisplay(params.mask(params.operation));
|
|
127140
|
+
const entity = toOneLineDisplay(params.mask(params.entity));
|
|
127141
|
+
const maskedCause = toOneLineDisplay(params.mask(causeText(params.cause)));
|
|
127142
|
+
const detail = toOneLineDisplay(params.mask(params.detail ?? ""));
|
|
127143
|
+
const remediation = toOneLineDisplay(params.mask(params.remediation));
|
|
127144
|
+
const body = `${operation} failed for ${entity}: ${maskedCause}${detail}`.replace(/[.]+$/u, "");
|
|
127145
|
+
return toOneLineDisplay(`${body}. ${remediation}`);
|
|
127146
|
+
}
|
|
126865
127147
|
function parseBooleanInput(value, defaultValue) {
|
|
126866
127148
|
const normalized = String(value || "").trim().toLowerCase();
|
|
126867
127149
|
if (!normalized) return defaultValue;
|
|
@@ -126958,6 +127240,17 @@ function parseBranchStrategy(value) {
|
|
|
126958
127240
|
`Unsupported branch-strategy "${normalized}". Supported values: ${allowed.join(", ")}`
|
|
126959
127241
|
);
|
|
126960
127242
|
}
|
|
127243
|
+
function parseCiRunnerOs(value) {
|
|
127244
|
+
const definition = postmanRepoSyncActionContract.inputs["ci-runner-os"];
|
|
127245
|
+
const allowed = definition.allowedValues ?? [];
|
|
127246
|
+
const normalized = String(value || "").trim() || (definition.default ?? "linux");
|
|
127247
|
+
if (allowed.includes(normalized)) {
|
|
127248
|
+
return normalized;
|
|
127249
|
+
}
|
|
127250
|
+
throw new Error(
|
|
127251
|
+
`Unsupported ci-runner-os "${normalized}". Supported values: ${allowed.join(", ")}`
|
|
127252
|
+
);
|
|
127253
|
+
}
|
|
126961
127254
|
function normalizeReleaseLabel(value) {
|
|
126962
127255
|
const cleaned = normalizeInputValue(value).replace(/^refs\/heads\//, "").replace(/^refs\/tags\//, "").replace(/\s+/g, "-").replace(/[^A-Za-z0-9._-]/g, "-").replace(/-+/g, "-").replace(/^[._-]+|[._-]+$/g, "");
|
|
126963
127256
|
return cleaned;
|
|
@@ -127035,6 +127328,7 @@ function resolveInputs(env = process.env) {
|
|
|
127035
127328
|
provider: repoContext.provider,
|
|
127036
127329
|
ciWorkflowBase64: getInput("ci-workflow-base64", env),
|
|
127037
127330
|
generateCiWorkflow: parseBooleanInput(getInput("generate-ci-workflow", env), true),
|
|
127331
|
+
ciRunnerOs: parseCiRunnerOs(getInput("ci-runner-os", env)),
|
|
127038
127332
|
monitorType: getInput("monitor-type", env) || "cloud",
|
|
127039
127333
|
ciWorkflowPath: getInput("ci-workflow-path", env) || (repoContext.provider === "azure-devops" ? "azure-pipelines.yml" : ".github/workflows/ci.yml"),
|
|
127040
127334
|
orgMode: parseBooleanInput(getInput("org-mode", env), false),
|
|
@@ -127053,6 +127347,7 @@ function resolveInputs(env = process.env) {
|
|
|
127053
127347
|
postmanBifrostBase: endpointProfile.bifrostBaseUrl,
|
|
127054
127348
|
postmanFallbackBase: endpointProfile.fallbackBaseUrl,
|
|
127055
127349
|
postmanCliInstallUrl: endpointProfile.cliInstallUrl,
|
|
127350
|
+
postmanCliWindowsInstallUrl: endpointProfile.cliWindowsInstallUrl,
|
|
127056
127351
|
postmanIapubBase: endpointProfile.iapubBaseUrl
|
|
127057
127352
|
};
|
|
127058
127353
|
}
|
|
@@ -127301,19 +127596,34 @@ async function upsertEnvironments(inputs, dependencies, resourcesState, assetMar
|
|
|
127301
127596
|
if (!inputs.workspaceId) {
|
|
127302
127597
|
return envUids;
|
|
127303
127598
|
}
|
|
127599
|
+
const mask = resolveRepoSyncMasker(dependencies);
|
|
127600
|
+
const envRemediation = "verify access-token/team/workspace permissions then rerun";
|
|
127304
127601
|
for (const envName of inputs.environments) {
|
|
127305
127602
|
const runtimeUrl = String(inputs.envRuntimeUrls[envName] || "").trim();
|
|
127306
127603
|
const displayName = `${inputs.projectName} - ${envName}`;
|
|
127307
127604
|
let existingUid = String(envUids[envName] || "").trim();
|
|
127308
127605
|
if (!existingUid) {
|
|
127309
|
-
|
|
127310
|
-
|
|
127311
|
-
|
|
127312
|
-
|
|
127313
|
-
|
|
127314
|
-
|
|
127315
|
-
|
|
127316
|
-
|
|
127606
|
+
try {
|
|
127607
|
+
const discovered = await dependencies.postman.findEnvironmentByName(
|
|
127608
|
+
inputs.workspaceId,
|
|
127609
|
+
displayName
|
|
127610
|
+
);
|
|
127611
|
+
if (discovered?.uid) {
|
|
127612
|
+
existingUid = discovered.uid;
|
|
127613
|
+
dependencies.core.info(
|
|
127614
|
+
`Discovered existing environment for ${displayName}: ${existingUid}`
|
|
127615
|
+
);
|
|
127616
|
+
}
|
|
127617
|
+
} catch (error) {
|
|
127618
|
+
throw new Error(
|
|
127619
|
+
formatOrchestrationIssue({
|
|
127620
|
+
operation: "Environment discovery",
|
|
127621
|
+
entity: `workspace ${inputs.workspaceId} environment "${displayName}"`,
|
|
127622
|
+
cause: error,
|
|
127623
|
+
remediation: envRemediation,
|
|
127624
|
+
mask
|
|
127625
|
+
}),
|
|
127626
|
+
{ cause: error }
|
|
127317
127627
|
);
|
|
127318
127628
|
}
|
|
127319
127629
|
}
|
|
@@ -127333,17 +127643,43 @@ async function upsertEnvironments(inputs, dependencies, resourcesState, assetMar
|
|
|
127333
127643
|
}
|
|
127334
127644
|
const values2 = buildEnvironmentValues(envName, runtimeUrl);
|
|
127335
127645
|
if (marker) values2.push({ key: "x-pm-onboarding", value: JSON.stringify(marker), type: "default" });
|
|
127336
|
-
|
|
127646
|
+
try {
|
|
127647
|
+
await dependencies.postman.updateEnvironment(existingUid, displayName, values2);
|
|
127648
|
+
} catch (error) {
|
|
127649
|
+
throw new Error(
|
|
127650
|
+
formatOrchestrationIssue({
|
|
127651
|
+
operation: "Environment update",
|
|
127652
|
+
entity: `workspace ${inputs.workspaceId} environment "${displayName}" (uid ${existingUid})`,
|
|
127653
|
+
cause: error,
|
|
127654
|
+
remediation: envRemediation,
|
|
127655
|
+
mask
|
|
127656
|
+
}),
|
|
127657
|
+
{ cause: error }
|
|
127658
|
+
);
|
|
127659
|
+
}
|
|
127337
127660
|
envUids[envName] = existingUid;
|
|
127338
127661
|
continue;
|
|
127339
127662
|
}
|
|
127340
127663
|
const values = buildEnvironmentValues(envName, runtimeUrl);
|
|
127341
127664
|
if (assetMarker) values.push({ key: "x-pm-onboarding", value: JSON.stringify(assetMarker), type: "default" });
|
|
127342
|
-
|
|
127343
|
-
|
|
127344
|
-
|
|
127345
|
-
|
|
127346
|
-
|
|
127665
|
+
try {
|
|
127666
|
+
envUids[envName] = await dependencies.postman.createEnvironment(
|
|
127667
|
+
inputs.workspaceId,
|
|
127668
|
+
displayName,
|
|
127669
|
+
values
|
|
127670
|
+
);
|
|
127671
|
+
} catch (error) {
|
|
127672
|
+
throw new Error(
|
|
127673
|
+
formatOrchestrationIssue({
|
|
127674
|
+
operation: "Environment create",
|
|
127675
|
+
entity: `workspace ${inputs.workspaceId} environment "${displayName}"`,
|
|
127676
|
+
cause: error,
|
|
127677
|
+
remediation: envRemediation,
|
|
127678
|
+
mask
|
|
127679
|
+
}),
|
|
127680
|
+
{ cause: error }
|
|
127681
|
+
);
|
|
127682
|
+
}
|
|
127347
127683
|
}
|
|
127348
127684
|
return envUids;
|
|
127349
127685
|
}
|
|
@@ -127600,11 +127936,15 @@ function renderCiWorkflow(inputs) {
|
|
|
127600
127936
|
if (inputs.provider === "azure-devops") {
|
|
127601
127937
|
return getCiWorkflowTemplate(inputs.provider, {
|
|
127602
127938
|
postmanCliInstallUrl: inputs.postmanCliInstallUrl,
|
|
127939
|
+
postmanCliWindowsInstallUrl: inputs.postmanCliWindowsInstallUrl,
|
|
127940
|
+
runnerOs: inputs.ciRunnerOs,
|
|
127603
127941
|
postmanRegion: inputs.postmanRegion
|
|
127604
127942
|
});
|
|
127605
127943
|
}
|
|
127606
127944
|
return renderCiWorkflowTemplate({
|
|
127607
127945
|
postmanCliInstallUrl: inputs.postmanCliInstallUrl,
|
|
127946
|
+
postmanCliWindowsInstallUrl: inputs.postmanCliWindowsInstallUrl,
|
|
127947
|
+
runnerOs: inputs.ciRunnerOs,
|
|
127608
127948
|
postmanRegion: inputs.postmanRegion
|
|
127609
127949
|
});
|
|
127610
127950
|
}
|
|
@@ -127699,6 +128039,7 @@ async function runRepoSync(inputs, dependencies) {
|
|
|
127699
128039
|
}
|
|
127700
128040
|
}
|
|
127701
128041
|
async function runRepoSyncInner(inputs, dependencies) {
|
|
128042
|
+
const mask = resolveRepoSyncMasker(dependencies);
|
|
127702
128043
|
const branchDecision = decideBranchTier(inputs);
|
|
127703
128044
|
assertBranchAssetIds(inputs, branchDecision);
|
|
127704
128045
|
const isCanonicalWriter = branchDecision.tier === "legacy" || branchDecision.tier === "canonical";
|
|
@@ -127758,6 +128099,39 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
127758
128099
|
}
|
|
127759
128100
|
}
|
|
127760
128101
|
}
|
|
128102
|
+
let skipRepositoryLinkPost = false;
|
|
128103
|
+
let repositoryLinkPreflightWasFree = false;
|
|
128104
|
+
if (inputs.workspaceLinkEnabled && inputs.workspaceId && inputs.repoUrl && dependencies.internalIntegration?.findWorkspaceForRepo) {
|
|
128105
|
+
const probe = await dependencies.internalIntegration.findWorkspaceForRepo(
|
|
128106
|
+
inputs.repoUrl,
|
|
128107
|
+
"/"
|
|
128108
|
+
);
|
|
128109
|
+
if (probe.state === "linked-visible") {
|
|
128110
|
+
if (probe.workspace.id === inputs.workspaceId) {
|
|
128111
|
+
skipRepositoryLinkPost = true;
|
|
128112
|
+
dependencies.core.info(
|
|
128113
|
+
`REPOSITORY_LINK_ALREADY_TARGET: Repository ${inputs.repoUrl} at path / is already linked to target workspace ${inputs.workspaceId}; continuing.`
|
|
128114
|
+
);
|
|
128115
|
+
} else {
|
|
128116
|
+
const ownerName = probe.workspace.name?.trim() || "unknown";
|
|
128117
|
+
throw new Error(
|
|
128118
|
+
`REPOSITORY_LINK_CONFLICT_VISIBLE: Repository ${inputs.repoUrl} at path / is already linked to workspace ${probe.workspace.id} ("${ownerName}"). No Postman assets were changed. Reuse that workspace or disconnect it in Workspace Settings, then rerun.`
|
|
128119
|
+
);
|
|
128120
|
+
}
|
|
128121
|
+
} else if (probe.state === "linked-invisible") {
|
|
128122
|
+
let message = `REPOSITORY_LINK_CONFLICT_INVISIBLE: Repository ${inputs.repoUrl} at path / is linked to workspace ${probe.workspaceId}, but these credentials cannot view it. No Postman assets were changed. Ask its owner or a team admin to disconnect it.`;
|
|
128123
|
+
if (inputs.orgMode) {
|
|
128124
|
+
message += " Verify workspace-team-id; if the owner is in another sub-team, ask that sub-team's admin to disconnect it.";
|
|
128125
|
+
}
|
|
128126
|
+
throw new Error(message);
|
|
128127
|
+
} else if (probe.state === "free") {
|
|
128128
|
+
repositoryLinkPreflightWasFree = true;
|
|
128129
|
+
} else {
|
|
128130
|
+
dependencies.core.warning(
|
|
128131
|
+
`REPOSITORY_LINK_PREFLIGHT_UNKNOWN: Unable to determine the existing repository link (${probe.reason}); continuing and relying on link creation conflict handling.`
|
|
128132
|
+
);
|
|
128133
|
+
}
|
|
128134
|
+
}
|
|
127761
128135
|
const branchAssetMarker = buildBranchAssetMarker(branchDecision, inputs);
|
|
127762
128136
|
const envUids = await upsertEnvironments(inputs, dependencies, resourcesState, branchAssetMarker);
|
|
127763
128137
|
outputs["environment-uids-json"] = JSON.stringify(envUids);
|
|
@@ -127775,8 +128149,15 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
127775
128149
|
outputs["environment-sync-status"] = "success";
|
|
127776
128150
|
} catch (error) {
|
|
127777
128151
|
outputs["environment-sync-status"] = "failed";
|
|
128152
|
+
const associationSummary = associations.map((entry) => `${entry.envUid}->${entry.systemEnvId}`).join(", ");
|
|
127778
128153
|
dependencies.core.warning(
|
|
127779
|
-
|
|
128154
|
+
formatOrchestrationIssue({
|
|
128155
|
+
operation: "System environment association",
|
|
128156
|
+
entity: `workspace ${inputs.workspaceId} (${associationSummary})`,
|
|
128157
|
+
cause: error,
|
|
128158
|
+
remediation: "verify access-token/team/system-env mapping then rerun",
|
|
128159
|
+
mask
|
|
128160
|
+
})
|
|
127780
128161
|
);
|
|
127781
128162
|
}
|
|
127782
128163
|
} else if (Object.keys(envUids).length > 0) {
|
|
@@ -127804,37 +128185,72 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
127804
128185
|
dependencies.core.info(`Reusing mock from explicit input: ${resolvedMockUrl}`);
|
|
127805
128186
|
}
|
|
127806
128187
|
if (!resolvedMockUrl && inputs.baselineCollectionId) {
|
|
127807
|
-
|
|
127808
|
-
|
|
127809
|
-
|
|
127810
|
-
|
|
127811
|
-
|
|
127812
|
-
|
|
127813
|
-
|
|
127814
|
-
|
|
128188
|
+
try {
|
|
128189
|
+
const discovered = await dependencies.postman.findMockByCollection(
|
|
128190
|
+
inputs.baselineCollectionId,
|
|
128191
|
+
mockEnvUid,
|
|
128192
|
+
mockName
|
|
128193
|
+
);
|
|
128194
|
+
if (discovered) {
|
|
128195
|
+
resolvedMockUrl = discovered.mockUrl;
|
|
128196
|
+
dependencies.core.info(`Discovered existing mock for collection ${inputs.baselineCollectionId}: ${resolvedMockUrl}`);
|
|
128197
|
+
}
|
|
128198
|
+
} catch (error) {
|
|
128199
|
+
throw new Error(
|
|
128200
|
+
formatOrchestrationIssue({
|
|
128201
|
+
operation: "Mock discovery",
|
|
128202
|
+
entity: `mock "${mockName}" workspace ${inputs.workspaceId} collection ${inputs.baselineCollectionId} environment ${mockEnvUid}`,
|
|
128203
|
+
cause: error,
|
|
128204
|
+
remediation: "verify collection/environment access then rerun",
|
|
128205
|
+
mask
|
|
128206
|
+
}),
|
|
128207
|
+
{ cause: error }
|
|
128208
|
+
);
|
|
127815
128209
|
}
|
|
127816
128210
|
}
|
|
127817
128211
|
if (!resolvedMockUrl) {
|
|
127818
|
-
const
|
|
127819
|
-
|
|
127820
|
-
|
|
127821
|
-
|
|
127822
|
-
|
|
127823
|
-
|
|
127824
|
-
|
|
127825
|
-
|
|
127826
|
-
|
|
127827
|
-
|
|
127828
|
-
|
|
127829
|
-
|
|
127830
|
-
|
|
127831
|
-
|
|
127832
|
-
)
|
|
128212
|
+
const mockEntity = `mock "${mockName}" workspace ${inputs.workspaceId} collection ${inputs.baselineCollectionId} environment ${mockEnvUid}`;
|
|
128213
|
+
const mockRemediation = "verify collection/environment access then rerun";
|
|
128214
|
+
try {
|
|
128215
|
+
const mock = await retry(
|
|
128216
|
+
() => dependencies.postman.createMock(
|
|
128217
|
+
inputs.workspaceId,
|
|
128218
|
+
mockName,
|
|
128219
|
+
inputs.baselineCollectionId,
|
|
128220
|
+
mockEnvUid
|
|
128221
|
+
),
|
|
128222
|
+
{
|
|
128223
|
+
maxAttempts: 3,
|
|
128224
|
+
delayMs: 2e3,
|
|
128225
|
+
backoffMultiplier: 2,
|
|
128226
|
+
onRetry: ({ attempt, maxAttempts, error }) => {
|
|
128227
|
+
dependencies.core.warning(
|
|
128228
|
+
formatOrchestrationIssue({
|
|
128229
|
+
operation: `Mock create attempt ${attempt}/${maxAttempts}`,
|
|
128230
|
+
entity: mockEntity,
|
|
128231
|
+
cause: error,
|
|
128232
|
+
remediation: mockRemediation,
|
|
128233
|
+
mask,
|
|
128234
|
+
detail: "; retrying"
|
|
128235
|
+
})
|
|
128236
|
+
);
|
|
128237
|
+
}
|
|
127833
128238
|
}
|
|
127834
|
-
|
|
127835
|
-
|
|
127836
|
-
|
|
127837
|
-
|
|
128239
|
+
);
|
|
128240
|
+
resolvedMockUrl = mock.url;
|
|
128241
|
+
dependencies.core.info(`Created new mock: ${resolvedMockUrl}`);
|
|
128242
|
+
} catch (error) {
|
|
128243
|
+
throw new Error(
|
|
128244
|
+
formatOrchestrationIssue({
|
|
128245
|
+
operation: "Mock create",
|
|
128246
|
+
entity: mockEntity,
|
|
128247
|
+
cause: error,
|
|
128248
|
+
remediation: mockRemediation,
|
|
128249
|
+
mask
|
|
128250
|
+
}),
|
|
128251
|
+
{ cause: error }
|
|
128252
|
+
);
|
|
128253
|
+
}
|
|
127838
128254
|
}
|
|
127839
128255
|
outputs["mock-url"] = resolvedMockUrl;
|
|
127840
128256
|
}
|
|
@@ -127845,35 +128261,71 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
127845
128261
|
if (monitorEnvUid && inputs.monitorType !== "cli") {
|
|
127846
128262
|
let resolvedMonitorId = "";
|
|
127847
128263
|
const monitorName = `${assetProjectName} - Smoke Monitor`;
|
|
128264
|
+
const monitorRemediation = "verify monitor IDs/access or set monitor-cron then rerun";
|
|
127848
128265
|
if (inputs.monitorId) {
|
|
127849
128266
|
const valid = await dependencies.postman.monitorExists(inputs.monitorId);
|
|
127850
128267
|
if (valid) {
|
|
127851
128268
|
resolvedMonitorId = inputs.monitorId;
|
|
127852
128269
|
dependencies.core.info(`Reusing monitor from explicit input: ${resolvedMonitorId}`);
|
|
127853
128270
|
} else {
|
|
127854
|
-
dependencies.core.warning(
|
|
128271
|
+
dependencies.core.warning(
|
|
128272
|
+
formatOrchestrationIssue({
|
|
128273
|
+
operation: "Explicit monitor-id lookup",
|
|
128274
|
+
entity: `monitor-id ${inputs.monitorId} workspace ${inputs.workspaceId} collection ${inputs.smokeCollectionId} environment ${monitorEnvUid}`,
|
|
128275
|
+
cause: "not found in Postman",
|
|
128276
|
+
remediation: monitorRemediation,
|
|
128277
|
+
mask,
|
|
128278
|
+
detail: "; falling through to discovery"
|
|
128279
|
+
})
|
|
128280
|
+
);
|
|
127855
128281
|
}
|
|
127856
128282
|
}
|
|
127857
128283
|
if (!resolvedMonitorId && inputs.smokeCollectionId) {
|
|
127858
|
-
|
|
127859
|
-
|
|
127860
|
-
|
|
127861
|
-
|
|
127862
|
-
|
|
127863
|
-
|
|
127864
|
-
|
|
127865
|
-
|
|
128284
|
+
try {
|
|
128285
|
+
const discovered = await dependencies.postman.findMonitorByCollection(
|
|
128286
|
+
inputs.smokeCollectionId,
|
|
128287
|
+
monitorEnvUid,
|
|
128288
|
+
monitorName
|
|
128289
|
+
);
|
|
128290
|
+
if (discovered) {
|
|
128291
|
+
resolvedMonitorId = discovered.uid;
|
|
128292
|
+
dependencies.core.info(`Discovered existing monitor for collection ${inputs.smokeCollectionId}: ${resolvedMonitorId}`);
|
|
128293
|
+
}
|
|
128294
|
+
} catch (error) {
|
|
128295
|
+
throw new Error(
|
|
128296
|
+
formatOrchestrationIssue({
|
|
128297
|
+
operation: "Monitor discovery",
|
|
128298
|
+
entity: `monitor "${monitorName}" workspace ${inputs.workspaceId} collection ${inputs.smokeCollectionId} environment ${monitorEnvUid}`,
|
|
128299
|
+
cause: error,
|
|
128300
|
+
remediation: monitorRemediation,
|
|
128301
|
+
mask
|
|
128302
|
+
}),
|
|
128303
|
+
{ cause: error }
|
|
128304
|
+
);
|
|
127866
128305
|
}
|
|
127867
128306
|
}
|
|
127868
128307
|
if (!resolvedMonitorId) {
|
|
127869
|
-
|
|
127870
|
-
|
|
127871
|
-
|
|
127872
|
-
|
|
127873
|
-
|
|
127874
|
-
|
|
127875
|
-
|
|
127876
|
-
|
|
128308
|
+
try {
|
|
128309
|
+
resolvedMonitorId = await dependencies.postman.createMonitor(
|
|
128310
|
+
inputs.workspaceId,
|
|
128311
|
+
monitorName,
|
|
128312
|
+
inputs.smokeCollectionId,
|
|
128313
|
+
monitorEnvUid,
|
|
128314
|
+
effectiveCron || void 0
|
|
128315
|
+
);
|
|
128316
|
+
dependencies.core.info(`Created new monitor: ${resolvedMonitorId}${effectiveCron ? "" : " (disabled \u2014 no cron configured; will trigger a one-time run)"}`);
|
|
128317
|
+
} catch (error) {
|
|
128318
|
+
throw new Error(
|
|
128319
|
+
formatOrchestrationIssue({
|
|
128320
|
+
operation: "Monitor create",
|
|
128321
|
+
entity: `monitor "${monitorName}" workspace ${inputs.workspaceId} collection ${inputs.smokeCollectionId} environment ${monitorEnvUid}`,
|
|
128322
|
+
cause: error,
|
|
128323
|
+
remediation: monitorRemediation,
|
|
128324
|
+
mask
|
|
128325
|
+
}),
|
|
128326
|
+
{ cause: error }
|
|
128327
|
+
);
|
|
128328
|
+
}
|
|
127877
128329
|
}
|
|
127878
128330
|
outputs["monitor-id"] = resolvedMonitorId;
|
|
127879
128331
|
if (!effectiveCron && resolvedMonitorId) {
|
|
@@ -127882,7 +128334,13 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
127882
128334
|
dependencies.core.info(`Triggered one-time run for monitor: ${resolvedMonitorId}`);
|
|
127883
128335
|
} catch (error) {
|
|
127884
128336
|
dependencies.core.warning(
|
|
127885
|
-
|
|
128337
|
+
formatOrchestrationIssue({
|
|
128338
|
+
operation: "Monitor one-time run",
|
|
128339
|
+
entity: `monitor ${resolvedMonitorId} name "${monitorName}" workspace ${inputs.workspaceId} collection ${inputs.smokeCollectionId} environment ${monitorEnvUid}`,
|
|
128340
|
+
cause: error,
|
|
128341
|
+
remediation: monitorRemediation,
|
|
128342
|
+
mask
|
|
128343
|
+
})
|
|
127886
128344
|
);
|
|
127887
128345
|
}
|
|
127888
128346
|
}
|
|
@@ -127890,18 +128348,33 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
127890
128348
|
}
|
|
127891
128349
|
if (inputs.workspaceLinkEnabled && inputs.workspaceId && inputs.repoUrl && dependencies.internalIntegration) {
|
|
127892
128350
|
try {
|
|
127893
|
-
|
|
127894
|
-
|
|
127895
|
-
|
|
127896
|
-
|
|
127897
|
-
|
|
127898
|
-
|
|
127899
|
-
|
|
127900
|
-
|
|
128351
|
+
if (skipRepositoryLinkPost) {
|
|
128352
|
+
outputs["workspace-link-status"] = "success";
|
|
128353
|
+
dependencies.core.info(
|
|
128354
|
+
`workspace-link-status=success workspace-id=${inputs.workspaceId} repo=${inputs.repoUrl} (preflight already-target; link POST skipped)`
|
|
128355
|
+
);
|
|
128356
|
+
} else {
|
|
128357
|
+
await dependencies.internalIntegration.connectWorkspaceToRepository(
|
|
128358
|
+
inputs.workspaceId,
|
|
128359
|
+
inputs.repoUrl,
|
|
128360
|
+
repositoryLinkPreflightWasFree ? { preflightWasFree: true } : void 0
|
|
128361
|
+
);
|
|
128362
|
+
outputs["workspace-link-status"] = "success";
|
|
128363
|
+
dependencies.core.info(
|
|
128364
|
+
`workspace-link-status=success workspace-id=${inputs.workspaceId} repo=${inputs.repoUrl}`
|
|
128365
|
+
);
|
|
128366
|
+
}
|
|
127901
128367
|
} catch (error) {
|
|
127902
128368
|
outputs["workspace-link-status"] = "failed";
|
|
127903
|
-
const
|
|
128369
|
+
const rawMessage = error instanceof Error ? error.message : String(error);
|
|
128370
|
+
const isUnresolvedContract = rawMessage.startsWith(
|
|
128371
|
+
"REPOSITORY_LINK_CONFLICT_UNRESOLVED:"
|
|
128372
|
+
);
|
|
128373
|
+
const message = isUnresolvedContract ? rawMessage : `Workspace link failed: ${rawMessage}`;
|
|
127904
128374
|
if (branchDecision.tier === "canonical") {
|
|
128375
|
+
if (isUnresolvedContract && error instanceof Error) {
|
|
128376
|
+
throw error;
|
|
128377
|
+
}
|
|
127905
128378
|
throw new Error(message, { cause: error });
|
|
127906
128379
|
}
|
|
127907
128380
|
dependencies.core.warning(message);
|
|
@@ -127932,18 +128405,57 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
127932
128405
|
dependencies.core.info(`Tagged spec version at finalize: ${tag.name || tagName}`);
|
|
127933
128406
|
} catch (error) {
|
|
127934
128407
|
const status = error.status;
|
|
128408
|
+
const specEntity = `spec ${inputs.specId} tag "${tagName}" workspace ${inputs.workspaceId}`;
|
|
128409
|
+
const specRemediation = "inspect existing tags/access and rerun";
|
|
127935
128410
|
if (status === 409) {
|
|
127936
|
-
|
|
128411
|
+
let tags = [];
|
|
128412
|
+
let listError;
|
|
128413
|
+
if (dependencies.postman.listSpecVersionTags) {
|
|
128414
|
+
try {
|
|
128415
|
+
tags = await dependencies.postman.listSpecVersionTags(inputs.specId);
|
|
128416
|
+
} catch (lookupError) {
|
|
128417
|
+
listError = lookupError;
|
|
128418
|
+
}
|
|
128419
|
+
}
|
|
127937
128420
|
const latest = tags[0];
|
|
127938
|
-
if (latest && (latest.name === tagName || /\([0-9a-f]{7}\)$/.test(latest.name) || /^[0-9a-f]{7}$/.test(latest.name))) {
|
|
128421
|
+
if (!listError && latest && (latest.name === tagName || /\([0-9a-f]{7}\)$/.test(latest.name) || /^[0-9a-f]{7}$/.test(latest.name))) {
|
|
127939
128422
|
outputs["spec-version-tag"] = latest.name;
|
|
127940
128423
|
outputs["spec-version-url"] = `https://web.postman.co/workspace/${encodeURIComponent(inputs.workspaceId)}/specification/${encodeURIComponent(inputs.specId)}?tagId=${encodeURIComponent(latest.id)}&versionLabel=${encodeURIComponent(latest.name)}`;
|
|
127941
128424
|
dependencies.core.info(`Latest changelog group already tagged as "${latest.name}"; adopting.`);
|
|
128425
|
+
} else if (listError) {
|
|
128426
|
+
dependencies.core.warning(
|
|
128427
|
+
formatOrchestrationIssue({
|
|
128428
|
+
operation: "Spec Hub tagging conflict",
|
|
128429
|
+
entity: specEntity,
|
|
128430
|
+
cause: `create=${causeText(error)}; listSpecVersionTags=${causeText(listError)}`,
|
|
128431
|
+
remediation: specRemediation,
|
|
128432
|
+
mask,
|
|
128433
|
+
detail: "; could not list existing tags to confirm adoption"
|
|
128434
|
+
})
|
|
128435
|
+
);
|
|
127942
128436
|
} else {
|
|
127943
|
-
dependencies.core.warning(
|
|
128437
|
+
dependencies.core.warning(
|
|
128438
|
+
formatOrchestrationIssue({
|
|
128439
|
+
operation: "Spec Hub tagging conflict",
|
|
128440
|
+
entity: specEntity,
|
|
128441
|
+
cause: error,
|
|
128442
|
+
remediation: specRemediation,
|
|
128443
|
+
mask,
|
|
128444
|
+
detail: "; latest changelog group already carries a hand-applied or nonmatching tag; leaving it in place"
|
|
128445
|
+
})
|
|
128446
|
+
);
|
|
127944
128447
|
}
|
|
127945
128448
|
} else {
|
|
127946
|
-
dependencies.core.warning(
|
|
128449
|
+
dependencies.core.warning(
|
|
128450
|
+
formatOrchestrationIssue({
|
|
128451
|
+
operation: "Spec version tagging",
|
|
128452
|
+
entity: specEntity,
|
|
128453
|
+
cause: error,
|
|
128454
|
+
remediation: specRemediation,
|
|
128455
|
+
mask,
|
|
128456
|
+
detail: " (non-fatal)"
|
|
128457
|
+
})
|
|
128458
|
+
);
|
|
127947
128459
|
}
|
|
127948
128460
|
}
|
|
127949
128461
|
}
|
|
@@ -127974,7 +128486,16 @@ async function resolvePostmanApiKeyAndTeamId(inputs, actionCore, actionExec, mas
|
|
|
127974
128486
|
}
|
|
127975
128487
|
} catch (error) {
|
|
127976
128488
|
if (typeof error === "object" && error !== null && "status" in error && (error.status === 401 || error.status === 403)) {
|
|
127977
|
-
|
|
128489
|
+
const status = error.status;
|
|
128490
|
+
actionCore.warning(
|
|
128491
|
+
formatOrchestrationIssue({
|
|
128492
|
+
operation: "PMAK GET /me validation",
|
|
128493
|
+
entity: `status ${status}`,
|
|
128494
|
+
cause: error,
|
|
128495
|
+
remediation: "replace postman-api-key or provide a valid postman-access-token then rerun",
|
|
128496
|
+
mask: masker
|
|
128497
|
+
})
|
|
128498
|
+
);
|
|
127978
128499
|
} else {
|
|
127979
128500
|
throw error;
|
|
127980
128501
|
}
|
|
@@ -127996,6 +128517,7 @@ async function resolvePostmanApiKeyAndTeamId(inputs, actionCore, actionExec, mas
|
|
|
127996
128517
|
const keyName = `repo-sync-action-${Date.now()}`;
|
|
127997
128518
|
apiKey = await internalIntegration.createApiKey(keyName);
|
|
127998
128519
|
actionCore.setSecret(apiKey);
|
|
128520
|
+
const persistSecretRemediation = "grant Actions secrets write permission or set POSTMAN_API_KEY manually then rerun";
|
|
127999
128521
|
if (inputs.provider === "azure-devops") {
|
|
128000
128522
|
if (options.persistGeneratedApiKeySecret ?? true) {
|
|
128001
128523
|
actionCore.warning(
|
|
@@ -128022,16 +128544,48 @@ async function resolvePostmanApiKeyAndTeamId(inputs, actionCore, actionExec, mas
|
|
|
128022
128544
|
ignoreReturnCode: true
|
|
128023
128545
|
});
|
|
128024
128546
|
if (ghCommand.exitCode !== 0) {
|
|
128025
|
-
actionCore.warning(
|
|
128547
|
+
actionCore.warning(
|
|
128548
|
+
formatOrchestrationIssue({
|
|
128549
|
+
operation: "gh secret set POSTMAN_API_KEY",
|
|
128550
|
+
entity: `repository ${repo}`,
|
|
128551
|
+
cause: ghCommand.stderr || `exit code ${ghCommand.exitCode}`,
|
|
128552
|
+
remediation: persistSecretRemediation,
|
|
128553
|
+
mask: masker
|
|
128554
|
+
})
|
|
128555
|
+
);
|
|
128026
128556
|
}
|
|
128027
128557
|
} catch (error) {
|
|
128028
128558
|
actionCore.warning(
|
|
128029
|
-
|
|
128559
|
+
formatOrchestrationIssue({
|
|
128560
|
+
operation: "gh secret set POSTMAN_API_KEY",
|
|
128561
|
+
entity: `repository ${repo}`,
|
|
128562
|
+
cause: error,
|
|
128563
|
+
remediation: persistSecretRemediation,
|
|
128564
|
+
mask: masker
|
|
128565
|
+
})
|
|
128030
128566
|
);
|
|
128031
128567
|
}
|
|
128568
|
+
} else {
|
|
128569
|
+
actionCore.warning(
|
|
128570
|
+
formatOrchestrationIssue({
|
|
128571
|
+
operation: "gh secret set POSTMAN_API_KEY",
|
|
128572
|
+
entity: "repository (missing)",
|
|
128573
|
+
cause: "repository context is empty",
|
|
128574
|
+
remediation: "set repository context or persist POSTMAN_API_KEY manually then rerun",
|
|
128575
|
+
mask: masker
|
|
128576
|
+
})
|
|
128577
|
+
);
|
|
128032
128578
|
}
|
|
128033
128579
|
} else if (options.persistGeneratedApiKeySecret ?? true) {
|
|
128034
|
-
actionCore.warning(
|
|
128580
|
+
actionCore.warning(
|
|
128581
|
+
formatOrchestrationIssue({
|
|
128582
|
+
operation: "gh secret set POSTMAN_API_KEY",
|
|
128583
|
+
entity: inputs.repository ? `repository ${inputs.repository}` : "repository (unknown)",
|
|
128584
|
+
cause: "no GitHub token provided",
|
|
128585
|
+
remediation: "provide github-token/gh-fallback-token or set POSTMAN_API_KEY manually then rerun",
|
|
128586
|
+
mask: masker
|
|
128587
|
+
})
|
|
128588
|
+
);
|
|
128035
128589
|
} else {
|
|
128036
128590
|
actionCore.info("Skipping generated POSTMAN_API_KEY GitHub secret persistence for this run.");
|
|
128037
128591
|
}
|
|
@@ -128070,7 +128624,13 @@ async function resolvePostmanApiKeyAndTeamId(inputs, actionCore, actionExec, mas
|
|
|
128070
128624
|
const isNonOrgSquads = error instanceof HttpError && error.status === 400 && /squad feature is not available/i.test(error.responseBody);
|
|
128071
128625
|
if (!isNonOrgSquads) {
|
|
128072
128626
|
actionCore.warning(
|
|
128073
|
-
|
|
128627
|
+
formatOrchestrationIssue({
|
|
128628
|
+
operation: "Org-mode auto-detection via ums squads",
|
|
128629
|
+
entity: `team ${teamId}`,
|
|
128630
|
+
cause: error,
|
|
128631
|
+
remediation: "set org-mode and team-id explicitly then rerun",
|
|
128632
|
+
mask: masker
|
|
128633
|
+
})
|
|
128074
128634
|
);
|
|
128075
128635
|
}
|
|
128076
128636
|
}
|
|
@@ -128190,7 +128750,8 @@ function createRepoSyncDependencies(inputs, resolved, factories, options = {}) {
|
|
|
128190
128750
|
core: factories.core,
|
|
128191
128751
|
postman,
|
|
128192
128752
|
internalIntegration,
|
|
128193
|
-
repoMutation
|
|
128753
|
+
repoMutation,
|
|
128754
|
+
secretMasker: masker
|
|
128194
128755
|
};
|
|
128195
128756
|
}
|
|
128196
128757
|
function decideBranchTier(inputs, env = process.env) {
|
|
@@ -128624,6 +129185,7 @@ var CLI_INPUT_NAMES = [
|
|
|
128624
129185
|
"gh-fallback-token",
|
|
128625
129186
|
"ci-workflow-base64",
|
|
128626
129187
|
"generate-ci-workflow",
|
|
129188
|
+
"ci-runner-os",
|
|
128627
129189
|
"monitor-type",
|
|
128628
129190
|
"ci-workflow-path",
|
|
128629
129191
|
"org-mode",
|