Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compose: Add --ex-lockfile-strict #1858

Merged
merged 1 commit into from
Apr 17, 2020

Conversation

jlebon
Copy link
Member

@jlebon jlebon commented Jun 14, 2019

Today, lockfiles only restrict the NEVRA of specifc package names from
which libsolv can pick. But nothing stops libsolv from picking entirely
different packages which still satisfy the manifest requests.

This was mostly a theoretical issue in Fedora CoreOS, but became reality
with the addition of Fedora 32 packages in the pool. libsolv would
happily try to pick e.g. libcurl-minimal from f32 instead of sticking
with the f31 libcurl from the lockfiles:

coreos/fedora-coreos-streams#75 (comment)

(But more generally, see
coreos/fedora-coreos-tracker#454).

Let's add a --ex-lockfile-strict mode, which in CI and production
pipeline build contexts will require that (1) only locked packages are
considered by libsolv, and (2) all locked packages were marked for
install.

One important thing to note here is that we don't short-circuit libsolv
and manually hy_goal_install lockfile packages. We want to make sure
the treefile is still canonical. Strict mode simply ensures that the
result agrees with the lockfile.

That said, even in developer contexts, we don't want the
libcurl-minimal issue that happened to be triggered. But we still want
to allow flexibility in adding and removing packages to make hacking
easier. I have some follow-up patches which will enable this.


Note: part (2) above was no longer true when this PR was merged, but I forgot to fix the commit message. See #1858 (comment).

@jlebon
Copy link
Member Author

jlebon commented Jun 14, 2019

There's possibly a cleaner way of doing this. One issue is that there's no "fail instead of installing dependencies" flag to give to libdnf. We could avoid depsolving entirely and let librpm depcheck the transaction, though we rely on the goal in a bunch of places too.

@cgwalters
Copy link
Member

cgwalters commented Jun 14, 2019

We talked through this when the lockfile semantics were being added, today we match e.g. cargo and I believe the rationale there is it's way more convenient for development.

Probably what we want here is really for the *COS pipelines to use cosa build --lockfile-strict?

@jlebon jlebon added the WIP label Jun 14, 2019
@jlebon
Copy link
Member Author

jlebon commented Jun 14, 2019

Right yeah, I'm open to switching the default vs flagged options around.

@dustymabe
Copy link
Member

Right yeah, I'm open to switching the default vs flagged options around.

I'm 👍 for either way as the default.

@rh-atomic-bot
Copy link

☔ The latest upstream changes (presumably dbf28ac) made this pull request unmergeable. Please resolve the merge conflicts.

@jlebon jlebon changed the title WIP: compose: Add --ex-lockfile-relaxed and default to strict compose: Add --ex-lockfile-strict Apr 14, 2020
@jlebon jlebon removed the WIP label Apr 14, 2020
@jlebon
Copy link
Member Author

jlebon commented Apr 14, 2020

OK, reworked this! Commit message updated.
Split out prep patches in #2057.

@jlebon
Copy link
Member Author

jlebon commented Apr 15, 2020

Rebased! (And reworked the relaxed path to be more efficient.)

@jlebon
Copy link
Member Author

jlebon commented Apr 15, 2020

Would appreciate some eyes on this and #2058 soon-ish!

Copy link
Member

@cgwalters cgwalters left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, this looks very good! That said, per our live discussion I am increasingly feeling that what we really want to do is reify this - we should extract something like:

rpm-ostree compose update-locked-rpmmd-repo --lockfile /path/to/lockfile.json --rpmmd-repo /path/to/repo

And we run that as a service that generates e.g. coreos-testing-devel.repo coreos-stable.repo etc.

This would make it trivial to use e.g. dnf download to get access to an RPM locked in this way, which would be generally useful.

And further then, this complex and subtle lockfile logic doesn't need to live in rpm-ostree, it could live in libdnf or some other tool/library that runs on the buildsystem side.

The huge difference between what we're doing and what Rust's cargo and other tools like that are doing is that we actually want to enforce a lot of uniformity in what we're locking, we don't expect many other consumers.

g_autoptr(GHashTable) goal_nevras =
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
for (guint i = 0; i < pkgs->len; i++)
g_hash_table_add (goal_nevras, g_strdup (dnf_package_get_nevra (pkgs->pdata[i])));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(If we were writing this in Rust we could be confident to avoid a strdup because we could guarantee the lifetime of the hashset with nevra is <= lifetime of the pkgs list)

return NULL;

if (g_str_equal (chksum, repodata_chksum))
g_ptr_array_add (pkgs, g_object_ref (match));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about something like:
n_checksum_mismatches++;
and then below:

g_ptr_array_add (pkgs, g_object_ref (match));
}
}
if (old_pkgs_len == pkgs->len)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think an if (matched) would be a bit clearer here.

}
}
if (old_pkgs_len == pkgs->len)
return glnx_null_throw (error, "Couldn't find locked package '%s'%s%s",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(%d non-matching packages), n_checksum_mismatches or so?

}
Map *map = dnf_packageset_get_map (pset);
map_setall (map);
map_subtract (map, dnf_packageset_get_map (locked_pset));
dnf_sack_add_excludes (sack, pset);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine as is, but it'd be clearer if there was an API like dnf_sack_include_only(locked_pset).

Today, lockfiles only restrict the NEVRA of specifc package names from
which libsolv can pick. But nothing stops libsolv from picking entirely
different packages which still satisfy the manifest requests.

This was mostly a theoretical issue in Fedora CoreOS, but became reality
with the addition of Fedora 32 packages in the pool. libsolv would
happily try to pick e.g. `libcurl-minimal` from f32 instead of sticking
with the f31 `libcurl` from the lockfiles:

coreos/fedora-coreos-streams#75 (comment)

(But more generally, see
coreos/fedora-coreos-tracker#454).

Let's add a `--ex-lockfile-strict` mode, which in CI and production
pipeline build contexts will require that (1) *only* locked packages are
considered by libsolv, and (2) *all* locked packages were marked for
install.

One important thing to note here is that we don't short-circuit libsolv
and manually `hy_goal_install` lockfile packages. We want to make sure
the treefile is still canonical. Strict mode simply ensures that the
result agrees with the lockfile.

That said, even in developer contexts, we don't want the
`libcurl-minimal` issue that happened to be triggered. But we still want
to allow flexibility in adding and removing packages to make hacking
easier. I have some follow-up patches which will enable this.
@jlebon
Copy link
Member Author

jlebon commented Apr 17, 2020

Updated for comments! I also ended up dropping check_locked_pkgs entirely after more thinking. Basically, having some packages in the lockfile but not in the transaction is now acceptable in strict mode too. This can happen if we add an override which pulls in less deps than the overridden package. That said of course, we still ensure that all packages we do pull in are locked, which is the most important part.

@jlebon
Copy link
Member Author

jlebon commented Apr 17, 2020

/test sanity

@jlebon
Copy link
Member Author

jlebon commented Apr 17, 2020

With nuking check_locked_pkgs we also drop the check that there are only DNF_PACKAGE_INFO_INSTALL goals, but note that this patch instead introduces an assertion check here: https://github.com/coreos/rpm-ostree/pull/1858/files#diff-07963b1a5922690400970963652cbe3bR1961-R1968.

@cgwalters
Copy link
Member

/test sanity
Should be fixed now

@cgwalters
Copy link
Member

/lgtm

@openshift-ci-robot
Copy link
Collaborator

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: cgwalters, jlebon

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-merge-robot openshift-merge-robot merged commit 5345673 into coreos:master Apr 17, 2020
jlebon added a commit to jlebon/rpm-ostree that referenced this pull request Apr 20, 2020
Minor follow-up to coreos#1858. Make the help string here more helpful and
accurate.
jlebon added a commit to jlebon/rpm-ostree that referenced this pull request Apr 20, 2020
Minor follow-up to coreos#1858. Make the help string here more helpful and
accurate.
openshift-merge-robot pushed a commit that referenced this pull request Apr 20, 2020
Minor follow-up to #1858. Make the help string here more helpful and
accurate.
@jlebon jlebon deleted the pr/strict-lockfile branch April 23, 2023 23:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants