Skip to content

Commit 1f4771d

Browse files
Merge pull request #1272 from mendix/moo/MOO-2286-docs-pr-automation-updates
[Moo-2286] : Release script fixes to raise PR in docs and NT changelog
2 parents 67f14c3 + 0c78aa9 commit 1f4771d

5 files changed

Lines changed: 163 additions & 57 deletions

File tree

.github/scripts/release-native-template.mjs

Lines changed: 123 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ const STUDIO_PRO_MAJOR = process.env.STUDIO_PRO_MAJOR;
3030
const GIT_AUTHOR_NAME = "MendixMobile";
3131
const GIT_AUTHOR_EMAIL = "moo@mendix.com";
3232

33+
// Native Template Repo Settings
34+
const NT_REPO_OWNER = process.env.GITHUB_REPOSITORY_OWNER;
35+
const NT_REPO_NAME = process.env.GITHUB_REPOSITORY.split("/")[1];
36+
const NT_CHANGELOG_BRANCH_NAME = `update-changelog-v${NATIVE_TEMPLATE_VERSION}`;
37+
3338
// Docs Repo Settings
3439
const DOCS_REPO_NAME = "docs";
3540
const DOCS_REPO_OWNER = "MendixMobile";
@@ -41,6 +46,14 @@ const TARGET_FILE = `${DOCS_PARENT_DIR}/nt-${NATIVE_TEMPLATE_MAJOR}-rn.md`;
4146

4247
const octokit = new Octokit({ auth: MENDIX_MOBILE_DOCS_PR_GITHUB_PAT });
4348

