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

cask/audit: add audit_min_os #16013

Merged
merged 3 commits into from Nov 6, 2023

Conversation

razvanazamfirei
Copy link
Member

@razvanazamfirei razvanazamfirei commented Sep 18, 2023

  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same change?
  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes? Here's an example.
  • Have you successfully run brew style with your changes locally?
  • Have you successfully run brew typecheck with your changes locally?
  • Have you successfully run brew tests with your changes locally?

This PR adds an audit to ensure that the minimum macOS version specified in the cask matches the minimum macOS version specified by the developer.

It does so by:

  1. Hijacking audit_livecheck_min_os to obtain the sparkle version information.
  2. Adding audit_plist_min_os to extract the version information from Info.plist.
  3. Comparing the cask min_os version with the extracted value. If both a sparkle min_os and plist min_os are present, we take the larger value of the two.

Note: This will break a lot of casks.

Comment on lines 544 to 549
def audit_min_os
odebug "Auditing minimum OS version"

sparkle_min_os = audit_livecheck_min_os
plist_min_os = audit_plist_min_os
min_os_string = [sparkle_min_os, plist_min_os].max
Copy link
Member

Choose a reason for hiding this comment

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

Worth noting that this will run as three audits as each audit is automatically run via looking for audit_-prefixed methods. It seems the intention here is to have one audit that calls these two methods, in which case you will have to rename these to something different and just have audit_min_os with the audit_ prefix

Copy link
Contributor

@apainintheneck apainintheneck left a comment

Choose a reason for hiding this comment

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

Just out of curiosity, do you have guesstimates for the number of casks that will fail this audit and how long it will take to run on average? I believe the cask repo runs online audits by default, right?

Comment on lines 620 to 639
path = tmpdir/artifact_path.relative_path_from(cask.staged_path)

next unless path.exist?

plist_path = "#{path}/Contents/Info.plist"
next unless File.exist?(plist_path)
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: We probably don't need the path check if we're checking for the existence of the file later on.

Copy link
Member

@p-linnane p-linnane Sep 21, 2023

Choose a reason for hiding this comment

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

There will probably be a large number of failures, since up until now we've only had an audit for Sparkle. Everything else has either been checking the .plist manually when the cask is added or referring to documentation.

@razvanazamfirei
Copy link
Member Author

I'm incorporating the comments made by people, but also slowly going through casks and updating min_os versions. If we end up implementing something akin to this audit, I think the effort required to update all the casks won't be trivial.

@apainintheneck

Number of casks affected:
I ran the audit on homebrew/cask-versions and 33.6% (81/241) of casks failed. I would imagine this number to be similar, if not higher for the main tap.

Time to run:
As part of the full audit, it doesn't seem to make much of a difference. Ran individually, it seems to add 5 seconds, but I didn't have a good audit to benchmark this against. In terms of running it for all the casks, ~11 hours excluding download times.

❯ hyperfine 'brew audit --cask --online --strict quickgpt' --prepare 'git checkou
t cask-audit-min-os' 'brew audit --cask --online --strict quickgpt'
Benchmark 1: brew audit --cask --online --strict quickgpt [old]
  Time (mean ± σ):     20.708 s ±  1.540 s    [User: 2.400 s, System: 1.209 s]
  Range (min … max):   18.472 s … 23.800 s    10 runs

Benchmark 2: brew audit --cask --online --strict quickgpt [new]
  Time (mean ± σ):     20.647 s ±  4.108 s    [User: 2.360 s, System: 1.134 s]
  Range (min … max):   12.560 s … 24.493 s    10 runs

❯ hyperfine 'brew audit --only \'name\' quickgpt --strict --online' 'brew audit -
-only \'min_os, name\' quickgpt --strict --online'
Benchmark 1: brew audit --only 'name' quickgpt --strict --online
  Time (mean ± σ):      3.245 s ±  0.223 s    [User: 1.883 s, System: 0.542 s]
  Range (min … max):    3.023 s …  3.709 s    10 runs

Benchmark 2: brew audit --only 'min_os, name' quickgpt --strict --online
  Time (mean ± σ):      8.001 s ±  0.829 s    [User: 2.193 s, System: 0.848 s]
  Range (min … max):    7.052 s …  9.655 s    10 runs

@apainintheneck
Copy link
Contributor

Thanks for the benchmarks. It doesn't look like it'll be a performance problem.

Like you already noted the number of casks this affects is large enough that it will take a lot of work to update all of them. Maybe it'd be better to just apply this to new cask updates so that we can ship it faster and then maybe enable it for all casks later on as a follow-up.

@p-linnane
Copy link
Member

Like you already noted the number of casks this affects is large enough that it will take a lot of work to update all of them. Maybe it'd be better to just apply this to new cask updates so that we can ship it faster and then maybe enable it for all casks later on as a follow-up.

This makes the most sense. Once it's merged we can create a tracking issue like we've done for our other projects of this scale.

@MikeMcQuaid
Copy link
Member

Like you already noted the number of casks this affects is large enough that it will take a lot of work to update all of them. Maybe it'd be better to just apply this to new cask updates so that we can ship it faster and then maybe enable it for all casks later on as a follow-up.

Agreed. I think making it a --strict and/or --new-cask only audit makes sense until it's fully implemented.

@razvanazamfirei razvanazamfirei force-pushed the cask-audit-min-os branch 3 times, most recently from 93feb2f to 4b7bf5d Compare October 3, 2023 15:46
@razvanazamfirei razvanazamfirei marked this pull request as ready for review October 3, 2023 15:46
Copy link
Member

@MikeMcQuaid MikeMcQuaid left a comment

Choose a reason for hiding this comment

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

Looking good so far! Have some mild performance concerns but they aren't necessarily specific to this check so could be non-blocking if you'd rather tackle them later.

Library/Homebrew/cask/audit.rb Outdated Show resolved Hide resolved
artifacts.each do |artifact|
artifact_path = artifact.is_a?(Artifact::Pkg) ? artifact.path : artifact.source
path = tmpdir/artifact_path.relative_path_from(cask.staged_path)
plist_path = "#{path}/Contents/Info.plist"
Copy link
Member

Choose a reason for hiding this comment

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

Can this somehow be the only file that's extracted?

Copy link
Member Author

Choose a reason for hiding this comment

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

There's some overlap between this method and audit_signing and perhaps it could make sense to have a common method for both? Otherwise, I'm happy to take a look at fixing this later on.

Copy link
Member

Choose a reason for hiding this comment

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

@razvanazamfirei any more thoughts on this? I don't know if there's decent enough support in these classes for partial extraction, ok if not, but nice to avoid extracting the entire archive if we can avoid it.

Library/Homebrew/cask/audit.rb Outdated Show resolved Hide resolved
@github-actions
Copy link

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@github-actions github-actions bot added the stale No recent activity label Oct 26, 2023
@razvanazamfirei razvanazamfirei removed the stale No recent activity label Oct 26, 2023
artifacts.each do |artifact|
artifact_path = artifact.is_a?(Artifact::Pkg) ? artifact.path : artifact.source
path = tmpdir/artifact_path.relative_path_from(cask.staged_path)
plist_path = "#{path}/Contents/Info.plist"
Copy link
Member

Choose a reason for hiding this comment

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

@razvanazamfirei any more thoughts on this? I don't know if there's decent enough support in these classes for partial extraction, ok if not, but nice to avoid extracting the entire archive if we can avoid it.

sparkle_min_os = livecheck_min_os
plist_min_os = cask_plist_min_os
odebug "Minimum OS version: Plist #{plist_min_os} | Sparkle #{sparkle_min_os.inspect}"
min_os_string = [sparkle_min_os, plist_min_os].compact.max
Copy link
Member

Choose a reason for hiding this comment

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

I don't think .max will work like how you want/expect on two strings. You probably need to do Version.new on them both and then compare them instead. String version comparisons can look like they work sometimes but are not worth relying on.

Copy link
Member Author

Choose a reason for hiding this comment

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

@MikeMcQuaid, I did not find great support for the partial extraction. I tried to deduplicate the extraction operation that was duplicated in the signing audit and the minimum OS audit.

Both livecheck_min_os and plist_min_os are a MacOSVersion.

Copy link
Member

@MikeMcQuaid MikeMcQuaid left a comment

Choose a reason for hiding this comment

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

Thanks again @razvanazamfirei, sorry for all the rounds of review!

@MikeMcQuaid MikeMcQuaid merged commit fce60ee into Homebrew:master Nov 6, 2023
27 checks passed
@github-actions github-actions bot added the outdated PR was locked due to age label Dec 7, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 7, 2023
@razvanazamfirei razvanazamfirei deleted the cask-audit-min-os branch January 28, 2024 17:22
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated PR was locked due to age
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants