Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to Velopack #171

Merged
merged 41 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
e9c11a0
initial implementation
smallketchup82 Jun 26, 2024
01ca7c4
Commit whatever I already have so that I can make the PR
smallketchup82 Jun 28, 2024
243bb7d
Get things stable
smallketchup82 Jun 30, 2024
b4f265d
Overhaul
smallketchup82 Jun 30, 2024
1453813
Run jetbrains formatter
smallketchup82 Jun 30, 2024
4549aa4
Remove keep deltas variable
smallketchup82 Jun 30, 2024
402bd4e
Bug fixes
smallketchup82 Jul 4, 2024
ba4ffef
Fix a silly path issue
smallketchup82 Aug 7, 2024
1555f2d
Bump velopack version
smallketchup82 Aug 7, 2024
5b86d4b
Apply auto refactoring
smoogipoo Aug 30, 2024
0e07b2c
Split into individual builders
smoogipoo Aug 30, 2024
a52a207
Use correct OS name for macOS
smoogipoo Aug 30, 2024
6a2cf44
Use custom app bundle
smoogipoo Aug 30, 2024
604916a
Restore tools before build
smoogipoo Aug 30, 2024
b377ef9
Always output stopwatch time
smoogipoo Aug 30, 2024
6d43dc2
Add signEntitlements
smoogipoo Aug 30, 2024
d67f460
Don't generate package for now
smoogipoo Aug 30, 2024
f3d2c88
Fully specify option names
smoogipoo Aug 30, 2024
acfae8d
Add keychain option
smoogipoo Aug 30, 2024
e3e7b1b
Merge pull request #1 from smoogipoo/builder-refactor
smallketchup82 Aug 31, 2024
b0a10d7
Merge branch 'velopack' into restore-tools
smallketchup82 Aug 31, 2024
a675d6a
Merge pull request #3 from smoogipoo/restore-tools
smallketchup82 Aug 31, 2024
2a9c7e9
Merge branch 'velopack' into always-time
smallketchup82 Aug 31, 2024
6f38914
Merge pull request #4 from smoogipoo/always-time
smallketchup82 Aug 31, 2024
d648894
Merge branch 'velopack' into fix-macos-build
smallketchup82 Aug 31, 2024
20eaae4
Merge pull request #2 from smoogipoo/fix-macos-build
smallketchup82 Aug 31, 2024
51e161f
Don't generate portable bundle on windows
smoogipoo Aug 31, 2024
82fce38
Merge pull request #5 from smoogipoo/no-portable-win
smallketchup82 Aug 31, 2024
5cef162
Rename assets to match existing releases
smoogipoo Aug 31, 2024
79494ab
Don't publish ios/android builds if requested not to
smoogipoo Aug 31, 2024
fab6a45
Fix windows exe name
smoogipoo Aug 31, 2024
7096183
Add `--packTitle` to pack command
smoogipoo Aug 31, 2024
8256034
Merge pull request #7 from smoogipoo/conditional-upload-ios-android
smallketchup82 Aug 31, 2024
2cd4e0a
Merge pull request #8 from smoogipoo/add-pack-title
smallketchup82 Aug 31, 2024
2076306
Merge pull request #6 from smoogipoo/rename-assets
smallketchup82 Aug 31, 2024
6829172
Update Velopack package
smoogipoo Aug 31, 2024
c1bebab
Fix Windows installer icon
smoogipoo Aug 31, 2024
4e7b398
Merge pull request #9 from smoogipoo/fix-windows-setup-icon
smallketchup82 Aug 31, 2024
c4092ca
Restore tools in correct directory
smoogipoo Sep 1, 2024
ae39a9c
Add back removed line + refactoring
smoogipoo Sep 1, 2024
16ad94b
Add missing dictionary and abbreviation entries
peppy Sep 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"vpk": {
"version": "0.0.598-g933b2ab",
"commands": [
"vpk"
]
}
}
}
47 changes: 47 additions & 0 deletions Builders/AndroidBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System.IO;
using osu.Desktop.Deploy.Uploaders;

namespace osu.Desktop.Deploy.Builders
{
public class AndroidBuilder : Builder
{
private readonly string? codeSigningPassword;

public AndroidBuilder(string version, string? codeSigningPassword)
: base(version)
{
if (!string.IsNullOrEmpty(Program.AndroidCodeSigningCertPath))
this.codeSigningPassword = codeSigningPassword ?? Program.ReadLineMasked("Enter code signing password: ");
}

protected override string TargetFramework => "net8.0-android";
protected override string RuntimeIdentifier => "android-arm64";

public override Uploader CreateUploader() => new GitHubUploader();

public override void Build()
{
string codeSigningArguments = string.Empty;

if (!string.IsNullOrEmpty(Program.AndroidCodeSigningCertPath))
{
codeSigningArguments +=
$" -p:AndroidKeyStore=true"
+ $" -p:AndroidSigningKeyStore={Program.AndroidCodeSigningCertPath}"
+ $" -p:AndroidSigningKeyAlias={Path.GetFileNameWithoutExtension(Program.AndroidCodeSigningCertPath)}"
+ $" -p:AndroidSigningKeyPass={codeSigningPassword}"
+ $" -p:AndroidSigningKeyStorePass={codeSigningPassword}";
}

string[] versionParts = Version.Split('.');
string versionCode = versionParts[0].PadLeft(4, '0') + versionParts[1].PadLeft(4, '0') + versionParts[2].PadLeft(1, '0');

RunDotnetPublish($"-p:ApplicationVersion={versionCode} {codeSigningArguments}");

File.Move(Path.Combine(Program.StagingPath, "sh.ppy.osulazer-Signed.apk"), Path.Combine(Program.ReleasesPath, "sh.ppy.osulazer.apk"), true);
}
}
}
53 changes: 53 additions & 0 deletions Builders/Builder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System.IO;
using osu.Desktop.Deploy.Uploaders;

namespace osu.Desktop.Deploy.Builders
{
public abstract class Builder
{
protected abstract string TargetFramework { get; }
protected abstract string RuntimeIdentifier { get; }

protected string SplashImagePath => Path.Combine(Program.SolutionPath, "assets", "lazer-nuget.png");
protected string IconPath => Path.Combine(Program.SolutionPath, Program.ProjectName, Program.IconName);

protected readonly string Version;

protected Builder(string version)
{
Version = version;

refreshDirectory(Program.STAGING_FOLDER);
}

public abstract Uploader CreateUploader();

public abstract void Build();

protected void RunDotnetPublish(string? extraArgs = null, string? outputDir = null)
{
extraArgs ??= string.Empty;
outputDir ??= Program.StagingPath;

Program.RunCommand("dotnet", $"publish"
+ $" -f {TargetFramework}"
+ $" -r {RuntimeIdentifier}"
+ $" -c Release"
+ $" -o \"{outputDir}\""
+ $" -p:Version={Version}"
+ $" --self-contained"
+ $" {extraArgs}"
+ $" {Program.ProjectName}");
}

private static void refreshDirectory(string directory)
{
if (Directory.Exists(directory))
Directory.Delete(directory, true);
Directory.CreateDirectory(directory);
}
}
}
28 changes: 28 additions & 0 deletions Builders/IOSBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System.IO;
using osu.Desktop.Deploy.Uploaders;

namespace osu.Desktop.Deploy.Builders
{
public class IOSBuilder : Builder
{
public IOSBuilder(string version)
: base(version)
{
}

protected override string TargetFramework => "net8.0-ios";
protected override string RuntimeIdentifier => "ios-arm64";

public override Uploader CreateUploader() => new GitHubUploader();

public override void Build()
{
RunDotnetPublish("-p:ApplicationDisplayVersion=1.0");

File.Move(Path.Combine(Program.StagingPath, "osu.iOS.app"), Path.Combine(Program.ReleasesPath, "osu.iOS.app"), true);
}
}
}
44 changes: 44 additions & 0 deletions Builders/LinuxBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System.IO;
using osu.Desktop.Deploy.Uploaders;

namespace osu.Desktop.Deploy.Builders
{
public class LinuxBuilder : Builder
{
private const string app_dir = "osu!.AppDir";
private const string app_name = "osu!";
private const string os_name = "linux";

private readonly string stagingTarget;
private readonly string publishTarget;

public LinuxBuilder(string version)
: base(version)
{
stagingTarget = Path.Combine(Program.StagingPath, app_dir);
publishTarget = Path.Combine(stagingTarget, "usr", "bin");
}

protected override string TargetFramework => "net8.0";
protected override string RuntimeIdentifier => $"{os_name}-x64";

public override Uploader CreateUploader() => new LinuxVelopackUploader(app_name, os_name, RuntimeIdentifier, RuntimeIdentifier, stagingPath: stagingTarget);

public override void Build()
{
if (Directory.Exists(stagingTarget))
Directory.Delete(stagingTarget, true);
Directory.CreateDirectory(stagingTarget);

foreach (var file in Directory.GetFiles(Path.Combine(Program.TemplatesPath, app_dir)))
new FileInfo(file).CopyTo(Path.Combine(stagingTarget, Path.GetFileName(file)));

Program.RunCommand("chmod", $"+x {stagingTarget}/AppRun");

RunDotnetPublish(outputDir: publishTarget);
}
}
}
70 changes: 70 additions & 0 deletions Builders/MacOSBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using System.IO;
using osu.Desktop.Deploy.Uploaders;

