Commit Graph

28 Commits

Author SHA1 Message Date
Jan Tojnar
ce96c79779 maintainers/scripts/update: Allow updating in (reverse) topological order
Previously, when updating multiple packages, we just updated them in arbitrary order. However, when some of those packages depended on each other, it could happen that some of the intermediary commits would not build because of version constraints on dependencies.

If we want each commit in the history to build when feasible, we need to consider four different scenarios:

1. Updated dependant is compatible with both the old and the new version of the dependency. Order of commits does not matter. But updating dependents first (i.e. reverse topological order) is useful since it allows building each package on the commit that updates it with minimal rebuilds.
2. Updated dependant raises the minimal dependency version. Dependency needs to be updated first (i.e. topological order).
3. Old dependant sets the maximal dependency version. Dependant needs to be updated first (i.e. reverse topological order).
4. Updated dependant depends on exact version of dependency and they are expected to be updated in lockstep. The earlier commit will be broken no matter the order.

This change allows selecting the order of updates to facilitate the first three scenarios. Since most package sets only have loose version constraints, the reverse topological order will generally be the most convenient. In major package set updates like bumping GNOME release, there will be exceptions (e.g. libadwaita typically requires GTK 4 from the same release) but those were probably in broken order before as well.

The downside of this feature is that it is quite slow – it requires instantiating each package and then querying Nix store for requisites.
It may also fail to detect dependency if there are multiple variants of the package and dependant uses a different one than the canonical one.

Testing with:

    env GNOME_UPDATE_STABILITY=unstable NIX_PATH=nixpkgs=$HOME/Projects/nixpkgs nix-shell maintainers/scripts/update.nix --arg predicate '(path: pkg: path == ["gnome-shell"] || path == ["mutter"] || path == ["glib"] || path == ["gtk3"] || path == ["pango"] || path == ["gnome-text-editor"])' --argstr order reverse-topological --argstr commit true --argstr max-workers 4
2025-03-03 00:46:17 +01:00
Jan Tojnar
1d2c1810eb maintainers/scripts/update: Prepare for ordered updates
Just minor refactorings:

- Extract `updater_tasks` into a variable.
- Make `main` itself async.
2025-03-03 00:46:17 +01:00
Jan Tojnar
f54d20c3a1 maintainers/scripts/update: Do not try to print error when there is not one
This can happen e.g. due to an error during `merge_changes` since we do not do `stderr=PIPE` for git commands.
2025-03-03 00:46:06 +01:00
Jan Tojnar
e3772a9bcb maintainers/scripts/update: Mark queue jobs as done
I believe this is only relevant if we were to `join` the queue itself but it is a good practice anyway.
https://docs.python.org/3/library/asyncio-queue.html#asyncio.Queue.task_done
2025-03-02 23:03:12 +01:00
Jan Tojnar
fdea10b433 maintainers/scripts/update: Fix update_info type
This was revealed when we added return type to `check_subprocess_output`.
2025-03-02 23:03:12 +01:00
Jan Tojnar
76f44542a8 maintainers/scripts/update: Add missing type hints 2025-03-02 23:03:12 +01:00
Jan Tojnar
81aed8eb80 maintainers/scripts/update: Modernize types
`list`, `dict` and `tuple` can accept generic arguments since Python 3.9:
https://docs.python.org/3.9/whatsnew/3.9.html#type-hinting-generics-in-standard-collections

`T | None` can be used instead of `Optional` since 3.10:
https://docs.python.org/3.10/whatsnew/3.10.html#pep-604-new-type-union-operator
2025-03-02 23:03:12 +01:00
Jan Tojnar
b91cb89649 maintainers/scripts/update: Format with black 2025-03-02 23:03:12 +01:00
Michael Hoang
e81b7d4f57 maintainers/scripts/update.nix: avoid deadlock
Use `Process.communicate()` instead of `Process.wait()` to ensure the
`stdin` and `stdout` OS pipe buffers don't get full and cause a deadlock
waiting for the buffers to get emptied.
2024-10-14 18:47:31 -03:00
Jan Tojnar
9fc19b0866 maintainers/scripts/update.py: Fix worktree cleanup on failure
The context manager would previously just terminate early on exception.
As a result, the worktree and branch would not get pruned when update script failed.

