diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index d73fd41a..64604446 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -1,45 +1,24 @@ name: Android Build on: - pull_request: - branches: - - main - paths: - - '.github/workflows/android.yml' - - 'android/**' - - 'src/**' - - 'example/android/**' - - 'example/src/**' - - 'example/package.json' - - 'example/metro.config.js' - - 'package.json' - - 'bun.lock' - - 'bunfig.toml' - - 'e2e/**' - push: - branches: - - main - -permissions: - contents: read - pull-requests: write + workflow_call: jobs: android-build: runs-on: ubuntu-latest timeout-minutes: 75 - concurrency: - group: ${{ github.ref }}-android - cancel-in-progress: true steps: - - uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2 - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 + with: + bun-version-file: package.json - name: Install dependencies - shell: bash - run: bun install + run: bun install --frozen-lockfile - - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + - uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: 'zulu' java-version: '17' @@ -57,7 +36,7 @@ jobs: working-directory: example/android - name: AVD cache - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 id: avd-cache with: path: | @@ -74,7 +53,7 @@ jobs: - name: Create AVD and generate snapshot for caching if: steps.avd-cache.outputs.cache-hit != 'true' - uses: reactivecircus/android-emulator-runner@1dcd0090116d15e7c562f8db72807de5e036a4ed # v2.34.0 + uses: reactivecircus/android-emulator-runner@a421e43855164a8197daf9d8d40fe71c6996bb0d # v2.38.0 with: api-level: 35 target: google_apis @@ -89,7 +68,7 @@ jobs: script: echo "Generated AVD snapshot for caching." - name: Run e2e tests - uses: reactivecircus/android-emulator-runner@1dcd0090116d15e7c562f8db72807de5e036a4ed # v2.34.0 + uses: reactivecircus/android-emulator-runner@a421e43855164a8197daf9d8d40fe71c6996bb0d # v2.38.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..750728ec --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,113 @@ +name: CI +# A required check skipped by an `on..paths` filter never reports and +# blocks the PR forever (https://github.com/orgs/community/discussions/13690), +# so `changes` filters paths and checks skip through a job-level `if:`. +# Branch protection requires only `Required checks`. If `changes` fails, +# every check runs instead of being skipped into green. Pushes to `main` +# always run everything. +on: + pull_request: + push: + branches: + - main + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + changes: + name: Changed paths + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: read + pull-requests: read + outputs: + # Empty when the filter is skipped (not a pull request), so everything runs. + android: ${{ steps.filter.outputs.android != 'false' }} + ios: ${{ steps.filter.outputs.ios != 'false' }} + steps: + - id: filter + if: github.event_name == 'pull_request' + uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3 + with: + filters: | + shared: &shared + - '.github/workflows/ci.yml' + - 'src/**' + - 'example/src/**' + - 'example/package.json' + - 'example/metro.config.js' + - 'example/index.js' + - 'example/babel.config.js' + - 'example/react-native.config.js' + - 'package.json' + - 'bun.lock' + - 'bunfig.toml' + - 'e2e/**/*.ts' + - 'e2e/package.json' + android: + - *shared + - '.github/workflows/android.yml' + - 'android/**' + - 'example/android/**' + ios: + - *shared + - '.github/workflows/ios.yml' + - 'ios/**' + - 'example/ios/**' + - '*.podspec' + - 'example/Gemfile' + - 'example/Gemfile.lock' + + lint: + name: Lint + uses: ./.github/workflows/lint.yml + + android: + name: Android Build + needs: changes + if: ${{ !cancelled() && (needs.changes.result != 'success' || needs.changes.outputs.android == 'true') }} + permissions: + contents: read + pull-requests: write + uses: ./.github/workflows/android.yml + + ios: + name: iOS Build + needs: changes + if: ${{ !cancelled() && (needs.changes.result != 'success' || needs.changes.outputs.ios == 'true') }} + permissions: + contents: read + pull-requests: write + uses: ./.github/workflows/ios.yml + + required: + name: Required checks + needs: [changes, lint, android, ios] + # `always()`, not `!cancelled()`: a skipped required check counts as passing. + if: always() + runs-on: ubuntu-latest + timeout-minutes: 5 + env: + NEEDS: ${{ toJSON(needs) }} + steps: + - name: Report every check + run: | + { + echo "| Check | Result |" + echo "| --- | --- |" + echo "$NEEDS" | jq -r 'to_entries | sort_by(.key) | .[] | "| \(.key) | \(.value.result) |"' + } >> "$GITHUB_STEP_SUMMARY" + - name: Fail on any failed or cancelled check + run: | + echo "$NEEDS" | jq -e ' + to_entries | all(.value.result as $r | { + changes: ["success", "failure"], + lint: ["success"] + }[.key] // ["success", "skipped"] | index($r))' > /dev/null diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml index 0f9750df..bb9b63c0 100644 --- a/.github/workflows/ios.yml +++ b/.github/workflows/ios.yml @@ -1,52 +1,29 @@ name: iOS Build on: - pull_request: - branches: - - main - paths: - - '.github/workflows/ios.yml' - - 'ios/**' - - 'src/**' - - 'example/ios/**' - - 'example/src/**' - - 'example/package.json' - - 'example/metro.config.js' - - 'package.json' - - 'bun.lock' - - 'bunfig.toml' - - 'e2e/**' - push: - branches: - - main - -permissions: - contents: read - pull-requests: write + workflow_call: jobs: ios-build: runs-on: macos-26 timeout-minutes: 60 - concurrency: - group: ${{ github.ref }}-ios - cancel-in-progress: true steps: - - uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2 - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 + with: + bun-version-file: package.json - name: Install dependencies - shell: bash - run: bun install + run: bun install --frozen-lockfile - name: Cache Pods - id: cache-pods - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 - env: - cache-name: cached-ios-pods-deps + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: example/ios/Pods - key: ${{ hashFiles('example/ios/Podfile.lock') }} + key: pods-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('example/ios/Podfile.lock') }} + restore-keys: pods-${{ runner.os }}-${{ runner.arch }}- - name: Install example Pods run: bun pods @@ -58,8 +35,7 @@ jobs: run: defaults write com.apple.iphonesimulator ConnectHardwareKeyboard -bool false - name: Build iOS App - run: | - bun example:ios:release + run: bun example:ios:release - name: Run e2e tests run: bun run test:ios diff --git a/.github/workflows/main.yml b/.github/workflows/lint.yml similarity index 63% rename from .github/workflows/main.yml rename to .github/workflows/lint.yml index c89e916c..435cf648 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/lint.yml @@ -1,32 +1,26 @@ name: Lint on: - pull_request: - branches: - - main - push: - branches: - - main - -concurrency: - group: ${{ github.ref }}-js - cancel-in-progress: true + workflow_call: jobs: verify-package-source: name: Lint package runs-on: ubuntu-latest - + timeout-minutes: 10 steps: - - name: Set up Bun - uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2 - - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Set up Bun + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 + with: + bun-version-file: package.json - name: Install dependencies - shell: bash - run: bun install + run: bun install --frozen-lockfile - name: Check formatting run: bun run format:check diff --git a/README.md b/README.md index f166c5cf..e94807a8 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,7 @@ [![Lean Core Extracted](https://img.shields.io/badge/Lean%20Core-Extracted-brightgreen.svg)](https://github.com/facebook/react-native/issues/23313) [![License](https://img.shields.io/github/license/callstack/react-native-pager-view?color=blue)](https://github.com/callstack/react-native-pager-view/blob/main/LICENSE) -[![Lint](https://github.com/callstack/react-native-pager-view/actions/workflows/main.yml/badge.svg)](https://github.com/callstack/react-native-pager-view/actions/workflows/main.yml) -[![iOS Build](https://github.com/callstack/react-native-pager-view/actions/workflows/ios.yml/badge.svg)](https://github.com/callstack/react-native-pager-view/actions/workflows/ios.yml) -[![Android Build](https://github.com/callstack/react-native-pager-view/actions/workflows/android.yml/badge.svg)](https://github.com/callstack/react-native-pager-view/actions/workflows/android.yml) +[![CI](https://github.com/callstack/react-native-pager-view/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/callstack/react-native-pager-view/actions/workflows/ci.yml) `PagerView` lets users swipe left and right (or up and down) through pages of content. It is a native component: on Android it renders a [Jetpack Compose pager](https://developer.android.com/develop/ui/compose/layouts/pager), and on iOS a [SwiftUI paged `TabView`](https://developer.apple.com/documentation/swiftui/tabview). [See it in action!](#preview) diff --git a/package.json b/package.json index 838a6ce2..862f1b59 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "!**/__mocks__", "!**/.*" ], + "packageManager": "bun@1.4.2", "workspaces": [ "example", "e2e"