Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/actions/test-library-on-nightly/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ inputs:
description: Number of retry attempts for failed operations
required: false
default: '3'
patch-file:
description: Optional path to a patch file to apply after installing the library
required: false
default: ''
runs:
using: composite
steps:
Expand All @@ -19,6 +23,22 @@ runs:
run: |
cd /tmp
npx @react-native-community/cli init RNApp --skip-install --version nightly


- name: Apply patch if specified
if: ${{ inputs.patch-file != '' }}
shell: bash
run: |
if [ -f "$GITHUB_WORKSPACE/${{ inputs.patch-file }}" ]; then
echo "Applying patch: ${{ inputs.patch-file }}"
cd /tmp/RNApp
node "$GITHUB_WORKSPACE/scripts/apply-patch.js" "$GITHUB_WORKSPACE/${{ inputs.patch-file }}"
echo "✅ Patch applied successfully"
else
echo "⚠️ Warning: Patch file not found: ${{ inputs.patch-file }}"
echo "Continuing without patch..."
fi

- name: Add library with retry
uses: nick-fields/retry@v3
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/check-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ jobs:
firebase_app_email: ${{ secrets.FIREBASE_APP_EMAIL }}
firebase_app_pass: ${{ secrets.FIREBASE_APP_PASS }}
firebase_app_projectname: ${{ secrets.FIREBASE_APP_PROJECTNAME }}
firebase_app_apikey: ${{ secrets.FIREBASE_APP_APIKEY }}
firebase_app_apikey: ${{ secrets.FIREBASE_APP_APIKEY }}
3 changes: 2 additions & 1 deletion .github/workflows/test-libraries-on-nightlies.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ jobs:
with:
library-npm-package: ${{ fromJSON(needs.runner-setup.outputs.library-data)[matrix.library].installCommand }}
platform: ${{ matrix.platform }}
patch-file: ${{ fromJSON(needs.runner-setup.outputs.library-data)[matrix.library].patchFile || '' }}
- name: Save outcome
id: save-outcome
if: always()
Expand All @@ -71,7 +72,7 @@ jobs:
with:
name: ${{ steps.save-outcome.outputs.lib_folder }}-${{ matrix.platform }}-outcome
path: /tmp/${{ steps.save-outcome.outputs.lib_folder }}-${{ matrix.platform }}-outcome

collect-results:
runs-on: ubuntu-latest
needs: [test-library-on-nightly]
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ jspm_packages/
!.yarn/releases
!.yarn/sdks
!.yarn/versions


