Migrate to npm and publish via the shared release workflow - #5
Closed
JStonevalley wants to merge 7 commits into
Closed
Migrate to npm and publish via the shared release workflow#5JStonevalley wants to merge 7 commits into
JStonevalley wants to merge 7 commits into
Conversation
Prepares the repo for the shared release pipeline in sellpy/package-release-actions, which installs with npm ci. - Drop yarn.lock, .yarn/ (pinned Yarn 3.6.1 release + plugins), .yarnrc.yml and packageManager; add package-lock.json. - resolutions -> overrides. Add a targeted peer override so @expo/webpack-config (peer expo@^48) resolves against the example's expo@~50; Yarn only warned about this, npm refuses to install. - Drop the `example` passthrough script: it ran an arbitrary command in a workspace, which npm has no equivalent for. Call sites use `npm exec -w @sellpy/react-native-scroll-anchor-example -- <cmd>`. - Pin bob's tsc path. bob 0.20 locates tsc via `npm bin`, removed in npm 9, so it silently fell back to a globally installed tsc and would fail in CI. - Fix the example for npm's hoisting. Yarn used nmHoistingLimits: workspaces, so expo and the peer deps sat in example/node_modules; npm hoists them to the root, which broke expo/AppEntry.js's relative import and left the metro/webpack aliases pointing at paths that no longer exist. The example now registers its root component from its own index.js and resolves peer deps with require.resolve. Verified: lint, typecheck, jest, `bob build` and `expo export:web` all pass, and the packed tarball contains lib/ and src/. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STVhZLEVATkpeYFJijWQuZ
- setup action: npm ci with setup-node's built-in npm cache, replacing the yarn install and the hand-rolled actions/cache block. always-auth was a no-op without a registry-url. - ci.yml: yarn -> npm at every call site. `npm test --` forwards the jest flags; the example web build goes through `npm exec -w`. - Add workflow_call to ci.yml so the publish workflow can gate on it. Nothing in this repo was callable before. - Bump checkout to v5 and setup-node to v5; the v3 releases run on the retired Node 16 runner. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STVhZLEVATkpeYFJijWQuZ
Replaces the release-triggered publish with the org-wide pipeline in sellpy/package-release-actions@v1, matching commons, pdf-creator, automation-commons and fetch-graphql-schema. - release.yml now fires when a PR to main closes, gates on ci.yml and delegates to npm-publish-master.yml@v1. The old hand-written ~/.npmrc, the vestigial `yarn pack` step and `--access public` all go with it; the shared workflow authenticates, resolves the next version from the registry, publishes and pushes a vX.Y.Z tag using GITHUB_TOKEN. - Add pr-validation.yml so every PR carries exactly one major/minor/patch label, which is what the publish reads to decide the bump. Two follow-ups have to happen outside the repo before the first release: create the major/minor/patch labels, and confirm NPM_AUTOMATION_TOKEN can both publish and read this package's versions. Note the cadence change: every merge to main now publishes, and a semver label is mandatory on every PR. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STVhZLEVATkpeYFJijWQuZ
yarn -> npm throughout, including the note that npm could not be used, and the example commands rewritten as workspace-scoped npm invocations. Adds a Releasing section covering the mandatory semver label, the merge-to-main cadence and the 0.0.0-managed placeholder. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STVhZLEVATkpeYFJijWQuZ
publishConfig.access: public replaces the dropped `--access public` flag, so the intent lives in package.json rather than in a workflow this repo no longer owns. The shared publish workflow runs a bare `npm publish`, and nothing about `access` interferes with its `--registry` flag — unlike publishConfig.registry, which outranks it and is why that field had to go. Note this is belt-and-braces rather than a fix: access is a registry-side setting on the package, and `--access` only applies to the first publish of a scoped name. `npm access get status` reports @sellpy/react-native-scroll-anchor as public today and dropping the flag would not have changed that. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STVhZLEVATkpeYFJijWQuZ
@expo/webpack-config@19.0.1 declares `expo: "^49.0.7 || ^50.0.0-0"`, so it accepts the example's expo 50 on its own. The repo was pinned to ^18.0.1, which resolves to 18.1.4 and still asks for expo ^48.0.17 — the conflict npm refused to install and Yarn only warned about. Bumping the dependency fixes the cause rather than silencing the symptom, so the `overrides` entry added for it goes away. The @types/react override stays; that one is a deliberate pin, not a workaround. Verified: clean npm ci, lint, typecheck, jest, and `expo export:web` compiles. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STVhZLEVATkpeYFJijWQuZ
Replaces `expo export:web` with `expo export -p web`. The webpack path was deprecated in SDK 50 and removed in 51, and @expo/webpack-config@19.0.1 is its last release, so the previous commit's dependency bump only bought time. Metro is the supported web bundler and needs no separate bundler config: the example loses webpack.config.js, @expo/webpack-config and babel-loader outright. Expo 54 is the floor we support, which sets the rest: - example: expo ~54.0.36, react 19.1.0, react-dom 19.1.0, react-native 0.81.5, react-native-web ~0.21.0, expo-status-bar ~3.0.9 — the versions SDK 54 bundles. `babel-preset-expo` and `@react-native/babel-preset` become explicit dependencies; both used to resolve transitively and no longer do. - root devDependencies track the same react and react-native, so the example and the library build against one copy, and @types/react moves to 19 (the override with it). - .nvmrc goes v18 -> v22. React Native 0.81 requires Node >= 20.19, so v18 would have failed at install; v22 also matches the sibling packages. - app.json declares `web.bundler: "metro"` and metro.config.js requires `expo/metro-config` rather than the `@expo/metro-config` alias. Two things this surfaced rather than caused: - **React 19 changed `useRef<T>(null)` to return `RefObject<T | null>`.** The public types took `RefObject<NativeComponent>` and `RefObject<ScrollView>`, which a ref from `useRef<T>(null)` no longer satisfies, so `bob build` failed on the type definitions. The parameters are widened to accept `| null`, which is what a React 19 caller actually has. Every internal dereference already null-checked, so no logic changed. Callers passing a non-null ref are unaffected: this widens what the API accepts. - **@react-native/eslint-config 0.81 no longer depends on eslint-plugin-prettier**, only on eslint-config-prettier, so `prettier/prettier` was an unregistered rule and every file errored. The config now extends `plugin:prettier/recommended`, which registers the plugin and keeps the formatting rule enforced. Verified from a clean `npm ci`: lint, typecheck, jest, `bob build` via the prepare hook, and `expo export -p web` — whose bundle contains the library's own source, confirming the module-resolver alias still resolves through Metro. `npm pack --dry-run` is unchanged at 73 files. Untested: the native dev flow (`start` / `ios` / `android`), which needs a device or simulator. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STVhZLEVATkpeYFJijWQuZ
Member
Author
|
@ThunbergOlle will migrate this into Sellphone |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The shared publish pipeline in
sellpy/package-release-actionshas been adopted by pdf-creator, commons, automation-commons and fetch-graphql-schema (automation-commons#16 most recently), all four with real releases through it. This repo is the fifth and last single-package one; after it onlydesign-systemremains.It was also the furthest from the others: the only one publishing
on: releaserather than on a labelled merge, and the only one on Yarn. The registry becomes the source of truth for the released version, and nothing is pushed tomainany more — only avX.Y.Ztag.What is here
release.ymlbecomes a caller stanza, keeping the trigger, concurrency group, validate gate andNPM_AUTOMATION_TOKENsecret name here, which is what the shared workflow leaves to callers.permissions: contents: writeon the calling job is required, not optional — a called workflow can lower the permissions it is handed but never raise them. The hand-written~/.npmrc, the vestigialyarn packstep and--access publicgo with it.ci.ymlgainsworkflow_callso the publish can gate on it, andpr-validation.ymlis new.package.jsontakes a0.0.0-managedplaceholder and dropspublishConfig.registry, which outranks the--registryflag the shared workflow publishes with.publishConfig.access: "public"replaces the old--access publicflag; the package is already public on npmjs, so this records intent rather than changing anything.Setup and CI move to
npm ciwithsetup-node's npm cache, andcheckout/setup-nodego from v3 to v5 (v3 runs on the retired Node 16 runner).CONTRIBUTING.mdis rewritten for npm and documents the new release cadence: every merge tomainnow publishes, and a semver label is mandatory on every PR.Unique to this repo
This is a Yarn 3 → npm migration as well as a pipeline one, since the shared workflow installs with
npm ci. Three things in it would each have broken the release on their own:react-native-builder-bobcannot findtscunder npm ≥ 9. bob 0.20 locates it by runningnpm bin, removed in npm 9, then falls back towhich tscwith only a warning — so it silently uses a global TypeScript locally and fails hard on a runner that has none. Pinned via bob'stscoption.npm's hoisting broke the example. Yarn's
nmHoistingLimits: workspaceskeptexpoand the peer deps inexample/node_modules; npm hoists them to the root, which breaks the relativeimport App from '../../App'insideexpo/AppEntry.jsand leaves the metro aliases pointing at paths that no longer exist. The example now registers its root component from its ownindex.jsand resolves peer deps withrequire.resolve.The example moves to Expo 54 and Metro web bundling.
expo export:weband@expo/webpack-configwere deprecated in SDK 50 and webpack removed in SDK 51, so upgrading that package would only have bought time.webpack.config.js,@expo/webpack-configandbabel-loaderare deleted and CI runsexpo export -p web. Expo 54 brings react 19.1.0, react-native 0.81.5, react-native-web ~0.21.0 and friends, with the root'sreact/react-nativedevDependencies tracking the same versions;babel-preset-expoand@react-native/babel-presetbecome explicit dependencies because they no longer resolve transitively.Three consequences of that upgrade worth flagging:
.nvmrcv18 → v22. RN 0.81 requires Node ≥ 20.19, so v18 fails at install. The shared workflow reads.nvmrc, so releases build on 22 from now on — same as the siblings.useRef<T>(null)returnRefObject<T | null>, whichRefObject<NativeComponent>andRefObject<ScrollView>no longer accept, sobob buildfailed emitting definitions. Those parameters now take| null. Internal dereferences already null-checked, so no logic changed, and widening leaves existing callers unaffected.@react-native/eslint-config@0.81turned out to have droppedeslint-plugin-prettier, leavingprettier/prettierunregistered. The config now extendsplugin:prettier/recommended.Testing
The registry read, publish and tag push only run on a merge, so they cannot be verified beforehand — but four sibling repos have released through this exact workflow.
On the first merge, expect
Registry latest is 0.1.1, publishing 0.1.2 (patch), then a publish, then tagv0.1.2.Two gaps to know about: the native dev flow (
start/ios/android) has not been run — it needs a device, and the entry point, dependency resolution and Expo major all changed, so start the app once before merging. And the jest suite is a singletest.todo, soneeds: validategates lint, typecheck and builds rather than real coverage.