Skip to content

Commit 8e9bfec

Browse files
zeyapfacebook-github-bot
authored andcommitted
Lint changed iOS podspecs in CI with pod lib lint
Summary: The RNTester integration build only proves that pods work *together* inside one workspace — it does not build every pod from source, and pods outside RNTester's dependency closure are never validated on their own. As a result, a podspec can ship with a defect that only shows up when the pod is built in isolation: a malformed compiler flag, or a header/dependency that the pod uses but never declares (which surfaces as a `'yoga/Yoga.h' file not found` style build error for open-source consumers). This adds a pull-request job that runs `pod lib lint` on the `*.podspec` files a change actually touches. Each pod is linted in isolation, so a dependency that is used-but-not-declared fails to resolve and the job fails. Because React Native's pods are not published to a spec repo, the script exposes every local podspec via `--include-podspecs`, letting the linter resolve inter-pod dependencies from the checkout. The job is scoped to changed podspecs via `dorny/paths-filter`, so PRs that touch no podspec do no extra work. Changelog: [Internal] - Add CI linting for changed iOS podspecs Differential Revision: D108889958
1 parent 7b2ebdc commit 8e9bfec

3 files changed

Lines changed: 131 additions & 0 deletions

File tree

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: lint-ios-podspecs
2+
description: Lint the CocoaPods podspecs changed by a pull request with `pod lib lint`
3+
inputs:
4+
ruby-version:
5+
description: The version of ruby that must be used
6+
default: 2.6.10
7+
podspecs:
8+
description: Space-separated list of changed *.podspec paths to lint
9+
required: true
10+
runs:
11+
using: composite
12+
steps:
13+
- name: Setup xcode
14+
uses: ./.github/actions/setup-xcode
15+
- name: Setup ruby
16+
uses: ruby/setup-ruby@v1
17+
with:
18+
ruby-version: ${{ inputs.ruby-version }}
19+
- name: Install gems
20+
shell: bash
21+
run: bundle install
22+
- name: Lint changed podspecs
23+
shell: bash
24+
run: ./scripts/lint-changed-podspecs.sh ${{ inputs.podspecs }}

.github/workflows/test-all.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,31 @@ jobs:
8989
- 'packages/debugger-shell/**'
9090
- 'scripts/debugger-shell/**'
9191
92+
lint_ios_podspecs:
93+
runs-on: macos-15
94+
timeout-minutes: 60
95+
needs: check_code_changes
96+
if: |
97+
github.repository == 'react/react-native' &&
98+
needs.check_code_changes.outputs.any_code_change == 'true' &&
99+
needs.check_code_changes.outputs.should_test_ios == 'true'
100+
steps:
101+
- name: Checkout
102+
uses: actions/checkout@v6
103+
- name: Detect changed podspecs
104+
uses: dorny/paths-filter@209e61402dbca8aa44f967535da6666b284025ed
105+
id: changed_podspecs
106+
with:
107+
list-files: shell
108+
filters: |
109+
podspecs:
110+
- 'packages/react-native/**/*.podspec'
111+
- name: Lint changed podspecs
112+
if: ${{ steps.changed_podspecs.outputs.podspecs == 'true' }}
113+
uses: ./.github/actions/lint-ios-podspecs
114+
with:
115+
podspecs: ${{ steps.changed_podspecs.outputs.podspecs_files }}
116+
92117
prebuild_apple_dependencies:
93118
needs: check_code_changes
94119
if: |

scripts/lint-changed-podspecs.sh

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#!/bin/bash
2+
# Copyright (c) Meta Platforms, Inc. and affiliates.
3+
#
4+
# This source code is licensed under the MIT license found in the
5+
# LICENSE file in the root directory of this source tree.
6+
7+
# Lints the podspecs passed as arguments — intended for the *.podspec files that
8+
# a pull request changes. Each pod is linted in isolation with `pod lib lint`,
9+
# which builds it from source using ONLY its declared dependencies. That catches
10+
# podspec defects the RNTester integration build misses, e.g. a malformed
11+
# compiler flag, or a header/dependency that the pod uses but does not declare
12+
# (which surfaces as a "'yoga/Yoga.h' file not found" style build error).
13+
#
14+
# React Native's pods are not published to a CocoaPods spec repo, so we expose
15+
# every local podspec via `--include-podspecs`. That lets the linter resolve
16+
# inter-pod dependencies (React-Core, Yoga, React-Fabric, the third-party deps,
17+
# …) from this checkout instead of from trunk. A dependency that is *used but
18+
# not declared* still fails to resolve its headers, which is exactly the class
19+
# of breakage this check exists to prevent.
20+
21+
set -eo pipefail
22+
23+
SCRIPTS="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
24+
ROOT="$(dirname "$SCRIPTS")"
25+
26+
if [ "$#" -eq 0 ]; then
27+
echo "No changed podspecs to lint."
28+
exit 0
29+
fi
30+
31+
cd "$ROOT"
32+
33+
# Make every local podspec resolvable as a dependency source during lint. The
34+
# `**` glob also covers the root React.podspec and third-party-podspecs/. Loaded
35+
# this way each spec resolves by path (like a `:path` install), so we must NOT
36+
# set the INSTALL_YOGA_* env vars that process-podspecs.sh uses only for `push`.
37+
INCLUDE_PODSPECS='packages/react-native/**/*.podspec'
38+
39+
# Lint options follow scripts/process-podspecs.sh; dependency resolution differs
40+
# (we rely on --include-podspecs rather than a published spec repo).
41+
LINT_OPT=(
42+
--verbose
43+
--allow-warnings
44+
--fail-fast
45+
--private
46+
--swift-version=3.0
47+
--include-podspecs="$INCLUDE_PODSPECS"
48+
--sources=https://github.com/CocoaPods/Specs.git
49+
)
50+
51+
echo "Linting $# changed podspec(s): $*"
52+
53+
status=0
54+
for podspec in "$@"; do
55+
if [ ! -f "$podspec" ]; then
56+
# The podspec was deleted/renamed in this change; nothing to lint.
57+
echo "Skipping '$podspec' (no longer present)."
58+
continue
59+
fi
60+
61+
case "$podspec" in
62+
*/__fixtures__/*)
63+
# Codegen test fixtures are not real pods; do not attempt to lint them.
64+
echo "Skipping '$podspec' (codegen test fixture)."
65+
continue
66+
;;
67+
esac
68+
69+
echo "::group::pod lib lint $podspec"
70+
# Lint both the default (frameworks) and the static-library builds, mirroring
71+
# process-podspecs.sh, since linkage-specific issues can hide in either.
72+
for extra in "" "--use-libraries"; do
73+
# shellcheck disable=SC2086
74+
if ! bundle exec pod lib lint "$podspec" "${LINT_OPT[@]}" $extra; then
75+
echo "::error file=$podspec::pod lib lint failed for $podspec ${extra:-(frameworks)}"
76+
status=1
77+
fi
78+
done
79+
echo "::endgroup::"
80+
done
81+
82+
exit "$status"

0 commit comments

Comments
 (0)