49+
function getToday() {
50+
const today = new Date();
51+
const yyyy = today.getFullYear();
52+
const mm = String(today.getMonth() + 1).padStart(2, "0");
53+
const dd = String(today.getDate()).padStart(2, "0");
54+
return `${yyyy}-${mm}-${dd}`;
55+
}
56+
4457
function extractUnreleasedChangelog() {
4558
const changelogPath = path.resolve(
4659
path.join(__dirname, "..", "..", "CHANGELOG.md"),
@@ -52,19 +65,118 @@ function extractUnreleasedChangelog() {
5265
if (!match) throw new Error("No [Unreleased] section found!");
5366
const unreleasedContent = match[1].trim();
5467
if (!unreleasedContent) throw new Error("No changes under [Unreleased]!");
55-
return unreleasedContent;
68+
return { changelog, unreleasedContent, changelogPath };
5669
}
5770

5871
function buildFrontmatter() {
5972
return `---\ntitle: "Native Template ${NATIVE_TEMPLATE_MAJOR}"\nurl: /releasenotes/mobile/nt-${NATIVE_TEMPLATE_MAJOR}-rn/\nweight: 1\ndescription: "Native Template ${NATIVE_TEMPLATE_MAJOR}"\n---`;
6073
}
6174

75+
// Changelog Update for Native Template Repo
76+
function updateChangelog({ changelog, unreleasedContent, changelogPath }) {
77+
const today = getToday();
78+
const newSection = `## [${NATIVE_TEMPLATE_VERSION}] - ${today}\n\n${unreleasedContent}\n\n`;
79+
const unreleasedRegex =
80+
/^## \[Unreleased\](.*?)(?=^## \[\d+\.\d+\.\d+\][^\n]*|\Z)/ms;
81+
const updatedChangelog = changelog.replace(
82+
unreleasedRegex,
83+
`## [Unreleased]\n\n${newSection}`
84+
);
85+
fs.writeFileSync(changelogPath, updatedChangelog, "utf-8");
86+
}
87+
88+
// Raise a PR to update the CHANGELOG.md in the native-template repo
89+
async function createPRUpdateChangelog() {
90+
const git = simpleGit();
91+
92+
await git.addConfig("user.name", GIT_AUTHOR_NAME, ["--global"]);
93+
await git.addConfig("user.email", GIT_AUTHOR_EMAIL, ["--global"]);
94+
95+
// Get the current branch name (the one selected in GitHub Actions UI)
96+
const currentBranch = process.env.GITHUB_REF_NAME;
97+
if (!currentBranch) {
98+
throw new Error("GITHUB_REF_NAME environment variable is not set");
99+
}
100+
101+
await git.checkoutLocalBranch(NT_CHANGELOG_BRANCH_NAME);
102+
103+
await git.add("CHANGELOG.md");
104+
await git.commit(`chore: update CHANGELOG for v${NATIVE_TEMPLATE_VERSION}`);
105+
await git.push("origin", NT_CHANGELOG_BRANCH_NAME, ["--force"]);
106+
107+
const prBody = `
108+
Automated update of CHANGELOG.md for v${NATIVE_TEMPLATE_VERSION}.
109+
110+
This PR moves the \`[Unreleased]\` section content to a new versioned section \`[${NATIVE_TEMPLATE_VERSION}]\`.
111+
112+
---
113+
114+
**Note:**
115+
This pull request was automatically generated by an automation process managed by the Mobile team.
116+
**Please do not take any action on this pull request unless it has been reviewed and approved by a member of the Mobile team.**
117+
`;
118+
119+
try {
120+
await octokit.pulls.create({
121+
owner: NT_REPO_OWNER,
122+
repo: NT_REPO_NAME,
123+
title: `Update CHANGELOG for v${NATIVE_TEMPLATE_VERSION}`,
124+
head: NT_CHANGELOG_BRANCH_NAME,
125+
base: currentBranch,
126+
body: prBody,
127+
draft: true,
128+
});
129+
console.log("✅ Created PR to update CHANGELOG in native-template");
130+
} catch (err) {
131+
const isPRExistsError =
132+
err.status === 422 &&
133+
(err.message?.includes("A pull request already exists") ||
134+
err.response?.data?.errors?.some(
135+
(e) => e.resource === "PullRequest" && e.message?.includes("A pull request already exists")
136+
));
137+
138+
if (isPRExistsError) {
139+
console.log("ℹ️ PR already exists, updating existing PR...");
140+
const { data: existingPRs } = await octokit.pulls.list({
141+
owner: NT_REPO_OWNER,
142+
repo: NT_REPO_NAME,
143+
head: NT_CHANGELOG_BRANCH_NAME,
144+
base: currentBranch,
145+
state: "open",
146+
});
147+
if (existingPRs.length > 0) {
148+
const existingPR = existingPRs[0];
149+
await octokit.pulls.update({
150+
owner: NT_REPO_OWNER,
151+
repo: NT_REPO_NAME,
152+
pull_number: existingPR.number,
153+
body: prBody,
154+
});
155+
console.log(`✅ Updated existing PR #${existingPR.number}`);
156+
} else {
157+
throw new Error("PR exists but could not be found for update");
158+
}
159+
} else {
160+
throw err;
161+
}
162+
}
163+
}
164+
165+
async function updateNTChangelog(changelog, unreleasedContent, changelogPath) {
166+
try {
167+
updateChangelog({ changelog, unreleasedContent, changelogPath });
168+
await createPRUpdateChangelog();
169+
} catch (err) {
170+
console.error("❌ Updating NT Changelog failed:", err);
171+
process.exit(1);
172+
}
173+
}
174+
62175
// Docs
63176
function injectUnreleasedToDoc(docPath, unreleasedContent) {
64177
if (!fs.existsSync(DOCS_PARENT_DIR)) {
65-
throw new Error(
66-
`Parent directory not found: ${DOCS_PARENT_DIR}\nA new Studio Pro parent folder requires manual setup in the docs repo.`,
67-
);
178+
console.log(`Parent directory not found. Creating: ${DOCS_PARENT_DIR}`);
179+
fs.mkdirSync(DOCS_PARENT_DIR, { recursive: true });
68180
}
69181

70182
const date = new Date();
@@ -99,10 +211,6 @@ function injectUnreleasedToDoc(docPath, unreleasedContent) {
99211
return `${frontmatter}\n\n${beforeReleases}${releaseHeading}\n\n${unreleasedContent}\n\n${releaseSections}`;
100212
}
101213

102-
// This file exists only in the fork (MendixMobile/docs) and not in upstream (mendix/docs).
103-
// Removing it in our branch ensures it doesn't appear in the cross-fork PR diff.
104-
const FORK_SYNC_FILE = ".github/workflows/sync.yml";
105-
106214
async function cloneDocsRepo() {
107215
const git = simpleGit();
108216
const docsCloneDir = fs.mkdtempSync(
@@ -131,10 +239,6 @@ async function updateDocsNTReleaseNotes(unreleasedContent) {
131239
}
132240

133241
async function createPRUpdateDocsNTReleaseNotes(git) {
134-
// Remove the fork's sync.yml so it doesn't appear in the cross-fork PR diff.
135-
if (fs.existsSync(FORK_SYNC_FILE)) {
136-
await git.rm(FORK_SYNC_FILE);
137-
}
138242
await git.add(TARGET_FILE);
139243
await git.commit(
140244
`docs: update mobile release notes for v${NATIVE_TEMPLATE_VERSION}`,
@@ -171,7 +275,7 @@ async function updateNTReleaseNotes(unreleasedContent) {
171275
updateDocsNTReleaseNotes(unreleasedContent);
172276
await createPRUpdateDocsNTReleaseNotes(git);
173277
} catch (err) {
174-
console.error("❌ Updating NT Release Notes failed:", err);
278+
console.error("❌ Updating NT Release Notes in Docs failed:", err);
175279
process.exit(1);
176280
}
177281
}
@@ -185,7 +289,12 @@ function readVersionFromPackageJson() {
185289
}
186290

187291
(async () => {
188-
const unreleasedContent = extractUnreleasedChangelog();
292+
const { changelog, unreleasedContent, changelogPath } =
293+
extractUnreleasedChangelog();
294+
295+
// Update CHANGELOG.md in native-template repo
296+
await updateNTChangelog(changelog, unreleasedContent, changelogPath);
189297

298+
// Update release notes in docs repo
190299
await updateNTReleaseNotes(unreleasedContent);
191300
})();

.github/workflows/publish-changelog-to-docs.yml

Lines changed: 0 additions & 39 deletions
This file was deleted.

.github/workflows/release-it.yml

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ on:
1515
- preminor
1616
- premajor
1717
- prepatch
18+
studio_pro_version:
19+
description: 'Studio Pro major version (determines the docs parent folder for changelog publishing)'
20+
required: true
21+
default: 'Studio Pro 11.x'
22+
type: choice
23+
options:
24+
- 'Studio Pro 10.x'
25+
- 'Studio Pro 11.x'
1826

1927
jobs:
2028
release:
@@ -37,4 +45,19 @@ jobs:
3745
git config --global user.name "github-action"
3846
release-it -VV --increment=${{ github.event.inputs.version }} --ci --github.release --github.draft --git.commitMessage="chore: release v\${version}" --git.tagName="v\${version}"
3947
40-
48+
- name: Sync docs fork with upstream
49+
if: ${{ contains(fromJSON('["patch","minor","major"]'), github.event.inputs.version) }}
50+
run: gh repo sync MendixMobile/docs --branch development --force
51+
env:
52+
GH_TOKEN: ${{ secrets.MENDIX_MOBILE_DOCS_PR_GITHUB_PAT }}
53+
54+
- name: Install docs release script dependencies
55+
if: ${{ contains(fromJSON('["patch","minor","major"]'), github.event.inputs.version) }}
56+
run: npm ci --prefix .github/scripts
57+
58+
- name: Create Changelog PR in native-template and release notes PR in mendix/docs
59+
if: ${{ contains(fromJSON('["patch","minor","major"]'), github.event.inputs.version) }}
60+
env:
61+
MENDIX_MOBILE_DOCS_PR_GITHUB_PAT: ${{ secrets.MENDIX_MOBILE_DOCS_PR_GITHUB_PAT }}
62+
STUDIO_PRO_MAJOR: ${{ github.event.inputs.studio_pro_version == 'Studio Pro 10.x' && '10' || '11' }}
63+
run: node .github/scripts/release-native-template.mjs
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name: Sync Docs Fork Daily
2+
3+
on:
4+
schedule:
5+
- cron: '0 0 * * *' # Daily at midnight UTC
6+
workflow_dispatch: # Allow manual trigger
7+
8+
jobs:
9+
sync:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Sync MendixMobile/docs fork with upstream
13+
run: gh repo sync MendixMobile/docs --branch development --force
14+
env:
15+
GH_TOKEN: ${{ secrets.MENDIX_MOBILE_DOCS_PR_GITHUB_PAT }}

.github/workflows/update_releases_list.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,4 @@ jobs:
5656
5757
A new version of Native Template has been released with updated version compatibility information.
5858
59-
Please review the PR for more details: ${{ github.server_url }}/${{ github.repository }}/pull/${{ steps.pr.outputs.number }}
60-
61-
📝 *Reminder:* Run the <${{ github.server_url }}/${{ github.repository }}/actions/workflows/publish-changelog-to-docs.yml|Publish Changelog to Mendix Docs> workflow to publish the release notes to the docs repo.
59+
Please review the PR for more details: ${{ github.server_url }}/${{ github.repository }}/pull/${{ steps.pr.outputs.number }}

0 commit comments

Comments
 (0)