Skip to content

Release a package only for a change that counts, leaving out documentation, tests, examples and manifest metadata - #60

Merged
jwrosewell merged 10 commits into
rcfrom
feature/release-plan-ignore
Nov 13, 2026
Merged

jwrosewell merged 10 commits into
rcfrom
feature/release-plan-ignore

Conversation

@jwrosewell

@jwrosewell jwrosewell commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

For the release rule of common-ci#306, in this repository, alongside common-ci#310.

The problem

James decided on 7 November that a package is not released when the only changes under its folders since its last tag are to documentation, tests, examples or manifest metadata such as links. The release plan here, Get-ReleasePlan in ci/packages.ps1, releases a package when git diff --quiet <package>/<version> HEAD reports any change under its Path or ExtraPaths, so a README, a test or an example releases the package and every package that depends on it. ci/get-next-package-version.ps1, ci/package-update-required.ps1, ci/build-package.ps1, ci/publish-package.ps1 and ci/write-package-versions.ps1 all take what they release from that one plan.

This repository does not use common-ci's shared steps/release-plan.ps1 yet. #47 switches to it. When this draft was written, common-ci#307 and common-ci#310 had not reached common-ci's main, which the workflows here use, and both have since, in common-ci's release of 12 November. So the rule is made to work in this repository's own copy, with the same fields, defaults and filter as the shared step has from common-ci#310, so that nothing changes in behaviour when #47 lands.

The change

ci/packages.ps1 takes the code of common-ci#310 at 7eb3d89 as it is, being $ReleasePlanDefaultIgnore, Get-PackageExcludes, Get-ChangedFiles and Select-CountedFiles, and Get-ReleasePlan now counts the files those leave.

  • Each entry in ci/packages.json may have Ignore, globs from the repository root whose changes do not count, and IgnoreDefaults, true when absent. No entry sets either yet.
  • The defaults are **/*.md, **/docs/**, **/tests/**, **/test/**, **/examples/** and **/LICENSE*, passed to git as :(exclude,glob,icase) pathspecs, and the Ignore globs as :(exclude,glob).
  • The reason now reads changed since 4.5.38 (1 file) or (3 files).
  • When git cannot list the changes, the plan stops naming the package, where git diff --quiet exiting with anything but 1 was read as no change before.
  • IgnoreDefaults given as anything but a JSON true or false stops the plan, and so does a path the filter returns that it was not given.
  • A submodule in Path or ExtraPaths, such as pipeline/owid-python for fiftyone_pipeline_did, changes as one path, so any move of it counts.

ci/release-plan-filter.ps1 is the hook both plans call, with -RepoPath, -Package, -From and -Files. Files other than a pyproject.toml, setup.py or setup.cfg all count. Those three go to ci/release-plan-filter.py, which compares each file at the tag and at HEAD with the metadata left out, and the file counts when anything else differs.

File What is left out before comparing
setup.py the description, long_description, long_description_content_type, keywords, url, project_urls, download_url, classifiers, author, author_email, maintainer and maintainer_email arguments of every setup() call. The rest is compared as a Python syntax tree, so comments and layout do not count either.
setup.cfg the same options in [metadata]. Every other section and option is compared.
pyproject.toml description, keywords, urls, classifiers, readme, authors and maintainers in [project], and the [project.urls], [project.authors], [project.maintainers] and [project.readme] tables. Blank lines and comments do not count.

A file that is missing at the tag or at HEAD, or that cannot be read, counts, so a doubt always releases. The TOML is read line by line, following tables, keys, bracketed values and triple-quoted strings, rather than with tomllib, because Python 3.10 has no tomllib and every job of a publish must work out the same plan whatever Python it has. For the same reason the filter stops with an error when it finds no Python rather than counting every file. The publish's Configure, Build and Package jobs run on ubuntu-latest, whose own Python the build step already calls as python, and the other jobs install one.

AGENTS.md says what counts.

How to verify

The tests are new It blocks in ci/packages.Tests.ps1, which build a throwaway repository with tags, as the file's other release plan tests do, and copy the real filter into it.

