diff --git a/.github/workflows/generate.yml b/.github/workflows/generate.yml
index 543ecbc..a9362fa 100644
--- a/.github/workflows/generate.yml
+++ b/.github/workflows/generate.yml
@@ -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 }}
@@ -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 }}
diff --git a/.github/workflows/on-push-master.yml b/.github/workflows/on-push-master.yml
index 36ca904..aaee735 100644
--- a/.github/workflows/on-push-master.yml
+++ b/.github/workflows/on-push-master.yml
@@ -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,
@@ -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"
@@ -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:
@@ -40,6 +45,7 @@ jobs:
- uses: dorny/paths-filter@v2
id: filter
with:
+ base: ${{ github.event_name == 'repository_dispatch' && 'HEAD~1' || '' }}
filters: |
v20111101:
- 'v20111101/**'
@@ -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 }}
diff --git a/.github/workflows/openapi-generate-and-push.yml b/.github/workflows/openapi-generate-and-push.yml
index c0bec5b..5b83844 100644
--- a/.github/workflows/openapi-generate-and-push.yml
+++ b/.github/workflows/openapi-generate-and-push.yml
@@ -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:
@@ -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
@@ -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
@@ -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
@@ -128,6 +119,22 @@ 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: |
@@ -135,11 +142,18 @@ jobs:
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 }}"
@@ -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 }}"
@@ -163,6 +178,7 @@ jobs:
cp CHANGELOG.md "./$VERSION/CHANGELOG.md"
cp MIGRATION.md "./$VERSION/MIGRATION.md"
done
+
- name: Checkout master
run: git checkout master
- name: Create commit
@@ -170,10 +186,38 @@ jobs:
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 }}
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index b69c8c4..b801f3a 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -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 }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index c1236f1..d45ebb0 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -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 }}
diff --git a/docs/Adding-a-New-API-Version.md b/docs/Adding-a-New-API-Version.md
index 02b1af1..b713aac 100644
--- a/docs/Adding-a-New-API-Version.md
+++ b/docs/Adding-a-New-API-Version.md
@@ -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))
@@ -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:
@@ -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**
diff --git a/docs/Multi-Version-SDK-Flow.md b/docs/Multi-Version-SDK-Flow.md
index feb9cc2..0fe10d2 100644
--- a/docs/Multi-Version-SDK-Flow.md
+++ b/docs/Multi-Version-SDK-Flow.md
@@ -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
@@ -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)
@@ -83,7 +83,7 @@ sequenceDiagram
Gen->>Push: Commit to master
Update CHANGELOG.md
deactivate Gen
- Push->>+OnPush: Push event triggers
+ Push->>+OnPush: repository_dispatch
(automated_push_to_master)
OnPush->>OnPush: Check skip-publish flag
OnPush->>OnPush: Serial: v20111101 publish
OnPush->>npm: npm publish v2.x.x
diff --git a/docs/Troubleshooting-Guide.md b/docs/Troubleshooting-Guide.md
index 0764c4b..d59aa02 100644
--- a/docs/Troubleshooting-Guide.md
+++ b/docs/Troubleshooting-Guide.md
@@ -2,7 +2,7 @@
**Document Purpose**: Quick reference for diagnosing and fixing issues in the multi-version SDK generation, publishing, and release workflows.
-**Last Updated**: January 29, 2026
+**Last Updated**: February 18, 2026
**Audience**: Developers debugging workflow failures
---
@@ -289,6 +289,33 @@ fatal: A release with this tag already exists
---
+### Generated Files Placed in Nested Subdirectory
+
+**Symptom**: After automated generation, SDK files appear at `v20111101/generated-v20111101/api.ts` instead of `v20111101/api.ts`
+
+**Cause**: The `Process-and-Push` job in `openapi-generate-and-push.yml` downloads generated artifacts and moves them into the version directory. If the version directory already exists (from a prior commit), `mv` places the source *inside* the existing directory as a subdirectory rather than replacing it.
+
+**Solution**: Already fixed in `openapi-generate-and-push.yml`. The workflow now runs `rm -rf ./$VERSION` before `mv` to ensure the target directory doesn't exist, so the move replaces rather than nests. If you see this issue, verify the workflow includes the `rm -rf` step before the `mv` command in the Process-and-Push job.
+
+---
+
+### Version Bump Not Applied During Automated Generation
+
+**Symptom**: Automated generation completes but the version in `package.json` didn't increment (stays at the previous version)
+
+**Cause**: The `version.rb` script argument was quoted incorrectly in the workflow. Passing `"$VERSION"` (with surrounding quotes in the shell script) causes bash to pass the literal string `$VERSION` instead of its value, so `version.rb` receives an unrecognized bump type and silently fails.
+
+**Solution**: Already fixed in `openapi-generate-and-push.yml`. The `$VERSION` variable is now passed unquoted to `version.rb`. If you see this issue, verify the workflow calls `version.rb` with `$VERSION` (not `"$VERSION"`):
+```bash
+# Correct
+NEW_VERSION=$(ruby .github/version.rb $VERSION ${{ matrix.config_file }})
+
+# Wrong — passes literal string
+NEW_VERSION=$(ruby .github/version.rb "$VERSION" ${{ matrix.config_file }})
+```
+
+---
+
### Workflow Not Triggering on Push
**Symptom**: Merged a PR with changes to `v20111101/` directory, but `on-push-master.yml` didn't run
@@ -298,6 +325,7 @@ fatal: A release with this tag already exists
- Changes were not actually in the version directory
- Commit was made to wrong branch
- Workflow file has syntax error
+- (Automated flow only) The push was made with `GITHUB_TOKEN`, which does not trigger `push` events for other workflows
**Solutions**:
1. Verify path filter syntax is correct:
@@ -308,6 +336,8 @@ fatal: A release with this tag already exists
paths:
- 'v20111101/**' # Correct format
- 'v20250224/**'
+ repository_dispatch:
+ types: [automated_push_to_master]
```
2. Check what files were actually changed:
```bash
@@ -322,6 +352,7 @@ fatal: A release with this tag already exists
```bash
ruby -e "require 'yaml'; puts YAML.load(File.read('.github/workflows/on-push-master.yml'))"
```
+5. **For automated flows**: Verify that `openapi-generate-and-push.yml` sends a `repository_dispatch` event after pushing. The `push` trigger only works for manual PR merges. Automated pushes from workflows use `GITHUB_TOKEN`, which does not trigger other workflows — the generate workflow must send an explicit `repository_dispatch` (type: `automated_push_to_master`) using a GitHub App token.
---
@@ -347,6 +378,36 @@ git commit -m "Migrate SDK structure skip-publish"
---
+### Skip-Publish Check Fails with Bash Error
+
+**Symptom**: The `check-skip-publish` step in `on-push-master.yml` errors with something like `SDK: command not found` (exit code 127), and downstream jobs skip unexpectedly
+
+**Cause**: The commit message contains double quotes (e.g., `Revert "Generated SDK versions: v20111101"`). If the workflow uses inline `${{ }}` interpolation to assign the commit message, the inner quotes close the outer quotes in bash, causing the remaining text to be interpreted as commands.
+
+**Example of broken pattern**:
+```yaml
+# BROKEN - double quotes in commit message break this
+COMMIT_MSG="${{ github.event.head_commit.message }}"
+```
+
+**Solution**: The workflow should use an `env:` block to pass the commit message safely:
+```yaml
+- name: Check for [skip-publish] flag in commit message
+ id: check
+ env:
+ COMMIT_MSG: ${{ github.event.head_commit.message }}
+ run: |
+ if [[ "$COMMIT_MSG" == *"[skip-publish]"* ]]; then
+ echo "skip_publish=true" >> $GITHUB_OUTPUT
+ else
+ echo "skip_publish=false" >> $GITHUB_OUTPUT
+ fi
+```
+
+This fix is already applied to `on-push-master.yml`. If you see this error, verify that the workflow is using the `env:` block pattern and not inline interpolation.
+
+---
+
### Version.rb Script Errors
#### Error: "Version directory parameter required"
diff --git a/docs/Workflow-and-Configuration-Reference.md b/docs/Workflow-and-Configuration-Reference.md
index 8090f04..2ceb769 100644
--- a/docs/Workflow-and-Configuration-Reference.md
+++ b/docs/Workflow-and-Configuration-Reference.md
@@ -2,7 +2,7 @@
**Document Purpose**: Detailed technical reference for the multi-version SDK generation, publishing, and release workflows. Covers implementation details, configuration files, and system architecture.
-**Last Updated**: January 29, 2026
+**Last Updated**: February 18, 2026
**Audience**: Developers who need to understand or modify the implementation
---
@@ -81,14 +81,21 @@ strategy:
6. **Upload Artifacts**
- Upload generated SDK to workflow artifact storage
+ - Upload bumped config file as separate artifact (config file version bump happens on Generate runner, but Process-and-Push runs on a different runner with a fresh checkout — without this, the version bump would be lost)
- Allows atomic multi-version commit after all matrix jobs complete
#### Step 3: Post-Generation Processing (After All Matrix Jobs Complete)
1. **Download Artifacts**
- Retrieve generated SDKs for all versions from artifact storage
+ - Retrieve config file artifacts and restore them to `openapi/` directory
+ - Clean up config artifact directories (`rm -rf ./generated/config-*`) to prevent them from being committed
-2. **Track Generated Versions**
+2. **Move Generated Files to Version Directories**
+ - Remove existing version directory contents before moving: `rm -rf ./$VERSION` then `mv` generated files into place
+ - This prevents the generated files from being placed in a nested subdirectory (e.g., `v20111101/generated-v20111101/` instead of `v20111101/`)
+
+3. **Track Generated Versions**
- Record which directories were actually generated
- Used by CHANGELOG automation to add entries only for generated versions
@@ -129,7 +136,11 @@ strategy:
#### Step 5: Automatic Publish and Release (via on-push-master.yml)
-**Architecture**: After `Process-and-Push` completes and pushes to master, the automatic `on-push-master.yml` workflow is triggered by GitHub's push event.
+**Architecture**: After `Process-and-Push` completes and pushes to master, it explicitly triggers `on-push-master.yml` via a `repository_dispatch` event (type: `automated_push_to_master`).
+
+**Why `repository_dispatch` instead of relying on the push event?** GitHub's security model prevents workflows triggered by `GITHUB_TOKEN` from triggering other workflows. Since `openapi-generate-and-push.yml` pushes to master using `GITHUB_TOKEN`, that push does **not** trigger `on-push-master.yml`'s `push` event. To solve this, `openapi-generate-and-push.yml` generates a GitHub App token (via `tibdex/github-app-token@v1`) and uses it to send a `repository_dispatch` event (via `peter-evans/repository-dispatch@v2`), which does trigger `on-push-master.yml`.
+
+**Note**: The `push` trigger on `on-push-master.yml` still exists and works for manual PR merges — only automated pushes from workflows need the `repository_dispatch` workaround.
**Why This Architecture?**
- Separates concerns: `openapi-generate-and-push.yml` owns generation, `on-push-master.yml` owns publishing
@@ -137,7 +148,7 @@ strategy:
- Prevents duplicate publishes: Manual generate.yml + PR merge only triggers publish once (via on-push-master.yml)
**Process** (handled by `on-push-master.yml`):
-1. Detect-changes job uses `dorny/paths-filter@v2` to identify which version directories changed (v20111101/**, v20250224/**)
+1. Detect-changes job uses `dorny/paths-filter@v2` to identify which version directories changed (v20111101/**, v20250224/**). For `repository_dispatch` events, uses `base: HEAD~1` to compare against the previous commit (push events use default `before`/`after` automatically).
2. Check-skip-publish job detects if `[skip-publish]` flag is in commit message
3. For each version with path changes (output by detect-changes):
- Publish job: Call `publish.yml` with version-specific directory (only if paths modified)
@@ -339,8 +350,13 @@ publish-v20250224:
-### Trigger
-Push to `master` branch with changes in version-specific directories (`v20111101/**` or `v20250224/**`)
+### Triggers
+
+`on-push-master.yml` responds to two trigger types:
+1. **`push`** — activated when changes are pushed to `master` (e.g., PR merges)
+2. **`repository_dispatch`** (type: `automated_push_to_master`) — activated by `openapi-generate-and-push.yml` after it pushes generated SDK files to master (needed because `GITHUB_TOKEN` pushes don't trigger `push` events for other workflows)
+
+Both triggers require changes in version-specific directories (`v20111101/**` or `v20250224/**`) to proceed to publishing.
### Skip-Publish Safety Mechanism
Include `[skip-publish]` in commit message to prevent publish/release for this push.
@@ -358,15 +374,21 @@ Include `[skip-publish]` in commit message to prevent publish/release for this p
**Job**: `check-skip-publish`
```yaml
-- name: Check for skip-publish flag
+- name: Check for [skip-publish] flag in commit message
+ id: check
+ env:
+ COMMIT_MSG: ${{ github.event.head_commit.message }}
run: |
- if [[ "${{ github.event.head_commit.message }}" == *"[skip-publish]"* ]]; then
+ if [[ "$COMMIT_MSG" == *"[skip-publish]"* ]]; then
echo "skip_publish=true" >> $GITHUB_OUTPUT
+ echo "🚫 [skip-publish] flag detected - skipping all publish/release jobs"
else
echo "skip_publish=false" >> $GITHUB_OUTPUT
+ echo "✅ No skip flag - proceeding with publish/release"
fi
```
+- Uses `env:` block to safely pass commit message (avoids bash errors when commit messages contain double quotes — e.g., `Revert "Generated SDK versions: v20111101"` would break inline `${{ }}` interpolation)
- Parses HEAD commit message
- Sets output: `skip_publish` = true/false
- Used by subsequent jobs to determine execution
@@ -454,6 +476,22 @@ If v20250224 jobs depended directly on v20111101's publish job, the workflow wou
---
+## Slack Failure Notifications
+
+All workflows send Slack notifications on failure to the channel configured via `SLACK_WEBHOOK_URL`. Notifications include a clickable link to the specific failed workflow run URL for quick diagnosis.
+
+| Workflow | Notification Scope |
+|----------|--------------------|
+| `openapi-generate-and-push.yml` | Generate job failures, Process-and-Push job failures |
+| `on-push-master.yml` | Orchestration job failures (check-skip-publish, detect-changes, delay). Publish/release jobs have their own notifications via `publish.yml` and `release.yml`. |
+| `generate.yml` | Generation failures |
+| `publish.yml` | Publish failures |
+| `release.yml` | Release failures |
+
+**Message format**: The workflow name in Slack messages links directly to the failed run URL, making it easy to jump straight to the failing step without navigating through the GitHub Actions UI.
+
+---
+
## Supporting Scripts
### version.rb - Multi-Version Support
@@ -643,8 +681,12 @@ on:
# - 'openapi/**' (config changes alone)
# - 'docs/**' (documentation changes)
# - 'README.md' (root documentation)
+ repository_dispatch:
+ types: [automated_push_to_master] # Triggered by openapi-generate-and-push.yml
```
+The `repository_dispatch` trigger is required because automated pushes from `openapi-generate-and-push.yml` use `GITHUB_TOKEN`, which does not trigger `push` events for other workflows (GitHub security feature). The generate workflow sends this dispatch explicitly using a GitHub App token.
+
**Benefits**:
- Enhancement PRs (docs only) don't trigger publish
- Workflow file changes don't trigger publish
@@ -680,6 +722,8 @@ The repository uses **semantic versioning with major version = API version**:
| `NPM_AUTH_TOKEN` | publish.yml | Authenticate to npm registry for publishing |
| `GITHUB_TOKEN` | All workflows | GitHub API access (auto-provided by GitHub Actions) |
| `SLACK_WEBHOOK_URL` | All workflows | Send failure notifications to Slack |
+| `APP_ID` | openapi-generate-and-push.yml | GitHub App ID for generating tokens that can trigger cross-workflow events |
+| `APP_PRIVATE_KEY` | openapi-generate-and-push.yml | GitHub App private key (used with `tibdex/github-app-token@v1` to create tokens for `repository_dispatch`) |
### Environment Setup
@@ -706,13 +750,15 @@ openapi-generate-and-push.yml: Triggered
├─ Download artifacts
├─ Update CHANGELOG.md
├─ Commit to master
- ├─ Push to master (triggers on-push-master.yml)
+ ├─ Push to master
+ ├─ Send repository_dispatch (automated_push_to_master)
↓
-on-push-master.yml: Triggered (push event)
+on-push-master.yml: Triggered (repository_dispatch)
├─ check-skip-publish: Verify no [skip-publish] flag
+ ├─ detect-changes: paths-filter with base: HEAD~1
├─ publish-v20111101: npm publish (path filter matched)
├─ release-v20111101: Create tag v2.0.1 (after publish)
- ├─ publish-v20250224: npm publish (serialized, after v20111101 release)
+ ├─ publish-v20250224: npm publish (serialized, after delay)
├─ release-v20250224: Create tag v3.0.1 (after publish)
↓
Result: Both versions published and released sequentially, CHANGELOG updated