Skip to content

Commit c9bdb21

Browse files
committed
ci: add github action for building the app
1 parent 0d3d651 commit c9bdb21

File tree

10 files changed

+240
-26
lines changed

10 files changed

+240
-26
lines changed

.github/workflows/release.yaml

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
name: build
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- "src/**"
9+
pull_request:
10+
branches:
11+
- main
12+
paths:
13+
- "src/**"
14+
15+
permissions:
16+
contents: write
17+
18+
jobs:
19+
build-exe:
20+
runs-on: windows-2022
21+
steps:
22+
- name: Checkout code
23+
uses: actions/checkout@v4
24+
25+
- name: Generate release version
26+
id: version
27+
env:
28+
GH_TOKEN: ${{ github.token }}
29+
shell: pwsh
30+
run: |
31+
$today = (Get-Date -Format 'yyyy.M.d')
32+
$defaultVersion = "${today}.0"
33+
34+
# fetch the latest release tag name
35+
try {
36+
$latestVersion = gh release list --limit 1 --json tagName | ConvertFrom-Json | Select-Object -ExpandProperty tagName
37+
} catch {
38+
$latestVersion = ""
39+
}
40+
41+
# check if we successfully got a latest version and if its date matches today's date
42+
if (-not [string]::IsNullOrEmpty($latestVersion) -and ($latestVersion -match '^v([0-9]{4}\.[0-9]{2}\.[0-9]{2})\.([0-9]+)$')) {
43+
$latestDate = $Matches[1]
44+
$latestIncrement = [int]$Matches[2]
45+
46+
if ($latestDate -eq $today) {
47+
# date matches; increment the number
48+
$newIncrement = $latestIncrement + 1
49+
$newVersion = "${today}.${newIncrement}"
50+
} else {
51+
# date does not match; use the default version with .0
52+
$newVersion = $defaultVersion
53+
}
54+
} else {
55+
# No latest release found or format is unexpected, use the default version with .0
56+
$newVersion = $defaultVersion
57+
}
58+
59+
Write-Host "Using version $newVersion"
60+
echo "version=$newVersion" >> $env:GITHUB_OUTPUT
61+
62+
- name: Install signing certificate
63+
id: cert
64+
env:
65+
CERTIFICATE_BASE64: ${{ secrets.CERTIFICATE_BASE64 }}
66+
CERTIFICATE_PASSWORD: ${{ secrets.CERTIFICATE_PASSWORD }}
67+
shell: pwsh
68+
run: |
69+
$b64Path = "$env:TEMP\certificate.base64.txt"
70+
$certPath = "$env:TEMP\certificate.pfx"
71+
Remove-Item -Path $b64Path, $certPath -ErrorAction Ignore
72+
73+
Set-Content -Path $b64Path -Value $env:CERTIFICATE_BASE64 -Encoding ASCII
74+
75+
& certutil -decode $b64Path $certPath
76+
77+
$certPassword = ConvertTo-SecureString -String ${{ secrets.CERTIFICATE_PASSWORD }} -AsPlainText -Force
78+
Import-PfxCertificate -FilePath $certPath -CertStoreLocation Cert:\CurrentUser\My -Password $certPassword
79+
80+
# import the certificate and capture the output object
81+
$importedCert = Import-PfxCertificate -FilePath $certPath -CertStoreLocation Cert:\CurrentUser\My -Password $certPassword
82+
83+
# output the thumbprint
84+
if ($null -ne $importedCert) {
85+
# save thumbprint to github output
86+
$thumbprint = $importedCert.Thumbprint
87+
Write-Host "Certificate thumbprint: $thumbprint"
88+
echo "thumbprint=$thumbprint" >> $env:GITHUB_OUTPUT
89+
90+
} else {
91+
Write-Error "Failed to import certificate or retrieve the certificate object."
92+
}
93+
94+
# clean up
95+
Remove-Item -Path $b64Path, $certPath -Force
96+
97+
- name: Build app
98+
shell: pwsh
99+
run: |
100+
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
101+
.\build.ps1 -ForceVersion ${{ steps.version.outputs.version }} -ForcePublisher "Jack Buehner"
102+
103+
- name: Build for Microsoft Store
104+
shell: pwsh
105+
run: |
106+
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
107+
.\build.ps1 -ForStore
108+
109+
- name: Save store build output
110+
uses: actions/upload-artifact@v4
111+
with:
112+
name: "msft-store-build"
113+
path: |
114+
dist/msft-store/
115+
116+
- name: Add version number to file name
117+
shell: pwsh
118+
run: |
119+
$version = "${{ steps.version.outputs.version }}"
120+
121+
# make all names lowercase and use underscores instead of spaces
122+
$files = Get-ChildItem -Path "dist" -File
123+
foreach ($file in $files) {
124+
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($file.Name)
125+
$extension = [System.IO.Path]::GetExtension($file.Name)
126+
$newName = "$($baseName.ToLower())$extension"
127+
$newName = $newName -replace ' ', '_'
128+
Rename-Item -Path $file.FullName -NewName $newName
129+
}
130+
131+
# add version number to the msix file name
132+
$file = Get-ChildItem -Path "dist" -Filter "rdp_protocol_handler.msix" -File
133+
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($file.Name)
134+
$extension = [System.IO.Path]::GetExtension($file.Name)
135+
$newName = "${baseName}_v${version}$extension"
136+
Rename-Item -Path $file.FullName -NewName $newName
137+
138+
# echo all the file names
139+
$files = Get-ChildItem -Path "dist" -File
140+
foreach ($file in $files) {
141+
Write-Host "File: $($file.Name)"
142+
}
143+
144+
- name: Create draft release
145+
uses: ncipollo/release-action@v1
146+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/heads/main')
147+
with:
148+
artifacts: "dist/rdp_protocol_handler_v${{ steps.version.outputs.version }}.msix,dist/rdp_protocol_handler.cer,dist/install_cert.bat" # comma-delimited list of artifact names
149+
tag: "v${{ steps.version.outputs.version }}"
150+
name: "Release v${{ steps.version.outputs.version }}"
151+
draft: true
152+
generateReleaseNotes: true
153+
skipIfReleaseExists: true
154+
body: |
155+
## Get the latest published release
156+
157+
<a href="https://apps.microsoft.com/detail/9n1192wschv9" target="_blank">
158+
<picture>
159+
<source media="(prefers-color-scheme: dark)" srcset="https://get.microsoft.com/images/en-us%20light.svg">
160+
<source media="(prefers-color-scheme: light)" srcset="https://get.microsoft.com/images/en-us%20dark.svg">
161+
<img src="frontend/lib/assets/favorites_light.png" alt="A screenshot of the favorites page in RAWeb">
162+
</picture>
163+
</a>
164+
165+
## Install this release
166+
167+
1. **Install the certificate**
168+
Download `rdp_protocol_handler.ce` and `install_cert.bat`. Run `install_cert.bat`.
169+
170+
2. **Install the app**
171+
Download `rdp_protocol_handler_v${{ steps.version.outputs.version }}.msix` and open it. Click **Install** to install the app.

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
11
src/package/priconfig.xml
2+
src/package/rdp_launcher.exe
23
src/package/resources.pri
34
dist/msft-store
5+
dist/
6+
.artifacts
7+
cert.base64.txt
8+
cert.cer
9+
cert.pfx
10+
cert.pvk
11+
runner.secrets

