Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .github/workflows/generate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ jobs:
git config user.name "devexperience"
git config user.email "devexperience@mx.com"
git add .
git commit -m "Generated API ${{ github.event.inputs.api_version }} SDK for version ${{ steps.bump_version.outputs.version }}
git commit -m "Manually Generated API ${{ github.event.inputs.api_version }} SDK for version ${{ steps.bump_version.outputs.version }}

This pull request was automatically generated by a GitHub Action.
This pull request was automatically generated by generate GitHub Action.

API Version: ${{ github.event.inputs.api_version }}
SDK Version: ${{ steps.bump_version.outputs.version }}
Expand All @@ -113,8 +113,7 @@ jobs:
status: ${{ job.status }}
token: ${{ secrets.GITHUB_TOKEN }}
notification_title: "{repo}: {workflow} workflow"
message_format: "{emoji} *{workflow}* {status_message} in <{repo_url}|{repo}>"
footer: "<{workflow_url}|View Workflow>"
message_format: "{emoji} *<{workflow_url}|{workflow}>* {status_message} in <{repo_url}|{repo}>"
notify_when: "failure"
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
33 changes: 29 additions & 4 deletions .github/workflows/on-push-master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ on:
paths:
- 'v20111101/**'
- 'v20250224/**'
repository_dispatch:
types: [automated_push_to_master]

jobs:
# Check for skip-publish flag in commit message. This allows skipping publish/release for specific scenarios,
Expand All @@ -17,8 +19,9 @@ jobs:
steps:
- name: Check for [skip-publish] flag in commit message
id: check
env:
COMMIT_MSG: ${{ github.event.head_commit.message }}
run: |
COMMIT_MSG="${{ github.event.head_commit.message }}"
if [[ "$COMMIT_MSG" == *"[skip-publish]"* ]]; then
echo "skip_publish=true" >> $GITHUB_OUTPUT
echo "🚫 [skip-publish] flag detected - skipping all publish/release jobs"
Expand All @@ -27,9 +30,11 @@ jobs:
echo "✅ No skip flag - proceeding with publish/release"
fi

# Detect which API versions were modified in this push
# Uses dorny/paths-filter to reliably check which directories changed
# This allows us to run publish/release jobs only for versions that were actually modified
# Detect which API versions were modified
# Uses dorny/paths-filter to check which version directories changed.
# For push events: paths-filter uses github.event.before/after automatically.
# For repository_dispatch events: both push and dispatch target master (same branch),
# so we compare HEAD against HEAD~1 to detect changes from the just-pushed commit.
detect-changes:
runs-on: ubuntu-latest
outputs:
Expand All @@ -40,6 +45,7 @@ jobs:
- uses: dorny/paths-filter@v2
id: filter
with:
base: ${{ github.event_name == 'repository_dispatch' && 'HEAD~1' || '' }}
filters: |
v20111101:
- 'v20111101/**'
Expand Down Expand Up @@ -88,3 +94,22 @@ jobs:
with:
version_directory: v20250224
secrets: inherit

# Notify on failure of orchestration jobs (check-skip-publish, detect-changes, delay).
# Publish and release workflows have their own Slack notifications, so we only
# monitor the jobs owned by this workflow to avoid double-alerting.
slack-notification:
runs-on: ubuntu-latest
needs: [check-skip-publish, detect-changes, delay-for-v20250224]
if: always() && (needs.check-skip-publish.result == 'failure' || needs.detect-changes.result == 'failure' || needs.delay-for-v20250224.result == 'failure')
steps:
- name: Slack notification
uses: ravsamhq/notify-slack-action@v2
with:
status: failure
token: ${{ secrets.GITHUB_TOKEN }}
notification_title: "{repo}: {workflow} workflow"
message_format: "{emoji} *<{workflow_url}|{workflow}>* {status_message} in <{repo_url}|{repo}>"
notify_when: "failure"
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
100 changes: 72 additions & 28 deletions .github/workflows/openapi-generate-and-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@ name: "OpenAPI: Automated Generate and Push"
on:
repository_dispatch:
types: [generate_publish_release]
workflow_dispatch:
inputs:
payload_json:
description: 'JSON payload (e.g., {"api_versions":"v20111101","version":"patch","commit_sha":"abc123"})'
required: false
type: string

jobs:
Setup:
Expand All @@ -20,12 +14,7 @@ jobs:
- name: Parse payload
id: parse-payload
run: |
# Parse workflow_dispatch payload if provided, otherwise use repository_dispatch payload
if [ -n "${{ github.event.inputs.payload_json }}" ]; then
VERSIONS=$(echo '${{ github.event.inputs.payload_json }}' | jq -r '.api_versions // "v20111101"')
else
VERSIONS="${{ github.event.client_payload.api_versions || 'v20111101' }}"
fi
VERSIONS="${{ github.event.client_payload.api_versions || 'v20111101' }}"
echo "versions_to_generate=$VERSIONS" >> $GITHUB_OUTPUT

- name: Set up matrix
Expand Down Expand Up @@ -74,33 +63,28 @@ jobs:
ruby-version: 3.1
- name: Validate configuration
run: ruby .github/config_validator.rb "${{ matrix.config_file }}" "${{ matrix.api_version }}"

