-
Notifications
You must be signed in to change notification settings - Fork 58
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
Hardcode known wrapper checksums to avoid network requests #167
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, this looks like it's headed in the right direction!
I think the biggest ask is tooling/automation to keep the list up-to-date more easily, and ideally, with a GitHub action
src/checksums.ts
Outdated
@@ -6,9 +6,165 @@ const httpc = new httpm.HttpClient( | |||
{allowRetries: true, maxRetries: 3} | |||
) | |||
|
|||
/** Known checksums from previously published Wrapper versions */ | |||
export const KNOWN_VALID_CHECKSUMS = new Set([ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to pull this from a resource file instead of hard-coding it into the source code.
Ideally, there would be a resource file, and there would also be a script that CI could automatically run to update this file and would auto-push then auto-release when there was an update
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, that would be much better. If the file was formatted as JSON, it could be trivially loaded into an object: that way we could include the Gradle version as well as the checksum in the metadata.
@Marcono1234 you can see here an example of loading a resource file in Typescript. It may not be the best way, but it works!
Then, you can use JSON.parse(fileContents)
and use it as a typed Javascript object. Here are some examples.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks pretty good to me. If we can extract the checksums list into a resource file, then I'm OK if this needs to be maintained by hand (for now). New Gradle versions will continue to require a network call until the wrapper action is updated.
As @JLLeitschuh mentioned, it would be ideal if we had a job that ran in this repository to update the versions file when a new Gradle version is released. But we'll still need to release a new action version each time.
An additional optimization would be to store any "discovered" checksums in the GitHub Actions cache. We read the set of known versions from the resource, add any discovered versions, and write the JSON file directly to the cache.
src/checksums.ts
Outdated
@@ -6,9 +6,165 @@ const httpc = new httpm.HttpClient( | |||
{allowRetries: true, maxRetries: 3} | |||
) | |||
|
|||
/** Known checksums from previously published Wrapper versions */ | |||
export const KNOWN_VALID_CHECKSUMS = new Set([ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, that would be much better. If the file was formatted as JSON, it could be trivially loaded into an object: that way we could include the Gradle version as well as the checksum in the metadata.
@Marcono1234 you can see here an example of loading a resource file in Typescript. It may not be the best way, but it works!
Then, you can use JSON.parse(fileContents)
and use it as a typed Javascript object. Here are some examples.
@Marcono1234 The changes to |
Thanks for the feedback! I will try to adjust this in the next days. Would it make sense though to use a plaintext / custom text format where for example each line represents a checksum, except if it is blank or starts with
JSON has the disadvantage that it doesn't support comments, and just having a large list of checksums without any indication to which versions they belong might make reviewing it difficult. However, with #145 maybe it would make sense to use JSON instead of a custom text format, but then include the version numbers. For example: {
"87e50531ca7aab675f5bb65755ef78328afd64cf0877e37ad876047a8a014055": [
"1.0"
],
"22c56a9780daeee00e5bf31621f991b68e73eff6fe8afca628a1fe2c50c6038e": [
"1.1",
]
} |
Yes that's what I meant. Something like:
That way you could use Once you have this array, you can get the list of checksums on their own using |
I have performed the following changes now:
I hope that is ok like this. Feedback is appreciated! |
- name: Create or update pull request | ||
uses: peter-evans/create-pull-request@v6 | ||
with: | ||
branch: wrapper-checksums-update |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the branch name should use a prefix such as bot/
to prevent accidentally manually editing this branch, which might then be overwritten by this workflow.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds completely reasonable to prefix it with bot/
Thanks @Marcono1234 . I'm not going to have capacity to take this further until Feb 13 at the earliest. But it's on my list! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome. Was thinking about writing this myself and wasn't looking forward to it. Solid bit of work here!
Javascript is definitely not my strongest area, ngl. 😆
@@ -6,7 +6,8 @@ | |||
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ | |||
"strict": true, /* Enable all strict type-checking options. */ | |||
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ | |||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ | |||
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ | |||
"resolveJsonModule": true, /* Enable importing JSON files as module; used for importing wrapper checksums JSON */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was what I was missing when I took an early crack at this! 🎉
* | ||
* Maps from the checksum to the names of the Gradle versions whose wrapper has this checksum. | ||
*/ | ||
export const KNOWN_VALID_CHECKSUMS = getKnownValidChecksums() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a unit test that verifies that this is never empty, and always contains some reasonable versions as a spot-check that this logic never breaks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've never really worked on this code, and I don't want to delay the merge. So I'm going to approve (and merge) based on @JLLeitschuh approval.
I'd like to include this in the first RC of v2.0.0
, since that mitigates some of the risk of the change. (People have to explicitly update to get the new version).
This has been merged manually. I need to find a better process for merging external PRs. |
Actually, I forgot that I already released |
@Marcono1234 seriously, thank you so much for working this problem out. Really truly. You can see by the number of issues that @bigdaz closed how much pain our network connection logic has caused over the years. You've just significantly increased the stability and usability of this action for all of the users of it. Truly, thank you so much for your contribution. I'm incredibly appreciative you took the time to contribute it. |
Thanks for the kind words and the feedback! I have addressed the feedback (adding tests, and |
I've just released |
Fixes #161
If a checksum is not found in the hardcoded list, the action falls back to fetching the checksums from the Gradle API, as before.
For now there is no logic for automatically updating the list of known checksums; that has to be done manually. But maybe it could be automated in some way in the future.
Here is my somewhat hacky (but hopefully bug-free) Java code which I used to generate the list of checksums:
Checksums list creator