.vscode/tasks.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"version": "2.0.0",
3+
"tasks": [
4+
{
5+
"label": "build",
6+
"type": "shell",
7+
"command": "act -s GITHUB_TOKEN=$(gh auth token) -P windows-2022=-self-hosted --artifact-server-path $PWD/.artifacts --secret-file runner.secrets",
8+
"options": {
9+
"shell": {
10+
"executable": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
11+
"args": [
12+
"-NoProfile",
13+
"-ExecutionPolicy",
14+
"Bypass"
15+
]
16+
}
17+
},
18+
"group": {
19+
"kind": "build",
20+
"isDefault": true
21+
},
22+
"problemMatcher": [
23+
"$tsc"
24+
]
25+
}
26+
]
27+
}

build.ps1

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
Param(
22
[switch]$Unpackaged = $false,
3-
[switch]$ForStore = $false
3+
[switch]$ForStore = $false,
4+
[string]$ForceVersion = $null, # Optional parameter to force a specific version
5+
[string]$ForcePublisher = $null # Optional parameter to force a specific publisher
46
)
57

68
function Find-CertificateByEkuAndPublisher {
@@ -136,7 +138,11 @@ if ($ForStore) {
136138
$manifestPath = "$packageDir\appxmanifest.xml"
137139
$xml = [xml](Get-Content $manifestPath)
138140

139-
$version = (Get-Date).ToString("yyyy.Mdd.Hmm.0") # Microsft Store requires the last part to be 0
141+
$version = $ForceVersion
142+
if (-not $version) {
143+
# if no version is provided, use the current date and time
144+
$version = (Get-Date).ToString("yyyy.Mdd.Hmm.0") # Microsft Store requires the last part to be 0
145+
}
140146
$xml.Package.Identity.Version = $version
141147

142148
# set the identity name in appxmanifest.xml
@@ -147,7 +153,9 @@ if ($ForStore) {
147153
}
148154

149155
# Set the publisher in appxmanifest.xml
150-
if ($ForStore) {
156+
if ($ForcePublisher) {
157+
$publisher = $ForcePublisher
158+
} elseif ($ForStore) {
151159
$publisher = "21E4C6BE-57F6-4999-923A-E201D6663071"
152160
} else {
153161
$publisher = [System.Net.Dns]::GetHostName()

create_cert.ps1

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Run this script on a Windows machine with the Windows SDK installed.
2+
# It will create a code-signing certificate.
3+
# This certificate is used in the GitHub Actions workflow to sign the Windows installer.
4+
5+
# get the platform version from the windows SDK manifest file
6+
$windowsSdkManifestPath = "C:\Program Files (x86)\Windows Kits\10\SDKManifest.xml"
7+
$windowsSdkManifest = [xml](Get-Content $windowsSdkManifestPath)
8+
$platformVersion = $windowsSdkManifest.FileList | Where-Object { $_.PlatformIdentity -match 'UAP, Version=(\d+\.\d+\.\d+\.\d+)' } | ForEach-Object { $_.PlatformIdentity -replace 'UAP, Version=', '' }
9+
Write-Host "Fouund Windows SDK with Platform Version: $platformVersion"
10+
11+
# get the paths for makecert and pvk2pfx
12+
$makecertPath = "C:\Program Files (x86)\Windows Kits\10\bin\$platformVersion\x64\makecert.exe"
13+
$pvk2pfxPath = "C:\Program Files (x86)\Windows Kits\10\bin\$platformVersion\x64\pvk2pfx.exe"
14+
15+
# remove existing cert files
16+
Remove-Item -Path 'cert.cer', 'cert.pvk', 'cert.pfx', 'cert.base64.txt' -ErrorAction SilentlyContinue
17+
18+
& $makecertPath /pe /n "CN=Jack Buehner" /r /h 0 /eku "1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.10.3.13" /e "12/31/2099" cert.cer -sv cert.pvk
19+
20+
& $pvk2pfxPath -pvk cert.pvk -spc cert.cer -pfx cert.pfx
21+
22+
& certutil -encode cert.pfx cert.base64.txt

dist/RDP Protocol Handler.cer

-817 Bytes
Binary file not shown.

dist/RDP Protocol Handler.msix

-19.5 KB
Binary file not shown.

dist/install_cert.bat

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/package/appxmanifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities">
3-
<Identity Name="17225JackBuehner.RDPProtocolHandler" Version="2025.605.1220.0" Publisher="CN=21E4C6BE-57F6-4999-923A-E201D6663071" ProcessorArchitecture="neutral" />
3+
<Identity Name="JackBuehner.RDPProtocolHandler" Version="1.0.0.0" Publisher="CN=JackDesktop2024" ProcessorArchitecture="neutral" />
44
<Properties>
55
<DisplayName>RDP Protocol Handler</DisplayName>
66
<PublisherDisplayName>Jack Buehner</PublisherDisplayName>

src/package/rdp_launcher.exe

-18 KB
Binary file not shown.

0 commit comments

Comments
 (0)