Skip to content

Commit b453285

Browse files
XS⚠️ ◾ Added PR workflow to create pre-release and add comment to PR (#143)
* added workflow * Update package.json Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * clean up tags --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 43fb006 commit b453285

File tree

3 files changed

+348
-65
lines changed

3 files changed

+348
-65
lines changed

.github/workflows/pr-release.yml

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
name: PR Pre-release
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened, closed]
6+
7+
permissions:
8+
contents: write
9+
pull-requests: write
10+
11+
env:
12+
APP_NAME: SSW.YakShaver
13+
NODE_VERSION: 20
14+
15+
jobs:
16+
cleanup-release:
17+
if: |
18+
github.event_name != 'pull_request' ||
19+
github.event.action != 'closed'
20+
runs-on: ubuntu-latest
21+
outputs:
22+
pr_number: ${{ steps.pr_info.outputs.pr_number }}
23+
release_tag: ${{ steps.pr_info.outputs.tag }}
24+
channel: ${{ steps.pr_info.outputs.channel }}
25+
version: ${{ steps.pr_info.outputs.version }}
26+
pr_sha: ${{ steps.pr_info.outputs.pr_sha }}
27+
steps:
28+
- uses: actions/checkout@v4
29+
with:
30+
ref: ${{ github.event.pull_request.head.ref || github.ref }}
31+
32+
- uses: actions/setup-node@v4
33+
with:
34+
node-version: ${{ env.NODE_VERSION }}
35+
36+
- name: Get PR info
37+
id: pr_info
38+
run: |
39+
PR_NUMBER="${{ github.event.pull_request.number }}"
40+
PR_SHA="${{ github.event.pull_request.head.sha || github.sha }}"
41+
SHORT_SHA="${PR_SHA:0:7}"
42+
BUILD_TIMESTAMP=$(date +%s)
43+
BASE_VERSION=$(node -p 'require("./package.json").version.split("-")[0]')
44+
CHANNEL_NAME="beta.${PR_NUMBER}"
45+
PRE_RELEASE_VERSION="${BASE_VERSION}-${CHANNEL_NAME}.${BUILD_TIMESTAMP}"
46+
TAG_NAME="${PRE_RELEASE_VERSION}"
47+
echo "tag=${TAG_NAME}" >> $GITHUB_OUTPUT
48+
echo "pr_number=${PR_NUMBER}" >> $GITHUB_OUTPUT
49+
echo "channel=${CHANNEL_NAME}" >> $GITHUB_OUTPUT
50+
echo "version=${PRE_RELEASE_VERSION}" >> $GITHUB_OUTPUT
51+
echo "pr_sha=${SHORT_SHA}" >> $GITHUB_OUTPUT
52+
echo "PR: ${PR_NUMBER}, Tag: ${TAG_NAME}, Channel: ${CHANNEL_NAME}, Version: ${PRE_RELEASE_VERSION}"
53+
54+
- name: Delete existing PR releases
55+
continue-on-error: true
56+
env:
57+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
58+
run: |
59+
PR_NUMBER="${{ steps.pr_info.outputs.pr_number }}"
60+
61+
echo "Finding and deleting existing releases for PR #${PR_NUMBER}"
62+
63+
# Collect both release IDs and tag names BEFORE deleting anything
64+
RELEASES_DATA=$(gh api --paginate /repos/${{ github.repository }}/releases --jq ".[] | select(.body | contains(\"PR #${PR_NUMBER}\")) | {id: .id, tag: .tag_name}")
65+
66+
RELEASE_IDS=$(echo "$RELEASES_DATA" | jq -r '.id')
67+
TAG_NAMES=$(echo "$RELEASES_DATA" | jq -r '.tag')
68+
69+
# Now delete the releases
70+
for id in $RELEASE_IDS; do
71+
if [ -n "$id" ]; then
72+
echo "Deleting release ID: $id"
73+
gh api -X DELETE /repos/${{ github.repository }}/releases/$id || true
74+
fi
75+
done
76+
77+
# Clean up associated tags (collected before deletion)
78+
for tag in $TAG_NAMES; do
79+
if [ -n "$tag" ]; then
80+
echo "Deleting tag: $tag"
81+
gh api -X DELETE /repos/${{ github.repository }}/git/refs/tags/$tag || true
82+
fi
83+
done
84+
85+
echo "Cleanup completed"
86+
87+
build-windows:
88+
needs: cleanup-release
89+
if: |
90+
github.event_name != 'pull_request' ||
91+
github.event.action != 'closed'
92+
runs-on: windows-latest
93+
steps:
94+
- uses: actions/checkout@v4
95+
with:
96+
ref: ${{ github.event.pull_request.head.ref || github.ref }}
97+
98+
- uses: actions/setup-node@v4
99+
with:
100+
node-version: ${{ env.NODE_VERSION }}
101+
cache: npm
102+
cache-dependency-path: package-lock.json
103+
104+
# TODO: Remove this step once this PBI is done: https://github.com/SSWConsulting/SSW.YakShaver/issues/3095
105+
- name: Create .env from secrets
106+
shell: pwsh
107+
env:
108+
YOUTUBE_CLIENT_ID: ${{ secrets.YOUTUBE_CLIENT_ID }}
109+
YOUTUBE_CLIENT_SECRET: ${{ secrets.YOUTUBE_CLIENT_SECRET }}
110+
run: |
111+
"YOUTUBE_CLIENT_ID=$env:YOUTUBE_CLIENT_ID" | Out-File -FilePath ".env" -Encoding utf8 -NoNewline
112+
Add-Content -Path ".env" -Value "`nYOUTUBE_CLIENT_SECRET=$env:YOUTUBE_CLIENT_SECRET"
113+
114+
- name: Install dependencies
115+
run: npm ci --prefer-offline
116+
117+
- name: Install UI dependencies
118+
run: npm ci --prefer-offline
119+
working-directory: src/ui
120+
121+
- name: Update version for pre-release
122+
shell: pwsh
123+
run: |
124+
$version = "${{ needs.cleanup-release.outputs.version }}"
125+
if (-not $version) {
126+
throw "Missing version output"
127+
}
128+
npm version $version --no-git-tag-version
129+
130+
- name: Publish Windows pre-release
131+
run: npm run publish -- --win --publish never
132+
env:
133+
NODE_ENV: production
134+
CI: true
135+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
136+
CHANNEL: ${{ needs.cleanup-release.outputs.channel }}
137+
138+
- name: Fix update manifest filenames
139+
shell: pwsh
140+
run: |
141+
Get-ChildItem "build/*.yml" | ForEach-Object {
142+
$content = Get-Content $_.FullName -Raw
143+
$content = $content -replace "YakShaver-Setup-", "YakShaver.Setup."
144+
$content | Out-File -FilePath $_.FullName -Encoding utf8 -NoNewline
145+
Write-Host "Fixed $($_.Name)"
146+
}
147+
148+
- name: Create or update GitHub release
149+
uses: softprops/action-gh-release@v2
150+
with:
151+
tag_name: ${{ needs.cleanup-release.outputs.release_tag }}
152+
name: "Pre-release PR #${{ needs.cleanup-release.outputs.pr_number }} (${{ needs.cleanup-release.outputs.pr_sha }})"
153+
body: |
154+
Pre-release build for PR #${{ needs.cleanup-release.outputs.pr_number }}
155+
156+
Commit: ${{ needs.cleanup-release.outputs.pr_sha }}
157+
PR: ${{ github.event.pull_request.html_url || 'N/A' }}
158+
159+
This is an automated pre-release. It will be updated automatically when new commits are pushed to the PR.
160+
prerelease: true
161+
files: |
162+
build/*.yml
163+
build/YakShaver*Setup*.exe
164+
build/YakShaver*Setup*.exe.blockmap
165+
draft: false
166+
token: ${{ secrets.GITHUB_TOKEN }}
167+
168+
build-macos:
169+
needs: cleanup-release
170+
if: |
171+
github.event_name != 'pull_request' ||
172+
github.event.action != 'closed'
173+
runs-on: macos-latest
174+
steps:
175+
- uses: actions/checkout@v4
176+
with:
177+
ref: ${{ github.event.pull_request.head.ref || github.ref }}
178+
179+
- uses: actions/setup-node@v4
180+
with:
181+
node-version: ${{ env.NODE_VERSION }}
182+
cache: npm
183+
cache-dependency-path: package-lock.json
184+
185+
# TODO: Remove this step once this PBI is done: https://github.com/SSWConsulting/SSW.YakShaver/issues/3095
186+
- name: Create .env from secrets
187+
env:
188+
YOUTUBE_CLIENT_ID: ${{ secrets.YOUTUBE_CLIENT_ID }}
189+
YOUTUBE_CLIENT_SECRET: ${{ secrets.YOUTUBE_CLIENT_SECRET }}
190+
run: |
191+
printf "YOUTUBE_CLIENT_ID=%s\nYOUTUBE_CLIENT_SECRET=%s\n" "$YOUTUBE_CLIENT_ID" "$YOUTUBE_CLIENT_SECRET" > .env
192+
193+
- name: Install dependencies
194+
run: npm ci --prefer-offline
195+
196+
- name: Install UI dependencies
197+
run: npm ci --prefer-offline
198+
working-directory: src/ui
199+
200+
- name: Update version for pre-release
201+
run: |
202+
VERSION="${{ needs.cleanup-release.outputs.version }}"
203+
if [[ -z "$VERSION" ]]; then
204+
echo "Missing version output"
205+
exit 1
206+
fi
207+
npm version "$VERSION" --no-git-tag-version
208+
209+
- name: Publish macOS pre-release
210+
run: npm run publish -- --mac --publish never
211+
env:
212+
NODE_ENV: production
213+
CI: true
214+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
215+
CHANNEL: ${{ needs.cleanup-release.outputs.channel }}
216+
217+
- name: Create or update GitHub release
218+
uses: softprops/action-gh-release@v2
219+
with:
220+
tag_name: ${{ needs.cleanup-release.outputs.release_tag }}
221+
name: "Pre-release PR #${{ needs.cleanup-release.outputs.pr_number }} (${{ needs.cleanup-release.outputs.pr_sha }})"
222+
body: |
223+
Pre-release build for PR #${{ needs.cleanup-release.outputs.pr_number }}
224+
225+
Commit: ${{ needs.cleanup-release.outputs.pr_sha }}
226+
PR: ${{ github.event.pull_request.html_url || 'N/A' }}
227+
228+
This is an automated pre-release. It will be updated automatically when new commits are pushed to the PR.
229+
prerelease: true
230+
files: |
231+
build/YakShaver-*-mac.zip
232+
build/YakShaver-*-mac.zip.blockmap
233+
build/*-mac.yml
234+
draft: false
235+
token: ${{ secrets.GITHUB_TOKEN }}
236+
237+
comment-release:
238+
runs-on: ubuntu-latest
239+
needs:
240+
- cleanup-release
241+
- build-windows
242+
- build-macos
243+
if: |
244+
github.event.action != 'closed' &&
245+
needs.cleanup-release.outputs.pr_number != ''
246+
steps:
247+
- name: Comment release link on PR
248+
uses: peter-evans/create-or-update-comment@v5
249+
with:
250+
token: ${{ secrets.GITHUB_TOKEN }}
251+
issue-number: ${{ needs.cleanup-release.outputs.pr_number }}
252+
body: |
253+
🚀 Pre-release build is available for this PR:
254+
https://github.com/${{ github.repository }}/releases/tag/${{ needs.cleanup-release.outputs.release_tag }}
255+
256+
delete-release:
257+
runs-on: ubuntu-latest
258+
if: |
259+
github.event_name == 'pull_request' &&
260+
github.event.action == 'closed'
261+
steps:
262+
- name: Delete PR pre-releases
263+
env:
264+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
265+
run: |
266+
PR_NUMBER="${{ github.event.pull_request.number }}"
267+
268+
echo "Deleting all releases for closed PR #${PR_NUMBER}"
269+
270+
# Collect both release IDs and tag names BEFORE deleting anything
271+
RELEASES_DATA=$(gh api --paginate /repos/${{ github.repository }}/releases --jq ".[] | select(.body | contains(\"PR #${PR_NUMBER}\")) | {id: .id, tag: .tag_name}")
272+
273+
RELEASE_IDS=$(echo "$RELEASES_DATA" | jq -r '.id')
274+
TAG_NAMES=$(echo "$RELEASES_DATA" | jq -r '.tag')
275+
276+
# Delete the releases
277+
for id in $RELEASE_IDS; do
278+
if [ -n "$id" ]; then
279+
echo "Deleting release ID: $id"
280+
gh api -X DELETE /repos/${{ github.repository }}/releases/$id || true
281+
fi
282+
done
283+
284+
# Clean up associated tags (collected before deletion)
285+
for tag in $TAG_NAMES; do
286+
if [ -n "$tag" ]; then
287+
echo "Deleting tag: $tag"
288+
gh api -X DELETE /repos/${{ github.repository }}/git/refs/tags/$tag || true
289+
fi
290+
done
291+
292+
echo "Deletion completed for closed PR"

electron-builder.config.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
module.exports = {
2+
appId: "com.ssw.yakshaver",
3+
productName: "YakShaver",
4+
directories: {
5+
output: "build",
6+
buildResources: "src/ui/public/icons",
7+
},
8+
files: [
9+
"**/*",
10+
"!**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme}",
11+
"!src/ui/**",
12+
"src/ui/dist/**",
13+
"!src/backend/**",
14+
"!**/*.ts",
15+
"!**/node_modules/**/*.md",
16+
],
17+
extraResources: [".env", "src/ui/public/**"],
18+
asar: true,
19+
asarUnpack: ["src/ui/dist/**", "**/@ffmpeg-installer/**"],
20+
afterPack: "./afterPack.js",
21+
win: {
22+
icon: "src/ui/public/icons/icon.ico",
23+
target: [
24+
{
25+
target: "nsis",
26+
arch: ["x64"],
27+
},
28+
],
29+
},
30+
nsis: {
31+
oneClick: false,
32+
allowToChangeInstallationDirectory: true,
33+
},
34+
mac: {
35+
icon: "src/ui/public/icons/icon.icns",
36+
target: ["zip"],
37+
},
38+
linux: {
39+
icon: "src/ui/public/icons/icon.png",
40+
target: ["deb"],
41+
},
42+
generateUpdatesFilesForAllChannels: true,
43+
publish: [
44+
{
45+
provider: "github",
46+
owner: "SSWConsulting",
47+
repo: "SSW.YakShaver.Desktop",
48+
private: false,
49+
releaseType: process.env.RELEASE_TYPE || "release",
50+
channel: process.env.CHANNEL || "latest",
51+
},
52+
],
53+
};

0 commit comments

Comments
 (0)