diff --git a/actions/android/action.yml b/actions/android/action.yml index 5c4e5a4b..e55bdd5c 100644 --- a/actions/android/action.yml +++ b/actions/android/action.yml @@ -8,6 +8,11 @@ inputs: description: The runner to use required: true type: string + packager: + description: The package manager to use (pnpm, npm, yarn, bun, deno) + required: false + type: string + default: 'pnpm' projectRoot: description: The project root directory required: false @@ -116,7 +121,7 @@ runs: script: | echo $(pwd) adb install -r ${{ inputs.app }} - pnpm react-native-harness --harnessRunner ${{ inputs.runner }} + node ${{ github.action_path }}/../shared/run-harness.cjs "${{ inputs.packager }}" "${{ inputs.runner }}" - name: Upload visual test artifacts if: always() && inputs.uploadVisualTestArtifacts == 'true' uses: actions/upload-artifact@v4 diff --git a/actions/ios/action.yml b/actions/ios/action.yml index 706d573a..0d3b8197 100644 --- a/actions/ios/action.yml +++ b/actions/ios/action.yml @@ -8,6 +8,11 @@ inputs: description: The runner to use required: true type: string + packager: + description: The package manager to use (pnpm, npm, yarn, bun, deno) + required: false + type: string + default: 'pnpm' projectRoot: description: The project root directory required: false @@ -44,7 +49,7 @@ runs: shell: bash working-directory: ${{ inputs.projectRoot }} run: | - pnpm react-native-harness --harnessRunner ${{ inputs.runner }} + node ${{ github.action_path }}/../shared/run-harness.cjs "${{ inputs.packager }}" "${{ inputs.runner }}" - name: Upload visual test artifacts if: always() && inputs.uploadVisualTestArtifacts == 'true' uses: actions/upload-artifact@v4 diff --git a/actions/shared/run-harness.cjs b/actions/shared/run-harness.cjs new file mode 100644 index 00000000..aae18f23 --- /dev/null +++ b/actions/shared/run-harness.cjs @@ -0,0 +1,30 @@ +"use strict"; + +// src/shared/run-harness.ts +var import_node_child_process = require("child_process"); +var [packager, runner] = process.argv.slice(2); +if (!runner) { + console.error("Runner input is required"); + process.exit(1); +} +var commands = { + pnpm: ["pnpm", ["react-native-harness", "--harnessRunner", runner]], + npm: ["npx", ["react-native-harness", "--harnessRunner", runner]], + yarn: ["yarn", ["react-native-harness", "--harnessRunner", runner]], + bun: ["bunx", ["react-native-harness", "--harnessRunner", runner]], + deno: [ + "deno", + ["run", "-A", "npm:react-native-harness", "--harnessRunner", runner] + ] +}; +var key = packager || "pnpm"; +var entry = commands[key]; +if (!entry) { + console.error(`Unsupported packager: ${packager}`); + console.error("Supported packagers: pnpm, npm, yarn, bun, deno"); + process.exit(1); +} +var [cmd, args] = entry; +var child = (0, import_node_child_process.spawn)(cmd, args, { stdio: "inherit" }); +child.on("close", (code) => process.exit(code ?? 1)); +child.on("error", () => process.exit(1)); diff --git a/actions/web/action.yml b/actions/web/action.yml index 5cd40061..9cdb3604 100644 --- a/actions/web/action.yml +++ b/actions/web/action.yml @@ -5,6 +5,11 @@ inputs: description: The runner to use required: true type: string + packager: + description: The package manager to use (pnpm, npm, yarn, bun, deno) + required: false + type: string + default: 'pnpm' projectRoot: description: The project root directory required: false @@ -32,7 +37,7 @@ runs: shell: bash working-directory: ${{ inputs.projectRoot }} run: | - pnpm react-native-harness --harnessRunner ${{ inputs.runner }} + node ${{ github.action_path }}/../shared/run-harness.cjs "${{ inputs.packager }}" "${{ inputs.runner }}" - name: Upload visual test artifacts if: always() && inputs.uploadVisualTestArtifacts == 'true' uses: actions/upload-artifact@v4 diff --git a/packages/github-action/README.md b/packages/github-action/README.md index bc34b692..e44fa5e6 100644 --- a/packages/github-action/README.md +++ b/packages/github-action/README.md @@ -26,6 +26,7 @@ Runs React Native Harness tests on Android emulators. This action handles: - `app` (required): Path to your built Android app (`.apk` file) - `runner` (required): The runner name from your configuration +- `packager` (optional): Package manager to use (`pnpm`, `npm`, `yarn`, `bun`, or `deno`. Defaults to `pnpm`) - `projectRoot` (optional): The project root directory (defaults to repository root) **Requirements:** @@ -43,6 +44,7 @@ Runs React Native Harness tests on Android emulators. This action handles: with: app: './android/app/build/outputs/apk/debug/app-debug.apk' runner: 'android' + packager: 'pnpm' projectRoot: './apps/my-app' ``` @@ -59,6 +61,7 @@ Runs React Native Harness tests on iOS simulators. This action handles: - `app` (required): Path to your built iOS app (`.app` bundle) - `runner` (required): The runner name from your configuration +- `packager` (optional): Package manager to use (`pnpm`, `npm`, `yarn`, `bun` or `deno`. Defaults to `pnpm`) - `projectRoot` (optional): The project root directory (defaults to repository root) **Requirements:** @@ -74,6 +77,7 @@ Runs React Native Harness tests on iOS simulators. This action handles: with: app: './ios/build/Build/Products/Debug-iphonesimulator/MyApp.app' runner: 'ios' + packager: 'pnpm' projectRoot: './apps/my-app' ``` diff --git a/packages/github-action/src/android/action.yml b/packages/github-action/src/android/action.yml index 5c4e5a4b..e55bdd5c 100644 --- a/packages/github-action/src/android/action.yml +++ b/packages/github-action/src/android/action.yml @@ -8,6 +8,11 @@ inputs: description: The runner to use required: true type: string + packager: + description: The package manager to use (pnpm, npm, yarn, bun, deno) + required: false + type: string + default: 'pnpm' projectRoot: description: The project root directory required: false @@ -116,7 +121,7 @@ runs: script: | echo $(pwd) adb install -r ${{ inputs.app }} - pnpm react-native-harness --harnessRunner ${{ inputs.runner }} + node ${{ github.action_path }}/../shared/run-harness.cjs "${{ inputs.packager }}" "${{ inputs.runner }}" - name: Upload visual test artifacts if: always() && inputs.uploadVisualTestArtifacts == 'true' uses: actions/upload-artifact@v4 diff --git a/packages/github-action/src/ios/action.yml b/packages/github-action/src/ios/action.yml index 706d573a..0d3b8197 100644 --- a/packages/github-action/src/ios/action.yml +++ b/packages/github-action/src/ios/action.yml @@ -8,6 +8,11 @@ inputs: description: The runner to use required: true type: string + packager: + description: The package manager to use (pnpm, npm, yarn, bun, deno) + required: false + type: string + default: 'pnpm' projectRoot: description: The project root directory required: false @@ -44,7 +49,7 @@ runs: shell: bash working-directory: ${{ inputs.projectRoot }} run: | - pnpm react-native-harness --harnessRunner ${{ inputs.runner }} + node ${{ github.action_path }}/../shared/run-harness.cjs "${{ inputs.packager }}" "${{ inputs.runner }}" - name: Upload visual test artifacts if: always() && inputs.uploadVisualTestArtifacts == 'true' uses: actions/upload-artifact@v4 diff --git a/packages/github-action/src/shared/run-harness.ts b/packages/github-action/src/shared/run-harness.ts new file mode 100644 index 00000000..6f922edb --- /dev/null +++ b/packages/github-action/src/shared/run-harness.ts @@ -0,0 +1,34 @@ +import { spawn } from 'node:child_process'; + +const [packager, runner] = process.argv.slice(2); + +if (!runner) { + console.error('Runner input is required'); + process.exit(1); +} + +const commands: Record = { + pnpm: ['pnpm', ['react-native-harness', '--harnessRunner', runner]], + npm: ['npx', ['react-native-harness', '--harnessRunner', runner]], + yarn: ['yarn', ['react-native-harness', '--harnessRunner', runner]], + bun: ['bunx', ['react-native-harness', '--harnessRunner', runner]], + deno: [ + 'deno', + ['run', '-A', 'npm:react-native-harness', '--harnessRunner', runner], + ], +}; + +const key = packager || 'pnpm'; +const entry = commands[key]; + +if (!entry) { + console.error(`Unsupported packager: ${packager}`); + console.error('Supported packagers: pnpm, npm, yarn, bun, deno'); + process.exit(1); +} + +const [cmd, args] = entry; +const child = spawn(cmd, args, { stdio: 'inherit' }); + +child.on('close', (code) => process.exit(code ?? 1)); +child.on('error', () => process.exit(1)); diff --git a/packages/github-action/src/web/action.yml b/packages/github-action/src/web/action.yml index 5cd40061..9cdb3604 100644 --- a/packages/github-action/src/web/action.yml +++ b/packages/github-action/src/web/action.yml @@ -5,6 +5,11 @@ inputs: description: The runner to use required: true type: string + packager: + description: The package manager to use (pnpm, npm, yarn, bun, deno) + required: false + type: string + default: 'pnpm' projectRoot: description: The project root directory required: false @@ -32,7 +37,7 @@ runs: shell: bash working-directory: ${{ inputs.projectRoot }} run: | - pnpm react-native-harness --harnessRunner ${{ inputs.runner }} + node ${{ github.action_path }}/../shared/run-harness.cjs "${{ inputs.packager }}" "${{ inputs.runner }}" - name: Upload visual test artifacts if: always() && inputs.uploadVisualTestArtifacts == 'true' uses: actions/upload-artifact@v4 diff --git a/packages/github-action/tsup.config.mts b/packages/github-action/tsup.config.mts index 8d15b463..a42e30e0 100644 --- a/packages/github-action/tsup.config.mts +++ b/packages/github-action/tsup.config.mts @@ -6,15 +6,16 @@ const OUT_DIR = path.resolve('../../actions'); const TARGETS = ['ios', 'android', 'web']; const packageJson = JSON.parse( - fs.readFileSync(path.resolve('./package.json'), 'utf8') + fs.readFileSync(path.resolve('./package.json'), 'utf8'), ); export default defineConfig({ entry: { ...Object.fromEntries( - TARGETS.map((target) => [`${target}/index`, `src/${target}/index.ts`]) + TARGETS.map((target) => [`${target}/index`, `src/${target}/index.ts`]), ), 'shared/index': 'src/shared/index.ts', + 'shared/run-harness': 'src/shared/run-harness.ts', }, outDir: OUT_DIR, format: 'cjs', @@ -28,7 +29,7 @@ export default defineConfig({ TARGETS.forEach((target) => { fs.copyFileSync( path.resolve(`./src/${target}/action.yml`), - path.resolve(OUT_DIR, `./${target}/action.yml`) + path.resolve(OUT_DIR, `./${target}/action.yml`), ); }); }, diff --git a/website/src/docs/guides/ci-cd.md b/website/src/docs/guides/ci-cd.md index 94a77134..5ffc0051 100644 --- a/website/src/docs/guides/ci-cd.md +++ b/website/src/docs/guides/ci-cd.md @@ -38,6 +38,7 @@ Both actions accept the following inputs: - `app` (required): Path to your built app (`.apk` for Android, `.app` for iOS) - `runner` (required): The runner name (e.g., `"android"` or `"ios"`) +- `packager` (optional): Package manager to use (`pnpm`, `npm`, `yarn`, `bun` or `deno`. Defaults to `pnpm`) - `projectRoot` (optional): The project root directory (defaults to the repository root) ## GitHub Actions Example