Skip to content

Release

Release #95

Workflow file for this run

name: Release
on:
workflow_dispatch:
inputs:
run:
description: The Package workflow run to release
required: true
dry-run:
description: If true, the workflow only indicates which artifacts would be uploaded
required: true
type: boolean
default: true
workflow_call:
inputs:
dispatch:
description: Marker to indicate that the workflow was dispatched via workflow_call
type: string
required: false
default: workflow_call
dry-run:
description: If true, the workflow only indicates which artifacts would be uploaded
required: true
type: boolean
default: true
concurrency: gateway-release
jobs:
preflight:
name: Preflight
runs-on: ubuntu-latest
outputs:
run: ${{ steps.get-run.outputs.run }}
version: ${{ steps.get-version.outputs.version }}
skip-publishing: ${{ steps.check-release.outputs.skip-publishing }}
steps:
## workflow_dispatch: The run_id is read from the inputs
## workflow_call: The run_id is the current run_id
- name: Get run
id: get-run
run: |
if ('${{ github.event.inputs.run }}') {
echo "run=${{ github.event.inputs.run }}" >> $Env:GITHUB_OUTPUT
} else {
echo "run=${{ github.run_id }}" >> $Env:GITHUB_OUTPUT
}
shell: pwsh
- name: Get dry run
id: get-dry-run
run: |
$DryRun = "false"
if ('${{ inputs.dry-run }}') {
$DryRun = "${{ inputs.dry-run }}"
}
if ([System.Convert]::ToBoolean($DryRun)) {
echo "::notice::This is a dry run; publishing will be skipped"
} else {
echo "::warning::This is not a dry run, release will be published!"
}
shell: pwsh
- name: Download version
run: gh run download ${{ steps.get-run.outputs.run }} -n version --repo $Env:GITHUB_REPOSITORY
shell: pwsh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Get version
id: get-version
run: |
$Version = Get-Content VERSION -TotalCount 1
echo "version=$Version" >> $Env:GITHUB_OUTPUT
echo "::notice::Releasing artifacts for version $Version from run ${{ steps.get-run.outputs.run }}"
shell: pwsh
## If we already released this version to GitHub, publishing will be skipped
- name: Check GitHub releases
id: check-release
run: |
Set-PSDebug -Trace 1
$Output = (gh release list --repo $Env:GITHUB_REPOSITORY) | Out-String
$Releases = ( $Output -split '\r?\n' ).Trim()
$Versions = ForEach($Release in $Releases) {
$Version = ( $Release -Split '\s+' ).Trim()
$Version = $Version.TrimStart("v")
$Version[0]
}
$SkipPublishing = 'false'
if ($Versions -Contains "${{ steps.get-version.outputs.version }}") {
echo "::warning::GitHub already has a release version ${{ steps.get-version.outputs.version }}; publishing will be skipped"
$SkipPublishing = 'true'
}
echo "skip-publishing=$SkipPublishing" >> $Env:GITHUB_OUTPUT
shell: pwsh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
container:
name: Container [${{ matrix.os }} ${{ matrix.base-image }}]
environment: publish-prod
if: ${{ needs.preflight.outputs.skip-publishing == 'false' || inputs.dry-run }}
needs: [preflight]
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
os: [linux]
base-image: [bookworm-slim]
include:
- os: linux
runner: ubuntu-latest
steps:
- name: Download artifacts
run: |
gh run download ${{ needs.preflight.outputs.run }} -n webapp-client -n docker -n devolutions-gateway-signed -n native-libs --repo $Env:GITHUB_REPOSITORY
Move-Item -Path devolutions-gateway-signed -Destination devolutions-gateway
shell: pwsh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Multi-arch Docker build strategy:
# We prepare separate build contexts for amd64 and arm64 because each architecture
# needs its own pre-compiled binary and architecture-specific native libraries (libxmf.so).
# This approach is more reliable than trying to use COPY --platform in the Dockerfile,
# which would require the binaries to be organized in a specific directory structure.
- name: Prepare artifacts (amd64)
id: prepare-artifacts-amd64
run: |
Set-PSDebug -Trace 1
$PkgDir = Join-Path docker $Env:RUNNER_OS "amd64"
echo "package-path-amd64=$PkgDir" >> $Env:GITHUB_OUTPUT
Write-Host "PkgDir = $PkgDir"
New-Item -ItemType Directory -Path $PkgDir -Force
$SourceFileName = "DevolutionsGateway_$($Env:RUNNER_OS)_${{ needs.preflight.outputs.version }}_x86_64"
$TargetFileName = "devolutions-gateway"
Write-Host "SourceFileName = $SourceFileName"
Write-Host "TargetFileName = $TargetFileName"
$SourcePath = Get-ChildItem -Recurse -Filter $SourceFileName -File -Path devolutions-gateway
$TargetPath = Join-Path $PkgDir $TargetFileName
Write-Host "SourcePath = $SourcePath"
Write-Host "TargetPath = $TargetPath"
Copy-Item -Path $SourcePath -Destination $TargetPath
chmod +x $TargetPath
$XmfFileName = "libxmf.so"
$XmfSourcePath = Join-Path "native-libs" "linux" "x64" $XmfFileName | Resolve-Path
$XmfTargetPath = Join-Path $PkgDir $XmfFileName
Write-Host "XmfSourcePath = $XmfSourcePath"
Write-Host "XmfTargetPath = $XmfTargetPath"
Copy-Item -Path $XmfSourcePath -Destination $XmfTargetPath
$WebAppArchive = Get-ChildItem -Recurse -Filter "devolutions_gateway_webapp_*.tar.gz" | Select-Object -First 1
$TargetPath = Join-Path $PkgDir "webapp" "client"
Write-Host "WebAppArchive = $WebAppArchive"
Write-Host "TargetPath = $TargetPath"
New-Item -ItemType Directory -Path $TargetPath
tar -xvzf $WebAppArchive.FullName -C $TargetPath --strip-components=1
$PowerShellArchive = Get-ChildItem -Recurse -Filter "DevolutionsGateway-ps-*.tar" | Select-Object -First 1
$psModuleArchiveHash = (Get-FileHash -Path "$PowerShellArchive").Hash
Write-Host "PS module archive hash: $psModuleArchiveHash"
tar -xvf "$PowerShellArchive" -C "$PkgDir"
# Copy Dockerfile and entrypoint
Copy-Item -Path "docker/Linux/Dockerfile" -Destination $PkgDir
Copy-Item -Path "docker/Linux/entrypoint.ps1" -Destination $PkgDir
shell: pwsh
- name: Prepare artifacts (arm64)
id: prepare-artifacts-arm64
run: |
Set-PSDebug -Trace 1
$PkgDir = Join-Path docker $Env:RUNNER_OS "arm64"
echo "package-path-arm64=$PkgDir" >> $Env:GITHUB_OUTPUT
Write-Host "PkgDir = $PkgDir"
New-Item -ItemType Directory -Path $PkgDir -Force
$SourceFileName = "DevolutionsGateway_$($Env:RUNNER_OS)_${{ needs.preflight.outputs.version }}_arm64"
$TargetFileName = "devolutions-gateway"
Write-Host "SourceFileName = $SourceFileName"
Write-Host "TargetFileName = $TargetFileName"
$SourcePath = Get-ChildItem -Recurse -Filter $SourceFileName -File -Path devolutions-gateway
$TargetPath = Join-Path $PkgDir $TargetFileName
Write-Host "SourcePath = $SourcePath"
Write-Host "TargetPath = $TargetPath"
Copy-Item -Path $SourcePath -Destination $TargetPath
chmod +x $TargetPath
$XmfFileName = "libxmf.so"
$XmfSourcePath = Join-Path "native-libs" "linux" "arm64" $XmfFileName | Resolve-Path
$XmfTargetPath = Join-Path $PkgDir $XmfFileName
Write-Host "XmfSourcePath = $XmfSourcePath"
Write-Host "XmfTargetPath = $XmfTargetPath"
Copy-Item -Path $XmfSourcePath -Destination $XmfTargetPath
$WebAppArchive = Get-ChildItem -Recurse -Filter "devolutions_gateway_webapp_*.tar.gz" | Select-Object -First 1
$TargetPath = Join-Path $PkgDir "webapp" "client"
Write-Host "WebAppArchive = $WebAppArchive"
Write-Host "TargetPath = $TargetPath"
New-Item -ItemType Directory -Path $TargetPath
tar -xvzf $WebAppArchive.FullName -C $TargetPath --strip-components=1
$PowerShellArchive = Get-ChildItem -Recurse -Filter "DevolutionsGateway-ps-*.tar" | Select-Object -First 1
$psModuleArchiveHash = (Get-FileHash -Path "$PowerShellArchive").Hash
Write-Host "PS module archive hash: $psModuleArchiveHash"
tar -xvf "$PowerShellArchive" -C "$PkgDir"
# Copy Dockerfile and entrypoint
Copy-Item -Path "docker/Linux/Dockerfile" -Destination $PkgDir
Copy-Item -Path "docker/Linux/entrypoint.ps1" -Destination $PkgDir
shell: pwsh
# QEMU is required for cross-platform Docker builds on x86_64 runners.
# It enables the runner to emulate ARM64 architecture during the build process.
# Without QEMU, we would need native ARM64 runners (which are more expensive and less available).
# Note: QEMU is only used during the IMAGE BUILD, not at runtime - the final images are native.
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
# Docker Buildx is required for multi-platform builds and creating manifest lists.
# It provides:
# 1. The ability to build for multiple architectures in a single command
# 2. The 'docker buildx imagetools' command for creating multi-arch manifests
# 3. Better caching and build performance compared to legacy docker build
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: devolutionsbot
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
# Multi-arch build strategy:
# 1. Build separate images for each architecture with arch-specific tags
# 2. Push each image to the registry
# 3. Create a multi-arch manifest that references both images
#
# When users pull the image without specifying architecture, Docker automatically
# selects the correct variant based on their platform. This works because:
# - Each image is tagged with the architecture (e.g., :2025.3.3-amd64)
# - The manifest list (:2025.3.3) contains references to both arch-specific images
# - Docker client inspects the manifest and pulls the matching architecture
#
# Why we use separate contexts instead of --platform linux/amd64,linux/arm64:
# - Each architecture needs different pre-compiled binaries and native libraries
# - Separate contexts allow us to use architecture-specific artifacts directly
# - More explicit and easier to debug than complex Dockerfile conditionals
- name: Build and push multi-arch container
id: build-container
run: |
Set-PSDebug -Trace 1
$Version = "${{ needs.preflight.outputs.version }}"
$ImageName = "devolutions/devolutions-gateway"
$Amd64Context = "${{ steps.prepare-artifacts-amd64.outputs.package-path-amd64 }}"
$Arm64Context = "${{ steps.prepare-artifacts-arm64.outputs.package-path-arm64 }}"
$DryRun = [System.Convert]::ToBoolean('${{ inputs.dry-run }}')
# Build and push amd64 image
Write-Host "Building amd64 image..."
if (-Not $DryRun) {
docker buildx build --platform linux/amd64 `
--tag "${ImageName}:${Version}-amd64" `
--push `
$Amd64Context
} else {
docker buildx build --platform linux/amd64 `
--tag "${ImageName}:${Version}-amd64" `
$Amd64Context
}
# Build and push arm64 image (cross-compiled on x86_64 runner using QEMU)
Write-Host "Building arm64 image..."
if (-Not $DryRun) {
docker buildx build --platform linux/arm64 `
--tag "${ImageName}:${Version}-arm64" `
--push `
$Arm64Context
} else {
docker buildx build --platform linux/arm64 `
--tag "${ImageName}:${Version}-arm64" `
$Arm64Context
}
if (-Not $DryRun) {
# Create multi-arch manifests that reference both architecture-specific images.
# This enables Docker to automatically select the correct image based on the user's platform.
Write-Host "Creating multi-arch manifest for version ${Version}..."
docker buildx imagetools create `
--tag "${ImageName}:${Version}" `
"${ImageName}:${Version}-amd64" `
"${ImageName}:${Version}-arm64"
Write-Host "Creating multi-arch manifest for latest..."
docker buildx imagetools create `
--tag "${ImageName}:latest" `
"${ImageName}:${Version}-amd64" `
"${ImageName}:${Version}-arm64"
} else {
Write-Host "Dry run: skipping manifest creation and push"
}
echo "image-name=${ImageName}:${Version}" >> $Env:GITHUB_OUTPUT
echo "latest-image-name=${ImageName}:latest" >> $Env:GITHUB_OUTPUT
shell: pwsh
github-release:
name: GitHub release
environment: publish-prod
if: ${{ needs.preflight.outputs.skip-publishing == 'false' || inputs.dry-run }}
needs: [preflight]
runs-on: ubuntu-latest
steps:
- name: Configure runner
run: cargo install parse-changelog
- name: Download artifacts
run: |
gh run download ${{ needs.preflight.outputs.run }} -n jetsocat-signed -n devolutions-gateway-signed -n devolutions-agent-signed -n webapp-client -n changelog --repo $Env:GITHUB_REPOSITORY
Move-Item -Path jetsocat-signed -Destination jetsocat
Move-Item -Path devolutions-gateway-signed -Destination devolutions-gateway
Move-Item -Path devolutions-agent-signed -Destination devolutions-agent
shell: pwsh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Manage artifacts
run: |
# Devolutions Agent on Linux does not have any useful feature yet, so we filter out the Linux artifacts.
Remove-Item -Path (Join-Path devolutions-agent linux) -Recurse
# Do not upload tun2socks.exe by itself.
Remove-Item -Path (Join-Path devolutions-agent tun2socks) -Recurse
# For the PowerShell module, only upload the nupkg.
Remove-Item -Path (Join-Path devolutions-gateway PowerShell DevolutionsGateway-ps-*.tar)
shell: pwsh
- name: Create jetsocat ZIP files for winget
run: |
Set-PSDebug -Trace 1
$Version = "${{ needs.preflight.outputs.version }}"
$ZipFolder = "jetsocat-zips"
New-Item -ItemType Directory -Path $ZipFolder -Force
# Define the platforms and architectures.
$Platforms = @(
@{ OS = "windows"; Arch = "x86_64"; Extension = ".exe" },
@{ OS = "windows"; Arch = "arm64"; Extension = ".exe" },
@{ OS = "linux"; Arch = "x86_64"; Extension = "" },
@{ OS = "linux"; Arch = "arm64"; Extension = "" },
@{ OS = "macos"; Arch = "x86_64"; Extension = "" },
@{ OS = "macos"; Arch = "arm64"; Extension = "" }
)
foreach ($Platform in $Platforms) {
$OS = $Platform.OS
$Arch = $Platform.Arch
$Ext = $Platform.Extension
# Find the original binary.
$BinaryPattern = "jetsocat_*_${Version}_${Arch}${Ext}"
$OriginalBinary = Get-ChildItem -Recurse -Filter $BinaryPattern -File | Select-Object -First 1
if ($OriginalBinary) {
# Create temporary folder for this zip.
$TempFolder = Join-Path $ZipFolder "temp-$OS-$Arch"
New-Item -ItemType Directory -Path $TempFolder -Force
# Copy binary with standard name.
$TargetName = "jetsocat${Ext}"
$TargetPath = Join-Path $TempFolder $TargetName
Copy-Item -Path $OriginalBinary.FullName -Destination $TargetPath
# Create ZIP file.
$ZipName = "jetsocat-$OS-$Arch.zip"
$ZipPath = Join-Path $ZipFolder $ZipName
Compress-Archive -Path $TargetPath -DestinationPath $ZipPath -Force
Write-Host "Created $ZipName"
# Clean up temp folder.
Remove-Item -Path $TempFolder -Recurse -Force
# Remove the original binary to avoid uploading it.
Remove-Item -Path $OriginalBinary.FullName
} else {
Write-Warning "Could not find binary for $OS $Arch"
}
}
shell: pwsh
- name: Create GitHub release
run: |
Set-PSDebug -Trace 1
$Version = "${{ needs.preflight.outputs.version }}"
$HashPath = 'checksums'
$Files = Get-ChildItem -Recurse -File -Exclude 'CHANGELOG.md', '*.dll' | % { Get-FileHash -Algorithm SHA256 $_.FullName }
$Files | % { "$($_.Hash) $(Split-Path $_.Path -leaf)" } | Out-File -FilePath $HashPath -Append -Encoding ASCII
echo "::group::checksums"
Get-Content $HashPath
echo "::endgroup::"
$ChangesPath = 'changes'
parse-changelog $(Join-Path changelog CHANGELOG.md) $Version | Out-File -Encoding UTF8NoBOM $ChangesPath
echo "::group::changes"
Get-Content $ChangesPath
echo "::endgroup::"
$GhCmd = $(@('gh', 'release', 'create', "v$Version", "--repo", $Env:GITHUB_REPOSITORY, "--notes-file", $ChangesPath, $HashPath) + $Files.Path) -Join ' '
Write-Host $GhCmd
$DryRun = [System.Convert]::ToBoolean('${{ inputs.dry-run }}')
if (-Not $DryRun) {
Invoke-Expression $GhCmd
}
shell: pwsh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
psgallery-release:
name: PowerShell release
environment: publish-prod
if: ${{ needs.preflight.outputs.skip-publishing == 'false' || inputs.dry-run }}
needs: [preflight]
runs-on: ubuntu-latest
steps:
- name: Download artifacts
run: gh run download ${{ needs.preflight.outputs.run }} -n devolutions-gateway-signed --repo $Env:GITHUB_REPOSITORY
shell: pwsh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
## workflow_call: The same artifacts persist across the entire run, so the PowerShell/DevolutionsGateway directory will still exist from the CI workflow
- name: Manage artifacts
run: Remove-Item -Path (Join-Path PowerShell DevolutionsGateway) -Recurse -ErrorAction Ignore
shell: pwsh
- name: Install PSResourceGet
run: |
Install-PSResource Microsoft.PowerShell.PSResourceGet -Scope CurrentUser -TrustRepository
shell: pwsh
- name: Publish PowerShell module
run: |
$Archive = Get-ChildItem -Recurse -Filter "*-ps-*.tar" -File
Write-Host "Archive = $Archive"
tar -xvf "$Archive" -C './PowerShell'
Get-ChildItem -Path "./PowerShell" -Recurse
$PublishCmd = @('Publish-PSResource', '-Repository', 'PSGallery', '-Path', (Join-Path PowerShell DevolutionsGateway), '-ApiKey', '${{ secrets.PS_GALLERY_NUGET_API_KEY }}')
$DryRun = [System.Convert]::ToBoolean('${{ inputs.dry-run }}')
if ($DryRun) {
$PublishCmd += '-WhatIf'
}
$PublishCmd = $PublishCmd -Join ' '
Write-Host "PublishCmd = $PublishCmd"
try {
Invoke-Expression $PublishCmd
} catch {
if ($_.Exception.Message -ilike "*cannot be published as the current version*is already available in the repository*") {
echo "::warning::PowerShell module not published; this version is already listed on PSGallery"
} else {
Write-Error $_
exit 1
}
}
shell: pwsh
onedrive-gateway:
name: OneDrive (Devolutions Gateway)
environment: onedrive-upload # for OneDrive secrets
if: ${{ needs.preflight.outputs.skip-publishing == 'false' || inputs.dry-run }}
needs: [preflight]
runs-on: ubuntu-latest
steps:
- name: Check out Devolutions/actions
uses: actions/checkout@v4
with:
repository: Devolutions/actions
ref: v1
token: ${{ secrets.DEVOLUTIONSBOT_TOKEN }}
path: ./.github/workflows
## Devolutions Toolbox is required for OneDrive uploading
- name: Install Devolutions Toolbox
uses: ./.github/workflows/toolbox-install
with:
github_token: ${{ secrets.DEVOLUTIONSBOT_TOKEN }}
- name: Download artifacts
run: gh run download ${{ needs.preflight.outputs.run }} -n devolutions-gateway-signed --repo $Env:GITHUB_REPOSITORY
shell: pwsh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare upload
id: prepare
run: |
Set-PSDebug -Trace 1
$destinationFolder = "${{ runner.temp }}/artifacts"
$version="${{ needs.preflight.outputs.version }}"
# Note that ".0" is appended here (required by release tooling downstream)
$versionFull="$version.0"
echo "version=${versionFull}" >> $Env:GITHUB_OUTPUT
echo "files-to-upload=$destinationFolder" >> $Env:GITHUB_OUTPUT
New-Item -Path "$destinationFolder" -ItemType "directory"
Move-Item -Path "./windows/x86_64/DevolutionsGateway-x86_64-${version}.msi" -Destination "$destinationFolder/DevolutionsGateway-x86_64-${versionFull}.msi"
Move-Item -Path "./windows/x86_64/DevolutionsGateway_Windows_${version}_x86_64.pdb" -Destination "$destinationFolder/DevolutionsGateway-x86_64-${versionFull}.pdb"
Move-Item -Path "./linux/x86_64/devolutions-gateway_${version}-1_amd64.deb" -Destination "$destinationFolder/devolutions-gateway_${versionFull}_amd64.deb"
Move-Item -Path "./linux/x86_64/devolutions-gateway_${version}-1_x86_64.rpm" -Destination "$destinationFolder/devolutions-gateway_${versionFull}_x86_64.rpm"
shell: pwsh
- name: Upload to OneDrive
uses: ./.github/workflows/onedrive-upload
if: ${{ needs.preflight.outputs.skip-publishing == 'false' && !inputs.dry-run }}
with:
azure_client_id: ${{ secrets.ONEDRIVE_AUTOMATION_CLIENT_ID }}
azure_client_secret: ${{ secrets.ONEDRIVE_AUTOMATION_CLIENT_SECRET }}
conflict_behavior: fail
destination_path: /Gateway/${{ steps.prepare.outputs.version }}
remote: releases
source_path: ${{ steps.prepare.outputs.files-to-upload }}
onedrive-agent:
name: OneDrive (Devolutions Agent)
environment: onedrive-upload # for OneDrive secrets
if: ${{ needs.preflight.outputs.skip-publishing == 'false' || inputs.dry-run }}
needs: [preflight]
runs-on: ubuntu-latest
steps:
- name: Check out Devolutions/actions
uses: actions/checkout@v4
with:
repository: Devolutions/actions
ref: v1
token: ${{ secrets.DEVOLUTIONSBOT_TOKEN }}
path: ./.github/workflows
## Devolutions Toolbox is required for OneDrive uploading
- name: Install Devolutions Toolbox
uses: ./.github/workflows/toolbox-install
with:
github_token: ${{ secrets.DEVOLUTIONSBOT_TOKEN }}
- name: Download artifacts
run: gh run download ${{ needs.preflight.outputs.run }} -n devolutions-agent-signed --repo $Env:GITHUB_REPOSITORY
shell: pwsh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare upload
id: prepare
run: |
Set-PSDebug -Trace 1
$destinationFolder = "${{ runner.temp }}/artifacts"
$version="${{ needs.preflight.outputs.version }}"
# Note that ".0" is appended here (required by release tooling downstream)
$versionFull="$version.0"
echo "version=${versionFull}" >> $Env:GITHUB_OUTPUT
echo "files-to-upload=$destinationFolder" >> $Env:GITHUB_OUTPUT
New-Item -Path "$destinationFolder" -ItemType "directory"
Move-Item -Path "./windows/x86_64/DevolutionsAgent-x86_64-${version}.msi" -Destination "$destinationFolder/DevolutionsAgent-x86_64-${versionFull}.msi"
Move-Item -Path "./windows/x86_64/DevolutionsAgent-x86_64-${version}.symbols.zip" -Destination "$destinationFolder/DevolutionsAgent-x86_64-${versionFull}.symbols.zip"
Move-Item -Path "./linux/x86_64/devolutions-agent_${version}-1_amd64.deb" -Destination "$destinationFolder/devolutions-agent_${versionFull}_amd64.deb"
Move-Item -Path "./linux/x86_64/devolutions-agent_${version}-1_x86_64.rpm" -Destination "$destinationFolder/devolutions-agent_${versionFull}_x86_64.rpm"
shell: pwsh
- name: Upload to OneDrive
uses: ./.github/workflows/onedrive-upload
if: ${{ needs.preflight.outputs.skip-publishing == 'false' && !inputs.dry-run }}
with:
azure_client_id: ${{ secrets.ONEDRIVE_AUTOMATION_CLIENT_ID }}
azure_client_secret: ${{ secrets.ONEDRIVE_AUTOMATION_CLIENT_SECRET }}
conflict_behavior: fail
destination_path: /Agent/${{ steps.prepare.outputs.version }}
remote: releases
source_path: ${{ steps.prepare.outputs.files-to-upload }}
jetsocat-publish:
name: Jetsocat NuGet publish
environment: publish-prod
if: ${{ needs.preflight.outputs.skip-publishing == 'false' || inputs.dry-run }}
needs: [preflight]
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- name: Download jetsocat-nuget artifact
run: gh run download ${{ needs.preflight.outputs.run }} -n jetsocat-nuget --repo $Env:GITHUB_REPOSITORY
shell: pwsh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: NuGet login (OIDC)
id: nuget-login
uses: NuGet/login@v1
with:
user: ${{ secrets.NUGET_BOT_USERNAME }}
- name: Publish Jetsocat NuGet package
run: |
Set-PSDebug -Trace 1
$Package = Get-ChildItem -Recurse -Filter "Devolutions.Jetsocat.*.nupkg" -File | Select-Object -First 1
Write-Host "Package = $Package"
$PushCmd = @(
'dotnet',
'nuget',
'push',
"$($Package.FullName)",
'--api-key',
'${{ steps.nuget-login.outputs.NUGET_API_KEY }}',
'--source',
'https://api.nuget.org/v3/index.json',
'--skip-duplicate'
)
$PushCmd = $PushCmd -Join ' '
Write-Host $PushCmd
$DryRun = [System.Convert]::ToBoolean('${{ inputs.dry-run }}')
if (-Not $DryRun) {
try {
Invoke-Expression $PushCmd
} catch {
if ($_.Exception.Message -ilike "*package already exists*" -Or $_.Exception.Message -ilike "*already has a package*") {
echo "::warning::Jetsocat NuGet package not published; this version is already listed on NuGet.org"
} else {
Write-Error $_
exit 1
}
}
}
shell: pwsh
remove-labels:
name: Remove release-required labels
if: ${{ needs.preflight.outputs.skip-publishing == 'false' && !inputs.dry-run }}
needs: [preflight, container, github-release, psgallery-release, onedrive-gateway, onedrive-agent, jetsocat-publish]
runs-on: ubuntu-latest
steps:
- name: Check out ${{ github.repository }}
uses: actions/checkout@v4
- name: Remove labels
run: ./ci/remove-labels.ps1 -Label 'release-required'
shell: pwsh
env:
GITHUB_TOKEN: ${{ github.token }}
upload-sbom:
name: Upload SBOM
environment: sbom
if: ${{ needs.preflight.outputs.skip-publishing == 'false' && !inputs.dry-run }}
needs: [preflight]
runs-on: ubuntu-latest
steps:
- name: Check out Devolutions/actions
uses: actions/checkout@v4
with:
repository: Devolutions/actions
ref: v1
token: ${{ secrets.DEVOLUTIONSBOT_TOKEN }}
path: ./.github/workflows
## Devolutions Toolbox is required for OneDrive uploading
- name: Install Devolutions Toolbox
uses: ./.github/workflows/toolbox-install
with:
github_token: ${{ secrets.DEVOLUTIONSBOT_TOKEN }}
- name: Download SBOM artifact
run: gh run download ${{ needs.preflight.outputs.run }} -n sbom --repo $GITHUB_REPOSITORY
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload SBOM to OneDrive Releases
uses: ./.github/workflows/onedrive-upload
with:
azure_client_id: ${{ secrets.ONEDRIVE_AUTOMATION_CLIENT_ID }}
azure_client_secret: ${{ secrets.ONEDRIVE_AUTOMATION_CLIENT_SECRET }}
conflict_behavior: replace
# Append ".0" to match the 4-part version format in OneDrive.
destination_path: /Gateway/${{ needs.preflight.outputs.version }}.0
remote: releases
source_path: bom.json
- name: Upload SBOM to Dependency-Track
uses: ./.github/workflows/dtrack-upload-sbom
with:
api_key: ${{ secrets.DTRACK_AUTOMATION_API_KEY }}
autocreate: 'true'
bom_filename: bom.json
project_name: devolutions-gateway
project_version: ${{ needs.preflight.outputs.version }}
server_hostname: 'dtrack-api.devolutions.com'