namespace osu.Desktop.Deploy.Builders
{
public class MacOSBuilder : Builder
{
private const string app_dir = "osu!.app";
private const string app_name = "osu!";
private const string os_name = "osx";

private readonly string stagingTarget;
private readonly string publishTarget;

public MacOSBuilder(string version, string? arch)
: base(version)
{
if (string.IsNullOrEmpty(arch))
{
Console.Write("Build for which architecture? [x64/arm64]: ");
arch = Console.ReadLine() ?? string.Empty;
}

if (arch != "x64" && arch != "arm64")
Logger.Error($"Invalid Architecture: {arch}");

RuntimeIdentifier = $"{os_name}-{arch}";

stagingTarget = Path.Combine(Program.StagingPath, app_dir);
publishTarget = Path.Combine(stagingTarget, "Contents", "MacOS");
}

protected override string TargetFramework => "net8.0";
protected override string RuntimeIdentifier { get; }

public override Uploader CreateUploader()
{
string extraArgs = $" --signEntitlements=\"{Path.Combine(Environment.CurrentDirectory, "osu.entitlements")}\""
+ $" --noInst";

if (!string.IsNullOrEmpty(Program.AppleCodeSignCertName))
extraArgs += $" --signAppIdentity=\"{Program.AppleCodeSignCertName}\"";
if (!string.IsNullOrEmpty(Program.AppleInstallSignCertName))
extraArgs += $" --signInstallIdentity=\"{Program.AppleInstallSignCertName}\"";
if (!string.IsNullOrEmpty(Program.AppleNotaryProfileName))
extraArgs += $" --notaryProfile=\"{Program.AppleNotaryProfileName}\"";
if (!string.IsNullOrEmpty(Program.AppleKeyChainPath))
extraArgs += $" --keychain=\"{Program.AppleKeyChainPath}\"";

return new MacOSVelopackUploader(app_name, os_name, RuntimeIdentifier, RuntimeIdentifier, extraArgs: extraArgs, stagingPath: stagingTarget);
}

public override void Build()
{
if (Directory.Exists(stagingTarget))
Directory.Delete(stagingTarget, true);

Program.RunCommand("cp", $"-r \"{Path.Combine(Program.TemplatesPath, app_dir)}\" \"{stagingTarget}\"");

RunDotnetPublish(outputDir: publishTarget);

// without touching the app bundle itself, changes to file associations / icons / etc. will be cached at a macOS level and not updated.
Program.RunCommand("touch", $"\"{stagingTarget}\" {Program.StagingPath}", false);
}
}
}
65 changes: 65 additions & 0 deletions Builders/WindowsBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using System.IO;
using osu.Desktop.Deploy.Uploaders;

