Skip to content

Commit 153a9ae

Browse files
Merge pull request #789 from midnightntwrk/release-notes-ci
Release notes workflow
2 parents 1817b72 + 168ed90 commit 153a9ae

12 files changed

+401
-98
lines changed
Lines changed: 359 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,359 @@
1+
# Copy release notes from product repositories into midnight-docs (similar to apis.yml).
2+
# Trigger manually; pick the component and either:
3+
# - provide `source_url` (recommended, supports GitHub release/tag/blob URLs), or
4+
# - provide `source_path` + branch for clone-based copy.
5+
#
6+
# Extend: add a `component` option, matching `branch_*` input, clone step, and a branch in the case statement
7+
# in "Map component → paths" and "Update DynamicList*".
8+
9+
name: Copy release notes
10+
11+
on:
12+
workflow_dispatch:
13+
inputs:
14+
branch_merge:
15+
description: 'Destination branch on midnight-docs'
16+
default: 'main'
17+
component:
18+
description: 'Which product repo / DynamicList to update'
19+
type: choice
20+
options:
21+
- wallet
22+
- ledger
23+
- compact
24+
- midnight-js
25+
- node
26+
- midnight-indexer
27+
- dapp-connector-api
28+
- compact-js
29+
branch_wallet:
30+
description: 'wallet: branch'
31+
default: 'main'
32+
branch_ledger:
33+
description: 'ledger: branch'
34+
default: 'main'
35+
branch_compact:
36+
description: 'compact: branch'
37+
default: 'release/midnight'
38+
branch_midnight_js:
39+
description: 'midnight-js: branch'
40+
default: 'main'
41+
branch_node:
42+
description: 'node: branch'
43+
default: 'main'
44+
branch_midnight_indexer:
45+
description: 'midnight-indexer: branch'
46+
default: 'main'
47+
branch_dapp_connector_api:
48+
description: 'dapp-connector-api: branch'
49+
default: 'main'
50+
branch_compact_js:
51+
description: 'compact-js: branch/tag (e.g. cjs-2.5.0)'
52+
default: 'cjs-2.5.0'
53+
source_url:
54+
description: 'Optional source URL to release notes (supports raw.githubusercontent.com and github.com release/tag/blob/tree URLs)'
55+
required: false
56+
default: ''
57+
type: string
58+
source_path:
59+
description: 'Optional path to the release notes .md inside the cloned repo (used when source_url is empty)'
60+
required: false
61+
default: ''
62+
type: string
63+
version:
64+
description: 'Version for DynamicList (e.g. 2.0.0 or v2.0.0)'
65+
required: true
66+
type: string
67+
compact_language_version:
68+
description: "Only when component is compact: language version (e.g. v0.22.0 or 0.22.0). Ignored for other components."
69+
required: false
70+
default: ''
71+
type: string
72+
pr_title:
73+
description: 'PR title'
74+
default: 'Copy release notes from product repository'
75+
76+
permissions:
77+
contents: write
78+
pull-requests: write
79+
80+
jobs:
81+
copy_release_notes:
82+
runs-on: ubuntu-latest
83+
steps:
84+
- name: Checkout midnight-docs
85+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
86+
with:
87+
path: ${{ github.workspace }}
88+
ref: ${{ github.event.inputs.branch_merge }}
89+
90+
- name: Git config
91+
run: |
92+
git config --global user.email "midnight-ci@users.noreply.github.com"
93+
git config --global user.name "Midnight CI GitHub Action"
94+
git config --global url.https://${{ secrets.GH_TOKEN }}@github.com/.insteadOf https://github.com/
95+
96+
- name: Clone wallet
97+
if: ${{ github.event.inputs.component == 'wallet' }}
98+
run: |
99+
mkdir -p ./temp && cd ./temp
100+
git clone --branch "$WALLET_BRANCH" https://github.com/midnightntwrk/midnight-wallet.git
101+
env:
102+
WALLET_BRANCH: ${{ github.event.inputs.branch_wallet }}
103+
104+
- name: Clone ledger
105+
if: ${{ github.event.inputs.component == 'ledger' }}
106+
run: |
107+
mkdir -p ./temp && cd ./temp
108+
git clone --branch "$LEDGER_BRANCH" https://github.com/midnightntwrk/midnight-ledger.git
109+
env:
110+
LEDGER_BRANCH: ${{ github.event.inputs.branch_ledger }}
111+
112+
- name: Clone compact
113+
if: ${{ github.event.inputs.component == 'compact' }}
114+
run: |
115+
mkdir -p ./temp && cd ./temp
116+
git clone --branch "$COMPACT_BRANCH" https://github.com/LFDT-Minokawa/compact/
117+
env:
118+
COMPACT_BRANCH: ${{ github.event.inputs.branch_compact }}
119+
120+
- name: Clone midnight-js
121+
if: ${{ github.event.inputs.component == 'midnight-js' }}
122+
run: |
123+
mkdir -p ./temp && cd ./temp
124+
git clone --branch "$MIDNIGHT_JS_BRANCH" https://github.com/midnightntwrk/midnight-js.git
125+
env:
126+
MIDNIGHT_JS_BRANCH: ${{ github.event.inputs.branch_midnight_js }}
127+
128+
- name: Clone node
129+
if: ${{ github.event.inputs.component == 'node' }}
130+
run: |
131+
mkdir -p ./temp && cd ./temp
132+
git clone --branch "$NODE_BRANCH" https://github.com/midnightntwrk/midnight-node.git
133+
env:
134+
NODE_BRANCH: ${{ github.event.inputs.branch_node }}
135+
136+
- name: Clone midnight-indexer
137+
if: ${{ github.event.inputs.component == 'midnight-indexer' }}
138+
run: |
139+
mkdir -p ./temp && cd ./temp
140+
git clone --branch "$MIDNIGHT_INDEXER_BRANCH" https://github.com/midnightntwrk/midnight-indexer.git
141+
env:
142+
MIDNIGHT_INDEXER_BRANCH: ${{ github.event.inputs.branch_midnight_indexer }}
143+
144+
- name: Clone dapp-connector-api
145+
if: ${{ github.event.inputs.component == 'dapp-connector-api' }}
146+
run: |
147+
mkdir -p ./temp && cd ./temp
148+
git clone --branch "$DAPP_CONNECTOR_API_BRANCH" https://github.com/midnightntwrk/midnight-dapp-connector-api.git
149+
env:
150+
DAPP_CONNECTOR_API_BRANCH: ${{ github.event.inputs.branch_dapp_connector_api }}
151+
152+
- name: Clone compact-js
153+
if: ${{ github.event.inputs.component == 'compact-js' }}
154+
run: |
155+
mkdir -p ./temp && cd ./temp
156+
git clone --branch "$COMPACT_JS_BRANCH" https://github.com/midnightntwrk/midnight-sdk.git
157+
env:
158+
COMPACT_JS_BRANCH: ${{ github.event.inputs.branch_compact_js }}
159+
160+
- name: Copy release notes into docs
161+
id: copy
162+
run: |
163+
set -euo pipefail
164+
COMPONENT="$COMPONENT"
165+
SRC_REL="$SRC_REL"
166+
SRC_URL="$SRC_URL"
167+
SRC=""
168+
169+
# Resolve source: URL (preferred) or clone path.
170+
if [ -n "$SRC_URL" ]; then
171+
mkdir -p temp
172+
TMP_SOURCE="temp/source-release-notes.md"
173+
RAW_URL="$SRC_URL"
174+
case "$SRC_URL" in
175+
https://raw.githubusercontent.com/*)
176+
RAW_URL="$SRC_URL"
177+
;;
178+
https://github.com/*/releases/tag/*)
179+
# Fetch release notes body from GitHub Releases API.
180+
OWNER_REPO=$(echo "$SRC_URL" | sed -E 's|^https://github.com/([^/]+/[^/]+)/releases/tag/.*$|\1|')
181+
TAG=$(echo "$SRC_URL" | sed -E 's|^https://github.com/[^/]+/[^/]+/releases/tag/(.*)$|\1|')
182+
gh api "repos/${OWNER_REPO}/releases/tags/${TAG}" --jq '.body' > "$TMP_SOURCE"
183+
;;
184+
https://github.com/*/blob/*)
185+
RAW_URL=$(echo "$SRC_URL" | sed -E 's|^https://github.com/([^/]+/[^/]+)/blob/([^/]+)/(.*)$|https://raw.githubusercontent.com/\1/\2/\3|')
186+
;;
187+
https://github.com/*/tree/*)
188+
# Used by compact-js style URLs. Build RELEASE_NOTES.md from repo/tree root.
189+
TREE_RAW=$(echo "$SRC_URL" | sed -E 's|^https://github.com/([^/]+/[^/]+)/tree/([^/]+)/(.*)$|https://raw.githubusercontent.com/\1/\2/\3|')
190+
RAW_URL="${TREE_RAW}/RELEASE_NOTES.md"
191+
;;
192+
esac
193+
curl -fsSL "$RAW_URL" -o "$TMP_SOURCE"
194+
SRC="$TMP_SOURCE"
195+
fi
196+
197+
if [ -z "$SRC" ] && [ -z "$SRC_REL" ]; then
198+
echo "One of source_url or source_path is required."
199+
exit 1
200+
fi
201+
202+
if [ -z "$SRC" ]; then
203+
# Repo folder name after clone (must match clone URLs above)
204+
case "$COMPONENT" in
205+
wallet) REPO_DIR="midnight-wallet" ;;
206+
ledger) REPO_DIR="midnight-ledger" ;;
207+
compact) REPO_DIR="compact" ;;
208+
midnight-js) REPO_DIR="midnight-js" ;;
209+
node) REPO_DIR="midnight-node" ;;
210+
midnight-indexer) REPO_DIR="midnight-indexer" ;;
211+
dapp-connector-api) REPO_DIR="midnight-dapp-connector-api" ;;
212+
compact-js) REPO_DIR="midnight-sdk" ;;
213+
*) echo "Unknown component: $COMPONENT"; exit 1 ;;
214+
esac
215+
SRC="temp/${REPO_DIR}/${SRC_REL}"
216+
fi
217+
if [ ! -f "$SRC" ]; then
218+
echo "Source file not found: $SRC"
219+
exit 1
220+
fi
221+
BASENAME_INPUT="${SRC_REL:-$SRC_URL}"
222+
BASENAME=$(basename "$BASENAME_INPUT")
223+
BASENAME="${BASENAME%.md}"
224+
BASENAME="${BASENAME%.mdx}"
225+
BASENAME="${BASENAME%/}"
226+
BASENAME="${BASENAME//./-}"
227+
BASENAME="${BASENAME//_/-}"
228+
BASENAME=$(echo "$BASENAME" | sed -E 's/^-+//; s/-+$//')
229+
if [ -z "$BASENAME" ] || [ "$BASENAME" = "source-release-notes" ] || [ "$BASENAME" = "release-notes" ] || [ "$BASENAME" = "RELEASE-NOTES" ]; then
230+
BASENAME="${COMPONENT}-$VERSION"
231+
BASENAME="${BASENAME#v}"
232+
BASENAME="${BASENAME//./-}"
233+
fi
234+
case "$COMPONENT" in
235+
wallet) DEST_DIR="docs/relnotes/wallet" ;;
236+
ledger) DEST_DIR="docs/relnotes/ledger" ;;
237+
compact) DEST_DIR="docs/relnotes/compact" ;;
238+
midnight-js) DEST_DIR="docs/relnotes/midnight-js" ;;
239+
node) DEST_DIR="docs/relnotes/node" ;;
240+
midnight-indexer) DEST_DIR="docs/relnotes/midnight-indexer" ;;
241+
dapp-connector-api) DEST_DIR="docs/relnotes/dapp-connector-api" ;;
242+
compact-js) DEST_DIR="docs/relnotes/compact-js" ;;
243+
esac
244+
mkdir -p "$DEST_DIR"
245+
cp "$SRC" "${DEST_DIR}/${BASENAME}.mdx"
246+
echo "relnotes_subdir=$(basename "$DEST_DIR")" >> "$GITHUB_OUTPUT"
247+
echo "slug=$BASENAME" >> "$GITHUB_OUTPUT"
248+
echo "Copied $SRC -> ${DEST_DIR}/${BASENAME}.mdx"
249+
env:
250+
COMPONENT: ${{ github.event.inputs.component }}
251+
VERSION: ${{ github.event.inputs.version }}
252+
SRC_REL: ${{ github.event.inputs.source_path }}
253+
SRC_URL: ${{ github.event.inputs.source_url }}
254+
255+
- name: Update DynamicList component file
256+
run: |
257+
set -euo pipefail
258+
COMPONENT="$COMPONENT"
259+
VERSION_RAW="$VERSION_RAW"
260+
VERSION="${VERSION_RAW#v}"
261+
SLUG="$SLUG"
262+
SUBDIR="$SUBDIR"
263+
TODAY=$(date +'%d %B %Y')
264+
265+
case "$COMPONENT" in
266+
wallet) DYNAMIC_LIST="src/components/DynamicListWallet.js" ;;
267+
ledger) DYNAMIC_LIST="src/components/DynamicListLedger.js" ;;
268+
compact) DYNAMIC_LIST="src/components/DynamicListCompact.js" ;;
269+
midnight-js) DYNAMIC_LIST="src/components/DynamicListMidnightJS.js" ;;
270+
node) DYNAMIC_LIST="src/components/DynamicListNode.js" ;;
271+
midnight-indexer) DYNAMIC_LIST="src/components/DynamicListMidnightIndexer.js" ;;
272+
dapp-connector-api) DYNAMIC_LIST="src/components/DynamicListDappConnectorAPI.js" ;;
273+
compact-js) DYNAMIC_LIST="src/components/DynamicListCompactJS.js" ;;
274+
*) echo "Unknown component"; exit 1 ;;
275+
esac
276+
277+
sed -i "s/status: 'LATEST'/status: 'UNSUPPORTED'/" "$DYNAMIC_LIST"
278+
279+
if [ "$COMPONENT" = "compact" ]; then
280+
if [ -z "$LANG_RAW" ]; then
281+
echo "compact_language_version is required when component is compact"
282+
exit 1
283+
fi
284+
COMPACT_VER="${LANG_RAW#v}"
285+
NEW_ENTRY=" {\n\
286+
version: '${VERSION}',\n\
287+
compactVersion: '${COMPACT_VER}',\n\
288+
status: 'LATEST',\n\
289+
date: '${TODAY}',\n\
290+
summary: 'Summary of Release ${VERSION}',\n\
291+
details: [],\n\
292+
artifacts: [],\n\
293+
link: '/relnotes/${SUBDIR}/${SLUG}',\n\
294+
},"
295+
else
296+
NEW_ENTRY=" {\n\
297+
version: '${VERSION}',\n\
298+
status: 'LATEST',\n\
299+
date: '${TODAY}',\n\
300+
summary: 'Summary of Release ${VERSION}',\n\
301+
details: [],\n\
302+
artifacts: [],\n\
303+
link: '/relnotes/${SUBDIR}/${SLUG}',\n\
304+
},"
305+
fi
306+
307+
sed -i "/^const releases = \[$/a\\${NEW_ENTRY}" "$DYNAMIC_LIST"
308+
echo "Updated $DYNAMIC_LIST"
309+
env:
310+
COMPONENT: ${{ github.event.inputs.component }}
311+
VERSION_RAW: ${{ github.event.inputs.version }}
312+
SLUG: ${{ steps.copy.outputs.slug }}
313+
SUBDIR: ${{ steps.copy.outputs.relnotes_subdir }}
314+
LANG_RAW: ${{ github.event.inputs.compact_language_version }}
315+
316+
- name: Prepare branch
317+
id: prep
318+
run: |
319+
rm -rf ./temp
320+
BRANCH="relnotes/$(date +'%Y-%m-%dT%H%M%S')-$COMPONENT"
321+
git checkout -b "$BRANCH"
322+
if git diff --quiet && git diff --cached --quiet; then
323+
echo "No changes (unexpected)"
324+
exit 1
325+
fi
326+
echo "NEW_BRANCH=$BRANCH" >> "$GITHUB_OUTPUT"
327+
echo "UPDATE=true" >> "$GITHUB_OUTPUT"
328+
git add -A
329+
git push -u origin "$BRANCH"
330+
env:
331+
GH_TOKEN: ${{ secrets.GH_TOKEN }}
332+
COMPONENT: ${{ github.event.inputs.component }}
333+
334+
- uses: planetscale/ghcommit-action@25309d8005ac7c3bcd61d3fe19b69e0fe47dbdde # v0.2.20
335+
if: ${{ steps.prep.outputs.UPDATE == 'true' }}
336+
with:
337+
commit_message: "Copy release notes for ${{ github.event.inputs.component }}"
338+
repo: ${{ github.repository }}
339+
branch: ${{ steps.prep.outputs.NEW_BRANCH }}
340+
env:
341+
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
342+
343+
- name: Create PR
344+
if: ${{ steps.prep.outputs.UPDATE == 'true' }}
345+
run: |
346+
gh pr create \
347+
--base "$BRANCH_MERGE" \
348+
--head "$NEW_BRANCH" \
349+
--title "$PR_TITLE" \
350+
--body "Automated release notes copy — component: \`$COMPONENT\`, source_url: \`$SOURCE_URL\`, source_path: \`$SOURCE_PATH\`, version: \`$VERSION\`."
351+
env:
352+
GH_TOKEN: ${{ secrets.GH_TOKEN }}
353+
PR_TITLE: ${{ github.event.inputs.pr_title }}
354+
BRANCH_MERGE: ${{ github.event.inputs.branch_merge }}
355+
NEW_BRANCH: ${{ steps.prep.outputs.NEW_BRANCH }}
356+
COMPONENT: ${{ github.event.inputs.component }}
357+
SOURCE_URL: ${{ github.event.inputs.source_url }}
358+
SOURCE_PATH: ${{ github.event.inputs.source_path }}
359+
VERSION: ${{ github.event.inputs.version }}

src/components/DynamicListCompactJS.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import { useLocation } from '@docusaurus/router';
1717

1818
const releases = [
1919
{
20-
id: 1,
2120
version: '2.4.0',
2221
status: 'LATEST',
2322
date: '28 January 2026',
@@ -33,6 +32,10 @@ const releases = [
3332
}
3433
];
3534

35+
releases.forEach((release, index) => {
36+
release.id = index + 1;
37+
});
38+
3639
// Ensure versions are sorted with the latest at the top
3740
const sortedVersions = releases
3841
.map(release => release.version)

0 commit comments

Comments
 (0)