commit c4525f7b3f128c8ba78e3ff36dba4d92a353400e
parent dd7bc67e5574e7d15045363e8503f9d62dc1b516
Author: Drew DeVault <sir@cmpwn.com>
Date: Mon, 22 Nov 2021 11:30:30 +0100
hare release: start SSH agent for signing
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
1 file changed, 21 insertions(+), 3 deletions(-)
diff --git a/cmd/hare/release.ha b/cmd/hare/release.ha
@@ -110,7 +110,7 @@ fn do_release(
shortlog(clfile, range)?;
git_runcmd("tag", "-aeF", changelog, newtag)?;
- signtag(name, newtag, key)?;
+ signtag(dir, name, newtag, key)?;
fmt::printfln("Tagged {} version {}. "
"Use 'git push --follow-tags' to publish the new release.",
name, newtag)!;
@@ -140,7 +140,7 @@ fn do_initial_release(ver: (modversion | increment)) (void | release_error) = {
fmt::fprintfln(clfile, initial_template, name, newtag)?;
git_runcmd("tag", "-aeF", changelog, newtag)?;
- signtag(name, newtag, key)?;
+ signtag(dir, name, newtag, key)?;
fmt::printfln("Tagged {} version {}. "
"Use 'git push --follow-tags' to publish the new release.",
name, newtag)!;
@@ -269,10 +269,27 @@ fn choosekey() (str | release_error) = {
const proc = exec::start(&cmd)?;
const status = exec::wait(&proc)?;
exec::check(&status)?;
+ fmt::println("You will be prompted to enter your password again to create the release signature.")!;
return path;
};
-fn signtag(name: str, tag: str, key: str) (void | release_error) = {
+fn signtag(tmpdir: str, name: str, tag: str, key: str) (void | release_error) = {
+ // This could work without the agent if it were not for the fact that
+ // ssh-keygen is bloody stupid when it comes to prompting you for your
+ // password.
+ const socket = path::join(tmpdir, "agent");
+ defer free(socket);
+ const agent = exec::cmd("ssh-agent", "-Da", socket)?;
+ exec::nullstd(&agent);
+ const agent = exec::start(&agent)?;
+ defer exec::kill(agent)!;
+
+ const addkey = exec::cmd("ssh-add", key)?;
+ exec::setenv(&addkey, "SSH_AUTH_SOCK", socket);
+ const addkey = exec::start(&addkey)?;
+ const addkey = exec::wait(&addkey)?;
+ exec::check(&addkey)?;
+
const prefix = fmt::asprintf("--prefix={}-{}/", name, tag);
defer free(prefix);
const archive = exec::cmd("git", "archive",
@@ -282,6 +299,7 @@ fn signtag(name: str, tag: str, key: str) (void | release_error) = {
const note = exec::cmd("git", "notes", "add", "-F", "-", tag)?;
exec::setenv(¬e, "GIT_NOTES_REF", "refs/notes/signatures/tar.gz");
+ exec::setenv(&ssh, "SSH_AUTH_SOCK", socket);
// Squelch "Signing data on standard input" message
// TODO: It might be better to capture this and print it to stderr
// ourselves if ssh-keygen exits nonzero, so that the error details are