Red is rc at 0507eef with the new tests and the two filter files added and ci/packages.ps1 unchanged (run 42395975607). Green is this branch at 0713add (run 42399992499). Both ran Pester 5 on ubuntu-latest with its own Python (/usr/bin/python, 3.12.3, as the publish's Configure job has), on Windows with Python 3.10 and on macOS with Python 3.14.

  1. Red, failure on all three, Tests Passed: 39, Failed: 10, being the new tests of what does not count.
    [-] says how many files counted
    [-] releases nothing for a change only to documentation, tests or examples
    [-] ignores documentation, tests and examples whatever their case
    [-] releases for the code changed beside the documentation
    [-] leaves out the files a package's Ignore globs match
    [-] does not release for a setup.py change only to metadata
    [-] releases for a setup.py change to anything else
    [-] counts the code changed beside a setup.py change only to metadata
    [-] does not release for a setup.cfg change only to metadata
    [-] does not release for a pyproject.toml change only to metadata
    
    The others, such as releases for a setup.cfg change to its options and releases for a manifest it cannot read, passed on rc as well, because rc releases for any change.
  2. Green, success on all three, Tests Passed: 50, Failed: 0. Two commits since then decode a manifest inside the guarded comparison, so one that is not UTF-8 counts rather than stopping the plan, and test that. On those (d3ce8df) Ubuntu and Windows gave Tests Passed: 51, Failed: 0 (run 42403623093).
  3. With common-ci's shared step. The same job checked out common-ci#310 at 7eb3d89 and ran ci/packages.Tests.ps1 with its steps/release-plan.ps1 loaded after ci/packages.ps1, so the shared step's functions replaced this repository's ones and called this branch's filter. Tests Passed: 50, Failed: 0.
  4. Dry-run plans of this commit against the real tags, from rc's ci/packages.ps1, from this branch's and from the shared step with this branch's filter. The last two were the same, as the job checks. All three release the same 15 packages at the same versions, because fiftyone_pipeline_core and fiftyone_pipeline_engines_fiftyone changed in their code and most packages depend on them. The difference is in the reasons.
    fiftyone_pipeline_core                 counts  pipeline/fiftyone_pipeline_core/src/fiftyone_pipeline_core/callback_url.py
    fiftyone_pipeline_core                 ignored pipeline/fiftyone_pipeline_core/tests/test_callback_url.py
    fiftyone_ipintelligence_translation    counts  ip-intelligence/fiftyone_ipintelligence_translation/tox.ini
    fiftyone_pipeline_engines_fiftyone     ignored pipeline/fiftyone_pipeline_engines_fiftyone/examples/usagesharing/51d.json
    fiftyone_ipintelligence_shared         counts  ip-intelligence/fiftyone_ipintelligence_shared/tox.ini
    fiftyone_location                      counts  location/tox.ini
    fiftyone_devicedetection_cloud         counts  device-detection/fiftyone_devicedetection_cloud/tox.ini
    fiftyone_ipintelligence_cloud          counts  ip-intelligence/fiftyone_ipintelligence_cloud/tox.ini
    fiftyone_ipintelligence                ignored ip-intelligence/fiftyone_ipintelligence/examples/gettingstarted.py
    
    fiftyone_ipintelligence was "changed since 4.5.3" under rc's rule, for an example alone, and is now "a package it depends on is released". Five packages changed only in their tox.ini, which no longer counts (see the tox.ini section below).

Change to tox.ini of 9 November

James Rosewell decided that a change to tox.ini alone must not release a package. Commit 3668b67 and the commit before it add "Ignore": ["**/tox.ini"] to all 19 entries in ci/packages.json. Fifteen of those packages have a tox.ini beside them today. The other four (fiftyone_pipeline_examples, fiftyone_devicedetection_shared, fiftyone_devicedetection, fiftyone_ipintelligence) have none, and they carry the entry as well so that a tox.ini added later releases nothing. The tox.ini under pipeline/fiftyone_pipeline_cloudrequestengine/examples was already ignored by the examples default.

Three new tests in ci/packages.Tests.ps1 read the real ci/packages.json. One changes the tox.ini of every package and expects an empty plan, one changes the source and tox.ini of fiftyone_pipeline_core and expects that package released for the one source file, and one checks every entry carries the ignore.

  • Red, on this branch before the change with the tests added, run 42686848374 failed 3 of 54 tests. A tox.ini-only change released 16 packages.
  • A first green attempt, run 42686876250, still released 5 packages, because the change then covered only the 15 packages with a tox.ini and the scratch history gave the other four one. That is why all 19 entries carry the ignore.
  • Green, run 42689458155 at head 01570211 (the temporary branch holding this branch plus a workflow). All 54 Pester tests passed. The same run built a scratch git history from the real ci/packages.json, tagged every published package at 4.5.1 and printed the plan. A commit changing only every package's tox.ini released 0 packages. A commit changing fiftyone_pipeline_core source and its tox.ini released 15 packages, fiftyone_pipeline_core for 1 file and the rest as dependents.
  • Open question 1 of this body, whether tox.ini should count, is decided and has been removed.

Maintainers, 13 November

The earlier version of this body asked James whether the maintainer fields should be left out as the authors are. The rule of 7 November leaves out manifest metadata such as links and names no fields. I read maintainer and maintainer_email in setup.py and setup.cfg, and maintainers in pyproject.toml, as manifest metadata of the same kind as the authors, which the filter already left out, because they name people to contact and change nothing that is installed. The pyproject.toml specification describes the two keys in one section, authors/maintainers, and says "The "maintainers" key is similar to "authors" in that its exact meaning is open to interpretation." So ci/release-plan-filter.py leaves them out too. license and python_requires still count, because they change the terms a package is published under and the Pythons that can install it, which is more than metadata. No package here sets a maintainer today.

Four new cases of one test, does not release for a change only to the maintainers in <Case>, add the maintainers to a setup.py, a setup.cfg, a pyproject.toml key and a [[project.maintainers]] table, and expect no release.

  • Red, the tests without the filter change at e2220a18, run 43474649904, failed on ubuntu-latest and windows-latest, Tests Passed: 151, Failed: 4, being the four new cases.
  • Green, at 766fe11, run 43474666896, passed on both, Tests Passed: 155, Failed: 0. Both runs are temporary branches holding a workflow that runs every ci/*.Tests.ps1 with Pester and then prints the release plan of the branch against the real tags. The plan was empty, so rc with this draft releases nothing, as rc holds only CI and documentation changes since the release of 13 November.

The head

Head ec8b2fdd is the earlier head 3668b67 with rc at df0949d7 merged in, then the maintainers test and the change above at 766fe11, then a commit that adds the maintainers to the list of fields in the comment of ci/release-plan-filter.ps1 and changes no code. rc changed none of ci/packages.ps1, ci/packages.json or ci/get-next-package-version.ps1 since this draft's base 0507eef, so the red and green runs above for the earlier commits still hold for that code.

This draft changes only CI scripts, their tests and AGENTS.md, with no package code. James Rosewell decided at about 11:35 UTC on 12 November, for such a change, "rebuild and include, but the change doesn't impact the code so no need to run the full builds." So it has no full build. A full build was started on the earlier head 3668b67 as run 42694898479 and ended cancelled, its five macOS jobs having started and been cancelled, so it is not evidence for this draft. Its quick checks passed on this head, being run 43489897620 (environment variable names), run 43489898225 (only rc into main) and run 43489897522 (link campaign tags).

The AGENTS.md paragraph this draft changes no longer joins clauses with a semicolon or a colon.

What remains

The last release into main was #114, merged at 06:22 UTC on 13 November.

A package's tox.ini sets up its test environments and is not part of
what is published, so a change to it alone no longer releases the
package. Each package with a tox.ini ignores it in packages.json, and
the tests cover the real package list.
@jwrosewell
jwrosewell marked this pull request as ready for review November 13, 2026 22:29
@jwrosewell
jwrosewell merged commit 5eb295c into rc Nov 13, 2026
3 checks passed
@jwrosewell
jwrosewell deleted the feature/release-plan-ignore branch November 13, 2026 22:29
jwrosewell added a commit that referenced this pull request Nov 14, 2026
The scripts in `ci/` decide what a pull request builds and what a publish releases, and each has Pester tests beside it. `rc` holds five such files, being `ci/packages.Tests.ps1`, `ci/dispatch.Tests.ps1`, `ci/check-environment-variable-names.Tests.ps1`, `ci/get-next-package-version.Tests.ps1` from [#54](#54) and `ci/select-options.Tests.ps1` from [#33](#33). Only the environment variable name tests ran in a workflow. The rest ran only by hand or on a temporary branch, as [#47](#47), [#54](#54) and [#60](#60) each say under what remains, so a change to the release plan or the dispatcher could break them unseen.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant