Skip to content

Commit bfecf7f

Browse files
garg-muditMGDS01
andauthored
[DCM-16244]: Fix Postman API sync failure for eSign collection (#181)
## Summary Add an opt-in preprocessing step to the shared Postman sync workflow to strip nested `id` fields before uploading a collection, and enable it only for the eSign collection. ## Background The shared `sync-postman-collection.yml` workflow was working for other collections such as Admin, but eSign collection updates were consistently failing through Postman API with an internal server error. During debugging: - The same shared workflow worked for other collections. - The same API key and request pattern worked for non-eSign collections. - eSign collection could still be imported successfully through Postman UI. - eSign updates failed specifically through the API path. - Additional narrowing suggested the issue was related to content within the eSign payload rather than the wrapper logic itself. Based on the investigation, stripping nested `id` fields from the collection JSON before upload resolves the API update issue for eSign. ## Changes made ### Shared workflow Updated `.github/workflows/sync-postman-collection.yml` to support a new optional input: - `strip-item-ids` (boolean, default: `false`) When enabled, the workflow: 1. Reads the collection JSON from the repository 2. Removes all nested `id` fields using `jq` 3. Wraps the processed JSON in the Postman API request format: ```json { "collection": ... } Co-authored-by: Mudit Garg <mudit.garg@docusign.com>
1 parent 6e59e3f commit bfecf7f

2 files changed

Lines changed: 82 additions & 25 deletions

File tree

.github/workflows/sync-esign-v2.1.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,24 @@ name: Sync eSign-v2.1 Postman Collection
33
on:
44
push:
55
branches:
6-
- master # Change this to the branch you want to trigger the action
6+
- master
77
paths:
88
- 'assets/esign-v2.1-collection.json'
9-
9+
1010
workflow_dispatch: # Enables manual trigger from GitHub UI
1111

1212
jobs:
1313
sync-postman-collection:
1414
uses: ./.github/workflows/sync-postman-collection.yml
1515
with:
16+
# Target Postman collection UID for eSign collection sync.
1617
collection-uid: ${{ vars.ESIGN_COLLECTION_UID }}
18+
19+
# Path to the eSign collection JSON in the repo.
1720
collection-path: './assets/esign-v2.1-collection.json'
21+
22+
# Enable id stripping only for eSign for now, since this collection was
23+
# observed to fail Postman API updates when nested `id` fields are present.
24+
strip-item-ids: true
1825
secrets:
1926
POSTMAN_API_KEY: ${{ secrets.POSTMAN_API_KEY }}

.github/workflows/sync-postman-collection.yml

Lines changed: 73 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,54 +5,104 @@ on:
55
workflow_call:
66
inputs:
77
collection-uid:
8-
description: 'The UID of the Postman collection to update'
8+
description: 'UID of the Postman collection to update'
99
required: true
1010
type: string
11+
1112
collection-path:
12-
description: 'The path to the Postman collection JSON file in the repository'
13+
description: 'Path to the Postman collection JSON file in the repository'
1314
required: true
1415
type: string
16+
17+
strip-item-ids:
18+
description: 'If true, removes all `id` fields from the collection JSON before uploading'
19+
required: false
20+
type: boolean
21+
default: false
22+
1523
secrets:
1624
POSTMAN_API_KEY:
17-
description: 'API key for authenticating with Postman'
25+
description: 'API key for authenticating with Postman API'
1826
required: true
27+
1928
jobs:
2029
update-postman:
2130
runs-on: ubuntu-latest
31+
2232
steps:
33+
# Step 1:
34+
# Check out the repository so the workflow can read the collection JSON file.
2335
- name: Checkout repository
24-
uses: actions/checkout@v2
36+
uses: actions/checkout@v4
2537

26-
- name: Update Postman Collection
38+
# Step 2:
39+
# Prepare the collection payload and upload it to Postman.
40+
- name: Prepare and update Postman Collection
2741
env:
2842
POSTMAN_API_KEY: ${{ secrets.POSTMAN_API_KEY }}
2943
COLLECTION_UID: ${{ inputs.collection-uid }}
3044
GITHUB_COLLECTION_PATH: ${{ inputs.collection-path }}
45+
STRIP_ITEM_IDS: ${{ inputs.strip-item-ids }}
3146
run: |
32-
33-
# Read the file content and wrap it inside a collection object
34-
WRAPPED_CONTENT=$(jq -n --slurpfile data "$GITHUB_COLLECTION_PATH" '{"collection": $data[0]}')
35-
36-
# Write the wrapped content to a temporary file
37-
echo "$WRAPPED_CONTENT" > wrapped_collection.json
38-
39-
# Make API request and capture response & HTTP status
40-
HTTP_RESPONSE=$(curl --silent --write-out "HTTPSTATUS:%{http_code}" --location --request PUT \
41-
"https://api.getpostman.com/collections/$COLLECTION_UID" \
42-
--header "x-api-key: $POSTMAN_API_KEY" \
43-
--header "Content-Type: application/json" \
44-
--data-binary @wrapped_collection.json)
45-
46-
# Extract body and status code
47+
set -euo pipefail
48+
49+
# Input collection file from the repository.
50+
INPUT_JSON="$GITHUB_COLLECTION_PATH"
51+
52+
# Intermediate file that will be uploaded after any required transformation.
53+
PREPARED_JSON="prepared_collection.json"
54+
55+
# Final payload file in the format expected by Postman API:
56+
# {
57+
# "collection": { ...actual collection json... }
58+
# }
59+
WRAPPED_JSON="wrapped_collection.json"
60+
61+
# Step 2a:
62+
# Some collections (currently eSign) fail on Postman API update if nested `id`
63+
# fields are present. To keep the shared workflow reusable, this behavior is
64+
# controlled through the `strip-item-ids` input and enabled only where needed.
65+
if [ "$STRIP_ITEM_IDS" = "true" ]; then
66+
echo "Stripping all id fields from collection JSON before upload..."
67+
68+
# Remove every `id` field from all nested objects in the collection JSON.
69+
# This keeps the structure intact while avoiding Postman API failures seen
70+
# with certain collections during update.
71+
jq 'walk(if type == "object" then del(.id) else . end)' \
72+
"$INPUT_JSON" > "$PREPARED_JSON"
73+
else
74+
echo "Keeping collection JSON unchanged..."
75+
cp "$INPUT_JSON" "$PREPARED_JSON"
76+
fi
77+
78+
# Step 2b:
79+
# Wrap the collection JSON inside a top-level `collection` object because
80+
# Postman API expects the request body in this format for collection updates.
81+
jq -n --slurpfile data "$PREPARED_JSON" \
82+
'{"collection": $data[0]}' > "$WRAPPED_JSON"
83+
84+
# Step 2c:
85+
# Send the PUT request to update the target Postman collection.
86+
# We also capture both the response body and HTTP status for debugging.
87+
HTTP_RESPONSE=$(curl --silent --write-out "HTTPSTATUS:%{http_code}" \
88+
--location --request PUT \
89+
"https://api.getpostman.com/collections/$COLLECTION_UID" \
90+
--header "x-api-key: $POSTMAN_API_KEY" \
91+
--header "Content-Type: application/json" \
92+
--data-binary @"$WRAPPED_JSON")
93+
94+
# Step 2d:
95+
# Split the combined curl output into response body and HTTP status code.
4796
HTTP_BODY=$(echo "$HTTP_RESPONSE" | sed -e 's/HTTPSTATUS\:.*//g')
4897
HTTP_STATUS=$(echo "$HTTP_RESPONSE" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
4998
50-
# Output the response body and status code
99+
# Print response details to make failures easier to debug in Actions logs.
51100
echo "API Response: $HTTP_BODY"
52101
echo "HTTP Status Code: $HTTP_STATUS"
53102
54-
# Fail the job if the API request was not successful (HTTP 200-299 are success codes)
103+
# Step 2e:
104+
# Fail the job if Postman API did not return a success status code.
55105
if [[ "$HTTP_STATUS" -lt 200 || "$HTTP_STATUS" -ge 300 ]]; then
56106
echo "❌ API request failed with status code $HTTP_STATUS"
57107
exit 1
58-
fi
108+
fi

0 commit comments

Comments
 (0)