@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/index.cjs
CHANGED
|
@@ -125136,6 +125136,7 @@ var POSTMAN_ENDPOINT_PROFILES = {
|
|
|
125136
125136
|
bifrostBaseUrl: "https://bifrost-premium-https-v4.gw.postman.com",
|
|
125137
125137
|
fallbackBaseUrl: "https://go.postman.co/_api",
|
|
125138
125138
|
cliInstallUrl: "https://dl-cli.pstmn.io/install/unix.sh",
|
|
125139
|
+
cliWindowsInstallUrl: "https://dl-cli.pstmn.io/install/win64.ps1",
|
|
125139
125140
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
125140
125141
|
},
|
|
125141
125142
|
beta: {
|
|
@@ -125143,6 +125144,7 @@ var POSTMAN_ENDPOINT_PROFILES = {
|
|
|
125143
125144
|
bifrostBaseUrl: "https://bifrost-https-v4.gw.postman-beta.com",
|
|
125144
125145
|
fallbackBaseUrl: "https://go.postman-beta.co/_api",
|
|
125145
125146
|
cliInstallUrl: "https://dl-cli.pstmn-beta.io/install/unix.sh",
|
|
125147
|
+
cliWindowsInstallUrl: "https://dl-cli.pstmn-beta.io/install/win64.ps1",
|
|
125146
125148
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
125147
125149
|
}
|
|
125148
125150
|
};
|
|
@@ -125176,6 +125178,7 @@ function resolvePostmanEndpointProfile(stack, region = "us") {
|
|
|
125176
125178
|
|
|
125177
125179
|
// src/lib/ci-workflow-template.ts
|
|
125178
125180
|
var DEFAULT_POSTMAN_CLI_INSTALL_URL = POSTMAN_ENDPOINT_PROFILES.prod.cliInstallUrl;
|
|
125181
|
+
var DEFAULT_POSTMAN_CLI_WINDOWS_INSTALL_URL = POSTMAN_ENDPOINT_PROFILES.prod.cliWindowsInstallUrl;
|
|
125179
125182
|
function validateHttpsInstallUrl(url) {
|
|
125180
125183
|
const safeUrlPattern = /^https:\/\/[A-Za-z0-9.-]+\/[A-Za-z0-9._~/?=&%-]+$/;
|
|
125181
125184
|
if (!safeUrlPattern.test(url)) {
|
|
@@ -125192,7 +125195,18 @@ function resolvePostmanRegion(postmanRegionOption) {
|
|
|
125192
125195
|
}
|
|
125193
125196
|
return postmanRegion;
|
|
125194
125197
|
}
|
|
125198
|
+
function resolveCiRunnerOs(runnerOsOption) {
|
|
125199
|
+
const runnerOs = String(runnerOsOption || "").trim() || "linux";
|
|
125200
|
+
if (runnerOs === "linux" || runnerOs === "windows") {
|
|
125201
|
+
return runnerOs;
|
|
125202
|
+
}
|
|
125203
|
+
throw new Error("ci-runner-os must be one of: linux, windows; got: " + runnerOs);
|
|
125204
|
+
}
|
|
125195
125205
|
function renderCiWorkflowTemplate(options = {}) {
|
|
125206
|
+
const runnerOs = resolveCiRunnerOs(options.runnerOs);
|
|
125207
|
+
if (runnerOs === "windows") {
|
|
125208
|
+
throw new Error("ci-runner-os=windows is currently supported for azure-devops workflows only");
|
|
125209
|
+
}
|
|
125196
125210
|
const rawUrl = String(options.postmanCliInstallUrl || "").trim() || DEFAULT_POSTMAN_CLI_INSTALL_URL;
|
|
125197
125211
|
const installUrl = validateHttpsInstallUrl(rawUrl);
|
|
125198
125212
|
const postmanRegion = resolvePostmanRegion(options.postmanRegion);
|
|
@@ -125299,6 +125313,132 @@ function buildCiWorkflowLines(installUrl, postmanRegion) {
|
|
|
125299
125313
|
];
|
|
125300
125314
|
}
|
|
125301
125315
|
var CI_WORKFLOW_TEMPLATE = renderCiWorkflowTemplate();
|
|
125316
|
+
function buildAdoWindowsCollectionRunLines(displayName, collectionEnvironmentName) {
|
|
125317
|
+
return [
|
|
125318
|
+
" - pwsh: |",
|
|
125319
|
+
" $ErrorActionPreference = 'Stop'",
|
|
125320
|
+
" function Resolve-AdoOptional([string]$Value) {",
|
|
125321
|
+
" if ($Value -match '^\\$\\([^)]+\\)$') { return '' }",
|
|
125322
|
+
" return $Value",
|
|
125323
|
+
" }",
|
|
125324
|
+
` $collectionUid = $env:${collectionEnvironmentName}`,
|
|
125325
|
+
" $ciEnvironment = Resolve-AdoOptional $env:CI_ENVIRONMENT",
|
|
125326
|
+
" if ([string]::IsNullOrWhiteSpace($ciEnvironment)) { $ciEnvironment = 'Production' }",
|
|
125327
|
+
` $arguments = @('collection', 'run', $collectionUid, '-e', $env:POSTMAN_ENVIRONMENT_UID, '--report-events', '--env-var', "CI_ENVIRONMENT=$ciEnvironment")`,
|
|
125328
|
+
" $sslRoot = Join-Path $env:AGENT_TEMPDIRECTORY 'postman-ssl'",
|
|
125329
|
+
" $clientCert = Join-Path $sslRoot 'client.crt'",
|
|
125330
|
+
" $clientKey = Join-Path $sslRoot 'client.key'",
|
|
125331
|
+
" $caCert = Join-Path $sslRoot 'ca.crt'",
|
|
125332
|
+
" if (Test-Path -LiteralPath $clientCert) {",
|
|
125333
|
+
" $arguments += @('--ssl-client-cert', $clientCert, '--ssl-client-key', $clientKey)",
|
|
125334
|
+
" $passphrase = Resolve-AdoOptional $env:POSTMAN_SSL_CLIENT_PASSPHRASE",
|
|
125335
|
+
" if (-not [string]::IsNullOrWhiteSpace($passphrase)) {",
|
|
125336
|
+
" $arguments += @('--ssl-client-passphrase', $passphrase)",
|
|
125337
|
+
" }",
|
|
125338
|
+
" if (Test-Path -LiteralPath $caCert) {",
|
|
125339
|
+
" $arguments += @('--ssl-extra-ca-certs', $caCert)",
|
|
125340
|
+
" }",
|
|
125341
|
+
" }",
|
|
125342
|
+
" & postman @arguments",
|
|
125343
|
+
` if ($LASTEXITCODE -ne 0) { throw '${displayName} failed with exit code ' + $LASTEXITCODE }`,
|
|
125344
|
+
` displayName: ${displayName}`,
|
|
125345
|
+
" env:",
|
|
125346
|
+
` ${collectionEnvironmentName}: $(${collectionEnvironmentName})`,
|
|
125347
|
+
" POSTMAN_ENVIRONMENT_UID: $(POSTMAN_ENVIRONMENT_UID)",
|
|
125348
|
+
" CI_ENVIRONMENT: $(CI_ENVIRONMENT)",
|
|
125349
|
+
" POSTMAN_SSL_CLIENT_PASSPHRASE: $(POSTMAN_SSL_CLIENT_PASSPHRASE)"
|
|
125350
|
+
];
|
|
125351
|
+
}
|
|
125352
|
+
function buildAdoWindowsCiWorkflowLines(installUrl, postmanRegion) {
|
|
125353
|
+
return [
|
|
125354
|
+
"trigger:",
|
|
125355
|
+
" branches:",
|
|
125356
|
+
" include:",
|
|
125357
|
+
" - main",
|
|
125358
|
+
"schedules:",
|
|
125359
|
+
' - cron: "0 */6 * * *"',
|
|
125360
|
+
" displayName: Scheduled run",
|
|
125361
|
+
" branches:",
|
|
125362
|
+
" include:",
|
|
125363
|
+
" - main",
|
|
125364
|
+
" always: true",
|
|
125365
|
+
"pool:",
|
|
125366
|
+
" vmImage: windows-latest",
|
|
125367
|
+
"steps:",
|
|
125368
|
+
" - checkout: self",
|
|
125369
|
+
" persistCredentials: true",
|
|
125370
|
+
" - pwsh: |",
|
|
125371
|
+
" $ErrorActionPreference = 'Stop'",
|
|
125372
|
+
" if (-not (Get-Command postman -ErrorAction SilentlyContinue)) {",
|
|
125373
|
+
" [System.Net.ServicePointManager]::SecurityProtocol = 3072",
|
|
125374
|
+
" Invoke-Expression ((New-Object System.Net.WebClient).DownloadString($env:POSTMAN_CLI_INSTALL_URL))",
|
|
125375
|
+
" }",
|
|
125376
|
+
" & postman --version",
|
|
125377
|
+
" if ($LASTEXITCODE -ne 0) { throw 'Postman CLI installation failed' }",
|
|
125378
|
+
" displayName: Install Postman CLI",
|
|
125379
|
+
" env:",
|
|
125380
|
+
` POSTMAN_CLI_INSTALL_URL: ${installUrl}`,
|
|
125381
|
+
" - pwsh: |",
|
|
125382
|
+
" $ErrorActionPreference = 'Stop'",
|
|
125383
|
+
" $arguments = @('login', '--with-api-key', $env:POSTMAN_API_KEY)",
|
|
125384
|
+
...postmanRegion === "eu" ? [" $arguments += @('--region', 'eu')"] : [],
|
|
125385
|
+
" & postman @arguments",
|
|
125386
|
+
" if ($LASTEXITCODE -ne 0) { throw 'Postman CLI login failed' }",
|
|
125387
|
+
" displayName: Login to Postman CLI",
|
|
125388
|
+
" env:",
|
|
125389
|
+
" POSTMAN_API_KEY: $(POSTMAN_API_KEY)",
|
|
125390
|
+
" - pwsh: |",
|
|
125391
|
+
" $ErrorActionPreference = 'Stop'",
|
|
125392
|
+
" $section = ''",
|
|
125393
|
+
" $smoke = ''",
|
|
125394
|
+
" $contract = ''",
|
|
125395
|
+
" $environment = ''",
|
|
125396
|
+
" $fallbackEnvironment = ''",
|
|
125397
|
+
" foreach ($line in Get-Content -LiteralPath '.postman/resources.yaml') {",
|
|
125398
|
+
" if ($line -match '^ (collections|environments):\\s*$') { $section = $Matches[1]; continue }",
|
|
125399
|
+
" if ($line -notmatch '^ (.+?):\\s+(.+?)\\s*$') { continue }",
|
|
125400
|
+
` $key = $Matches[1].Trim().Trim("'").Trim('"')`,
|
|
125401
|
+
` $value = $Matches[2].Trim().Trim("'").Trim('"')`,
|
|
125402
|
+
" if ($section -eq 'collections' -and $key -match '\\[Smoke\\]') { $smoke = $value }",
|
|
125403
|
+
" if ($section -eq 'collections' -and $key -match '\\[Contract\\]') { $contract = $value }",
|
|
125404
|
+
" if ($section -eq 'environments') {",
|
|
125405
|
+
" if ([string]::IsNullOrWhiteSpace($fallbackEnvironment)) { $fallbackEnvironment = $value }",
|
|
125406
|
+
" if ($key -match 'prod\\.postman_environment\\.json$') { $environment = $value }",
|
|
125407
|
+
" }",
|
|
125408
|
+
" }",
|
|
125409
|
+
" if ([string]::IsNullOrWhiteSpace($environment)) { $environment = $fallbackEnvironment }",
|
|
125410
|
+
" if ([string]::IsNullOrWhiteSpace($smoke)) { throw 'Missing smoke collection UID in .postman/resources.yaml' }",
|
|
125411
|
+
" if ([string]::IsNullOrWhiteSpace($contract)) { throw 'Missing contract collection UID in .postman/resources.yaml' }",
|
|
125412
|
+
" if ([string]::IsNullOrWhiteSpace($environment)) { throw 'Missing environment UID in .postman/resources.yaml' }",
|
|
125413
|
+
' Write-Host "##vso[task.setvariable variable=POSTMAN_SMOKE_COLLECTION_UID]$smoke"',
|
|
125414
|
+
' Write-Host "##vso[task.setvariable variable=POSTMAN_CONTRACT_COLLECTION_UID]$contract"',
|
|
125415
|
+
' Write-Host "##vso[task.setvariable variable=POSTMAN_ENVIRONMENT_UID]$environment"',
|
|
125416
|
+
" displayName: Resolve Postman Resource IDs",
|
|
125417
|
+
" - pwsh: |",
|
|
125418
|
+
" $ErrorActionPreference = 'Stop'",
|
|
125419
|
+
" function Resolve-AdoOptional([string]$Value) {",
|
|
125420
|
+
" if ($Value -match '^\\$\\([^)]+\\)$') { return '' }",
|
|
125421
|
+
" return $Value",
|
|
125422
|
+
" }",
|
|
125423
|
+
" $sslRoot = Join-Path $env:AGENT_TEMPDIRECTORY 'postman-ssl'",
|
|
125424
|
+
" New-Item -ItemType Directory -Path $sslRoot -Force | Out-Null",
|
|
125425
|
+
" [IO.File]::WriteAllBytes((Join-Path $sslRoot 'client.crt'), [Convert]::FromBase64String($env:POSTMAN_SSL_CLIENT_CERT_B64))",
|
|
125426
|
+
" [IO.File]::WriteAllBytes((Join-Path $sslRoot 'client.key'), [Convert]::FromBase64String($env:POSTMAN_SSL_CLIENT_KEY_B64))",
|
|
125427
|
+
" $extraCa = Resolve-AdoOptional $env:POSTMAN_SSL_EXTRA_CA_CERTS_B64",
|
|
125428
|
+
" if (-not [string]::IsNullOrWhiteSpace($extraCa)) {",
|
|
125429
|
+
" [IO.File]::WriteAllBytes((Join-Path $sslRoot 'ca.crt'), [Convert]::FromBase64String($extraCa))",
|
|
125430
|
+
" }",
|
|
125431
|
+
" condition: ne(variables['POSTMAN_SSL_CLIENT_CERT_B64'], '')",
|
|
125432
|
+
" displayName: Decode SSL certificates",
|
|
125433
|
+
" env:",
|
|
125434
|
+
" POSTMAN_SSL_CLIENT_CERT_B64: $(POSTMAN_SSL_CLIENT_CERT_B64)",
|
|
125435
|
+
" POSTMAN_SSL_CLIENT_KEY_B64: $(POSTMAN_SSL_CLIENT_KEY_B64)",
|
|
125436
|
+
" POSTMAN_SSL_EXTRA_CA_CERTS_B64: $(POSTMAN_SSL_EXTRA_CA_CERTS_B64)",
|
|
125437
|
+
...buildAdoWindowsCollectionRunLines("Run Smoke Tests", "POSTMAN_SMOKE_COLLECTION_UID"),
|
|
125438
|
+
...buildAdoWindowsCollectionRunLines("Run Contract Tests", "POSTMAN_CONTRACT_COLLECTION_UID"),
|
|
125439
|
+
""
|
|
125440
|
+
];
|
|
125441
|
+
}
|
|
125302
125442
|
function buildAdoCiWorkflowLines(installUrl, postmanRegion) {
|
|
125303
125443
|
return [
|
|
125304
125444
|
"trigger:",
|
|
@@ -125478,10 +125618,12 @@ function renderGcWorkflowTemplate() {
|
|
|
125478
125618
|
}
|
|
125479
125619
|
var GC_WORKFLOW_TEMPLATE = renderGcWorkflowTemplate();
|
|
125480
125620
|
function getCiWorkflowTemplate(provider, options = {}) {
|
|
125621
|
+
const runnerOs = resolveCiRunnerOs(options.runnerOs);
|
|
125481
125622
|
if (provider === "azure-devops") {
|
|
125482
|
-
const rawUrl = String(options.postmanCliInstallUrl || "").trim() || DEFAULT_POSTMAN_CLI_INSTALL_URL;
|
|
125623
|
+
const rawUrl = runnerOs === "windows" ? String(options.postmanCliWindowsInstallUrl || "").trim() || DEFAULT_POSTMAN_CLI_WINDOWS_INSTALL_URL : String(options.postmanCliInstallUrl || "").trim() || DEFAULT_POSTMAN_CLI_INSTALL_URL;
|
|
125483
125624
|
const postmanRegion = resolvePostmanRegion(options.postmanRegion);
|
|
125484
|
-
|
|
125625
|
+
const installUrl = validateHttpsInstallUrl(rawUrl);
|
|
125626
|
+
return (runnerOs === "windows" ? buildAdoWindowsCiWorkflowLines(installUrl, postmanRegion) : buildAdoCiWorkflowLines(installUrl, postmanRegion)).join("\n");
|
|
125485
125627
|
}
|
|
125486
125628
|
return renderCiWorkflowTemplate(options);
|
|
125487
125629
|
}
|
|
@@ -126876,6 +127018,17 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
126876
127018
|
mask: this.secretMasker
|
|
126877
127019
|
};
|
|
126878
127020
|
}
|
|
127021
|
+
/**
|
|
127022
|
+
* One-line non-fatal preflight reason: operation + entity (repo/path) + cause +
|
|
127023
|
+
* operator action. Secrets are redacted via secretMasker, then CR/LF and other
|
|
127024
|
+
* line-breaking whitespace are collapsed to spaces so CI logs stay one line.
|
|
127025
|
+
* Display-only: does not alter request repoUrl/path or probe classification.
|
|
127026
|
+
*/
|
|
127027
|
+
unknownFilesystemLookupReason(repoUrl, fsPath, cause) {
|
|
127028
|
+
return this.secretMasker(
|
|
127029
|
+
`filesystem lookup for repository ${repoUrl} path ${fsPath} ${cause}; verify Bifrost connectivity/credentials then rerun`
|
|
127030
|
+
).replace(/[\r\n\v\f\u2028\u2029]+/g, " ");
|
|
127031
|
+
}
|
|
126879
127032
|
async associateSystemEnvironments(workspaceId, associations) {
|
|
126880
127033
|
if (associations.length === 0) {
|
|
126881
127034
|
return;
|
|
@@ -126915,7 +127068,106 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
126915
127068
|
throw advised ?? httpErr;
|
|
126916
127069
|
}
|
|
126917
127070
|
}
|
|
126918
|
-
|
|
127071
|
+
/**
|
|
127072
|
+
* Probe who (if anyone) already owns the global `(repo, path)` filesystem
|
|
127073
|
+
* link. Non-fatal: unexpected statuses / network errors yield `unknown` so
|
|
127074
|
+
* callers can proceed and rely on reactive POST conflict handling.
|
|
127075
|
+
*
|
|
127076
|
+
* Bifrost states (FileSystemController.fetchWorkspaceForFileSystem):
|
|
127077
|
+
* - 200 + data null -> free
|
|
127078
|
+
* - 200 + data -> linked-visible (workspace payload)
|
|
127079
|
+
* - 403 + error.meta.workspaceId -> linked-invisible
|
|
127080
|
+
* - 200 + error.meta.workspaceId -> linked-invisible (proxy envelope)
|
|
127081
|
+
*/
|
|
127082
|
+
async findWorkspaceForRepo(repoUrl, path9 = "/") {
|
|
127083
|
+
const fsPath = path9 && path9.trim() ? path9.trim() : "/";
|
|
127084
|
+
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
127085
|
+
const payload = {
|
|
127086
|
+
service: "workspaces",
|
|
127087
|
+
method: "GET",
|
|
127088
|
+
path: `/workspaces/filesystem?repo=${encodeURIComponent(repoUrl)}&path=${encodeURIComponent(fsPath)}`
|
|
127089
|
+
};
|
|
127090
|
+
try {
|
|
127091
|
+
const response = await this.fetchImpl(url, {
|
|
127092
|
+
method: "POST",
|
|
127093
|
+
headers: this.bifrostHeaders(),
|
|
127094
|
+
body: JSON.stringify(payload)
|
|
127095
|
+
});
|
|
127096
|
+
let parsed = {};
|
|
127097
|
+
try {
|
|
127098
|
+
parsed = await response.json();
|
|
127099
|
+
} catch {
|
|
127100
|
+
return {
|
|
127101
|
+
state: "unknown",
|
|
127102
|
+
reason: this.unknownFilesystemLookupReason(
|
|
127103
|
+
repoUrl,
|
|
127104
|
+
fsPath,
|
|
127105
|
+
`returned non-JSON body (HTTP ${response.status})`
|
|
127106
|
+
)
|
|
127107
|
+
};
|
|
127108
|
+
}
|
|
127109
|
+
const errorMetaWorkspaceId = typeof parsed?.error?.meta?.workspaceId === "string" && parsed.error.meta.workspaceId.trim() ? parsed.error.meta.workspaceId.trim() : void 0;
|
|
127110
|
+
if (errorMetaWorkspaceId) {
|
|
127111
|
+
return { state: "linked-invisible", workspaceId: errorMetaWorkspaceId };
|
|
127112
|
+
}
|
|
127113
|
+
if (response.ok) {
|
|
127114
|
+
if (parsed?.data == null) {
|
|
127115
|
+
return { state: "free" };
|
|
127116
|
+
}
|
|
127117
|
+
const id = typeof parsed.data.id === "string" ? parsed.data.id.trim() : "";
|
|
127118
|
+
if (!id) {
|
|
127119
|
+
return {
|
|
127120
|
+
state: "unknown",
|
|
127121
|
+
reason: this.unknownFilesystemLookupReason(
|
|
127122
|
+
repoUrl,
|
|
127123
|
+
fsPath,
|
|
127124
|
+
"returned 200 without a workspace id"
|
|
127125
|
+
)
|
|
127126
|
+
};
|
|
127127
|
+
}
|
|
127128
|
+
const name = typeof parsed.data.name === "string" && parsed.data.name.trim() ? parsed.data.name.trim() : void 0;
|
|
127129
|
+
return {
|
|
127130
|
+
state: "linked-visible",
|
|
127131
|
+
workspace: name ? { id, name } : { id }
|
|
127132
|
+
};
|
|
127133
|
+
}
|
|
127134
|
+
if (response.status === 403) {
|
|
127135
|
+
const workspaceId = extractDuplicateWorkspaceId(
|
|
127136
|
+
JSON.stringify(parsed)
|
|
127137
|
+
);
|
|
127138
|
+
if (workspaceId) {
|
|
127139
|
+
return { state: "linked-invisible", workspaceId };
|
|
127140
|
+
}
|
|
127141
|
+
return {
|
|
127142
|
+
state: "unknown",
|
|
127143
|
+
reason: this.unknownFilesystemLookupReason(
|
|
127144
|
+
repoUrl,
|
|
127145
|
+
fsPath,
|
|
127146
|
+
"returned 403 without error.meta.workspaceId"
|
|
127147
|
+
)
|
|
127148
|
+
};
|
|
127149
|
+
}
|
|
127150
|
+
return {
|
|
127151
|
+
state: "unknown",
|
|
127152
|
+
reason: this.unknownFilesystemLookupReason(
|
|
127153
|
+
repoUrl,
|
|
127154
|
+
fsPath,
|
|
127155
|
+
`returned HTTP ${response.status}`
|
|
127156
|
+
)
|
|
127157
|
+
};
|
|
127158
|
+
} catch (error2) {
|
|
127159
|
+
const cause = error2 instanceof Error ? error2.message : String(error2);
|
|
127160
|
+
return {
|
|
127161
|
+
state: "unknown",
|
|
127162
|
+
reason: this.unknownFilesystemLookupReason(
|
|
127163
|
+
repoUrl,
|
|
127164
|
+
fsPath,
|
|
127165
|
+
`failed: ${cause}`
|
|
127166
|
+
)
|
|
127167
|
+
};
|
|
127168
|
+
}
|
|
127169
|
+
}
|
|
127170
|
+
async connectWorkspaceToRepository(workspaceId, repoUrl, options) {
|
|
126919
127171
|
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
126920
127172
|
const payload = {
|
|
126921
127173
|
service: "workspaces",
|
|
@@ -126942,6 +127194,11 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
126942
127194
|
if (isDuplicate) {
|
|
126943
127195
|
const existingWorkspaceId = extractDuplicateWorkspaceId(body);
|
|
126944
127196
|
if (existingWorkspaceId && existingWorkspaceId !== workspaceId) {
|
|
127197
|
+
if (options?.preflightWasFree) {
|
|
127198
|
+
throw new Error(
|
|
127199
|
+
`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.`
|
|
127200
|
+
);
|
|
127201
|
+
}
|
|
126945
127202
|
throw new Error(
|
|
126946
127203
|
await this.describeWorkspaceLinkConflict(existingWorkspaceId, workspaceId, repoUrl)
|
|
126947
127204
|
);
|
|
@@ -127120,6 +127377,12 @@ var postmanRepoSyncActionContract = {
|
|
|
127120
127377
|
required: false,
|
|
127121
127378
|
default: ".github/workflows/ci.yml"
|
|
127122
127379
|
},
|
|
127380
|
+
"ci-runner-os": {
|
|
127381
|
+
description: "Runner operating system for the generated CI workflow.",
|
|
127382
|
+
required: false,
|
|
127383
|
+
default: "linux",
|
|
127384
|
+
allowedValues: ["linux", "windows"]
|
|
127385
|
+
},
|
|
127123
127386
|
"project-name": {
|
|
127124
127387
|
description: "Service project name used for environment, mock, and monitor naming.",
|
|
127125
127388
|
required: true
|
|
@@ -128831,6 +129094,25 @@ function parseAssetMarker(description) {
|
|
|
128831
129094
|
}
|
|
128832
129095
|
|
|
128833
129096
|
// src/index.ts
|
|
129097
|
+
var identitySecretMasker = (input) => input;
|
|
129098
|
+
function resolveRepoSyncMasker(dependencies) {
|
|
129099
|
+
return dependencies.secretMasker ?? identitySecretMasker;
|
|
129100
|
+
}
|
|
129101
|
+
function causeText(cause) {
|
|
129102
|
+
return cause instanceof Error ? cause.message : String(cause);
|
|
129103
|
+
}
|
|
129104
|
+
function toOneLineDisplay(value) {
|
|
129105
|
+
return String(value ?? "").replace(/[\r\n\u0085\u2028\u2029\v\f]+/g, " ").replace(/[ \t]{2,}/g, " ").trim();
|
|
129106
|
+
}
|
|
129107
|
+
function formatOrchestrationIssue(params) {
|
|
129108
|
+
const operation = toOneLineDisplay(params.mask(params.operation));
|
|
129109
|
+
const entity = toOneLineDisplay(params.mask(params.entity));
|
|
129110
|
+
const maskedCause = toOneLineDisplay(params.mask(causeText(params.cause)));
|
|
129111
|
+
const detail = toOneLineDisplay(params.mask(params.detail ?? ""));
|
|
129112
|
+
const remediation = toOneLineDisplay(params.mask(params.remediation));
|
|
129113
|
+
const body = `${operation} failed for ${entity}: ${maskedCause}${detail}`.replace(/[.]+$/u, "");
|
|
129114
|
+
return toOneLineDisplay(`${body}. ${remediation}`);
|
|
129115
|
+
}
|
|
128834
129116
|
function parseBooleanInput(value, defaultValue) {
|
|
128835
129117
|
const normalized = String(value || "").trim().toLowerCase();
|
|
128836
129118
|
if (!normalized) return defaultValue;
|
|
@@ -128930,6 +129212,17 @@ function parseBranchStrategy(value) {
|
|
|
128930
129212
|
`Unsupported branch-strategy "${normalized}". Supported values: ${allowed.join(", ")}`
|
|
128931
129213
|
);
|
|
128932
129214
|
}
|
|
129215
|
+
function parseCiRunnerOs(value) {
|
|
129216
|
+
const definition = postmanRepoSyncActionContract.inputs["ci-runner-os"];
|
|
129217
|
+
const allowed = definition.allowedValues ?? [];
|
|
129218
|
+
const normalized = String(value || "").trim() || (definition.default ?? "linux");
|
|
129219
|
+
if (allowed.includes(normalized)) {
|
|
129220
|
+
return normalized;
|
|
129221
|
+
}
|
|
129222
|
+
throw new Error(
|
|
129223
|
+
`Unsupported ci-runner-os "${normalized}". Supported values: ${allowed.join(", ")}`
|
|
129224
|
+
);
|
|
129225
|
+
}
|
|
128933
129226
|
function normalizeReleaseLabel(value) {
|
|
128934
129227
|
const cleaned = normalizeInputValue(value).replace(/^refs\/heads\//, "").replace(/^refs\/tags\//, "").replace(/\s+/g, "-").replace(/[^A-Za-z0-9._-]/g, "-").replace(/-+/g, "-").replace(/^[._-]+|[._-]+$/g, "");
|
|
128935
129228
|
return cleaned;
|
|
@@ -129007,6 +129300,7 @@ function resolveInputs(env = process.env) {
|
|
|
129007
129300
|
provider: repoContext.provider,
|
|
129008
129301
|
ciWorkflowBase64: getInput2("ci-workflow-base64", env),
|
|
129009
129302
|
generateCiWorkflow: parseBooleanInput(getInput2("generate-ci-workflow", env), true),
|
|
129303
|
+
ciRunnerOs: parseCiRunnerOs(getInput2("ci-runner-os", env)),
|
|
129010
129304
|
monitorType: getInput2("monitor-type", env) || "cloud",
|
|
129011
129305
|
ciWorkflowPath: getInput2("ci-workflow-path", env) || (repoContext.provider === "azure-devops" ? "azure-pipelines.yml" : ".github/workflows/ci.yml"),
|
|
129012
129306
|
orgMode: parseBooleanInput(getInput2("org-mode", env), false),
|
|
@@ -129025,6 +129319,7 @@ function resolveInputs(env = process.env) {
|
|
|
129025
129319
|
postmanBifrostBase: endpointProfile.bifrostBaseUrl,
|
|
129026
129320
|
postmanFallbackBase: endpointProfile.fallbackBaseUrl,
|
|
129027
129321
|
postmanCliInstallUrl: endpointProfile.cliInstallUrl,
|
|
129322
|
+
postmanCliWindowsInstallUrl: endpointProfile.cliWindowsInstallUrl,
|
|
129028
129323
|
postmanIapubBase: endpointProfile.iapubBaseUrl
|
|
129029
129324
|
};
|
|
129030
129325
|
}
|
|
@@ -129294,6 +129589,7 @@ function readActionInputs(actionCore) {
|
|
|
129294
129589
|
INPUT_GH_FALLBACK_TOKEN: ghFallbackToken,
|
|
129295
129590
|
INPUT_CI_WORKFLOW_BASE64: readInput(actionCore, "ci-workflow-base64"),
|
|
129296
129591
|
INPUT_GENERATE_CI_WORKFLOW: readInput(actionCore, "generate-ci-workflow"),
|
|
129592
|
+
INPUT_CI_RUNNER_OS: readInput(actionCore, "ci-runner-os"),
|
|
129297
129593
|
INPUT_MONITOR_TYPE: readInput(actionCore, "monitor-type") || "cloud",
|
|
129298
129594
|
INPUT_CI_WORKFLOW_PATH: readInput(actionCore, "ci-workflow-path"),
|
|
129299
129595
|
INPUT_ORG_MODE: readInput(actionCore, "org-mode"),
|
|
@@ -129411,19 +129707,34 @@ async function upsertEnvironments(inputs, dependencies, resourcesState, assetMar
|
|
|
129411
129707
|
if (!inputs.workspaceId) {
|
|
129412
129708
|
return envUids;
|
|
129413
129709
|
}
|
|
129710
|
+
const mask = resolveRepoSyncMasker(dependencies);
|
|
129711
|
+
const envRemediation = "verify access-token/team/workspace permissions then rerun";
|
|
129414
129712
|
for (const envName of inputs.environments) {
|
|
129415
129713
|
const runtimeUrl = String(inputs.envRuntimeUrls[envName] || "").trim();
|
|
129416
129714
|
const displayName = `${inputs.projectName} - ${envName}`;
|
|
129417
129715
|
let existingUid = String(envUids[envName] || "").trim();
|
|
129418
129716
|
if (!existingUid) {
|
|
129419
|
-
|
|
129420
|
-
|
|
129421
|
-
|
|
129422
|
-
|
|
129423
|
-
|
|
129424
|
-
|
|
129425
|
-
|
|
129426
|
-
|
|
129717
|
+
try {
|
|
129718
|
+
const discovered = await dependencies.postman.findEnvironmentByName(
|
|
129719
|
+
inputs.workspaceId,
|
|
129720
|
+
displayName
|
|
129721
|
+
);
|
|
129722
|
+
if (discovered?.uid) {
|
|
129723
|
+
existingUid = discovered.uid;
|
|
129724
|
+
dependencies.core.info(
|
|
129725
|
+
`Discovered existing environment for ${displayName}: ${existingUid}`
|
|
129726
|
+
);
|
|
129727
|
+
}
|
|
129728
|
+
} catch (error2) {
|
|
129729
|
+
throw new Error(
|
|
129730
|
+
formatOrchestrationIssue({
|
|
129731
|
+
operation: "Environment discovery",
|
|
129732
|
+
entity: `workspace ${inputs.workspaceId} environment "${displayName}"`,
|
|
129733
|
+
cause: error2,
|
|
129734
|
+
remediation: envRemediation,
|
|
129735
|
+
mask
|
|
129736
|
+
}),
|
|
129737
|
+
{ cause: error2 }
|
|
129427
129738
|
);
|
|
129428
129739
|
}
|
|
129429
129740
|
}
|
|
@@ -129443,17 +129754,43 @@ async function upsertEnvironments(inputs, dependencies, resourcesState, assetMar
|
|
|
129443
129754
|
}
|
|
129444
129755
|
const values2 = buildEnvironmentValues(envName, runtimeUrl);
|
|
129445
129756
|
if (marker) values2.push({ key: "x-pm-onboarding", value: JSON.stringify(marker), type: "default" });
|
|
129446
|
-
|
|
129757
|
+
try {
|
|
129758
|
+
await dependencies.postman.updateEnvironment(existingUid, displayName, values2);
|
|
129759
|
+
} catch (error2) {
|
|
129760
|
+
throw new Error(
|
|
129761
|
+
formatOrchestrationIssue({
|
|
129762
|
+
operation: "Environment update",
|
|
129763
|
+
entity: `workspace ${inputs.workspaceId} environment "${displayName}" (uid ${existingUid})`,
|
|
129764
|
+
cause: error2,
|
|
129765
|
+
remediation: envRemediation,
|
|
129766
|
+
mask
|
|
129767
|
+
}),
|
|
129768
|
+
{ cause: error2 }
|
|
129769
|
+
);
|
|
129770
|
+
}
|
|
129447
129771
|
envUids[envName] = existingUid;
|
|
129448
129772
|
continue;
|
|
129449
129773
|
}
|
|
129450
129774
|
const values = buildEnvironmentValues(envName, runtimeUrl);
|
|
129451
129775
|
if (assetMarker) values.push({ key: "x-pm-onboarding", value: JSON.stringify(assetMarker), type: "default" });
|
|
129452
|
-
|
|
129453
|
-
|
|
129454
|
-
|
|
129455
|
-
|
|
129456
|
-
|
|
129776
|
+
try {
|
|
129777
|
+
envUids[envName] = await dependencies.postman.createEnvironment(
|
|
129778
|
+
inputs.workspaceId,
|
|
129779
|
+
displayName,
|
|
129780
|
+
values
|
|
129781
|
+
);
|
|
129782
|
+
} catch (error2) {
|
|
129783
|
+
throw new Error(
|
|
129784
|
+
formatOrchestrationIssue({
|
|
129785
|
+
operation: "Environment create",
|
|
129786
|
+
entity: `workspace ${inputs.workspaceId} environment "${displayName}"`,
|
|
129787
|
+
cause: error2,
|
|
129788
|
+
remediation: envRemediation,
|
|
129789
|
+
mask
|
|
129790
|
+
}),
|
|
129791
|
+
{ cause: error2 }
|
|
129792
|
+
);
|
|
129793
|
+
}
|
|
129457
129794
|
}
|
|
129458
129795
|
return envUids;
|
|
129459
129796
|
}
|
|
@@ -129710,11 +130047,15 @@ function renderCiWorkflow(inputs) {
|
|
|
129710
130047
|
if (inputs.provider === "azure-devops") {
|
|
129711
130048
|
return getCiWorkflowTemplate(inputs.provider, {
|
|
129712
130049
|
postmanCliInstallUrl: inputs.postmanCliInstallUrl,
|
|
130050
|
+
postmanCliWindowsInstallUrl: inputs.postmanCliWindowsInstallUrl,
|
|
130051
|
+
runnerOs: inputs.ciRunnerOs,
|
|
129713
130052
|
postmanRegion: inputs.postmanRegion
|
|
129714
130053
|
});
|
|
129715
130054
|
}
|
|
129716
130055
|
return renderCiWorkflowTemplate({
|
|
129717
130056
|
postmanCliInstallUrl: inputs.postmanCliInstallUrl,
|
|
130057
|
+
postmanCliWindowsInstallUrl: inputs.postmanCliWindowsInstallUrl,
|
|
130058
|
+
runnerOs: inputs.ciRunnerOs,
|
|
129718
130059
|
postmanRegion: inputs.postmanRegion
|
|
129719
130060
|
});
|
|
129720
130061
|
}
|
|
@@ -129809,6 +130150,7 @@ async function runRepoSync(inputs, dependencies) {
|
|
|
129809
130150
|
}
|
|
129810
130151
|
}
|
|
129811
130152
|
async function runRepoSyncInner(inputs, dependencies) {
|
|
130153
|
+
const mask = resolveRepoSyncMasker(dependencies);
|
|
129812
130154
|
const branchDecision = decideBranchTier(inputs);
|
|
129813
130155
|
assertBranchAssetIds(inputs, branchDecision);
|
|
129814
130156
|
const isCanonicalWriter = branchDecision.tier === "legacy" || branchDecision.tier === "canonical";
|
|
@@ -129868,6 +130210,39 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
129868
130210
|
}
|
|
129869
130211
|
}
|
|
129870
130212
|
}
|
|
130213
|
+
let skipRepositoryLinkPost = false;
|
|
130214
|
+
let repositoryLinkPreflightWasFree = false;
|
|
130215
|
+
if (inputs.workspaceLinkEnabled && inputs.workspaceId && inputs.repoUrl && dependencies.internalIntegration?.findWorkspaceForRepo) {
|
|
130216
|
+
const probe = await dependencies.internalIntegration.findWorkspaceForRepo(
|
|
130217
|
+
inputs.repoUrl,
|
|
130218
|
+
"/"
|
|
130219
|
+
);
|
|
130220
|
+
if (probe.state === "linked-visible") {
|
|
130221
|
+
if (probe.workspace.id === inputs.workspaceId) {
|
|
130222
|
+
skipRepositoryLinkPost = true;
|
|
130223
|
+
dependencies.core.info(
|
|
130224
|
+
`REPOSITORY_LINK_ALREADY_TARGET: Repository ${inputs.repoUrl} at path / is already linked to target workspace ${inputs.workspaceId}; continuing.`
|
|
130225
|
+
);
|
|
130226
|
+
} else {
|
|
130227
|
+
const ownerName = probe.workspace.name?.trim() || "unknown";
|
|
130228
|
+
throw new Error(
|
|
130229
|
+
`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.`
|
|
130230
|
+
);
|
|
130231
|
+
}
|
|
130232
|
+
} else if (probe.state === "linked-invisible") {
|
|
130233
|
+
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.`;
|
|
130234
|
+
if (inputs.orgMode) {
|
|
130235
|
+
message += " Verify workspace-team-id; if the owner is in another sub-team, ask that sub-team's admin to disconnect it.";
|
|
130236
|
+
}
|
|
130237
|
+
throw new Error(message);
|
|
130238
|
+
} else if (probe.state === "free") {
|
|
130239
|
+
repositoryLinkPreflightWasFree = true;
|
|
130240
|
+
} else {
|
|
130241
|
+
dependencies.core.warning(
|
|
130242
|
+
`REPOSITORY_LINK_PREFLIGHT_UNKNOWN: Unable to determine the existing repository link (${probe.reason}); continuing and relying on link creation conflict handling.`
|
|
130243
|
+
);
|
|
130244
|
+
}
|
|
130245
|
+
}
|
|
129871
130246
|
const branchAssetMarker = buildBranchAssetMarker(branchDecision, inputs);
|
|
129872
130247
|
const envUids = await upsertEnvironments(inputs, dependencies, resourcesState, branchAssetMarker);
|
|
129873
130248
|
outputs["environment-uids-json"] = JSON.stringify(envUids);
|
|
@@ -129885,8 +130260,15 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
129885
130260
|
outputs["environment-sync-status"] = "success";
|
|
129886
130261
|
} catch (error2) {
|
|
129887
130262
|
outputs["environment-sync-status"] = "failed";
|
|
130263
|
+
const associationSummary = associations.map((entry) => `${entry.envUid}->${entry.systemEnvId}`).join(", ");
|
|
129888
130264
|
dependencies.core.warning(
|
|
129889
|
-
|
|
130265
|
+
formatOrchestrationIssue({
|
|
130266
|
+
operation: "System environment association",
|
|
130267
|
+
entity: `workspace ${inputs.workspaceId} (${associationSummary})`,
|
|
130268
|
+
cause: error2,
|
|
130269
|
+
remediation: "verify access-token/team/system-env mapping then rerun",
|
|
130270
|
+
mask
|
|
130271
|
+
})
|
|
129890
130272
|
);
|
|
129891
130273
|
}
|
|
129892
130274
|
} else if (Object.keys(envUids).length > 0) {
|
|
@@ -129914,37 +130296,72 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
129914
130296
|
dependencies.core.info(`Reusing mock from explicit input: ${resolvedMockUrl}`);
|
|
129915
130297
|
}
|
|
129916
130298
|
if (!resolvedMockUrl && inputs.baselineCollectionId) {
|
|
129917
|
-
|
|
129918
|
-
|
|
129919
|
-
|
|
129920
|
-
|
|
129921
|
-
|
|
129922
|
-
|
|
129923
|
-
|
|
129924
|
-
|
|
130299
|
+
try {
|
|
130300
|
+
const discovered = await dependencies.postman.findMockByCollection(
|
|
130301
|
+
inputs.baselineCollectionId,
|
|
130302
|
+
mockEnvUid,
|
|
130303
|
+
mockName
|
|
130304
|
+
);
|
|
130305
|
+
if (discovered) {
|
|
130306
|
+
resolvedMockUrl = discovered.mockUrl;
|
|
130307
|
+
dependencies.core.info(`Discovered existing mock for collection ${inputs.baselineCollectionId}: ${resolvedMockUrl}`);
|
|
130308
|
+
}
|
|
130309
|
+
} catch (error2) {
|
|
130310
|
+
throw new Error(
|
|
130311
|
+
formatOrchestrationIssue({
|
|
130312
|
+
operation: "Mock discovery",
|
|
130313
|
+
entity: `mock "${mockName}" workspace ${inputs.workspaceId} collection ${inputs.baselineCollectionId} environment ${mockEnvUid}`,
|
|
130314
|
+
cause: error2,
|
|
130315
|
+
remediation: "verify collection/environment access then rerun",
|
|
130316
|
+
mask
|
|
130317
|
+
}),
|
|
130318
|
+
{ cause: error2 }
|
|
130319
|
+
);
|
|
129925
130320
|
}
|
|
129926
130321
|
}
|
|
129927
130322
|
if (!resolvedMockUrl) {
|
|
129928
|
-
const
|
|
129929
|
-
|
|
129930
|
-
|
|
129931
|
-
|
|
129932
|
-
|
|
129933
|
-
|
|
129934
|
-
|
|
129935
|
-
|
|
129936
|
-
|
|
129937
|
-
|
|
129938
|
-
|
|
129939
|
-
|
|
129940
|
-
|
|
129941
|
-
|
|
129942
|
-
)
|
|
130323
|
+
const mockEntity = `mock "${mockName}" workspace ${inputs.workspaceId} collection ${inputs.baselineCollectionId} environment ${mockEnvUid}`;
|
|
130324
|
+
const mockRemediation = "verify collection/environment access then rerun";
|
|
130325
|
+
try {
|
|
130326
|
+
const mock = await retry(
|
|
130327
|
+
() => dependencies.postman.createMock(
|
|
130328
|
+
inputs.workspaceId,
|
|
130329
|
+
mockName,
|
|
130330
|
+
inputs.baselineCollectionId,
|
|
130331
|
+
mockEnvUid
|
|
130332
|
+
),
|
|
130333
|
+
{
|
|
130334
|
+
maxAttempts: 3,
|
|
130335
|
+
delayMs: 2e3,
|
|
130336
|
+
backoffMultiplier: 2,
|
|
130337
|
+
onRetry: ({ attempt, maxAttempts, error: error2 }) => {
|
|
130338
|
+
dependencies.core.warning(
|
|
130339
|
+
formatOrchestrationIssue({
|
|
130340
|
+
operation: `Mock create attempt ${attempt}/${maxAttempts}`,
|
|
130341
|
+
entity: mockEntity,
|
|
130342
|
+
cause: error2,
|
|
130343
|
+
remediation: mockRemediation,
|
|
130344
|
+
mask,
|
|
130345
|
+
detail: "; retrying"
|
|
130346
|
+
})
|
|
130347
|
+
);
|
|
130348
|
+
}
|
|
129943
130349
|
}
|
|
129944
|
-
|
|
129945
|
-
|
|
129946
|
-
|
|
129947
|
-
|
|
130350
|
+
);
|
|
130351
|
+
resolvedMockUrl = mock.url;
|
|
130352
|
+
dependencies.core.info(`Created new mock: ${resolvedMockUrl}`);
|
|
130353
|
+
} catch (error2) {
|
|
130354
|
+
throw new Error(
|
|
130355
|
+
formatOrchestrationIssue({
|
|
130356
|
+
operation: "Mock create",
|
|
130357
|
+
entity: mockEntity,
|
|
130358
|
+
cause: error2,
|
|
130359
|
+
remediation: mockRemediation,
|
|
130360
|
+
mask
|
|
130361
|
+
}),
|
|
130362
|
+
{ cause: error2 }
|
|
130363
|
+
);
|
|
130364
|
+
}
|
|
129948
130365
|
}
|
|
129949
130366
|
outputs["mock-url"] = resolvedMockUrl;
|
|
129950
130367
|
}
|
|
@@ -129955,35 +130372,71 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
129955
130372
|
if (monitorEnvUid && inputs.monitorType !== "cli") {
|
|
129956
130373
|
let resolvedMonitorId = "";
|
|
129957
130374
|
const monitorName = `${assetProjectName} - Smoke Monitor`;
|
|
130375
|
+
const monitorRemediation = "verify monitor IDs/access or set monitor-cron then rerun";
|
|
129958
130376
|
if (inputs.monitorId) {
|
|
129959
130377
|
const valid = await dependencies.postman.monitorExists(inputs.monitorId);
|
|
129960
130378
|
if (valid) {
|
|
129961
130379
|
resolvedMonitorId = inputs.monitorId;
|
|
129962
130380
|
dependencies.core.info(`Reusing monitor from explicit input: ${resolvedMonitorId}`);
|
|
129963
130381
|
} else {
|
|
129964
|
-
dependencies.core.warning(
|
|
130382
|
+
dependencies.core.warning(
|
|
130383
|
+
formatOrchestrationIssue({
|
|
130384
|
+
operation: "Explicit monitor-id lookup",
|
|
130385
|
+
entity: `monitor-id ${inputs.monitorId} workspace ${inputs.workspaceId} collection ${inputs.smokeCollectionId} environment ${monitorEnvUid}`,
|
|
130386
|
+
cause: "not found in Postman",
|
|
130387
|
+
remediation: monitorRemediation,
|
|
130388
|
+
mask,
|
|
130389
|
+
detail: "; falling through to discovery"
|
|
130390
|
+
})
|
|
130391
|
+
);
|
|
129965
130392
|
}
|
|
129966
130393
|
}
|
|
129967
130394
|
if (!resolvedMonitorId && inputs.smokeCollectionId) {
|
|
129968
|
-
|
|
129969
|
-
|
|
129970
|
-
|
|
129971
|
-
|
|
129972
|
-
|
|
129973
|
-
|
|
129974
|
-
|
|
129975
|
-
|
|
130395
|
+
try {
|
|
130396
|
+
const discovered = await dependencies.postman.findMonitorByCollection(
|
|
130397
|
+
inputs.smokeCollectionId,
|
|
130398
|
+
monitorEnvUid,
|
|
130399
|
+
monitorName
|
|
130400
|
+
);
|
|
130401
|
+
if (discovered) {
|
|
130402
|
+
resolvedMonitorId = discovered.uid;
|
|
130403
|
+
dependencies.core.info(`Discovered existing monitor for collection ${inputs.smokeCollectionId}: ${resolvedMonitorId}`);
|
|
130404
|
+
}
|
|
130405
|
+
} catch (error2) {
|
|
130406
|
+
throw new Error(
|
|
130407
|
+
formatOrchestrationIssue({
|
|
130408
|
+
operation: "Monitor discovery",
|
|
130409
|
+
entity: `monitor "${monitorName}" workspace ${inputs.workspaceId} collection ${inputs.smokeCollectionId} environment ${monitorEnvUid}`,
|
|
130410
|
+
cause: error2,
|
|
130411
|
+
remediation: monitorRemediation,
|
|
130412
|
+
mask
|
|
130413
|
+
}),
|
|
130414
|
+
{ cause: error2 }
|
|
130415
|
+
);
|
|
129976
130416
|
}
|
|
129977
130417
|
}
|
|
129978
130418
|
if (!resolvedMonitorId) {
|
|
129979
|
-
|
|
129980
|
-
|
|
129981
|
-
|
|
129982
|
-
|
|
129983
|
-
|
|
129984
|
-
|
|
129985
|
-
|
|
129986
|
-
|
|
130419
|
+
try {
|
|
130420
|
+
resolvedMonitorId = await dependencies.postman.createMonitor(
|
|
130421
|
+
inputs.workspaceId,
|
|
130422
|
+
monitorName,
|
|
130423
|
+
inputs.smokeCollectionId,
|
|
130424
|
+
monitorEnvUid,
|
|
130425
|
+
effectiveCron || void 0
|
|
130426
|
+
);
|
|
130427
|
+
dependencies.core.info(`Created new monitor: ${resolvedMonitorId}${effectiveCron ? "" : " (disabled \u2014 no cron configured; will trigger a one-time run)"}`);
|
|
130428
|
+
} catch (error2) {
|
|
130429
|
+
throw new Error(
|
|
130430
|
+
formatOrchestrationIssue({
|
|
130431
|
+
operation: "Monitor create",
|
|
130432
|
+
entity: `monitor "${monitorName}" workspace ${inputs.workspaceId} collection ${inputs.smokeCollectionId} environment ${monitorEnvUid}`,
|
|
130433
|
+
cause: error2,
|
|
130434
|
+
remediation: monitorRemediation,
|
|
130435
|
+
mask
|
|
130436
|
+
}),
|
|
130437
|
+
{ cause: error2 }
|
|
130438
|
+
);
|
|
130439
|
+
}
|
|
129987
130440
|
}
|
|
129988
130441
|
outputs["monitor-id"] = resolvedMonitorId;
|
|
129989
130442
|
if (!effectiveCron && resolvedMonitorId) {
|
|
@@ -129992,7 +130445,13 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
129992
130445
|
dependencies.core.info(`Triggered one-time run for monitor: ${resolvedMonitorId}`);
|
|
129993
130446
|
} catch (error2) {
|
|
129994
130447
|
dependencies.core.warning(
|
|
129995
|
-
|
|
130448
|
+
formatOrchestrationIssue({
|
|
130449
|
+
operation: "Monitor one-time run",
|
|
130450
|
+
entity: `monitor ${resolvedMonitorId} name "${monitorName}" workspace ${inputs.workspaceId} collection ${inputs.smokeCollectionId} environment ${monitorEnvUid}`,
|
|
130451
|
+
cause: error2,
|
|
130452
|
+
remediation: monitorRemediation,
|
|
130453
|
+
mask
|
|
130454
|
+
})
|
|
129996
130455
|
);
|
|
129997
130456
|
}
|
|
129998
130457
|
}
|
|
@@ -130000,18 +130459,33 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
130000
130459
|
}
|
|
130001
130460
|
if (inputs.workspaceLinkEnabled && inputs.workspaceId && inputs.repoUrl && dependencies.internalIntegration) {
|
|
130002
130461
|
try {
|
|
130003
|
-
|
|
130004
|
-
|
|
130005
|
-
|
|
130006
|
-
|
|
130007
|
-
|
|
130008
|
-
|
|
130009
|
-
|
|
130010
|
-
|
|
130462
|
+
if (skipRepositoryLinkPost) {
|
|
130463
|
+
outputs["workspace-link-status"] = "success";
|
|
130464
|
+
dependencies.core.info(
|
|
130465
|
+
`workspace-link-status=success workspace-id=${inputs.workspaceId} repo=${inputs.repoUrl} (preflight already-target; link POST skipped)`
|
|
130466
|
+
);
|
|
130467
|
+
} else {
|
|
130468
|
+
await dependencies.internalIntegration.connectWorkspaceToRepository(
|
|
130469
|
+
inputs.workspaceId,
|
|
130470
|
+
inputs.repoUrl,
|
|
130471
|
+
repositoryLinkPreflightWasFree ? { preflightWasFree: true } : void 0
|
|
130472
|
+
);
|
|
130473
|
+
outputs["workspace-link-status"] = "success";
|
|
130474
|
+
dependencies.core.info(
|
|
130475
|
+
`workspace-link-status=success workspace-id=${inputs.workspaceId} repo=${inputs.repoUrl}`
|
|
130476
|
+
);
|
|
130477
|
+
}
|
|
130011
130478
|
} catch (error2) {
|
|
130012
130479
|
outputs["workspace-link-status"] = "failed";
|
|
130013
|
-
const
|
|
130480
|
+
const rawMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
130481
|
+
const isUnresolvedContract = rawMessage.startsWith(
|
|
130482
|
+
"REPOSITORY_LINK_CONFLICT_UNRESOLVED:"
|
|
130483
|
+
);
|
|
130484
|
+
const message = isUnresolvedContract ? rawMessage : `Workspace link failed: ${rawMessage}`;
|
|
130014
130485
|
if (branchDecision.tier === "canonical") {
|
|
130486
|
+
if (isUnresolvedContract && error2 instanceof Error) {
|
|
130487
|
+
throw error2;
|
|
130488
|
+
}
|
|
130015
130489
|
throw new Error(message, { cause: error2 });
|
|
130016
130490
|
}
|
|
130017
130491
|
dependencies.core.warning(message);
|
|
@@ -130042,18 +130516,57 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
130042
130516
|
dependencies.core.info(`Tagged spec version at finalize: ${tag.name || tagName}`);
|
|
130043
130517
|
} catch (error2) {
|
|
130044
130518
|
const status = error2.status;
|
|
130519
|
+
const specEntity = `spec ${inputs.specId} tag "${tagName}" workspace ${inputs.workspaceId}`;
|
|
130520
|
+
const specRemediation = "inspect existing tags/access and rerun";
|
|
130045
130521
|
if (status === 409) {
|
|
130046
|
-
|
|
130522
|
+
let tags = [];
|
|
130523
|
+
let listError;
|
|
130524
|
+
if (dependencies.postman.listSpecVersionTags) {
|
|
130525
|
+
try {
|
|
130526
|
+
tags = await dependencies.postman.listSpecVersionTags(inputs.specId);
|
|
130527
|
+
} catch (lookupError) {
|
|
130528
|
+
listError = lookupError;
|
|
130529
|
+
}
|
|
130530
|
+
}
|
|
130047
130531
|
const latest = tags[0];
|
|
130048
|
-
if (latest && (latest.name === tagName || /\([0-9a-f]{7}\)$/.test(latest.name) || /^[0-9a-f]{7}$/.test(latest.name))) {
|
|
130532
|
+
if (!listError && latest && (latest.name === tagName || /\([0-9a-f]{7}\)$/.test(latest.name) || /^[0-9a-f]{7}$/.test(latest.name))) {
|
|
130049
130533
|
outputs["spec-version-tag"] = latest.name;
|
|
130050
130534
|
outputs["spec-version-url"] = `https://web.postman.co/workspace/${encodeURIComponent(inputs.workspaceId)}/specification/${encodeURIComponent(inputs.specId)}?tagId=${encodeURIComponent(latest.id)}&versionLabel=${encodeURIComponent(latest.name)}`;
|
|
130051
130535
|
dependencies.core.info(`Latest changelog group already tagged as "${latest.name}"; adopting.`);
|
|
130536
|
+
} else if (listError) {
|
|
130537
|
+
dependencies.core.warning(
|
|
130538
|
+
formatOrchestrationIssue({
|
|
130539
|
+
operation: "Spec Hub tagging conflict",
|
|
130540
|
+
entity: specEntity,
|
|
130541
|
+
cause: `create=${causeText(error2)}; listSpecVersionTags=${causeText(listError)}`,
|
|
130542
|
+
remediation: specRemediation,
|
|
130543
|
+
mask,
|
|
130544
|
+
detail: "; could not list existing tags to confirm adoption"
|
|
130545
|
+
})
|
|
130546
|
+
);
|
|
130052
130547
|
} else {
|
|
130053
|
-
dependencies.core.warning(
|
|
130548
|
+
dependencies.core.warning(
|
|
130549
|
+
formatOrchestrationIssue({
|
|
130550
|
+
operation: "Spec Hub tagging conflict",
|
|
130551
|
+
entity: specEntity,
|
|
130552
|
+
cause: error2,
|
|
130553
|
+
remediation: specRemediation,
|
|
130554
|
+
mask,
|
|
130555
|
+
detail: "; latest changelog group already carries a hand-applied or nonmatching tag; leaving it in place"
|
|
130556
|
+
})
|
|
130557
|
+
);
|
|
130054
130558
|
}
|
|
130055
130559
|
} else {
|
|
130056
|
-
dependencies.core.warning(
|
|
130560
|
+
dependencies.core.warning(
|
|
130561
|
+
formatOrchestrationIssue({
|
|
130562
|
+
operation: "Spec version tagging",
|
|
130563
|
+
entity: specEntity,
|
|
130564
|
+
cause: error2,
|
|
130565
|
+
remediation: specRemediation,
|
|
130566
|
+
mask,
|
|
130567
|
+
detail: " (non-fatal)"
|
|
130568
|
+
})
|
|
130569
|
+
);
|
|
130057
130570
|
}
|
|
130058
130571
|
}
|
|
130059
130572
|
}
|
|
@@ -130084,7 +130597,16 @@ async function resolvePostmanApiKeyAndTeamId(inputs, actionCore, actionExec, mas
|
|
|
130084
130597
|
}
|
|
130085
130598
|
} catch (error2) {
|
|
130086
130599
|
if (typeof error2 === "object" && error2 !== null && "status" in error2 && (error2.status === 401 || error2.status === 403)) {
|
|
130087
|
-
|
|
130600
|
+
const status = error2.status;
|
|
130601
|
+
actionCore.warning(
|
|
130602
|
+
formatOrchestrationIssue({
|
|
130603
|
+
operation: "PMAK GET /me validation",
|
|
130604
|
+
entity: `status ${status}`,
|
|
130605
|
+
cause: error2,
|
|
130606
|
+
remediation: "replace postman-api-key or provide a valid postman-access-token then rerun",
|
|
130607
|
+
mask: masker
|
|
130608
|
+
})
|
|
130609
|
+
);
|
|
130088
130610
|
} else {
|
|
130089
130611
|
throw error2;
|
|
130090
130612
|
}
|
|
@@ -130106,6 +130628,7 @@ async function resolvePostmanApiKeyAndTeamId(inputs, actionCore, actionExec, mas
|
|
|
130106
130628
|
const keyName = `repo-sync-action-${Date.now()}`;
|
|
130107
130629
|
apiKey = await internalIntegration.createApiKey(keyName);
|
|
130108
130630
|
actionCore.setSecret(apiKey);
|
|
130631
|
+
const persistSecretRemediation = "grant Actions secrets write permission or set POSTMAN_API_KEY manually then rerun";
|
|
130109
130632
|
if (inputs.provider === "azure-devops") {
|
|
130110
130633
|
if (options.persistGeneratedApiKeySecret ?? true) {
|
|
130111
130634
|
actionCore.warning(
|
|
@@ -130132,16 +130655,48 @@ async function resolvePostmanApiKeyAndTeamId(inputs, actionCore, actionExec, mas
|
|
|
130132
130655
|
ignoreReturnCode: true
|
|
130133
130656
|
});
|
|
130134
130657
|
if (ghCommand.exitCode !== 0) {
|
|
130135
|
-
actionCore.warning(
|
|
130658
|
+
actionCore.warning(
|
|
130659
|
+
formatOrchestrationIssue({
|
|
130660
|
+
operation: "gh secret set POSTMAN_API_KEY",
|
|
130661
|
+
entity: `repository ${repo}`,
|
|
130662
|
+
cause: ghCommand.stderr || `exit code ${ghCommand.exitCode}`,
|
|
130663
|
+
remediation: persistSecretRemediation,
|
|
130664
|
+
mask: masker
|
|
130665
|
+
})
|
|
130666
|
+
);
|
|
130136
130667
|
}
|
|
130137
130668
|
} catch (error2) {
|
|
130138
130669
|
actionCore.warning(
|
|
130139
|
-
|
|
130670
|
+
formatOrchestrationIssue({
|
|
130671
|
+
operation: "gh secret set POSTMAN_API_KEY",
|
|
130672
|
+
entity: `repository ${repo}`,
|
|
130673
|
+
cause: error2,
|
|
130674
|
+
remediation: persistSecretRemediation,
|
|
130675
|
+
mask: masker
|
|
130676
|
+
})
|
|
130140
130677
|
);
|
|
130141
130678
|
}
|
|
130679
|
+
} else {
|
|
130680
|
+
actionCore.warning(
|
|
130681
|
+
formatOrchestrationIssue({
|
|
130682
|
+
operation: "gh secret set POSTMAN_API_KEY",
|
|
130683
|
+
entity: "repository (missing)",
|
|
130684
|
+
cause: "repository context is empty",
|
|
130685
|
+
remediation: "set repository context or persist POSTMAN_API_KEY manually then rerun",
|
|
130686
|
+
mask: masker
|
|
130687
|
+
})
|
|
130688
|
+
);
|
|
130142
130689
|
}
|
|
130143
130690
|
} else if (options.persistGeneratedApiKeySecret ?? true) {
|
|
130144
|
-
actionCore.warning(
|
|
130691
|
+
actionCore.warning(
|
|
130692
|
+
formatOrchestrationIssue({
|
|
130693
|
+
operation: "gh secret set POSTMAN_API_KEY",
|
|
130694
|
+
entity: inputs.repository ? `repository ${inputs.repository}` : "repository (unknown)",
|
|
130695
|
+
cause: "no GitHub token provided",
|
|
130696
|
+
remediation: "provide github-token/gh-fallback-token or set POSTMAN_API_KEY manually then rerun",
|
|
130697
|
+
mask: masker
|
|
130698
|
+
})
|
|
130699
|
+
);
|
|
130145
130700
|
} else {
|
|
130146
130701
|
actionCore.info("Skipping generated POSTMAN_API_KEY GitHub secret persistence for this run.");
|
|
130147
130702
|
}
|
|
@@ -130180,7 +130735,13 @@ async function resolvePostmanApiKeyAndTeamId(inputs, actionCore, actionExec, mas
|
|
|
130180
130735
|
const isNonOrgSquads = error2 instanceof HttpError && error2.status === 400 && /squad feature is not available/i.test(error2.responseBody);
|
|
130181
130736
|
if (!isNonOrgSquads) {
|
|
130182
130737
|
actionCore.warning(
|
|
130183
|
-
|
|
130738
|
+
formatOrchestrationIssue({
|
|
130739
|
+
operation: "Org-mode auto-detection via ums squads",
|
|
130740
|
+
entity: `team ${teamId}`,
|
|
130741
|
+
cause: error2,
|
|
130742
|
+
remediation: "set org-mode and team-id explicitly then rerun",
|
|
130743
|
+
mask: masker
|
|
130744
|
+
})
|
|
130184
130745
|
);
|
|
130185
130746
|
}
|
|
130186
130747
|
}
|
|
@@ -130300,7 +130861,8 @@ function createRepoSyncDependencies(inputs, resolved, factories, options = {}) {
|
|
|
130300
130861
|
core: factories.core,
|
|
130301
130862
|
postman,
|
|
130302
130863
|
internalIntegration,
|
|
130303
|
-
repoMutation
|
|
130864
|
+
repoMutation,
|
|
130865
|
+
secretMasker: masker
|
|
130304
130866
|
};
|
|
130305
130867
|
}
|
|
130306
130868
|
function decideBranchTier(inputs, env = process.env) {
|