Prepare QSfera production release

This commit is contained in:
Курнат Андрей
2026-06-08 19:57:40 +03:00
parent 2315f25754
commit 43caef7a6a
27 changed files with 1159 additions and 42 deletions
+16
View File
@@ -57,6 +57,8 @@ jobs:
CRAFT_TARGET: ${{ matrix.target }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CRAFT_PACKAGE_SYMBOLS: ${{ github.event_name != 'pull_request' }}
SIGN_PACKAGE: ${{ secrets.QSFERA_DESKTOP_SIGN_PACKAGE }}
CRAFT_CODESIGN_CERTIFICATE: ${{ secrets.QSFERA_DESKTOP_CODESIGN_CERTIFICATE }}
container: ${{ matrix.container }}
@@ -188,11 +190,25 @@ jobs:
- name: Package
if: matrix.target != 'macos-clang-arm64'
run: |
$requireSigning = "${{ matrix.os }}" -eq "windows-latest" -and "${{ github.ref_type }}" -eq "tag" -and "${{ inputs.releaseChannel }}" -ne "beta"
if ("${{ matrix.os }}" -eq "windows-latest") {
$validationArgs = @()
if ($requireSigning) {
$validationArgs += "-RequireSigning"
}
& "${env:GITHUB_WORKSPACE}/scripts/validate-production-release.ps1" @validationArgs
}
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --no-cache --package opencloud/opencloud-desktop
- name: Package Appx
if: ${{ matrix.os == 'windows-latest' && github.event_name != 'pull_request' }}
run: |
$requireSigning = "${{ github.ref_type }}" -eq "tag" -and "${{ inputs.releaseChannel }}" -ne "beta"
$validationArgs = @()
if ($requireSigning) {
$validationArgs += "-RequireSigning"
}
& "${env:GITHUB_WORKSPACE}/scripts/validate-production-release.ps1" @validationArgs
& "${env:GITHUB_WORKSPACE}/.github/workflows/.craft.ps1" -c --no-cache --package --options "[Packager]PackageType=AppxPackager" --options "[Packager]Destination=${{ github.workspace }}/appx/" opencloud/opencloud-desktop
- name: Prepare artifacts
@@ -0,0 +1,60 @@
param(
[switch]$RequireSigning,
[string]$Root = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
)
$ErrorActionPreference = "Stop"
function Fail($Message) {
Write-Error $Message
exit 1
}
function Read-Text($RelativePath) {
Get-Content -LiteralPath (Join-Path $Root $RelativePath) -Raw -Encoding UTF8
}
$branding = Read-Text "QSFERA.cmake"
$cmake = Read-Text "CMakeLists.txt"
$craft = Read-Text ".craft.ini"
$expectedAppName = -join ([char[]](0x041a, 0x0443, 0x0421, 0x0444, 0x0435, 0x0440, 0x0430))
if (-not $branding.Contains("APPLICATION_NAME") -or -not $branding.Contains($expectedAppName)) {
Fail "Desktop branding must use the production Cyrillic application name."
}
if ($branding -notmatch 'APPLICATION_EXECUTABLE\s+"qsfera"') {
Fail "Desktop executable must remain `"qsfera`" for the production profile."
}
if ($branding -notmatch 'APPLICATION_REV_DOMAIN\s+"eu\.qsfera\.desktop"') {
Fail "Desktop reverse-domain id must remain eu.qsfera.desktop for the production profile."
}
if ($branding -notmatch 'APPLICATION_DEFAULT_SERVER_URL\s+"https://qsfera\.kusoft\.xyz"') {
Fail "Desktop default server URL must be https://qsfera.kusoft.xyz."
}
if ($cmake -notmatch 'option\(WITH_UPDATE_NOTIFICATION\s+"Whether to check for new releases"\s+ON\)') {
Fail "Desktop release builds must keep update notifications enabled by default."
}
if ($cmake -notmatch 'VIRTUAL_FILE_SYSTEM_PLUGINS\s+off\s+cfapi\s+openvfs') {
Fail "Desktop release builds must include the Windows CfAPI VFS plugin."
}
if ($craft -notmatch 'CodeSigning/Enabled\s*=\s*\$\{Env:SIGN_PACKAGE\}') {
Fail "Craft code-signing must be controlled by SIGN_PACKAGE."
}
if ($RequireSigning) {
if ($env:SIGN_PACKAGE -notin @("True", "true", "1", "yes", "YES")) {
Fail "Production Windows tag releases require SIGN_PACKAGE=True."
}
if ([string]::IsNullOrWhiteSpace($env:CRAFT_CODESIGN_CERTIFICATE)) {
Fail "Production Windows tag releases require CRAFT_CODESIGN_CERTIFICATE."
}
}
Write-Host "QSfera Desktop production release validation passed."
+1 -1
View File
@@ -331,7 +331,7 @@ void ConfigFile::setSkipUpdateCheck(bool skip)
QString ConfigFile::updateChannel() const
{
auto settings = makeQSettings();
return settings.value(updateChannelC(), OCC::Version::isBeta() ? u"stable"_s : u"beta"_s).toString();
return settings.value(updateChannelC(), OCC::Version::isBeta() ? u"beta"_s : u"stable"_s).toString();
}
void ConfigFile::setUpdateChannel(const QString &channel)
+1
View File
@@ -13,6 +13,7 @@ qsfera_add_test(ConcatUrl)
qsfera_add_test(XmlParse)
qsfera_add_test(ChecksumValidator)
qsfera_add_test(ConnectionValidator)
qsfera_add_test(ConfigFile)
# TODO: we need keychain access for this test
+52
View File
@@ -0,0 +1,52 @@
/*
* Copyright (C) QSfera
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include "configfile.h"
#include "common/version.h"
#include <QFile>
#include <QTemporaryDir>
#include <QtTest>
using namespace OCC;
using namespace Qt::Literals::StringLiterals;
class TestConfigFile : public QObject
{
Q_OBJECT
private Q_SLOTS:
void init()
{
QVERIFY(_configDir.isValid());
QVERIFY(ConfigFile::setConfDir(_configDir.path()));
QFile::remove(ConfigFile::configFile());
}
void testDefaultUpdateChannelMatchesBuildChannel()
{
const auto expectedChannel = Version::isBeta() ? u"beta"_s : u"stable"_s;
QCOMPARE(ConfigFile().updateChannel(), expectedChannel);
}
void testStoredUpdateChannelOverridesBuildDefault()
{
ConfigFile().setUpdateChannel(u"beta"_s);
QCOMPARE(ConfigFile().updateChannel(), u"beta"_s);
ConfigFile().setUpdateChannel(u"stable"_s);
QCOMPARE(ConfigFile().updateChannel(), u"stable"_s);
}
private:
QTemporaryDir _configDir;
};
QTEST_MAIN(TestConfigFile)
#include "testconfigfile.moc"