Skip to content

Commit d8426ce

Browse files
authored
Fix: Updater fixes and improvements (#13)
1 parent 3c19ccd commit d8426ce

File tree

8 files changed

+159
-42
lines changed

8 files changed

+159
-42
lines changed

.github/workflows/build_v3.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ on:
1717
- "src/Whisparr.Api.*/openapi.json"
1818

1919
concurrency:
20-
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
20+
group: ${{ github.workflow }}-pr-${{ github.event.pull_request.number }}
2121
cancel-in-progress: true
2222

2323
env:
@@ -91,6 +91,8 @@ jobs:
9191
steps:
9292
- name: Check out
9393
uses: actions/checkout@v5
94+
with:
95+
fetch-depth: 0
9496

9597
- name: Build
9698
uses: ./.github/actions/build
@@ -106,6 +108,8 @@ jobs:
106108
steps:
107109
- name: Check out
108110
uses: actions/checkout@v5
111+
with:
112+
fetch-depth: 0
109113

110114
- name: Volta
111115
uses: volta-cli/action@v4
@@ -151,6 +155,8 @@ jobs:
151155
steps:
152156
- name: Check out
153157
uses: actions/checkout@v5
158+
with:
159+
fetch-depth: 0
154160

155161
- name: Test
156162
uses: ./.github/actions/test
@@ -170,6 +176,8 @@ jobs:
170176
steps:
171177
- name: Check out
172178
uses: actions/checkout@v5
179+
with:
180+
fetch-depth: 0
173181

174182
- name: Test
175183
uses: ./.github/actions/test
@@ -207,6 +215,8 @@ jobs:
207215
steps:
208216
- name: Check out
209217
uses: actions/checkout@v5
218+
with:
219+
fetch-depth: 0
210220
- name: Test
211221
uses: ./.github/actions/test
212222
with:

.github/workflows/deploy.yml

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ jobs:
6969
steps:
7070
- name: Check out
7171
uses: actions/checkout@v4
72+
with:
73+
fetch-depth: 0
74+
fetch-tags: true
7275

7376
- name: Download release artifacts
7477
uses: actions/download-artifact@v4
@@ -84,23 +87,7 @@ jobs:
8487
GITHUB_TOKEN: ${{ github.token }}
8588
with:
8689
latest: true
87-
prerelease: ${{ inputs.branch != 'main' }}
88-
89-
- name: Generate Release Notes
90-
id: generate-release-notes
91-
uses: actions/github-script@v7
92-
with:
93-
github-token: ${{ github.token }}
94-
result-encoding: string
95-
script: |
96-
const { data } = await github.rest.repos.generateReleaseNotes({
97-
owner: context.repo.owner,
98-
repo: context.repo.repo,
99-
tag_name: 'v${{ inputs.version }}',
100-
target_commitish: '${{ github.sha }}',
101-
previous_tag_name: '${{ steps.previous-release.outputs.tag_name }}',
102-
})
103-
return data.body
90+
prerelease: ${{ inputs.branch != 'eros' }}
10491

10592
- name: Enable GPG signing
10693
uses: crazy-max/ghaction-import-gpg@v6
@@ -118,13 +105,22 @@ jobs:
118105
env:
119106
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
120107

108+
- name: Generate Commit Changelog
109+
id: generate-commit-changelog
110+
run: |
111+
PREV_TAG="${{ steps.previous-release.outputs.tag_name }}"
112+
CUR_TAG="v${{ inputs.version }}"
113+
echo "## What's Changed" > changelog.md
114+
git log "$PREV_TAG..$CUR_TAG" --pretty=format:"- %s (%h) - @%an" >> changelog.md
115+
cat changelog.md
116+
121117
- name: Create release
122118
uses: ncipollo/release-action@v1
123119
with:
124120
artifacts: _artifacts/Whisparr.*
125121
commit: ${{ github.sha }}
126122
generateReleaseNotes: false
127-
body: ${{ steps.generate-release-notes.outputs.result }}
123+
bodyFile: changelog.md
128124
name: ${{ inputs.version }}
129125
prerelease: ${{ inputs.branch != 'eros' }}
130126
skipIfReleaseExists: true

frontend/src/System/Updates/Updates.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,7 @@
5151
margin-left: 10px;
5252
font-size: 14px;
5353
}
54+
55+
a {
56+
color: var(--linkColor);
57+
}

