From 1fe0817e648e61ad1da381464bebb6a6a20a0af9 Mon Sep 17 00:00:00 2001 From: Alexande B Date: Thu, 3 Oct 2024 15:13:05 +0200 Subject: [PATCH] tools: reuse __scripts__/generate-example.js in ci --- .github/workflows/tests.yaml | 111 +++++++++++--------------------- Example.jest.config.js | 1 + Example.jest.setup.js | 6 ++ MAINTAINER.md | 2 +- __scripts__/generate-example.js | 47 +++++++++----- package.json | 4 +- 6 files changed, 78 insertions(+), 93 deletions(-) create mode 100644 Example.jest.setup.js diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index b20835f..e6e50ea 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -9,11 +9,6 @@ on: schedule: - cron: '0 0 * * 0' # https://crontab.guru/every-week -env: - TEST_APP_DEPS: react-native-modal react-native-webview - TEST_APP_DEV_DEPS: typescript @babel/preset-env react-shallow-renderer - RN_BUNDLE_ARGS: --entry-file index.js --platform android --dev false --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res - jobs: build: runs-on: ubuntu-latest @@ -21,11 +16,29 @@ jobs: - uses: actions/checkout@v4 - run: npm install - run: npm test - test-yarn: + + test: needs: build - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} outputs: rn-version: ${{ steps.rn-version.outputs.value }} + concurrency: + group: '${{ github.workflow }}-${{ matrix.platform }}-${{ matrix.pm }}-${{ github.head_ref || github.ref_name }}' + cancel-in-progress: true + strategy: + fail-fast: false + max-parallel: 5 + matrix: + os: [ ubuntu-latest ] + platform: [ android ] + pm: [ npm, yarn ] + include: + - os: macos-latest + platform: ios + pm: npm + - os: macos-latest + platform: ios + pm: yarn steps: - uses: actions/checkout@v4 with: @@ -34,85 +47,32 @@ jobs: with: java-version: 17 distribution: adopt - - run: npx react-native init rnexample + - run: | + # npm install -g ${{ matrix.pm }} react-native + npm run example -- --pm ${{ matrix.pm }} + working-directory: react-native-hcaptcha - id: rn-version - working-directory: rnexample + working-directory: react-native-hcaptcha-example run: | RN_VERSION=$(cat package.json | jq ".dependencies.\"react-native\"" -r) echo "value=${RN_VERSION}" >> $GITHUB_OUTPUT - - name: Run yarn add ... - working-directory: rnexample - run: | - yarn add @hcaptcha/react-native-hcaptcha@file:../react-native-hcaptcha - yarn add --dev ${{ env.TEST_APP_DEV_DEPS }} - yarn add ${{ env.TEST_APP_DEPS }} - cp ../react-native-hcaptcha/Example.App.js App.js - cp ../react-native-hcaptcha/Example.jest.config.js jest.config.js - - run: | - mkdir -p android/app/src/main/assets - mkdir -p android/app/src/main/res - yarn react-native bundle ${{ env.RN_BUNDLE_ARGS }} - working-directory: rnexample - run: cat package.json - working-directory: rnexample + working-directory: react-native-hcaptcha-example - run: yarn test --config ./jest.config.js - working-directory: rnexample + working-directory: react-native-hcaptcha-example + - run: npx react-native build-${{ matrix.platform }} + working-directory: react-native-hcaptcha-example - run: npx --yes check-peer-dependencies --yarn --runOnlyOnRootDependencies - working-directory: rnexample - test-npm: - needs: build - runs-on: ubuntu-latest - outputs: - rn-version: ${{ steps.rn-version.outputs.value }} - steps: - - uses: actions/setup-java@v4 - with: - java-version: 17 - distribution: adopt - - run: npx react-native init rnexample - - id: rn-version - working-directory: rnexample - run: | - RN_VERSION=$(cat package.json | jq ".dependencies.\"react-native\"" -r) - echo "value=${RN_VERSION}" >> $GITHUB_OUTPUT - - uses: actions/checkout@v4 - with: - path: rnexample/react-native-hcaptcha - - name: Run npm install ... - working-directory: rnexample - run: | - npm i --save file:./react-native-hcaptcha - npm i --save --include=dev ${{ env.TEST_APP_DEV_DEPS }} - npm i --save ${{ env.TEST_APP_DEPS }} - cp ./react-native-hcaptcha/Example.App.js App.js - cp ./react-native-hcaptcha/Example.jest.config.js jest.config.js - - run: | - mkdir -p android/app/src/main/assets - mkdir -p android/app/src/main/res - npx react-native bundle ${{ env.RN_BUNDLE_ARGS }} - working-directory: rnexample - - run: cat package.json - working-directory: rnexample - - run: npm run test -- --config ./jest.config.js - working-directory: rnexample - - run: npx --yes check-peer-dependencies --npm --runOnlyOnRootDependencies - working-directory: rnexample - - run: | - echo "org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=1024m" >> gradle.properties - ./gradlew assemble - working-directory: rnexample/android - - uses: actions/upload-artifact@v4 - with: - name: apks - path: rnexample/android/app/build/outputs/apk/release/app-release.apk + working-directory: react-native-hcaptcha-example + create-an-issue: runs-on: ubuntu-latest - needs: [test-npm, test-yarn] - if: always() && github.event == 'schedule' && (needs.test-npm.result == 'failure' || needs.test-yarn.result == 'failure') + needs: test + if: always() && github.event == 'schedule' && needs.test.result == 'failure' steps: - uses: actions/checkout@v4 - run: | - RN_VERSION="${{ needs.test-npm.outputs.rn-version || needs.test-yarn.outputs.rn-version }}" + RN_VERSION="${{ needs.test.outputs.rn-version }}" GHA_RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" echo "RN_VERSION=${RN_VERSION}" >> $GITHUB_ENV echo "GHA_RUN_URL=${GHA_RUN_URL}" >> $GITHUB_ENV @@ -123,9 +83,10 @@ jobs: assignees: CAMOBAP update_existing: true filename: .github/examples-issue-template.md + release: if: github.event_name == 'release' - needs: [test-npm, test-yarn] + needs: test runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/Example.jest.config.js b/Example.jest.config.js index eb12417..364abb8 100644 --- a/Example.jest.config.js +++ b/Example.jest.config.js @@ -12,4 +12,5 @@ module.exports = { + "|react-native-animatable" + ")/)", ], + setupFiles: ['./jest.setup.js'], } diff --git a/Example.jest.setup.js b/Example.jest.setup.js new file mode 100644 index 0000000..4290416 --- /dev/null +++ b/Example.jest.setup.js @@ -0,0 +1,6 @@ +jest.mock('react-native-webview', () => { + return { + WebView: () => 'WebView', + }; +}); + diff --git a/MAINTAINER.md b/MAINTAINER.md index 85888cf..b3168b6 100644 --- a/MAINTAINER.md +++ b/MAINTAINER.md @@ -153,6 +153,6 @@ Problem: Usage Error: The file:../react-native-hcaptcha string didn't match the required format (package-name@range). Did you perhaps forget to explicitly reference the package name? ``` -Solution: `yarn add ../react-native-hcaptcha` +Solution: `yarn add @hcaptcha/react-native-hcaptcha@file:../react-native-hcaptcha` Yarn 2.10.x and above doesn't require `file:` scheme prefix https://stackoverflow.com/questions/40102686/how-to-install-package-with-local-path-by-yarn-it-couldnt-find-package \ No newline at end of file diff --git a/__scripts__/generate-example.js b/__scripts__/generate-example.js index 1c6a8cf..dbb2e60 100644 --- a/__scripts__/generate-example.js +++ b/__scripts__/generate-example.js @@ -25,7 +25,7 @@ function parseArgs(args) { cliName: 'react-native', projectName: 'react_native_hcaptcha_example', projectRelativeProjectPath: '../react-native-hcaptcha-example', - packageManager: 'yarn', // npm is broken https://github.com/facebook/react-native/issues/29977 + packageManager: 'yarn', projectTemplate: undefined, frameworkVersion: undefined, }; @@ -37,6 +37,10 @@ function parseArgs(args) { options.projectName = value.replace(/[^a-zA-Z0-9]/g, '_'); options.projectRelativeProjectPath = path.join('..', value); }, + '--path': (value) => { + options.projectRelativeProjectPath = value; + }, + '--pm': (value) => options.packageManager = value, '-h': showHelp, '--help': showHelp }; @@ -82,7 +86,7 @@ function cleanupEnvPathNode() { // Function to build the create command function buildCreateCommand({ cliName, projectRelativeProjectPath, projectName, projectTemplate, packageManager, frameworkVersion }) { - let createCommand = [cliName, 'init', projectName, '--directory', projectRelativeProjectPath]; + let createCommand = ['npx', cliName, 'init', projectName, '--directory', projectRelativeProjectPath]; if (projectTemplate) { createCommand.push('--template', projectTemplate); @@ -97,7 +101,7 @@ function buildCreateCommand({ cliName, projectRelativeProjectPath, projectName, createCommand.push('--version', frameworkVersion); } - createCommand.push('--skip-install'); + // createCommand.push('--skip-install'); } else { console.error('Error: unsupporte cliName'); showHelp(); @@ -108,46 +112,50 @@ function buildCreateCommand({ cliName, projectRelativeProjectPath, projectName, return createCommand; } -// Function to check if hCaptcha is linked function checkHcaptchaLinked() { - // - return false; + return false; // https://stackoverflow.com/a/47403470/902217 } // Main function that takes parsed arguments and runs the necessary setup function main({ cliName, projectRelativeProjectPath, projectName, projectTemplate, packageManager, frameworkVersion }) { cleanupEnvPathNode(); - console.warn(`Warning! Example project will be generated in '${path.dirname(__dirname)}' directory`); + console.warn(`Warning! Example project will be generated in '${path.dirname(process.cwd())}' os='${platform()}'`); // Build the command to initialize the project const createCommand = buildCreateCommand({ cliName, projectRelativeProjectPath, projectName, projectTemplate, packageManager, frameworkVersion }); // Run the project initialization command console.log(`Running command: ${createCommand}`); - execSync(createCommand.join(' '), { stdio: 'inherit', shell: true }); + execSync(createCommand.join(' '), { stdio: 'inherit', shell: true, env: { ...process.env, USE_HERMES: 0 } }); const projectPath = path.join(process.cwd(), projectRelativeProjectPath); const packageManagerOptions = { stdio: 'inherit', cwd: projectPath }; // Copy App.js - fs.readdirSync(projectPath) - .filter(file => file.startsWith('App.')) - .forEach(file => fs.unlinkSync(path.join(projectPath, file))); - fs.copyFileSync('Example.App.js', `${projectPath}/App.js`); + fs.unlinkSync(path.join(projectPath, 'App.tsx')) + fs.copyFileSync('Example.App.js', path.join(projectPath, 'App.js')); + fs.copyFileSync('Example.jest.config.js', path.join(projectPath, 'jest.config.js')); + fs.copyFileSync('Example.jest.setup.js', path.join(projectPath, 'jest.setup.js')); // Install dependencies const isHcaptchaLinked = checkHcaptchaLinked(); const mainPackage = '@hcaptcha/react-native-hcaptcha' const mainPackagePath = `${path.dirname(projectRelativeProjectPath)}/react-native-hcaptcha` const peerPackages = 'react-native-modal react-native-webview'; + const devPackages = 'typescript @babel/preset-env react-shallow-renderer'; console.warn('Installing dependencies...'); if (packageManager === 'yarn') { - execSync(`yarn add ${mainPackagePath}`, packageManagerOptions); + execSync(`yarn add @hcaptcha/react-native-hcaptcha@file:${mainPackagePath}`, packageManagerOptions); + execSync(`yarn add --dev ${devPackages}`, packageManagerOptions); execSync(`yarn add ${peerPackages}`, packageManagerOptions); } else { - execSync(`npm i --save ${mainPackagePath}`, packageManagerOptions); + // https://github.com/facebook/react-native/issues/29977 - react-native doesn't work with symlinks so `cp` instead + // fs.symlinkSync(mainPackagePath, path.join(projectPath, 'react-native-hcaptcha'), 'dir'); + execSync(`cp -r ${mainPackagePath} ${projectPath}`); + execSync(`npm i --save file:./react-native-hcaptcha`, packageManagerOptions); + execSync(`npm i --save --dev ${devPackages}`, packageManagerOptions); execSync(`npm i --save ${peerPackages}`, packageManagerOptions); } @@ -155,13 +163,22 @@ function main({ cliName, projectRelativeProjectPath, projectName, projectTemplat execSync(`${packageManager} link ${mainPackage}`, packageManagerOptions); } - // Handle iOS-specific setup if running on macOS + // iOS: pod install if (platform() === 'darwin') { const podOptions = { stdio: 'inherit', cwd: path.join(projectPath, 'ios'), env: { ...process.env, USE_HERMES: 0 } }; execSync('bundle install', podOptions); execSync('bundle exec pod install', podOptions); } + // Android + const gradleOptions = { + stdio: 'inherit', cwd: path.join(projectPath, 'android'), + env: { ...process.env, GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx4096m -XX:MaxMetaspaceSize=1024m"' } + }; + execSync('./gradlew assemble', gradleOptions); + + ['assets', 'res'].map(dir => fs.mkdirSync(path.join(projectPath, 'android/app/src/main', dir), { recursive: true })); + console.log('Setup complete.'); } diff --git a/package.json b/package.json index 9171d3e..b6e59d4 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "test": "jest", - "example": "node __scripts__/generate-example.js --name react-native-hcaptcha-example" + "example": "node __scripts__/generate-example.js" }, "jest": { "preset": "react-native", @@ -61,4 +61,4 @@ "babel-jest": "^27.2.2", "metro-react-native-babel-preset": "^0.77.0" } -} +} \ No newline at end of file