diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8253bdb..ebfc6a2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -266,13 +266,50 @@ jobs: run: | set -euo pipefail tag="${GITHUB_REF_NAME}" - previous_tag="$(git describe --tags --abbrev=0 "${tag}^" 2>/dev/null || true)" + previous_tag="$(git describe --tags --abbrev=0 --match '[0-9]*.[0-9]*.[0-9]*' --exclude '*[!0-9.]*' "${tag}^" 2>/dev/null || true)" range="${tag}" if [ -n "${previous_tag}" ]; then range="${previous_tag}..${tag}" fi - changes="$(git log --format='- %s (%an)' "${range}")" + release_author() { + local name="$1" + local email="$2" + local nickname="" + + case "${email}" in + *+*@users.noreply.github.com) + nickname="${email#*+}" + nickname="${nickname%@users.noreply.github.com}" + ;; + *@users.noreply.github.com) + nickname="${email%@users.noreply.github.com}" + ;; + sam@rmcreative.ru) + nickname="samdark" + ;; + pamparam83@gmail.com) + nickname="pamparam83" + ;; + *) + if [[ "${name}" != *" "* ]]; then + nickname="${name}" + else + nickname="${email%@*}" + fi + ;; + esac + + nickname="${nickname//[^[:alnum:]_.-]/-}" + printf '@%s' "${nickname:-unknown}" + } + + changes_file="$(mktemp)" + while IFS=$'\t' read -r subject name email; do + author="$(release_author "${name}" "${email}")" + printf -- '- %s (%s)\n' "${subject}" "${author}" >> "${changes_file}" + done < <(git log --format='%s%x09%an%x09%ae' "${range}") + image="${REGISTRY}/${IMAGE_NAME}:${tag}" { @@ -288,7 +325,7 @@ jobs: if [ -n "${previous_tag}" ]; then printf 'Changes since %s:\n\n' "${previous_tag}" fi - printf '%s\n' "${changes}" + cat "${changes_file}" } > release-notes.md - name: Create draft release with assets diff --git a/tests/Unit/Packaging/ConfigurationPackagingTest.php b/tests/Unit/Packaging/ConfigurationPackagingTest.php index 6688725..5797397 100644 --- a/tests/Unit/Packaging/ConfigurationPackagingTest.php +++ b/tests/Unit/Packaging/ConfigurationPackagingTest.php @@ -356,6 +356,30 @@ public function documentationWorkflowUsesNightlyBinaryAfterPackageWorkflow(): vo self::assertStringNotContainsString('--user=root', $workflow); } + #[Test] + public function releaseWorkflowBuildsNotesFromPreviousStableReleaseTag(): void + { + $workflow = file_get_contents(dirname(__DIR__, 3) . '/.github/workflows/release.yml'); + self::assertIsString($workflow); + + self::assertStringContainsString("tags:\n - '*.*.*'", $workflow); + self::assertStringContainsString( + "git describe --tags --abbrev=0 --match '[0-9]*.[0-9]*.[0-9]*' --exclude '*[!0-9.]*' \"\${tag}^\"", + $workflow, + ); + self::assertStringContainsString('release_author() {', $workflow); + self::assertStringContainsString('*+*@users.noreply.github.com)', $workflow); + self::assertStringContainsString('sam@rmcreative.ru)', $workflow); + self::assertStringContainsString('nickname="samdark"', $workflow); + self::assertStringContainsString('pamparam83@gmail.com)', $workflow); + self::assertStringContainsString('nickname="pamparam83"', $workflow); + self::assertStringContainsString("git log --format='%s%x09%an%x09%ae'", $workflow); + self::assertStringNotContainsString('repos/${GITHUB_REPOSITORY}/commits/${commit}', $workflow); + self::assertStringNotContainsString("git log --format='- %s (%an)'", $workflow); + self::assertStringNotContainsString('git describe --tags --abbrev=0 "${tag}^"', $workflow); + self::assertStringContainsString('Changes since %s:', $workflow); + } + #[Test] public function cloudflareDeploymentVerifiesDownloadedBinaryChecksum(): void {