- name: Bump version
id: bump_version
run: |
# Parse version from workflow_dispatch or repository_dispatch
if [ -n "${{ github.event.inputs.payload_json }}" ]; then
VERSION=$(echo '${{ github.event.inputs.payload_json }}' | jq -r '.version // "patch"')
else
VERSION="${{ github.event.client_payload.version || 'patch' }}"
fi
NEW_VERSION=$(ruby .github/version.rb "$VERSION" ${{ matrix.config_file }})
VERSION="${{ github.event.client_payload.version || 'patch' }}"
NEW_VERSION=$(ruby .github/version.rb $VERSION ${{ matrix.config_file }})
echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT

- name: Clean repo
run: ruby .github/clean.rb ${{ matrix.api_version }}

- name: Copy generator ignore rules
run: |
mkdir -p ./${{ matrix.api_version }}/
cp .openapi-generator-ignore ./${{ matrix.api_version }}/

- name: Install openapi-generator-cli
run: npm install @openapitools/openapi-generator-cli -g

- name: Generate SDK
run: |
# Parse commit_sha from workflow_dispatch or repository_dispatch
if [ -n "${{ github.event.inputs.payload_json }}" ]; then
COMMIT_SHA=$(echo '${{ github.event.inputs.payload_json }}' | jq -r '.commit_sha // "master"')
else
COMMIT_SHA="${{ github.event.client_payload.commit_sha || 'master' }}"
fi
COMMIT_SHA="${{ github.event.client_payload.commit_sha || 'master' }}"

# Versioned spec URLs with commit SHA to avoid GitHub CDN cache race condition
# Problem: GitHub's raw.githubusercontent.com CDN caches files for 5 minutes
Expand All @@ -113,11 +97,18 @@ jobs:
-c ${{ matrix.config_file }} \
-t ./openapi/templates \
-o ./${{ matrix.api_version }}
- name: Upload artifacts

- name: Upload SDK artifacts
uses: actions/upload-artifact@v4
with:
name: generated-${{ matrix.api_version }}
path: ./${{ matrix.api_version }}

- name: Upload config artifact
uses: actions/upload-artifact@v4
with:
name: config-${{ matrix.api_version }}
path: ${{ matrix.config_file }}

Process-and-Push:
runs-on: ubuntu-latest
Expand All @@ -128,18 +119,41 @@ jobs:
uses: actions/download-artifact@v4
with:
path: ./generated

