11name : Desktop Release
22
33on :
4+ push :
5+ branches :
6+ - main
47 workflow_dispatch :
5- inputs :
6- version_bump :
7- description : Version bump type for DotPilot desktop releases
8- required : true
9- default : patch
10- type : choice
11- options :
12- - patch
13- - minor
14- - major
15- prerelease :
16- description : Publish the GitHub Release as a prerelease
17- required : true
18- default : false
19- type : boolean
208
219permissions :
2210 contents : write
@@ -33,11 +21,11 @@ jobs:
3321 - name : Enforce Supported Release Branches
3422 shell : bash
3523 run : |
36- if [[ "${GITHUB_REF_NAME}" == "main" || "${GITHUB_REF_NAME}" == release/* ]]; then
24+ if [[ "${GITHUB_REF_NAME}" == "main" ]]; then
3725 exit 0
3826 fi
3927
40- echo "Desktop releases may only run from main or release/* branches ." >&2
28+ echo "Desktop releases may only run from main." >&2
4129 exit 1
4230
4331 prepare_release :
@@ -46,20 +34,17 @@ jobs:
4634 needs :
4735 - validate_release_ref
4836 outputs :
49- application_version : ${{ steps.bump_version .outputs.application_version }}
37+ application_version : ${{ steps.resolve_version .outputs.application_version }}
5038 previous_tag : ${{ steps.previous_tag.outputs.value }}
51- release_tag : ${{ steps.bump_version .outputs.release_tag }}
52- release_version : ${{ steps.bump_version .outputs.display_version }}
39+ release_tag : ${{ steps.resolve_version .outputs.release_tag }}
40+ release_version : ${{ steps.resolve_version .outputs.display_version }}
5341 steps :
5442 - uses : actions/checkout@v4
5543 with :
5644 fetch-depth : 0
5745
58- - name : Configure Git Identity
59- shell : bash
60- run : |
61- git config user.name "github-actions[bot]"
62- git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
46+ - name : Install Dependencies
47+ uses : " ./.github/steps/install_dependencies"
6348
6449 - name : Fetch Tags
6550 shell : bash
@@ -72,30 +57,22 @@ jobs:
7257 previous_tag="$(git tag --list 'v*' --sort=-version:refname | head -n 1)"
7358 echo "value=${previous_tag}" >> "$GITHUB_OUTPUT"
7459
75- - name : Bump App Version
76- id : bump_version
60+ - name : Resolve Release Version
61+ id : resolve_version
7762 shell : bash
7863 run : |
79- python3 ./scripts/release/update_app_version.py \
80- --project-file ./DotPilot/DotPilot.csproj \
81- --bump-type '${{ inputs.version_bump }}' \
82- --github-output "$GITHUB_OUTPUT"
83-
84- - name : Commit Version Bump
85- shell : bash
86- run : |
87- git add DotPilot/DotPilot.csproj
88- git commit -m "chore(release): v${{ steps.bump_version.outputs.display_version }}"
89-
90- - name : Create Release Tag
91- shell : bash
92- run : git tag "${{ steps.bump_version.outputs.release_tag }}"
64+ version_prefix="$(dotnet msbuild ./DotPilot/DotPilot.csproj -getProperty:ApplicationDisplayVersion | tail -n 1 | tr -d '\r')"
65+ if [[ ! "${version_prefix}" =~ ^[0-9]+\.[0-9]+$ ]]; then
66+ echo "ApplicationDisplayVersion must be a two-segment numeric prefix. Found: '${version_prefix}'." >&2
67+ exit 1
68+ fi
9369
94- - name : Push Release Commit And Tag
95- shell : bash
96- run : |
97- git push origin "HEAD:${GITHUB_REF_NAME}"
98- git push origin "${{ steps.bump_version.outputs.release_tag }}"
70+ display_version="${version_prefix}.${{ github.run_number }}"
71+ {
72+ echo "display_version=${display_version}"
73+ echo "application_version=${{ github.run_number }}"
74+ echo "release_tag=v${display_version}"
75+ } >> "$GITHUB_OUTPUT"
9976
10077 publish_desktop :
10178 name : Publish Desktop (${{ matrix.name }})
@@ -125,15 +102,19 @@ jobs:
125102 - uses : actions/checkout@v4
126103 with :
127104 fetch-depth : 0
128- ref : ${{ needs.prepare_release.outputs.release_tag }}
105+ ref : ${{ github.sha }}
129106
130107 - name : Install Dependencies
131108 timeout-minutes : 60
132109 uses : " ./.github/steps/install_dependencies"
133110
134111 - name : Publish Desktop App
135112 shell : pwsh
136- run : dotnet publish ./DotPilot/DotPilot.csproj -c Release -f net10.0-desktop -o ./${{ matrix.output_path }}
113+ run : >
114+ dotnet publish ./DotPilot/DotPilot.csproj -c Release -f net10.0-desktop
115+ -o ./${{ matrix.output_path }}
116+ -p:ApplicationDisplayVersion=${{ needs.prepare_release.outputs.release_version }}
117+ -p:ApplicationVersion=${{ needs.prepare_release.outputs.application_version }}
137118
138119 - name : Archive Desktop Publish Output
139120 shell : pwsh
@@ -164,7 +145,7 @@ jobs:
164145 - uses : actions/checkout@v4
165146 with :
166147 fetch-depth : 0
167- ref : ${{ needs.prepare_release.outputs.release_tag }}
148+ ref : ${{ github.sha }}
168149
169150 - name : Fetch Tags
170151 shell : bash
@@ -177,22 +158,73 @@ jobs:
177158
178159 - name : Generate Feature Summary
179160 shell : bash
161+ env :
162+ PREVIOUS_TAG : ${{ needs.prepare_release.outputs.previous_tag }}
163+ RELEASE_TAG : ${{ needs.prepare_release.outputs.release_tag }}
164+ REPOSITORY : ${{ github.repository }}
180165 run : |
181- python3 ./scripts/release/get_release_summary.py \
182- --repository '${{ github.repository }}' \
183- --release-tag '${{ needs.prepare_release.outputs.release_tag }}' \
184- --previous-tag '${{ needs.prepare_release.outputs.previous_tag }}' \
185- --output-path ./artifacts/release-summary.md
166+ mkdir -p ./artifacts
167+
168+ commit_range="HEAD"
169+ if [[ -n "${PREVIOUS_TAG}" ]]; then
170+ commit_range="${PREVIOUS_TAG}..HEAD"
171+ fi
172+
173+ git log --no-merges --pretty=format:%s "${commit_range}" |
174+ awk 'NF && tolower($0) !~ /^chore\(release\):/ && !seen[$0]++' > ./artifacts/release-commits.txt
175+ if [[ ! -s ./artifacts/release-commits.txt ]]; then
176+ printf '%s\n' "Maintenance and release preparation changes." > ./artifacts/release-commits.txt
177+ fi
178+
179+ : > ./artifacts/release-feature-docs.txt
180+ if [[ -n "${PREVIOUS_TAG}" ]]; then
181+ git diff --name-only "${PREVIOUS_TAG}..HEAD" -- 'docs/Features/*.md' |
182+ awk '/^docs\/Features\// && !seen[$0]++' > ./artifacts/release-feature-docs.txt
183+ elif [[ -d ./docs/Features ]]; then
184+ find ./docs/Features -maxdepth 1 -type f -name '*.md' | sed 's#^\./##' | sort > ./artifacts/release-feature-docs.txt
185+ fi
186+
187+ {
188+ echo "## Feature Summary"
189+ while IFS= read -r subject; do
190+ if [[ -n "${subject}" ]]; then
191+ echo "- ${subject}"
192+ fi
193+ done < ./artifacts/release-commits.txt
194+ } > ./artifacts/release-summary.md
195+
196+ if [[ -s ./artifacts/release-feature-docs.txt ]]; then
197+ {
198+ echo
199+ echo "## Feature Specs"
200+ while IFS= read -r feature_doc; do
201+ if [[ -z "${feature_doc}" ]]; then
202+ continue
203+ fi
204+
205+ title="$(sed -n 's/^# //p' "${feature_doc}" | head -n 1)"
206+ if [[ -z "${title}" ]]; then
207+ title="$(basename "${feature_doc}" .md)"
208+ fi
209+
210+ printf -- '- [%s](https://github.com/%s/blob/%s/%s)\n' \
211+ "${title}" \
212+ "${REPOSITORY}" \
213+ "${RELEASE_TAG}" \
214+ "${feature_doc}"
215+ done < ./artifacts/release-feature-docs.txt
216+ } >> ./artifacts/release-summary.md
217+ fi
186218
187219 - name : Publish GitHub Release
188220 shell : bash
189221 env :
190222 GH_TOKEN : ${{ github.token }}
191223 PREVIOUS_TAG : ${{ needs.prepare_release.outputs.previous_tag }}
192224 RELEASE_TAG : ${{ needs.prepare_release.outputs.release_tag }}
225+ RELEASE_TARGET_SHA : ${{ github.sha }}
193226 RELEASE_VERSION : ${{ needs.prepare_release.outputs.release_version }}
194227 REPOSITORY : ${{ github.repository }}
195- PRERELEASE : ${{ inputs.prerelease }}
196228 run : |
197229 mapfile -t release_assets < <(find ./artifacts/release-assets -type f -name '*.zip' | sort)
198230 if [[ ${#release_assets[@]} -eq 0 ]]; then
@@ -205,7 +237,7 @@ jobs:
205237 gh release create "${RELEASE_TAG}"
206238 "${release_assets[@]}"
207239 --repo "${REPOSITORY}"
208- --verify-tag
240+ --target "${RELEASE_TARGET_SHA}"
209241 --title "DotPilot ${RELEASE_VERSION}"
210242 --generate-notes
211243 --notes "${release_notes}"
@@ -215,8 +247,4 @@ jobs:
215247 release_command+=(--notes-start-tag "${PREVIOUS_TAG}")
216248 fi
217249
218- if [[ "${PRERELEASE}" == "true" ]]; then
219- release_command+=(--prerelease)
220- fi
221-
222250 "${release_command[@]}"
0 commit comments