From fadad7264be2d881ecd0f4b51930cbbcecc8a67b Mon Sep 17 00:00:00 2001 From: Revopush Date: Thu, 15 Oct 2026 15:54:38 +0300 Subject: [PATCH] Upgrade Prettier to 3 and check formatting in CI - Keep trailingComma "es5" so Prettier 3 formats the code as before - Format the three files that had drifted - Add a format:check script and run it in the lint job Co-Authored-By: Claude Opus 5.5 --- .github/workflows/CI.yaml | 3 +++ package-lock.json | 13 +++++++------ package.json | 3 ++- prettier.config.js | 2 ++ script/binary-utils.ts | 10 +++++++--- script/command-executor.ts | 12 +++++------- script/utils/gradle-utils.ts | 22 ++++++++++++++-------- 7 files changed, 40 insertions(+), 25 deletions(-) diff --git a/.github/workflows/CI.yaml b/.github/workflows/CI.yaml index bb12fdd..a02bcfb 100644 --- a/.github/workflows/CI.yaml +++ b/.github/workflows/CI.yaml @@ -62,3 +62,6 @@ jobs: - name: Lint run: npm run lint + + - name: Check formatting + run: npm run format:check diff --git a/package-lock.json b/package-lock.json index 2a43d42..127bdca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,7 +47,7 @@ "@typescript-eslint/parser": "^6.0.0", "eslint": "^8.45.0", "mocha": "^12.0.1", - "prettier": "^2.8.8", + "prettier": "^3.9.10", "sinon": "15.1.2", "superagent-mock": "^4.0.0", "typescript": "^5.1.3" @@ -2822,15 +2822,16 @@ } }, "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.10.tgz", + "integrity": "sha512-skGHTH1Yb9QvaTC4hWnRTzEYtCpApF0UMBPz+t/0ZPzP8ihefo/btKd+QA7pUE0fEwA1SbS/NmhyEcstdXOIdA==", "dev": true, + "license": "MIT", "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" diff --git a/package.json b/package.json index 536b272..eb9e0e7 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "pretest": "node -e \"require('fs').rmSync('bin', { recursive: true, force: true })\"", "test": "tsc && node -e \"require('fs').cpSync('test/resources', 'bin/test/resources', { recursive: true })\" && mocha", "prettier": "prettier --write \"./**/*.ts\"", + "format:check": "prettier --check \"script/**/*.ts\" \"test/**/*.ts\"", "lint": "eslint \"script/**/*.ts\" \"test/**/*.ts\"", "lint:fix": "eslint \"script/**/*.ts\" \"test/**/*.ts\" --fix" }, @@ -68,7 +69,7 @@ "@typescript-eslint/parser": "^6.0.0", "eslint": "^8.45.0", "mocha": "^12.0.1", - "prettier": "^2.8.8", + "prettier": "^3.9.10", "sinon": "15.1.2", "superagent-mock": "^4.0.0", "typescript": "^5.1.3" diff --git a/prettier.config.js b/prettier.config.js index 19c0012..4ae264e 100644 --- a/prettier.config.js +++ b/prettier.config.js @@ -4,4 +4,6 @@ module.exports = { printWidth: 135, endOfLine: "auto", + // Prettier 3 defaults to "all"; keep the existing style + trailingComma: "es5", }; diff --git a/script/binary-utils.ts b/script/binary-utils.ts index ded5a54..45422ce 100644 --- a/script/binary-utils.ts +++ b/script/binary-utils.ts @@ -9,7 +9,7 @@ import * as yauzl from "yauzl"; import { readFile } from "node:fs/promises"; import { buffer as readStreamToBuffer } from "node:stream/consumers"; import * as protobuf from "protobufjs"; -import * as plist from "plist" +import * as plist from "plist"; import * as bplist from "bplist-parser"; export async function extractMetadataFromAndroid(extractFolder, outputFolder) { @@ -219,13 +219,17 @@ const AAB_MANIFEST_ENTRY_NAME = "base/manifest/AndroidManifest.xml"; // An AAB's is protobuf-encoded as an aapt.pb.XmlNode. We only read a // few attributes, so we declare just that slice (field numbers from AOSP // aapt2/Resources.proto); the decoder skips every field we omit. -const XmlNode = protobuf.parse(` +const XmlNode = protobuf + .parse( + ` syntax = "proto3"; package aapt.pb; message XmlAttribute { string name = 2; string value = 3; } message XmlElement { string name = 3; repeated XmlAttribute attribute = 4; } message XmlNode { XmlElement element = 1; } -`).root.lookupType("aapt.pb.XmlNode"); +` + ) + .root.lookupType("aapt.pb.XmlNode"); async function readManifestAttributes(file: string | Buffer): Promise { const zipFile = typeof file === "string" ? await yauzl.openPromise(file) : await yauzl.fromBufferPromise(file); diff --git a/script/command-executor.ts b/script/command-executor.ts index 584185d..27d9cdd 100644 --- a/script/command-executor.ts +++ b/script/command-executor.ts @@ -1050,8 +1050,7 @@ async function patch(command: cli.IPatchCommand): Promise { // Standard fields use null as "not provided"; buildNumber uses undefined (null means reset). // Check both to avoid treating an unset buildNumber (undefined) as a valid update. - const hasUpdate = - Object.values(packageInfo).some((v) => v !== null && v !== undefined) || command.buildNumber !== undefined; + const hasUpdate = Object.values(packageInfo).some((v) => v !== null && v !== undefined) || command.buildNumber !== undefined; if (!hasUpdate) { throw new Error("At least one property must be specified to patch a release."); @@ -1169,10 +1168,7 @@ interface ReactReleaseInputs { // Up-front validation for the React-style release flows (release-react / release-expo). // Throws on the first violation and returns the derived inputs. The semver-range check // is done by the caller since it needs the resolved app version. -function validateReactReleaseCommand( - command: cli.IReleaseReactCommand, - options: { resolveEntryFile: boolean } -): ReactReleaseInputs { +function validateReactReleaseCommand(command: cli.IReleaseReactCommand, options: { resolveEntryFile: boolean }): ReactReleaseInputs { const { resolveEntryFile } = options; const platform: string = (command.platform = command.platform.toLowerCase()); @@ -1194,7 +1190,9 @@ function validateReactReleaseCommand( try { projectPackageJson = require(path.join(process.cwd(), "package.json")); } catch (error) { - throw new Error('Unable to find or read "package.json" in the CWD. The command must be executed in a React Native project folder.'); + throw new Error( + 'Unable to find or read "package.json" in the CWD. The command must be executed in a React Native project folder.' + ); } const projectName: string = projectPackageJson.name; diff --git a/script/utils/gradle-utils.ts b/script/utils/gradle-utils.ts index aa70e0c..62788bc 100644 --- a/script/utils/gradle-utils.ts +++ b/script/utils/gradle-utils.ts @@ -33,7 +33,8 @@ const FALLBACK_HINT = "Pass the version explicitly with --targetBinaryVersion to // "revopush"-prefixed to avoid collisions with project tasks; written in Groovy, // which Gradle accepts as an init script for projects of either DSL. const PRINT_VERSION_TASK = "_revopushPrintVersion"; -const printVersionInitScript = (moduleName: string) => ` +const printVersionInitScript = (moduleName: string) => + ` allprojects { afterEvaluate { proj -> if (proj.name == '${moduleName}') { @@ -68,10 +69,12 @@ export async function getAndroidVersionInfo(gradleFile?: string | null): Promise const appVersion = resolveAppVersion(versionName, buildFile); const buildNumber = resolveBuildNumber(versionCode, buildFile); if (!buildNumber) { - console.log(chalk.yellow( - `Warning: Unable to read "android.defaultConfig.versionCode" from "${buildFile}". ` + - `This is expected if it is set dynamically (e.g. on CI). Pass --buildNumber explicitly to include it in the release.` - )); + console.log( + chalk.yellow( + `Warning: Unable to read "android.defaultConfig.versionCode" from "${buildFile}". ` + + `This is expected if it is set dynamically (e.g. on CI). Pass --buildNumber explicitly to include it in the release.` + ) + ); } return { appVersion, buildNumber }; } @@ -135,7 +138,10 @@ async function parseGroovyDslBuildFile(buildFile: string): Promise { function getLegacyReactProperty(parsed: any, key: string): string | undefined { const entries: string[] = parsed["project.ext.react"] || []; const entry = entries.map((prop) => prop.replace(/\/\/.*$/gm, "").trim()).find((prop) => prop.startsWith(`${key}:`)); - return entry?.slice(key.length + 1).trim().replace(/^["']|["']$/g, ""); + return entry + ?.slice(key.length + 1) + .trim() + .replace(/^["']|["']$/g, ""); } async function parseGroovyDslVersion(buildFile: string): Promise { @@ -146,7 +152,7 @@ async function parseGroovyDslVersion(buildFile: string): Promise