Skip to content

Commit cd7685c

Browse files
committed
chore: add Yarn constraints
1 parent 872bc8c commit cd7685c

File tree

4 files changed

+134
-0
lines changed

4 files changed

+134
-0
lines changed

.github/workflows/microsoft-pr.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,19 @@ jobs:
6363
run: |
6464
echo "Target branch: ${{ github.base_ref }}"
6565
yarn nx release --dry-run --verbose
66+
yarn-constraints:
67+
name: "Check Yarn Constraints"
68+
permissions: {}
69+
runs-on: ubuntu-latest
70+
steps:
71+
- uses: actions/checkout@v4
72+
with:
73+
filter: blob:none
74+
fetch-depth: 0
75+
- uses: actions/setup-node@v4
76+
with:
77+
node-version: '22'
78+
- name: Install dependencies
79+
run: yarn
80+
- name: Check constraints
81+
run: yarn constraints

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
"@tsconfig/node18": "1.0.1",
5757
"@types/react": "^18.2.6",
5858
"@typescript-eslint/parser": "^7.1.1",
59+
"@yarnpkg/types": "^4.0.1",
5960
"ansi-styles": "^4.2.1",
6061
"babel-plugin-minify-dead-code-elimination": "^0.5.2",
6162
"babel-plugin-syntax-hermes-parser": "0.23.1",

yarn.config.cjs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// @ts-check
2+
3+
/** @type {import('@yarnpkg/types')} */
4+
const {defineConfig} = require('@yarnpkg/types');
5+
6+
/**
7+
* @typedef {import('@yarnpkg/types').Yarn.Constraints.Context} Context
8+
* @typedef {import('@yarnpkg/types').Yarn.Constraints.Workspace} Workspace
9+
* @typedef {import('@yarnpkg/types').Yarn.Constraints.Dependency} Dependency
10+
*/
11+
12+
/**
13+
* Enforce that react-native-macos declares a peer dependency on react-native on release branches,
14+
* except on the main branch, where there is no published version of React Native to align to.
15+
* @param {Context} context
16+
*/
17+
function expectReactNativePeerDependency({Yarn}) {
18+
const rnmWorkspace = Yarn.workspace({ident: 'react-native-macos'});
19+
if (!rnmWorkspace) {
20+
// Report error on root workspace since react-native-macos doesn't exist
21+
Yarn.workspace().error('react-native-macos workspace must exist in the monorepo');
22+
return;
23+
}
24+
25+
// Check if react-native-macos version is 1000.0.0 - implying we are on the main branch
26+
const isMainBranch = rnmWorkspace.pkg.version === '1000.0.0';
27+
if (!isMainBranch) {
28+
const rnPeerDependency = rnmWorkspace.pkg.peerDependencies.get('react-native');
29+
if (!rnPeerDependency) {
30+
rnmWorkspace.error('react-native-macos must declare a peer dependency on react-native on release branches');
31+
}
32+
}
33+
}
34+
35+
/**
36+
* Enforce that all @react-native/ scoped packages use the same version
37+
* as the react-native peer dependency declared in react-native-macos.
38+
* On the main branch, enforce that we use workspace:* for @react-native/ packages.
39+
* @param {Context} context
40+
*/
41+
function enforceReactNativeVersionConsistency({Yarn}) {
42+
const rnmWorkspace = Yarn.workspace({ident: 'react-native-macos'});
43+
if (!rnmWorkspace) {
44+
// Report error on root workspace since react-native-macos doesn't exist
45+
Yarn.workspace().error('react-native-macos workspace must exist in the monorepo');
46+
return;
47+
}
48+
49+
// Check if react-native-macos version is 1000.0.0 - implying we are on the main branch
50+
const isMainBranch = rnmWorkspace.pkg.version === '1000.0.0';
51+
52+
let targetVersion;
53+
if (isMainBranch) {
54+
// On main branch, use workspace:* for @react-native/ packages
55+
targetVersion = 'workspace:*';
56+
} else {
57+
const rnPeerDependency = rnmWorkspace.pkg.peerDependencies.get('react-native');
58+
if (!rnPeerDependency) {
59+
rnmWorkspace.error('react-native-macos must declare a peer dependency on react-native on release branches');
60+
return;
61+
}
62+
targetVersion = rnPeerDependency;
63+
} // Enforce this version on all @react-native/ scoped packages across all workspaces
64+
for (const dependency of Yarn.dependencies()) {
65+
if (dependency.ident.startsWith('@react-native/')) {
66+
dependency.update(targetVersion);
67+
}
68+
}
69+
}
70+
71+
/**
72+
* Enforce that all @react-native-macos/ scoped packages use the same version
73+
* as react-native-macos, but only for non-private packages.
74+
* @param {Context} context
75+
*/
76+
function enforceReactNativeMacosVersionConsistency({Yarn}) {
77+
const rnmWorkspace = Yarn.workspace({ident: 'react-native-macos'});
78+
if (!rnmWorkspace) {
79+
// Report error on root workspace since react-native-macos doesn't exist
80+
Yarn.workspace().error('react-native-macos workspace must exist in the monorepo');
81+
return;
82+
}
83+
84+
const targetVersion = rnmWorkspace.pkg.version;
85+
if (!targetVersion) {
86+
rnmWorkspace.error('react-native-macos must have a version');
87+
return;
88+
}
89+
90+
// Enforce this version on all non-private @react-native-macos/ scoped packages
91+
for (const workspace of Yarn.workspaces()) {
92+
const isReactNativeMacosScoped = workspace.ident && workspace.ident.startsWith('@react-native-macos/');
93+
const isPrivate = workspace.manifest.private;
94+
95+
if (isReactNativeMacosScoped && !isPrivate) {
96+
workspace.set('version', targetVersion);
97+
}
98+
}
99+
}
100+
101+
module.exports = defineConfig({
102+
constraints: async ctx => {
103+
expectReactNativePeerDependency(ctx);
104+
enforceReactNativeVersionConsistency(ctx);
105+
enforceReactNativeMacosVersionConsistency(ctx);
106+
},
107+
});

yarn.lock

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3363,6 +3363,7 @@ __metadata:
33633363
"@tsconfig/node18": "npm:1.0.1"
33643364
"@types/react": "npm:^18.2.6"
33653365
"@typescript-eslint/parser": "npm:^7.1.1"
3366+
"@yarnpkg/types": "npm:^4.0.1"
33663367
ansi-styles: "npm:^4.2.1"
33673368
babel-plugin-minify-dead-code-elimination: "npm:^0.5.2"
33683369
babel-plugin-syntax-hermes-parser: "npm:0.23.1"
@@ -4658,6 +4659,15 @@ __metadata:
46584659
languageName: node
46594660
linkType: hard
46604661

4662+
"@yarnpkg/types@npm:^4.0.1":
4663+
version: 4.0.1
4664+
resolution: "@yarnpkg/types@npm:4.0.1"
4665+
dependencies:
4666+
tslib: "npm:^2.4.0"
4667+
checksum: 10c0/90226789475680ba599833571dd76c0718dd5b4c5022481263ef309d6a628f6246671cd6ca86e49c966ddefa7aca6ccef82240dc1476d2cea702ea5bee2a6b72
4668+
languageName: node
4669+
linkType: hard
4670+
46614671
"@zkochan/js-yaml@npm:0.0.7":
46624672
version: 0.0.7
46634673
resolution: "@zkochan/js-yaml@npm:0.0.7"

0 commit comments

Comments
 (0)