frontend/src/System/Updates/Updates.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ function Updates() {
269269
return (
270270
<InlineMarkdown
271271
data={translate('MaintenanceReleaseWithLink', {
272-
url: 'https://github.com/Whisparr/Whisparr/commits/eros/',
272+
url: 'https://github.com/Whisparr/Whisparr-Eros/commits/eros/',
273273
})}
274274
/>
275275
);

src/NzbDrone.Core.Test/HealthCheck/Checks/ReleaseBranchCheckFixture.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ public void should_return_warning_when_branch_is_not_valid(string branch)
3535
Subject.Check().ShouldBeWarning();
3636
}
3737

38-
[TestCase("nightly")]
39-
[TestCase("Nightly")]
40-
[TestCase("develop")]
41-
[TestCase("master")]
38+
[TestCase("eros")]
39+
[TestCase("eros-develop")]
40+
[TestCase("Eros")]
41+
[TestCase("Eros-Develop")]
4242
public void should_return_no_warning_when_branch_valid(string branch)
4343
{
4444
GivenValidBranch(branch);

src/NzbDrone.Core/HealthCheck/Checks/ReleaseBranchCheck.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public ReleaseBranchCheck(IConfigFileProvider configFileService, ILocalizationSe
1919

2020
public override HealthCheck Check()
2121
{
22-
var currentBranch = _configFileService.Branch.ToLower();
22+
var currentBranch = _configFileService.Branch.ToLower().Replace("-", "");
2323

2424
if (!Enum.GetNames(typeof(ReleaseBranches)).Any(x => x.ToLower() == currentBranch))
2525
{
@@ -31,10 +31,8 @@ public override HealthCheck Check()
3131

3232
public enum ReleaseBranches
3333
{
34-
Master,
35-
Develop,
36-
Nightly,
37-
Eros
34+
Eros,
35+
ErosDevelop
3836
}
3937
}
4038
}

src/NzbDrone.Core/Update/GithubUpdatePackageProvider.cs

Lines changed: 97 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33
using System.Linq;
44
using System.Runtime.InteropServices;
55
using System.Text.Json;
6+
using System.Text.RegularExpressions;
67
using NLog;
78
using NzbDrone.Common.Cloud;
89
using NzbDrone.Common.EnvironmentInfo;
910
using NzbDrone.Common.Http;
1011
using NzbDrone.Core.Analytics;
1112
using NzbDrone.Core.Configuration;
1213
using NzbDrone.Core.Datastore;
14+
using Semver;
1315

1416
namespace NzbDrone.Core.Update
1517
{
@@ -54,11 +56,15 @@ public UpdatePackage GetLatestUpdate(string branch, Version currentVersion)
5456
if (latest != null)
5557
{
5658
_logger.Info("Update found: {0} ({1})", latest.Version, latest.FileName);
57-
if (Semver.SemVersion.ComparePrecedence(Semver.SemVersion.Parse(currentVersion.ToString()), latest.Version) >= 0)
59+
60+
// Convert latest.Version (SemVersion) to .NET Version for comparison
61+
var latestDotNetVersion = releaseVersionAsAssemblyVersion(latest.Version.ToString());
62+
63+
if (currentVersion >= latestDotNetVersion)
5864
{
5965
_logger.Info("Current version '{0}' is up-to-date or newer than the latest available update '{1}'.",
6066
currentVersion,
61-
latest.Version);
67+
latestDotNetVersion);
6268
return null;
6369
}
6470

@@ -88,7 +94,7 @@ public List<UpdatePackage> GetRecentUpdates(string branch, Version currentVersio
8894

8995
var builder = _cloudRequestBuilder.GithubReleases.Create();
9096
builder.SetSegment("githubownerrepo", ownerRepo);
91-
builder.AddQueryParam("per_page", "5");
97+
builder.AddQueryParam("per_page", "25");
9298

9399
var request = builder.Build();
94100
_logger.Debug($"Requesting: {request.Url}");
@@ -104,16 +110,58 @@ public List<UpdatePackage> GetRecentUpdates(string branch, Version currentVersio
104110
var packages = new List<UpdatePackage>();
105111
foreach (var release in releases)
106112
{
113+
// Filter out releases that do not match the requested branch
114+
// For example, if branch is 'eros-develop', skip tags like 'v3.2.0-release.27'
115+
// You may need to adjust this logic if your tag naming changes
116+
if (!string.IsNullOrEmpty(branch))
117+
{
118+
var tagLower = release.tag_name.ToLowerInvariant();
119+
var branchLower = branch.ToLowerInvariant();
120+
121+
// If branch is exactly 'eros', skip prerelease tags
122+
if (branchLower == "eros" && tagLower.Contains("develop"))
123+
{
124+
_logger.Debug($"Skipping prerelease {release.tag_name} for stable branch {branch}.");
125+
continue;
126+
}
127+
128+
// If branch contains 'develop', skip tags with 'release' and vice versa
129+
if (branchLower.Contains("develop") && !tagLower.Contains("develop"))
130+
{
131+
_logger.Debug($"Skipping release {release.tag_name} because it is a release tag and branch is {branch}.");
132+
continue;
133+
}
134+
}
135+
107136
if (release.assets == null)
108137
{
109138
_logger.Debug($"Release {release.tag_name} has no package assets, skipping.");
110139
continue;
111140
}
112141

113-
// Filter release assets by mapped OS asset string and architecture
114-
var asset = release.assets.FirstOrDefault(a =>
115-
a.name.Contains(osAssetString, StringComparison.OrdinalIgnoreCase) &&
116-
a.name.Contains(arch, StringComparison.OrdinalIgnoreCase));
142+
// Prefer .tar.gz for Osx, fallback to .zip/.app
143+
GithubAsset asset = null;
144+
if (OsInfo.Os == Os.Osx)
145+
{
146+
asset = release.assets.FirstOrDefault(a =>
147+
a.name.Contains(osAssetString, StringComparison.OrdinalIgnoreCase) &&
148+
a.name.Contains(arch, StringComparison.OrdinalIgnoreCase) &&
149+
a.name.EndsWith(".tar.gz", StringComparison.OrdinalIgnoreCase));
150+
if (asset == null)
151+
{
152+
asset = release.assets.FirstOrDefault(a =>
153+
a.name.Contains(osAssetString, StringComparison.OrdinalIgnoreCase) &&
154+
a.name.Contains(arch, StringComparison.OrdinalIgnoreCase) &&
155+
(a.name.EndsWith(".zip", StringComparison.OrdinalIgnoreCase) || a.name.EndsWith(".app", StringComparison.OrdinalIgnoreCase)));
156+
}
157+
}
158+
else
159+
{
160+
asset = release.assets.FirstOrDefault(a =>
161+
a.name.Contains(osAssetString, StringComparison.OrdinalIgnoreCase) &&
162+
a.name.Contains(arch, StringComparison.OrdinalIgnoreCase));
163+
}
164+
117165
if (asset == null)
118166
{
119167
_logger.Debug("No asset found for release {0} matching OS asset string '{1}' and arch '{2}'",
@@ -125,7 +173,12 @@ public List<UpdatePackage> GetRecentUpdates(string branch, Version currentVersio
125173

126174
_logger.Debug($"Found update: {release.tag_name} - {asset.name}");
127175
var tag = release.tag_name.TrimStart('v');
128-
var version = Semver.SemVersion.Parse(tag);
176+
177+
// Attempt to strip "what's new", as it's repetitive in our UI
178+
var body = release?.body != null
179+
? Regex.Replace(release.body, @"^## What's Changed\s*\r?\n", "", RegexOptions.Multiline)
180+
: string.Empty;
181+
var version = SemVersion.Parse(tag);
129182
if (version == null)
130183
{
131184
_logger.Warn("Could not parse semver from tag '{0}' (parsed: '{1}'). Skipping this release.",
@@ -141,8 +194,8 @@ public List<UpdatePackage> GetRecentUpdates(string branch, Version currentVersio
141194
ReleaseDate = release.published_at,
142195
FileName = asset.name,
143196
Url = asset.browser_download_url,
144-
Changes = new UpdateChanges { New = new List<string> { release.body } },
145-
Hash = asset.digest,
197+
Changes = new UpdateChanges { New = new List<string> { body } },
198+
Hash = asset.digest.Replace("sha256:", "", StringComparison.OrdinalIgnoreCase),
146199
Branch = branch
147200
});
148201
}
@@ -151,6 +204,37 @@ public List<UpdatePackage> GetRecentUpdates(string branch, Version currentVersio
151204
return packages;
152205
}
153206

207+
/// <summary> Converts a GitHub release version string to a .NET Version object.</summary>
208+
/// <param name="releaseTag">The release version string (e.g., "v3.2.0-develop.23").</param>
209+
/// <returns>The corresponding .NET Assembly Version object.(e.e., 3.2.0.27)</returns>
210+
private static Version releaseVersionAsAssemblyVersion(string releaseTag)
211+
{
212+
var semver = SemVersion.Parse(releaseTag.TrimStart('v'));
213+
if (semver == null)
214+
{
215+
throw new ArgumentException($"Invalid semver: {releaseTag}", nameof(releaseTag));
216+
}
217+
218+
// Use major, minor, patch, and if available, the last numeric part of prerelease as revision
219+
var major = (int)semver.Major;
220+
var minor = (int)semver.Minor;
221+
var build = (int)semver.Patch;
222+
223+
// Try to extract revision from prerelease (e.g., 3.2.0-develop.23)
224+
var revision = 0;
225+
226+
if (!string.IsNullOrEmpty(semver.Prerelease))
227+
{
228+
var parts = semver.Prerelease.Split('.');
229+
if (parts.Length > 0 && int.TryParse(parts.Last(), out var rev))
230+
{
231+
revision = rev;
232+
}
233+
}
234+
235+
return new Version(major, minor, build, revision);
236+
}
237+
154238
/// <summary>
155239
/// Maps the OsInfo.Os enum to the asset string prefix used in GitHub release asset names.
156240
/// </summary>
@@ -175,7 +259,7 @@ private static string GetOsAssetString(Os os)
175259
}
176260
}
177261

178-
private class GithubRelease
262+
internal class GithubRelease
179263
{
180264
/// <summary>The tag name of the release.</summary>
181265
public string tag_name { get; set; }
@@ -191,12 +275,12 @@ private class GithubRelease
191275
}
192276

193277
/// <summary>Represents an asset in a GitHub release.</summary>
194-
private class GithubAsset
278+
internal class GithubAsset
195279
{
196280
/// <summary>The name of the asset file.</summary>
197281
public string name { get; set; }
198282

199-
/// <summary>The digest (sha:hash) of the asset.</summary>
283+
/// <summary>The digest (sha256 hash) of the asset.</summary>
200284
public string digest { get; set; }
201285

202286
/// <summary>The download URL of the asset.</summary>

src/NzbDrone.Core/Update/InstallUpdateService.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,31 @@ private bool InstallUpdate(UpdatePackage updatePackage)
139139
_archiveService.Extract(packageDestination, updateSandboxFolder);
140140
_logger.Info("Update package extracted successfully");
141141

142+
// Log the contents of the updateSandboxFolder after extraction
143+
144+
try
145+
{
146+
var extractedDirs = _diskProvider.GetDirectories(updateSandboxFolder);
147+
var extractedFiles = _diskProvider.GetFiles(updateSandboxFolder, true); // true = recursive
148+
_logger.Info("[Update Debug] Contents of updateSandboxFolder after extraction:");
149+
foreach (var dir in extractedDirs)
150+
{
151+
_logger.Info("[Update Debug] Dir: {0}", dir);
152+
}
153+
154+
foreach (var file in extractedFiles)
155+
{
156+
_logger.Info("[Update Debug] File: {0}", file);
157+
}
158+
}
159+
catch (Exception ex)
160+
{
161+
_logger.Warn(ex, "[Update Debug] Failed to enumerate extracted updateSandboxFolder contents");
162+
}
163+
164+
var expectedUpdateClientFolder = _appFolderInfo.GetUpdateClientFolder();
165+
_logger.Info("[Update Debug] Expected update client folder: {0}", expectedUpdateClientFolder);
166+
142167
EnsureValidBranch(updatePackage);
143168

144169
_backupService.Backup(BackupType.Update);

0 commit comments

Comments
 (0)