-
Notifications
You must be signed in to change notification settings - Fork 588
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
Added SignTool for v5 #2444
Added SignTool for v5 #2444
Conversation
Thanks @jhromadik! Can you please resolve the conflicts? One thing I already noticed: Usually API design is to let users input a function and change arguments. You let users call |
…tion parameter (default) and the other taking an options record parameter (o suffix)
Conflicts resolved. As to my API design choice ... I'm not sure. I thought that I had looked at other projects to see what they were doing, concluded that it was about 50/50, and decided to go with the record-style. Looking through the projects now, I see that everyone is doing the function-style. So now I don't know what I was thinking. Anyway, I reworked all functions to the function-style by default. I also kept the record-style functions as alternatives, same name only with an 'o' suffix, should anyone prefer to call them that way. |
One problem with the regular record is when we add fields which we don't consider a breaking change. If people construct the record by hand (by specifying all fields and not using the create function) the code will no longer compile. So usung the functions kind of forces people to use the correct syntax without them having to know about the create function. |
Only function-style functions remain. They have better usability, and if you have a record you want to use, you can still do that - took me a while to realize this :). Added random string generation to tests, since FsCheck doesn't do that by default. |
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.
Ok thanks again! I did a full review now and I think some things are still old because of the port from the legacy SignToolHelper
API?
We should consider fixing them as well, otherwise it looks reasonable. Especially thanks for the docs. That made reviewing easier :)
Let me know what you think.
help/markdown/fake-tools-signtool.md
Outdated
// val sign : certificate:SignTool.SignCertificate -> setOptions:(SignTool.SignOptions -> SignTool.SignOptions) -> files:seq<string> -> unit | ||
SignTool.sign | ||
(SignTool.SignCertificate.Store { | ||
SignTool.CertificateFromStore.Create() with |
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.
(minor) This looks a bit strange, on the other hand I thought about it and couldn't come up with something I really liked.
The "best" might be a CreateStore
helper function which takes a creation function:
SignTool.SignCertificate.FromStore ("path/to/certificate-file.pfx", fun opts ->
{ opts with
Password = Some "pw" })
or
SignTool.SignCertificate.FromFile (fun opts ->
{ opts with
AutomaticallySelectCertificate = Some true
SubjectName = Some "subject"
StoreName = Some "My" })
Which might be a bit more familiar and you don't need to call Create
by hand.
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.
I was trying to find a way to make this "prettier" but came up empty. I like your suggestion and will implement it, thanks.
help/markdown/fake-tools-signtool.md
Outdated
SignTool.timeStamp | ||
(fun o -> | ||
{ o with | ||
TimeStamp = Some { SignTool.TimeStampOption.Create() with |
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.
Again: Quite Unusual
Maybe add overloads of the Create
function? (One with only the server and one with server & algorithm).
Not sure what the most likely scenario is.
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 think I'll just pull ServerUrl
and Algorithm
up to the options level.
Default parameters:
SignTool.timeStamp (fun o -> o)
With additional parameters:
SignTool.timeStamp
(fun o -> { o with
ServerUrl = ...
Algorithm = ... } )
ToolPath: string option | ||
/// Timeout. | ||
/// If not provided, default value is 10 seconds per file. | ||
Timeout: TimeSpan option |
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 would expect Timeout = None
to make the timeout disabled. Or is there a default by the tool itself (when no parameter is given)?
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 was just trying to set a reasonable default value. In retrospect, it is unreasonable and more confusing than useful. I'll remove the default value and there will be no timeout when set to None
.
help/markdown/fake-tools-signtool.md
Outdated
// set path to signtool.exe - if you want to use a specific version or you don't have Windows SDKs installed | ||
// by default, an attempt will be made to locate it automatically in 'Program Files (x86)\Windows Kits' | ||
{ o with | ||
ToolOptions = Some { SignTool.ToolOptions.Create() with |
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.
Same as above in addition to the suggestions above another way would be to "inline" all the record fields. With the downside of duplicated code on the implementation (you could use SRTP - statically resolved type parameter to work around this)
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'll "inline" these. It will be much prettier on the surface and should only be a minor implementation inconvenience.
let serverUrl = t.ServerUrl |> Option.defaultValue "http://timestamp.digicert.com" | ||
yield match t.Algorithm with | ||
| Some SHA1 -> sprintf "/t \"%s\"" serverUrl | ||
| Some SHA256 | None -> sprintf "/tr \"%s\" /td \"sha256\"" serverUrl |
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'd prefer to use the Arguments API as (briefly) documented in https://fake.build/core-process.html and https://fake.build/apidocs/v5/fake-core-argumentsmodule.html
It handles proper escaping and edge cases accordingly
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'll look into it.
| true, File f -> | ||
if f.Password.IsSome then | ||
// surround in quotes to lower chances of replacing non-password occurences of password-string | ||
TraceSecrets.register "\"<PASSWORD>\"" (sprintf "\"%s\"" f.Password.Value) |
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 guess you mean if a very simple password is used and replaced elsewhere?
This is a known problem, even on build servers which support secret variables (like azure devops)
I'm not sure we need special casing here, this might lead to the password being printed when it is not quoted?
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 ran into this when I was using a test certificate where the password was also in the file name (to make sure I didn't forget it) - part of the file name was replaced with the registered replacement which looked pretty weird.
The implementation makes sure it is always quoted and there is a test for it too, so erroneously displaying the password should not be a problem.
…elper functions to make creating a SignCertificate easier
…rUrl is now required
…they are supposed to contain, nothing more
Hi! Thanks for the contribution, is there anything I can do to help get this merged? I was just about to port this but then saw you already had a pull request for it. |
I hope to find the time to prepare a new release within a couple of days. Either all points are addressed (or only small things which I can do myself are open) and it will be part of the release or new comments will follow :) |
- using the newest Windows SDK available - working around ProcessUtils.tryFindFile's lack of globbing support
I think I've addressed all comments:
Plus some additional work:
@matthid, @Robin1985 please have a look at it and let me know what you think. |
Looks good to me, thanks a lot! |
Added SignTool for FAKE v5, some documentation, unit tests and updated obsolete information for the old SignToolHelper.
If someone could please have a look to make sure everything is OK ... Other than that, I think it's ready.