Repository navigation
Give each package its own version and release only what changed - #37
Merged
Merged
Conversation
Each of the 16 packages is listed in ci/packages.json and tagged <package>/<version>. common-ci's steps/release-plan.ps1 works out which packages a publish releases. A package is released when a file under its folders changed since its last tag, and every package depending on it is released with it. Only the patch number moves. ci/build-package.ps1 packs only the planned packages, each at its own version, and requires each package here at the version it has once the release is out. ci/publish-package.ps1 publishes only those tarballs and tags each package. ci/check-version-bump.ps1 and ci/check-release-interval.ps1 check each planned package on its own. Step 3.1 of 51Degrees/common-ci#306.
ci/release-plan.ps1 looks at COMMON_CI before the common-ci root, and ci/check-version-bump.ps1 runs the shared check twice for each package.
common-ci's release plan now leaves out documentation, tests, examples and LICENSE files, and calls a repository's ci/release-plan-filter.ps1 for the files left. This repository's filter does not count a package.json or remote_package.json whose only changes since the package's last tag are to description, keywords, homepage, repository, bugs, author, license, files or readme. A change to any other field, such as version, dependencies, main, exports or scripts, counts. Every package also ignores __tests__ folders, the other folder name jest finds tests in. The two shared packages export modules from their tests and examples folders, so they turn the defaults off and ignore only their Markdown and LICENSE files. ci/release-plan-filter.Tests.ps1 holds the Pester tests of the filter.
This was referenced Nov 9, 2026
fiftyone.devicedetection.shared and fiftyone.ipintelligence.shared published the modules in their examples and tests folders through index.js, so the release plan could not ignore those folders for them. The modules now live in lib, the packages use the default ignore list, and a test checks the layout.
# Conflicts: # ip-intelligence/fiftyone.ipintelligence.shared/index.js # ip-intelligence/fiftyone.ipintelligence.shared/lib/exampleOutput.js # ip-intelligence/fiftyone.ipintelligence.shared/types/lib/exampleOutput.d.ts
Each old path under examples and tests is a one-line re-export of the module now in lib, and is listed in files so that it is published. The release plan still ignores both folders, and the stubs never change, so the code in lib decides whether a package is released.
…ports fixed A change to files in package.json decides what a package ships, so it counts towards a release. The layout test now names the six re-exports, so deleting one fails, and each re-export carries the licence header. AGENTS.md no longer calls the shared packages an exception.
Merged
rc changed the shared packages' tests/keyUtils.js and tests/testConstants.js, which this branch moved to lib with a one-line re-export at the old path. The changes are applied to the files in lib, and the environment variable name tests now name the files in lib, where the names are read.
…requires ci/publish-package.ps1 published every tarball in name order through common-ci's npm step, which stops at the first failure, and tagged nothing until all had published. So fiftyone.devicedetection went to npm before the seven packages it requires at the new version, and a publish that stopped part way left npm with untagged versions that the next run planned again and npm refused. Each planned package is now published, tagged and released in the plan's order before the next, and one npm already has is tagged and released without publishing it again, so a rerun finishes the release. ci/publish-package.Tests.ps1 runs the script against a repository of three packages with npm and gh replaced by stand-ins.
npm reads a relative path such as package/name.tgz as a GitHub repository and tries to clone it, which is how the Publish dry run failed.
npm read package/<name>.tgz as a GitHub repository and tried to clone it, which stopped the Publish dry run on the first package.
common-ci's plan leaves out a package tagged at HEAD and does not count it as a change for its dependants, so after a publish that stopped part way, a package whose only reason was a dependency already released and tagged was never released. Such a dependant is now added with the patch after its last release.
jwrosewell
marked this pull request as ready for review
November 14, 2026 06:36
This was referenced Nov 14, 2026
Draft
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.
Problem
Step 3.1 of common-ci#306.
ci/build-package.ps1line 35 at 21fa1199 runsnpm versionwith the run's one version for every package, so all 16 packages published 4.5.102 on 4 November 2026 (Publish run 41918901313) whatever had changed. That spends every package's allowance under the weekly release rule, and the release of 13 November would have done the same.The decisions in the run book apply. Each package has its own version, tagged
<package>/<version>, continuing from the version it last published, and only the patch number moves. A package is released when a file that counts under its folders changed since its last tag, and every package that depends on it is released with it, with its requirement raised to the new version. Documentation, tests, examples and manifest text never release a package (James Rosewell's decisions of 7 and 9 November).Change
ci/packages.jsonlists the 16 packages withName,Path,ExtraPaths,ExcludePaths,Ignore,DependsOnandPublish, read by common-ci'ssteps/release-plan.ps1at 1c5c0e0.DependsOnis the packages here that eachremote_package.jsonrequires, and the build stops when a manifest andDependsOndisagree. Both on-premise packages havecxxinExtraPaths, because their native modules compile from it.*.mdandLICENSEfile and everydocs,tests,testandexamplesfolder. Each package'sIgnoreadds**/__tests__/**, andExcludePathsleaves out itsexamplesfolder.ci/release-plan-filter.ps1leaves out apackage.jsonorremote_package.jsonwhose only changes are todescription,keywords,homepage,repository,bugs,author,licenseorreadme. A change to any other field counts,files,version, the dependencies,main,exportsandscriptsamong them.ci/release-plan-filter.Tests.ps1holds 25 Pester tests of the filter.ci/release-plan.ps1loads common-ci's step from the common-ci root the shared workflows run these scripts from, and adds the build plan and the versions the requirements are set from. Only the publish scripts load it, so the pull request builds do not need it. After a publish that stopped part way, it also plans each package not yet tagged at HEAD that depends on one that is, because common-ci's step leaves a package tagged at HEAD out of the plan and so does not count it as a change for its dependants.ci/get-next-package-version.ps1gives the run the highest planned version as its label, andci/package-update-required.ps1prints the plan and answers 1 when it is empty, as common-ci'snightly-publish.configure.ps1lines 37 to 48 expects.ci/build-package.ps1packs only the planned packages, each at its own version. Each requirement on a package here becomes^and that package's version once the release is out, being its planned version, or its last released version when it is not planned. When nothing is planned, every package is packed at its released version, so the nightly publish still tests packed packages.ci/install-package.ps1builds a native module from source when its package has no tarball, because that package is not being released.ci/publish-package.ps1publishes only the planned tarballs, in place of common-ci's npm step, which publishes every tarball in name order and stops at the first failure. Each planned package is published, tagged<package>/<version>and given one GitHub release with its tarball attached before the next, in the plan's order, which lists each package after the packages it depends on. So npm never offers a package before the versions it requires, and a publish that stops part way leaves every package before the failure released and tagged, which the next run then leaves out of its plan. A package npm already has at the planned version, which an earlier run published and did not tag, is tagged and released without publishing it again, as npm refuses a version twice.ci/publish-package.Tests.ps1runs the script against a repository of three packages, withnpmandghreplaced by stand-ins.ci/check-version-bump.ps1runs common-ci'ssteps/check-version-bump.ps1for each planned package against its own tags, and again against the version npm'slatestdist-tag gives, so that a tag pushed by hand or aFirstVersioncannot set where a package starts.ci/check-release-interval.ps1runs common-ci'ssteps/check-release-interval.ps1with-TagPrefixfor each planned package. common-ci'snightly-publish.ymlruns both in place of its own checks, as 51degrees-node is in itsOWN_CHECKlist (line 142 at 1c5c0e0).sharedpackages keep the code theirindex.jsexports inlib, so the default ignore list applies to them as to every other package.dataExtension.js,exampleConstants.jsandoptionsExtension.jsmoved fromexamples, andexampleOutput.js,keyUtils.jsandtestConstants.jsfromtests, with the generatedtypes. A one-line file at each old path re-exports the module inlib, sorequire('fiftyone.devicedetection.shared/tests/keyUtils')and the other five paths in each package still work.__tests__/layout.test.jsin each package checks the exports, the packed files and the re-exports.AGENTS.mddescribes the scheme in place of the single version, andci/packages.ps1loses$PublishedPackages, which nothing reads now.The merges of rc
313be18 merges
rcat 24592acb.rchad changed the shared packages'tests/keyUtils.jsandtests/testConstants.js(the deprecated environment variable names of #70 and #88), which this branch moved tolib, so those changes are applied to the files inlib. The environment variable name tests inci/testsnow name the files inlib, where the names are read. e305bf7 changes onlyAGENTS.md, and 8a5fe26 fixes the indentation of one line in each__tests__/layout.test.js, which the lint refused. 3af4682 mergesrcat 7cbf8bc7, which added #94 and #15, with no conflict.26dea568 changes
ci/publish-package.ps1to publish, tag and release each package in turn, after review found that the earlier script published in name order through common-ci's npm step, sofiftyone.devicedetectionreached npm before the seven packages it requires, and that a publish stopping part way left versions on npm that the next run planned again and npm refused. It addsci/publish-package.Tests.ps1. c21ff4f1 says so inAGENTS.md. A Publish dry run of c21ff4f (run 43520747902) then stopped at the first package, because npm read the relative pathpackage/fiftyone.devicedetection.shared-4.5.103.tgzas a GitHub repository and tried to clone it ("Permission denied (publickey)"). common-ci's npm step had passed npm the full path. 163a4241 makes the test'snpmstand-in refuse such a path, and 5e38889e gives npm the tarball's full path. 8d0bc615 tests a rerun whose only package left is a dependant with no change of its own, the case a review of the same scheme in PHP found, and eaf93b1d plans that dependant inci/release-plan.ps1. b239089c adds the workflow that runs these Pester tests, after review found that nothing would run them once this merged, and says so inAGENTS.md. It changes no script underci/.What had to come first
common-ci's #307, #310 and the
OWN_CHECKentry reached common-ci'smainwith common-ci#312 (1c5c0e0). The 16 tags below were pushed on 7 November as lightweight tags with no release, on384bff2d, the commit every package published 4.5.102 from, and npm'slatestis 4.5.102 for all 16. A lightweight tag is dated by its commit, 4 November, so the weekly check counts from then.Checks
Publishing each package in turn.
ci/publish-package.Tests.ps1runsci/publish-package.ps1against a repository of three packages,zeta.base,alpha.app, which requires it, andmid.tool, so name order and dependency order differ.npmandghare functions that keep a registry and the releases in memory, git is real, and origin is a bare repository. It checks that npm is given a path it reads as a file, that each package is published after the packages it requires, that a version npm already has is tagged and released without publishing it again, that a rerun after a publish that stopped onzeta.basefinishes with every package on npm and every tag pushed, that a rerun after one that stopped onalpha.app, whose only reason iszeta.base, publishesalpha.appalone, and that a dry run publishes nothing and pushes no tag.alpha.appwas published beforezeta.base, a version npm already had stopped the run ("npm refuses to publish over zeta.base@1.0.1"), and the rerun stopped onalpha.app@1.0.1, which the first run had published and not tagged. The dry run test passed.Every change to
ci/runs these tests. The CI script tests workflow ran on this pull request at the head b239089 (run 43558971492), as the pull request changesci/, and 30 of 30 Pester tests passed on Ubuntu and 30 of 30 on Windows, being the 5 ofci/publish-package.Tests.ps1and the 25 ofci/release-plan-filter.Tests.ps1. It runs again for every pull request and every push tomainorrcthat changesci/.The plan through the real Publish workflow. Run 43541104747 ran this repository's Publish workflow with
dryrunon a branch namedversion/owner-node-37-dryrun4, holding eaf93b1, whose files underci/are this head's, with the macOS entries left out ofci/options.jsonandskip-testsandskip-compare-performanceset. Aversion/branch was used because common-ci's Package step runsci/publish-package.ps1only onmain,alphaor aversion/branch (nightly-publish.package.ps1line 32 at 1c5c0e0). Every job that ran passed.4.5.102tag and one released because a package it depends on is.The changes behind each are real code. For example
fiftyone.pipeline.translation's one file istranslationEngine.js,fiftyone.devicedetection's isdeviceDetectionPipelineBuilder.js, and both on-premise packages count the move ofcxx.fiftyone.ipintelligence.translationhas no counted change of its own and is released becausefiftyone.pipeline.translationis.WEEKLY_RELEASES_FROMis not set.^4.5.103.ci/publish-package.ps1, which, for each of the 16 packages in turn and in the plan's order, rannpm publish --dry-run("+ fiftyone.pipeline.core@4.5.103" and so on) and then printed "Dry run - tagged 'fiftyone.pipeline.core/4.5.103' locally, not pushed, no release made".fiftyone.devicedetectionandfiftyone.ipintelligence, which require the most, came 15th and 16th. npm had none of the 16 at 4.5.103, so none was tagged without publishing. common-ci then printed "Tag update skipped", so no single4.5.103tag was made. Afterwards the repository has no tag holding4.5.103.Run 43526712326 on 5e38889, before the plan fix for a rerun, gave the same plan and output. Run 43492725405 on 3af4682 ran the earlier script, which published all 16 in name order through common-ci's npm step and then tagged them, so
fiftyone.devicedetectioncame first.The whole Publish workflow, tests included. Run 43476224513 ran the Publish workflow with
dryrunontmp/owner-node-37-publish, holding 313be18 merged with #95's head 0468ed4, which fixes the example that failed the 13 November publish, and with the macOS entries left out. Configure printed the same 16 packages, Build packed the same 16 tarballs, all six Test jobs on Ubuntu, Ubuntu ARM and Windows with Node.js 22 and 24 installed them withci/install-package.ps1and passed, and Compare Performance passed. On that branch name the Package step skipsci/publish-package.ps1, which is why the run above was made.Which package each kind of change releases. Run 43476196706 checked out 313be18 and common-ci
mainat 1c5c0e0. The 25 Pester tests of the filter passed. Then it tagged every package locally at HEAD, as if the next release had gone out, and for each of 14 scenarios made one local commit and compared the plan with the changed packages and every package that depends on one of them, worked out separately fromDependsOn. All 14 passed, each planned package one patch on from its tag.fiftyone.pipeline.did, offiftyone.geolocation, or offiftyone.ipintelligence.translationfiftyone.pipeline.enginesfiftyone.pipeline.corelib/keyUtils.jsoffiftyone.devicedetection.shared, orlib/dataExtension.jsoffiftyone.ipintelligence.sharedcxxsubmodule movedfiftyone.devicedetectionandfiftyone.ipintelligencepackage.jsonoffiftyone.pipeline.diddescription,keywordsandhomepagein three manifests__tests__file, an example and adocsfileci/options.json, a workflow,AGENTS.mdandREADME.mdThe commits after 313be18 change
AGENTS.md, two lines of tests,ci/publish-package.ps1and its tests, and whatrcbrought in, and none of the files that make the plan (ci/release-plan.ps1,ci/release-plan-filter.ps1andci/packages.json).Full build. Run 43559008982 on
tmp/pr-matrix-37-mon7, started bytools/pr-matrix.pywithout macOS, on the head b239089. All sevenSetting 'PullRequestSha'lines are b239089, Configure printed "Left out 2 macOS entries", and each of the six Ubuntu, Ubuntu ARM and Windows jobs on Node 22 and 24 passed 1,377 unit tests with 2 skipped and 132 integration tests with 4 skipped. macOS was left out of this draft's full build under the 9 November decision. The rc head is built with macOS before it merges into main. The full build on e305bf7 failed lint on one line's indentation in each__tests__/layout.test.js, which 8a5fe26 fixes, and run 43539579929 on eaf93b1 passed before the workflow was added.What remains
ExcludePathsand common-ci's default**/examples/**and**/docs/**now leave out the same folders, soExcludePathsand the code inci/release-plan.ps1that reads it could go in a later change.readme.mddoes not release it, so a README fix reaches npm with the package's next release for another reason.ci/build-extension.ps1and the Node.js versions inci/options.jsondecide the native modules the on-premise tarballs carry, but neither is under a package's folders, so a change to either releases nothing. Whether such a change should release the on-premise packages is a rule question for James.