#Tmp Templates
/tmp
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ The repository includes Jest tests for the workflow scripts. To run the tests lo
yarn install && yarn test
```

### Working with Patch Files

Some libraries may require modifications to the React Native template (e.g., editing pod files, manifest files) to work properly with nightly builds. For detailed instructions on creating and applying patch files, see the [Patch Instructions](patch.md) guide.

## 📄 License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
3 changes: 2 additions & 1 deletion libraries.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@
"android": true,
"ios": true,
"maintainersUsernames": [],
"notes": ""
"notes": "",
"patchFile": "patches/reanimated.patch"
},
"react-native-worklets": {
"description": "Powerful multithreading engine",
Expand Down
8 changes: 8 additions & 0 deletions libraries.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@
"Build currently broken due to X reason.",
"One of top most used libraries according to the npm stats."
]
},
"patchFile": {
"type": "string",
"description": "Optional path to a patch file (relative to repo root) to apply after installing the library but before building. Patch should be created using 'git diff --binary' format (e.g., using scripts/make-patch.js).",
"examples": [
"patches/react-native-reanimated.patch",
"patches/library-name-fix.patch"
]
}
},
"required": [
Expand Down
67 changes: 67 additions & 0 deletions patch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Patch Instructions

This guide covers how to generate a patch file for your libraries. This is helpful in cases where you need to edit pod files, manifest files, etc.

## How to Generate a Patch File

### Step 1: Create a New Project

Clone this repository, then create a new project with the following command:

```sh
npx @react-native-community/cli@latest init RNApp --version nightly --skip-install --directory tmp/RNApp
```

### Step 2: Navigate to the Directory

```sh
cd tmp/RNApp
```

### Step 3: Make Necessary Changes

Make the necessary changes to the template.

### Step 4: Generate the Patch File

```sh
node ../../scripts/make-patch.js ../../patches/{libraryName}.patch
```

For example:
```sh
node ../../scripts/make-patch.js ../../patches/react-native-turbo-encryption.patch
```

This will generate a patch file in the patches folder.

**Note:** Remove any lock files like `yarn.lock`, `Podfile.lock`, or any generated files that are tracked before generating the patch file, as these can lead to an excessively long patch file.

### Step 5: Verify the Patch File

```sh
node ../../scripts/apply-patch.js ../../patches/{libraryName}.patch
```
For example:
```sh
node ../../scripts/apply-patch.js ../../patches/react-native-turbo-encryption.patch
```


### Step 6: Add the Patch File to `libraries.json`

```json
"react-native-reanimated": {
"description": "React Native's Animated library reimplemented",
"installCommand": "react-native-reanimated@nightly react-native-worklets@nightly",
"android": true,
"ios": true,
"maintainersUsernames": [],
"notes": "",
"patchFile": "patches/reanimated.patch" # <-- Path to patch file
}
```

### Step 7: Submit Your Changes

Push the changes and create a pull request. Your patch file is ready!
Empty file added patches/.gitkeep
Empty file.
9 changes: 9 additions & 0 deletions patches/reanimated.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
diff --git a/babel.config.js b/babel.config.js
index f7b3da3..8ba8eb6 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -1,3 +1,4 @@
module.exports = {
presets: ['module:@react-native/babel-preset'],
+ plugins: ['react-native-worklets/plugin'],
};
48 changes: 48 additions & 0 deletions scripts/apply-patch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env node
/**
* apply-patch.js
* Applies a patch file to the current directory
*
* Usage:
* node scripts/apply-patch.js <patchfile>
*/

const { execSync } = require("child_process");
const fs = require("fs");
const path = require("path");

// Get patch file from arguments
const patchFile = process.argv[2];

if (!patchFile) {
console.error("Usage: node scripts/apply-patch.js <patchfile>");
console.error("Example: node scripts/apply-patch.js patches/my-fix.patch");
process.exit(1);
}

try {
// Check if we're in a git repository
execSync("git rev-parse --is-inside-work-tree", { stdio: "ignore" });

// Check if patch file exists
const patchPath = path.resolve(process.cwd(), patchFile);
if (!fs.existsSync(patchPath)) {
console.error(`❌ Patch file not found: ${patchPath}`);
process.exit(1);
}

console.log(`Applying patch: ${patchFile}`);

// Apply the patch
execSync(`git apply --binary --3way --whitespace=nowarn "${patchPath}"`, {
stdio: "inherit",
encoding: "utf8"
});

console.log("✅ Patch applied successfully!");

} catch (err) {
console.error("❌ Failed to apply patch");
console.error(err.message);
process.exit(1);
}
55 changes: 55 additions & 0 deletions scripts/make-patch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env node
/**
* make-patch.js
* Creates a patch file from all current changes (staged and unstaged)
*
* Usage:
* node scripts/make-patch.js [output-filename]
*
* If no filename is provided, generates one with timestamp.
*/

const { execSync } = require("child_process");
const fs = require("fs");
const path = require("path");

// Get output filename from args or generate timestamp-based name
const outputFile = process.argv[2] || (() => {
const d = new Date();
const pad = n => String(n).padStart(2, "0");
return `patch-${d.getFullYear()}${pad(d.getMonth()+1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}.patch`;
})();

try {
// Check if we're in a git repository
execSync("git rev-parse --is-inside-work-tree", { stdio: "ignore" });

// Create diff of all changes (staged + unstaged + untracked)
console.log("Creating patch from all changes...");

// Stage untracked files temporarily (without content)
execSync("git add -N .", { stdio: "ignore" });

// Generate the patch
const patch = execSync("git diff HEAD --binary", {
encoding: "utf8",
maxBuffer: 100 * 1024 * 1024 // 100MB buffer
});

if (!patch.trim()) {
console.log("No changes found. Nothing to patch.");
process.exit(0);
}

// Write patch file
const outputPath = path.resolve(process.cwd(), outputFile);
fs.writeFileSync(outputPath, patch, "utf8");

console.log(`✅ Patch created successfully: ${outputPath}`);
console.log(` To apply: node scripts/apply-patch.js ${outputFile}`);

} catch (err) {
console.error("❌ Error creating patch:");
console.error(err.message);
process.exit(1);
}
Loading