Skip to content

Commit 32a6c7f

Browse files
committed
ci: overhaul artifact naming and release pipeline
Artifact naming conventions: - Use 'x64' everywhere (drop 'x86_64', 'amd64') - Files live in os/arch folders with simple basenames Linux archive: - Replace ZIP releases with self-contained tar.xz for Gateway and Jetsocat on Linux and macOS; Windows uses .zip for Jetsocat Windows ZIP: - Add DevolutionsGateway-{Version}-windows-x64.zip (exe + xmf.dll + webapp) mirroring the Linux tar.xz structure Jetsocat archive format: - Linux and macOS: .tar.xz - Windows: .zip - Hard-fail (throw) on any missing binary; no soft-skip webapp artifact: - Drop tar.gz wrapper; re-upload raw directories - Rename job web-app -> webapp tun2socks: - Stage under tun2socks/\/ per build so files land in arch subdirs; per-arch artifacts named tun2socks-windows-{arch} - Add tun2socks-windows-merge job to produce single tun2socks-windows artifact; package.yml downloads it in one line into \/windows arm64 Agent MSI: - Loop over @('x64','arm64') in a single 'Regenerate and Repackage Agent MSI' step: generate, sign runtime EXEs, assemble for each arch
1 parent fc3b46f commit 32a6c7f

7 files changed

Lines changed: 444 additions & 392 deletions

File tree

.claude/settings.local.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(pwsh .claude/skills/prepare-release/scripts/resolve-version.ps1 -Arg \"\")",
5+
"Bash(pwsh .claude/skills/prepare-release/scripts/resolve-version.ps1 -Arg \"hotfix\")",
6+
"Bash(pwsh ./tools/bump-version.ps1 -NewVersion 2026.1.2 2>&1)",
7+
"Bash(git cliff:*)",
8+
"mcp__claude_ai_Atlassian__transitionJiraIssue",
9+
"mcp__claude_ai_Atlassian__getTransitionsForJiraIssue",
10+
"mcp__claude_ai_Atlassian__searchJiraIssuesUsingJql"
11+
]
12+
}
13+
}

.github/workflows/ci.yml

