ros2 / ci

ROS 2 CI Infrastructure
http://ci.ros2.org/
Apache License 2.0
48 stars 30 forks source link

Switch to always opting into phased updates. #709

Closed nuclearsandwich closed 1 year ago

nuclearsandwich commented 1 year ago

When initially installing a package, phased update percentage is not considered at all. It's only used when considering package upgrades.

As a result, opting out of phased updates can create a situation where a package from the updates repository is installed during the container build in an earlier phase, but a later installation may try to install dependencies in sibling packages which are not available at the required version due to being behind the phased update percentage wall.

This is intended to be an alternative to #708


As of the time these tests were performed, the following was the entry for dovecot-core in the contents of the jammy-updates repository for amd64. I picked dovecot-core because it was the first result for a phased update and doesn't have too many dependencies.

Package: dovecot-core
Architecture: amd64
Version: 1:2.3.16+dfsg1-3ubuntu2.2
Priority: optional
Section: mail
Source: dovecot
Origin: Ubuntu
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Original-Maintainer: Dovecot Maintainers <dovecot@packages.debian.org>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 10308
Provides: dovecot-abi-2.3.abiv16, dovecot-common
Pre-Depends: init-system-helpers (>= 1.54~)
Depends: adduser, libpam-runtime, lsb-base, openssl, ssl-cert, ucf, libapparmor1 (>= 2.7.0~beta1+bzr1772), libbz2-1.0, libc6 (>= 2.34), libcap2 (>= 1:2.10), libcrypt1 (>= 1:4.1.0), libexttextcat-2.0-0 (>= 3.3.0), libicu70 (>= 70.1-1~), liblua5.3-0, liblz4-1 (>= 0.0~r130), liblzma5 (>= 5.1.1alpha+20120614), libpam0g (>= 0.99.7.1), libsodium23 (>= 1.0.13), libssl3 (>= 3.0.0~~alpha1), libstemmer0d (>= 0+svn527), libsystemd0, libtirpc3 (>= 1.0.2), libwrap0 (>= 7.6-4~), libzstd1 (>= 1.4.0), zlib1g (>= 1:1.1.4)
Suggests: dovecot-gssapi, dovecot-imapd, dovecot-ldap, dovecot-lmtpd, dovecot-lucene, dovecot-managesieved, dovecot-mysql, dovecot-pgsql, dovecot-pop3d, dovecot-sieve, dovecot-solr, dovecot-sqlite, dovecot-submissiond, ntp
Breaks: dovecot-common (<< 1:2.0.14-2~), mailavenger (<< 0.8.1-4)
Replaces: dovecot-common (<< 1:2.0.14-2~), mailavenger (<< 0.8.1-4)
Filename: pool/main/d/dovecot/dovecot-core_2.3.16+dfsg1-3ubuntu2.2_amd64.deb
Size: 3319176
MD5sum: c9dde8c23854efc06772501e128ca852
SHA1: db94aabd11c4aa106923a9c9c605b97e41c01613
SHA256: d38c2632f220e28da8c8aa8796353a6ddaec19ea6b8ab8ca53d854e5018d222a
SHA512: 28ead9414eff88656ca90fec0ba3f244242a2e6ee3bfab53bef7b95e30efefb175a7bad9f782948d048949c5351b052b469c92483c0bd4790a89c3332e0d170b
Homepage: https://dovecot.org/
Description: secure POP3/IMAP server - core files
Task: mail-server
Description-md5: 42825422b1ef9e3a592c94dfafed375c
Phased-Update-Percentage: 50

Two initial base images always, and never.

FROM ubuntu:jammy as always
RUN echo 'apt::get::always-include-phased-updates "true";' > /etc/apt/apt.conf.d/90-phased-updates
RUN apt update
RUN apt install -y dovecot-core
CMD apt list --installed | grep dovecot-core
FROM ubuntu:jammy as never
RUN echo 'apt::get::never-include-phased-updates "true";' > /etc/apt/apt.conf.d/90-phased-updates
RUN apt update
RUN apt install -y dovecot-core
CMD apt list --installed | grep dovecot-core

In both cases, the output from docker run ... is the same


WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

dovecot-core/jammy-updates,now 1:2.3.16+dfsg1-3ubuntu2.2 amd64 [installed]

So empirically, the phased update configuration has no bearing on what is considered an installation candidate for an initial install. This seems overall problematic but maybe we're doing something very unusual here.

If we simulate our scenario by forcing the install of the base version of the package, we get the following pair of image builds:

FROM ubuntu:jammy as always
RUN echo 'apt::get::always-include-phased-updates "true";' > /etc/apt/apt.conf.d/90-phased-updates
RUN apt update
RUN apt install -y dovecot-core=1:2.3.16+dfsg1-3ubuntu2.1
CMD apt list --installed | grep dovecot-core
FROM ubuntu:jammy as never
RUN echo 'apt::get::never-include-phased-updates "true";' > /etc/apt/apt.conf.d/90-phased-updates
RUN apt update
RUN apt install -y dovecot-core=1:2.3.16+dfsg1-3ubuntu2.1
CMD apt list --installed | grep dovecot-core

Again in both cases, the output is, perhaps surprisingly, the same:


WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

dovecot-core/jammy-security,now 1:2.3.16+dfsg1-3ubuntu2.1 amd64 [installed,upgradable to: 1:2.3.16+dfsg1-3ubuntu2.2]

Even where phased updates are opted-out, the package is listed as upgradeable. When running apt upgrade we see an actual difference.

Always:

# apt upgrade
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Calculating upgrade... Done
The following packages will be upgraded:
  dovecot-core libncurses6 libncursesw6 libssl3 libtinfo6 ncurses-base ncurses-bin
7 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 5788 kB of archives.
After this operation, 4096 B disk space will be freed.
Do you want to continue? [Y/n]

Never:

# apt upgrade
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Calculating upgrade... Done
The following packages have been kept back:
  dovecot-core
The following packages will be upgraded:
  libncurses6 libncursesw6 libssl3 libtinfo6 ncurses-base ncurses-bin
6 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.
Need to get 2469 kB of archives.
After this operation, 4096 B disk space will be freed.
Do you want to continue? [Y/n]

One odd thing, I couldn't reproduce the behavior where an installation of a new package would fail when a set of dependencies conflicted.

I tried installing dovecot-imapd, which had a dependency on dovecot-core (= 1:2.3.16+dfsg1-3ubuntu2.2) and in both scenarios this resulted in the version of dovecot-core getting installed.

So I'm starting to suspect that this is an issue with recovering from a phased update being completely removed (as it seems the mesa update has been, as of now) and that nothing we do in this configuration will actually make one jot of difference in that scenario since it does not seem that anything would allow us to recover short of completely busting the docker image cache.


So this PR does not seem likely to resolve this class of error in the future. I debated just closing it, but on balance I think that switching to opt-in for phased updates will make the image more consistent with what will actually get put on it during the build phase, and if in the future apt changes to respecting this value during initial package installation it will make it will ensure continuity of behavior.

Other controls, such as forcing a full --no-cache build once in a while or catching apt issues in a post-build heuristic and retriggering after a cache purge would be potential ways to address this core problem.

claraberendsen commented 1 year ago

Test builds

ros-discourse commented 1 year ago

This pull request has been mentioned on ROS Discourse. There might be relevant details there:

https://discourse.ros.org/t/ros-infrastructure-updates-from-june-2023/32258/1