- name: Restore config files from artifacts
run: |
# Config files are bumped in the Generate job (separate runner).
# Restore them here so the version bump persists in the commit.
for dir in ./generated/config-*; do
[ -d "$dir" ] || continue
VERSION=$(basename "$dir" | sed 's/config-//')
CONFIG_FILE="openapi/config-${VERSION}.yml"
cp "$dir"/* "./$CONFIG_FILE" 2>/dev/null || echo "Config not found in $dir"
echo "Restored $CONFIG_FILE"
done

# Clean up config artifact directories so they don't get committed
rm -rf ./generated/config-*

- name: Move generated files and track versions
id: track_versions
run: |
GENERATED_VERSIONS=""

for dir in ./generated/generated-*; do
VERSION=$(basename "$dir" | sed 's/generated-//')

# Remove target directory before moving to prevent nesting
if [ -d "./$VERSION" ]; then
rm -rf "./$VERSION"
fi

mv "$dir" "./$VERSION"
GENERATED_VERSIONS="$GENERATED_VERSIONS $VERSION"
done

echo "generated_versions=$GENERATED_VERSIONS" >> $GITHUB_OUTPUT

- name: Update CHANGELOG
run: |
GENERATED_VERSIONS="${{ steps.track_versions.outputs.generated_versions }}"
Expand All @@ -154,6 +168,7 @@ jobs:
# Trim leading/trailing whitespace first
VERSIONS_CSV=$(echo "$GENERATED_VERSIONS" | xargs | tr ' ' ',')
ruby .github/changelog_manager.rb "$VERSIONS_CSV"

- name: Copy documentation
run: |
GENERATED_VERSIONS="${{ steps.track_versions.outputs.generated_versions }}"
Expand All @@ -163,17 +178,46 @@ jobs:
cp CHANGELOG.md "./$VERSION/CHANGELOG.md"
cp MIGRATION.md "./$VERSION/MIGRATION.md"
done

- name: Checkout master
run: git checkout master
- name: Create commit
run: |
git config user.name "devexperience"
git config user.email "devexperience@mx.com"
git add .
git commit -m "Generated SDK versions: ${{ needs.Setup.outputs.versions_to_generate }}
git commit -m "Automated Generated SDK versions: ${{ needs.Setup.outputs.versions_to_generate }}

This commit was automatically created by a GitHub Action."
This commit was automatically created by openapi-generate-and-push GitHub Action."
- name: Push to master
run: git push origin master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# GitHub security feature: pushes using GITHUB_TOKEN don't trigger other workflows.
# We must explicitly trigger on-push-master.yml using a GitHub App token.
- name: Generate access token
id: generate_token
uses: tibdex/github-app-token@v1
with:
app_id: ${{ secrets.PAPI_SDK_APP_ID }}
installation_id: ${{ secrets.PAPI_SDK_INSTALLATION_ID }}
private_key: ${{ secrets.PAPI_SDK_PRIVATE_KEY }}

- name: Trigger publish and release workflow
uses: peter-evans/repository-dispatch@v2
with:
token: ${{ steps.generate_token.outputs.token }}
event-type: automated_push_to_master

- name: Slack notification
uses: ravsamhq/notify-slack-action@v2
if: always()
with:
status: ${{ job.status }}
token: ${{ secrets.GITHUB_TOKEN }}
notification_title: "{repo}: {workflow} workflow"
message_format: "{emoji} *<{workflow_url}|{workflow}>* {status_message} in <{repo_url}|{repo}>"
notify_when: "failure"
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
3 changes: 1 addition & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ jobs:
status: ${{ job.status }}
token: ${{ secrets.GITHUB_TOKEN }}
notification_title: "{repo}: {workflow} workflow"
message_format: "{emoji} *{workflow}* {status_message} in <{repo_url}|{repo}>"
footer: "<{workflow_url}|View Workflow>"
message_format: "{emoji} *<{workflow_url}|{workflow}>* {status_message} in <{repo_url}|{repo}>"
notify_when: "failure"
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
3 changes: 1 addition & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ jobs:
status: ${{ job.status }}
token: ${{ secrets.GITHUB_TOKEN }}
notification_title: "{repo}: {workflow} workflow"
message_format: "{emoji} *{workflow}* {status_message} in <{repo_url}|{repo}>"
footer: "<{workflow_url}|View Workflow>"
message_format: "{emoji} *<{workflow_url}|{workflow}>* {status_message} in <{repo_url}|{repo}>"
notify_when: "failure"
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
8 changes: 6 additions & 2 deletions docs/Adding-a-New-API-Version.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

**Document Purpose**: Step-by-step guide for adding support for a new API version (e.g., `v20300101`) to the mx-platform-node repository.

**Last Updated**: January 29, 2026
**Last Updated**: February 18, 2026
**Time to Complete**: 30-45 minutes
**Prerequisites**: Familiarity with the multi-version architecture (see [Multi-Version-SDK-Flow.md](Multi-Version-SDK-Flow.md))

Expand Down Expand Up @@ -152,6 +152,8 @@ version_directory:

This workflow is automatically triggered by the OpenAPI repository to generate and push SDKs for all versions in parallel.

**Note**: The existing infrastructure handles config file artifact upload/download between Generate and Process-and-Push jobs automatically. You only need to add the version-to-config mapping below — the artifact pipeline will pick up your new config file without additional changes.

**Location 1: Version-to-config mapping**

In the `Setup` job's `Set up matrix` step, find the section with the version-to-config mapping and add an `elif` branch for your new version:
Expand Down Expand Up @@ -228,9 +230,11 @@ on:
- 'v20111101/**'
- 'v20250224/**'
- 'v20300101/**' # NEW
repository_dispatch:
types: [automated_push_to_master] # No changes needed here
```

This ensures the workflow triggers when changes to your version directory are pushed to master.
This ensures the workflow triggers when changes to your version directory are pushed to master. The `repository_dispatch` trigger does not need modification — it is used by `openapi-generate-and-push.yml` to trigger this workflow after automated pushes, and works regardless of which version directories changed.

**Location 3: Add publish job for new version**

Expand Down
6 changes: 3 additions & 3 deletions docs/Multi-Version-SDK-Flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

**Document Purpose**: Quick-reference guide to the multi-version SDK generation, publishing, and release system. This is your entry point to understanding how the system works.

**Last Updated**: January 28, 2026
**Last Updated**: February 18, 2026
**Read Time**: 5-10 minutes
**Audience**: Anyone joining the team or needing a system overview

Expand Down Expand Up @@ -37,7 +37,7 @@ OpenAPI spec changes → `openapi-generate-and-push.yml` generates SDK → commi
**What Happens**:
1. `openapi-generate-and-push.yml` generates all specified versions in parallel
2. All generated files committed to master
3. `on-push-master.yml` automatically triggered by the push
3. `openapi-generate-and-push.yml` sends a `repository_dispatch` event (`automated_push_to_master`) to trigger `on-push-master.yml` (required because `GITHUB_TOKEN` pushes don't trigger other workflows)
4. `on-push-master.yml` handles serial publish/release with version gating

**Key Details**: See [Workflow-and-Configuration-Reference.md](Workflow-and-Configuration-Reference.md#flow-1-automatic-multi-version-generation-repository-dispatch)
Expand Down Expand Up @@ -83,7 +83,7 @@ sequenceDiagram
Gen->>Push: Commit to master<br/>Update CHANGELOG.md
deactivate Gen

Push->>+OnPush: Push event triggers
Push->>+OnPush: repository_dispatch<br/>(automated_push_to_master)
OnPush->>OnPush: Check skip-publish flag
OnPush->>OnPush: Serial: v20111101 publish
OnPush->>npm: npm publish v2.x.x
Expand Down
Loading