mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-22 14:48:11 +00:00
android: derive release notes from changelog
This commit is contained in:
@@ -30,7 +30,9 @@ const PUBLIC_EXTENSION_CONTRACT_RE =
|
||||
*/
|
||||
export const RELEASE_METADATA_PATHS = new Set([
|
||||
"CHANGELOG.md",
|
||||
"apps/android/CHANGELOG.md",
|
||||
"apps/android/Config/Version.properties",
|
||||
"apps/android/fastlane/metadata/android/en-US/release_notes.txt",
|
||||
"apps/android/version.json",
|
||||
"apps/ios/CHANGELOG.md",
|
||||
"apps/ios/Config/Version.xcconfig",
|
||||
|
||||
@@ -46,7 +46,9 @@ const LINTABLE_CORE_PATH_RE = /^(?:src|ui|packages)\/.+\.[cm]?[jt]sx?$/u;
|
||||
const CORE_LINT_OPTIMIZATION_NEUTRAL_PATH_RE =
|
||||
/^(?:scripts|test\/scripts)\/|^\.github\/workflows\/ci\.yml$/u;
|
||||
const ANDROID_VERSION_SYNC_PATHS = new Set([
|
||||
"apps/android/CHANGELOG.md",
|
||||
"apps/android/Config/Version.properties",
|
||||
"apps/android/fastlane/metadata/android/en-US/release_notes.txt",
|
||||
"apps/android/version.json",
|
||||
]);
|
||||
let corepackPnpmShimDir;
|
||||
|
||||
@@ -4,7 +4,9 @@ import path from "node:path";
|
||||
import { parseReleaseVersion } from "./npm-publish-plan.mjs";
|
||||
|
||||
const ANDROID_VERSION_FILE = "apps/android/version.json";
|
||||
const ANDROID_CHANGELOG_FILE = "apps/android/CHANGELOG.md";
|
||||
const ANDROID_VERSION_PROPERTIES_FILE = "apps/android/Config/Version.properties";
|
||||
const ANDROID_RELEASE_NOTES_FILE = "apps/android/fastlane/metadata/android/en-US/release_notes.txt";
|
||||
const ANDROID_VERSION_CODE_MAX = 2_100_000_000;
|
||||
|
||||
type AndroidVersionManifest = {
|
||||
@@ -14,6 +16,8 @@ type AndroidVersionManifest = {
|
||||
|
||||
export type ResolvedAndroidVersion = {
|
||||
canonicalVersion: string;
|
||||
changelogPath: string;
|
||||
releaseNotesPath: string;
|
||||
versionCode: number;
|
||||
versionFilePath: string;
|
||||
versionPropertiesPath: string;
|
||||
@@ -161,13 +165,17 @@ export function writeAndroidVersionManifest(
|
||||
|
||||
export function resolveAndroidVersion(rootDir = path.resolve(".")): ResolvedAndroidVersion {
|
||||
const versionFilePath = path.join(rootDir, ANDROID_VERSION_FILE);
|
||||
const changelogPath = path.join(rootDir, ANDROID_CHANGELOG_FILE);
|
||||
const versionPropertiesPath = path.join(rootDir, ANDROID_VERSION_PROPERTIES_FILE);
|
||||
const releaseNotesPath = path.join(rootDir, ANDROID_RELEASE_NOTES_FILE);
|
||||
const manifest = readAndroidVersionManifest(rootDir);
|
||||
const canonicalVersion = normalizePinnedAndroidVersion(manifest.version ?? "");
|
||||
const versionCode = normalizeAndroidVersionCode(manifest.versionCode, canonicalVersion);
|
||||
|
||||
return {
|
||||
canonicalVersion,
|
||||
changelogPath,
|
||||
releaseNotesPath,
|
||||
versionCode,
|
||||
versionFilePath,
|
||||
versionPropertiesPath,
|
||||
@@ -178,6 +186,51 @@ export function renderAndroidVersionProperties(version: ResolvedAndroidVersion):
|
||||
return `# Shared Android version defaults.\n# Source of truth: apps/android/version.json\n# Generated by scripts/android-sync-versioning.ts.\n\nOPENCLAW_ANDROID_VERSION_NAME=${version.canonicalVersion}\nOPENCLAW_ANDROID_VERSION_CODE=${version.versionCode}\n`;
|
||||
}
|
||||
|
||||
function matchChangelogHeading(line: string, heading: string): boolean {
|
||||
const normalized = line.trim();
|
||||
return normalized === `## ${heading}` || normalized.startsWith(`## ${heading} - `);
|
||||
}
|
||||
|
||||
export function extractChangelogSection(content: string, heading: string): string | null {
|
||||
const lines = content.split(/\r?\n/u);
|
||||
const startIndex = lines.findIndex((line) => matchChangelogHeading(line, heading));
|
||||
if (startIndex === -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let endIndex = lines.length;
|
||||
for (let index = startIndex + 1; index < lines.length; index += 1) {
|
||||
if (lines[index]?.startsWith("## ")) {
|
||||
endIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const body = lines
|
||||
.slice(startIndex + 1, endIndex)
|
||||
.join("\n")
|
||||
.trim();
|
||||
return body || null;
|
||||
}
|
||||
|
||||
export function renderAndroidReleaseNotes(
|
||||
version: ResolvedAndroidVersion,
|
||||
changelogContent: string,
|
||||
): string {
|
||||
const candidateHeadings = [version.canonicalVersion, "Unreleased"];
|
||||
|
||||
for (const heading of candidateHeadings) {
|
||||
const body = extractChangelogSection(changelogContent, heading);
|
||||
if (body) {
|
||||
return `${body}\n`;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Unable to find Android changelog notes for ${version.canonicalVersion}. Add a matching section to ${ANDROID_CHANGELOG_FILE}.`,
|
||||
);
|
||||
}
|
||||
|
||||
function syncFile(params: {
|
||||
mode: SyncAndroidVersioningMode;
|
||||
path: string;
|
||||
@@ -207,7 +260,9 @@ export function syncAndroidVersioning(params?: {
|
||||
const mode = params?.mode ?? "write";
|
||||
const rootDir = path.resolve(params?.rootDir ?? ".");
|
||||
const version = resolveAndroidVersion(rootDir);
|
||||
const changelogContent = readFileSync(version.changelogPath, "utf8");
|
||||
const nextVersionProperties = renderAndroidVersionProperties(version);
|
||||
const nextReleaseNotes = renderAndroidReleaseNotes(version, changelogContent);
|
||||
const updatedPaths: string[] = [];
|
||||
|
||||
if (
|
||||
@@ -221,5 +276,16 @@ export function syncAndroidVersioning(params?: {
|
||||
updatedPaths.push(version.versionPropertiesPath);
|
||||
}
|
||||
|
||||
if (
|
||||
syncFile({
|
||||
mode,
|
||||
path: version.releaseNotesPath,
|
||||
nextContent: nextReleaseNotes,
|
||||
label: "Android release notes",
|
||||
})
|
||||
) {
|
||||
updatedPaths.push(version.releaseNotesPath);
|
||||
}
|
||||
|
||||
return { updatedPaths };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user