Skip to content

Conversation

jeremyd2019
Copy link
Contributor

@jeremyd2019 jeremyd2019 commented Feb 27, 2025

I noticed the latest release created picked up its name from the latest commit to the main branch in the pacman-repo repository, namely 2025-02-26T22-44-26.725080300Z: Merge pull request #1 from git-for-windows/populate-the-readme. Given that it's very unlikely that the commit(s) on the main branch have anything to do with the releases, just specify the name to be the same as the tagname.

When I use gh release create to create releases, in order to suppress this behavior, I have to specify --title as well as the tag. It seems the REST API equivalent is name

example:

gh release create "$timestamp" --title "$timestamp" --notes "" -R ${{ github.repository }} 

(I didn't bother trying to specify empty notes, I think you get the same behavior in the REST api by not specifying them)

I noticed the latest release created picked up its name from the latest commit to the main branch in the pacman-repo repository, namely "2025-02-26T22-44-26.725080300Z: Merge pull request #1 from git-for-windows/populate-the-readme".  Given that it's very unlikely that the commit(s) on the main branch have anything to do with the releases, just specify the name to be the same as the tagname.

Signed-off-by: jeremyd2019 <[email protected]>
@dscho dscho merged commit 42f32b5 into main Feb 27, 2025
6 checks passed
@dscho dscho deleted the jeremyd2019-pacman-helper-release-name branch February 27, 2025 00:17
@dscho
Copy link
Member

dscho commented Feb 27, 2025

Nice!

@dscho
Copy link
Member

dscho commented Feb 27, 2025

I guess we could even re-use the commit message(s) as the body of the release?

@jeremyd2019
Copy link
Contributor Author

I guess we could even re-use the commit message(s) as the body of the release?

If you feel like json-escaping it.

@jeremyd2019
Copy link
Contributor Author

jeremyd2019 commented Feb 27, 2025

you know what you could do is specify the target_commitish to the commit, then the body would automatically show the commit message and the tag would point to something more relevant than the main branch. Of course, there's more than one branch/commit corresponding to a single release, so maybe not.

@dscho
Copy link
Member

dscho commented Feb 27, 2025

Of course, there's more than one branch/commit corresponding to a single release, so maybe not.

Right, that's the culprit. There are separate branches for the different CPU architectures. But something like this should work:

diff --git a/pacman-helper.sh b/pacman-helper.sh
index 5a4a40502..c6c12ef16 100755
--- a/pacman-helper.sh
+++ b/pacman-helper.sh
@@ -349,6 +349,7 @@ quick_action () { # <action> <file>...
 	test -z "$GPGKEY" || sign_option=--sign
 	dbs=
 	to_push=
+	>release-notes.txt
 	for arch in $architectures
 	do
 		eval "msys=\$${arch}_msys"
@@ -454,11 +455,16 @@ quick_action () { # <action> <file>...
 				$(printf '%s\n' $msys $mingw | wc -l) \
 				"$(printf '%s\n' $msys $mingw |
 					sed 's/^\(.*\)-\([^-]*-[^-]*\)-[^-]*\.pkg\.tar\.\(xz\|zst\)$/\1 -> \2/')")"
+			printf '%s\n' $msys $mingw |
+			sed 's/^\(.*\)-\([^-]*-[^-]*\)-[^-]*\.pkg\.tar\.\(xz\|zst\)$/* \1 -> \2/' >>release-notes.txt
 			;;
 		 remove)
 			 msg="$(printf 'Remove %s package(s)\n\n%s\n' \
 				$(printf '%s\n' $msys $mingw | wc -l) \
 				"$(printf '%s\n' $msys $mingw)")"
+			printf '%s\n' $msys $mingw |
+			sed 's/^/* dropped /' >>release-notes.txt
+			;;
 		 esac &&
 		 git commit -asm "$msg") ||
 		die "Could not ${label} $msys $mingw to/from db in $arch"
@@ -545,8 +551,9 @@ quick_action () { # <action> <file>...
 	then
 		echo "Would create a GitHub Release '$tagname' at git-for-windows/pacman-repo" >&2
 	else
+		body="$(sed -e 's/[\\"]/\\&/g' -e ':1;N;${s/\n/\\n/g;b};b1' release-notes.txt)"
 		id="$(curl -H "Authorization: Bearer $GITHUB_TOKEN" -sfL --show-error -XPOST -d \
-			'{"tag_name":"'"$tagname"'","name":"'"$tagname"'","draft":true,"prerelease":true}' \
+			'{"tag_name":"'"$tagname"'","name":"'"$tagname"'","body":"'"$body"'","draft":true,"prerelease":true}' \
 			"https://api.github.com/repos/git-for-windows/pacman-repo/releases" |
 		sed -n 's/^  "id": *\([0-9]*\).*/\1/p')"
 	fi ||

@jeremyd2019
Copy link
Contributor Author

jeremyd2019 commented Feb 27, 2025

+		body="$(sed -e 's/[\\"]/\\&/g' -e ':1;N;${s/\n/\\n/g;b};b1' release-notes.txt)"

I'm still trying to figure out some of the finer points of sed scripts. How does this play out? It seems to me like it would only escape \ or " in the first line, because subsequent lines would be eaten by the loop escaping newlines?

Might it be better to build a string variable and do the newline substitution in bash, something like:

--- a/pacman-helper.sh
+++ b/pacman-helper.sh
@@ -349,6 +349,7 @@ quick_action () { # <action> <file>...
 	test -z "$GPGKEY" || sign_option=--sign
 	dbs=
 	to_push=
+	body=
 	for arch in $architectures
 	do
 		eval "msys=\$${arch}_msys"
@@ -454,11 +455,16 @@ quick_action () { # <action> <file>...
 				$(printf '%s\n' $msys $mingw | wc -l) \
 				"$(printf '%s\n' $msys $mingw |
 					sed 's/^\(.*\)-\([^-]*-[^-]*\)-[^-]*\.pkg\.tar\.\(xz\|zst\)$/\1 -> \2/')")"
+			body+="$(printf '%s\n' $msys $mingw |
+			sed -e 's/^\(.*\)-\([^-]*-[^-]*\)-[^-]*\.pkg\.tar\.\(xz\|zst\)$/* \1 -> \2/' -e 's/[\"]/\\&/g')"
 			;;
 		 remove)
 			 msg="$(printf 'Remove %s package(s)\n\n%s\n' \
 				$(printf '%s\n' $msys $mingw | wc -l) \
 				"$(printf '%s\n' $msys $mingw)")"
+			body+="$(printf '%s\n' $msys $mingw |
+			sed -e 's/^/* dropped /' -e 's/[\"]/\\&/g')"
+			;;
 		 esac &&
 		 git commit -asm "$msg") ||
 		die "Could not ${label} $msys $mingw to/from db in $arch"
@@ -545,8 +551,9 @@ quick_action () { # <action> <file>...
 	then
 		echo "Would create a GitHub Release '$tagname' at git-for-windows/pacman-repo" >&2
 	else
+		body="${body//$'\n'/\\n}"
 		id="$(curl -H "Authorization: Bearer $GITHUB_TOKEN" -sfL --show-error -XPOST -d \
-			'{"tag_name":"'"$tagname"'","name":"'"$tagname"'","draft":true,"prerelease":true}' \
+			'{"tag_name":"'"$tagname"'","name":"'"$tagname"'","body":"'"$body"'","draft":true,"prerelease":true}' \
 			"https://api.github.com/repos/git-for-windows/pacman-repo/releases" |
 		sed -n 's/^  "id": *\([0-9]*\).*/\1/p')"
 	fi ||

@dscho
Copy link
Member

dscho commented Feb 28, 2025

+		body="$(sed -e 's/[\\"]/\\&/g' -e ':1;N;${s/\n/\\n/g;b};b1' release-notes.txt)"

I'm still trying to figure out some of the finer points of sed scripts. How does this play out? It seems to me like it would only escape \ or " in the first line, because subsequent lines would be eaten by the loop escaping newlines?

Correct:

$ printf 'a"hi"\nb"bye"\n' | sed -e 's/[\\"]/\\&/g' -e ':1;N;${s/\n/\\n/g;b};b1'
a\"hi\"\nb"bye"

So a better idea is to do it at the end of the loop:

$ printf 'a"hi"\nb"bye"\n' | sed -e '
	# concatenate all lines in one big loop
	:loop
	N # read next line
	${ # upon the last line:
		s/[\\"]/\\&/g # escape all double quotes and backslashes
		s/\n/\\n/g # convert newlines to `\n`
		# (There are no tabs or other control/Unicode characters
		# that we would need to take care of.)
		b # and exit the loop
	}
	bloop # advance to the next line (branch to the "loop" label)
'
a\"hi\"\nb\"bye\"

You could write this shorter, at the expense of readability, as:

$ printf 'a"hi"\nb"bye"\n' | sed -e ':1;N;${s/[\\"]/\\&/g;s/\n/\\n/g;b};b1'
a\"hi\"\nb\"bye\"

That looks quite a bit like a Perl program on the right-hand side... ("Perl is the only programming language where you can bang your head on the keyboard and the result is a valid program")

Might it be better to build a string variable and do the newline substitution in bash

My aversion to doing everything in Bash is probably irrational and triggered by Git's own over-use of Unix shell scripting for production code (something it is distinctly ill-equipped for, with so many things lacking: proper data structures, error handling is awful, job control is horrible, multi-threading is non-existent, etc). But I digress.

In this instance, I would deem it a job worthy of a stream editor, which sed is, and Bash isn't.

@jeremyd2019
Copy link
Contributor Author

	# concatenate all lines in one big loop
	:loop
	N # read next line
	${ # upon the last line:
		s/[\\"]/\\&/g # escape all double quotes and backslashes
		s/\n/\\n/g # convert newlines to `\n`
		# (There are no tabs or other control/Unicode characters
		# that we would need to take care of.)
		b # and exit the loop
	}
	bloop # advance to the next line (branch to the "loop" label)

My aversion to doing everything in Bash is probably irrational and triggered by Git's own over-use of Unix shell scripting for production code (something it is distinctly ill-equipped for, with so many things lacking: proper data structures, error handling is awful, job control is horrible, multi-threading is non-existent, etc). But I digress.

In this instance, I would deem it a job worthy of a stream editor, which sed is, and Bash isn't.

OK. I was just annoyed by how it was necessary to do a loop to deal with newlines. Also, minor nit, backslashes are not special in character classes so you don't need to escape it there.

@jeremyd2019
Copy link
Contributor Author

jeremyd2019 commented Feb 28, 2025

I tried to see if it was cleaner in awk. Kinda - except you have to set RS to something (setting it to empty string turns on a special mode that I don't want here). I set it to \f (form-feed), as a character that won't be in the input:

BEGIN {RS="\f"} {gsub(/[\\"]/, "\\\\&"); gsub(/\n/, "\\n"); print}

The escaping rules in the replacement string in gsub are a nightmare, see https://www.gnu.org/software/gawk/manual/html_node/Gory-Details.html

@dscho
Copy link
Member

dscho commented Mar 2, 2025

This follow-up discussion found its elegant conclusion on #603

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants