diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 62d2cffd..f0b896cc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,6 +10,16 @@ Depending on your needs, you may need to install CocoaPods in the example React After contributing your changes, please make sure to add a [changeset](https://github.com/changesets/changesets) describing your changes. This will help us in publishing new versions. +### Pre-commit guard for brownfield-navigation + + This is a monorepo and the files inside `@callstack/brownfield-navigation` are auto-generated whenever `brownfield:package:*` is run. This is a desired behavior for the end user as these files will be inside the `node_modules`. However, since in this repo this package is symlinked, we see the changes in our git tree. + +These should not be committed by accident. A `pre-commit` guard blocks commits when those generated files are staged. + +If you need to intentionally commit those files (for an explicit update), bypass the guard for that commit: + +`SKIP_BROWNFIELD_NAVIGATION_CHECK=1 git commit -m "..."` + ## Publishing to npm We use [changesets](https://github.com/changesets/changesets) to make it easier to publish new versions. It handles common tasks like bumping version based on semver, creating tags and releases etc. diff --git a/apps/RNApp/ios/Podfile.lock b/apps/RNApp/ios/Podfile.lock index 90fc0f1b..552d7bd9 100644 --- a/apps/RNApp/ios/Podfile.lock +++ b/apps/RNApp/ios/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - BrownfieldNavigation (3.8.1): + - BrownfieldNavigation (3.12.0): - hermes-engine - RCTRequired - RCTTypeSafety @@ -21,7 +21,7 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - Brownie (3.8.1): + - Brownie (3.12.0): - hermes-engine - RCTRequired - RCTTypeSafety @@ -1803,7 +1803,7 @@ PODS: - ReactNativeDependencies - ReactAppDependencyProvider (0.85.0): - ReactCodegen - - ReactBrownfield (3.8.1): + - ReactBrownfield (3.12.0): - hermes-engine - RCTRequired - RCTTypeSafety @@ -2174,10 +2174,10 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/yoga" SPEC CHECKSUMS: - BrownfieldNavigation: 6bab41701e536267009b77cf6dc6a8a509db1f4a - Brownie: c0b61f2fd916a0bcb6b4918b49aa3eebec5e1cd6 + BrownfieldNavigation: eb4f0937d1f5d81f97bcccaea57484913a7e83e1 + Brownie: 9d58df8e6fbc0c7f01968df81370af2207e76e16 FBLazyVector: c00c20551d40126351a6783c47ce75f5b374851b - hermes-engine: 891a8d77b6705a5c71992a8f3eaf2bfc2cfb1dda + hermes-engine: 133acc7688f66a6db232bff7de874c7129b01e1e RCTDeprecation: 3bb167081b134461cfeb875ff7ae1945f8635257 RCTRequired: 74839f55d5058a133a0bc4569b0afec750957f64 RCTSwiftUI: 87a316382f3eab4dd13d2a0d0fd2adcce917361a @@ -2186,7 +2186,7 @@ SPEC CHECKSUMS: React: 1b1536b9099195944034e65b1830f463caaa8390 React-callinvoker: 6dff6d17d1d6cc8fdf85468a649bafed473c65f5 React-Core: 00faa4d038298089a1d5a5b21dde8660c4f0820d - React-Core-prebuilt: ca4f822f6813ee31e20a965602ed5bbe611a003d + React-Core-prebuilt: 46fad9d85d53619a69cbd91fa8703ce085c73c29 React-CoreModules: a17807f849bfd86045b0b9a75ec8c19373b482f6 React-cxxreact: c7b53ace5827be54048288bce5c55f337c41e95f React-debug: 1f20c32441d0090cf67e6b966895f4ccd929d84c @@ -2246,10 +2246,10 @@ SPEC CHECKSUMS: React-utils: f747ea9fa3f4b293533ec4ef7976d1e37f004ef8 React-webperformancenativemodule: cf676ba871cc4b6ae175f75b92e8c689960c4141 ReactAppDependencyProvider: 5787b37b8e2e51dfeab697ec031cc7c4080dcea2 - ReactBrownfield: 9acfec561aae66f2adbf6faa451a0712b17a38b2 + ReactBrownfield: 3e3d19d1f8859299826e72a87976bb9525f378c8 ReactCodegen: d9ba64702c846111b3eeb157ea2e15aa5bb2ea55 ReactCommon: fe2a3af8975e63efa60f95fca8c34dc85deee360 - ReactNativeDependencies: 94375812b438d76ddfa8937a75fbb59cc0cd8fff + ReactNativeDependencies: bf5d16ce034aaabeeb0f7102f7db739529a3b910 RNScreens: 85c533985720c563272c6f6dd19e1278dfd0f5d4 Yoga: ce94692032f0a4e4ca7ed9e52a284cb208fcdbbb diff --git a/lefthook.yml b/lefthook.yml index f55eb961..5823dad2 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -1,6 +1,9 @@ pre-commit: parallel: true commands: + brownfield-navigation-drift: + run: node --experimental-strip-types --no-warnings ./scripts/check-brownfield-navigation-drift.ts + lint: glob: '*.{js,ts,jsx,tsx}' run: yarn lint diff --git a/scripts/check-brownfield-navigation-drift.ts b/scripts/check-brownfield-navigation-drift.ts new file mode 100644 index 00000000..f270c212 --- /dev/null +++ b/scripts/check-brownfield-navigation-drift.ts @@ -0,0 +1,71 @@ +import path from 'node:path'; +import { execFileSync } from 'node:child_process'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const REPO_ROOT = path.resolve(__dirname, '..'); +const SKIP_ENV_VAR = 'SKIP_BROWNFIELD_NAVIGATION_CHECK'; + +const PROTECTED_GENERATED_FILES = [ + 'packages/brownfield-navigation/src/NativeBrownfieldNavigation.ts', + 'packages/brownfield-navigation/src/index.ts', + 'packages/brownfield-navigation/lib/commonjs/index.js', + 'packages/brownfield-navigation/lib/module/index.js', + 'packages/brownfield-navigation/lib/typescript/commonjs/src/index.d.ts', + 'packages/brownfield-navigation/lib/typescript/module/src/index.d.ts', + 'packages/brownfield-navigation/ios/BrownfieldNavigationDelegate.swift', + 'packages/brownfield-navigation/ios/BrownfieldNavigationModels.swift', + 'packages/brownfield-navigation/ios/NativeBrownfieldNavigation.mm', + 'packages/brownfield-navigation/android/src/main/java/com/callstack/nativebrownfieldnavigation/BrownfieldNavigationDelegate.kt', + 'packages/brownfield-navigation/android/src/main/java/com/callstack/nativebrownfieldnavigation/BrownfieldNavigationModels.kt', + 'packages/brownfield-navigation/android/src/main/java/com/callstack/nativebrownfieldnavigation/NativeBrownfieldNavigationModule.kt', +]; + +function readStagedFiles(repoRoot: string): string[] { + const output = execFileSync( + 'git', + ['diff', '--cached', '--name-only', '--diff-filter=ACMR'], + { + cwd: repoRoot, + encoding: 'utf8', + } + ); + + return output + .split('\n') + .map((filePath) => filePath.trim()) + .filter(Boolean); +} + +function main(): void { + if (process.env[SKIP_ENV_VAR] === '1') { + console.log( + `${SKIP_ENV_VAR}=1 set, skipping brownfield navigation generated file check` + ); + return; + } + + const protectedFiles = new Set(PROTECTED_GENERATED_FILES); + const stagedProtectedFiles = readStagedFiles(REPO_ROOT).filter((filePath) => + protectedFiles.has(filePath) + ); + + if (stagedProtectedFiles.length === 0) { + return; + } + + console.error( + [ + 'Commit blocked: generated brownfield-navigation files are staged.', + '', + 'These files are generated by brownfield navigation codegen and should not be committed accidentally:', + ...stagedProtectedFiles.map((filePath) => `- ${filePath}`), + '', + `If this change is intentional, bypass once with: ${SKIP_ENV_VAR}=1 git commit -m "..."`, + ].join('\n') + ); + process.exit(1); +} + +main();