Skip to content

Commit 7c7db8d

Browse files
committed
chore: add notify doc changes action
1 parent c164b6e commit 7c7db8d

1 file changed

Lines changed: 196 additions & 0 deletions

File tree

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
name: Notify Docs Consumers
2+
3+
# Notifies downstream repositories (MCP server, agent skills, etc.) whenever
4+
# documentation changes are merged, so they can update their own content if relevant.
5+
#
6+
# Each target repository must have a workflow listening for the
7+
# `medusa-docs-updated` repository_dispatch event. The event's `client_payload`
8+
# contains the commit link, sha, message, and the list of changed docs files.
9+
10+
on:
11+
push:
12+
branches:
13+
- develop
14+
paths:
15+
- "www/apps/book/**"
16+
- "www/apps/resources/**"
17+
- "www/apps/ui/**"
18+
- "www/apps/user-guide/**"
19+
- "www/apps/cloud/**"
20+
- "www/apps/api-reference/**"
21+
workflow_dispatch:
22+
inputs:
23+
commit_sha:
24+
description: "Commit SHA to notify the downstream repositories about"
25+
required: true
26+
type: string
27+
28+
concurrency:
29+
group: notify-docs-consumers
30+
cancel-in-progress: false
31+
32+
jobs:
33+
collect:
34+
name: Collect docs changes
35+
runs-on: ubuntu-latest
36+
outputs:
37+
commit_sha: ${{ steps.changes.outputs.commit_sha }}
38+
commit_url: ${{ steps.changes.outputs.commit_url }}
39+
commit_message: ${{ steps.changes.outputs.commit_message }}
40+
changed_files: ${{ steps.changes.outputs.changed_files }}
41+
has_changes: ${{ steps.changes.outputs.has_changes }}
42+
steps:
43+
- name: Checkout repository
44+
uses: actions/checkout@v4
45+
with:
46+
fetch-depth: 0
47+
48+
- name: Collect changed documentation files
49+
id: changes
50+
env:
51+
COMMIT_SHA: ${{ github.event.inputs.commit_sha || github.sha }}
52+
run: |
53+
node --input-type=module << 'EOF'
54+
import { execFileSync } from "child_process"
55+
import { appendFileSync } from "fs"
56+
57+
const sha = execFileSync("git", ["rev-parse", process.env.COMMIT_SHA], {
58+
encoding: "utf8",
59+
}).trim()
60+
const message = execFileSync("git", ["log", "-1", "--pretty=%s", sha], {
61+
encoding: "utf8",
62+
}).trim()
63+
64+
// Files changed by the commit. Merge commits are diffed against their
65+
// first parent, which is the state of `develop` before the merge.
66+
// Renames are reported as a delete + an add so that consumers are told
67+
// about the path that went away, not only the one that replaced it.
68+
const diff = execFileSync(
69+
"git",
70+
[
71+
"diff-tree",
72+
"--no-commit-id",
73+
"--name-status",
74+
"--no-renames",
75+
"-m",
76+
"--first-parent",
77+
"-r",
78+
sha,
79+
],
80+
{ encoding: "utf8" }
81+
)
82+
83+
const docsApps = [
84+
"book",
85+
"resources",
86+
"ui",
87+
"user-guide",
88+
"cloud",
89+
"api-reference",
90+
]
91+
const seen = new Set()
92+
const files = diff
93+
.split("\n")
94+
.filter(Boolean)
95+
.map((line) => {
96+
const [status, path] = line.split("\t")
97+
// "A" (added), "M" (modified), or "D" (deleted)
98+
return { status, path }
99+
})
100+
.filter(({ path }) => {
101+
if (!path || seen.has(path)) {
102+
return false
103+
}
104+
seen.add(path)
105+
return docsApps.some((app) => path.startsWith(`www/apps/${app}/`))
106+
})
107+
108+
// `client_payload` is limited in size, so only send a capped list.
109+
const MAX_FILES = 100
110+
const cappedFiles = files.slice(0, MAX_FILES)
111+
if (files.length > MAX_FILES) {
112+
console.log(
113+
`Capping changed files list at ${MAX_FILES} (${files.length} changed).`
114+
)
115+
}
116+
117+
const outputs = {
118+
commit_sha: sha,
119+
commit_url: `https://github.com/${process.env.GITHUB_REPOSITORY}/commit/${sha}`,
120+
commit_message: message,
121+
changed_files: JSON.stringify(cappedFiles),
122+
has_changes: files.length > 0 ? "true" : "false",
123+
}
124+
125+
appendFileSync(
126+
process.env.GITHUB_OUTPUT,
127+
Object.entries(outputs)
128+
.map(([key, value]) => `${key}<<__EOF__\n${value}\n__EOF__`)
129+
.join("\n") + "\n"
130+
)
131+
132+
console.log(`Commit: ${sha}`)
133+
console.log(`Changed docs files: ${files.length}`)
134+
EOF
135+
136+
notify:
137+
name: Notify ${{ matrix.repo }}
138+
needs: collect
139+
if: ${{ needs.collect.outputs.has_changes == 'true' }}
140+
runs-on: ubuntu-latest
141+
strategy:
142+
fail-fast: false
143+
matrix:
144+
# Add downstream repositories here (names only — they are all under the
145+
# `medusajs` org). Each one needs a workflow listening for the
146+
# `medusa-docs-updated` repository_dispatch event, and the Medusa GitHub
147+
# App must be installed on it.
148+
repo:
149+
- medusa-mcp
150+
- medusa-agent-skills
151+
steps:
152+
# Same app as the issue/PR triage workflows. Unlike those, `owner` and
153+
# `repositories` are set explicitly: the action defaults to the current
154+
# repository, which cannot dispatch to another one. Scoping the token to
155+
# the single repo of this matrix leg keeps it minimally privileged.
156+
- name: Generate GitHub App token
157+
id: app-token
158+
uses: actions/create-github-app-token@v1
159+
with:
160+
app-id: ${{ secrets.MEDUSA_APP_ID }}
161+
private-key: ${{ secrets.MEDUSA_APP_PRIVATE_KEY }}
162+
owner: ${{ github.repository_owner }}
163+
repositories: ${{ matrix.repo }}
164+
165+
- name: Send repository dispatch
166+
env:
167+
# Needs the `Contents: write` repository permission.
168+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
169+
TARGET_REPO: ${{ github.repository_owner }}/${{ matrix.repo }}
170+
COMMIT_SHA: ${{ needs.collect.outputs.commit_sha }}
171+
COMMIT_URL: ${{ needs.collect.outputs.commit_url }}
172+
COMMIT_MESSAGE: ${{ needs.collect.outputs.commit_message }}
173+
CHANGED_FILES: ${{ needs.collect.outputs.changed_files }}
174+
run: |
175+
payload=$(jq -n \
176+
--arg sha "$COMMIT_SHA" \
177+
--arg url "$COMMIT_URL" \
178+
--arg message "$COMMIT_MESSAGE" \
179+
--arg repository "$GITHUB_REPOSITORY" \
180+
--argjson changed_files "$CHANGED_FILES" \
181+
'{
182+
event_type: "medusa-docs-updated",
183+
client_payload: {
184+
repository: $repository,
185+
commit_sha: $sha,
186+
commit_url: $url,
187+
commit_message: $message,
188+
changed_files: $changed_files
189+
}
190+
}')
191+
192+
echo "$payload" | gh api "repos/$TARGET_REPO/dispatches" \
193+
--method POST \
194+
--input -
195+
196+
echo "Dispatched medusa-docs-updated to $TARGET_REPO for $COMMIT_URL"

0 commit comments

Comments
 (0)