@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/action.cjs
CHANGED
|
@@ -125116,6 +125116,7 @@ var POSTMAN_ENDPOINT_PROFILES = {
|
|
|
125116
125116
|
bifrostBaseUrl: "https://bifrost-premium-https-v4.gw.postman.com",
|
|
125117
125117
|
fallbackBaseUrl: "https://go.postman.co/_api",
|
|
125118
125118
|
cliInstallUrl: "https://dl-cli.pstmn.io/install/unix.sh",
|
|
125119
|
+
cliWindowsInstallUrl: "https://dl-cli.pstmn.io/install/win64.ps1",
|
|
125119
125120
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
125120
125121
|
},
|
|
125121
125122
|
beta: {
|
|
@@ -125123,6 +125124,7 @@ var POSTMAN_ENDPOINT_PROFILES = {
|
|
|
125123
125124
|
bifrostBaseUrl: "https://bifrost-https-v4.gw.postman-beta.com",
|
|
125124
125125
|
fallbackBaseUrl: "https://go.postman-beta.co/_api",
|
|
125125
125126
|
cliInstallUrl: "https://dl-cli.pstmn-beta.io/install/unix.sh",
|
|
125127
|
+
cliWindowsInstallUrl: "https://dl-cli.pstmn-beta.io/install/win64.ps1",
|
|
125126
125128
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
125127
125129
|
}
|
|
125128
125130
|
};
|
|
@@ -125156,6 +125158,7 @@ function resolvePostmanEndpointProfile(stack, region = "us") {
|
|
|
125156
125158
|
|
|
125157
125159
|
// src/lib/ci-workflow-template.ts
|
|
125158
125160
|
var DEFAULT_POSTMAN_CLI_INSTALL_URL = POSTMAN_ENDPOINT_PROFILES.prod.cliInstallUrl;
|
|
125161
|
+
var DEFAULT_POSTMAN_CLI_WINDOWS_INSTALL_URL = POSTMAN_ENDPOINT_PROFILES.prod.cliWindowsInstallUrl;
|
|
125159
125162
|
function validateHttpsInstallUrl(url) {
|
|
125160
125163
|
const safeUrlPattern = /^https:\/\/[A-Za-z0-9.-]+\/[A-Za-z0-9._~/?=&%-]+$/;
|
|
125161
125164
|
if (!safeUrlPattern.test(url)) {
|
|
@@ -125172,7 +125175,18 @@ function resolvePostmanRegion(postmanRegionOption) {
|
|
|
125172
125175
|
}
|
|
125173
125176
|
return postmanRegion;
|
|
125174
125177
|
}
|
|
125178
|
+
function resolveCiRunnerOs(runnerOsOption) {
|
|
125179
|
+
const runnerOs = String(runnerOsOption || "").trim() || "linux";
|
|
125180
|
+
if (runnerOs === "linux" || runnerOs === "windows") {
|
|
125181
|
+
return runnerOs;
|
|
125182
|
+
}
|
|
125183
|
+
throw new Error("ci-runner-os must be one of: linux, windows; got: " + runnerOs);
|
|
125184
|
+
}
|
|
125175
125185
|
function renderCiWorkflowTemplate(options = {}) {
|
|
125186
|
+
const runnerOs = resolveCiRunnerOs(options.runnerOs);
|
|
125187
|
+
if (runnerOs === "windows") {
|
|
125188
|
+
throw new Error("ci-runner-os=windows is currently supported for azure-devops workflows only");
|
|
125189
|
+
}
|
|
125176
125190
|
const rawUrl = String(options.postmanCliInstallUrl || "").trim() || DEFAULT_POSTMAN_CLI_INSTALL_URL;
|
|
125177
125191
|
const installUrl = validateHttpsInstallUrl(rawUrl);
|
|
125178
125192
|
const postmanRegion = resolvePostmanRegion(options.postmanRegion);
|
|
@@ -125279,6 +125293,132 @@ function buildCiWorkflowLines(installUrl, postmanRegion) {
|
|
|
125279
125293
|
];
|
|
125280
125294
|
}
|
|
125281
125295
|
var CI_WORKFLOW_TEMPLATE = renderCiWorkflowTemplate();
|
|
125296
|
+
function buildAdoWindowsCollectionRunLines(displayName, collectionEnvironmentName) {
|
|
125297
|
+
return [
|
|
125298
|
+
" - pwsh: |",
|
|
125299
|
+
" $ErrorActionPreference = 'Stop'",
|
|
125300
|
+
" function Resolve-AdoOptional([string]$Value) {",
|
|
125301
|
+
" if ($Value -match '^\\$\\([^)]+\\)$') { return '' }",
|
|
125302
|
+
" return $Value",
|
|
125303
|
+
" }",
|
|
125304
|
+
` $collectionUid = $env:${collectionEnvironmentName}`,
|
|
125305
|
+
" $ciEnvironment = Resolve-AdoOptional $env:CI_ENVIRONMENT",
|
|
125306
|
+
" if ([string]::IsNullOrWhiteSpace($ciEnvironment)) { $ciEnvironment = 'Production' }",
|
|
125307
|
+
` $arguments = @('collection', 'run', $collectionUid, '-e', $env:POSTMAN_ENVIRONMENT_UID, '--report-events', '--env-var', "CI_ENVIRONMENT=$ciEnvironment")`,
|
|
125308
|
+
" $sslRoot = Join-Path $env:AGENT_TEMPDIRECTORY 'postman-ssl'",
|
|
125309
|
+
" $clientCert = Join-Path $sslRoot 'client.crt'",
|
|
125310
|
+
" $clientKey = Join-Path $sslRoot 'client.key'",
|
|
125311
|
+
" $caCert = Join-Path $sslRoot 'ca.crt'",
|
|
125312
|
+
" if (Test-Path -LiteralPath $clientCert) {",
|
|
125313
|
+
" $arguments += @('--ssl-client-cert', $clientCert, '--ssl-client-key', $clientKey)",
|
|
125314
|
+
" $passphrase = Resolve-AdoOptional $env:POSTMAN_SSL_CLIENT_PASSPHRASE",
|
|
125315
|
+
" if (-not [string]::IsNullOrWhiteSpace($passphrase)) {",
|
|
125316
|
+
" $arguments += @('--ssl-client-passphrase', $passphrase)",
|
|
125317
|
+
" }",
|
|
125318
|
+
" if (Test-Path -LiteralPath $caCert) {",
|
|
125319
|
+
" $arguments += @('--ssl-extra-ca-certs', $caCert)",
|
|
125320
|
+
" }",
|
|
125321
|
+
" }",
|
|
125322
|
+
" & postman @arguments",
|
|
125323
|
+
` if ($LASTEXITCODE -ne 0) { throw '${displayName} failed with exit code ' + $LASTEXITCODE }`,
|
|
125324
|
+
` displayName: ${displayName}`,
|
|
125325
|
+
" env:",
|
|
125326
|
+
` ${collectionEnvironmentName}: $(${collectionEnvironmentName})`,
|
|
125327
|
+
" POSTMAN_ENVIRONMENT_UID: $(POSTMAN_ENVIRONMENT_UID)",
|
|
125328
|
+
" CI_ENVIRONMENT: $(CI_ENVIRONMENT)",
|
|
125329
|
+
" POSTMAN_SSL_CLIENT_PASSPHRASE: $(POSTMAN_SSL_CLIENT_PASSPHRASE)"
|
|
125330
|
+
];
|
|
125331
|
+
}
|
|
125332
|
+
function buildAdoWindowsCiWorkflowLines(installUrl, postmanRegion) {
|
|
125333
|
+
return [
|
|
125334
|
+
"trigger:",
|
|
125335
|
+
" branches:",
|
|
125336
|
+
" include:",
|
|
125337
|
+
" - main",
|
|
125338
|
+
"schedules:",
|
|
125339
|
+
' - cron: "0 */6 * * *"',
|
|
125340
|
+
" displayName: Scheduled run",
|
|
125341
|
+
" branches:",
|
|
125342
|
+
" include:",
|
|
125343
|
+
" - main",
|
|
125344
|
+
" always: true",
|
|
125345
|
+
"pool:",
|
|
125346
|
+
" vmImage: windows-latest",
|
|
125347
|
+
"steps:",
|
|
125348
|
+
" - checkout: self",
|
|
125349
|
+
" persistCredentials: true",
|
|
125350
|
+
" - pwsh: |",
|
|
125351
|
+
" $ErrorActionPreference = 'Stop'",
|
|
125352
|
+
" if (-not (Get-Command postman -ErrorAction SilentlyContinue)) {",
|
|
125353
|
+
" [System.Net.ServicePointManager]::SecurityProtocol = 3072",
|
|
125354
|
+
" Invoke-Expression ((New-Object System.Net.WebClient).DownloadString($env:POSTMAN_CLI_INSTALL_URL))",
|
|
125355
|
+
" }",
|
|
125356
|
+
" & postman --version",
|
|
125357
|
+
" if ($LASTEXITCODE -ne 0) { throw 'Postman CLI installation failed' }",
|
|
125358
|
+
" displayName: Install Postman CLI",
|
|
125359
|
+
" env:",
|
|
125360
|
+
` POSTMAN_CLI_INSTALL_URL: ${installUrl}`,
|
|
125361
|
+
" - pwsh: |",
|
|
125362
|
+
" $ErrorActionPreference = 'Stop'",
|
|
125363
|
+
" $arguments = @('login', '--with-api-key', $env:POSTMAN_API_KEY)",
|
|
125364
|
+
...postmanRegion === "eu" ? [" $arguments += @('--region', 'eu')"] : [],
|
|
125365
|
+
" & postman @arguments",
|
|
125366
|
+
" if ($LASTEXITCODE -ne 0) { throw 'Postman CLI login failed' }",
|
|
125367
|
+
" displayName: Login to Postman CLI",
|
|
125368
|
+
" env:",
|
|
125369
|
+
" POSTMAN_API_KEY: $(POSTMAN_API_KEY)",
|
|
125370
|
+
" - pwsh: |",
|
|
125371
|
+
" $ErrorActionPreference = 'Stop'",
|
|
125372
|
+
" $section = ''",
|
|
125373
|
+
" $smoke = ''",
|
|
125374
|
+
" $contract = ''",
|
|
125375
|
+
" $environment = ''",
|
|
125376
|
+
" $fallbackEnvironment = ''",
|
|
125377
|
+
" foreach ($line in Get-Content -LiteralPath '.postman/resources.yaml') {",
|
|
125378
|
+
" if ($line -match '^ (collections|environments):\\s*$') { $section = $Matches[1]; continue }",
|
|
125379
|
+
" if ($line -notmatch '^ (.+?):\\s+(.+?)\\s*$') { continue }",
|
|
125380
|
+
` $key = $Matches[1].Trim().Trim("'").Trim('"')`,
|
|
125381
|
+
` $value = $Matches[2].Trim().Trim("'").Trim('"')`,
|
|
125382
|
+
" if ($section -eq 'collections' -and $key -match '\\[Smoke\\]') { $smoke = $value }",
|
|
125383
|
+
" if ($section -eq 'collections' -and $key -match '\\[Contract\\]') { $contract = $value }",
|
|
125384
|
+
" if ($section -eq 'environments') {",
|
|
125385
|
+
" if ([string]::IsNullOrWhiteSpace($fallbackEnvironment)) { $fallbackEnvironment = $value }",
|
|
125386
|
+
" if ($key -match 'prod\\.postman_environment\\.json$') { $environment = $value }",
|
|
125387
|
+
" }",
|
|
125388
|
+
" }",
|
|
125389
|
+
" if ([string]::IsNullOrWhiteSpace($environment)) { $environment = $fallbackEnvironment }",
|
|
125390
|
+
" if ([string]::IsNullOrWhiteSpace($smoke)) { throw 'Missing smoke collection UID in .postman/resources.yaml' }",
|
|
125391
|
+
" if ([string]::IsNullOrWhiteSpace($contract)) { throw 'Missing contract collection UID in .postman/resources.yaml' }",
|
|
125392
|
+
" if ([string]::IsNullOrWhiteSpace($environment)) { throw 'Missing environment UID in .postman/resources.yaml' }",
|
|
125393
|
+
' Write-Host "##vso[task.setvariable variable=POSTMAN_SMOKE_COLLECTION_UID]$smoke"',
|
|
125394
|
+
' Write-Host "##vso[task.setvariable variable=POSTMAN_CONTRACT_COLLECTION_UID]$contract"',
|
|
125395
|
+
' Write-Host "##vso[task.setvariable variable=POSTMAN_ENVIRONMENT_UID]$environment"',
|
|
125396
|
+
" displayName: Resolve Postman Resource IDs",
|
|
125397
|
+
" - pwsh: |",
|
|
125398
|
+
" $ErrorActionPreference = 'Stop'",
|
|
125399
|
+
" function Resolve-AdoOptional([string]$Value) {",
|
|
125400
|
+
" if ($Value -match '^\\$\\([^)]+\\)$') { return '' }",
|
|
125401
|
+
" return $Value",
|
|
125402
|
+
" }",
|
|
125403
|
+
" $sslRoot = Join-Path $env:AGENT_TEMPDIRECTORY 'postman-ssl'",
|
|
125404
|
+
" New-Item -ItemType Directory -Path $sslRoot -Force | Out-Null",
|
|
125405
|
+
" [IO.File]::WriteAllBytes((Join-Path $sslRoot 'client.crt'), [Convert]::FromBase64String($env:POSTMAN_SSL_CLIENT_CERT_B64))",
|
|
125406
|
+
" [IO.File]::WriteAllBytes((Join-Path $sslRoot 'client.key'), [Convert]::FromBase64String($env:POSTMAN_SSL_CLIENT_KEY_B64))",
|
|
125407
|
+
" $extraCa = Resolve-AdoOptional $env:POSTMAN_SSL_EXTRA_CA_CERTS_B64",
|
|
125408
|
+
" if (-not [string]::IsNullOrWhiteSpace($extraCa)) {",
|
|
125409
|
+
" [IO.File]::WriteAllBytes((Join-Path $sslRoot 'ca.crt'), [Convert]::FromBase64String($extraCa))",
|
|
125410
|
+
" }",
|
|
125411
|
+
" condition: ne(variables['POSTMAN_SSL_CLIENT_CERT_B64'], '')",
|
|
125412
|
+
" displayName: Decode SSL certificates",
|
|
125413
|
+
" env:",
|
|
125414
|
+
" POSTMAN_SSL_CLIENT_CERT_B64: $(POSTMAN_SSL_CLIENT_CERT_B64)",
|
|
125415
|
+
" POSTMAN_SSL_CLIENT_KEY_B64: $(POSTMAN_SSL_CLIENT_KEY_B64)",
|
|
125416
|
+
" POSTMAN_SSL_EXTRA_CA_CERTS_B64: $(POSTMAN_SSL_EXTRA_CA_CERTS_B64)",
|
|
125417
|
+
...buildAdoWindowsCollectionRunLines("Run Smoke Tests", "POSTMAN_SMOKE_COLLECTION_UID"),
|
|
125418
|
+
...buildAdoWindowsCollectionRunLines("Run Contract Tests", "POSTMAN_CONTRACT_COLLECTION_UID"),
|
|
125419
|
+
""
|
|
125420
|
+
];
|
|
125421
|
+
}
|
|
125282
125422
|
function buildAdoCiWorkflowLines(installUrl, postmanRegion) {
|
|
125283
125423
|
return [
|
|
125284
125424
|
"trigger:",
|
|
@@ -125458,10 +125598,12 @@ function renderGcWorkflowTemplate() {
|
|
|
125458
125598
|
}
|
|
125459
125599
|
var GC_WORKFLOW_TEMPLATE = renderGcWorkflowTemplate();
|
|
125460
125600
|
function getCiWorkflowTemplate(provider, options = {}) {
|
|
125601
|
+
const runnerOs = resolveCiRunnerOs(options.runnerOs);
|
|
125461
125602
|
if (provider === "azure-devops") {
|
|
125462
|
-
const rawUrl = String(options.postmanCliInstallUrl || "").trim() || DEFAULT_POSTMAN_CLI_INSTALL_URL;
|
|
125603
|
+
const rawUrl = runnerOs === "windows" ? String(options.postmanCliWindowsInstallUrl || "").trim() || DEFAULT_POSTMAN_CLI_WINDOWS_INSTALL_URL : String(options.postmanCliInstallUrl || "").trim() || DEFAULT_POSTMAN_CLI_INSTALL_URL;
|
|
125463
125604
|
const postmanRegion = resolvePostmanRegion(options.postmanRegion);
|
|
125464
|
-
|
|
125605
|
+
const installUrl = validateHttpsInstallUrl(rawUrl);
|
|
125606
|
+
return (runnerOs === "windows" ? buildAdoWindowsCiWorkflowLines(installUrl, postmanRegion) : buildAdoCiWorkflowLines(installUrl, postmanRegion)).join("\n");
|
|
125465
125607
|
}
|
|
125466
125608
|
return renderCiWorkflowTemplate(options);
|
|
125467
125609
|
}
|
|
@@ -126856,6 +126998,17 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
126856
126998
|
mask: this.secretMasker
|
|
126857
126999
|
};
|
|
126858
127000
|
}
|
|
127001
|
+
/**
|
|
127002
|
+
* One-line non-fatal preflight reason: operation + entity (repo/path) + cause +
|
|
127003
|
+
* operator action. Secrets are redacted via secretMasker, then CR/LF and other
|
|
127004
|
+
* line-breaking whitespace are collapsed to spaces so CI logs stay one line.
|
|
127005
|
+
* Display-only: does not alter request repoUrl/path or probe classification.
|
|
127006
|
+
*/
|
|
127007
|
+
unknownFilesystemLookupReason(repoUrl, fsPath, cause) {
|
|
127008
|
+
return this.secretMasker(
|
|
127009
|
+
`filesystem lookup for repository ${repoUrl} path ${fsPath} ${cause}; verify Bifrost connectivity/credentials then rerun`
|
|
127010
|
+
).replace(/[\r\n\v\f\u2028\u2029]+/g, " ");
|
|
127011
|
+
}
|
|
126859
127012
|
async associateSystemEnvironments(workspaceId, associations) {
|
|
126860
127013
|
if (associations.length === 0) {
|
|
126861
127014
|
return;
|
|
@@ -126895,7 +127048,106 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
126895
127048
|
throw advised ?? httpErr;
|
|
126896
127049
|
}
|
|
126897
127050
|
}
|
|
126898
|
-
|
|
127051
|
+
/**
|
|
127052
|
+
* Probe who (if anyone) already owns the global `(repo, path)` filesystem
|
|
127053
|
+
* link. Non-fatal: unexpected statuses / network errors yield `unknown` so
|
|
127054
|
+
* callers can proceed and rely on reactive POST conflict handling.
|
|
127055
|
+
*
|
|
127056
|
+
* Bifrost states (FileSystemController.fetchWorkspaceForFileSystem):
|
|
127057
|
+
* - 200 + data null -> free
|
|
127058
|
+
* - 200 + data -> linked-visible (workspace payload)
|
|
127059
|
+
* - 403 + error.meta.workspaceId -> linked-invisible
|
|
127060
|
+
* - 200 + error.meta.workspaceId -> linked-invisible (proxy envelope)
|
|
127061
|
+
*/
|
|
127062
|
+
async findWorkspaceForRepo(repoUrl, path9 = "/") {
|
|
127063
|
+
const fsPath = path9 && path9.trim() ? path9.trim() : "/";
|
|
127064
|
+
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
127065
|
+
const payload = {
|
|
127066
|
+
service: "workspaces",
|
|
127067
|
+
method: "GET",
|
|
127068
|
+
path: `/workspaces/filesystem?repo=${encodeURIComponent(repoUrl)}&path=${encodeURIComponent(fsPath)}`
|
|
127069
|
+
};
|
|
127070
|
+
try {
|
|
127071
|
+
const response = await this.fetchImpl(url, {
|
|
127072
|
+
method: "POST",
|
|
127073
|
+
headers: this.bifrostHeaders(),
|
|
127074
|
+
body: JSON.stringify(payload)
|
|
127075
|
+
});
|
|
127076
|
+
let parsed = {};
|
|
127077
|
+
try {
|
|
127078
|
+
parsed = await response.json();
|
|
127079
|
+
} catch {
|
|
127080
|
+
return {
|
|
127081
|
+
state: "unknown",
|
|
127082
|
+
reason: this.unknownFilesystemLookupReason(
|
|
127083
|
+
repoUrl,
|
|
127084
|
+
fsPath,
|
|
127085
|
+
`returned non-JSON body (HTTP ${response.status})`
|
|
127086
|
+
)
|
|
127087
|
+
};
|
|
127088
|
+
}
|
|
127089
|
+
const errorMetaWorkspaceId = typeof parsed?.error?.meta?.workspaceId === "string" && parsed.error.meta.workspaceId.trim() ? parsed.error.meta.workspaceId.trim() : void 0;
|
|
127090
|
+
if (errorMetaWorkspaceId) {
|
|
127091
|
+
return { state: "linked-invisible", workspaceId: errorMetaWorkspaceId };
|
|
127092
|
+
}
|
|
127093
|
+
if (response.ok) {
|
|
127094
|
+
if (parsed?.data == null) {
|
|
127095
|
+
return { state: "free" };
|
|
127096
|
+
}
|
|
127097
|
+
const id = typeof parsed.data.id === "string" ? parsed.data.id.trim() : "";
|
|
127098
|
+
if (!id) {
|
|
127099
|
+
return {
|
|
127100
|
+
state: "unknown",
|
|
127101
|
+
reason: this.unknownFilesystemLookupReason(
|
|
127102
|
+
repoUrl,
|
|
127103
|
+
fsPath,
|
|
127104
|
+
"returned 200 without a workspace id"
|
|
127105
|
+
)
|
|
127106
|
+
};
|
|
127107
|
+
}
|
|
127108
|
+
const name = typeof parsed.data.name === "string" && parsed.data.name.trim() ? parsed.data.name.trim() : void 0;
|
|
127109
|
+
return {
|
|
127110
|
+
state: "linked-visible",
|
|
127111
|
+
workspace: name ? { id, name } : { id }
|
|
127112
|
+
};
|
|
127113
|
+
}
|
|
127114
|
+
if (response.status === 403) {
|
|
127115
|
+
const workspaceId = extractDuplicateWorkspaceId(
|
|
127116
|
+
JSON.stringify(parsed)
|
|
127117
|
+
);
|
|
127118
|
+
if (workspaceId) {
|
|
127119
|
+
return { state: "linked-invisible", workspaceId };
|
|
127120
|
+
}
|
|
127121
|
+
return {
|
|
127122
|
+
state: "unknown",
|
|
127123
|
+
reason: this.unknownFilesystemLookupReason(
|
|
127124
|
+
repoUrl,
|
|
127125
|
+
fsPath,
|
|
127126
|
+
"returned 403 without error.meta.workspaceId"
|
|
127127
|
+
)
|
|
127128
|
+
};
|
|
127129
|
+
}
|
|
127130
|
+
return {
|
|
127131
|
+
state: "unknown",
|
|
127132
|
+
reason: this.unknownFilesystemLookupReason(
|
|
127133
|
+
repoUrl,
|
|
127134
|
+
fsPath,
|
|
127135
|
+
`returned HTTP ${response.status}`
|
|
127136
|
+
)
|
|
127137
|
+
};
|
|
127138
|
+
} catch (error2) {
|
|
127139
|
+
const cause = error2 instanceof Error ? error2.message : String(error2);
|
|
127140
|
+
return {
|
|
127141
|
+
state: "unknown",
|
|
127142
|
+
reason: this.unknownFilesystemLookupReason(
|
|
127143
|
+
repoUrl,
|
|
127144
|
+
fsPath,
|
|
127145
|
+
`failed: ${cause}`
|
|
127146
|
+
)
|
|
127147
|
+
};
|
|
127148
|
+
}
|
|
127149
|
+
}
|
|
127150
|
+
async connectWorkspaceToRepository(workspaceId, repoUrl, options) {
|
|
126899
127151
|
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
126900
127152
|
const payload = {
|
|
126901
127153
|
service: "workspaces",
|
|
@@ -126922,6 +127174,11 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
126922
127174
|
if (isDuplicate) {
|
|
126923
127175
|
const existingWorkspaceId = extractDuplicateWorkspaceId(body);
|
|
126924
127176
|
if (existingWorkspaceId && existingWorkspaceId !== workspaceId) {
|
|
127177
|
+
if (options?.preflightWasFree) {
|
|
127178
|
+
throw new Error(
|
|
127179
|
+
`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.`
|
|
127180
|
+
);
|
|
127181
|
+
}
|
|
126925
127182
|
throw new Error(
|
|
126926
127183
|
await this.describeWorkspaceLinkConflict(existingWorkspaceId, workspaceId, repoUrl)
|
|
126927
127184
|
);
|
|
@@ -127100,6 +127357,12 @@ var postmanRepoSyncActionContract = {
|
|
|
127100
127357
|
required: false,
|
|
127101
127358
|
default: ".github/workflows/ci.yml"
|
|
127102
127359
|
},
|
|
127360
|
+
"ci-runner-os": {
|
|
127361
|
+
description: "Runner operating system for the generated CI workflow.",
|
|
127362
|
+
required: false,
|
|
127363
|
+
default: "linux",
|
|
127364
|
+
allowedValues: ["linux", "windows"]
|
|
127365
|
+
},
|
|
127103
127366
|
"project-name": {
|
|
127104
127367
|
description: "Service project name used for environment, mock, and monitor naming.",
|
|
127105
127368
|
required: true
|
|
@@ -128811,6 +129074,25 @@ function parseAssetMarker(description) {
|
|
|
128811
129074
|
}
|
|
128812
129075
|
|
|
128813
129076
|
// src/index.ts
|
|
129077
|
+
var identitySecretMasker = (input) => input;
|
|
129078
|
+
function resolveRepoSyncMasker(dependencies) {
|
|
129079
|
+
return dependencies.secretMasker ?? identitySecretMasker;
|
|
129080
|
+
}
|
|
129081
|
+
function causeText(cause) {
|
|
129082
|
+
return cause instanceof Error ? cause.message : String(cause);
|
|
129083
|
+
}
|
|
129084
|
+
function toOneLineDisplay(value) {
|
|
129085
|
+
return String(value ?? "").replace(/[\r\n\u0085\u2028\u2029\v\f]+/g, " ").replace(/[ \t]{2,}/g, " ").trim();
|
|
129086
|
+
}
|
|
129087
|
+
function formatOrchestrationIssue(params) {
|
|
129088
|
+
const operation = toOneLineDisplay(params.mask(params.operation));
|
|
129089
|
+
const entity = toOneLineDisplay(params.mask(params.entity));
|
|
129090
|
+
const maskedCause = toOneLineDisplay(params.mask(causeText(params.cause)));
|
|
129091
|
+
const detail = toOneLineDisplay(params.mask(params.detail ?? ""));
|
|
129092
|
+
const remediation = toOneLineDisplay(params.mask(params.remediation));
|
|
129093
|
+
const body = `${operation} failed for ${entity}: ${maskedCause}${detail}`.replace(/[.]+$/u, "");
|
|
129094
|
+
return toOneLineDisplay(`${body}. ${remediation}`);
|
|
129095
|
+
}
|
|
128814
129096
|
function parseBooleanInput(value, defaultValue) {
|
|
128815
129097
|
const normalized = String(value || "").trim().toLowerCase();
|
|
128816
129098
|
if (!normalized) return defaultValue;
|
|
@@ -128910,6 +129192,17 @@ function parseBranchStrategy(value) {
|
|
|
128910
129192
|
`Unsupported branch-strategy "${normalized}". Supported values: ${allowed.join(", ")}`
|
|
128911
129193
|
);
|
|
128912
129194
|
}
|
|
129195
|
+
function parseCiRunnerOs(value) {
|
|
129196
|
+
const definition = postmanRepoSyncActionContract.inputs["ci-runner-os"];
|
|
129197
|
+
const allowed = definition.allowedValues ?? [];
|
|
129198
|
+
const normalized = String(value || "").trim() || (definition.default ?? "linux");
|
|
129199
|
+
if (allowed.includes(normalized)) {
|
|
129200
|
+
return normalized;
|
|
129201
|
+
}
|
|
129202
|
+
throw new Error(
|
|
129203
|
+
`Unsupported ci-runner-os "${normalized}". Supported values: ${allowed.join(", ")}`
|
|
129204
|
+
);
|
|
129205
|
+
}
|
|
128913
129206
|
function normalizeReleaseLabel(value) {
|
|
128914
129207
|
const cleaned = normalizeInputValue(value).replace(/^refs\/heads\//, "").replace(/^refs\/tags\//, "").replace(/\s+/g, "-").replace(/[^A-Za-z0-9._-]/g, "-").replace(/-+/g, "-").replace(/^[._-]+|[._-]+$/g, "");
|
|
128915
129208
|
return cleaned;
|
|
@@ -128987,6 +129280,7 @@ function resolveInputs(env = process.env) {
|
|
|
128987
129280
|
provider: repoContext.provider,
|
|
128988
129281
|
ciWorkflowBase64: getInput2("ci-workflow-base64", env),
|
|
128989
129282
|
generateCiWorkflow: parseBooleanInput(getInput2("generate-ci-workflow", env), true),
|
|
129283
|
+
ciRunnerOs: parseCiRunnerOs(getInput2("ci-runner-os", env)),
|
|
128990
129284
|
monitorType: getInput2("monitor-type", env) || "cloud",
|
|
128991
129285
|
ciWorkflowPath: getInput2("ci-workflow-path", env) || (repoContext.provider === "azure-devops" ? "azure-pipelines.yml" : ".github/workflows/ci.yml"),
|
|
128992
129286
|
orgMode: parseBooleanInput(getInput2("org-mode", env), false),
|
|
@@ -129005,6 +129299,7 @@ function resolveInputs(env = process.env) {
|
|
|
129005
129299
|
postmanBifrostBase: endpointProfile.bifrostBaseUrl,
|
|
129006
129300
|
postmanFallbackBase: endpointProfile.fallbackBaseUrl,
|
|
129007
129301
|
postmanCliInstallUrl: endpointProfile.cliInstallUrl,
|
|
129302
|
+
postmanCliWindowsInstallUrl: endpointProfile.cliWindowsInstallUrl,
|
|
129008
129303
|
postmanIapubBase: endpointProfile.iapubBaseUrl
|
|
129009
129304
|
};
|
|
129010
129305
|
}
|
|
@@ -129274,6 +129569,7 @@ function readActionInputs(actionCore) {
|
|
|
129274
129569
|
INPUT_GH_FALLBACK_TOKEN: ghFallbackToken,
|
|
129275
129570
|
INPUT_CI_WORKFLOW_BASE64: readInput(actionCore, "ci-workflow-base64"),
|
|
129276
129571
|
INPUT_GENERATE_CI_WORKFLOW: readInput(actionCore, "generate-ci-workflow"),
|
|
129572
|
+
INPUT_CI_RUNNER_OS: readInput(actionCore, "ci-runner-os"),
|
|
129277
129573
|
INPUT_MONITOR_TYPE: readInput(actionCore, "monitor-type") || "cloud",
|
|
129278
129574
|
INPUT_CI_WORKFLOW_PATH: readInput(actionCore, "ci-workflow-path"),
|
|
129279
129575
|
INPUT_ORG_MODE: readInput(actionCore, "org-mode"),
|
|
@@ -129391,19 +129687,34 @@ async function upsertEnvironments(inputs, dependencies, resourcesState, assetMar
|
|
|
129391
129687
|
if (!inputs.workspaceId) {
|
|
129392
129688
|
return envUids;
|
|
129393
129689
|
}
|
|
129690
|
+
const mask = resolveRepoSyncMasker(dependencies);
|
|
129691
|
+
const envRemediation = "verify access-token/team/workspace permissions then rerun";
|
|
129394
129692
|
for (const envName of inputs.environments) {
|
|
129395
129693
|
const runtimeUrl = String(inputs.envRuntimeUrls[envName] || "").trim();
|
|
129396
129694
|
const displayName = `${inputs.projectName} - ${envName}`;
|
|
129397
129695
|
let existingUid = String(envUids[envName] || "").trim();
|
|
129398
129696
|
if (!existingUid) {
|
|
129399
|
-
|
|
129400
|
-
|
|
129401
|
-
|
|
129402
|
-
|
|
129403
|
-
|
|
129404
|
-
|
|
129405
|
-
|
|
129406
|
-
|
|
129697
|
+
try {
|
|
129698
|
+
const discovered = await dependencies.postman.findEnvironmentByName(
|
|
129699
|
+
inputs.workspaceId,
|
|
129700
|
+
displayName
|
|
129701
|
+
);
|
|
129702
|
+
if (discovered?.uid) {
|
|
129703
|
+
existingUid = discovered.uid;
|
|
129704
|
+
dependencies.core.info(
|
|
129705
|
+
`Discovered existing environment for ${displayName}: ${existingUid}`
|
|
129706
|
+
);
|
|
129707
|
+
}
|
|
129708
|
+
} catch (error2) {
|
|
129709
|
+
throw new Error(
|
|
129710
|
+
formatOrchestrationIssue({
|
|
129711
|
+
operation: "Environment discovery",
|
|
129712
|
+
entity: `workspace ${inputs.workspaceId} environment "${displayName}"`,
|
|
129713
|
+
cause: error2,
|
|
129714
|
+
remediation: envRemediation,
|
|
129715
|
+
mask
|
|
129716
|
+
}),
|
|
129717
|
+
{ cause: error2 }
|
|
129407
129718
|
);
|
|
129408
129719
|
}
|
|
129409
129720
|
}
|
|
@@ -129423,17 +129734,43 @@ async function upsertEnvironments(inputs, dependencies, resourcesState, assetMar
|
|
|
129423
129734
|
}
|
|
129424
129735
|
const values2 = buildEnvironmentValues(envName, runtimeUrl);
|
|
129425
129736
|
if (marker) values2.push({ key: "x-pm-onboarding", value: JSON.stringify(marker), type: "default" });
|
|
129426
|
-
|
|
129737
|
+
try {
|
|
129738
|
+
await dependencies.postman.updateEnvironment(existingUid, displayName, values2);
|
|
129739
|
+
} catch (error2) {
|
|
129740
|
+
throw new Error(
|
|
129741
|
+
formatOrchestrationIssue({
|
|
129742
|
+
operation: "Environment update",
|
|
129743
|
+
entity: `workspace ${inputs.workspaceId} environment "${displayName}" (uid ${existingUid})`,
|
|
129744
|
+
cause: error2,
|
|
129745
|
+
remediation: envRemediation,
|
|
129746
|
+
mask
|
|
129747
|
+
}),
|
|
129748
|
+
{ cause: error2 }
|
|
129749
|
+
);
|
|
129750
|
+
}
|
|
129427
129751
|
envUids[envName] = existingUid;
|
|
129428
129752
|
continue;
|
|
129429
129753
|
}
|
|
129430
129754
|
const values = buildEnvironmentValues(envName, runtimeUrl);
|
|
129431
129755
|
if (assetMarker) values.push({ key: "x-pm-onboarding", value: JSON.stringify(assetMarker), type: "default" });
|
|
129432
|
-
|
|
129433
|
-
|
|
129434
|
-
|
|
129435
|
-
|
|
129436
|
-
|
|
129756
|
+
try {
|
|
129757
|
+
envUids[envName] = await dependencies.postman.createEnvironment(
|
|
129758
|
+
inputs.workspaceId,
|
|
129759
|
+
displayName,
|
|
129760
|
+
values
|
|
129761
|
+
);
|
|
129762
|
+
} catch (error2) {
|
|
129763
|
+
throw new Error(
|
|
129764
|
+
formatOrchestrationIssue({
|
|
129765
|
+
operation: "Environment create",
|
|
129766
|
+
entity: `workspace ${inputs.workspaceId} environment "${displayName}"`,
|
|
129767
|
+
cause: error2,
|
|
129768
|
+
remediation: envRemediation,
|
|
129769
|
+
mask
|
|
129770
|
+
}),
|
|
129771
|
+
{ cause: error2 }
|
|
129772
|
+
);
|
|
129773
|
+
}
|
|
129437
129774
|
}
|
|
129438
129775
|
return envUids;
|
|
129439
129776
|
}
|
|
@@ -129690,11 +130027,15 @@ function renderCiWorkflow(inputs) {
|
|
|
129690
130027
|
if (inputs.provider === "azure-devops") {
|
|
129691
130028
|
return getCiWorkflowTemplate(inputs.provider, {
|
|
129692
130029
|
postmanCliInstallUrl: inputs.postmanCliInstallUrl,
|
|
130030
|
+
postmanCliWindowsInstallUrl: inputs.postmanCliWindowsInstallUrl,
|
|
130031
|
+
runnerOs: inputs.ciRunnerOs,
|
|
129693
130032
|
postmanRegion: inputs.postmanRegion
|
|
129694
130033
|
});
|
|
129695
130034
|
}
|
|
129696
130035
|
return renderCiWorkflowTemplate({
|
|
129697
130036
|
postmanCliInstallUrl: inputs.postmanCliInstallUrl,
|
|
130037
|
+
postmanCliWindowsInstallUrl: inputs.postmanCliWindowsInstallUrl,
|
|
130038
|
+
runnerOs: inputs.ciRunnerOs,
|
|
129698
130039
|
postmanRegion: inputs.postmanRegion
|
|
129699
130040
|
});
|
|
129700
130041
|
}
|
|
@@ -129789,6 +130130,7 @@ async function runRepoSync(inputs, dependencies) {
|
|
|
129789
130130
|
}
|
|
129790
130131
|
}
|
|
129791
130132
|
async function runRepoSyncInner(inputs, dependencies) {
|
|
130133
|
+
const mask = resolveRepoSyncMasker(dependencies);
|
|
129792
130134
|
const branchDecision = decideBranchTier(inputs);
|
|
129793
130135
|
assertBranchAssetIds(inputs, branchDecision);
|
|
129794
130136
|
const isCanonicalWriter = branchDecision.tier === "legacy" || branchDecision.tier === "canonical";
|
|
@@ -129848,6 +130190,39 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
129848
130190
|
}
|
|
129849
130191
|
}
|
|
129850
130192
|
}
|
|
130193
|
+
let skipRepositoryLinkPost = false;
|
|
130194
|
+
let repositoryLinkPreflightWasFree = false;
|
|
130195
|
+
if (inputs.workspaceLinkEnabled && inputs.workspaceId && inputs.repoUrl && dependencies.internalIntegration?.findWorkspaceForRepo) {
|
|
130196
|
+
const probe = await dependencies.internalIntegration.findWorkspaceForRepo(
|
|
130197
|
+
inputs.repoUrl,
|
|
130198
|
+
"/"
|
|
130199
|
+
);
|
|
130200
|
+
if (probe.state === "linked-visible") {
|
|
130201
|
+
if (probe.workspace.id === inputs.workspaceId) {
|
|
130202
|
+
skipRepositoryLinkPost = true;
|
|
130203
|
+
dependencies.core.info(
|
|
130204
|
+
`REPOSITORY_LINK_ALREADY_TARGET: Repository ${inputs.repoUrl} at path / is already linked to target workspace ${inputs.workspaceId}; continuing.`
|
|
130205
|
+
);
|
|
130206
|
+
} else {
|
|
130207
|
+
const ownerName = probe.workspace.name?.trim() || "unknown";
|
|
130208
|
+
throw new Error(
|
|
130209
|
+
`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.`
|
|
130210
|
+
);
|
|
130211
|
+
}
|
|
130212
|
+
} else if (probe.state === "linked-invisible") {
|
|
130213
|
+
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.`;
|
|
130214
|
+
if (inputs.orgMode) {
|
|
130215
|
+
message += " Verify workspace-team-id; if the owner is in another sub-team, ask that sub-team's admin to disconnect it.";
|
|
130216
|
+
}
|
|
130217
|
+
throw new Error(message);
|
|
130218
|
+
} else if (probe.state === "free") {
|
|
130219
|
+
repositoryLinkPreflightWasFree = true;
|
|
130220
|
+
} else {
|
|
130221
|
+
dependencies.core.warning(
|
|
130222
|
+
`REPOSITORY_LINK_PREFLIGHT_UNKNOWN: Unable to determine the existing repository link (${probe.reason}); continuing and relying on link creation conflict handling.`
|
|
130223
|
+
);
|
|
130224
|
+
}
|
|
130225
|
+
}
|
|
129851
130226
|
const branchAssetMarker = buildBranchAssetMarker(branchDecision, inputs);
|
|
129852
130227
|
const envUids = await upsertEnvironments(inputs, dependencies, resourcesState, branchAssetMarker);
|
|
129853
130228
|
outputs["environment-uids-json"] = JSON.stringify(envUids);
|
|
@@ -129865,8 +130240,15 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
129865
130240
|
outputs["environment-sync-status"] = "success";
|
|
129866
130241
|
} catch (error2) {
|
|
129867
130242
|
outputs["environment-sync-status"] = "failed";
|
|
130243
|
+
const associationSummary = associations.map((entry) => `${entry.envUid}->${entry.systemEnvId}`).join(", ");
|
|
129868
130244
|
dependencies.core.warning(
|
|
129869
|
-
|
|
130245
|
+
formatOrchestrationIssue({
|
|
130246
|
+
operation: "System environment association",
|
|
130247
|
+
entity: `workspace ${inputs.workspaceId} (${associationSummary})`,
|
|
130248
|
+
cause: error2,
|
|
130249
|
+
remediation: "verify access-token/team/system-env mapping then rerun",
|
|
130250
|
+
mask
|
|
130251
|
+
})
|
|
129870
130252
|
);
|
|
129871
130253
|
}
|
|
129872
130254
|
} else if (Object.keys(envUids).length > 0) {
|
|
@@ -129894,37 +130276,72 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
129894
130276
|
dependencies.core.info(`Reusing mock from explicit input: ${resolvedMockUrl}`);
|
|
129895
130277
|
}
|
|
129896
130278
|
if (!resolvedMockUrl && inputs.baselineCollectionId) {
|
|
129897
|
-
|
|
129898
|
-
|
|
129899
|
-
|
|
129900
|
-
|
|
129901
|
-
|
|
129902
|
-
|
|
129903
|
-
|
|
129904
|
-
|
|
130279
|
+
try {
|
|
130280
|
+
const discovered = await dependencies.postman.findMockByCollection(
|
|
130281
|
+
inputs.baselineCollectionId,
|
|
130282
|
+
mockEnvUid,
|
|
130283
|
+
mockName
|
|
130284
|
+
);
|
|
130285
|
+
if (discovered) {
|
|
130286
|
+
resolvedMockUrl = discovered.mockUrl;
|
|
130287
|
+
dependencies.core.info(`Discovered existing mock for collection ${inputs.baselineCollectionId}: ${resolvedMockUrl}`);
|
|
130288
|
+
}
|
|
130289
|
+
} catch (error2) {
|
|
130290
|
+
throw new Error(
|
|
130291
|
+
formatOrchestrationIssue({
|
|
130292
|
+
operation: "Mock discovery",
|
|
130293
|
+
entity: `mock "${mockName}" workspace ${inputs.workspaceId} collection ${inputs.baselineCollectionId} environment ${mockEnvUid}`,
|
|
130294
|
+
cause: error2,
|
|
130295
|
+
remediation: "verify collection/environment access then rerun",
|
|
130296
|
+
mask
|
|
130297
|
+
}),
|
|
130298
|
+
{ cause: error2 }
|
|
130299
|
+
);
|
|
129905
130300
|
}
|
|
129906
130301
|
}
|
|
129907
130302
|
if (!resolvedMockUrl) {
|
|
129908
|
-
const
|
|
129909
|
-
|
|
129910
|
-
|
|
129911
|
-
|
|
129912
|
-
|
|
129913
|
-
|
|
129914
|
-
|
|
129915
|
-
|
|
129916
|
-
|
|
129917
|
-
|
|
129918
|
-
|
|
129919
|
-
|
|
129920
|
-
|
|
129921
|
-
|
|
129922
|
-
)
|
|
130303
|
+
const mockEntity = `mock "${mockName}" workspace ${inputs.workspaceId} collection ${inputs.baselineCollectionId} environment ${mockEnvUid}`;
|
|
130304
|
+
const mockRemediation = "verify collection/environment access then rerun";
|
|
130305
|
+
try {
|
|
130306
|
+
const mock = await retry(
|
|
130307
|
+
() => dependencies.postman.createMock(
|
|
130308
|
+
inputs.workspaceId,
|
|
130309
|
+
mockName,
|
|
130310
|
+
inputs.baselineCollectionId,
|
|
130311
|
+
mockEnvUid
|
|
130312
|
+
),
|
|
130313
|
+
{
|
|
130314
|
+
maxAttempts: 3,
|
|
130315
|
+
delayMs: 2e3,
|
|
130316
|
+
backoffMultiplier: 2,
|
|
130317
|
+
onRetry: ({ attempt, maxAttempts, error: error2 }) => {
|
|
130318
|
+
dependencies.core.warning(
|
|
130319
|
+
formatOrchestrationIssue({
|
|
130320
|
+
operation: `Mock create attempt ${attempt}/${maxAttempts}`,
|
|
130321
|
+
entity: mockEntity,
|
|
130322
|
+
cause: error2,
|
|
130323
|
+
remediation: mockRemediation,
|
|
130324
|
+
mask,
|
|
130325
|
+
detail: "; retrying"
|
|
130326
|
+
})
|
|
130327
|
+
);
|
|
130328
|
+
}
|
|
129923
130329
|
}
|
|
129924
|
-
|
|
129925
|
-
|
|
129926
|
-
|
|
129927
|
-
|
|
130330
|
+
);
|
|
130331
|
+
resolvedMockUrl = mock.url;
|
|
130332
|
+
dependencies.core.info(`Created new mock: ${resolvedMockUrl}`);
|
|
130333
|
+
} catch (error2) {
|
|
130334
|
+
throw new Error(
|
|
130335
|
+
formatOrchestrationIssue({
|
|
130336
|
+
operation: "Mock create",
|
|
130337
|
+
entity: mockEntity,
|
|
130338
|
+
cause: error2,
|
|
130339
|
+
remediation: mockRemediation,
|
|
130340
|
+
mask
|
|
130341
|
+
}),
|
|
130342
|
+
{ cause: error2 }
|
|
130343
|
+
);
|
|
130344
|
+
}
|
|
129928
130345
|
}
|
|
129929
130346
|
outputs["mock-url"] = resolvedMockUrl;
|
|
129930
130347
|
}
|
|
@@ -129935,35 +130352,71 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
129935
130352
|
if (monitorEnvUid && inputs.monitorType !== "cli") {
|
|
129936
130353
|
let resolvedMonitorId = "";
|
|
129937
130354
|
const monitorName = `${assetProjectName} - Smoke Monitor`;
|
|
130355
|
+
const monitorRemediation = "verify monitor IDs/access or set monitor-cron then rerun";
|
|
129938
130356
|
if (inputs.monitorId) {
|
|
129939
130357
|
const valid = await dependencies.postman.monitorExists(inputs.monitorId);
|
|
129940
130358
|
if (valid) {
|
|
129941
130359
|
resolvedMonitorId = inputs.monitorId;
|
|
129942
130360
|
dependencies.core.info(`Reusing monitor from explicit input: ${resolvedMonitorId}`);
|
|
129943
130361
|
} else {
|
|
129944
|
-
dependencies.core.warning(
|
|
130362
|
+
dependencies.core.warning(
|
|
130363
|
+
formatOrchestrationIssue({
|
|
130364
|
+
operation: "Explicit monitor-id lookup",
|
|
130365
|
+
entity: `monitor-id ${inputs.monitorId} workspace ${inputs.workspaceId} collection ${inputs.smokeCollectionId} environment ${monitorEnvUid}`,
|
|
130366
|
+
cause: "not found in Postman",
|
|
130367
|
+
remediation: monitorRemediation,
|
|
130368
|
+
mask,
|
|
130369
|
+
detail: "; falling through to discovery"
|
|
130370
|
+
})
|
|
130371
|
+
);
|
|
129945
130372
|
}
|
|
129946
130373
|
}
|
|
129947
130374
|
if (!resolvedMonitorId && inputs.smokeCollectionId) {
|
|
129948
|
-
|
|
129949
|
-
|
|
129950
|
-
|
|
129951
|
-
|
|
129952
|
-
|
|
129953
|
-
|
|
129954
|
-
|
|
129955
|
-
|
|
130375
|
+
try {
|
|
130376
|
+
const discovered = await dependencies.postman.findMonitorByCollection(
|
|
130377
|
+
inputs.smokeCollectionId,
|
|
130378
|
+
monitorEnvUid,
|
|
130379
|
+
monitorName
|
|
130380
|
+
);
|
|
130381
|
+
if (discovered) {
|
|
130382
|
+
resolvedMonitorId = discovered.uid;
|
|
130383
|
+
dependencies.core.info(`Discovered existing monitor for collection ${inputs.smokeCollectionId}: ${resolvedMonitorId}`);
|
|
130384
|
+
}
|
|
130385
|
+
} catch (error2) {
|
|
130386
|
+
throw new Error(
|
|
130387
|
+
formatOrchestrationIssue({
|
|
130388
|
+
operation: "Monitor discovery",
|
|
130389
|
+
entity: `monitor "${monitorName}" workspace ${inputs.workspaceId} collection ${inputs.smokeCollectionId} environment ${monitorEnvUid}`,
|
|
130390
|
+
cause: error2,
|
|
130391
|
+
remediation: monitorRemediation,
|
|
130392
|
+
mask
|
|
130393
|
+
}),
|
|
130394
|
+
{ cause: error2 }
|
|
130395
|
+
);
|
|
129956
130396
|
}
|
|
129957
130397
|
}
|
|
129958
130398
|
if (!resolvedMonitorId) {
|
|
129959
|
-
|
|
129960
|
-
|
|
129961
|
-
|
|
129962
|
-
|
|
129963
|
-
|
|
129964
|
-
|
|
129965
|
-
|
|
129966
|
-
|
|
130399
|
+
try {
|
|
130400
|
+
resolvedMonitorId = await dependencies.postman.createMonitor(
|
|
130401
|
+
inputs.workspaceId,
|
|
130402
|
+
monitorName,
|
|
130403
|
+
inputs.smokeCollectionId,
|
|
130404
|
+
monitorEnvUid,
|
|
130405
|
+
effectiveCron || void 0
|
|
130406
|
+
);
|
|
130407
|
+
dependencies.core.info(`Created new monitor: ${resolvedMonitorId}${effectiveCron ? "" : " (disabled \u2014 no cron configured; will trigger a one-time run)"}`);
|
|
130408
|
+
} catch (error2) {
|
|
130409
|
+
throw new Error(
|
|
130410
|
+
formatOrchestrationIssue({
|
|
130411
|
+
operation: "Monitor create",
|
|
130412
|
+
entity: `monitor "${monitorName}" workspace ${inputs.workspaceId} collection ${inputs.smokeCollectionId} environment ${monitorEnvUid}`,
|
|
130413
|
+
cause: error2,
|
|
130414
|
+
remediation: monitorRemediation,
|
|
130415
|
+
mask
|
|
130416
|
+
}),
|
|
130417
|
+
{ cause: error2 }
|
|
130418
|
+
);
|
|
130419
|
+
}
|
|
129967
130420
|
}
|
|
129968
130421
|
outputs["monitor-id"] = resolvedMonitorId;
|
|
129969
130422
|
if (!effectiveCron && resolvedMonitorId) {
|
|
@@ -129972,7 +130425,13 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
129972
130425
|
dependencies.core.info(`Triggered one-time run for monitor: ${resolvedMonitorId}`);
|
|
129973
130426
|
} catch (error2) {
|
|
129974
130427
|
dependencies.core.warning(
|
|
129975
|
-
|
|
130428
|
+
formatOrchestrationIssue({
|
|
130429
|
+
operation: "Monitor one-time run",
|
|
130430
|
+
entity: `monitor ${resolvedMonitorId} name "${monitorName}" workspace ${inputs.workspaceId} collection ${inputs.smokeCollectionId} environment ${monitorEnvUid}`,
|
|
130431
|
+
cause: error2,
|
|
130432
|
+
remediation: monitorRemediation,
|
|
130433
|
+
mask
|
|
130434
|
+
})
|
|
129976
130435
|
);
|
|
129977
130436
|
}
|
|
129978
130437
|
}
|
|
@@ -129980,18 +130439,33 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
129980
130439
|
}
|
|
129981
130440
|
if (inputs.workspaceLinkEnabled && inputs.workspaceId && inputs.repoUrl && dependencies.internalIntegration) {
|
|
129982
130441
|
try {
|
|
129983
|
-
|
|
129984
|
-
|
|
129985
|
-
|
|
129986
|
-
|
|
129987
|
-
|
|
129988
|
-
|
|
129989
|
-
|
|
129990
|
-
|
|
130442
|
+
if (skipRepositoryLinkPost) {
|
|
130443
|
+
outputs["workspace-link-status"] = "success";
|
|
130444
|
+
dependencies.core.info(
|
|
130445
|
+
`workspace-link-status=success workspace-id=${inputs.workspaceId} repo=${inputs.repoUrl} (preflight already-target; link POST skipped)`
|
|
130446
|
+
);
|
|
130447
|
+
} else {
|
|
130448
|
+
await dependencies.internalIntegration.connectWorkspaceToRepository(
|
|
130449
|
+
inputs.workspaceId,
|
|
130450
|
+
inputs.repoUrl,
|
|
130451
|
+
repositoryLinkPreflightWasFree ? { preflightWasFree: true } : void 0
|
|
130452
|
+
);
|
|
130453
|
+
outputs["workspace-link-status"] = "success";
|
|
130454
|
+
dependencies.core.info(
|
|
130455
|
+
`workspace-link-status=success workspace-id=${inputs.workspaceId} repo=${inputs.repoUrl}`
|
|
130456
|
+
);
|
|
130457
|
+
}
|
|
129991
130458
|
} catch (error2) {
|
|
129992
130459
|
outputs["workspace-link-status"] = "failed";
|
|
129993
|
-
const
|
|
130460
|
+
const rawMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
130461
|
+
const isUnresolvedContract = rawMessage.startsWith(
|
|
130462
|
+
"REPOSITORY_LINK_CONFLICT_UNRESOLVED:"
|
|
130463
|
+
);
|
|
130464
|
+
const message = isUnresolvedContract ? rawMessage : `Workspace link failed: ${rawMessage}`;
|
|
129994
130465
|
if (branchDecision.tier === "canonical") {
|
|
130466
|
+
if (isUnresolvedContract && error2 instanceof Error) {
|
|
130467
|
+
throw error2;
|
|
130468
|
+
}
|
|
129995
130469
|
throw new Error(message, { cause: error2 });
|
|
129996
130470
|
}
|
|
129997
130471
|
dependencies.core.warning(message);
|
|
@@ -130022,18 +130496,57 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
130022
130496
|
dependencies.core.info(`Tagged spec version at finalize: ${tag.name || tagName}`);
|
|
130023
130497
|
} catch (error2) {
|
|
130024
130498
|
const status = error2.status;
|
|
130499
|
+
const specEntity = `spec ${inputs.specId} tag "${tagName}" workspace ${inputs.workspaceId}`;
|
|
130500
|
+
const specRemediation = "inspect existing tags/access and rerun";
|
|
130025
130501
|
if (status === 409) {
|
|
130026
|
-
|
|
130502
|
+
let tags = [];
|
|
130503
|
+
let listError;
|
|
130504
|
+
if (dependencies.postman.listSpecVersionTags) {
|
|
130505
|
+
try {
|
|
130506
|
+
tags = await dependencies.postman.listSpecVersionTags(inputs.specId);
|
|
130507
|
+
} catch (lookupError) {
|
|
130508
|
+
listError = lookupError;
|
|
130509
|
+
}
|
|
130510
|
+
}
|
|
130027
130511
|
const latest = tags[0];
|
|
130028
|
-
if (latest && (latest.name === tagName || /\([0-9a-f]{7}\)$/.test(latest.name) || /^[0-9a-f]{7}$/.test(latest.name))) {
|
|
130512
|
+
if (!listError && latest && (latest.name === tagName || /\([0-9a-f]{7}\)$/.test(latest.name) || /^[0-9a-f]{7}$/.test(latest.name))) {
|
|
130029
130513
|
outputs["spec-version-tag"] = latest.name;
|
|
130030
130514
|
outputs["spec-version-url"] = `https://web.postman.co/workspace/${encodeURIComponent(inputs.workspaceId)}/specification/${encodeURIComponent(inputs.specId)}?tagId=${encodeURIComponent(latest.id)}&versionLabel=${encodeURIComponent(latest.name)}`;
|
|
130031
130515
|
dependencies.core.info(`Latest changelog group already tagged as "${latest.name}"; adopting.`);
|
|
130516
|
+
} else if (listError) {
|
|
130517
|
+
dependencies.core.warning(
|
|
130518
|
+
formatOrchestrationIssue({
|
|
130519
|
+
operation: "Spec Hub tagging conflict",
|
|
130520
|
+
entity: specEntity,
|
|
130521
|
+
cause: `create=${causeText(error2)}; listSpecVersionTags=${causeText(listError)}`,
|
|
130522
|
+
remediation: specRemediation,
|
|
130523
|
+
mask,
|
|
130524
|
+
detail: "; could not list existing tags to confirm adoption"
|
|
130525
|
+
})
|
|
130526
|
+
);
|
|
130032
130527
|
} else {
|
|
130033
|
-
dependencies.core.warning(
|
|
130528
|
+
dependencies.core.warning(
|
|
130529
|
+
formatOrchestrationIssue({
|
|
130530
|
+
operation: "Spec Hub tagging conflict",
|
|
130531
|
+
entity: specEntity,
|
|
130532
|
+
cause: error2,
|
|
130533
|
+
remediation: specRemediation,
|
|
130534
|
+
mask,
|
|
130535
|
+
detail: "; latest changelog group already carries a hand-applied or nonmatching tag; leaving it in place"
|
|
130536
|
+
})
|
|
130537
|
+
);
|
|
130034
130538
|
}
|
|
130035
130539
|
} else {
|
|
130036
|
-
dependencies.core.warning(
|
|
130540
|
+
dependencies.core.warning(
|
|
130541
|
+
formatOrchestrationIssue({
|
|
130542
|
+
operation: "Spec version tagging",
|
|
130543
|
+
entity: specEntity,
|
|
130544
|
+
cause: error2,
|
|
130545
|
+
remediation: specRemediation,
|
|
130546
|
+
mask,
|
|
130547
|
+
detail: " (non-fatal)"
|
|
130548
|
+
})
|
|
130549
|
+
);
|
|
130037
130550
|
}
|
|
130038
130551
|
}
|
|
130039
130552
|
}
|
|
@@ -130064,7 +130577,16 @@ async function resolvePostmanApiKeyAndTeamId(inputs, actionCore, actionExec, mas
|
|
|
130064
130577
|
}
|
|
130065
130578
|
} catch (error2) {
|
|
130066
130579
|
if (typeof error2 === "object" && error2 !== null && "status" in error2 && (error2.status === 401 || error2.status === 403)) {
|
|
130067
|
-
|
|
130580
|
+
const status = error2.status;
|
|
130581
|
+
actionCore.warning(
|
|
130582
|
+
formatOrchestrationIssue({
|
|
130583
|
+
operation: "PMAK GET /me validation",
|
|
130584
|
+
entity: `status ${status}`,
|
|
130585
|
+
cause: error2,
|
|
130586
|
+
remediation: "replace postman-api-key or provide a valid postman-access-token then rerun",
|
|
130587
|
+
mask: masker
|
|
130588
|
+
})
|
|
130589
|
+
);
|
|
130068
130590
|
} else {
|
|
130069
130591
|
throw error2;
|
|
130070
130592
|
}
|
|
@@ -130086,6 +130608,7 @@ async function resolvePostmanApiKeyAndTeamId(inputs, actionCore, actionExec, mas
|
|
|
130086
130608
|
const keyName = `repo-sync-action-${Date.now()}`;
|
|
130087
130609
|
apiKey = await internalIntegration.createApiKey(keyName);
|
|
130088
130610
|
actionCore.setSecret(apiKey);
|
|
130611
|
+
const persistSecretRemediation = "grant Actions secrets write permission or set POSTMAN_API_KEY manually then rerun";
|
|
130089
130612
|
if (inputs.provider === "azure-devops") {
|
|
130090
130613
|
if (options.persistGeneratedApiKeySecret ?? true) {
|
|
130091
130614
|
actionCore.warning(
|
|
@@ -130112,16 +130635,48 @@ async function resolvePostmanApiKeyAndTeamId(inputs, actionCore, actionExec, mas
|
|
|
130112
130635
|
ignoreReturnCode: true
|
|
130113
130636
|
});
|
|
130114
130637
|
if (ghCommand.exitCode !== 0) {
|
|
130115
|
-
actionCore.warning(
|
|
130638
|
+
actionCore.warning(
|
|
130639
|
+
formatOrchestrationIssue({
|
|
130640
|
+
operation: "gh secret set POSTMAN_API_KEY",
|
|
130641
|
+
entity: `repository ${repo}`,
|
|
130642
|
+
cause: ghCommand.stderr || `exit code ${ghCommand.exitCode}`,
|
|
130643
|
+
remediation: persistSecretRemediation,
|
|
130644
|
+
mask: masker
|
|
130645
|
+
})
|
|
130646
|
+
);
|
|
130116
130647
|
}
|
|
130117
130648
|
} catch (error2) {
|
|
130118
130649
|
actionCore.warning(
|
|
130119
|
-
|
|
130650
|
+
formatOrchestrationIssue({
|
|
130651
|
+
operation: "gh secret set POSTMAN_API_KEY",
|
|
130652
|
+
entity: `repository ${repo}`,
|
|
130653
|
+
cause: error2,
|
|
130654
|
+
remediation: persistSecretRemediation,
|
|
130655
|
+
mask: masker
|
|
130656
|
+
})
|
|
130120
130657
|
);
|
|
130121
130658
|
}
|
|
130659
|
+
} else {
|
|
130660
|
+
actionCore.warning(
|
|
130661
|
+
formatOrchestrationIssue({
|
|
130662
|
+
operation: "gh secret set POSTMAN_API_KEY",
|
|
130663
|
+
entity: "repository (missing)",
|
|
130664
|
+
cause: "repository context is empty",
|
|
130665
|
+
remediation: "set repository context or persist POSTMAN_API_KEY manually then rerun",
|
|
130666
|
+
mask: masker
|
|
130667
|
+
})
|
|
130668
|
+
);
|
|
130122
130669
|
}
|
|
130123
130670
|
} else if (options.persistGeneratedApiKeySecret ?? true) {
|
|
130124
|
-
actionCore.warning(
|
|
130671
|
+
actionCore.warning(
|
|
130672
|
+
formatOrchestrationIssue({
|
|
130673
|
+
operation: "gh secret set POSTMAN_API_KEY",
|
|
130674
|
+
entity: inputs.repository ? `repository ${inputs.repository}` : "repository (unknown)",
|
|
130675
|
+
cause: "no GitHub token provided",
|
|
130676
|
+
remediation: "provide github-token/gh-fallback-token or set POSTMAN_API_KEY manually then rerun",
|
|
130677
|
+
mask: masker
|
|
130678
|
+
})
|
|
130679
|
+
);
|
|
130125
130680
|
} else {
|
|
130126
130681
|
actionCore.info("Skipping generated POSTMAN_API_KEY GitHub secret persistence for this run.");
|
|
130127
130682
|
}
|
|
@@ -130160,7 +130715,13 @@ async function resolvePostmanApiKeyAndTeamId(inputs, actionCore, actionExec, mas
|
|
|
130160
130715
|
const isNonOrgSquads = error2 instanceof HttpError && error2.status === 400 && /squad feature is not available/i.test(error2.responseBody);
|
|
130161
130716
|
if (!isNonOrgSquads) {
|
|
130162
130717
|
actionCore.warning(
|
|
130163
|
-
|
|
130718
|
+
formatOrchestrationIssue({
|
|
130719
|
+
operation: "Org-mode auto-detection via ums squads",
|
|
130720
|
+
entity: `team ${teamId}`,
|
|
130721
|
+
cause: error2,
|
|
130722
|
+
remediation: "set org-mode and team-id explicitly then rerun",
|
|
130723
|
+
mask: masker
|
|
130724
|
+
})
|
|
130164
130725
|
);
|
|
130165
130726
|
}
|
|
130166
130727
|
}
|
|
@@ -130280,7 +130841,8 @@ function createRepoSyncDependencies(inputs, resolved, factories, options = {}) {
|
|
|
130280
130841
|
core: factories.core,
|
|
130281
130842
|
postman,
|
|
130282
130843
|
internalIntegration,
|
|
130283
|
-
repoMutation
|
|
130844
|
+
repoMutation,
|
|
130845
|
+
secretMasker: masker
|
|
130284
130846
|
};
|
|
130285
130847
|
}
|
|
130286
130848
|
function decideBranchTier(inputs, env = process.env) {
|