namespace osu.Desktop.Deploy.Builders
{
public class WindowsBuilder : Builder
{
private const string app_name = "osu!.exe";
private const string os_name = "win";
private const string channel = "win";

private readonly string? codeSigningPassword;

public WindowsBuilder(string version, string? codeSigningPassword)
: base(version)
{
if (!string.IsNullOrEmpty(Program.WindowsCodeSigningCertPath))
this.codeSigningPassword = codeSigningPassword ?? Program.ReadLineMasked("Enter code signing password: ");
}

protected override string TargetFramework => "net8.0";
protected override string RuntimeIdentifier => $"{os_name}-x64";

public override Uploader CreateUploader()
{
string installIcon = Path.Combine(Environment.CurrentDirectory, "install.ico");
string extraArgs = $" --splashImage=\"{SplashImagePath}\""
+ $" --icon=\"{installIcon}\""
+ $" --noPortable";

if (!string.IsNullOrEmpty(Program.WindowsCodeSigningCertPath))
extraArgs += $" --signParams=\"/td sha256 /fd sha256 /f {Program.WindowsCodeSigningCertPath} /p {codeSigningPassword} /tr http://timestamp.comodoca.com\"";

return new WindowsVelopackUploader(app_name, os_name, RuntimeIdentifier, channel, extraArgs: extraArgs);
}

public override void Build()
{
RunDotnetPublish();

bool rcEditCommand =
Program.RunCommand("tools/rcedit-x64.exe", $"\"{Path.Combine(Program.StagingPath, "osu!.exe")}\""
+ $" --set-icon \"{IconPath}\"",
exitOnFail: false);

if (!rcEditCommand)
{
// Retry again with wine
// TODO: Should probably change this to use RuntimeInfo.OS checks instead of fail values
bool wineRcEditCommand =
Program.RunCommand("wine", $"\"{Path.GetFullPath("tools/rcedit-x64.exe")}\""
+ $" \"{Path.Combine(Program.StagingPath, "osu!.exe")}\""
+ $" --set-icon \"{IconPath}\"",
exitOnFail: false);
Comment on lines +54 to +58
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this something specific to your operating environment @smoogipoo, or something github actions related? I know for a fact that I have wine installed nowhere.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is how it is in master, dating back to 2018 or so. I don't remember the reason why this exists in the first place, but It looks like .NET is handling the app icon fine via ApplicationIcon at least when compiled on Windows (which is what our runners do anyway). So... we can maybe remove this, but as I mentioned above I intended to keep the code familiar and not introduce too many changes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh okay. I checked and it looked like it didn't exist but I guess I missed it.

Copy link
Contributor

@smoogipoo smoogipoo Sep 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I'm going crazy. I definitely thought I saw it there but I can't find it, and it looks like it was added in this PR (the Wine part)...

I guess it's not a big issue either way? Though I still want to explore removing all of this altogether as a followup?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe @smallketchup82 can answer this then

Copy link
Contributor

@smoogipoo smoogipoo Sep 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documenting here for now because I was about to remove this... It appears that ApplicationIcon sets the icon correctly for the shortcut, taskbar, and alt-tab, but the window titlebar loses its icon.

Which is weird because we have SDL code to handle that... https://github.com/ppy/osu-framework/blob/e0e945672d41c395c1977d273220cb17f9d52e2a/osu.Framework/Platform/Windows/SDL2WindowsWindow.cs#L293

Needs more investigation.

Copy link
Contributor Author

@smallketchup82 smallketchup82 Sep 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe @smallketchup82 can answer this then

Yes I added this in. Meant to be a sort of "fallback" method when compiling for windows on a linux system. There's no equivalent unix binary for that tool (at least to my knowledge), so the best way to run it is via wine (if the user has it installed). If the user doesn't have wine installed, it'll fail gracefully and move on.

Seems to work perfectly, and removing it more or less breaks cross compilation (icon's don't get set). Best to keep it in so that the option of using it is available

Copy link

@caesay caesay Sep 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Velopack now has a cross-platform resource editor written in C#, as it needs to set icons on it's own Update.exe even when on Linux. I guess you could steal this and make your own small utility instead of using wine+rcedit. https://github.com/velopack/velopack/blob/develop/src/vpk/Velopack.Packaging.Windows/ResourceEdit.cs


if (!wineRcEditCommand)
Logger.Error("Failed to set icon on osu!.exe");
}
}
}
}
9 changes: 6 additions & 3 deletions GitHubObject.cs → GitHubAsset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@

namespace osu.Desktop.Deploy
{
public class GitHubObject
public class GitHubAsset
{
[JsonProperty(@"id")]
[JsonProperty("url")]
public string Url = string.Empty;

[JsonProperty("id")]
public int Id;

[JsonProperty(@"name")]
[JsonProperty("name")]
public string Name = string.Empty;
}
}
16 changes: 10 additions & 6 deletions GitHubRelease.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using Newtonsoft.Json;

namespace osu.Desktop.Deploy
{
public class GitHubRelease
{
[JsonProperty(@"id")]
[JsonProperty("id")]
public int Id;

[JsonProperty(@"tag_name")]
[JsonProperty("tag_name")]
public string TagName => $"{Name}";

[JsonProperty(@"name")]
[JsonProperty("name")]
public string Name = string.Empty;

[JsonProperty(@"draft")]
[JsonProperty("draft")]
public bool Draft;

[JsonProperty(@"prerelease")]
[JsonProperty("prerelease")]
public bool PreRelease;

[JsonProperty(@"upload_url")]
[JsonProperty("upload_url")]
public string UploadUrl = string.Empty;

[JsonProperty("assets")]
public GitHubAsset[] Assets = Array.Empty<GitHubAsset>();
}
}
Loading
Loading