Lines changed: 136 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
id: setup-matrix
4444
run: |
4545
$Jobs = @()
46-
$Archs = @( 'x86_64', 'arm64' )
46+
$Archs = @( 'x64', 'arm64' )
4747
$Platforms = @( 'linux', 'windows' )
4848
4949
$Platforms | ForEach-Object {
@@ -203,7 +203,7 @@ jobs:
203203
runs-on: ${{ matrix.runner }}
204204
strategy:
205205
matrix:
206-
arch: [x86_64]
206+
arch: [x64]
207207
os: [windows, linux]
208208
include:
209209
- os: windows
@@ -325,7 +325,7 @@ jobs:
325325
shell: pwsh
326326

327327
- name: Configure macOS (intel) runner
328-
if: ${{ matrix.os == 'macos' && matrix.arch == 'x86_64' }}
328+
if: ${{ matrix.os == 'macos' && matrix.arch == 'x64' }}
329329
run: |
330330
sudo rm -rf /Library/Developer/CommandLineTools
331331
rustup target add x86_64-apple-darwin
@@ -335,7 +335,7 @@ jobs:
335335
run: |
336336
$StagingPath = Join-Path $Env:RUNNER_TEMP "staging"
337337
$TargetOutputPath = Join-Path $StagingPath ${{ matrix.os }} ${{ matrix.arch }}
338-
$ExecutableFileName = 'jetsocat_${{ runner.os }}_${{ needs.preflight.outputs.version }}_${{ matrix.arch }}'
338+
$ExecutableFileName = 'jetsocat'
339339
340340
if ($Env:RUNNER_OS -eq "Windows") {
341341
$ExecutableFileName = "$($ExecutableFileName).exe"
@@ -344,8 +344,8 @@ jobs:
344344
}
345345
346346
if ($Env:RUNNER_OS -eq "Linux") {
347-
$LinuxArch = @{'x86_64'='amd64';'arm64'='arm64'}['${{ matrix.arch }}']
348-
$RustArch = @{'x86_64'='x86_64';'arm64'='aarch64'}['${{ matrix.arch }}']
347+
$LinuxArch = @{'x64'='amd64';'arm64'='arm64'}['${{ matrix.arch }}']
348+
$RustArch = @{'x64'='x86_64';'arm64'='aarch64'}['${{ matrix.arch }}']
349349
$RustTarget = "$RustArch-unknown-linux-gnu"
350350
$Env:SYSROOT_NAME = "ubuntu-18.04-$LinuxArch"
351351
. "$HOME/.cargo/cbake/${RustTarget}-enter.ps1"
@@ -402,8 +402,8 @@ jobs:
402402
run: |
403403
$OutputPath = Join-Path "macos" "universal"
404404
New-Item -ItemType Directory -Path $OutputPath | Out-Null
405-
$Binaries = Get-ChildItem -Recurse -Path "macos" -Filter "jetsocat_*" | Foreach-Object { $_.FullName } | Select -Unique
406-
$LipoCmd = $(@('lipo', '-create', '-output', (Join-Path -Path $OutputPath -ChildPath "jetsocat_macOS_${{ needs.preflight.outputs.version }}_universal")) + $Binaries) -Join ' '
405+
$Binaries = Get-ChildItem -Recurse -Path "macos" -Filter "jetsocat" -File | Foreach-Object { $_.FullName } | Select -Unique
406+
$LipoCmd = $(@('lipo', '-create', '-output', (Join-Path -Path $OutputPath -ChildPath "jetsocat")) + $Binaries) -Join ' '
407407
Write-Host $LipoCmd
408408
Invoke-Expression $LipoCmd
409409
shell: pwsh
@@ -576,7 +576,7 @@ jobs:
576576
- name: Download Cadeau
577577
run: |
578578
$Platform = @{'windows'='win'; 'linux'='linux'}['${{ matrix.os }}']
579-
$Arch = @{'x86_64'='x64';'arm64'='arm64'}['${{ matrix.arch }}']
579+
$Arch = '${{ matrix.arch }}'
580580
./ci/download-cadeau.ps1 -Platform $Platform -Architecture $Arch
581581
shell: pwsh
582582

@@ -586,11 +586,10 @@ jobs:
586586
$PackageVersion = "${{ needs.preflight.outputs.version }}"
587587
$StagingPath = Join-Path $Env:RUNNER_TEMP "staging"
588588
$TargetOutputPath = Join-Path $StagingPath ${{ matrix.os }} ${{ matrix.arch }}
589-
$ExecutableFileName = "DevolutionsGateway_${{ runner.os }}_${PackageVersion}_${{ matrix.arch }}"
589+
$ExecutableFileName = if ($Env:RUNNER_OS -eq "Windows") { "DevolutionsGateway.exe" } else { "devolutions-gateway" }
590590
591591
if ($Env:RUNNER_OS -eq "Windows") {
592-
$ExecutableFileName = "$($ExecutableFileName).exe"
593-
$PackageFileName = "DevolutionsGateway-${{ matrix.arch }}-${PackageVersion}.msi"
592+
$PackageFileName = "DevolutionsGateway.msi"
594593
$DGatewayPackage = Join-Path $TargetOutputPath $PackageFileName
595594
echo "dgateway-package=$DGatewayPackage" >> $Env:GITHUB_OUTPUT
596595
}
@@ -657,8 +656,8 @@ jobs:
657656
- name: Build
658657
run: |
659658
if ($Env:RUNNER_OS -eq "Linux") {
660-
$LinuxArch = @{'x86_64'='amd64';'arm64'='arm64'}['${{ matrix.arch }}']
661-
$RustArch = @{'x86_64'='x86_64';'arm64'='aarch64'}['${{ matrix.arch }}']
659+
$LinuxArch = @{'x64'='amd64';'arm64'='arm64'}['${{ matrix.arch }}']
660+
$RustArch = @{'x64'='x86_64';'arm64'='aarch64'}['${{ matrix.arch }}']
662661
$RustTarget = "$RustArch-unknown-linux-gnu"
663662
$Env:SYSROOT_NAME = "ubuntu-18.04-$LinuxArch"
664663
. "$HOME/.cargo/cbake/${RustTarget}-enter.ps1"
@@ -703,6 +702,14 @@ jobs:
703702
$Env:DGATEWAY_WEBPLAYER_PATH = Join-Path "webapp" "dist" "recording-player" | Resolve-Path
704703
705704
./ci/tlk.ps1 package -Product gateway -Platform ${{ matrix.os }} -Architecture ${{ matrix.arch }} -CargoProfile ${{ needs.preflight.outputs.rust-profile }}
705+
706+
# Rename versioned fpm output to simple basenames for consistent folder-based addressing.
707+
if ($Env:RUNNER_OS -eq "Linux") {
708+
$OutputPath = "${{ steps.load-variables.outputs.target-output-path }}"
709+
Get-ChildItem "$OutputPath/*.deb" | Rename-Item -NewName "devolutions-gateway.deb"
710+
Get-ChildItem "$OutputPath/*.changes" | Rename-Item -NewName "devolutions-gateway.changes"
711+
Get-ChildItem "$OutputPath/*.rpm" | Rename-Item -NewName "devolutions-gateway.rpm"
712+
}
706713
shell: pwsh
707714
env:
708715
DGATEWAY_EXECUTABLE: ${{ steps.load-variables.outputs.dgateway-executable }}
@@ -787,11 +794,10 @@ jobs:
787794
New-Item -ItemType Directory $SymbolsPath
788795
789796
$TargetOutputPath = Join-Path $StagingPath ${{ matrix.os }} ${{ matrix.arch }}
790-
$ExecutableFileName = "DevolutionsAgent_${{ runner.os }}_${PackageVersion}_${{ matrix.arch }}"
797+
$ExecutableFileName = if ($Env:RUNNER_OS -eq "Windows") { "DevolutionsAgent.exe" } else { "devolutions-agent" }
791798
792799
if ($Env:RUNNER_OS -eq "Windows") {
793-
$ExecutableFileName = "$($ExecutableFileName).exe"
794-
$PackageFileName = "DevolutionsAgent-${{ matrix.arch }}-${PackageVersion}.msi"
800+
$PackageFileName = "DevolutionsAgent.msi"
795801
$DAgentPackage = Join-Path $TargetOutputPath $PackageFileName
796802
797803
echo "dagent-package=$DAgentPackage" >> $Env:GITHUB_OUTPUT
@@ -805,7 +811,7 @@ jobs:
805811
$DAgentSessionExecutable = Join-Path $TargetOutputPath "DevolutionsSession.exe"
806812
echo "dagent-session-executable=$DAgentSessionExecutable" >> $Env:GITHUB_OUTPUT
807813
808-
$DAgentUpdaterExecutable = Join-Path $TargetOutputPath "DevolutionsAgentUpdater_${{ runner.os }}_${PackageVersion}_${{ matrix.arch }}.exe"
814+
$DAgentUpdaterExecutable = Join-Path $TargetOutputPath "DevolutionsAgentUpdater.exe"
809815
echo "dagent-updater-executable=$DAgentUpdaterExecutable" >> $Env:GITHUB_OUTPUT
810816
}
811817
@@ -827,8 +833,8 @@ jobs:
827833
id: tun2socks
828834
if: ${{ matrix.os == 'windows' }}
829835
run: |
830-
$Arch = @{'x86_64'='x64';'arm64'='arm64'}['${{ matrix.arch }}']
831-
$Destination = Join-Path $PWD "tun2socks"
836+
$Arch = '${{ matrix.arch }}'
837+
$Destination = Join-Path $PWD "tun2socks" $Arch
832838
./ci/download-tun2socks.ps1 -Architecture $Arch -Destination $Destination
833839
$Tun2SocksExecutablePath = Join-Path $Destination "tun2socks.exe"
834840
$WintunLibraryPath = Join-Path $Destination "wintun.dll"
@@ -843,7 +849,7 @@ jobs:
843849
if: ${{ matrix.os == 'windows' }}
844850
uses: actions/upload-artifact@v7
845851
with:
846-
name: tun2socks-${{ matrix.os }}-${{ matrix.arch }}
852+
name: tun2socks-windows-${{ matrix.arch }}
847853
path: tun2socks/
848854

849855
- name: Setup LLVM
@@ -911,8 +917,8 @@ jobs:
911917
}
912918
913919
if ($Env:RUNNER_OS -eq "Linux") {
914-
$LinuxArch = @{'x86_64'='amd64';'arm64'='arm64'}['${{ matrix.arch }}']
915-
$RustArch = @{'x86_64'='x86_64';'arm64'='aarch64'}['${{ matrix.arch }}']
920+
$LinuxArch = @{'x64'='amd64';'arm64'='arm64'}['${{ matrix.arch }}']
921+
$RustArch = @{'x64'='x86_64';'arm64'='aarch64'}['${{ matrix.arch }}']
916922
$RustTarget = "$RustArch-unknown-linux-gnu"
917923
$Env:SYSROOT_NAME = "ubuntu-18.04-$LinuxArch"
918924
. "$HOME/.cargo/cbake/${RustTarget}-enter.ps1"
@@ -944,6 +950,14 @@ jobs:
944950
}
945951
946952
./ci/tlk.ps1 package -Product agent -Platform ${{ matrix.os }} -Architecture ${{ matrix.arch }} -CargoProfile ${{ needs.preflight.outputs.rust-profile }}
953+
954+
# Rename versioned fpm output to simple basenames for consistent folder-based addressing.
955+
if ($Env:RUNNER_OS -eq "Linux") {
956+
$OutputPath = "${{ steps.load-variables.outputs.target-output-path }}"
957+
Get-ChildItem "$OutputPath/*.deb" | Rename-Item -NewName "devolutions-agent.deb"
958+
Get-ChildItem "$OutputPath/*.changes" | Rename-Item -NewName "devolutions-agent.changes"
959+
Get-ChildItem "$OutputPath/*.rpm" | Rename-Item -NewName "devolutions-agent.rpm"
960+
}
947961
shell: pwsh
948962
env:
949963
DAGENT_EXECUTABLE: ${{ steps.load-variables.outputs.dagent-executable }}
@@ -987,6 +1001,19 @@ jobs:
9871001
pattern: devolutions-agent-*
9881002
delete-merged: true
9891003

1004+
tun2socks-windows-merge:
1005+
name: tun2socks windows merge artifacts
1006+
runs-on: ubuntu-latest
1007+
needs: [preflight, devolutions-agent]
1008+
1009+
steps:
1010+
- name: Merge Artifacts
1011+
uses: actions/upload-artifact/merge@v7
1012+
with:
1013+
name: tun2socks-windows
1014+
pattern: tun2socks-windows-*
1015+
delete-merged: true
1016+
9901017
devolutions-pedm-client:
9911018
name: devolutions-pedm-client
9921019
runs-on: ubuntu-latest
@@ -1020,9 +1047,7 @@ jobs:
10201047
ref: ${{ needs.preflight.outputs.ref }}
10211048

10221049
- name: Tests
1023-
run: |
1024-
Set-PSDebug -Trace 1
1025-
dotnet test utils/dotnet/GatewayUtils.sln
1050+
run: dotnet test utils/dotnet/GatewayUtils.sln
10261051
shell: pwsh
10271052

10281053

@@ -1290,39 +1315,98 @@ jobs:
12901315
12911316
New-Item -Path "$destinationFolder" -ItemType "directory"
12921317
1293-
$allFiles = Get-ChildItem -Path "$sourceFolder" -Exclude PowerShell | Get-ChildItem -Recurse | Where { -Not $_.Mode.StartsWith('d') }
1294-
1295-
# Exclude some files that are already bundled in installers
1296-
$excludeFiles = @(
1297-
'DevolutionsPedmShellExt.dll',
1298-
'DevolutionsPedmShellExt.msix',
1299-
'DevolutionsSession.exe',
1300-
# NOTE: We may want to include that in the future, but needs to be renamed per platform.
1301-
# TODO(@awakecoding): We could create a zip with the same name as
1302-
# the package except ".symbols" at the end, so we'd end up with arch-specific zips
1303-
# containing the debug symbols. I've done this for MsRdpEx.
1304-
'DevolutionsPedmShellExt.pdb',
1305-
'DevolutionsSession.pdb'
1318+
function MoveArtifact([string]$RelSource, [string]$DestName) {
1319+
$src = Join-Path $sourceFolder $RelSource
1320+
$dst = Join-Path $destinationFolder $DestName
1321+
Write-Host "$src --> $dst"
1322+
Move-Item -Path $src -Destination $dst
1323+
}
1324+
1325+
# Create symbols ZIPs from individual PDBs (package.yml signing hasn't run yet).
1326+
$SymbolProducts = @(
1327+
@{ Dir = 'devolutions-gateway'; Name = 'DevolutionsGateway'; Arches = @('x64') },
1328+
@{ Dir = 'devolutions-agent'; Name = 'DevolutionsAgent'; Arches = @('x64', 'arm64') },
1329+
@{ Dir = 'jetsocat'; Name = 'jetsocat'; Arches = @('x64', 'arm64') }
13061330
)
1331+
foreach ($P in $SymbolProducts) {
1332+
foreach ($Arch in $P.Arches) {
1333+
$ArchDir = Join-Path $sourceFolder $P.Dir windows $Arch
1334+
$Pdbs = Get-ChildItem -Path $ArchDir -Filter '*.pdb' -File -ErrorAction SilentlyContinue
1335+
if ($Pdbs) {
1336+
$Pdbs | Compress-Archive -DestinationPath (Join-Path $ArchDir "$($P.Name).symbols.zip") -CompressionLevel Optimal
1337+
}
1338+
}
1339+
}
13071340
1308-
Write-Host
1341+
# Gateway Windows MSI + symbols
1342+
MoveArtifact "devolutions-gateway/windows/x64/DevolutionsGateway.msi" "DevolutionsGateway-${version}-x64.msi"
1343+
MoveArtifact "devolutions-gateway/windows/x64/DevolutionsGateway.symbols.zip" "DevolutionsGateway-${version}-x64.symbols.zip"
13091344
1310-
foreach ($file in $allFiles) {
1311-
$dir = $file.Directory
1312-
$name = $file.Name
1313-
$source = "$dir/$name"
1314-
$destination = "$destinationFolder/$name"
1345+
# Gateway Linux DEB/RPM/changes
1346+
foreach ($Arch in @('x64', 'arm64')) {
1347+
MoveArtifact "devolutions-gateway/linux/${Arch}/devolutions-gateway.deb" "devolutions-gateway_${version}_${Arch}.deb"
1348+
MoveArtifact "devolutions-gateway/linux/${Arch}/devolutions-gateway.rpm" "devolutions-gateway_${version}_${Arch}.rpm"
1349+
MoveArtifact "devolutions-gateway/linux/${Arch}/devolutions-gateway.changes" "devolutions-gateway_${version}_${Arch}.changes"
1350+
}
13151351
1316-
# Skip architecture-specific files that are part of installers
1317-
if ($name -in $excludeFiles) {
1318-
Write-Host "Skipping $source"
1319-
continue
1320-
}
1352+
# Agent Windows MSI + symbols.zip
1353+
foreach ($Arch in @('x64', 'arm64')) {
1354+
MoveArtifact "devolutions-agent/windows/${Arch}/DevolutionsAgent.msi" "DevolutionsAgent-${version}-${Arch}.msi"
1355+
MoveArtifact "devolutions-agent/windows/${Arch}/DevolutionsAgent.symbols.zip" "DevolutionsAgent-${version}-${Arch}.symbols.zip"
1356+
}
13211357
1322-
Write-Host "$source --> $destination"
1358+
# Agent Linux DEB/RPM/changes
1359+
foreach ($Arch in @('x64', 'arm64')) {
1360+
MoveArtifact "devolutions-agent/linux/${Arch}/devolutions-agent.deb" "devolutions-agent_${version}_${Arch}.deb"
1361+
MoveArtifact "devolutions-agent/linux/${Arch}/devolutions-agent.rpm" "devolutions-agent_${version}_${Arch}.rpm"
1362+
MoveArtifact "devolutions-agent/linux/${Arch}/devolutions-agent.changes" "devolutions-agent_${version}_${Arch}.changes"
1363+
}
13231364
1324-
Move-Item -Path "$source" -Destination "$destination"
1365+
# Jetsocat archives: .tar.xz for Linux, .zip for Windows and macOS
1366+
$Platforms = @(
1367+
@{ OS = "windows"; Arch = "x64"; Ext = ".exe"; Archive = "zip" },
1368+
@{ OS = "windows"; Arch = "arm64"; Ext = ".exe"; Archive = "zip" },
1369+
@{ OS = "linux"; Arch = "x64"; Ext = ""; Archive = "tar.xz" },
1370+
@{ OS = "linux"; Arch = "arm64"; Ext = ""; Archive = "tar.xz" },
1371+
@{ OS = "macos"; Arch = "x64"; Ext = ""; Archive = "tar.xz" },
1372+
@{ OS = "macos"; Arch = "arm64"; Ext = ""; Archive = "tar.xz" },
1373+
@{ OS = "macos"; Arch = "universal"; Ext = ""; Archive = "tar.xz" }
1374+
)
1375+
1376+
foreach ($P in $Platforms) {
1377+
$BinaryPath = Join-Path $sourceFolder jetsocat $P.OS $P.Arch "jetsocat$($P.Ext)"
1378+
if (Test-Path $BinaryPath) {
1379+
$ArchiveDst = Join-Path $destinationFolder "jetsocat-${version}-$($P.OS)-$($P.Arch).$($P.Archive)"
1380+
$BinaryName = Split-Path $BinaryPath -Leaf
1381+
$StageDir = Join-Path $Env:RUNNER_TEMP "jetsocat-stage-$($P.OS)-$($P.Arch)"
1382+
New-Item -ItemType Directory -Path $StageDir -Force | Out-Null
1383+
Copy-Item -Path $BinaryPath -Destination (Join-Path $StageDir $BinaryName) -Force
1384+
if ($P.Archive -eq 'tar.xz') {
1385+
tar -cJf $ArchiveDst -C $StageDir .
1386+
} else {
1387+
# Compress-Archive preserves the source path structure inside the ZIP.
1388+
# Staging to a flat temp dir ensures the binary lands at the ZIP root.
1389+
Compress-Archive -Path (Join-Path $StageDir '*') -DestinationPath $ArchiveDst -Force
1390+
}
1391+
Remove-Item -Path $StageDir -Recurse -Force
1392+
Write-Host "$BinaryPath --> $ArchiveDst"
1393+
} else {
1394+
throw "Jetsocat binary not found: $BinaryPath"
1395+
}
13251396
}
1397+
1398+
# Jetsocat Windows symbols
1399+
foreach ($Arch in @('x64', 'arm64')) {
1400+
$SymPath = Join-Path $sourceFolder jetsocat windows $Arch jetsocat.symbols.zip
1401+
if (Test-Path $SymPath) {
1402+
MoveArtifact "jetsocat/windows/${Arch}/jetsocat.symbols.zip" "jetsocat-${version}-windows-${Arch}.symbols.zip"
1403+
} else {
1404+
throw "Jetsocat Windows symbols not found: $SymPath"
1405+
}
1406+
}
1407+
1408+
# git-log
1409+
MoveArtifact "git-log/git-log.txt" "git-log.txt"
13261410
shell: pwsh
13271411

13281412
- name: Upload to OneDrive

0 commit comments

Comments
 (0)