Let’s wrap the cleanup code in `finally` block as suggested by Python docs:
https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager
2024-07-13 15:48:17 +02:00
superherointj
abce0bda0b maintainers/scripts/update.py: support skipping prompts 2024-06-14 14:09:13 -03:00
Stanisław Pitucha
f42b9fd745 maintainers/scripts/update.nix: Remove unicode from message and comply with CONTRIBUTING.md
It's not used infrequently and the ascii version is nicer for automatic parsing.
```
git log --grep '->' --oneline --since '2022-01-01' | wc -l
   67791
git log --grep '→' --oneline --since '2022-01-01' | wc -l
    2914
```
2023-04-05 11:28:47 +10:00
José Romildo
1f239257c5 maintainers/scripts/update.nix: make package name, pname and old version available to the update script 2022-09-26 22:16:19 -03:00
Winter
814026db2d maintainers/scripts/update.nix: exit with nonzero exit code when script fails 2022-09-20 17:59:07 -04:00
Jan Tojnar
3cce255fc1 maintainers/scripts/update.nix: Add experimental support for customizing commit message 2022-02-21 19:12:35 +01:00
Jan Tojnar
a20a4af62a maintainers/scripts/update.nix: Support committing with nix-update-script
When updating a package using nix-update-script with `--argstr commit true`,
update.nix would not detect the changes because nix-update would stage them
and `git diff` would be empty.

We now detect both staged and unstaged changes to handle this use case.
2021-10-31 11:00:37 +01:00
Jan Tojnar
416cd66e29
maintainers/scripts/update.nix: Ensure the worktree is clean
When an update script fails, it might still modify the source tree.
These changes would then be committed in the next update attempt.
Let’s make sure the worktree is clean before updating to avoid that.
2021-05-05 22:42:30 +02:00
Jan Tojnar
71c246c785
maintainers/scripts/update.nix: Run update scripts from the worktree
`update.nix` extracts `passthru.updateScript` attributes in the main repo
and when they are relative paths (e.g. `./update.sh`), Nix will resolve them
to absolute paths in the main repo.

Update scripts can use $(dirname $0) to get the location of files they
should update but that would point to the main repo.
We want them to modify the appropriate git worktree instead
so we replace the prefix accordingly.

`git rev-parse --show-toplevel` will resolve symlinks but, fortunately,
Nix will do that as well, so the path will match:

https://github.com/NixOS/nixpkgs/pull/98304#issuecomment-695761754
2020-09-20 20:12:34 +02:00
Jan Tojnar
0c5ddf3358
maintainers/scripts/update.nix: run update script with UPDATE_NIX_ATTR_PATH
The environment variable will contain the attribute path the script is supposed to update.
2020-09-20 20:12:33 +02:00
Jan Tojnar
c21a85c6a0
maintainers/scripts/update.nix: auto-detect attrPath 2020-09-20 20:11:46 +02:00
Jan Tojnar
b351de0971
maintainers/scripts/update.nix: mention when there were no changes committed 2020-09-20 20:11:46 +02:00
Jan Tojnar
b828285933
maintainers/scripts/update.nix: support filling in auto-commit attributes
We can determine all of them when attrPath is present so we might jsut as well do it.
2020-09-20 20:11:46 +02:00
Jan Tojnar
4a161ddb3b
maintainers/scripts/update.nix: support auto-committing by passing attrPath
Instead of having the updateScript support returning JSON object,
it should be sufficient to specify attrPath in passthru.updateScript.
It is much easier to use.

The former is now considered experimental.
2020-09-20 20:11:46 +02:00
Jan Tojnar
01b9d5371c
maintainers/scripts/update.nix: switch to asyncio
This will make it cleaner and also better respect SIGTERM.
2020-09-20 20:11:45 +02:00
Jan Tojnar
17f89667b3
maintainers/scripts/update.nix: refactoring
Get rid of some globals, split main into smaller functions, rename some variables, add typehints.
2020-09-20 20:11:45 +02:00
Jan Tojnar
1efc042d92
maintainers/scripts/update.nix: Add support for auto-commiting changes
Update scripts can now declare features using

	passthru.updateScript = {
	  command = [ ../../update.sh pname ];
	  supportedFeatures = [ "commit" ];
	};

A `commit` feature means that when the update script finishes successfully,
it will print a JSON list like the following:

	[
	  {
	    "attrPath": "volume_key",
	    "oldVersion": "0.3.11",
	    "newVersion": "0.3.12",
	    "files": [
	      "/path/to/nixpkgs/pkgs/development/libraries/volume-key/default.nix"
	    ]
	  }
	]

and data from that will be used when update.nix is run with --argstr commit true
to create commits.

We will create a new git worktree for each thread in the pool and run the update
script there. Then we will commit the change and cherry pick it in the main repo,
releasing the worktree for a next change.
2020-09-20 20:11:22 +02:00
Jan Tojnar
5adbeb13c5
update.nix: use ThreadPoolExecutor
Not sure why I chose ProcessPoolExecutor in the first place.
2020-09-18 20:52:07 +02:00
Jan Tojnar
59a94b57f0
update.nix: Run update scripts in parallel
To make updating large attribute sets faster, the update scripts
are now run in parallel.

Please note the following changes in semantics:

- The string passed to updateScript needs to be a path to an executable file.
- The updateScript can also be a list: the tail elements will then be passed
  to the head as command line arguments.
2018-12-01 19:17:13 +01:00